Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108593428
D40477.id123010.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
34 KB
Referenced Files
None
Subscribers
None
D40477.id123010.diff
View Options
Index: sys/arm64/coresight/coresight.h
===================================================================
--- sys/arm64/coresight/coresight.h
+++ sys/arm64/coresight/coresight.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -60,7 +60,8 @@
enum cs_dev_type {
CORESIGHT_ETMV4,
- CORESIGHT_TMC,
+ CORESIGHT_TMC_ETF,
+ CORESIGHT_TMC_ETR,
CORESIGHT_DYNAMIC_REPLICATOR,
CORESIGHT_FUNNEL,
CORESIGHT_CPU_DEBUG,
@@ -125,9 +126,10 @@
uint32_t low;
uint32_t high;
uint32_t bufsize;
- uint32_t flags;
-#define ETR_FLAG_ALLOCATE (1 << 0)
-#define ETR_FLAG_RELEASE (1 << 1)
+ vm_page_t *pages;
+ int npages;
+ int curpage;
+ vm_offset_t curpage_offset;
};
struct coresight_event {
@@ -154,11 +156,14 @@
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 **);
+struct coresight_device * coresight_get_output_device(struct coresight_device *cs_dev, struct endpoint *endp, struct endpoint **);
int coresight_register(struct coresight_desc *desc);
int coresight_init_event(int cpu, struct coresight_event *event);
+void coresight_start(int cpu, struct coresight_event *event);
+void coresight_stop(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);
+void coresight_dump(int cpu, struct coresight_event *event);
#endif /* !_ARM64_CORESIGHT_CORESIGHT_H_ */
Index: sys/arm64/coresight/coresight.c
===================================================================
--- sys/arm64/coresight/coresight.c
+++ sys/arm64/coresight/coresight.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -42,10 +42,127 @@
#include <machine/bus.h>
#include <arm64/coresight/coresight.h>
+#include <dev/hwt/hwtvar.h>
static struct mtx cs_mtx;
struct coresight_device_list cs_devs;
+static struct hwt_backend backend;
+static struct coresight_event cs_event[MAXCPU];
+
+static void
+coresight_event_init(struct hwt_context *hwt)
+{
+ struct coresight_event *event;
+
+#if 0
+ printf("%s: cpu_id %d\n", __func__, hwt->cpu_id);
+#endif
+
+ event = &cs_event[hwt->cpu_id];
+ memset(event, 0, sizeof(struct coresight_event));
+ event->etr.started = 0;
+ event->etr.low = 0;
+ event->etr.high = 0;
+ event->etr.pages = hwt->pages;
+ event->etr.npages = hwt->npages;
+ event->etr.bufsize = hwt->npages * PAGE_SIZE;
+ event->excp_level = 1; /* Kernel */
+ event->excp_level = 0; /* User level */
+ event->src = CORESIGHT_ETMV4;
+ event->sink = CORESIGHT_TMC_ETR;
+
+ /*
+ * Set the trace ID required for ETM component.
+ * TODO: this should be derived from pmctrace.
+ */
+
+ event->etm.trace_id = 0x10;
+ coresight_init_event(hwt->cpu_id, event);
+}
+
+static void
+coresight_event_start(struct hwt_context *hwt)
+{
+ struct coresight_event *event;
+
+#if 0
+ printf("%s: cpu_id %d\n", __func__, hwt->cpu_id);
+#endif
+
+ event = &cs_event[hwt->cpu_id];
+
+ coresight_start(hwt->cpu_id, event);
+}
+
+static void
+coresight_event_stop(struct hwt_context *hwt)
+{
+ struct coresight_event *event;
+
+ event = &cs_event[hwt->cpu_id];
+
+ coresight_stop(hwt->cpu_id, event);
+}
+
+static void
+coresight_event_enable(struct hwt_context *hwt)
+{
+ struct coresight_event *event;
+
+ event = &cs_event[hwt->cpu_id];
+
+ coresight_enable(hwt->cpu_id, event);
+}
+
+static void
+coresight_event_disable(struct hwt_context *hwt)
+{
+ struct coresight_event *event;
+
+ event = &cs_event[hwt->cpu_id];
+
+ coresight_disable(hwt->cpu_id, event);
+}
+
+static void
+coresight_event_dump(struct hwt_context *hwt)
+{
+ struct coresight_event *event;
+
+ event = &cs_event[hwt->cpu_id];
+
+ coresight_dump(hwt->cpu_id, event);
+}
+
+static int
+coresight_event_read(struct hwt_context *hwt, int *curpage,
+ vm_offset_t *curpage_offset)
+{
+ struct coresight_event *event;
+
+ event = &cs_event[hwt->cpu_id];
+
+ KASSERT(event != NULL, ("No event found"));
+
+ coresight_read(hwt->cpu_id, event);
+
+ *curpage = event->etr.curpage;
+ *curpage_offset = event->etr.curpage_offset;
+
+ return (0);
+}
+
+static struct hwt_backend_ops coresight_ops = {
+ .hwt_event_init = coresight_event_init,
+ .hwt_event_start = coresight_event_start,
+ .hwt_event_stop = coresight_event_stop,
+ .hwt_event_enable = coresight_event_enable,
+ .hwt_event_disable = coresight_event_disable,
+ .hwt_event_dump = coresight_event_dump,
+ .hwt_event_read = coresight_event_read,
+};
+
int
coresight_register(struct coresight_desc *desc)
{
@@ -61,6 +178,11 @@
TAILQ_INSERT_TAIL(&cs_devs, cs_dev, link);
mtx_unlock(&cs_mtx);
+ if (desc->dev_type == CORESIGHT_TMC_ETR) {
+ backend.ops = &coresight_ops;
+ hwt_register(&backend);
+ }
+
return (0);
}
@@ -81,7 +203,8 @@
}
struct coresight_device *
-coresight_get_output_device(struct endpoint *endp, struct endpoint **out_endp)
+coresight_get_output_device(struct coresight_device *cs_dev0,
+ struct endpoint *endp, struct endpoint **out_endp)
{
struct coresight_platform_data *pdata;
struct coresight_device *cs_dev;
@@ -94,7 +217,11 @@
case CORESIGHT_BUS_FDT:
#ifdef FDT
if (endp->their_node == endp2->my_node) {
- *out_endp = endp2;
+ *out_endp =
+ malloc(sizeof(struct endpoint),
+ M_CORESIGHT, M_WAITOK | M_ZERO);
+ memcpy(*out_endp, endp2,
+ sizeof(struct endpoint));
return (cs_dev);
}
#endif
@@ -103,7 +230,11 @@
case CORESIGHT_BUS_ACPI:
#ifdef DEV_ACPI
if (endp->their_handle == endp2->my_handle) {
- *out_endp = endp2;
+ *out_endp =
+ malloc(sizeof(struct endpoint),
+ M_CORESIGHT, M_WAITOK | M_ZERO);
+ memcpy(*out_endp, endp2,
+ sizeof(struct endpoint));
return (cs_dev);
}
#endif
Index: sys/arm64/coresight/coresight_cmd.c
===================================================================
--- sys/arm64/coresight/coresight_cmd.c
+++ sys/arm64/coresight/coresight_cmd.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -57,7 +57,7 @@
if (endp->input != 0)
continue;
- out = coresight_get_output_device(endp, &out_endp);
+ out = coresight_get_output_device(cs_dev, endp, &out_endp);
if (out != NULL) {
if (LIST_EMPTY(&event->endplist)) {
/* Add source device */
@@ -122,9 +122,39 @@
CORESIGHT_INIT(cs_dev->dev);
}
+ /* Configure all devices in the path. */
+ LIST_FOREACH(endp, &event->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ CORESIGHT_CONFIGURE(cs_dev->dev, event);
+ }
+
return (0);
}
+void
+coresight_start(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_START(cs_dev->dev, endp, event);
+ }
+}
+
+void
+coresight_stop(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_STOP(cs_dev->dev, endp, event);
+ }
+}
+
void
coresight_enable(int cpu, struct coresight_event *event)
{
@@ -149,11 +179,26 @@
}
}
+void
+coresight_dump(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_DUMP(cs_dev->dev);
+ }
+}
+
void
coresight_read(int cpu, struct coresight_event *event)
{
+ struct coresight_device *cs_dev;
struct endpoint *endp;
- LIST_FOREACH(endp, &event->endplist, endplink)
- CORESIGHT_READ(endp->cs_dev->dev, endp, event);
+ LIST_FOREACH(endp, &event->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ CORESIGHT_READ(cs_dev->dev, endp, event);
+ }
}
Index: sys/arm64/coresight/coresight_etm4x.h
===================================================================
--- sys/arm64/coresight/coresight_etm4x.h
+++ sys/arm64/coresight/coresight_etm4x.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
Index: sys/arm64/coresight/coresight_etm4x.c
===================================================================
--- sys/arm64/coresight/coresight_etm4x.c
+++ sys/arm64/coresight/coresight_etm4x.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -75,6 +75,8 @@
uint32_t reg;
int i;
+ dprintf("%s%d\n", __func__, device_get_unit(dev));
+
sc = device_get_softc(dev);
/* Configure ETM */
@@ -88,6 +90,7 @@
reg |= TRCCONFIGR_INSTP0_LDRSTR;
reg |= TRCCONFIGR_COND_ALL;
bus_write_4(sc->res, TRCCONFIGR, reg);
+ dprintf("%s: TRCCONFIGR is %x\n", __func__, reg);
/* Disable all event tracing. */
bus_write_4(sc->res, TRCEVENTCTL0R, 0);
@@ -102,6 +105,11 @@
/* Set a value for the trace ID */
bus_write_4(sc->res, TRCTRACEIDR, event->etm.trace_id);
+ dprintf("%s: IDR0 is %x\n", __func__, bus_read_4(sc->res, TRCIDR(0)));
+ dprintf("%s: IDR1 is %x\n", __func__, bus_read_4(sc->res, TRCIDR(1)));
+ dprintf("%s: IDR2 is %x\n", __func__, bus_read_4(sc->res, TRCIDR(2)));
+ dprintf("%s: IDR8 is %x\n", __func__, bus_read_4(sc->res, TRCIDR(8)));
+
/*
* Disable the timestamp event. The trace unit still generates
* timestamps due to other reasons such as trace synchronization.
@@ -191,6 +199,16 @@
return (0);
}
+static int
+etm_start(device_t dev, struct endpoint *endp,
+ struct coresight_event *event)
+{
+
+ etm_prepare(dev, event);
+
+ return (0);
+}
+
static int
etm_enable(device_t dev, struct endpoint *endp,
struct coresight_event *event)
@@ -200,7 +218,7 @@
sc = device_get_softc(dev);
- etm_prepare(dev, event);
+ dprintf("%s%d\n", __func__, device_get_unit(dev));
/* Enable the trace unit */
bus_write_4(sc->res, TRCPRGCTLR, TRCPRGCTLR_EN);
@@ -225,6 +243,8 @@
sc = device_get_softc(dev);
+ dprintf("%s%d\n", __func__, device_get_unit(dev));
+
/* Disable the trace unit */
bus_write_4(sc->res, TRCPRGCTLR, 0);
@@ -258,6 +278,7 @@
static device_method_t etm_methods[] = {
/* Coresight interface */
DEVMETHOD(coresight_init, etm_init),
+ DEVMETHOD(coresight_start, etm_start),
DEVMETHOD(coresight_enable, etm_enable),
DEVMETHOD(coresight_disable, etm_disable),
DEVMETHOD_END
Index: sys/arm64/coresight/coresight_fdt.c
===================================================================
--- sys/arm64/coresight/coresight_fdt.c
+++ sys/arm64/coresight/coresight_fdt.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -39,6 +39,7 @@
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/smp.h>
#include <machine/bus.h>
#include <dev/ofw/ofw_bus.h>
@@ -47,10 +48,10 @@
#include <arm64/coresight/coresight.h>
static int
-coresight_fdt_get_ports(phandle_t dev_node,
- struct coresight_platform_data *pdata)
+coresight_fdt_get_ports(phandle_t dev_node, phandle_t node,
+ struct coresight_platform_data *pdata, bool input)
{
- phandle_t node, child;
+ phandle_t child;
pcell_t port_reg;
phandle_t xref;
char *name;
@@ -58,12 +59,6 @@
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)
@@ -89,8 +84,8 @@
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) {
+
+ if (input) {
pdata->in_ports++;
endp->input = 1;
} else
@@ -108,19 +103,27 @@
}
static int
-coresight_fdt_get_cpu(phandle_t node,
- struct coresight_platform_data *pdata)
+coresight_fdt_get_cpu(phandle_t node, struct coresight_platform_data *pdata)
{
+ struct pcpu *pcpu;
phandle_t cpu_node;
pcell_t xref;
- pcell_t cpu_reg;
+ pcell_t cpu_reg[2];
+ int i;
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);
+ sizeof(cpu_reg)) > 0) {
+ for (i = 0; i < mp_ncpus; i++) {
+ pcpu = cpuid_to_pcpu[i];
+ if (pcpu->pc_mpidr_low == cpu_reg[1] &&
+ pcpu->pc_mpidr_high == cpu_reg[0]) {
+ pdata->cpu = pcpu->pc_cpuid;
+printf("cpuid %d\n", pdata->cpu);
+ return (0);
+ }
+ }
}
}
@@ -131,7 +134,7 @@
coresight_fdt_get_platform_data(device_t dev)
{
struct coresight_platform_data *pdata;
- phandle_t node;
+ phandle_t node, child;
node = ofw_bus_get_node(dev);
@@ -143,7 +146,14 @@
TAILQ_INIT(&pdata->endpoints);
coresight_fdt_get_cpu(node, pdata);
- coresight_fdt_get_ports(node, pdata);
+
+ child = ofw_bus_find_child(node, "in-ports");
+ if (child)
+ coresight_fdt_get_ports(node, child, pdata, true);
+
+ child = ofw_bus_find_child(node, "out-ports");
+ if (child)
+ coresight_fdt_get_ports(node, child, pdata, false);
if (bootverbose)
printf("Total ports: in %d out %d\n",
Index: sys/arm64/coresight/coresight_funnel.c
===================================================================
--- sys/arm64/coresight/coresight_funnel.c
+++ sys/arm64/coresight/coresight_funnel.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -76,7 +76,7 @@
}
static int
-funnel_enable(device_t dev, struct endpoint *endp,
+funnel_start(device_t dev, struct endpoint *endp,
struct coresight_event *event)
{
struct funnel_softc *sc;
@@ -96,7 +96,7 @@
}
static void
-funnel_disable(device_t dev, struct endpoint *endp,
+funnel_stop(device_t dev, struct endpoint *endp,
struct coresight_event *event)
{
struct funnel_softc *sc;
@@ -135,8 +135,8 @@
static device_method_t funnel_methods[] = {
/* Coresight interface */
DEVMETHOD(coresight_init, funnel_init),
- DEVMETHOD(coresight_enable, funnel_enable),
- DEVMETHOD(coresight_disable, funnel_disable),
+ DEVMETHOD(coresight_start, funnel_start),
+ DEVMETHOD(coresight_stop, funnel_stop),
DEVMETHOD_END
};
Index: sys/arm64/coresight/coresight_funnel_fdt.c
===================================================================
--- sys/arm64/coresight/coresight_funnel_fdt.c
+++ sys/arm64/coresight/coresight_funnel_fdt.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -49,7 +49,7 @@
#include "coresight_if.h"
static struct ofw_compat_data compat_data[] = {
- { "arm,coresight-funnel", HWTYPE_FUNNEL },
+ { "arm,coresight-dynamic-funnel", HWTYPE_FUNNEL },
{ "arm,coresight-static-funnel", HWTYPE_STATIC_FUNNEL },
{ NULL, HWTYPE_NONE }
};
Index: sys/arm64/coresight/coresight_if.m
===================================================================
--- sys/arm64/coresight/coresight_if.m
+++ sys/arm64/coresight/coresight_if.m
@@ -1,5 +1,5 @@
#-
-# Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com>
+# Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com>
# All rights reserved.
#
# This software was developed by SRI International and the University of
@@ -39,6 +39,23 @@
device_t dev;
};
+METHOD int configure {
+ device_t dev;
+ struct coresight_event *event;
+};
+
+METHOD int start {
+ device_t dev;
+ struct endpoint *endp;
+ struct coresight_event *event;
+};
+
+METHOD void stop {
+ device_t dev;
+ struct endpoint *endp;
+ struct coresight_event *event;
+};
+
METHOD int enable {
device_t dev;
struct endpoint *endp;
@@ -51,6 +68,10 @@
struct coresight_event *event;
};
+METHOD void dump {
+ device_t dev;
+};
+
METHOD int read {
device_t dev;
struct endpoint *endp;
Index: sys/arm64/coresight/coresight_replicator.c
===================================================================
--- sys/arm64/coresight/coresight_replicator.c
+++ sys/arm64/coresight/coresight_replicator.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -64,7 +64,7 @@
}
static int
-replicator_enable(device_t dev, struct endpoint *endp,
+replicator_start(device_t dev, struct endpoint *endp,
struct coresight_event *event)
{
struct replicator_softc *sc;
@@ -84,7 +84,7 @@
}
static void
-replicator_disable(device_t dev, struct endpoint *endp,
+replicator_stop(device_t dev, struct endpoint *endp,
struct coresight_event *event)
{
struct replicator_softc *sc;
@@ -119,8 +119,8 @@
static device_method_t replicator_methods[] = {
/* Coresight interface */
DEVMETHOD(coresight_init, replicator_init),
- DEVMETHOD(coresight_enable, replicator_enable),
- DEVMETHOD(coresight_disable, replicator_disable),
+ DEVMETHOD(coresight_start, replicator_start),
+ DEVMETHOD(coresight_stop, replicator_stop),
DEVMETHOD_END
};
Index: sys/arm64/coresight/coresight_tmc.h
===================================================================
--- sys/arm64/coresight/coresight_tmc.h
+++ sys/arm64/coresight/coresight_tmc.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -119,7 +119,7 @@
DECLARE_CLASS(tmc_driver);
struct tmc_softc {
- struct resource *res;
+ struct resource *res[2];
device_t dev;
uint64_t cycle;
struct coresight_platform_data *pdata;
@@ -128,10 +128,13 @@
#define CORESIGHT_ETR 1
#define CORESIGHT_ETF 2
uint32_t nev;
- struct coresight_event *event;
boolean_t etf_configured;
+ boolean_t scatter_gather;
+ void *intrhand;
};
+typedef uint32_t sgte_t;
+
int tmc_attach(device_t dev);
#endif /* !_ARM64_CORESIGHT_CORESIGHT_TMC_H_ */
Index: sys/arm64/coresight/coresight_tmc.c
===================================================================
--- sys/arm64/coresight/coresight_tmc.c
+++ sys/arm64/coresight/coresight_tmc.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
+ * Copyright (c) 2018-2023 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -39,6 +39,14 @@
#include <sys/module.h>
#include <machine/bus.h>
+#include <vm/vm.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/pmap.h>
+
#include <arm64/coresight/coresight.h>
#include <arm64/coresight/coresight_tmc.h>
@@ -46,18 +54,85 @@
#define TMC_DEBUG
#undef TMC_DEBUG
-
+
#ifdef TMC_DEBUG
#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define dprintf(fmt, ...)
#endif
+#define SG_PT_ENTIRES_PER_PAGE (PAGE_SIZE / sizeof(sgte_t))
+#define ETR_SG_ET_MASK 0x3
+#define ETR_SG_ET_LAST 0x1
+#define ETR_SG_ET_NORMAL 0x2
+#define ETR_SG_ET_LINK 0x3
+
+#define ETR_SG_PAGE_SHIFT 12
+#define ETR_SG_ADDR_SHIFT 4
+
+#define ETR_SG_ENTRY(addr, type) \
+ (sgte_t)((((addr) >> ETR_SG_PAGE_SHIFT) << ETR_SG_ADDR_SHIFT) | \
+ (type & ETR_SG_ET_MASK))
+
static struct resource_spec tmc_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE | RF_OPTIONAL },
{ -1, 0 }
};
+static int
+tmc_alloc_pages(struct tmc_softc *sc, vm_page_t *pages, int npages)
+{
+ vm_paddr_t low, high, boundary;
+ vm_memattr_t memattr;
+ int alignment;
+ vm_pointer_t va;
+ int pflags;
+ vm_page_t m;
+ int tries;
+ int i;
+
+ alignment = PAGE_SIZE;
+ low = 0;
+ high = -1UL;
+ boundary = 0;
+ pflags = VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY | VM_ALLOC_WIRED |
+ VM_ALLOC_ZERO;
+ memattr = VM_MEMATTR_DEFAULT;
+
+ for (i = 0; i < npages; i++) {
+ tries = 0;
+retry:
+ m = vm_page_alloc_noobj_contig(pflags, 1, low, high,
+ alignment, boundary, memattr);
+ if (m == NULL) {
+ if (tries < 3) {
+ if (!vm_page_reclaim_contig(pflags, 1, low,
+ high, alignment, boundary))
+ vm_wait(NULL);
+ tries++;
+ goto retry;
+ }
+
+ return (ENOMEM);
+ }
+
+ if ((m->flags & PG_ZERO) == 0)
+ pmap_zero_page(m);
+
+ va = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
+ cpu_dcache_wb_range(va, PAGE_SIZE);
+ cpu_dcache_inv_range(va, PAGE_SIZE);
+ m->valid = VM_PAGE_BITS_ALL;
+ m->oflags &= ~VPO_UNMANAGED;
+ m->flags |= PG_FICTITIOUS;
+
+ pages[i] = m;
+ }
+
+ return (0);
+}
+
static int
tmc_start(device_t dev)
{
@@ -66,21 +141,27 @@
sc = device_get_softc(dev);
- if (bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN)
+ if (sc->dev_type == CORESIGHT_ETR) {
+ dprintf("%s%d\n", __func__, device_get_unit(dev));
+ }
+
+ if (bus_read_4(sc->res[0], 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)
+ bus_write_4(sc->res[0], TMC_CTL, CTL_TRACECAPTEN);
+ if ((bus_read_4(sc->res[0], TMC_CTL) & CTL_TRACECAPTEN) == 0)
panic("Not enabled\n");
do {
- reg = bus_read_4(sc->res, TMC_STS);
+ reg = bus_read_4(sc->res[0], TMC_STS);
} while ((reg & STS_TMCREADY) == 1);
- if ((bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN) == 0)
+ if ((bus_read_4(sc->res[0], TMC_CTL) & CTL_TRACECAPTEN) == 0)
panic("Not enabled\n");
+ dprintf("%s: enabled\n", __func__);
+
return (0);
}
@@ -92,17 +173,49 @@
sc = device_get_softc(dev);
- reg = bus_read_4(sc->res, TMC_CTL);
+ dprintf("%s\n", __func__);
+
+ reg = bus_read_4(sc->res[0], TMC_CTL);
reg &= ~CTL_TRACECAPTEN;
- bus_write_4(sc->res, TMC_CTL, reg);
+ bus_write_4(sc->res[0], TMC_CTL, reg);
do {
- reg = bus_read_4(sc->res, TMC_STS);
+ reg = bus_read_4(sc->res[0], TMC_STS);
} while ((reg & STS_TMCREADY) == 1);
return (0);
}
+static void
+tmc_dump(device_t dev)
+{
+ struct tmc_softc *sc;
+ uint32_t reg;
+ size_t hi, lo;
+ size_t rrp, rwp;
+
+ sc = device_get_softc(dev);
+
+ lo = bus_read_4(sc->res[0], TMC_RRP);
+ hi = bus_read_4(sc->res[0], TMC_RRPHI);
+ rrp = lo | (hi << 32);
+
+ lo = bus_read_4(sc->res[0], TMC_RWP);
+ hi = bus_read_4(sc->res[0], TMC_RWPHI);
+ rwp = lo | (hi << 32);
+
+ reg = bus_read_4(sc->res[0], TMC_DEVID);
+ if ((reg & DEVID_CONFIGTYPE_M) == DEVID_CONFIGTYPE_ETR)
+ printf("%s%d: STS %x CTL %x RSZ %x RRP %lx RWP %lx AXICTL %x\n",
+ __func__,
+ device_get_unit(dev),
+ bus_read_4(sc->res[0], TMC_STS),
+ bus_read_4(sc->res[0], TMC_CTL),
+ bus_read_4(sc->res[0], TMC_RSZ),
+ rrp, rwp,
+ bus_read_4(sc->res[0], TMC_AXICTL));
+}
+
static int
tmc_configure_etf(device_t dev)
{
@@ -112,23 +225,14 @@
sc = device_get_softc(dev);
do {
- reg = bus_read_4(sc->res, TMC_STS);
+ reg = bus_read_4(sc->res[0], 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);
+ bus_write_4(sc->res[0], TMC_MODE, MODE_HW_FIFO);
+ bus_write_4(sc->res[0], 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));
+ tmc_dump(dev);
return (0);
}
@@ -142,44 +246,172 @@
sc = device_get_softc(dev);
- tmc_stop(dev);
-
do {
- reg = bus_read_4(sc->res, TMC_STS);
+ reg = bus_read_4(sc->res[0], TMC_STS);
} while ((reg & STS_TMCREADY) == 0);
/* Configure TMC */
- bus_write_4(sc->res, TMC_MODE, MODE_CIRCULAR_BUFFER);
+ bus_write_4(sc->res[0], 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);
+ if (sc->scatter_gather)
+ reg |= AXICTL_SG_MODE;
+ /* reg |= AXICTL_AXCACHE_OS; */
+ bus_write_4(sc->res[0], 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[0], TMC_FFCR, reg);
- bus_write_4(sc->res, TMC_TRG, 8);
+ bus_write_4(sc->res[0], 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);
+ if (sc->scatter_gather) {
+ dprintf("%s: event->etr.pages %p\n", __func__,
+ event->etr.pages);
+ dprintf("%s: event->etr.npages %d\n", __func__,
+ event->etr.npages);
+ } else {
+ bus_write_4(sc->res[0], TMC_DBALO, event->etr.low);
+ bus_write_4(sc->res[0], TMC_DBAHI, event->etr.high);
+ bus_write_4(sc->res[0], TMC_RSZ, event->etr.bufsize / 4);
+ bus_write_4(sc->res[0], TMC_RRP, event->etr.low);
+ bus_write_4(sc->res[0], TMC_RWP, event->etr.low);
+ }
- reg = bus_read_4(sc->res, TMC_STS);
+ reg = bus_read_4(sc->res[0], TMC_STS);
reg &= ~STS_FULL;
- bus_write_4(sc->res, TMC_STS, reg);
+ bus_write_4(sc->res[0], TMC_STS, reg);
- tmc_start(dev);
+ return (0);
+}
+
+static vm_page_t *
+tmc_allocate_pgdir(struct tmc_softc *sc, vm_page_t *pages, int nentries,
+ int npt)
+{
+ vm_page_t *pt_dir;
+ vm_paddr_t paddr;
+ int sgtentry;
+ sgte_t *ptr;
+ uint32_t dirpg;
+ int curpg;
+ int type;
+ int error;
+ int i;
+
+ pt_dir = malloc(sizeof(struct vm_page *) * npt, M_DEVBUF,
+ M_WAITOK | M_ZERO);
+ error = tmc_alloc_pages(sc, pt_dir, npt);
+ if (error) {
+ printf("%s: could not allocate pages\n", __func__);
+ return (NULL);
+ }
+
+ sgtentry = 0;
+ curpg = 0;
+ ptr = (sgte_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(pt_dir[0]));
+ dirpg = 1;
+
+ for (i = 0; i < nentries - 1; i++) {
+ dprintf("entry %d dirpg %d\n", i, dirpg);
+
+ if (sgtentry == (SG_PT_ENTIRES_PER_PAGE - 1)) {
+ type = ETR_SG_ET_LINK;
+ paddr = VM_PAGE_TO_PHYS(pt_dir[dirpg]);
+ } else {
+ type = ETR_SG_ET_NORMAL;
+ paddr = VM_PAGE_TO_PHYS(pages[curpg]);
+
+#ifdef TMC_DEBUG
+ if ((i % 100) == 0)
+ dprintf("%s: entry (%d/%d) type %d dirpg %d "
+ "curpg %d paddr %lx\n", __func__, i,
+ nentries, type, dirpg, curpg, paddr);
+#endif
+
+ curpg++;
+ }
+
+ *ptr = ETR_SG_ENTRY(paddr, type);
+ cpu_dcache_wb_range((vm_pointer_t)ptr, sizeof(sgte_t));
+ ptr++;
+
+ /* Take next directory page. */
+ if (type == ETR_SG_ET_LINK) {
+ ptr = (sgte_t *)PHYS_TO_DMAP(
+ VM_PAGE_TO_PHYS(pt_dir[dirpg]));
+ dirpg++;
+ }
+
+ sgtentry = (sgtentry + 1) % SG_PT_ENTIRES_PER_PAGE;
+ }
+
+ /* Last entry. */
+ paddr = VM_PAGE_TO_PHYS(pages[curpg]);
+ *ptr = ETR_SG_ENTRY(paddr, ETR_SG_ET_LAST);
+ cpu_dcache_wb_range((vm_pointer_t)ptr, sizeof(sgte_t));
+
+ return (pt_dir);
+}
+
+static int
+tmc_configure(device_t dev, struct coresight_event *event)
+{
+ struct tmc_softc *sc;
+ vm_page_t *pt_dir;
+ vm_page_t *pages;
+ uint64_t pbase;
+ uint32_t reg;
+ int nentries;
+ int nlinks;
+ int npages;
+ int npt;
+
+ sc = device_get_softc(dev);
+
+ reg = bus_read_4(sc->res[0], TMC_DEVID);
+ if ((reg & DEVID_CONFIGTYPE_M) != DEVID_CONFIGTYPE_ETR)
+ return (0);
+
+ if (!sc->scatter_gather)
+ return (0);
+
+ npages = event->etr.npages;
+ pages = event->etr.pages;
+
+ if (npages == 0 || pages == NULL)
+ return (EINVAL);
+
+ nlinks = npages / (SG_PT_ENTIRES_PER_PAGE - 1);
+ if (nlinks && ((npages % (SG_PT_ENTIRES_PER_PAGE - 1)) < 2))
+ nlinks--;
+ nentries = nlinks + npages;
+
+ npt = howmany(nentries, SG_PT_ENTIRES_PER_PAGE);
+
+ dprintf("%s: nentries %d, npt %d\n", __func__, nentries, npt);
+
+ pt_dir = tmc_allocate_pgdir(sc, pages, nentries, npt);
+ if (pt_dir == NULL)
+ return (ENOMEM);
+
+#ifdef TMC_DEBUG
+ ptr = (sgte_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(pt_dir[0]));
+ for (i = 0; i < nentries; i++)
+ dprintf("%s: entry %x\n", __func__, *ptr++);
+#endif
+
+ dprintf("%s: event->etr.pages %p\n", __func__, event->etr.pages);
+ dprintf("%s: event->etr.npages %d\n", __func__, event->etr.npages);
+
+ pbase = (uint64_t)VM_PAGE_TO_PHYS(pt_dir[0]);
+
+ dprintf("%s: pbase %lx\n", __func__, pbase);
+
+ bus_write_4(sc->res[0], TMC_DBALO, pbase & 0xffffffff);
+ bus_write_4(sc->res[0], TMC_DBAHI, pbase >> 32);
+ bus_write_4(sc->res[0], TMC_RSZ, (event->etr.npages * 4096) / 4);
return (0);
}
@@ -193,12 +425,12 @@
sc = device_get_softc(dev);
/* Unlock Coresight */
- bus_write_4(sc->res, CORESIGHT_LAR, CORESIGHT_UNLOCK);
+ bus_write_4(sc->res[0], CORESIGHT_LAR, CORESIGHT_UNLOCK);
/* Unlock TMC */
- bus_write_4(sc->res, TMC_LAR, CORESIGHT_UNLOCK);
+ bus_write_4(sc->res[0], TMC_LAR, CORESIGHT_UNLOCK);
- reg = bus_read_4(sc->res, TMC_DEVID);
+ reg = bus_read_4(sc->res[0], TMC_DEVID);
reg &= DEVID_CONFIGTYPE_M;
switch (reg) {
case DEVID_CONFIGTYPE_ETR:
@@ -222,7 +454,7 @@
}
static int
-tmc_enable(device_t dev, struct endpoint *endp,
+tmc_start_event(device_t dev, struct endpoint *endp,
struct coresight_event *event)
{
struct tmc_softc *sc;
@@ -241,22 +473,17 @@
* 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);
- }
+ nev = atomic_fetchadd_int(&sc->nev, 1);
+ if (nev == 0) {
+ tmc_configure_etr(dev, endp, event);
+ tmc_start(dev);
}
return (0);
}
static void
-tmc_disable(device_t dev, struct endpoint *endp,
+tmc_stop_event(device_t dev, struct endpoint *endp,
struct coresight_event *event)
{
struct tmc_softc *sc;
@@ -270,43 +497,54 @@
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;
- }
- }
+ nev = atomic_fetchadd_int(&sc->nev, -1);
+ if (nev == 1)
+ tmc_stop(dev);
+}
+
+static void
+tmc_intr(void *arg)
+{
+
+ /* TODO */
+
+ panic("unhandled interrupt");
}
static int
-tmc_read(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+tmc_read(device_t dev, struct endpoint *endp, struct coresight_event *event)
{
struct tmc_softc *sc;
- uint32_t cur_ptr;
+ vm_page_t page;
+ bool found;
+ uint64_t lo, hi;
+ uint64_t ptr;
+ int i;
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);
+ lo = bus_read_4(sc->res[0], TMC_RWP);
+ hi = bus_read_4(sc->res[0], TMC_RWPHI);
+ ptr = lo | (hi << 32);
- 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);
+ page = PHYS_TO_VM_PAGE(ptr);
+
+ found = false;
+
+ for (i = 0; i < event->etr.npages; i++) {
+ if (event->etr.pages[i] == page) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ event->etr.curpage = i;
+ event->etr.curpage_offset = ptr & 0xfff;
+ dprintf("CUR_PTR %lx, page %d of %d, offset %ld\n",
+ ptr, i, event->etr.npages, event->etr.curpage_offset);
}
return (0);
@@ -317,18 +555,36 @@
{
struct coresight_desc desc;
struct tmc_softc *sc;
+ uint32_t reg;
sc = device_get_softc(dev);
sc->dev = dev;
- if (bus_alloc_resources(dev, tmc_spec, &sc->res) != 0) {
+ if (bus_alloc_resources(dev, tmc_spec, sc->res) != 0) {
device_printf(dev, "cannot allocate resources for device\n");
return (ENXIO);
}
+ if (sc->res[1] != NULL) {
+ if (bus_setup_intr(dev, sc->res[1],
+ INTR_TYPE_MISC | INTR_MPSAFE, NULL, tmc_intr, sc,
+ &sc->intrhand)) {
+ bus_release_resources(dev, tmc_spec, sc->res);
+ device_printf(dev, "cannot setup interrupt handler\n");
+ return (ENXIO);
+ }
+ }
+
desc.pdata = sc->pdata;
desc.dev = dev;
- desc.dev_type = CORESIGHT_TMC;
+
+ reg = bus_read_4(sc->res[0], TMC_DEVID);
+ reg &= DEVID_CONFIGTYPE_M;
+ if (reg == DEVID_CONFIGTYPE_ETR)
+ desc.dev_type = CORESIGHT_TMC_ETR;
+ else
+ desc.dev_type = CORESIGHT_TMC_ETF;
+
coresight_register(&desc);
return (0);
@@ -340,8 +596,10 @@
/* Coresight interface */
DEVMETHOD(coresight_init, tmc_init),
- DEVMETHOD(coresight_enable, tmc_enable),
- DEVMETHOD(coresight_disable, tmc_disable),
+ DEVMETHOD(coresight_configure, tmc_configure),
+ DEVMETHOD(coresight_start, tmc_start_event),
+ DEVMETHOD(coresight_stop, tmc_stop_event),
+ DEVMETHOD(coresight_dump, tmc_dump),
DEVMETHOD(coresight_read, tmc_read),
DEVMETHOD_END
};
Index: sys/arm64/coresight/coresight_tmc_fdt.c
===================================================================
--- sys/arm64/coresight/coresight_tmc_fdt.c
+++ sys/arm64/coresight/coresight_tmc_fdt.c
@@ -71,10 +71,20 @@
tmc_fdt_attach(device_t dev)
{
struct tmc_softc *sc;
+ phandle_t node;
+ ssize_t len;
sc = device_get_softc(dev);
sc->pdata = coresight_fdt_get_platform_data(dev);
+ node = ofw_bus_get_node(dev);
+
+ len = OF_getproplen(node, "arm,scatter-gather");
+ if (len >= 0)
+ sc->scatter_gather = true;
+ else
+ sc->scatter_gather = false;
+
return (tmc_attach(dev));
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jan 27, 6:09 PM (1 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16203118
Default Alt Text
D40477.id123010.diff (34 KB)
Attached To
Mode
D40477: HWT: ARM CoreSight support
Attached
Detach File
Event Timeline
Log In to Comment