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 */