On Mon, Apr 24, 2017 at 10:18:08PM +0200, Mark Kettenis wrote:
> > Date: Mon, 24 Apr 2017 16:01:39 -0400
> > From: Dale Rahn <dr...@dalerahn.com>
> > 
> > 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).
> 
> I don't think this cpubus(4) device makes much sense.  We don't have
> something like that on other FDT/OpenFirmware architectures.
> 

I am not aware of another way to have the fdt bus probe force recursive search
on the tree other than this, as previously said, the '/cpus' node does
not have a compatible field to do a normal attch. 

Anyway, here is an updated diff which ignores nodes under /cpus other than 
'cpu' nodes.

diff --git sys/arch/arm64/arm64/cpu.c sys/arch/arm64/arm64/cpu.c
new file mode 100644
index 00000000000..7535522d1ed
--- /dev/null
+++ 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 sys/arch/arm64/conf/GENERIC sys/arch/arm64/conf/GENERIC
index 44ab4f3e39f..3a0f9433491 100644
--- sys/arch/arm64/conf/GENERIC
+++ 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 sys/arch/arm64/conf/files.arm64 sys/arch/arm64/conf/files.arm64
index e2370431497..79789833096 100644
--- sys/arch/arm64/conf/files.arm64
+++ 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 sys/arch/arm64/dev/cpu_fdt.c sys/arch/arm64/dev/cpu_fdt.c
new file mode 100644
index 00000000000..a63e9acabb4
--- /dev/null
+++ sys/arch/arm64/dev/cpu_fdt.c
@@ -0,0 +1,215 @@
+/* $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];
+       char name[32];
+       int i, len, line;
+       uint32_t                *cell, *reg;
+
+       if (!OF_getprop(node, "compatible", buffer, sizeof(buffer)))
+               return;
+
+       if (OF_getprop(node, "name", name, sizeof(name)) > 0) {
+               /* we only want to look at cpu nodes */
+               if (strcmp(name, "cpu") != 0)
+                       return;
+       } else 
+               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");
+       if (len <= 0)
+               return;
+
+       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 sys/arch/arm64/include/armreg.h sys/arch/arm64/include/armreg.h
index 1a1802b1dbb..2dc1d93d233 100644
--- sys/arch/arm64/include/armreg.h
+++ 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 sys/arch/arm64/include/cpu.h sys/arch/arm64/include/cpu.h
index 2497cb33ccf..9aee1148615 100644
--- sys/arch/arm64/include/cpu.h
+++ 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 */

Reply via email to