Complete the ACPI support for ARM Coresight:

o Parse the ACPI DSD (Device Specific Data) graph property and record
  device connections.
o Split-out FDT support to a separate file.
o Get the corresponding (FDT/ACPI) Coresight platform data in
  the device drivers.

Sponsored by:	DARPA, AFRL
This commit is contained in:
br 2020-06-17 15:54:51 +00:00
parent bb705f11f9
commit 8ce15a8c35
23 changed files with 711 additions and 154 deletions

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
@ -41,78 +41,11 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.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", (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)
{

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
* 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 <sys/bus.h>
#ifdef FDT
#include <dev/ofw/openfirm.h>
#endif
#ifdef DEV_ACPI
#include <contrib/dev/acpica/include/acpi.h>
#include <dev/acpica/acpivar.h>
#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);

View File

@ -0,0 +1,373 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 Ruslan Bukin <br@bsdpad.com>
*
* 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 <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/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/uuid.h>
#include <machine/bus.h>
#include <contrib/dev/acpica/include/acpi.h>
#include <dev/acpica/acpivar.h>
#include <arm64/coresight/coresight.h>
#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);
}

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
* 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);

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
* 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;

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
* 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),

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
* 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_ */

View File

@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <contrib/dev/acpica/include/acpi.h>
#include <dev/acpica/acpivar.h>
#include <arm64/coresight/coresight.h>
#include <arm64/coresight/coresight_etm4x.h>
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

View File

@ -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
};

View File

@ -0,0 +1,154 @@
/*-
* Copyright (c) 2018-2020 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/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <machine/bus.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <arm64/coresight/coresight.h>
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);
}

View File

@ -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),

View File

@ -75,4 +75,6 @@ struct funnel_softc {
int hwtype;
};
int funnel_attach(device_t dev);
#endif /* !_ARM64_CORESIGHT_CORESIGHT_FUNNEL_H_ */

View File

@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <contrib/dev/acpica/include/acpi.h>
#include <dev/acpica/acpivar.h>
#include <arm64/coresight/coresight.h>
#include <arm64/coresight/coresight_funnel.h>
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

View File

@ -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),

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
* 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),

View File

@ -43,4 +43,6 @@ struct replicator_softc {
struct coresight_platform_data *pdata;
};
int replicator_attach(device_t dev);
#endif /* !_ARM64_CORESIGHT_CORESIGHT_REPLICATOR_H_ */

View File

@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <contrib/dev/acpica/include/acpi.h>
#include <dev/acpica/acpivar.h>
#include <arm64/coresight/coresight.h>
#include <arm64/coresight/coresight_replicator.h>
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

View File

@ -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),

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
* 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;

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
* 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_ */

View File

@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <contrib/dev/acpica/include/acpi.h>
#include <dev/acpica/acpivar.h>
#include <arm64/coresight/coresight.h>
#include <arm64/coresight/coresight_tmc.h>
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

View File

@ -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
};

View File

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