diff --git a/sys/arm64/coresight/coresight.c b/sys/arm64/coresight/coresight.c index 3fd4a5f233d1..38a47c0c3b0f 100644 --- a/sys/arm64/coresight/coresight.c +++ b/sys/arm64/coresight/coresight.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2018 Ruslan Bukin + * Copyright (c) 2018-2020 Ruslan Bukin * All rights reserved. * * This software was developed by SRI International and the University of @@ -41,78 +41,11 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include - #include -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", (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) { @@ -121,7 +54,6 @@ coresight_register(struct coresight_desc *desc) 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; @@ -141,7 +73,7 @@ coresight_get_output_endpoint(struct coresight_platform_data *pdata) return (NULL); TAILQ_FOREACH(endp, &pdata->endpoints, link) { - if (endp->slave == 0) + if (endp->input == 0) return (endp); } @@ -151,14 +83,31 @@ coresight_get_output_endpoint(struct coresight_platform_data *pdata) struct coresight_device * coresight_get_output_device(struct endpoint *endp, struct endpoint **out_endp) { + struct coresight_platform_data *pdata; struct coresight_device *cs_dev; struct endpoint *endp2; TAILQ_FOREACH(cs_dev, &cs_devs, link) { + pdata = cs_dev->pdata; TAILQ_FOREACH(endp2, &cs_dev->pdata->endpoints, link) { - if (endp->their_node == endp2->my_node) { - *out_endp = endp2; - return (cs_dev); + switch (pdata->bus_type) { + case CORESIGHT_BUS_FDT: +#ifdef FDT + if (endp->their_node == endp2->my_node) { + *out_endp = endp2; + return (cs_dev); + } +#endif + break; + + case CORESIGHT_BUS_ACPI: +#ifdef DEV_ACPI + if (endp->their_handle == endp2->my_handle) { + *out_endp = endp2; + return (cs_dev); + } +#endif + break; } } } @@ -166,49 +115,6 @@ coresight_get_output_device(struct endpoint *endp, struct endpoint **out_endp) 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) { diff --git a/sys/arm64/coresight/coresight.h b/sys/arm64/coresight/coresight.h index 9ae4db51595e..a3aa71cb207f 100644 --- a/sys/arm64/coresight/coresight.h +++ b/sys/arm64/coresight/coresight.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2018 Ruslan Bukin + * Copyright (c) 2018-2020 Ruslan Bukin * All rights reserved. * * This software was developed by SRI International and the University of @@ -33,7 +33,19 @@ #ifndef _ARM64_CORESIGHT_CORESIGHT_H_ #define _ARM64_CORESIGHT_CORESIGHT_H_ +#include "opt_acpi.h" +#include "opt_platform.h" + +#include + +#ifdef FDT #include +#endif + +#ifdef DEV_ACPI +#include +#include +#endif #define CORESIGHT_ITCTRL 0xf00 #define CORESIGHT_CLAIMSET 0xfa0 @@ -53,20 +65,30 @@ enum cs_dev_type { CORESIGHT_CPU_DEBUG, }; +enum cs_bus_type { + CORESIGHT_BUS_ACPI, + CORESIGHT_BUS_FDT, +}; + 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; +#ifdef FDT phandle_t my_node; phandle_t their_node; phandle_t dev_node; - boolean_t slave; +#endif +#ifdef DEV_ACPI + ACPI_HANDLE their_handle; + ACPI_HANDLE my_handle; +#endif + boolean_t input; int reg; struct coresight_device *cs_dev; LIST_ENTRY(endpoint) endplink; @@ -78,6 +100,7 @@ struct coresight_platform_data { int out_ports; struct mtx mtx_lock; TAILQ_HEAD(endpoint_list, endpoint) endpoints; + enum cs_bus_type bus_type; }; struct coresight_desc { @@ -125,7 +148,10 @@ struct etm_config { uint8_t excp_level; }; -struct coresight_platform_data * coresight_get_platform_data(device_t dev); +static MALLOC_DEFINE(M_CORESIGHT, "coresight", "ARM Coresight"); + +struct coresight_platform_data *coresight_fdt_get_platform_data(device_t dev); +struct coresight_platform_data *coresight_acpi_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); diff --git a/sys/arm64/coresight/coresight_acpi.c b/sys/arm64/coresight/coresight_acpi.c new file mode 100644 index 000000000000..57fda8b97666 --- /dev/null +++ b/sys/arm64/coresight/coresight_acpi.c @@ -0,0 +1,373 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2020 Ruslan Bukin + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory (Department of Computer Science and + * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the + * DARPA SSITH 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define ACPI_CORESIGHT_LINK_OUTPUT 1 +#define ACPI_CORESIGHT_LINK_INPUT 0 + +static const struct uuid acpi_graph_uuid = { + 0xab02a46b, 0x74c7, 0x45a2, 0xbd, 0x68, + { 0xf7, 0xd3, 0x44, 0xef, 0x21, 0x53 }, +}; + +static const struct uuid coresight_graph_uuid = { + 0x3ecbc8b6, 0x1d0e, 0x4fb3, 0x81, 0x07, + { 0xe6, 0x27, 0xf8, 0x05, 0xc6, 0xcd }, +}; + +static inline bool +cs_acpi_validate_dsd_graph(const union acpi_object *graph) +{ + const union acpi_object *rev, *nr_graphs; + const union acpi_object *obj; + int i, n; + + if (graph->Package.Count < 2) + return (false); + + rev = &graph->Package.Elements[0]; + nr_graphs = &graph->Package.Elements[1]; + + if (rev->Type != ACPI_TYPE_INTEGER || + nr_graphs->Type != ACPI_TYPE_INTEGER) + return (false); + + /* Revision 0 supported only. */ + if (rev->Integer.Value != 0) + return (false); + + /* We are looking for a single graph. */ + n = nr_graphs->Integer.Value; + if (n != 1) + return (false); + + /* Check the number of elements. */ + if (graph->Package.Count != (n + 2)) + return (false); + + for (i = 2; i < n + 2; i++) { + obj = &graph->Package.Elements[i]; + if (obj->Type != ACPI_TYPE_PACKAGE || obj->Package.Count < 3) + return (false); + } + + return (true); +} + +static inline bool +cs_is_acpi_guid(const union acpi_object *obj) +{ + + return (obj->Type == ACPI_TYPE_BUFFER) && (obj->Buffer.Length == 16); +} + +static inline bool +cs_guid_equal(const struct uuid *u1, const struct uuid *u2) +{ + + if (memcmp(u1, u2, 16) == 0) + return (true); + + return (false); +} + +static inline bool +cs_acpi_guid_matches(const union acpi_object *obj, const struct uuid *guid) +{ + + if (cs_is_acpi_guid(obj) && + cs_guid_equal((struct uuid *)obj->Buffer.Pointer, guid)) + return (true); + + return (false); +} + +static inline bool +is_acpi_dsd_graph_guid(const union acpi_object *obj) +{ + + return (cs_acpi_guid_matches(obj, &acpi_graph_uuid)); +} + +static inline bool +cs_is_acpi_coresight_graph_guid(const union acpi_object *obj) +{ + + return (cs_acpi_guid_matches(obj, &coresight_graph_uuid)); +} + +static inline bool +cs_is_acpi_coresight_graph(const union acpi_object *obj) +{ + const union acpi_object *graphid, *guid, *links; + + if (obj->Type != ACPI_TYPE_PACKAGE || + obj->Package.Count < 3) + return (false); + + graphid = &obj->Package.Elements[0]; + guid = &obj->Package.Elements[1]; + links = &obj->Package.Elements[2]; + + if (graphid->Type != ACPI_TYPE_INTEGER || + links->Type != ACPI_TYPE_INTEGER) + return (false); + + if (cs_is_acpi_coresight_graph_guid(guid)) + return (true); + + return (false); +} + +static const union acpi_object * +cs_get_dsd_graph(device_t dev) +{ + const union acpi_object *guid, *package; + union acpi_object *dsd; + ACPI_STATUS status; + ACPI_BUFFER buf; + device_t bus; + int i; + + buf.Length = PAGE_SIZE; + buf.Pointer = malloc(buf.Length, M_TEMP, M_NOWAIT | M_ZERO); + if (buf.Pointer == NULL) { + printf("Failed to allocate memory.\n"); + return (NULL); + } + + bus = device_get_parent(dev); + status = ACPI_EVALUATE_OBJECT(bus, dev, "_DSD", NULL, &buf); + if (ACPI_FAILURE(status)) { + printf("Failed to evaluate object.\n"); + return (NULL); + } + + dsd = buf.Pointer; + + for (i = 0; i + 1 < dsd->Package.Count; i += 2) { + guid = &dsd->Package.Elements[i]; + package = &dsd->Package.Elements[i + 1]; + + if (!cs_is_acpi_guid(guid) || + package->Type != ACPI_TYPE_PACKAGE) + break; + + if (!is_acpi_dsd_graph_guid(guid)) + continue; + + if (cs_acpi_validate_dsd_graph(package)) + return (package); + } + + return (NULL); +} + +static inline bool +cs_acpi_validate_coresight_graph(const union acpi_object *cs_graph) +{ + int nlinks; + + nlinks = cs_graph->Package.Elements[2].Integer.Value; + if (cs_graph->Package.Count != (nlinks + 3)) + return (false); + + return (true); +} + +static const union acpi_object * +cs_get_coresight_graph(device_t dev) +{ + const union acpi_object *graph_list, *graph; + int i, nr_graphs; + + graph_list = cs_get_dsd_graph(dev); + if (!graph_list) { + printf("failed to get graph list\n"); + return (NULL); + } + + nr_graphs = graph_list->Package.Elements[1].Integer.Value; + for (i = 2; i < nr_graphs + 2; i++) { + graph = &graph_list->Package.Elements[i]; + if (!cs_is_acpi_coresight_graph(graph)) + continue; + if (cs_acpi_validate_coresight_graph(graph)) + return (graph); + break; + } + + return (NULL); +} + +static int +cs_acpi_record_endpoint(device_t dev, + struct coresight_platform_data *pdata, + const union acpi_object *link) +{ + const union acpi_object *fields; + struct endpoint *endp; + ACPI_HANDLE handle; + int dir; + + if (link->Type != ACPI_TYPE_PACKAGE || + link->Package.Count != 4) + return (ENXIO); + + fields = link->Package.Elements; + if (fields[0].Type != ACPI_TYPE_INTEGER || + fields[1].Type != ACPI_TYPE_INTEGER || + fields[2].Type != ACPI_TYPE_LOCAL_REFERENCE || + fields[3].Type != ACPI_TYPE_INTEGER) + return (ENXIO); + + handle = fields[2].Reference.Handle; + dir = fields[3].Integer.Value; + + endp = malloc(sizeof(struct endpoint), + M_CORESIGHT, M_WAITOK | M_ZERO); + if (endp == NULL) { + device_printf(dev, "Failed to allocate memory.\n"); + return (ENXIO); + } + + endp->their_handle = handle; + endp->my_handle = acpi_get_handle(dev); + + mtx_lock(&pdata->mtx_lock); + TAILQ_INSERT_TAIL(&pdata->endpoints, endp, link); + mtx_unlock(&pdata->mtx_lock); + + if (dir == ACPI_CORESIGHT_LINK_OUTPUT) { + pdata->out_ports++; + } else { + endp->input = true; + pdata->in_ports++; + } + + return (0); +} + +static int +coresight_acpi_get_ports(device_t dev, + struct coresight_platform_data *pdata) +{ + const union acpi_object *graph; + const union acpi_object *link; + int nlinks; + int error; + int i; + + graph = cs_get_coresight_graph(dev); + if (graph == NULL) { + device_printf(dev, "Coresight graph not found.\n"); + return (ENXIO); + } + + nlinks = graph->Package.Elements[2].Integer.Value; + if (!nlinks) + return (0); + + for (i = 0; i < nlinks; i++) { + link = &graph->Package.Elements[3 + i]; + error = cs_acpi_record_endpoint(dev, pdata, link); + if (error < 0) + return (error); + } + + return (0); +} + +static int +coresight_acpi_get_cpu(device_t dev, struct coresight_platform_data *pdata) +{ + ACPI_HANDLE handle, parent; + ACPI_STATUS status; + int cpuid; + + handle = acpi_get_handle(dev); + + status = AcpiGetParent(handle, &parent); + if (!ACPI_SUCCESS(status)) + return (ENXIO); + + if (!acpi_MatchHid(parent, "ACPI0007")) + return (ENXIO); + + status = acpi_GetInteger(parent, "_UID", &cpuid); + if (ACPI_SUCCESS(status)) { + pdata->cpu = cpuid; + return (0); + } + + return (ENXIO); +} + +struct coresight_platform_data * +coresight_acpi_get_platform_data(device_t dev) +{ + struct coresight_platform_data *pdata; + + pdata = malloc(sizeof(struct coresight_platform_data), + M_CORESIGHT, M_WAITOK | M_ZERO); + pdata->bus_type = CORESIGHT_BUS_ACPI; + + mtx_init(&pdata->mtx_lock, "Coresight Platform Data", NULL, MTX_DEF); + TAILQ_INIT(&pdata->endpoints); + + coresight_acpi_get_cpu(dev, pdata); + coresight_acpi_get_ports(dev, pdata); + + if (bootverbose) + printf("Total ports: in %d out %d\n", + pdata->in_ports, pdata->out_ports); + + return (pdata); +} diff --git a/sys/arm64/coresight/coresight_cmd.c b/sys/arm64/coresight/coresight_cmd.c index f0e794509009..c25f512f5aa7 100644 --- a/sys/arm64/coresight/coresight_cmd.c +++ b/sys/arm64/coresight/coresight_cmd.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2018 Ruslan Bukin + * Copyright (c) 2018-2020 Ruslan Bukin * All rights reserved. * * This software was developed by SRI International and the University of @@ -54,7 +54,7 @@ coresight_next_device(struct coresight_device *cs_dev, struct endpoint *endp; TAILQ_FOREACH(endp, &cs_dev->pdata->endpoints, link) { - if (endp->slave != 0) + if (endp->input != 0) continue; out = coresight_get_output_device(endp, &out_endp); @@ -67,6 +67,9 @@ coresight_next_device(struct coresight_device *cs_dev, } /* Add output device */ + if (bootverbose) + printf("Adding device %s to the chain\n", + device_get_nameunit(out->dev)); out_endp->cs_dev = out; LIST_INSERT_HEAD(&event->endplist, out_endp, endplink); diff --git a/sys/arm64/coresight/coresight_cpu_debug.c b/sys/arm64/coresight/coresight_cpu_debug.c index 42d6cf48d044..c28db5fd51c7 100644 --- a/sys/arm64/coresight/coresight_cpu_debug.c +++ b/sys/arm64/coresight/coresight_cpu_debug.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2018 Ruslan Bukin + * Copyright (c) 2018-2020 Ruslan Bukin * All rights reserved. * * This software was developed by BAE Systems, the University of Cambridge @@ -132,7 +132,7 @@ debug_attach(device_t dev) return (ENXIO); } - sc->pdata = coresight_get_platform_data(dev); + sc->pdata = coresight_fdt_get_platform_data(dev); desc.pdata = sc->pdata; desc.dev = dev; desc.dev_type = CORESIGHT_CPU_DEBUG; diff --git a/sys/arm64/coresight/coresight_etm4x.c b/sys/arm64/coresight/coresight_etm4x.c index d1234b7ae0fa..aabea2c41d99 100644 --- a/sys/arm64/coresight/coresight_etm4x.c +++ b/sys/arm64/coresight/coresight_etm4x.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2018 Ruslan Bukin + * Copyright (c) 2018-2020 Ruslan Bukin * All rights reserved. * * This software was developed by BAE Systems, the University of Cambridge @@ -234,7 +234,7 @@ etm_disable(device_t dev, struct endpoint *endp, } while ((reg & TRCSTATR_IDLE) == 0); } -static int +int etm_attach(device_t dev) { struct coresight_desc desc; @@ -247,7 +247,6 @@ etm_attach(device_t dev) return (ENXIO); } - sc->pdata = coresight_get_platform_data(dev); desc.pdata = sc->pdata; desc.dev = dev; desc.dev_type = CORESIGHT_ETMV4; @@ -257,8 +256,6 @@ etm_attach(device_t dev) } static device_method_t etm_methods[] = { - /* Device interface */ - DEVMETHOD(device_attach, etm_attach), /* Coresight interface */ DEVMETHOD(coresight_init, etm_init), diff --git a/sys/arm64/coresight/coresight_etm4x.h b/sys/arm64/coresight/coresight_etm4x.h index 42a4cffedc66..ce84a6c30e70 100644 --- a/sys/arm64/coresight/coresight_etm4x.h +++ b/sys/arm64/coresight/coresight_etm4x.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2018 Ruslan Bukin + * Copyright (c) 2018-2020 Ruslan Bukin * All rights reserved. * * This software was developed by BAE Systems, the University of Cambridge @@ -34,13 +34,6 @@ #ifndef _ARM64_CORESIGHT_ETM4X_H_ #define _ARM64_CORESIGHT_ETM4X_H_ -DECLARE_CLASS(etm_driver); - -struct etm_softc { - struct resource *res; - struct coresight_platform_data *pdata; -}; - #define TRCPRGCTLR 0x004 /* Trace Programming Control Register */ #define TRCPRGCTLR_EN (1 << 0) /* Trace unit enable bit */ #define TRCPROCSELR 0x008 /* Trace PE Select Control Register */ @@ -179,4 +172,13 @@ struct etm_softc { #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] */ +DECLARE_CLASS(etm_driver); + +struct etm_softc { + struct resource *res; + struct coresight_platform_data *pdata; +}; + +int etm_attach(device_t dev); + #endif /* !_ARM64_CORESIGHT_ETM4X_H_ */ diff --git a/sys/arm64/coresight/coresight_etm4x_acpi.c b/sys/arm64/coresight/coresight_etm4x_acpi.c index 00b29a05a24e..93dfd7a4f880 100644 --- a/sys/arm64/coresight/coresight_etm4x_acpi.c +++ b/sys/arm64/coresight/coresight_etm4x_acpi.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include static int @@ -62,9 +63,21 @@ etm_acpi_probe(device_t dev) return (error); } +static int +etm_acpi_attach(device_t dev) +{ + struct etm_softc *sc; + + sc = device_get_softc(dev); + sc->pdata = coresight_acpi_get_platform_data(dev); + + return (etm_attach(dev)); +} + static device_method_t etm_acpi_methods[] = { /* Device interface */ DEVMETHOD(device_probe, etm_acpi_probe), + DEVMETHOD(device_attach, etm_acpi_attach), /* End */ DEVMETHOD_END diff --git a/sys/arm64/coresight/coresight_etm4x_fdt.c b/sys/arm64/coresight/coresight_etm4x_fdt.c index a1e5a785ca31..b3418e538a47 100644 --- a/sys/arm64/coresight/coresight_etm4x_fdt.c +++ b/sys/arm64/coresight/coresight_etm4x_fdt.c @@ -67,9 +67,21 @@ etm_fdt_probe(device_t dev) return (BUS_PROBE_DEFAULT); } +static int +etm_fdt_attach(device_t dev) +{ + struct etm_softc *sc; + + sc = device_get_softc(dev); + sc->pdata = coresight_fdt_get_platform_data(dev); + + return (etm_attach(dev)); +} + static device_method_t etm_fdt_methods[] = { /* Device interface */ DEVMETHOD(device_probe, etm_fdt_probe), + DEVMETHOD(device_attach, etm_fdt_attach), DEVMETHOD_END }; diff --git a/sys/arm64/coresight/coresight_fdt.c b/sys/arm64/coresight/coresight_fdt.c new file mode 100644 index 000000000000..cd21b7da706c --- /dev/null +++ b/sys/arm64/coresight/coresight_fdt.c @@ -0,0 +1,154 @@ +/*- + * Copyright (c) 2018-2020 Ruslan Bukin + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +static int +coresight_fdt_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", (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->input = 1; + } else + pdata->out_ports++; + + mtx_lock(&pdata->mtx_lock); + TAILQ_INSERT_TAIL(&pdata->endpoints, + endp, link); + mtx_unlock(&pdata->mtx_lock); + } + } + } + + return (0); +} + +static int +coresight_fdt_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_fdt_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); + pdata->bus_type = CORESIGHT_BUS_FDT; + + mtx_init(&pdata->mtx_lock, "Coresight Platform Data", NULL, MTX_DEF); + TAILQ_INIT(&pdata->endpoints); + + coresight_fdt_get_cpu(node, pdata); + coresight_fdt_get_ports(node, pdata); + + if (bootverbose) + printf("Total ports: in %d out %d\n", + pdata->in_ports, pdata->out_ports); + + return (pdata); +} diff --git a/sys/arm64/coresight/coresight_funnel.c b/sys/arm64/coresight/coresight_funnel.c index b183bc247867..2eb588f18366 100644 --- a/sys/arm64/coresight/coresight_funnel.c +++ b/sys/arm64/coresight/coresight_funnel.c @@ -111,7 +111,7 @@ funnel_disable(device_t dev, struct endpoint *endp, bus_write_4(sc->res, FUNNEL_FUNCTL, reg); } -static int +int funnel_attach(device_t dev) { struct coresight_desc desc; @@ -124,7 +124,6 @@ funnel_attach(device_t dev) return (ENXIO); } - sc->pdata = coresight_get_platform_data(dev); desc.pdata = sc->pdata; desc.dev = dev; desc.dev_type = CORESIGHT_FUNNEL; @@ -134,9 +133,6 @@ funnel_attach(device_t dev) } static device_method_t funnel_methods[] = { - /* Device interface */ - DEVMETHOD(device_attach, funnel_attach), - /* Coresight interface */ DEVMETHOD(coresight_init, funnel_init), DEVMETHOD(coresight_enable, funnel_enable), diff --git a/sys/arm64/coresight/coresight_funnel.h b/sys/arm64/coresight/coresight_funnel.h index 6deab0516715..a064c187b5bb 100644 --- a/sys/arm64/coresight/coresight_funnel.h +++ b/sys/arm64/coresight/coresight_funnel.h @@ -75,4 +75,6 @@ struct funnel_softc { int hwtype; }; +int funnel_attach(device_t dev); + #endif /* !_ARM64_CORESIGHT_CORESIGHT_FUNNEL_H_ */ diff --git a/sys/arm64/coresight/coresight_funnel_acpi.c b/sys/arm64/coresight/coresight_funnel_acpi.c index 571c771531c4..0757af3d1ce0 100644 --- a/sys/arm64/coresight/coresight_funnel_acpi.c +++ b/sys/arm64/coresight/coresight_funnel_acpi.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include static int @@ -78,9 +79,21 @@ funnel_acpi_probe(device_t dev) return (ENXIO); } +static int +funnel_acpi_attach(device_t dev) +{ + struct funnel_softc *sc; + + sc = device_get_softc(dev); + sc->pdata = coresight_acpi_get_platform_data(dev); + + return (funnel_attach(dev)); +} + static device_method_t funnel_acpi_methods[] = { /* Device interface */ DEVMETHOD(device_probe, funnel_acpi_probe), + DEVMETHOD(device_attach, funnel_acpi_attach), /* End */ DEVMETHOD_END diff --git a/sys/arm64/coresight/coresight_funnel_fdt.c b/sys/arm64/coresight/coresight_funnel_fdt.c index 6d8514e4fd28..92951e7b3ec9 100644 --- a/sys/arm64/coresight/coresight_funnel_fdt.c +++ b/sys/arm64/coresight/coresight_funnel_fdt.c @@ -79,6 +79,17 @@ funnel_fdt_probe(device_t dev) return (BUS_PROBE_DEFAULT); } +static int +funnel_fdt_attach(device_t dev) +{ + struct funnel_softc *sc; + + sc = device_get_softc(dev); + sc->pdata = coresight_fdt_get_platform_data(dev); + + return (funnel_attach(dev)); +} + static device_method_t funnel_fdt_methods[] = { /* Device interface */ DEVMETHOD(device_probe, funnel_fdt_probe), diff --git a/sys/arm64/coresight/coresight_replicator.c b/sys/arm64/coresight/coresight_replicator.c index 121eb5d10c15..e7b4fdb770f6 100644 --- a/sys/arm64/coresight/coresight_replicator.c +++ b/sys/arm64/coresight/coresight_replicator.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2018 Ruslan Bukin + * Copyright (c) 2018-2020 Ruslan Bukin * All rights reserved. * * This software was developed by BAE Systems, the University of Cambridge @@ -95,7 +95,7 @@ replicator_disable(device_t dev, struct endpoint *endp, bus_write_4(sc->res, REPLICATOR_IDFILTER1, 0xff); } -static int +int replicator_attach(device_t dev) { struct replicator_softc *sc; @@ -108,7 +108,6 @@ replicator_attach(device_t dev) return (ENXIO); } - sc->pdata = coresight_get_platform_data(dev); desc.pdata = sc->pdata; desc.dev = dev; desc.dev_type = CORESIGHT_DYNAMIC_REPLICATOR; @@ -118,9 +117,6 @@ replicator_attach(device_t dev) } static device_method_t replicator_methods[] = { - /* Device interface */ - DEVMETHOD(device_attach, replicator_attach), - /* Coresight interface */ DEVMETHOD(coresight_init, replicator_init), DEVMETHOD(coresight_enable, replicator_enable), diff --git a/sys/arm64/coresight/coresight_replicator.h b/sys/arm64/coresight/coresight_replicator.h index 62c5c329799c..0b47eb5c9cd7 100644 --- a/sys/arm64/coresight/coresight_replicator.h +++ b/sys/arm64/coresight/coresight_replicator.h @@ -43,4 +43,6 @@ struct replicator_softc { struct coresight_platform_data *pdata; }; +int replicator_attach(device_t dev); + #endif /* !_ARM64_CORESIGHT_CORESIGHT_REPLICATOR_H_ */ diff --git a/sys/arm64/coresight/coresight_replicator_acpi.c b/sys/arm64/coresight/coresight_replicator_acpi.c index 694b9eaa717c..7cc08930c81f 100644 --- a/sys/arm64/coresight/coresight_replicator_acpi.c +++ b/sys/arm64/coresight/coresight_replicator_acpi.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include static int @@ -63,9 +64,21 @@ replicator_acpi_probe(device_t dev) return (error); } +static int +replicator_acpi_attach(device_t dev) +{ + struct replicator_softc *sc; + + sc = device_get_softc(dev); + sc->pdata = coresight_acpi_get_platform_data(dev); + + return (replicator_attach(dev)); +} + static device_method_t replicator_acpi_methods[] = { /* Device interface */ - DEVMETHOD(device_probe, replicator_acpi_probe), + DEVMETHOD(device_probe, replicator_acpi_probe), + DEVMETHOD(device_attach, replicator_acpi_attach), /* End */ DEVMETHOD_END diff --git a/sys/arm64/coresight/coresight_replicator_fdt.c b/sys/arm64/coresight/coresight_replicator_fdt.c index ef5d67a1db6f..8c5bde1974a8 100644 --- a/sys/arm64/coresight/coresight_replicator_fdt.c +++ b/sys/arm64/coresight/coresight_replicator_fdt.c @@ -67,6 +67,17 @@ replicator_fdt_probe(device_t dev) return (BUS_PROBE_DEFAULT); } +static int +replicator_acpi_attach(device_t dev) +{ + struct replicator_softc *sc; + + sc = device_get_softc(dev); + sc->pdata = coresight_fdt_get_platform_data(dev); + + return (replicator_attach(dev)); +} + static device_method_t replicator_fdt_methods[] = { /* Device interface */ DEVMETHOD(device_probe, replicator_fdt_probe), diff --git a/sys/arm64/coresight/coresight_tmc.c b/sys/arm64/coresight/coresight_tmc.c index 901f2ad81dd6..262e70ea4495 100644 --- a/sys/arm64/coresight/coresight_tmc.c +++ b/sys/arm64/coresight/coresight_tmc.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2018 Ruslan Bukin + * Copyright (c) 2018-2020 Ruslan Bukin * All rights reserved. * * This software was developed by SRI International and the University of @@ -312,14 +312,13 @@ tmc_read(device_t dev, struct endpoint *endp, return (0); } -static int +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) { @@ -327,7 +326,6 @@ tmc_attach(device_t dev) return (ENXIO); } - sc->pdata = coresight_get_platform_data(dev); desc.pdata = sc->pdata; desc.dev = dev; desc.dev_type = CORESIGHT_TMC; diff --git a/sys/arm64/coresight/coresight_tmc.h b/sys/arm64/coresight/coresight_tmc.h index 709f7000d5f1..051fb63f58f9 100644 --- a/sys/arm64/coresight/coresight_tmc.h +++ b/sys/arm64/coresight/coresight_tmc.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2018 Ruslan Bukin + * Copyright (c) 2018-2020 Ruslan Bukin * All rights reserved. * * This software was developed by SRI International and the University of @@ -132,4 +132,6 @@ struct tmc_softc { boolean_t etf_configured; }; +int tmc_attach(device_t dev); + #endif /* !_ARM64_CORESIGHT_CORESIGHT_TMC_H_ */ diff --git a/sys/arm64/coresight/coresight_tmc_acpi.c b/sys/arm64/coresight/coresight_tmc_acpi.c index 33da280008c3..020306593fc8 100644 --- a/sys/arm64/coresight/coresight_tmc_acpi.c +++ b/sys/arm64/coresight/coresight_tmc_acpi.c @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include static int @@ -62,9 +63,21 @@ tmc_acpi_probe(device_t dev) return (error); } +static int +tmc_acpi_attach(device_t dev) +{ + struct tmc_softc *sc; + + sc = device_get_softc(dev); + sc->pdata = coresight_acpi_get_platform_data(dev); + + return (tmc_attach(dev)); +} + static device_method_t tmc_acpi_methods[] = { /* Device interface */ DEVMETHOD(device_probe, tmc_acpi_probe), + DEVMETHOD(device_attach, tmc_acpi_attach), /* End */ DEVMETHOD_END diff --git a/sys/arm64/coresight/coresight_tmc_fdt.c b/sys/arm64/coresight/coresight_tmc_fdt.c index 249c817c485d..6b057231e208 100644 --- a/sys/arm64/coresight/coresight_tmc_fdt.c +++ b/sys/arm64/coresight/coresight_tmc_fdt.c @@ -67,9 +67,21 @@ tmc_fdt_probe(device_t dev) return (BUS_PROBE_DEFAULT); } +static int +tmc_fdt_attach(device_t dev) +{ + struct tmc_softc *sc; + + sc = device_get_softc(dev); + sc->pdata = coresight_fdt_get_platform_data(dev); + + return (tmc_attach(dev)); +} + static device_method_t tmc_fdt_methods[] = { /* Device interface */ DEVMETHOD(device_probe, tmc_fdt_probe), + DEVMETHOD(device_attach, tmc_fdt_attach), DEVMETHOD_END }; diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 1db70147cc74..08addf0df919 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -186,6 +186,8 @@ arm64/cavium/thunder_pcie_common.c optional soc_cavm_thunderx pci arm64/cloudabi32/cloudabi32_sysvec.c optional compat_cloudabi32 arm64/cloudabi64/cloudabi64_sysvec.c optional compat_cloudabi64 arm64/coresight/coresight.c standard +arm64/coresight/coresight_acpi.c optional acpi +arm64/coresight/coresight_fdt.c optional fdt arm64/coresight/coresight_if.m standard arm64/coresight/coresight_cmd.c standard arm64/coresight/coresight_cpu_debug.c standard