diff options
author | Ruslan Bukin <br@FreeBSD.org> | 2018-04-05 15:45:54 +0000 |
---|---|---|
committer | Ruslan Bukin <br@FreeBSD.org> | 2018-04-05 15:45:54 +0000 |
commit | b09de0b34a3cdda99d7a852988b1b8ca6a8dc4a8 (patch) | |
tree | c03d0bd94cfcbeea8eb43541a9dd82989aaca07d /sys/arm64 | |
parent | 2e23ded5c400a9b398ae07e70a5b443c4dc1ba6c (diff) | |
download | src-b09de0b34a3cdda99d7a852988b1b8ca6a8dc4a8.tar.gz src-b09de0b34a3cdda99d7a852988b1b8ca6a8dc4a8.zip |
Add support for the Coresight technology from ARM Ltd.
ARM Coresight is a solution for debug and trace of complex SoC designs.
This includes a collection of drivers for ARM Coresight interconnect
devices within a small Coresight framework.
Supported devices are:
o Embedded Trace Macrocell v4 (ETMv4)
o Funnel
o Dynamic Replicator
o Trace Memory Controller (TMC)
o CPU debug module
Devices are connected to each other internally in SoC and the
configuration of each device endpoints is described in FDT.
Typical trace flow (as found on Qualcomm Snapdragon 410e):
CPU0 -> ETM0 -> funnel1 -> funnel0 -> ETF -> replicator -> ETR -> DRAM
CPU1 -> ETM1 -^
CPU2 -> ETM2 -^
CPU3 -> ETM3 -^
Note that both Embedded Trace FIFO (ETF) and Embedded Trace Router (ETR)
are hardware configurations of TMC.
This is required for upcoming HWPMC tracing support.
This is tested on single-core system only.
Reviewed by: andrew (partially)
Sponsored by: DARPA, AFRL
Differential Revision: https://reviews.freebsd.org/D14618
Notes
Notes:
svn path=/head/; revision=332077
Diffstat (limited to 'sys/arm64')
-rw-r--r-- | sys/arm64/coresight/coresight-cmd.c | 156 | ||||
-rw-r--r-- | sys/arm64/coresight/coresight-cpu-debug.c | 164 | ||||
-rw-r--r-- | sys/arm64/coresight/coresight-dynamic-replicator.c | 172 | ||||
-rw-r--r-- | sys/arm64/coresight/coresight-etm4x.c | 307 | ||||
-rw-r--r-- | sys/arm64/coresight/coresight-etm4x.h | 175 | ||||
-rw-r--r-- | sys/arm64/coresight/coresight-funnel.c | 180 | ||||
-rw-r--r-- | sys/arm64/coresight/coresight-funnel.h | 66 | ||||
-rw-r--r-- | sys/arm64/coresight/coresight-tmc.c | 398 | ||||
-rw-r--r-- | sys/arm64/coresight/coresight-tmc.h | 119 | ||||
-rw-r--r-- | sys/arm64/coresight/coresight.c | 215 | ||||
-rw-r--r-- | sys/arm64/coresight/coresight.h | 137 | ||||
-rw-r--r-- | sys/arm64/coresight/coresight_if.m | 58 |
12 files changed, 2147 insertions, 0 deletions
diff --git a/sys/arm64/coresight/coresight-cmd.c b/sys/arm64/coresight/coresight-cmd.c new file mode 100644 index 000000000000..f0e794509009 --- /dev/null +++ b/sys/arm64/coresight/coresight-cmd.c @@ -0,0 +1,156 @@ +/*- + * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/rman.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> + +#include <arm64/coresight/coresight.h> + +#include "coresight_if.h" + +extern struct coresight_device_list cs_devs; + +static struct coresight_device * +coresight_next_device(struct coresight_device *cs_dev, + struct coresight_event *event) +{ + struct coresight_device *out; + struct endpoint *out_endp; + struct endpoint *endp; + + TAILQ_FOREACH(endp, &cs_dev->pdata->endpoints, link) { + if (endp->slave != 0) + continue; + + out = coresight_get_output_device(endp, &out_endp); + if (out != NULL) { + if (LIST_EMPTY(&event->endplist)) { + /* Add source device */ + endp->cs_dev = cs_dev; + LIST_INSERT_HEAD(&event->endplist, endp, + endplink); + } + + /* Add output device */ + out_endp->cs_dev = out; + LIST_INSERT_HEAD(&event->endplist, out_endp, endplink); + + return (out); + } + } + + return (NULL); +} + +static int +coresight_build_list(struct coresight_device *cs_dev, + struct coresight_event *event) +{ + struct coresight_device *out; + + out = cs_dev; + while (out != NULL) + out = coresight_next_device(out, event); + + return (0); +} + +int +coresight_init_event(int cpu, struct coresight_event *event) +{ + struct coresight_device *cs_dev; + struct endpoint *endp; + + /* Start building path from source device */ + TAILQ_FOREACH(cs_dev, &cs_devs, link) { + if (cs_dev->dev_type == event->src && + cs_dev->pdata->cpu == cpu) { + LIST_INIT(&event->endplist); + coresight_build_list(cs_dev, event); + break; + } + } + + /* Ensure Coresight is initialized for the CPU */ + TAILQ_FOREACH(cs_dev, &cs_devs, link) { + if (cs_dev->dev_type == CORESIGHT_CPU_DEBUG && + cs_dev->pdata->cpu == cpu) + CORESIGHT_INIT(cs_dev->dev); + } + + /* Init all devices in the path */ + LIST_FOREACH(endp, &event->endplist, endplink) { + cs_dev = endp->cs_dev; + CORESIGHT_INIT(cs_dev->dev); + } + + return (0); +} + +void +coresight_enable(int cpu, struct coresight_event *event) +{ + struct coresight_device *cs_dev; + struct endpoint *endp; + + LIST_FOREACH(endp, &event->endplist, endplink) { + cs_dev = endp->cs_dev; + CORESIGHT_ENABLE(cs_dev->dev, endp, event); + } +} + +void +coresight_disable(int cpu, struct coresight_event *event) +{ + struct coresight_device *cs_dev; + struct endpoint *endp; + + LIST_FOREACH(endp, &event->endplist, endplink) { + cs_dev = endp->cs_dev; + CORESIGHT_DISABLE(cs_dev->dev, endp, event); + } +} + +void +coresight_read(int cpu, struct coresight_event *event) +{ + struct endpoint *endp; + + LIST_FOREACH(endp, &event->endplist, endplink) + CORESIGHT_READ(endp->cs_dev->dev, endp, event); +} diff --git a/sys/arm64/coresight/coresight-cpu-debug.c b/sys/arm64/coresight/coresight-cpu-debug.c new file mode 100644 index 000000000000..42d6cf48d044 --- /dev/null +++ b/sys/arm64/coresight/coresight-cpu-debug.c @@ -0,0 +1,164 @@ +/*- + * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> + * All rights reserved. + * + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/rman.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <arm64/coresight/coresight.h> + +#include "coresight_if.h" + +#define EDPCSR 0x0a0 +#define EDCIDSR 0x0a4 +#define EDVIDSR 0x0a8 +#define EDPCSR_HI 0x0ac +#define EDOSLAR 0x300 +#define EDPRCR 0x310 +#define EDPRCR_COREPURQ (1 << 3) +#define EDPRCR_CORENPDRQ (1 << 0) +#define EDPRSR 0x314 +#define EDDEVID1 0xfc4 +#define EDDEVID 0xfc8 + +static struct ofw_compat_data compat_data[] = { + { "arm,coresight-cpu-debug", 1 }, + { NULL, 0 } +}; + +struct debug_softc { + struct resource *res; + struct coresight_platform_data *pdata; +}; + +static struct resource_spec debug_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +debug_init(device_t dev) +{ + struct debug_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + + /* Unlock Coresight */ + bus_write_4(sc->res, CORESIGHT_LAR, CORESIGHT_UNLOCK); + + /* Unlock Debug */ + bus_write_4(sc->res, EDOSLAR, 0); + + /* Already initialized? */ + reg = bus_read_4(sc->res, EDPRCR); + if (reg & EDPRCR_CORENPDRQ) + return (0); + + /* Enable power */ + reg |= EDPRCR_COREPURQ; + bus_write_4(sc->res, EDPRCR, reg); + + do { + reg = bus_read_4(sc->res, EDPRSR); + } while ((reg & EDPRCR_CORENPDRQ) == 0); + + return (0); +} + +static int +debug_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "Coresight CPU Debug"); + + return (BUS_PROBE_DEFAULT); +} + +static int +debug_attach(device_t dev) +{ + struct coresight_desc desc; + struct debug_softc *sc; + + sc = device_get_softc(dev); + + if (bus_alloc_resources(dev, debug_spec, &sc->res) != 0) { + device_printf(dev, "cannot allocate resources for device\n"); + return (ENXIO); + } + + sc->pdata = coresight_get_platform_data(dev); + desc.pdata = sc->pdata; + desc.dev = dev; + desc.dev_type = CORESIGHT_CPU_DEBUG; + coresight_register(&desc); + + return (0); +} + +static device_method_t debug_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, debug_probe), + DEVMETHOD(device_attach, debug_attach), + + /* Coresight interface */ + DEVMETHOD(coresight_init, debug_init), + DEVMETHOD_END +}; + +static driver_t debug_driver = { + "debug", + debug_methods, + sizeof(struct debug_softc), +}; + +static devclass_t debug_devclass; + +EARLY_DRIVER_MODULE(debug, simplebus, debug_driver, debug_devclass, + 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LATE); +MODULE_VERSION(debug, 1); diff --git a/sys/arm64/coresight/coresight-dynamic-replicator.c b/sys/arm64/coresight/coresight-dynamic-replicator.c new file mode 100644 index 000000000000..95dd4331e21c --- /dev/null +++ b/sys/arm64/coresight/coresight-dynamic-replicator.c @@ -0,0 +1,172 @@ +/*- + * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> + * All rights reserved. + * + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/rman.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> + +#include <arm64/coresight/coresight.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include "coresight_if.h" + +#define REPLICATOR_IDFILTER0 0x00 +#define REPLICATOR_IDFILTER1 0x04 + +static struct ofw_compat_data compat_data[] = { + { "arm,coresight-dynamic-replicator", 1 }, + { NULL, 0 } +}; + +struct replicator_softc { + struct resource *res; + struct coresight_platform_data *pdata; +}; + +static struct resource_spec replicator_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +replicator_init(device_t dev) +{ + struct replicator_softc *sc; + + sc = device_get_softc(dev); + + /* Unlock Coresight */ + bus_write_4(sc->res, CORESIGHT_LAR, CORESIGHT_UNLOCK); + + return (0); +} + +static int +replicator_enable(device_t dev, struct endpoint *endp, + struct coresight_event *event) +{ + struct replicator_softc *sc; + + sc = device_get_softc(dev); + + /* Enable the port. Keep the other port disabled */ + if (endp->reg == 0) { + bus_write_4(sc->res, REPLICATOR_IDFILTER0, 0x00); + bus_write_4(sc->res, REPLICATOR_IDFILTER1, 0xff); + } else { + bus_write_4(sc->res, REPLICATOR_IDFILTER0, 0xff); + bus_write_4(sc->res, REPLICATOR_IDFILTER1, 0x00); + } + + return (0); +} + +static void +replicator_disable(device_t dev, struct endpoint *endp, + struct coresight_event *event) +{ + struct replicator_softc *sc; + + sc = device_get_softc(dev); + + bus_write_4(sc->res, REPLICATOR_IDFILTER0, 0xff); + bus_write_4(sc->res, REPLICATOR_IDFILTER1, 0xff); +} + +static int +replicator_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "Coresight Dynamic Replicator"); + + return (BUS_PROBE_DEFAULT); +} + +static int +replicator_attach(device_t dev) +{ + struct replicator_softc *sc; + struct coresight_desc desc; + + sc = device_get_softc(dev); + + if (bus_alloc_resources(dev, replicator_spec, &sc->res) != 0) { + device_printf(dev, "cannot allocate resources for device\n"); + return (ENXIO); + } + + sc->pdata = coresight_get_platform_data(dev); + desc.pdata = sc->pdata; + desc.dev = dev; + desc.dev_type = CORESIGHT_DYNAMIC_REPLICATOR; + coresight_register(&desc); + + return (0); +} + +static device_method_t replicator_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, replicator_probe), + DEVMETHOD(device_attach, replicator_attach), + + /* Coresight interface */ + DEVMETHOD(coresight_init, replicator_init), + DEVMETHOD(coresight_enable, replicator_enable), + DEVMETHOD(coresight_disable, replicator_disable), + DEVMETHOD_END +}; + +static driver_t replicator_driver = { + "replicator", + replicator_methods, + sizeof(struct replicator_softc), +}; + +static devclass_t replicator_devclass; + +DRIVER_MODULE(replicator, simplebus, replicator_driver, replicator_devclass, + 0, 0); +MODULE_VERSION(replicator, 1); diff --git a/sys/arm64/coresight/coresight-etm4x.c b/sys/arm64/coresight/coresight-etm4x.c new file mode 100644 index 000000000000..ed4edb662c99 --- /dev/null +++ b/sys/arm64/coresight/coresight-etm4x.c @@ -0,0 +1,307 @@ +/*- + * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> + * All rights reserved. + * + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/rman.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <arm64/coresight/coresight.h> +#include <arm64/coresight/coresight-etm4x.h> + +#include "coresight_if.h" + +#define ETM_DEBUG +#undef ETM_DEBUG + +#ifdef ETM_DEBUG +#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) +#else +#define dprintf(fmt, ...) +#endif + +/* + * Typical trace flow: + * + * CPU0 -> ETM0 -> funnel1 -> funnel0 -> ETF -> replicator -> ETR -> DRAM + * CPU1 -> ETM1 -> funnel1 -^ + * CPU2 -> ETM2 -> funnel1 -^ + * CPU3 -> ETM3 -> funnel1 -^ + */ + +static struct ofw_compat_data compat_data[] = { + { "arm,coresight-etm4x", 1 }, + { NULL, 0 } +}; + +struct etm_softc { + struct resource *res; + struct coresight_platform_data *pdata; +}; + +static struct resource_spec etm_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +etm_prepare(device_t dev, struct coresight_event *event) +{ + struct etm_softc *sc; + uint32_t reg; + int i; + + sc = device_get_softc(dev); + + /* Configure ETM */ + + /* + * Enable the return stack, global timestamping, + * Context ID, and Virtual context identifier tracing. + */ + reg = TRCCONFIGR_RS | TRCCONFIGR_TS; + reg |= TRCCONFIGR_CID | TRCCONFIGR_VMID; + reg |= TRCCONFIGR_INSTP0_LDRSTR; + reg |= TRCCONFIGR_COND_ALL; + bus_write_4(sc->res, TRCCONFIGR, reg); + + /* Disable all event tracing. */ + bus_write_4(sc->res, TRCEVENTCTL0R, 0); + bus_write_4(sc->res, TRCEVENTCTL1R, 0); + + /* Disable stalling, if implemented. */ + bus_write_4(sc->res, TRCSTALLCTLR, 0); + + /* Enable trace synchronization every 4096 bytes of trace. */ + bus_write_4(sc->res, TRCSYNCPR, TRCSYNCPR_4K); + + /* Set a value for the trace ID */ + bus_write_4(sc->res, TRCTRACEIDR, event->etm.trace_id); + + /* + * Disable the timestamp event. The trace unit still generates + * timestamps due to other reasons such as trace synchronization. + */ + bus_write_4(sc->res, TRCTSCTLR, 0); + + /* + * Enable ViewInst to trace everything, with the start/stop + * logic started. + */ + reg = TRCVICTLR_SSSTATUS; + + /* The number of the single resource used to activate the event. */ + reg |= (1 << EVENT_SEL_S); + + if (event->excp_level > 2) + return (-1); + + reg |= TRCVICTLR_EXLEVEL_NS_M; + reg &= ~TRCVICTLR_EXLEVEL_NS(event->excp_level); + reg |= TRCVICTLR_EXLEVEL_S_M; + reg &= ~TRCVICTLR_EXLEVEL_S(event->excp_level); + bus_write_4(sc->res, TRCVICTLR, reg); + + for (i = 0; i < event->naddr * 2; i++) { + dprintf("configure range %d, address %lx\n", + i, event->addr[i]); + bus_write_8(sc->res, TRCACVR(i), event->addr[i]); + + reg = 0; + /* Secure state */ + reg |= TRCACATR_EXLEVEL_S_M; + reg &= ~TRCACATR_EXLEVEL_S(event->excp_level); + /* Non-secure state */ + reg |= TRCACATR_EXLEVEL_NS_M; + reg &= ~TRCACATR_EXLEVEL_NS(event->excp_level); + bus_write_4(sc->res, TRCACATR(i), reg); + + /* Address range is included */ + reg = bus_read_4(sc->res, TRCVIIECTLR); + reg |= (1 << (TRCVIIECTLR_INCLUDE_S + i / 2)); + bus_write_4(sc->res, TRCVIIECTLR, reg); + } + + /* No address filtering for ViewData. */ + bus_write_4(sc->res, TRCVDARCCTLR, 0); + + /* Clear the STATUS bit to zero */ + bus_write_4(sc->res, TRCSSCSR(0), 0); + + if (event->naddr == 0) { + /* No address range filtering for ViewInst. */ + bus_write_4(sc->res, TRCVIIECTLR, 0); + } + + /* No start or stop points for ViewInst. */ + bus_write_4(sc->res, TRCVISSCTLR, 0); + + /* Disable ViewData */ + bus_write_4(sc->res, TRCVDCTLR, 0); + + /* No address filtering for ViewData. */ + bus_write_4(sc->res, TRCVDSACCTLR, 0); + + return (0); +} + +static int +etm_init(device_t dev) +{ + struct etm_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + + /* Unlocking Coresight */ + bus_write_4(sc->res, CORESIGHT_LAR, CORESIGHT_UNLOCK); + + /* Unlocking ETM */ + bus_write_4(sc->res, TRCOSLAR, 0); + + reg = bus_read_4(sc->res, TRCIDR(1)); + dprintf("ETM Version: %d.%d\n", + (reg & TRCIDR1_TRCARCHMAJ_M) >> TRCIDR1_TRCARCHMAJ_S, + (reg & TRCIDR1_TRCARCHMIN_M) >> TRCIDR1_TRCARCHMIN_S); + + return (0); +} + +static int +etm_enable(device_t dev, struct endpoint *endp, + struct coresight_event *event) +{ + struct etm_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + + etm_prepare(dev, event); + + /* Enable the trace unit */ + bus_write_4(sc->res, TRCPRGCTLR, TRCPRGCTLR_EN); + + /* Wait for an IDLE bit to be LOW */ + do { + reg = bus_read_4(sc->res, TRCSTATR); + } while ((reg & TRCSTATR_IDLE) == 1); + + if ((bus_read_4(sc->res, TRCPRGCTLR) & TRCPRGCTLR_EN) == 0) + panic("etm is not enabled\n"); + + return (0); +} + +static void +etm_disable(device_t dev, struct endpoint *endp, + struct coresight_event *event) +{ + struct etm_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + + /* Disable the trace unit */ + bus_write_4(sc->res, TRCPRGCTLR, 0); + + /* Wait for an IDLE bit */ + do { + reg = bus_read_4(sc->res, TRCSTATR); + } while ((reg & TRCSTATR_IDLE) == 0); +} + +static int +etm_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "AArch64 Embedded Trace Macrocell"); + + return (BUS_PROBE_DEFAULT); +} + +static int +etm_attach(device_t dev) +{ + struct coresight_desc desc; + struct etm_softc *sc; + + sc = device_get_softc(dev); + + if (bus_alloc_resources(dev, etm_spec, &sc->res) != 0) { + device_printf(dev, "cannot allocate resources for device\n"); + return (ENXIO); + } + + sc->pdata = coresight_get_platform_data(dev); + desc.pdata = sc->pdata; + desc.dev = dev; + desc.dev_type = CORESIGHT_ETMV4; + coresight_register(&desc); + + return (0); +} + +static device_method_t etm_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, etm_probe), + DEVMETHOD(device_attach, etm_attach), + + /* Coresight interface */ + DEVMETHOD(coresight_init, etm_init), + DEVMETHOD(coresight_enable, etm_enable), + DEVMETHOD(coresight_disable, etm_disable), + DEVMETHOD_END +}; + +static driver_t etm_driver = { + "etm", + etm_methods, + sizeof(struct etm_softc), +}; + +static devclass_t etm_devclass; + +DRIVER_MODULE(etm, simplebus, etm_driver, etm_devclass, 0, 0); +MODULE_VERSION(etm, 1); diff --git a/sys/arm64/coresight/coresight-etm4x.h b/sys/arm64/coresight/coresight-etm4x.h new file mode 100644 index 000000000000..00235c8962e0 --- /dev/null +++ b/sys/arm64/coresight/coresight-etm4x.h @@ -0,0 +1,175 @@ +/*- + * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> + * All rights reserved. + * + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $FreeBSD$ + */ + +#ifndef _ARM64_CORESIGHT_ETM4X_H_ +#define _ARM64_CORESIGHT_ETM4X_H_ + +#define TRCPRGCTLR 0x004 /* Trace Programming Control Register */ +#define TRCPRGCTLR_EN (1 << 0) /* Trace unit enable bit */ +#define TRCPROCSELR 0x008 /* Trace PE Select Control Register */ +#define TRCSTATR 0x00C /* Trace Trace Status Register */ +#define TRCSTATR_PMSTABLE (1 << 1) /* The programmers' model is stable. */ +#define TRCSTATR_IDLE (1 << 0) /* The trace unit is idle. */ +#define TRCCONFIGR 0x010 /* Trace Trace Configuration Register */ +#define TRCCONFIGR_DV (1 << 17) /* Data value tracing is enabled when INSTP0 is not 0b00 */ +#define TRCCONFIGR_DA (1 << 16) /* Data address tracing is enabled when INSTP0 is not 0b00. */ +#define TRCCONFIGR_VMIDOPT (1 << 15) /* Control bit to configure the Virtual context identifier value */ +#define TRCCONFIGR_QE_S 13 /* Q element enable field */ +#define TRCCONFIGR_QE_M (0x3 << TRCCONFIGR_QE_S) +#define TRCCONFIGR_RS (1 << 12) /* Return stack enable bit */ +#define TRCCONFIGR_TS (1 << 11) /* Global timestamp tracing is enabled. */ +#define TRCCONFIGR_COND_S 8 /* Conditional instruction tracing bit. */ +#define TRCCONFIGR_COND_M (0x7 << TRCCONFIGR_COND_S) +#define TRCCONFIGR_COND_DIS 0 +#define TRCCONFIGR_COND_LDR (1 << TRCCONFIGR_COND_S) /* Conditional load instructions are traced. */ +#define TRCCONFIGR_COND_STR (2 << TRCCONFIGR_COND_S) /* Conditional store instructions are traced. */ +#define TRCCONFIGR_COND_LDRSTR (3 << TRCCONFIGR_COND_S) /* Conditional load and store instructions are traced. */ +#define TRCCONFIGR_COND_ALL (7 << TRCCONFIGR_COND_S) /* All conditional instructions are traced. */ +#define TRCCONFIGR_VMID (1 << 7) /* Virtual context identifier tracing is enabled. */ +#define TRCCONFIGR_CID (1 << 6) /* Context ID tracing is enabled. */ +#define TRCCONFIGR_CCI (1 << 4) /* Cycle counting in the instruction trace is enabled. */ +#define TRCCONFIGR_BB (1 << 3) /* Branch broadcast mode is enabled. */ +#define TRCCONFIGR_INSTP0_S 1 /* Instruction P0 field. */ +#define TRCCONFIGR_INSTP0_M (0x3 << TRCCONFIGR_INSTP0_S) +#define TRCCONFIGR_INSTP0_NONE 0 /* Do not trace load and store instructions as P0 instructions. */ +#define TRCCONFIGR_INSTP0_LDR (1 << TRCCONFIGR_INSTP0_S) /* Trace load instructions as P0 instructions. */ +#define TRCCONFIGR_INSTP0_STR (2 << TRCCONFIGR_INSTP0_S) /* Trace store instructions as P0 instructions. */ +#define TRCCONFIGR_INSTP0_LDRSTR (3 << TRCCONFIGR_INSTP0_S) /* Trace load and store instructions as P0 instr. */ +#define TRCAUXCTLR 0x018 /* Trace Auxiliary Control Register */ +#define TRCEVENTCTL0R 0x020 /* Trace Event Control 0 Register */ +#define TRCEVENTCTL1R 0x024 /* Trace Event Control 1 Register */ +#define TRCSTALLCTLR 0x02C /* Trace Stall Control Register */ +#define TRCTSCTLR 0x030 /* Trace Global Timestamp Control Register */ +#define TRCSYNCPR 0x034 /* Trace Synchronization Period Register */ +#define TRCSYNCPR_PERIOD_S 0 +#define TRCSYNCPR_PERIOD_M 0x1f +#define TRCSYNCPR_1K (10 << TRCSYNCPR_PERIOD_S) +#define TRCSYNCPR_2K (11 << TRCSYNCPR_PERIOD_S) +#define TRCSYNCPR_4K (12 << TRCSYNCPR_PERIOD_S) +#define TRCCCCTLR 0x038 /* Trace Cycle Count Control Register */ +#define TRCBBCTLR 0x03C /* Trace Branch Broadcast Control Register */ +#define TRCTRACEIDR 0x040 /* Trace Trace ID Register */ +#define TRCQCTLR 0x044 /* Trace Q Element Control Register */ +#define TRCQCTLR_MODE_INC (1 << 8) /* Include mode. */ +#define TRCVICTLR 0x080 /* Trace ViewInst Main Control Register */ +#define TRCVICTLR_SSSTATUS (1 << 9) /* The start/stop logic is in the started state. */ +#define TRCVICTLR_EXLEVEL_NS_S 20 +#define TRCVICTLR_EXLEVEL_NS_M (0xf << TRCVICTLR_EXLEVEL_NS_S) +#define TRCVICTLR_EXLEVEL_NS(n) (0x1 << ((n) + TRCVICTLR_EXLEVEL_NS_S)) +#define TRCVICTLR_EXLEVEL_S_S 16 +#define TRCVICTLR_EXLEVEL_S_M (0xf << TRCVICTLR_EXLEVEL_S_S) +#define TRCVICTLR_EXLEVEL_S(n) (0x1 << ((n) + TRCVICTLR_EXLEVEL_S_S)) +#define EVENT_SEL_S 0 +#define EVENT_SEL_M (0x1f << EVENT_SEL_S) +#define TRCVIIECTLR 0x084 /* Trace ViewInst Include/Exclude Control Register */ +#define TRCVIIECTLR_INCLUDE_S 0 +#define TRCVISSCTLR 0x088 /* Trace ViewInst Start/Stop Control Register */ +#define TRCVIPCSSCTLR 0x08C /* Trace ViewInst Start/Stop PE Comparator Control Register */ +#define TRCVDCTLR 0x0A0 /* Trace ViewData Main Control Register */ +#define TRCVDCTLR_TRCEXDATA (1 << 12) /* Exception and exception return data transfers are traced */ +#define TRCVDCTLR_TBI (1 << 11) /* The trace unit assigns bits[63:56] to have the same value as bits[63:56] of the data address. */ +#define TRCVDCTLR_PCREL (1 << 10) /* The trace unit does not trace the address or value portions of PC-relative transfers. */ +#define TRCVDCTLR_SPREL_S 8 +#define TRCVDCTLR_SPREL_M (0x3 << TRCVDCTLR_SPREL_S) +#define TRCVDCTLR_EVENT_S 0 +#define TRCVDCTLR_EVENT_M (0xff << TRCVDCTLR_EVENT_S) +#define TRCVDSACCTLR 0x0A4 /* Trace ViewData Include/Exclude Single Address Comparator Control Register */ +#define TRCVDARCCTLR 0x0A8 /* Trace ViewData Include/Exclude Address Range Comparator Control Register */ +#define TRCSEQEVR(n) (0x100 + (n) * 0x4) /* Trace Sequencer State Transition Control Register [n=0-2] */ +#define TRCSEQRSTEVR 0x118 /* Trace Sequencer Reset Control Register */ +#define TRCSEQSTR 0x11C /* Trace Sequencer State Register */ +#define TRCEXTINSELR 0x120 /* Trace External Input Select Register */ +#define TRCCNTRLDVR(n) (0x140 + (n) * 0x4) /* 32 Trace Counter Reload Value Register [n=0-3] */ +#define TRCCNTCTLR(n) (0x150 + (n) * 0x4) /* 32 Trace Counter Control Register [n=0-3] */ +#define TRCCNTVR(n) (0x160 + (n) * 0x4) /* 32 Trace Counter Value Register [n=0-3] */ +#define TRCIMSPEC(n) (0x1C0 + (n) * 0x4) /* Trace IMPLEMENTATION DEFINED register [n=0-7] */ + +#define TRCIDR0(n) (0x1E0 + 0x4 * (n)) +#define TRCIDR8(n) (0x180 + 0x4 * (n)) +#define TRCIDR(n) ((n > 7) ? TRCIDR8(n) : TRCIDR0(n)) +#define TRCIDR1_TRCARCHMAJ_S 8 +#define TRCIDR1_TRCARCHMAJ_M (0xf << TRCIDR1_TRCARCHMAJ_S) +#define TRCIDR1_TRCARCHMIN_S 4 +#define TRCIDR1_TRCARCHMIN_M (0xf << TRCIDR1_TRCARCHMIN_S) + +#define TRCRSCTLR(n) (0x200 + (n) * 0x4) /* Trace Resource Selection Control Register [n=2-31] */ +#define TRCSSCCR(n) (0x280 + (n) * 0x4) /* Trace Single-shot Comparator Control Register [n=0-7] */ +#define TRCSSCSR(n) (0x2A0 + (n) * 0x4) /* Trace Single-shot Comparator Status Register [n=0-7] */ +#define TRCSSPCICR(n) (0x2C0 + (n) * 0x4) /* Trace Single-shot PE Comparator Input Control [n=0-7] */ +#define TRCOSLAR 0x300 /* Management OS Lock Access Register */ +#define TRCOSLSR 0x304 /* Management OS Lock Status Register */ +#define TRCPDCR 0x310 /* Management PowerDown Control Register */ +#define TRCPDSR 0x314 /* Management PowerDown Status Register */ +#define TRCACVR(n) (0x400 + (n) * 0x8) /* Trace Address Comparator Value Register [n=0-15] */ +#define TRCACATR(n) (0x480 + (n) * 0x8) /* Trace Address Comparator Access Type Register [n=0-15] */ +#define TRCACATR_DTBM (1 << 21) +#define TRCACATR_DATARANGE (1 << 20) +#define TRCACATR_DATASIZE_S 18 +#define TRCACATR_DATASIZE_M (0x3 << TRCACATR_DATASIZE_S) +#define TRCACATR_DATASIZE_B (0x0 << TRCACATR_DATASIZE_S) +#define TRCACATR_DATASIZE_HW (0x1 << TRCACATR_DATASIZE_S) +#define TRCACATR_DATASIZE_W (0x2 << TRCACATR_DATASIZE_S) +#define TRCACATR_DATASIZE_DW (0x3 << TRCACATR_DATASIZE_S) +#define TRCACATR_DATAMATCH_S 16 +#define TRCACATR_DATAMATCH_M (0x3 << TRCACATR_DATAMATCH_S) +#define TRCACATR_EXLEVEL_S_S 8 +#define TRCACATR_EXLEVEL_S_M (0xf << TRCACATR_EXLEVEL_S_S) +#define TRCACATR_EXLEVEL_S(n) (0x1 << ((n) + TRCACATR_EXLEVEL_S_S)) +#define TRCACATR_EXLEVEL_NS_S 12 +#define TRCACATR_EXLEVEL_NS_M (0xf << TRCACATR_EXLEVEL_NS_S) +#define TRCACATR_EXLEVEL_NS(n) (0x1 << ((n) + TRCACATR_EXLEVEL_NS_S)) +#define TRCDVCVR(n) (0x500 + (n) * 0x8) /* Trace Data Value Comparator Value Register [n=0-7] */ +#define TRCDVCMR(n) (0x580 + (n) * 0x8) /* Trace Data Value Comparator Mask Register [n=0-7] */ +#define TRCCIDCVR(n) (0x600 + (n) * 0x8) /* Trace Context ID Comparator Value Register [n=0-7] */ +#define TRCVMIDCVR(n) (0x640 + (n) * 0x8) /* Trace Virtual context identifier Comparator Value [n=0-7] */ +#define TRCCIDCCTLR0 0x680 /* Trace Context ID Comparator Control Register 0 */ +#define TRCCIDCCTLR1 0x684 /* Trace Context ID Comparator Control Register 1 */ +#define TRCVMIDCCTLR0 0x688 /* Trace Virtual context identifier Comparator Control Register 0 */ +#define TRCVMIDCCTLR1 0x68C /* Trace Virtual context identifier Comparator Control Register 1 */ +#define TRCITCTRL 0xF00 /* Management Integration Mode Control register */ +#define TRCCLAIMSET 0xFA0 /* Trace Claim Tag Set register */ +#define TRCCLAIMCLR 0xFA4 /* Trace Claim Tag Clear register */ +#define TRCDEVAFF0 0xFA8 /* Management Device Affinity register 0 */ +#define TRCDEVAFF1 0xFAC /* Management Device Affinity register 1 */ +#define TRCLAR 0xFB0 /* Management Software Lock Access Register */ +#define TRCLSR 0xFB4 /* Management Software Lock Status Register */ +#define TRCAUTHSTATUS 0xFB8 /* Management Authentication Status register */ +#define TRCDEVARCH 0xFBC /* Management Device Architecture register */ +#define TRCDEVID 0xFC8 /* Management Device ID register */ +#define TRCDEVTYPE 0xFCC /* Management Device Type register */ +#define TRCPIDR4 0xFD0 /* Management Peripheral ID4 Register */ +#define TRCPIDR(n) (0xFE0 + (n) * 0x4) /* Management Peripheral IDn Register [n=0-3] */ +#define TRCPIDR567(n) (0xFD4 + ((n) - 5) * 0x4) /* Management Peripheral ID5 to Peripheral ID7 Registers */ +#define TRCCIDR(n) (0xFF0 + (n) * 0x4) /* Management Component IDn Register [n=0-4] */ + +#endif /* !_ARM64_CORESIGHT_ETM4X_H_ */ diff --git a/sys/arm64/coresight/coresight-funnel.c b/sys/arm64/coresight/coresight-funnel.c new file mode 100644 index 000000000000..e4e6156fd908 --- /dev/null +++ b/sys/arm64/coresight/coresight-funnel.c @@ -0,0 +1,180 @@ +/*- + * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> + * All rights reserved. + * + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/rman.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> + +#include <arm64/coresight/coresight.h> +#include <arm64/coresight/coresight-funnel.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include "coresight_if.h" + +#define FUNNEL_DEBUG +#undef FUNNEL_DEBUG + +#ifdef FUNNEL_DEBUG +#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) +#else +#define dprintf(fmt, ...) +#endif + +static struct ofw_compat_data compat_data[] = { + { "arm,coresight-funnel", 1 }, + { NULL, 0 } +}; + +struct funnel_softc { + struct resource *res; + struct coresight_platform_data *pdata; +}; + +static struct resource_spec funnel_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +funnel_init(device_t dev) +{ + struct funnel_softc *sc; + + sc = device_get_softc(dev); + + /* Unlock Coresight */ + bus_write_4(sc->res, CORESIGHT_LAR, CORESIGHT_UNLOCK); + + dprintf("Device ID: %x\n", bus_read_4(sc->res, FUNNEL_DEVICEID)); + + return (0); +} + +static int +funnel_enable(device_t dev, struct endpoint *endp, + struct coresight_event *event) +{ + struct funnel_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + + reg = bus_read_4(sc->res, FUNNEL_FUNCTL); + reg &= ~(FUNCTL_HOLDTIME_MASK); + reg |= (7 << FUNCTL_HOLDTIME_SHIFT); + reg |= (1 << endp->reg); + bus_write_4(sc->res, FUNNEL_FUNCTL, reg); + + return (0); +} + +static void +funnel_disable(device_t dev, struct endpoint *endp, + struct coresight_event *event) +{ + struct funnel_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + + reg = bus_read_4(sc->res, FUNNEL_FUNCTL); + reg &= ~(1 << endp->reg); + bus_write_4(sc->res, FUNNEL_FUNCTL, reg); +} + +static int +funnel_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "Coresight Funnel"); + + return (BUS_PROBE_DEFAULT); +} + +static int +funnel_attach(device_t dev) +{ + struct coresight_desc desc; + struct funnel_softc *sc; + + sc = device_get_softc(dev); + + if (bus_alloc_resources(dev, funnel_spec, &sc->res) != 0) { + device_printf(dev, "cannot allocate resources for device\n"); + return (ENXIO); + } + + sc->pdata = coresight_get_platform_data(dev); + desc.pdata = sc->pdata; + desc.dev = dev; + desc.dev_type = CORESIGHT_FUNNEL; + coresight_register(&desc); + + return (0); +} + +static device_method_t funnel_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, funnel_probe), + DEVMETHOD(device_attach, funnel_attach), + + /* Coresight interface */ + DEVMETHOD(coresight_init, funnel_init), + DEVMETHOD(coresight_enable, funnel_enable), + DEVMETHOD(coresight_disable, funnel_disable), + DEVMETHOD_END +}; + +static driver_t funnel_driver = { + "funnel", + funnel_methods, + sizeof(struct funnel_softc), +}; + +static devclass_t funnel_devclass; + +DRIVER_MODULE(funnel, simplebus, funnel_driver, funnel_devclass, 0, 0); +MODULE_VERSION(funnel, 1); diff --git a/sys/arm64/coresight/coresight-funnel.h b/sys/arm64/coresight/coresight-funnel.h new file mode 100644 index 000000000000..fd9bb496b69f --- /dev/null +++ b/sys/arm64/coresight/coresight-funnel.h @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> + * All rights reserved. + * + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $FreeBSD$ + */ + +#ifndef _ARM64_CORESIGHT_CORESIGHT_FUNNEL_H_ +#define _ARM64_CORESIGHT_CORESIGHT_FUNNEL_H_ + +#define FUNNEL_FUNCTL 0x000 /* Funnel Control Register */ +#define FUNCTL_HOLDTIME_SHIFT 8 +#define FUNCTL_HOLDTIME_MASK (0xf << FUNCTL_HOLDTIME_SHIFT) +#define FUNNEL_PRICTL 0x004 /* Priority Control Register */ +#define FUNNEL_ITATBDATA0 0xEEC /* Integration Register, ITATBDATA0 */ +#define FUNNEL_ITATBCTR2 0xEF0 /* Integration Register, ITATBCTR2 */ +#define FUNNEL_ITATBCTR1 0xEF4 /* Integration Register, ITATBCTR1 */ +#define FUNNEL_ITATBCTR0 0xEF8 /* Integration Register, ITATBCTR0 */ +#define FUNNEL_IMCR 0xF00 /* Integration Mode Control Register */ +#define FUNNEL_CTSR 0xFA0 /* Claim Tag Set Register */ +#define FUNNEL_CTCR 0xFA4 /* Claim Tag Clear Register */ +#define FUNNEL_LOCKACCESS 0xFB0 /* Lock Access */ +#define FUNNEL_LOCKSTATUS 0xFB4 /* Lock Status */ +#define FUNNEL_AUTHSTATUS 0xFB8 /* Authentication status */ +#define FUNNEL_DEVICEID 0xFC8 /* Device ID */ +#define FUNNEL_DEVICETYPE 0xFCC /* Device Type Identifier */ +#define FUNNEL_PERIPH4 0xFD0 /* Peripheral ID4 */ +#define FUNNEL_PERIPH5 0xFD4 /* Peripheral ID5 */ +#define FUNNEL_PERIPH6 0xFD8 /* Peripheral ID6 */ +#define FUNNEL_PERIPH7 0xFDC /* Peripheral ID7 */ +#define FUNNEL_PERIPH0 0xFE0 /* Peripheral ID0 */ +#define FUNNEL_PERIPH1 0xFE4 /* Peripheral ID1 */ +#define FUNNEL_PERIPH2 0xFE8 /* Peripheral ID2 */ +#define FUNNEL_PERIPH3 0xFEC /* Peripheral ID3 */ +#define FUNNEL_COMP0 0xFF0 /* Component ID0 */ +#define FUNNEL_COMP1 0xFF4 /* Component ID1 */ +#define FUNNEL_COMP2 0xFF8 /* Component ID2 */ +#define FUNNEL_COMP3 0xFFC /* Component ID3 */ + +#endif /* !_ARM64_CORESIGHT_CORESIGHT_FUNNEL_H_ */ diff --git a/sys/arm64/coresight/coresight-tmc.c b/sys/arm64/coresight/coresight-tmc.c new file mode 100644 index 000000000000..a346c9a9ee54 --- /dev/null +++ b/sys/arm64/coresight/coresight-tmc.c @@ -0,0 +1,398 @@ +/*- + * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/rman.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> + +#include <arm64/coresight/coresight.h> +#include <arm64/coresight/coresight-tmc.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include "coresight_if.h" + +#define TMC_DEBUG +#undef TMC_DEBUG + +#ifdef TMC_DEBUG +#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) +#else +#define dprintf(fmt, ...) +#endif + +static struct ofw_compat_data compat_data[] = { + { "arm,coresight-tmc", 1 }, + { NULL, 0 } +}; + +struct tmc_softc { + struct resource *res; + device_t dev; + uint64_t cycle; + struct coresight_platform_data *pdata; + uint32_t dev_type; +#define CORESIGHT_UNKNOWN 0 +#define CORESIGHT_ETR 1 +#define CORESIGHT_ETF 2 + uint32_t nev; + struct coresight_event *event; + boolean_t etf_configured; +}; + +static struct resource_spec tmc_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { -1, 0 } +}; + +static int +tmc_start(device_t dev) +{ + struct tmc_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + + if (bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN) + return (-1); + + /* Enable TMC */ + bus_write_4(sc->res, TMC_CTL, CTL_TRACECAPTEN); + if ((bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN) == 0) + panic("Not enabled\n"); + + do { + reg = bus_read_4(sc->res, TMC_STS); + } while ((reg & STS_TMCREADY) == 1); + + if ((bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN) == 0) + panic("Not enabled\n"); + + return (0); +} + +static int +tmc_stop(device_t dev) +{ + struct tmc_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + + reg = bus_read_4(sc->res, TMC_CTL); + reg &= ~CTL_TRACECAPTEN; + bus_write_4(sc->res, TMC_CTL, reg); + + do { + reg = bus_read_4(sc->res, TMC_STS); + } while ((reg & STS_TMCREADY) == 1); + + return (0); +} + +static int +tmc_configure_etf(device_t dev) +{ + struct tmc_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + + do { + reg = bus_read_4(sc->res, TMC_STS); + } while ((reg & STS_TMCREADY) == 0); + + bus_write_4(sc->res, TMC_MODE, MODE_HW_FIFO); + bus_write_4(sc->res, TMC_FFCR, FFCR_EN_FMT | FFCR_EN_TI); + + tmc_start(dev); + + dprintf("%s: STS %x, CTL %x, RSZ %x, RRP %x, RWP %x, " + "LBUFLEVEL %x, CBUFLEVEL %x\n", __func__, + bus_read_4(sc->res, TMC_STS), + bus_read_4(sc->res, TMC_CTL), + bus_read_4(sc->res, TMC_RSZ), + bus_read_4(sc->res, TMC_RRP), + bus_read_4(sc->res, TMC_RWP), + bus_read_4(sc->res, TMC_CBUFLEVEL), + bus_read_4(sc->res, TMC_LBUFLEVEL)); + + return (0); +} + +static int +tmc_configure_etr(device_t dev, struct endpoint *endp, + struct coresight_event *event) +{ + struct tmc_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + + tmc_stop(dev); + + do { + reg = bus_read_4(sc->res, TMC_STS); + } while ((reg & STS_TMCREADY) == 0); + + /* Configure TMC */ + bus_write_4(sc->res, TMC_MODE, MODE_CIRCULAR_BUFFER); + + reg = AXICTL_PROT_CTRL_BIT1; + reg |= AXICTL_WRBURSTLEN_16; + + /* + * SG operation is broken on DragonBoard 410c + * reg |= AXICTL_SG_MODE; + */ + + reg |= AXICTL_AXCACHE_OS; + bus_write_4(sc->res, TMC_AXICTL, reg); + + reg = FFCR_EN_FMT | FFCR_EN_TI | FFCR_FON_FLIN | + FFCR_FON_TRIG_EVT | FFCR_TRIGON_TRIGIN; + bus_write_4(sc->res, TMC_FFCR, reg); + + bus_write_4(sc->res, TMC_TRG, 8); + + bus_write_4(sc->res, TMC_DBALO, event->etr.low); + bus_write_4(sc->res, TMC_DBAHI, event->etr.high); + bus_write_4(sc->res, TMC_RSZ, event->etr.bufsize / 4); + + bus_write_4(sc->res, TMC_RRP, event->etr.low); + bus_write_4(sc->res, TMC_RWP, event->etr.low); + + reg = bus_read_4(sc->res, TMC_STS); + reg &= ~STS_FULL; + bus_write_4(sc->res, TMC_STS, reg); + + tmc_start(dev); + + return (0); +} + +static int +tmc_init(device_t dev) +{ + struct tmc_softc *sc; + uint32_t reg; + + sc = device_get_softc(dev); + + /* Unlock Coresight */ + bus_write_4(sc->res, CORESIGHT_LAR, CORESIGHT_UNLOCK); + + /* Unlock TMC */ + bus_write_4(sc->res, TMC_LAR, CORESIGHT_UNLOCK); + + reg = bus_read_4(sc->res, TMC_DEVID); + reg &= DEVID_CONFIGTYPE_M; + switch (reg) { + case DEVID_CONFIGTYPE_ETR: + sc->dev_type = CORESIGHT_ETR; + dprintf(dev, "ETR configuration found\n"); + break; + case DEVID_CONFIGTYPE_ETF: + sc->dev_type = CORESIGHT_ETF; + dprintf(dev, "ETF configuration found\n"); + if (sc->etf_configured == false) { + tmc_configure_etf(dev); + sc->etf_configured = true; + } + break; + default: + sc->dev_type = CORESIGHT_UNKNOWN; + break; + } + + return (0); +} + +static int +tmc_enable(device_t dev, struct endpoint *endp, + struct coresight_event *event) +{ + struct tmc_softc *sc; + uint32_t nev; + + sc = device_get_softc(dev); + + if (sc->dev_type == CORESIGHT_ETF) + return (0); + + KASSERT(sc->dev_type == CORESIGHT_ETR, + ("Wrong dev_type")); + + /* + * Multiple CPUs can call this same time. + * We allow only one running configuration. + */ + + if (event->etr.flags & ETR_FLAG_ALLOCATE) { + event->etr.flags &= ~ETR_FLAG_ALLOCATE; + nev = atomic_fetchadd_int(&sc->nev, 1); + if (nev == 0) { + sc->event = event; + tmc_stop(dev); + tmc_configure_etr(dev, endp, event); + tmc_start(dev); + } + } + + return (0); +} + +static void +tmc_disable(device_t dev, struct endpoint *endp, + struct coresight_event *event) +{ + struct tmc_softc *sc; + uint32_t nev; + + sc = device_get_softc(dev); + + /* ETF configuration is static */ + if (sc->dev_type == CORESIGHT_ETF) + return; + + KASSERT(sc->dev_type == CORESIGHT_ETR, ("Wrong dev_type")); + + if (event->etr.flags & ETR_FLAG_RELEASE) { + event->etr.flags &= ~ETR_FLAG_RELEASE; + nev = atomic_fetchadd_int(&sc->nev, -1); + if (nev == 1) { + tmc_stop(dev); + sc->event = NULL; + } + } +} + +static int +tmc_read(device_t dev, struct endpoint *endp, + struct coresight_event *event) +{ + struct tmc_softc *sc; + uint32_t cur_ptr; + + sc = device_get_softc(dev); + + if (sc->dev_type == CORESIGHT_ETF) + return (0); + + /* + * Ensure the event we are reading information for + * is currently configured one. + */ + if (sc->event != event) + return (0); + + if (bus_read_4(sc->res, TMC_STS) & STS_FULL) { + event->etr.offset = 0; + event->etr.cycle++; + tmc_stop(dev); + tmc_start(dev); + } else { + cur_ptr = bus_read_4(sc->res, TMC_RWP); + event->etr.offset = (cur_ptr - event->etr.low); + } + + return (0); +} + +static int +tmc_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "Coresight Trace Memory Controller (TMC)"); + + return (BUS_PROBE_DEFAULT); +} + +static int +tmc_attach(device_t dev) +{ + struct coresight_desc desc; + struct tmc_softc *sc; + + sc = device_get_softc(dev); + + sc->dev = dev; + + if (bus_alloc_resources(dev, tmc_spec, &sc->res) != 0) { + device_printf(dev, "cannot allocate resources for device\n"); + return (ENXIO); + } + + sc->pdata = coresight_get_platform_data(dev); + desc.pdata = sc->pdata; + desc.dev = dev; + desc.dev_type = CORESIGHT_TMC; + coresight_register(&desc); + + return (0); +} + +static device_method_t tmc_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, tmc_probe), + DEVMETHOD(device_attach, tmc_attach), + + /* Coresight interface */ + DEVMETHOD(coresight_init, tmc_init), + DEVMETHOD(coresight_enable, tmc_enable), + DEVMETHOD(coresight_disable, tmc_disable), + DEVMETHOD(coresight_read, tmc_read), + DEVMETHOD_END +}; + +static driver_t tmc_driver = { + "tmc", + tmc_methods, + sizeof(struct tmc_softc), +}; + +static devclass_t tmc_devclass; + +DRIVER_MODULE(tmc, simplebus, tmc_driver, tmc_devclass, 0, 0); +MODULE_VERSION(tmc, 1); diff --git a/sys/arm64/coresight/coresight-tmc.h b/sys/arm64/coresight/coresight-tmc.h new file mode 100644 index 000000000000..411818feb61a --- /dev/null +++ b/sys/arm64/coresight/coresight-tmc.h @@ -0,0 +1,119 @@ +/*- + * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $FreeBSD$ + */ + +#ifndef _ARM64_CORESIGHT_CORESIGHT_TMC_H_ +#define _ARM64_CORESIGHT_CORESIGHT_TMC_H_ + +#define TMC_RSZ 0x004 /* RAM Size Register */ +#define TMC_STS 0x00C /* Status Register */ +#define STS_MEMERR (1 << 5) +#define STS_EMPTY (1 << 4) +#define STS_FTEMPTY (1 << 3) +#define STS_TMCREADY (1 << 2) +#define STS_TRIGGERED (1 << 1) +#define STS_FULL (1 << 0) +#define TMC_RRD 0x010 /* RAM Read Data Register */ +#define TMC_RRP 0x014 /* RAM Read Pointer Register */ +#define TMC_RWP 0x018 /* RAM Write Pointer Register */ +#define TMC_TRG 0x01C /* Trigger Counter Register */ +#define TMC_CTL 0x020 /* Control Register */ +#define CTL_TRACECAPTEN (1 << 0) /* Controls trace capture. */ +#define TMC_RWD 0x024 /* RAM Write Data Register */ +#define TMC_MODE 0x028 /* Mode Register */ +#define MODE_HW_FIFO 2 +#define MODE_SW_FIFO 1 +#define MODE_CIRCULAR_BUFFER 0 +#define TMC_LBUFLEVEL 0x02C /* Latched Buffer Fill Level */ +#define TMC_CBUFLEVEL 0x030 /* Current Buffer Fill Level */ +#define TMC_BUFWM 0x034 /* Buffer Level Water Mark */ +#define TMC_RRPHI 0x038 /* RAM Read Pointer High Register */ +#define TMC_RWPHI 0x03C /* RAM Write Pointer High Register */ +#define TMC_AXICTL 0x110 /* AXI Control Register */ +#define AXICTL_WRBURSTLEN_S 8 +#define AXICTL_WRBURSTLEN_M (0xf << AXICTL_WRBURSTLEN_S) +#define AXICTL_WRBURSTLEN_16 (0xf << AXICTL_WRBURSTLEN_S) +#define AXICTL_SG_MODE (1 << 7) /* Scatter Gather Mode */ +#define AXICTL_CACHE_CTRL_BIT3 (1 << 5) +#define AXICTL_CACHE_CTRL_BIT2 (1 << 4) +#define AXICTL_CACHE_CTRL_BIT1 (1 << 3) +#define AXICTL_CACHE_CTRL_BIT0 (1 << 2) +#define AXICTL_AXCACHE_OS (0xf << 2) +#define AXICTL_PROT_CTRL_BIT1 (1 << 1) +#define AXICTL_PROT_CTRL_BIT0 (1 << 0) +#define TMC_DBALO 0x118 /* Data Buffer Address Low Register */ +#define TMC_DBAHI 0x11C /* Data Buffer Address High Register */ +#define TMC_FFSR 0x300 /* Formatter and Flush Status Register */ +#define TMC_FFCR 0x304 /* Formatter and Flush Control Register */ +#define FFCR_EN_FMT (1 << 0) +#define FFCR_EN_TI (1 << 1) +#define FFCR_FON_FLIN (1 << 4) +#define FFCR_FON_TRIG_EVT (1 << 5) +#define FFCR_FLUSH_MAN (1 << 6) +#define FFCR_TRIGON_TRIGIN (1 << 8) +#define TMC_PSCR 0x308 /* Periodic Synchronization Counter Register */ +#define TMC_ITATBMDATA0 0xED0 /* Integration Test ATB Master Data Register 0 */ +#define TMC_ITATBMCTR2 0xED4 /* Integration Test ATB Master Interface Control 2 Register */ +#define TMC_ITATBMCTR1 0xED8 /* Integration Test ATB Master Control Register 1 */ +#define TMC_ITATBMCTR0 0xEDC /* Integration Test ATB Master Interface Control 0 Register */ +#define TMC_ITMISCOP0 0xEE0 /* Integration Test Miscellaneous Output Register 0 */ +#define TMC_ITTRFLIN 0xEE8 /* Integration Test Trigger In and Flush In Register */ +#define TMC_ITATBDATA0 0xEEC /* Integration Test ATB Data Register 0 */ +#define TMC_ITATBCTR2 0xEF0 /* Integration Test ATB Control 2 Register */ +#define TMC_ITATBCTR1 0xEF4 /* Integration Test ATB Control 1 Register */ +#define TMC_ITATBCTR0 0xEF8 /* Integration Test ATB Control 0 Register */ +#define TMC_ITCTRL 0xF00 /* Integration Mode Control Register */ +#define TMC_CLAIMSET 0xFA0 /* Claim Tag Set Register */ +#define TMC_CLAIMCLR 0xFA4 /* Claim Tag Clear Register */ +#define TMC_LAR 0xFB0 /* Lock Access Register */ +#define TMC_LSR 0xFB4 /* Lock Status Register */ +#define TMC_AUTHSTATUS 0xFB8 /* Authentication Status Register */ +#define TMC_DEVID 0xFC8 /* Device Configuration Register */ +#define DEVID_CONFIGTYPE_S 6 +#define DEVID_CONFIGTYPE_M (0x3 << DEVID_CONFIGTYPE_S) +#define DEVID_CONFIGTYPE_ETB (0 << DEVID_CONFIGTYPE_S) +#define DEVID_CONFIGTYPE_ETR (1 << DEVID_CONFIGTYPE_S) +#define DEVID_CONFIGTYPE_ETF (2 << DEVID_CONFIGTYPE_S) +#define TMC_DEVTYPE 0xFCC /* Device Type Identifier Register */ +#define TMC_PERIPHID4 0xFD0 /* Peripheral ID4 Register */ +#define TMC_PERIPHID5 0xFD4 /* Peripheral ID5 Register */ +#define TMC_PERIPHID6 0xFD8 /* Peripheral ID6 Register */ +#define TMC_PERIPHID7 0xFDC /* Peripheral ID7 Register */ +#define TMC_PERIPHID0 0xFE0 /* Peripheral ID0 Register */ +#define TMC_PERIPHID1 0xFE4 /* Peripheral ID1 Register */ +#define TMC_PERIPHID2 0xFE8 /* Peripheral ID2 Register */ +#define TMC_PERIPHID3 0xFEC /* Peripheral ID3 Register */ +#define TMC_COMPID0 0xFF0 /* Component ID0 Register */ +#define TMC_COMPID1 0xFF4 /* Component ID1 Register */ +#define TMC_COMPID2 0xFF8 /* Component ID2 Register */ +#define TMC_COMPID3 0xFFC /* Component ID3 Register */ + +#endif /* !_ARM64_CORESIGHT_CORESIGHT_TMC_H_ */ diff --git a/sys/arm64/coresight/coresight.c b/sys/arm64/coresight/coresight.c new file mode 100644 index 000000000000..4f520ce70ca3 --- /dev/null +++ b/sys/arm64/coresight/coresight.c @@ -0,0 +1,215 @@ +/*- + * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/rman.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <arm64/coresight/coresight.h> + +MALLOC_DEFINE(M_CORESIGHT, "coresight", "ARM Coresight"); +static struct mtx cs_mtx; + +struct coresight_device_list cs_devs; + +static int +coresight_get_ports(phandle_t dev_node, + struct coresight_platform_data *pdata) +{ + phandle_t node, child; + pcell_t port_reg; + phandle_t xref; + char *name; + int ret; + phandle_t endpoint_child; + struct endpoint *endp; + + child = ofw_bus_find_child(dev_node, "ports"); + if (child) + node = child; + else + node = dev_node; + + for (child = OF_child(node); child != 0; child = OF_peer(child)) { + ret = OF_getprop_alloc(child, "name", sizeof(*name), (void **)&name); + if (ret == -1) + continue; + + if (strcasecmp(name, "port") || + strncasecmp(name, "port@", 6)) { + + port_reg = -1; + OF_getencprop(child, "reg", (void *)&port_reg, sizeof(port_reg)); + + endpoint_child = ofw_bus_find_child(child, "endpoint"); + if (endpoint_child) { + if (OF_getencprop(endpoint_child, "remote-endpoint", &xref, + sizeof(xref)) == -1) { + printf("failed\n"); + continue; + } + endp = malloc(sizeof(struct endpoint), M_CORESIGHT, + M_WAITOK | M_ZERO); + endp->my_node = endpoint_child; + endp->their_node = OF_node_from_xref(xref); + endp->dev_node = dev_node; + endp->reg = port_reg; + if (OF_getproplen(endpoint_child, "slave-mode") >= 0) { + pdata->in_ports++; + endp->slave = 1; + } else { + pdata->out_ports++; + } + + mtx_lock(&pdata->mtx_lock); + TAILQ_INSERT_TAIL(&pdata->endpoints, endp, link); + mtx_unlock(&pdata->mtx_lock); + } + } + } + + return (0); +} + +int +coresight_register(struct coresight_desc *desc) +{ + struct coresight_device *cs_dev; + + cs_dev = malloc(sizeof(struct coresight_device), + M_CORESIGHT, M_WAITOK | M_ZERO); + cs_dev->dev = desc->dev; + cs_dev->node = ofw_bus_get_node(desc->dev); + cs_dev->pdata = desc->pdata; + cs_dev->dev_type = desc->dev_type; + + mtx_lock(&cs_mtx); + TAILQ_INSERT_TAIL(&cs_devs, cs_dev, link); + mtx_unlock(&cs_mtx); + + return (0); +} + +struct endpoint * +coresight_get_output_endpoint(struct coresight_platform_data *pdata) +{ + struct endpoint *endp; + + if (pdata->out_ports != 1) + return (NULL); + + TAILQ_FOREACH(endp, &pdata->endpoints, link) { + if (endp->slave == 0) + return (endp); + } + + return (NULL); +} + +struct coresight_device * +coresight_get_output_device(struct endpoint *endp, struct endpoint **out_endp) +{ + struct coresight_device *cs_dev; + struct endpoint *endp2; + + TAILQ_FOREACH(cs_dev, &cs_devs, link) { + TAILQ_FOREACH(endp2, &cs_dev->pdata->endpoints, link) { + if (endp->their_node == endp2->my_node) { + *out_endp = endp2; + return (cs_dev); + } + } + } + + return (NULL); +} + +static int +coresight_get_cpu(phandle_t node, + struct coresight_platform_data *pdata) +{ + phandle_t cpu_node; + pcell_t xref; + pcell_t cpu_reg; + + if (OF_getencprop(node, "cpu", &xref, sizeof(xref)) != -1) { + cpu_node = OF_node_from_xref(xref); + if (OF_getencprop(cpu_node, "reg", (void *)&cpu_reg, + sizeof(cpu_reg)) > 0) { + pdata->cpu = cpu_reg; + return (0); + } + } + + return (-1); +} + +struct coresight_platform_data * +coresight_get_platform_data(device_t dev) +{ + struct coresight_platform_data *pdata; + phandle_t node; + + node = ofw_bus_get_node(dev); + + pdata = malloc(sizeof(struct coresight_platform_data), + M_CORESIGHT, M_WAITOK | M_ZERO); + mtx_init(&pdata->mtx_lock, "Coresight Platform Data", NULL, MTX_DEF); + TAILQ_INIT(&pdata->endpoints); + + coresight_get_cpu(node, pdata); + coresight_get_ports(node, pdata); + + if (bootverbose) + printf("Total ports: in %d out %d\n", + pdata->in_ports, pdata->out_ports); + + return (pdata); +} + +static void +coresight_init(void) +{ + + mtx_init(&cs_mtx, "ARM Coresight", NULL, MTX_DEF); + TAILQ_INIT(&cs_devs); +} + +SYSINIT(coresight, SI_SUB_DRIVERS, SI_ORDER_FIRST, coresight_init, NULL); diff --git a/sys/arm64/coresight/coresight.h b/sys/arm64/coresight/coresight.h new file mode 100644 index 000000000000..9ae4db51595e --- /dev/null +++ b/sys/arm64/coresight/coresight.h @@ -0,0 +1,137 @@ +/*- + * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $FreeBSD$ + */ + +#ifndef _ARM64_CORESIGHT_CORESIGHT_H_ +#define _ARM64_CORESIGHT_CORESIGHT_H_ + +#include <dev/ofw/openfirm.h> + +#define CORESIGHT_ITCTRL 0xf00 +#define CORESIGHT_CLAIMSET 0xfa0 +#define CORESIGHT_CLAIMCLR 0xfa4 +#define CORESIGHT_LAR 0xfb0 +#define CORESIGHT_UNLOCK 0xc5acce55 +#define CORESIGHT_LSR 0xfb4 +#define CORESIGHT_AUTHSTATUS 0xfb8 +#define CORESIGHT_DEVID 0xfc8 +#define CORESIGHT_DEVTYPE 0xfcc + +enum cs_dev_type { + CORESIGHT_ETMV4, + CORESIGHT_TMC, + CORESIGHT_DYNAMIC_REPLICATOR, + CORESIGHT_FUNNEL, + CORESIGHT_CPU_DEBUG, +}; + +struct coresight_device { + TAILQ_ENTRY(coresight_device) link; + device_t dev; + phandle_t node; + enum cs_dev_type dev_type; + struct coresight_platform_data *pdata; +}; + +struct endpoint { + TAILQ_ENTRY(endpoint) link; + phandle_t my_node; + phandle_t their_node; + phandle_t dev_node; + boolean_t slave; + int reg; + struct coresight_device *cs_dev; + LIST_ENTRY(endpoint) endplink; +}; + +struct coresight_platform_data { + int cpu; + int in_ports; + int out_ports; + struct mtx mtx_lock; + TAILQ_HEAD(endpoint_list, endpoint) endpoints; +}; + +struct coresight_desc { + struct coresight_platform_data *pdata; + device_t dev; + enum cs_dev_type dev_type; +}; + +TAILQ_HEAD(coresight_device_list, coresight_device); + +#define ETM_N_COMPRATOR 16 + +struct etm_state { + uint32_t trace_id; +}; + +struct etr_state { + boolean_t started; + uint32_t cycle; + uint32_t offset; + uint32_t low; + uint32_t high; + uint32_t bufsize; + uint32_t flags; +#define ETR_FLAG_ALLOCATE (1 << 0) +#define ETR_FLAG_RELEASE (1 << 1) +}; + +struct coresight_event { + LIST_HEAD(, endpoint) endplist; + + uint64_t addr[ETM_N_COMPRATOR]; + uint32_t naddr; + uint8_t excp_level; + enum cs_dev_type src; + enum cs_dev_type sink; + + struct etr_state etr; + struct etm_state etm; +}; + +struct etm_config { + uint64_t addr[ETM_N_COMPRATOR]; + uint32_t naddr; + uint8_t excp_level; +}; + +struct coresight_platform_data * coresight_get_platform_data(device_t dev); +struct endpoint * coresight_get_output_endpoint(struct coresight_platform_data *pdata); +struct coresight_device * coresight_get_output_device(struct endpoint *endp, struct endpoint **); +int coresight_register(struct coresight_desc *desc); +int coresight_init_event(int cpu, struct coresight_event *event); +void coresight_enable(int cpu, struct coresight_event *event); +void coresight_disable(int cpu, struct coresight_event *event); +void coresight_read(int cpu, struct coresight_event *event); + +#endif /* !_ARM64_CORESIGHT_CORESIGHT_H_ */ diff --git a/sys/arm64/coresight/coresight_if.m b/sys/arm64/coresight/coresight_if.m new file mode 100644 index 000000000000..e311c4c8f5cb --- /dev/null +++ b/sys/arm64/coresight/coresight_if.m @@ -0,0 +1,58 @@ +#- +# Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> +# All rights reserved. +# +# This software was developed by SRI International and the University of +# Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 +# ("CTSRD"), as part of the DARPA CRASH research programme. +# +# 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. +# +# $FreeBSD$ +# + +#include <machine/bus.h> +#include <arm64/coresight/coresight.h> + +INTERFACE coresight; + +METHOD int init { + device_t dev; +}; + +METHOD int enable { + device_t dev; + struct endpoint *endp; + struct coresight_event *event; +}; + +METHOD void disable { + device_t dev; + struct endpoint *endp; + struct coresight_event *event; +}; + +METHOD int read { + device_t dev; + struct endpoint *endp; + struct coresight_event *event; +}; |