> 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. > 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 > >