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

Reply via email to