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
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -48,6 +48,8 @@
#include
#endif
+#include
+
#define CORESIGHT_ITCTRL 0xf00
#define CORESIGHT_CLAIMSET 0xfa0
#define CORESIGHT_CLAIMCLR 0xfa4
@@ -60,7 +62,8 @@
enum cs_dev_type {
CORESIGHT_ETMV4,
- CORESIGHT_TMC,
+ CORESIGHT_TMC_ETF,
+ CORESIGHT_TMC_ETR,
CORESIGHT_DYNAMIC_REPLICATOR,
CORESIGHT_FUNNEL,
CORESIGHT_CPU_DEBUG,
@@ -92,7 +95,7 @@
boolean_t input;
int reg;
struct coresight_device *cs_dev;
- LIST_ENTRY(endpoint) endplink;
+ TAILQ_ENTRY(endpoint) endplink;
};
struct coresight_platform_data {
@@ -119,19 +122,20 @@
};
struct etr_state {
- boolean_t started;
- uint32_t cycle;
- uint32_t offset;
uint32_t low;
uint32_t high;
uint32_t bufsize;
- uint32_t flags;
-#define ETR_FLAG_ALLOCATE (1 << 0)
-#define ETR_FLAG_RELEASE (1 << 1)
+ vm_page_t *pages;
+ int npages;
+ int curpage;
+ vm_offset_t curpage_offset;
+
+ vm_page_t *pt_dir;
+ int npt;
};
-struct coresight_event {
- LIST_HEAD(, endpoint) endplist;
+struct coresight_pipeline {
+ TAILQ_HEAD(endplistname, endpoint) endplist;
uint64_t addr[ETM_N_COMPRATOR];
uint32_t naddr;
@@ -149,16 +153,36 @@
uint8_t excp_level;
};
-static MALLOC_DEFINE(M_CORESIGHT, "coresight", "ARM Coresight");
+MALLOC_DECLARE(M_CORESIGHT);
struct coresight_platform_data *coresight_fdt_get_platform_data(device_t dev);
+void coresight_fdt_release_platform_data(struct coresight_platform_data *pdata);
+
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 endpoint *
+ coresight_get_output_endpoint(struct coresight_platform_data *pdata);
+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_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);
+
+int coresight_init_pipeline(struct coresight_pipeline *pipeline, int cpu);
+void coresight_deinit_pipeline(struct coresight_pipeline *pipeline);
+
+int coresight_setup(struct coresight_pipeline *pipeline);
+int coresight_configure(struct coresight_pipeline *pipeline,
+ struct hwt_context *ctx);
+void coresight_deconfigure(struct coresight_pipeline *pipeline);
+
+int coresight_start(struct coresight_pipeline *pipeline);
+void coresight_stop(struct coresight_pipeline *pipeline);
+
+void coresight_enable(struct coresight_pipeline *pipeline);
+void coresight_disable(struct coresight_pipeline *pipeline);
+
+int coresight_read(struct coresight_pipeline *pipeline);
+void coresight_dump(struct coresight_pipeline *pipeline);
+
+int coresight_unregister(device_t dev);
#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
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -39,17 +39,278 @@
#include
#include
#include
+#include
+#include
#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define CORESIGHT_DEBUG
+#undef CORESIGHT_DEBUG
+
+#ifdef CORESIGHT_DEBUG
+#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__)
+#else
+#define dprintf(fmt, ...)
+#endif
+
+MALLOC_DEFINE(M_CORESIGHT, "coresight", "ARM Coresight");
+
static struct mtx cs_mtx;
struct coresight_device_list cs_devs;
+static struct hwt_backend_ops coresight_ops;
+
+static struct hwt_backend backend = {
+ .ops = &coresight_ops,
+ .name = "coresight",
+};
+static struct coresight_pipeline cs_pipeline[MAXCPU];
+
+/*
+ * https://people.freebsd.org/~br/coresight_diagram.png
+ */
+
+static int
+coresight_backend_init_thread(struct hwt_context *ctx)
+{
+ struct coresight_pipeline *pipeline;
+ struct hwt_thread *thr;
+ struct hwt_vm *vm;
+ int cpu_id;
+ int error;
+
+ /*
+ * 1. Use buffer from the first thread as Funnel merges traces from
+ * all CPUs to a single place.
+ *
+ * 2. Ctx was just allocated, so the lock is not really needed.
+ */
+ HWT_CTX_LOCK(ctx);
+ thr = hwt_thread_first(ctx);
+ HWT_CTX_UNLOCK(ctx);
+
+ vm = thr->vm;
+
+ for (cpu_id = 0; cpu_id < mp_ncpus; cpu_id++) {
+ pipeline = &cs_pipeline[cpu_id];
+ memset(pipeline, 0, sizeof(struct coresight_pipeline));
+ pipeline->excp_level = 0;
+ pipeline->src = CORESIGHT_ETMV4;
+ pipeline->sink = CORESIGHT_TMC_ETR;
+
+ error = coresight_init_pipeline(pipeline, cpu_id);
+ if (error)
+ return (error);
+ }
+
+ /*
+ * These methods are TMC-ETR only. We have single
+ * TMC-ETR per system, so call them on first pipeline
+ * only. The request will reach destination.
+ */
+ pipeline = &cs_pipeline[0];
+ pipeline->etr.low = 0;
+ pipeline->etr.high = 0;
+ pipeline->etr.pages = vm->pages;
+ pipeline->etr.npages = vm->npages;
+ pipeline->etr.bufsize = vm->npages * PAGE_SIZE;
+
+ error = coresight_setup(pipeline);
+ if (error)
+ return (error);
+
+ error = coresight_start(pipeline);
+ if (error)
+ return (error);
+
+ return (0);
+}
+
+static int
+coresight_backend_init_cpu(struct hwt_context *ctx)
+{
+ struct coresight_pipeline *pipeline;
+ struct hwt_vm *vm;
+ int error;
+ int cpu_id;
+
+ CPU_FOREACH(cpu_id) {
+ pipeline = &cs_pipeline[cpu_id];
+ memset(pipeline, 0, sizeof(struct coresight_pipeline));
+
+ pipeline->excp_level = 1;
+ pipeline->src = CORESIGHT_ETMV4;
+ pipeline->sink = CORESIGHT_TMC_ETR;
+
+ error = coresight_init_pipeline(pipeline, cpu_id);
+ if (error)
+ return (error);
+ }
+
+ /*
+ * The following is TMC (ETR) only, so pick vm from the first CPU.
+ */
+ pipeline = &cs_pipeline[0];
+
+ HWT_CTX_LOCK(ctx);
+ vm = hwt_cpu_first(ctx)->vm;
+ HWT_CTX_UNLOCK(ctx);
+
+ /* TMC(ETR) configuration. */
+ pipeline->etr.low = 0;
+ pipeline->etr.high = 0;
+ pipeline->etr.pages = vm->pages;
+ pipeline->etr.npages = vm->npages;
+ pipeline->etr.bufsize = vm->npages * PAGE_SIZE;
+
+ error = coresight_setup(pipeline);
+ if (error)
+ return (error);
+
+ error = coresight_start(pipeline);
+ if (error)
+ return (error);
+
+ return (0);
+}
+
+static int
+coresight_backend_init(struct hwt_context *ctx)
+{
+ int error;
+
+ if (ctx->mode == HWT_MODE_THREAD)
+ error = coresight_backend_init_thread(ctx);
+ else
+ error = coresight_backend_init_cpu(ctx);
+
+ return (error);
+}
+
+static void
+coresight_backend_deinit(void)
+{
+ struct coresight_pipeline *pipeline;
+ int cpu_id;
+
+ for (cpu_id = 0; cpu_id < mp_ncpus; cpu_id++) {
+ pipeline = &cs_pipeline[cpu_id];
+ coresight_disable(pipeline);
+ }
+
+ /* Now as TMC-ETF buffers flushed, stop TMC-ETR. */
+ pipeline = &cs_pipeline[0];
+ coresight_stop(pipeline);
+
+ for (cpu_id = 0; cpu_id < mp_ncpus; cpu_id++) {
+ pipeline = &cs_pipeline[cpu_id];
+ coresight_deinit_pipeline(pipeline);
+ }
+}
+
+static int
+coresight_backend_configure(struct hwt_context *ctx, int cpu_id, int session_id)
+{
+ struct coresight_pipeline *pipeline;
+ int error;
+
+ pipeline = &cs_pipeline[cpu_id];
+
+ /*
+ * OpenCSD needs a trace ID to distinguish trace sessions
+ * as they are merged to a single buffer by using funnel
+ * device.
+ *
+ * etmv4 session_id can't be 0.
+ */
+ pipeline->etm.trace_id = session_id + 1;
+
+ error = coresight_configure(pipeline, ctx);
+
+ return (error);
+}
+
+static void
+coresight_backend_enable(int cpu_id)
+{
+ struct coresight_pipeline *pipeline;
+
+ pipeline = &cs_pipeline[cpu_id];
+
+ coresight_enable(pipeline);
+}
+
+static void
+coresight_backend_disable(int cpu_id)
+{
+ struct coresight_pipeline *pipeline;
+
+ pipeline = &cs_pipeline[cpu_id];
+
+ coresight_disable(pipeline);
+}
+
+static int
+coresight_backend_read(int cpu_id, int *curpage, vm_offset_t *curpage_offset)
+{
+ struct coresight_pipeline *pipeline;
+ int error;
+
+ /*
+ * coresight_read() is TMC(ETR) only method. Also, we have a single
+ * TMC(ETR) per system configured from pipeline 0. So read data from
+ * pipeline 0.
+ */
+
+ pipeline = &cs_pipeline[0];
+
+ KASSERT(pipeline != NULL, ("No pipeline found"));
+
+ error = coresight_read(pipeline);
+ if (error == 0) {
+ *curpage = pipeline->etr.curpage;
+ *curpage_offset = pipeline->etr.curpage_offset;
+ }
+
+ return (error);
+}
+
+static void
+coresight_backend_dump(int cpu_id)
+{
+ struct coresight_pipeline *pipeline;
+
+ pipeline = &cs_pipeline[cpu_id];
+
+ coresight_dump(pipeline);
+}
+
+static struct hwt_backend_ops coresight_ops = {
+ .hwt_backend_init = coresight_backend_init,
+ .hwt_backend_deinit = coresight_backend_deinit,
+
+ .hwt_backend_configure = coresight_backend_configure,
+
+ .hwt_backend_enable = coresight_backend_enable,
+ .hwt_backend_disable = coresight_backend_disable,
+
+ .hwt_backend_read = coresight_backend_read,
+ .hwt_backend_dump = coresight_backend_dump,
+};
int
coresight_register(struct coresight_desc *desc)
{
struct coresight_device *cs_dev;
+ int error;
cs_dev = malloc(sizeof(struct coresight_device),
M_CORESIGHT, M_WAITOK | M_ZERO);
@@ -57,6 +318,14 @@
cs_dev->pdata = desc->pdata;
cs_dev->dev_type = desc->dev_type;
+ if (desc->dev_type == CORESIGHT_TMC_ETR) {
+ error = hwt_backend_register(&backend);
+ if (error != 0) {
+ free(cs_dev, M_CORESIGHT);
+ return (error);
+ }
+ }
+
mtx_lock(&cs_mtx);
TAILQ_INSERT_TAIL(&cs_devs, cs_dev, link);
mtx_unlock(&cs_mtx);
@@ -64,6 +333,27 @@
return (0);
}
+int
+coresight_unregister(device_t dev)
+{
+ struct coresight_device *cs_dev, *tmp;
+
+ mtx_lock(&cs_mtx);
+ TAILQ_FOREACH_SAFE(cs_dev, &cs_devs, link, tmp) {
+ if (cs_dev->dev == dev) {
+ TAILQ_REMOVE(&cs_devs, cs_dev, link);
+ mtx_unlock(&cs_mtx);
+ if (cs_dev->dev_type == CORESIGHT_TMC_ETR)
+ hwt_backend_unregister(&backend);
+ free(cs_dev, M_CORESIGHT);
+ return (0);
+ }
+ }
+ mtx_unlock(&cs_mtx);
+
+ return (ENOENT);
+}
+
struct endpoint *
coresight_get_output_endpoint(struct coresight_platform_data *pdata)
{
@@ -81,7 +371,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 +385,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 +398,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
@@ -115,12 +414,31 @@
return (NULL);
}
-static void
-coresight_init(void)
+static int
+coresight_modevent(module_t mod, int type, void *data)
{
- mtx_init(&cs_mtx, "ARM Coresight", NULL, MTX_DEF);
- TAILQ_INIT(&cs_devs);
+ switch (type) {
+ case MOD_LOAD:
+ mtx_init(&cs_mtx, "ARM Coresight", NULL, MTX_DEF);
+ TAILQ_INIT(&cs_devs);
+ break;
+ case MOD_UNLOAD:
+ mtx_destroy(&cs_mtx);
+ break;
+ default:
+ break;
+ }
+
+ return (0);
}
-
-SYSINIT(coresight, SI_SUB_DRIVERS, SI_ORDER_FIRST, coresight_init, NULL);
+
+static moduledata_t coresight_mod = {
+ "coresight",
+ coresight_modevent,
+ NULL
+};
+
+DECLARE_MODULE(coresight, coresight_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
+MODULE_DEPEND(coresight, hwt, 1, 1, 1);
+MODULE_VERSION(coresight, 1);
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
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -47,22 +47,27 @@
static struct coresight_device *
coresight_next_device(struct coresight_device *cs_dev,
- struct coresight_event *event)
+ struct coresight_pipeline *pipeline)
{
struct coresight_device *out;
- struct endpoint *out_endp;
+ struct endpoint *out_endp, *src_endp;
struct endpoint *endp;
TAILQ_FOREACH(endp, &cs_dev->pdata->endpoints, link) {
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)) {
+ if (TAILQ_EMPTY(&pipeline->endplist)) {
+
/* Add source device */
- endp->cs_dev = cs_dev;
- LIST_INSERT_HEAD(&event->endplist, endp,
+ src_endp = malloc(sizeof(struct endpoint),
+ M_CORESIGHT, M_WAITOK | M_ZERO);
+ memcpy(src_endp, endp, sizeof(struct endpoint));
+
+ src_endp->cs_dev = cs_dev;
+ TAILQ_INSERT_TAIL(&pipeline->endplist, src_endp,
endplink);
}
@@ -71,7 +76,8 @@
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);
+ TAILQ_INSERT_TAIL(&pipeline->endplist, out_endp,
+ endplink);
return (out);
}
@@ -81,30 +87,31 @@
}
static int
-coresight_build_list(struct coresight_device *cs_dev,
- struct coresight_event *event)
+coresight_build_pipeline(struct coresight_device *cs_dev,
+ struct coresight_pipeline *pipeline)
{
struct coresight_device *out;
out = cs_dev;
while (out != NULL)
- out = coresight_next_device(out, event);
+ out = coresight_next_device(out, pipeline);
return (0);
}
int
-coresight_init_event(int cpu, struct coresight_event *event)
+coresight_init_pipeline(struct coresight_pipeline *pipeline, int cpu)
{
struct coresight_device *cs_dev;
struct endpoint *endp;
+ int error;
/* Start building path from source device */
TAILQ_FOREACH(cs_dev, &cs_devs, link) {
- if (cs_dev->dev_type == event->src &&
+ if (cs_dev->dev_type == pipeline->src &&
cs_dev->pdata->cpu == cpu) {
- LIST_INIT(&event->endplist);
- coresight_build_list(cs_dev, event);
+ TAILQ_INIT(&pipeline->endplist);
+ coresight_build_pipeline(cs_dev, pipeline);
break;
}
}
@@ -112,48 +119,153 @@
/* Ensure Coresight is initialized for the CPU */
TAILQ_FOREACH(cs_dev, &cs_devs, link) {
if (cs_dev->dev_type == CORESIGHT_CPU_DEBUG &&
- cs_dev->pdata->cpu == cpu)
- CORESIGHT_INIT(cs_dev->dev);
+ cs_dev->pdata->cpu == cpu) {
+ error = CORESIGHT_INIT(cs_dev->dev);
+ if (error != ENXIO && error != 0)
+ return (error);
+ }
}
/* Init all devices in the path */
- LIST_FOREACH(endp, &event->endplist, endplink) {
+ TAILQ_FOREACH(endp, &pipeline->endplist, endplink) {
cs_dev = endp->cs_dev;
- CORESIGHT_INIT(cs_dev->dev);
+ error = CORESIGHT_INIT(cs_dev->dev);
+ if (error != ENXIO && error != 0)
+ return (error);
}
return (0);
}
void
-coresight_enable(int cpu, struct coresight_event *event)
+coresight_deinit_pipeline(struct coresight_pipeline *pipeline)
+{
+ struct coresight_device *cs_dev;
+ struct endpoint *endp, *tmp;
+
+ TAILQ_FOREACH_SAFE(endp, &pipeline->endplist, endplink, tmp) {
+ cs_dev = endp->cs_dev;
+ CORESIGHT_DEINIT(cs_dev->dev);
+
+ TAILQ_REMOVE(&pipeline->endplist, endp, endplink);
+ free(endp, M_CORESIGHT);
+ }
+}
+
+int
+coresight_setup(struct coresight_pipeline *pipeline)
{
struct coresight_device *cs_dev;
struct endpoint *endp;
+ int error;
- LIST_FOREACH(endp, &event->endplist, endplink) {
+ TAILQ_FOREACH(endp, &pipeline->endplist, endplink) {
cs_dev = endp->cs_dev;
- CORESIGHT_ENABLE(cs_dev->dev, endp, event);
+ error = CORESIGHT_SETUP(cs_dev->dev, endp, pipeline);
+ if (error != ENXIO && error != 0)
+ return (error);
+ }
+
+ return (0);
+}
+
+int
+coresight_configure(struct coresight_pipeline *pipeline,
+ struct hwt_context *ctx)
+{
+ struct coresight_device *cs_dev;
+ struct endpoint *endp;
+ int error;
+
+ TAILQ_FOREACH(endp, &pipeline->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ error = CORESIGHT_CONFIGURE(cs_dev->dev, endp, pipeline, ctx);
+ if (error != ENXIO && error != 0)
+ return (error);
+ }
+
+ return (0);
+}
+
+int
+coresight_start(struct coresight_pipeline *pipeline)
+{
+ struct coresight_device *cs_dev;
+ struct endpoint *endp;
+ int error;
+
+ TAILQ_FOREACH_REVERSE(endp, &pipeline->endplist, endplistname,
+ endplink) {
+ cs_dev = endp->cs_dev;
+ error = CORESIGHT_START(cs_dev->dev, endp, pipeline);
+ if (error != ENXIO && error != 0)
+ return (error);
+ }
+
+ return (0);
+}
+
+void
+coresight_stop(struct coresight_pipeline *pipeline)
+{
+ struct coresight_device *cs_dev;
+ struct endpoint *endp;
+
+ TAILQ_FOREACH(endp, &pipeline->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ CORESIGHT_STOP(cs_dev->dev, endp, pipeline);
+ }
+}
+
+void
+coresight_enable(struct coresight_pipeline *pipeline)
+{
+ struct coresight_device *cs_dev;
+ struct endpoint *endp;
+
+ TAILQ_FOREACH(endp, &pipeline->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ CORESIGHT_ENABLE(cs_dev->dev, endp, pipeline);
}
}
void
-coresight_disable(int cpu, struct coresight_event *event)
+coresight_disable(struct coresight_pipeline *pipeline)
{
struct coresight_device *cs_dev;
struct endpoint *endp;
- LIST_FOREACH(endp, &event->endplist, endplink) {
+ TAILQ_FOREACH(endp, &pipeline->endplist, endplink) {
cs_dev = endp->cs_dev;
- CORESIGHT_DISABLE(cs_dev->dev, endp, event);
+ CORESIGHT_DISABLE(cs_dev->dev, endp, pipeline);
}
}
void
-coresight_read(int cpu, struct coresight_event *event)
+coresight_dump(struct coresight_pipeline *pipeline)
{
+ struct coresight_device *cs_dev;
struct endpoint *endp;
- LIST_FOREACH(endp, &event->endplist, endplink)
- CORESIGHT_READ(endp->cs_dev->dev, endp, event);
+ TAILQ_FOREACH(endp, &pipeline->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ CORESIGHT_DUMP(cs_dev->dev);
+ }
+}
+
+int
+coresight_read(struct coresight_pipeline *pipeline)
+{
+ struct coresight_device *cs_dev;
+ struct endpoint *endp;
+ int error;
+
+ TAILQ_FOREACH(endp, &pipeline->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ error = CORESIGHT_READ(cs_dev->dev, endp, pipeline);
+ if (error != ENXIO && error != 0)
+ return (error);
+ }
+
+ return (0);
}
Index: sys/arm64/coresight/coresight_cpu_debug.c
===================================================================
--- sys/arm64/coresight/coresight_cpu_debug.c
+++ sys/arm64/coresight/coresight_cpu_debug.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -79,6 +79,7 @@
{
struct debug_softc *sc;
uint32_t reg;
+ int timeout;
sc = device_get_softc(dev);
@@ -97,9 +98,14 @@
reg |= EDPRCR_COREPURQ;
bus_write_4(sc->res, EDPRCR, reg);
+ timeout = 10000;
+
do {
reg = bus_read_4(sc->res, EDPRSR);
- } while ((reg & EDPRCR_CORENPDRQ) == 0);
+ } while ((reg & EDPRCR_CORENPDRQ) == 0 && timeout--);
+
+ if (timeout <= 0)
+ return (EINTEGRITY);
return (0);
}
@@ -141,10 +147,32 @@
return (0);
}
+static int
+debug_detach(device_t dev)
+{
+ struct debug_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ error = coresight_unregister(dev);
+ if (error)
+ return (error);
+
+ coresight_fdt_release_platform_data(sc->pdata);
+
+ sc->pdata = NULL;
+
+ bus_release_resources(dev, debug_spec, &sc->res);
+
+ return (0);
+}
+
static device_method_t debug_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, debug_probe),
DEVMETHOD(device_attach, debug_attach),
+ DEVMETHOD(device_detach, debug_detach),
/* Coresight interface */
DEVMETHOD(coresight_init, debug_init),
@@ -152,11 +180,12 @@
};
static driver_t debug_driver = {
- "debug",
+ "coresight_cpu_debug",
debug_methods,
sizeof(struct debug_softc),
};
-EARLY_DRIVER_MODULE(debug, simplebus, debug_driver, 0, 0,
+EARLY_DRIVER_MODULE(coresight_cpu_debug, simplebus, debug_driver, 0, 0,
BUS_PASS_BUS + BUS_PASS_ORDER_LATE);
-MODULE_VERSION(debug, 1);
+MODULE_VERSION(coresight_cpu_debug, 1);
+MODULE_DEPEND(coresight_cpu_debug, coresight, 1, 1, 1);
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
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -172,7 +172,66 @@
#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);
+/* ETMv4 resources */
+#define ETM_MAX_NR_PE 8
+#define ETMv4_MAX_CNTR 4
+#define ETM_MAX_SEQ_STATES 4
+#define ETM_MAX_EXT_INP_SEL 4
+#define ETM_MAX_EXT_INP 256
+#define ETM_MAX_EXT_OUT 4
+#define ETM_MAX_SINGLE_ADDR_CMP 16
+#define ETM_MAX_ADDR_RANGE_CMP (ETM_MAX_SINGLE_ADDR_CMP / 2)
+#define ETM_MAX_DATA_VAL_CMP 8
+#define ETMv4_MAX_CTXID_CMP 8
+#define ETM_MAX_VMID_CMP 8
+#define ETM_MAX_PE_CMP 8
+#define ETM_MAX_RES_SEL 32
+#define ETM_MAX_SS_CMP 8
+
+struct etmv4_config {
+ uint32_t mode;
+ uint32_t pe_sel;
+ uint32_t cfg;
+ uint32_t eventctrl0;
+ uint32_t eventctrl1;
+ uint32_t stall_ctrl;
+ uint32_t ts_ctrl;
+ uint32_t syncfreq;
+ uint32_t ccctlr;
+ uint32_t bb_ctrl;
+ uint32_t vinst_ctrl;
+ uint32_t viiectlr;
+ uint32_t vissctlr;
+ uint32_t vipcssctlr;
+ uint8_t seq_idx;
+ uint32_t seq_ctrl[ETM_MAX_SEQ_STATES];
+ uint32_t seq_rst;
+ uint32_t seq_state;
+ uint8_t cntr_idx;
+ uint32_t cntrldvr[ETMv4_MAX_CNTR];
+ uint32_t cntr_ctrl[ETMv4_MAX_CNTR];
+ uint32_t cntr_val[ETMv4_MAX_CNTR];
+ uint8_t res_idx;
+ uint32_t res_ctrl[ETM_MAX_RES_SEL];
+ uint8_t ss_idx;
+ uint32_t ss_ctrl[ETM_MAX_SS_CMP];
+ uint32_t ss_status[ETM_MAX_SS_CMP];
+ uint32_t ss_pe_cmp[ETM_MAX_SS_CMP];
+ uint8_t addr_idx;
+ uint64_t addr_val[ETM_MAX_SINGLE_ADDR_CMP];
+ uint64_t addr_acc[ETM_MAX_SINGLE_ADDR_CMP];
+ uint8_t addr_type[ETM_MAX_SINGLE_ADDR_CMP];
+ uint8_t ctxid_idx;
+ uint64_t ctxid_pid[ETMv4_MAX_CTXID_CMP];
+ uint32_t ctxid_mask0;
+ uint32_t ctxid_mask1;
+ uint8_t vmid_idx;
+ uint64_t vmid_val[ETM_MAX_VMID_CMP];
+ uint32_t vmid_mask0;
+ uint32_t vmid_mask1;
+ uint32_t ext_inp;
+ uint8_t s_ex_level;
+};
struct etm_softc {
struct resource *res;
@@ -180,5 +239,8 @@
};
int etm_attach(device_t dev);
+int etm_detach(device_t dev);
+
+DECLARE_CLASS(coresight_etm4x_driver);
#endif /* !_ARM64_CORESIGHT_ETM4X_H_ */
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
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -43,6 +43,8 @@
#include
#include
+#include
+
#include "coresight_if.h"
#define ETM_DEBUG
@@ -69,12 +71,97 @@
};
static int
-etm_prepare(device_t dev, struct coresight_event *event)
+etm_configure_etmv4(device_t dev, struct etmv4_config *config)
+{
+ struct etm_softc *sc;
+ int cpu;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ cpu = PCPU_GET(cpuid);
+
+ dprintf("%s_%d\n", __func__, device_get_unit(dev));
+
+ bus_write_4(sc->res, TRCCONFIGR, config->cfg);
+ bus_write_4(sc->res, TRCEVENTCTL0R, config->eventctrl0);
+ bus_write_4(sc->res, TRCEVENTCTL1R, config->eventctrl1);
+ bus_write_4(sc->res, TRCSTALLCTLR, config->stall_ctrl);
+ bus_write_4(sc->res, TRCTSCTLR, config->ts_ctrl);
+ bus_write_4(sc->res, TRCSYNCPR, config->syncfreq);
+ bus_write_4(sc->res, TRCVICTLR, config->vinst_ctrl);
+ bus_write_4(sc->res, TRCPROCSELR, cpu); /* Not sure if this is needed.*/
+
+ /* Address-range filtering. */
+ for (i = 0; i < ETM_MAX_SINGLE_ADDR_CMP; i++) {
+ bus_write_8(sc->res, TRCACVR(i), config->addr_val[i]);
+ bus_write_8(sc->res, TRCACATR(i), config->addr_acc[i]);
+ }
+ bus_write_4(sc->res, TRCVIIECTLR, config->viiectlr);
+
+ bus_write_4(sc->res, TRCVDARCCTLR, 0);
+ bus_write_4(sc->res, TRCSSCSR(0), 0);
+ bus_write_4(sc->res, TRCVISSCTLR, config->vissctlr);
+ bus_write_4(sc->res, TRCVDCTLR, 0);
+ bus_write_4(sc->res, TRCVDSACCTLR, 0);
+
+#if 0
+ uint32_t mode;
+ uint32_t pe_sel;
+ uint32_t cfg;
+ uint32_t eventctrl0;
+ uint32_t eventctrl1;
+ uint32_t stall_ctrl;
+ uint32_t ts_ctrl;
+ uint32_t syncfreq;
+ uint32_t ccctlr;
+ uint32_t bb_ctrl;
+ uint32_t vinst_ctrl;
+ uint32_t viiectlr;
+ uint32_t vissctlr;
+ uint32_t vipcssctlr;
+ uint8_t seq_idx;
+ uint32_t seq_ctrl[ETM_MAX_SEQ_STATES];
+ uint32_t seq_rst;
+ uint32_t seq_state;
+ uint8_t cntr_idx;
+ uint32_t cntrldvr[ETMv4_MAX_CNTR];
+ uint32_t cntr_ctrl[ETMv4_MAX_CNTR];
+ uint32_t cntr_val[ETMv4_MAX_CNTR];
+ uint8_t res_idx;
+ uint32_t res_ctrl[ETM_MAX_RES_SEL];
+ uint8_t ss_idx;
+ uint32_t ss_ctrl[ETM_MAX_SS_CMP];
+ uint32_t ss_status[ETM_MAX_SS_CMP];
+ uint32_t ss_pe_cmp[ETM_MAX_SS_CMP];
+ uint8_t addr_idx;
+ uint64_t addr_val[ETM_MAX_SINGLE_ADDR_CMP];
+ uint64_t addr_acc[ETM_MAX_SINGLE_ADDR_CMP];
+ uint8_t addr_type[ETM_MAX_SINGLE_ADDR_CMP];
+ uint8_t ctxid_idx;
+ uint64_t ctxid_pid[ETMv4_MAX_CTXID_CMP];
+ uint32_t ctxid_mask0;
+ uint32_t ctxid_mask1;
+ uint8_t vmid_idx;
+ uint64_t vmid_val[ETM_MAX_VMID_CMP];
+ uint32_t vmid_mask0;
+ uint32_t vmid_mask1;
+ uint32_t ext_inp;
+ uint8_t s_ex_level;
+#endif
+
+ return (0);
+}
+
+static int
+etm_configure_etmv4_default(device_t dev, struct coresight_pipeline *pipeline)
{
struct etm_softc *sc;
uint32_t reg;
int i;
+ dprintf("%s%d\n", __func__, device_get_unit(dev));
+
sc = device_get_softc(dev);
/* Configure ETM */
@@ -88,6 +175,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);
@@ -99,8 +187,10 @@
/* Enable trace synchronization every 4096 bytes of trace. */
bus_write_4(sc->res, TRCSYNCPR, TRCSYNCPR_4K);
- /* Set a value for the trace ID */
- bus_write_4(sc->res, TRCTRACEIDR, event->etm.trace_id);
+ 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
@@ -117,27 +207,27 @@
/* The number of the single resource used to activate the event. */
reg |= (1 << EVENT_SEL_S);
- if (event->excp_level > 2)
+ if (pipeline->excp_level > 2)
return (-1);
reg |= TRCVICTLR_EXLEVEL_NS_M;
- reg &= ~TRCVICTLR_EXLEVEL_NS(event->excp_level);
+ reg &= ~TRCVICTLR_EXLEVEL_NS(pipeline->excp_level);
reg |= TRCVICTLR_EXLEVEL_S_M;
- reg &= ~TRCVICTLR_EXLEVEL_S(event->excp_level);
+ reg &= ~TRCVICTLR_EXLEVEL_S(pipeline->excp_level);
bus_write_4(sc->res, TRCVICTLR, reg);
- for (i = 0; i < event->naddr * 2; i++) {
+ for (i = 0; i < pipeline->naddr * 2; i++) {
dprintf("configure range %d, address %lx\n",
- i, event->addr[i]);
- bus_write_8(sc->res, TRCACVR(i), event->addr[i]);
+ i, pipeline->addr[i]);
+ bus_write_8(sc->res, TRCACVR(i), pipeline->addr[i]);
reg = 0;
/* Secure state */
reg |= TRCACATR_EXLEVEL_S_M;
- reg &= ~TRCACATR_EXLEVEL_S(event->excp_level);
+ reg &= ~TRCACATR_EXLEVEL_S(pipeline->excp_level);
/* Non-secure state */
reg |= TRCACATR_EXLEVEL_NS_M;
- reg &= ~TRCACATR_EXLEVEL_NS(event->excp_level);
+ reg &= ~TRCACATR_EXLEVEL_NS(pipeline->excp_level);
bus_write_4(sc->res, TRCACATR(i), reg);
/* Address range is included */
@@ -152,7 +242,7 @@
/* Clear the STATUS bit to zero */
bus_write_4(sc->res, TRCSSCSR(0), 0);
- if (event->naddr == 0) {
+ if (pipeline->naddr == 0) {
/* No address range filtering for ViewInst. */
bus_write_4(sc->res, TRCVIIECTLR, 0);
}
@@ -169,6 +259,26 @@
return (0);
}
+static int
+etm_configure(device_t dev, struct endpoint *endp,
+ struct coresight_pipeline *pipeline, struct hwt_context *ctx)
+{
+ struct etmv4_config *config;
+ int error;
+
+ dprintf("%s%d\n", __func__, device_get_unit(dev));
+
+ if (ctx->config &&
+ ctx->config_size == sizeof(struct etmv4_config) &&
+ ctx->config_version == 1) {
+ config = (struct etmv4_config *)ctx->config;
+ error = etm_configure_etmv4(dev, config);
+ } else
+ error = etm_configure_etmv4_default(dev, pipeline);
+
+ return (error);
+}
+
static int
etm_init(device_t dev)
{
@@ -177,6 +287,8 @@
sc = device_get_softc(dev);
+ dprintf("%s%d\n", __func__, device_get_unit(dev));
+
/* Unlocking Coresight */
bus_write_4(sc->res, CORESIGHT_LAR, CORESIGHT_UNLOCK);
@@ -193,40 +305,53 @@
static int
etm_enable(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+ struct coresight_pipeline *pipeline)
{
struct etm_softc *sc;
uint32_t reg;
sc = device_get_softc(dev);
- etm_prepare(dev, event);
+ dprintf("%s%d\n", __func__, device_get_unit(dev));
+
+ /* Set a value for the trace ID */
+ bus_write_4(sc->res, TRCTRACEIDR, pipeline->etm.trace_id);
/* Enable the trace unit */
- bus_write_4(sc->res, TRCPRGCTLR, TRCPRGCTLR_EN);
+ reg = bus_read_4(sc->res, TRCPRGCTLR);
+ reg |= TRCPRGCTLR_EN;
+ bus_write_4(sc->res, TRCPRGCTLR, reg);
/* Wait for an IDLE bit to be LOW */
+
+ /* TODO: add timeout */
do {
reg = bus_read_4(sc->res, TRCSTATR);
- } while ((reg & TRCSTATR_IDLE) == 1);
+ } while (reg & TRCSTATR_IDLE);
- if ((bus_read_4(sc->res, TRCPRGCTLR) & TRCPRGCTLR_EN) == 0)
- panic("etm is not enabled\n");
+ if ((bus_read_4(sc->res, TRCPRGCTLR) & TRCPRGCTLR_EN) == 0) {
+ printf("%s: etm is not enabled\n", __func__);
+ return (ENXIO);
+ }
return (0);
}
static void
etm_disable(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+ struct coresight_pipeline *pipeline)
{
struct etm_softc *sc;
uint32_t reg;
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);
+ reg = bus_read_4(sc->res, TRCPRGCTLR);
+ reg &= ~TRCPRGCTLR_EN;
+ bus_write_4(sc->res, TRCPRGCTLR, reg);
/* Wait for an IDLE bit */
do {
@@ -255,12 +380,31 @@
return (0);
}
+int
+etm_detach(device_t dev)
+{
+ struct etm_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ error = coresight_unregister(dev);
+ if (error)
+ return (error);
+
+ bus_release_resources(dev, etm_spec, &sc->res);
+
+ return (0);
+}
+
static device_method_t etm_methods[] = {
/* Coresight interface */
DEVMETHOD(coresight_init, etm_init),
+ DEVMETHOD(coresight_configure, etm_configure),
DEVMETHOD(coresight_enable, etm_enable),
DEVMETHOD(coresight_disable, etm_disable),
DEVMETHOD_END
};
-DEFINE_CLASS_0(etm, etm_driver, etm_methods, sizeof(struct etm_softc));
+DEFINE_CLASS_0(coresight_etm4x, coresight_etm4x_driver, etm_methods,
+ sizeof(struct etm_softc));
Index: sys/arm64/coresight/coresight_etm4x_fdt.c
===================================================================
--- sys/arm64/coresight/coresight_etm4x_fdt.c
+++ sys/arm64/coresight/coresight_etm4x_fdt.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -78,15 +78,32 @@
return (etm_attach(dev));
}
+static int
+etm_fdt_detach(device_t dev)
+{
+ struct etm_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ coresight_fdt_release_platform_data(sc->pdata);
+
+ sc->pdata = NULL;
+
+ return (etm_detach(dev));
+}
+
static device_method_t etm_fdt_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, etm_fdt_probe),
DEVMETHOD(device_attach, etm_fdt_attach),
+ DEVMETHOD(device_detach, etm_fdt_detach),
DEVMETHOD_END
};
-DEFINE_CLASS_1(etm, etm_fdt_driver, etm_fdt_methods,
- sizeof(struct etm_softc), etm_driver);
+DEFINE_CLASS_1(coresight_etm4x, coresight_etm4x_fdt_driver, etm_fdt_methods,
+ sizeof(struct etm_softc), coresight_etm4x_driver);
-EARLY_DRIVER_MODULE(etm, simplebus, etm_fdt_driver, 0, 0,
- BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(coresight_etm4x, simplebus, coresight_etm4x_fdt_driver,
+ 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+MODULE_DEPEND(coresight_etm4x, coresight, 1, 1, 1);
+MODULE_VERSION(coresight_etm4x, 1);
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
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -39,6 +39,7 @@
#include
#include
#include
+#include
#include
#include
@@ -47,10 +48,10 @@
#include
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,28 @@
}
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];
+ uint64_t mpidr;
+ 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) {
+ mpidr = cpu_reg[1];
+ mpidr |= ((uint64_t)cpu_reg[0] << 32);
+ for (i = 0; i < mp_ncpus; i++) {
+ pcpu = cpuid_to_pcpu[i];
+ if (pcpu->pc_mpidr == mpidr) {
+ pdata->cpu = pcpu->pc_cpuid;
+ return (0);
+ }
+ }
}
}
@@ -131,7 +135,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 +147,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",
@@ -151,3 +162,16 @@
return (pdata);
}
+
+void
+coresight_fdt_release_platform_data(struct coresight_platform_data *pdata)
+{
+ struct endpoint *endp, *tmp;
+
+ TAILQ_FOREACH_SAFE(endp, &pdata->endpoints, link, tmp) {
+ TAILQ_REMOVE(&pdata->endpoints, endp, link);
+ free(endp, M_CORESIGHT);
+ }
+
+ free(pdata, M_CORESIGHT);
+}
Index: sys/arm64/coresight/coresight_funnel.h
===================================================================
--- sys/arm64/coresight/coresight_funnel.h
+++ sys/arm64/coresight/coresight_funnel.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -67,7 +67,7 @@
#define HWTYPE_FUNNEL 1
#define HWTYPE_STATIC_FUNNEL 2
-DECLARE_CLASS(funnel_driver);
+DECLARE_CLASS(coresight_funnel_driver);
struct funnel_softc {
struct resource *res;
@@ -76,5 +76,6 @@
};
int funnel_attach(device_t dev);
+int funnel_detach(device_t dev);
#endif /* !_ARM64_CORESIGHT_CORESIGHT_FUNNEL_H_ */
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
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -76,8 +76,8 @@
}
static int
-funnel_enable(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+funnel_configure(device_t dev, struct endpoint *endp,
+ struct coresight_pipeline *pipeline, struct hwt_context *ctx)
{
struct funnel_softc *sc;
uint32_t reg;
@@ -96,8 +96,8 @@
}
static void
-funnel_disable(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+funnel_deconfigure(device_t dev, struct endpoint *endp,
+ struct coresight_pipeline *pipeline)
{
struct funnel_softc *sc;
uint32_t reg;
@@ -132,13 +132,30 @@
return (0);
}
+int
+funnel_detach(device_t dev)
+{
+ struct funnel_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ error = coresight_unregister(dev);
+ if (error)
+ return (error);
+
+ bus_release_resources(dev, funnel_spec, &sc->res);
+
+ return (0);
+}
+
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_configure, funnel_configure),
+ DEVMETHOD(coresight_deconfigure,funnel_deconfigure),
DEVMETHOD_END
};
-DEFINE_CLASS_0(funnel, funnel_driver, funnel_methods,
+DEFINE_CLASS_0(coresight_funnel, coresight_funnel_driver, funnel_methods,
sizeof(struct funnel_softc));
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
+ * Copyright (c) 2018-2023 Ruslan Bukin
* 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 }
};
@@ -90,15 +90,32 @@
return (funnel_attach(dev));
}
+static int
+funnel_fdt_detach(device_t dev)
+{
+ struct funnel_softc *sc;
+
+ sc = device_get_softc(dev);
+ coresight_fdt_release_platform_data(sc->pdata);
+
+ sc->pdata = NULL;
+
+ return (funnel_detach(dev));
+}
+
static device_method_t funnel_fdt_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, funnel_fdt_probe),
DEVMETHOD(device_attach, funnel_fdt_attach),
+ DEVMETHOD(device_detach, funnel_fdt_detach),
DEVMETHOD_END
};
-DEFINE_CLASS_1(funnel, funnel_fdt_driver, funnel_fdt_methods,
- sizeof(struct funnel_softc), funnel_driver);
+DEFINE_CLASS_1(coresight_funnel, coresight_funnel_fdt_driver,
+ funnel_fdt_methods, sizeof(struct funnel_softc),
+ coresight_funnel_driver);
-EARLY_DRIVER_MODULE(funnel, simplebus, funnel_fdt_driver, 0, 0,
- BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(coresight_funnel, simplebus, coresight_funnel_fdt_driver,
+ 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+MODULE_DEPEND(coresight_funnel, coresight, 1, 1, 1);
+MODULE_VERSION(coresight_funnel, 1);
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
+# Copyright (c) 2018-2023 Ruslan Bukin
# All rights reserved.
#
# This software was developed by SRI International and the University of
@@ -39,20 +39,59 @@
device_t dev;
};
+METHOD int deinit {
+ device_t dev;
+};
+
+METHOD int setup {
+ device_t dev;
+ struct endpoint *endp;
+ struct coresight_pipeline *pipeline;
+};
+
+METHOD int configure {
+ device_t dev;
+ struct endpoint *endp;
+ struct coresight_pipeline *pipeline;
+ struct hwt_context *ctx;
+};
+
+METHOD void deconfigure {
+ device_t dev;
+ struct endpoint *endp;
+ struct coresight_pipeline *pipeline;
+};
+
+METHOD int start {
+ device_t dev;
+ struct endpoint *endp;
+ struct coresight_pipeline *pipeline;
+};
+
+METHOD void stop {
+ device_t dev;
+ struct endpoint *endp;
+ struct coresight_pipeline *pipeline;
+}
+
METHOD int enable {
device_t dev;
struct endpoint *endp;
- struct coresight_event *event;
+ struct coresight_pipeline *pipeline;
};
METHOD void disable {
device_t dev;
struct endpoint *endp;
- struct coresight_event *event;
+ struct coresight_pipeline *pipeline;
+};
+
+METHOD void dump {
+ device_t dev;
};
METHOD int read {
device_t dev;
struct endpoint *endp;
- struct coresight_event *event;
+ struct coresight_pipeline *pipeline;
};
Index: sys/arm64/coresight/coresight_replicator.h
===================================================================
--- sys/arm64/coresight/coresight_replicator.h
+++ sys/arm64/coresight/coresight_replicator.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2020 Ruslan Bukin
+ * Copyright (c) 2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -36,7 +36,7 @@
#define REPLICATOR_IDFILTER0 0x00
#define REPLICATOR_IDFILTER1 0x04
-DECLARE_CLASS(replicator_driver);
+DECLARE_CLASS(coresight_replicator_driver);
struct replicator_softc {
struct resource *res;
@@ -44,5 +44,6 @@
};
int replicator_attach(device_t dev);
+int replicator_detach(device_t dev);
#endif /* !_ARM64_CORESIGHT_CORESIGHT_REPLICATOR_H_ */
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
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -64,8 +64,8 @@
}
static int
-replicator_enable(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+replicator_configure(device_t dev, struct endpoint *endp,
+ struct coresight_pipeline *pipeline, struct hwt_context *ctx)
{
struct replicator_softc *sc;
@@ -84,8 +84,8 @@
}
static void
-replicator_disable(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+replicator_deconfigure(device_t dev, struct endpoint *endp,
+ struct coresight_pipeline *pipeline)
{
struct replicator_softc *sc;
@@ -116,13 +116,30 @@
return (0);
}
+int
+replicator_detach(device_t dev)
+{
+ struct replicator_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ error = coresight_unregister(dev);
+ if (error)
+ return (error);
+
+ bus_release_resources(dev, replicator_spec, &sc->res);
+
+ return (0);
+}
+
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_configure, replicator_configure),
+ DEVMETHOD(coresight_deconfigure,replicator_deconfigure),
DEVMETHOD_END
};
-DEFINE_CLASS_0(replicator, replicator_driver, replicator_methods,
- sizeof(struct replicator_softc));
+DEFINE_CLASS_0(coresight_replicator, coresight_replicator_driver,
+ replicator_methods, sizeof(struct replicator_softc));
Index: sys/arm64/coresight/coresight_replicator_fdt.c
===================================================================
--- sys/arm64/coresight/coresight_replicator_fdt.c
+++ sys/arm64/coresight/coresight_replicator_fdt.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -78,15 +78,34 @@
return (replicator_attach(dev));
}
+static int
+replicator_fdt_detach(device_t dev)
+{
+ struct replicator_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ coresight_fdt_release_platform_data(sc->pdata);
+
+ sc->pdata = NULL;
+
+ return (replicator_detach(dev));
+}
+
static device_method_t replicator_fdt_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, replicator_fdt_probe),
DEVMETHOD(device_attach, replicator_fdt_attach),
+ DEVMETHOD(device_detach, replicator_fdt_detach),
DEVMETHOD_END
};
-DEFINE_CLASS_1(replicator, replicator_fdt_driver, replicator_fdt_methods,
- sizeof(struct replicator_softc), replicator_driver);
+DEFINE_CLASS_1(coresight_replicator, coresight_replicator_fdt_driver,
+ replicator_fdt_methods, sizeof(struct replicator_softc),
+ coresight_replicator_driver);
-EARLY_DRIVER_MODULE(replicator, simplebus, replicator_fdt_driver, 0, 0,
+EARLY_DRIVER_MODULE(coresight_replicator, simplebus,
+ coresight_replicator_fdt_driver, 0, 0,
BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+MODULE_DEPEND(coresight_replicator, coresight, 1, 1, 1);
+MODULE_VERSION(coresight_replicator, 1);
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
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -79,6 +79,7 @@
#define FFCR_FON_TRIG_EVT (1 << 5)
#define FFCR_FLUSH_MAN (1 << 6)
#define FFCR_TRIGON_TRIGIN (1 << 8)
+#define FFCR_STOP_ON_FLUSH (1 << 12)
#define TMC_PSCR 0x308 /* Periodic Synchronization Counter Register */
#define TMC_ITATBMDATA0 0xED0 /* Integration Test ATB Master Data Register 0 */
#define TMC_ITATBMCTR2 0xED4 /* Integration Test ATB Master Interface Control 2 Register */
@@ -116,22 +117,25 @@
#define TMC_COMPID2 0xFF8 /* Component ID2 Register */
#define TMC_COMPID3 0xFFC /* Component ID3 Register */
-DECLARE_CLASS(tmc_driver);
+DECLARE_CLASS(coresight_tmc_driver);
struct tmc_softc {
- struct resource *res;
+ struct resource *res[2];
device_t dev;
- uint64_t cycle;
struct coresight_platform_data *pdata;
uint32_t dev_type;
#define CORESIGHT_UNKNOWN 0
#define CORESIGHT_ETR 1
#define CORESIGHT_ETF 2
uint32_t nev;
- struct coresight_event *event;
boolean_t etf_configured;
+ boolean_t scatter_gather;
+ void *intrhand;
};
+typedef uint32_t sgte_t;
+
int tmc_attach(device_t dev);
+int tmc_detach(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
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -39,6 +39,15 @@
#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
#include
#include
@@ -46,140 +55,390 @@
#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 MALLOC_DEFINE(M_CORESIGHT_TMC, "coresight_tmc", "Coresight TMC");
+
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_start(device_t dev)
+tmc_wait_for_tmcready(struct tmc_softc *sc)
{
- struct tmc_softc *sc;
uint32_t reg;
+ int timeout;
- sc = device_get_softc(dev);
+ timeout = 10000;
- if (bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN)
- return (-1);
+ do {
+ reg = bus_read_4(sc->res[0], TMC_STS);
+ if (reg & STS_TMCREADY)
+ break;
+ } while (timeout--);
+
+ if (timeout <= 0) {
+ printf("%s: Error: TMC type %d is running\n", __func__,
+ sc->dev_type);
+ return (EINTEGRITY);
+ }
- /* Enable TMC */
- bus_write_4(sc->res, TMC_CTL, CTL_TRACECAPTEN);
- if ((bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN) == 0)
- panic("Not enabled\n");
+ return (0);
+}
- do {
- reg = bus_read_4(sc->res, TMC_STS);
- } while ((reg & STS_TMCREADY) == 1);
+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 ((bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN) == 0)
- panic("Not enabled\n");
+ 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 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);
+ if (sc->dev_type == CORESIGHT_ETF)
+ return;
+
+ 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_stop(device_t dev)
+tmc_configure_etf(device_t dev)
{
struct tmc_softc *sc;
uint32_t reg;
sc = device_get_softc(dev);
- reg = bus_read_4(sc->res, TMC_CTL);
- reg &= ~CTL_TRACECAPTEN;
- bus_write_4(sc->res, TMC_CTL, reg);
+ dprintf("%s%d\n", __func__, device_get_unit(dev));
- do {
- reg = bus_read_4(sc->res, TMC_STS);
- } while ((reg & STS_TMCREADY) == 1);
+ bus_write_4(sc->res[0], TMC_MODE, MODE_HW_FIFO);
+ reg = FFCR_EN_FMT | FFCR_EN_TI;
+ bus_write_4(sc->res[0], TMC_FFCR, reg);
return (0);
}
static int
-tmc_configure_etf(device_t dev)
+tmc_configure_etr(device_t dev, struct endpoint *endp,
+ struct coresight_pipeline *pipeline)
{
struct tmc_softc *sc;
uint32_t reg;
sc = device_get_softc(dev);
- do {
- reg = bus_read_4(sc->res, TMC_STS);
- } while ((reg & STS_TMCREADY) == 0);
+ dprintf("%s%d\n", __func__, device_get_unit(dev));
+
+ /* Configure TMC */
+ bus_write_4(sc->res[0], TMC_MODE, MODE_CIRCULAR_BUFFER);
+
+ reg = AXICTL_PROT_CTRL_BIT1;
+ reg |= AXICTL_WRBURSTLEN_16;
+ if (sc->scatter_gather)
+ reg |= AXICTL_SG_MODE;
+ /* reg |= AXICTL_AXCACHE_OS; */
+ bus_write_4(sc->res[0], TMC_AXICTL, reg);
- bus_write_4(sc->res, TMC_MODE, MODE_HW_FIFO);
- bus_write_4(sc->res, TMC_FFCR, FFCR_EN_FMT | FFCR_EN_TI);
+ reg = FFCR_EN_FMT | FFCR_EN_TI | FFCR_FON_FLIN |
+ FFCR_FON_TRIG_EVT | FFCR_TRIGON_TRIGIN;
+ bus_write_4(sc->res[0], TMC_FFCR, reg);
- tmc_start(dev);
+ bus_write_4(sc->res[0], TMC_TRG, 0x3ff);
- 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));
+ if (sc->scatter_gather) {
+ dprintf("%s: pipeline->etr.pages %p\n", __func__,
+ pipeline->etr.pages);
+ dprintf("%s: pipeline->etr.npages %d\n", __func__,
+ pipeline->etr.npages);
+ } else {
+ bus_write_4(sc->res[0], TMC_DBALO, pipeline->etr.low);
+ bus_write_4(sc->res[0], TMC_DBAHI, pipeline->etr.high);
+ bus_write_4(sc->res[0], TMC_RSZ, pipeline->etr.bufsize / 4);
+ bus_write_4(sc->res[0], TMC_RRP, pipeline->etr.low);
+ bus_write_4(sc->res[0], TMC_RWP, pipeline->etr.low);
+ }
+
+ reg = bus_read_4(sc->res[0], TMC_STS);
+ reg &= ~STS_FULL;
+ bus_write_4(sc->res[0], TMC_STS, reg);
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_CORESIGHT_TMC,
+ 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 void
+tmc_deallocate_pgdir(struct coresight_pipeline *pipeline)
+{
+ vm_page_t *pg_dir;
+ vm_page_t m;
+ int npages;
+ int i;
+
+ pg_dir = pipeline->etr.pt_dir;
+ npages = pipeline->etr.npt;
+
+ for (i = 0; i < npages; i++) {
+ m = pg_dir[i];
+ if (m == NULL)
+ break;
+
+ vm_page_lock(m);
+ m->oflags |= VPO_UNMANAGED;
+ m->flags &= ~PG_FICTITIOUS;
+ vm_page_unwire_noq(m);
+ vm_page_free(m);
+ vm_page_unlock(m);
+ }
+
+ free(pg_dir, M_CORESIGHT_TMC);
+}
+
static int
-tmc_configure_etr(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+tmc_setup(device_t dev, struct endpoint *endp,
+ struct coresight_pipeline *pipeline)
{
struct tmc_softc *sc;
- uint32_t reg;
+ vm_page_t *pt_dir;
+ vm_page_t *pages;
+ uint64_t pbase;
+ int nentries;
+ int nlinks;
+ int npages;
+ int npt;
+ int error;
sc = device_get_softc(dev);
+ if (sc->dev_type == CORESIGHT_ETF)
+ return (0);
- tmc_stop(dev);
+ if (!sc->scatter_gather)
+ return (0);
- do {
- reg = bus_read_4(sc->res, TMC_STS);
- } while ((reg & STS_TMCREADY) == 0);
+ error = tmc_wait_for_tmcready(sc);
+ if (error)
+ return (error);
- /* Configure TMC */
- bus_write_4(sc->res, TMC_MODE, MODE_CIRCULAR_BUFFER);
+ npages = pipeline->etr.npages;
+ pages = pipeline->etr.pages;
- reg = AXICTL_PROT_CTRL_BIT1;
- reg |= AXICTL_WRBURSTLEN_16;
+ if (npages == 0 || pages == NULL)
+ return (EINVAL);
- /*
- * SG operation is broken on DragonBoard 410c
- * reg |= AXICTL_SG_MODE;
- */
+ nlinks = npages / (SG_PT_ENTIRES_PER_PAGE - 1);
+ if (nlinks && ((npages % (SG_PT_ENTIRES_PER_PAGE - 1)) < 2))
+ nlinks--;
+ nentries = nlinks + npages;
- reg |= AXICTL_AXCACHE_OS;
- bus_write_4(sc->res, TMC_AXICTL, reg);
+ npt = howmany(nentries, SG_PT_ENTIRES_PER_PAGE);
- 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);
+ dprintf("%s: nentries %d, npt %d\n", __func__, nentries, npt);
- bus_write_4(sc->res, TMC_TRG, 8);
+ pt_dir = tmc_allocate_pgdir(sc, pages, nentries, npt);
+ if (pt_dir == NULL)
+ return (ENOMEM);
+ pipeline->etr.pt_dir = pt_dir;
+ pipeline->etr.npt = npt;
- 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);
+#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
- bus_write_4(sc->res, TMC_RRP, event->etr.low);
- bus_write_4(sc->res, TMC_RWP, event->etr.low);
+ dprintf("%s: pipeline->etr.pages %p\n", __func__, pipeline->etr.pages);
+ dprintf("%s: pipeline->etr.npages %d\n", __func__,
+ pipeline->etr.npages);
- reg = bus_read_4(sc->res, TMC_STS);
- reg &= ~STS_FULL;
- bus_write_4(sc->res, TMC_STS, reg);
+ pbase = (uint64_t)VM_PAGE_TO_PHYS(pt_dir[0]);
+
+ dprintf("%s: pbase %lx\n", __func__, pbase);
- tmc_start(dev);
+ 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, (pipeline->etr.npages * 4096) / 4);
+
+ return (0);
+}
+
+static int
+tmc_enable_hw(device_t dev)
+{
+ struct tmc_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (bus_read_4(sc->res[0], TMC_CTL) & CTL_TRACECAPTEN) {
+ printf("%s: TMC is already enabled\n", __func__);
+ return (ENXIO);
+ }
+
+ /* Enable TMC */
+ bus_write_4(sc->res[0], TMC_CTL, CTL_TRACECAPTEN);
+
+ if ((bus_read_4(sc->res[0], TMC_CTL) & CTL_TRACECAPTEN) == 0) {
+ printf("%s: could not enable TMC\n", __func__);
+ return (ENXIO);
+ }
+
+ dprintf("%s: tmc type %d enabled\n", __func__, sc->dev_type);
return (0);
}
@@ -192,13 +451,15 @@
sc = device_get_softc(dev);
+ dprintf("%s%d\n", __func__, device_get_unit(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:
@@ -210,6 +471,7 @@
dprintf(dev, "ETF configuration found\n");
if (sc->etf_configured == false) {
tmc_configure_etf(dev);
+ tmc_enable_hw(dev);
sc->etf_configured = true;
}
break;
@@ -222,128 +484,260 @@
}
static int
-tmc_enable(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+tmc_flush(struct tmc_softc *sc, int stop_on_flush)
{
- struct tmc_softc *sc;
- uint32_t nev;
+ uint32_t reg;
+ int timeout;
- sc = device_get_softc(dev);
+ reg = bus_read_4(sc->res[0], TMC_FFCR);
- if (sc->dev_type == CORESIGHT_ETF)
- return (0);
+ if (stop_on_flush) {
+ reg |= FFCR_STOP_ON_FLUSH;
+ bus_write_4(sc->res[0], TMC_FFCR, reg);
+ }
- KASSERT(sc->dev_type == CORESIGHT_ETR,
- ("Wrong dev_type"));
-
- /*
- * Multiple CPUs can call this same time.
- * We allow only one running configuration.
- */
-
- if (event->etr.flags & ETR_FLAG_ALLOCATE) {
- event->etr.flags &= ~ETR_FLAG_ALLOCATE;
- nev = atomic_fetchadd_int(&sc->nev, 1);
- if (nev == 0) {
- sc->event = event;
- tmc_stop(dev);
- tmc_configure_etr(dev, endp, event);
- tmc_start(dev);
- }
+ reg |= FFCR_FLUSH_MAN;
+ bus_write_4(sc->res[0], TMC_FFCR, reg);
+
+ /* Wait for the flush to complete. */
+ timeout = 10000;
+
+ do {
+ reg = bus_read_4(sc->res[0], TMC_FFCR);
+ if ((reg & FFCR_FLUSH_MAN) == 0)
+ break;
+ } while (timeout--);
+
+ if (timeout <= 0) {
+ printf("%s: could not flush TMC\n", __func__);
+ return (EINTEGRITY);
}
return (0);
}
+static void
+tmc_disable_hw(device_t dev)
+{
+ struct tmc_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ error = tmc_flush(sc, 1);
+ if (error)
+ printf("%s: could not flush TMC\n", __func__);
+
+ error = tmc_wait_for_tmcready(sc);
+ if (error)
+ printf("%s: could not get TMC ready\n", __func__);
+
+ bus_write_4(sc->res[0], TMC_CTL, 0);
+
+ dprintf("%s: tmc type %d disabled\n", __func__, sc->dev_type);
+}
+
static void
tmc_disable(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+ struct coresight_pipeline *pipeline)
{
struct tmc_softc *sc;
- uint32_t nev;
sc = device_get_softc(dev);
- /* ETF configuration is static */
- if (sc->dev_type == CORESIGHT_ETF)
+ if (sc->dev_type == CORESIGHT_ETR)
return;
- KASSERT(sc->dev_type == CORESIGHT_ETR, ("Wrong dev_type"));
+ tmc_flush(sc, 0);
+}
- if (event->etr.flags & ETR_FLAG_RELEASE) {
- event->etr.flags &= ~ETR_FLAG_RELEASE;
- nev = atomic_fetchadd_int(&sc->nev, -1);
- if (nev == 1) {
- tmc_stop(dev);
- sc->event = NULL;
- }
+static int
+tmc_deinit(device_t dev)
+{
+ struct tmc_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (sc->dev_type == CORESIGHT_ETR)
+ return (0);
+
+ if (sc->etf_configured == true) {
+ sc->etf_configured = false;
+ tmc_disable_hw(dev);
}
+
+ return (0);
}
static int
-tmc_read(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+tmc_start(device_t dev, struct endpoint *endp,
+ struct coresight_pipeline *pipeline)
{
struct tmc_softc *sc;
- uint32_t cur_ptr;
+ int error;
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);
+ dprintf("%s%d type %d\n", __func__, device_get_unit(dev), sc->dev_type);
- 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);
- }
+ error = tmc_wait_for_tmcready(sc);
+ if (error)
+ return (error);
+
+ tmc_configure_etr(dev, endp, pipeline);
+ tmc_enable_hw(dev);
return (0);
}
+static int
+tmc_read(device_t dev, struct endpoint *endp,
+ struct coresight_pipeline *pipeline)
+{
+ struct tmc_softc *sc;
+ 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 (ENXIO);
+
+ lo = bus_read_4(sc->res[0], TMC_RWP);
+ hi = bus_read_4(sc->res[0], TMC_RWPHI);
+ ptr = lo | (hi << 32);
+
+ page = PHYS_TO_VM_PAGE(ptr);
+
+ found = false;
+
+ for (i = 0; i < pipeline->etr.npages; i++) {
+ if (pipeline->etr.pages[i] == page) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ pipeline->etr.curpage = i;
+ pipeline->etr.curpage_offset = ptr & 0xfff;
+ dprintf("CUR_PTR %lx, page %d of %d, offset %ld\n",
+ ptr, i, pipeline->etr.npages, pipeline->etr.curpage_offset);
+
+ return (0);
+ } else
+ dprintf("CUR_PTR not found\n");
+
+ return (ENOENT);
+}
+
+static void
+tmc_stop(device_t dev, struct endpoint *endp,
+ struct coresight_pipeline *pipeline)
+{
+ struct tmc_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->dev_type == CORESIGHT_ETF)
+ return;
+
+ dprintf("%s%d type %d\n", __func__, device_get_unit(dev), sc->dev_type);
+
+ /* Make final readings before we stop TMC-ETR. */
+ tmc_read(dev, endp, pipeline);
+ tmc_disable_hw(dev);
+ tmc_deallocate_pgdir(pipeline);
+}
+
+static void
+tmc_intr(void *arg)
+{
+
+ /* TODO */
+
+ panic("unhandled interrupt");
+}
+
int
tmc_attach(device_t dev)
{
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);
}
-static device_method_t tmc_methods[] = {
- /* Device interface */
- DEVMETHOD(device_attach, tmc_attach),
+int
+tmc_detach(device_t dev)
+{
+ struct tmc_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ error = coresight_unregister(dev);
+ if (error)
+ return (error);
+
+ if (sc->intrhand != NULL)
+ bus_teardown_intr(dev, sc->res[1], sc->intrhand);
+
+ bus_release_resources(dev, tmc_spec, sc->res);
+ return (0);
+}
+
+static device_method_t tmc_methods[] = {
/* Coresight interface */
DEVMETHOD(coresight_init, tmc_init),
- DEVMETHOD(coresight_enable, tmc_enable),
+
+ /* ETF only. */
+ DEVMETHOD(coresight_deinit, tmc_deinit),
DEVMETHOD(coresight_disable, tmc_disable),
+
+ /* ETR only. */
+ DEVMETHOD(coresight_setup, tmc_setup),
+ DEVMETHOD(coresight_start, tmc_start),
+ DEVMETHOD(coresight_stop, tmc_stop),
DEVMETHOD(coresight_read, tmc_read),
+ DEVMETHOD(coresight_dump, tmc_dump),
DEVMETHOD_END
};
-DEFINE_CLASS_0(tmc, tmc_driver, tmc_methods, sizeof(struct tmc_softc));
+DEFINE_CLASS_0(coresight_tmc, coresight_tmc_driver, tmc_methods,
+ sizeof(struct tmc_softc));
Index: sys/arm64/coresight/coresight_tmc_fdt.c
===================================================================
--- sys/arm64/coresight/coresight_tmc_fdt.c
+++ sys/arm64/coresight/coresight_tmc_fdt.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by BAE Systems, the University of Cambridge
@@ -71,22 +71,56 @@
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));
}
+static int
+tmc_fdt_detach(device_t dev)
+{
+ struct tmc_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ coresight_fdt_release_platform_data(sc->pdata);
+
+ sc->pdata = NULL;
+
+ error = tmc_detach(dev);
+
+ return (error);
+}
+
static device_method_t tmc_fdt_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, tmc_fdt_probe),
DEVMETHOD(device_attach, tmc_fdt_attach),
+ DEVMETHOD(device_detach, tmc_fdt_detach),
DEVMETHOD_END
};
-DEFINE_CLASS_1(tmc, tmc_fdt_driver, tmc_fdt_methods,
- sizeof(struct tmc_softc), tmc_driver);
+DEFINE_CLASS_1(coresight_tmc, tmc_fdt_driver, tmc_fdt_methods,
+ sizeof(struct tmc_softc), coresight_tmc_driver);
-EARLY_DRIVER_MODULE(tmc, simplebus, tmc_fdt_driver, 0, 0,
+EARLY_DRIVER_MODULE(coresight_tmc, simplebus, tmc_fdt_driver, 0, 0,
BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+MODULE_DEPEND(coresight_tmc, coresight, 1, 1, 1);
+MODULE_DEPEND(coresight_tmc, coresight_cpu_debug, 1, 1, 1);
+MODULE_DEPEND(coresight_tmc, coresight_etm4x, 1, 1, 1);
+MODULE_DEPEND(coresight_tmc, coresight_funnel, 1, 1, 1);
+MODULE_DEPEND(coresight_tmc, coresight_replicator, 1, 1, 1);
+MODULE_VERSION(coresight_tmc, 1);
Index: sys/conf/files.arm64
===================================================================
--- sys/conf/files.arm64
+++ sys/conf/files.arm64
@@ -139,24 +139,24 @@
# ANX6345 RGB to eDP bridge
dev/drm/bridges/anx6345/anx6345.c optional fdt anx6345 compile-with "${DRM_C}"
-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 optional fdt
-arm64/coresight/coresight_etm4x.c standard
-arm64/coresight/coresight_etm4x_acpi.c optional acpi
-arm64/coresight/coresight_etm4x_fdt.c optional fdt
-arm64/coresight/coresight_funnel.c standard
-arm64/coresight/coresight_funnel_acpi.c optional acpi
-arm64/coresight/coresight_funnel_fdt.c optional fdt
-arm64/coresight/coresight_replicator.c standard
-arm64/coresight/coresight_replicator_acpi.c optional acpi
-arm64/coresight/coresight_replicator_fdt.c optional fdt
-arm64/coresight/coresight_tmc.c standard
-arm64/coresight/coresight_tmc_acpi.c optional acpi
-arm64/coresight/coresight_tmc_fdt.c optional fdt
+arm64/coresight/coresight.c optional hwt coresight
+arm64/coresight/coresight_acpi.c optional hwt coresight acpi
+arm64/coresight/coresight_fdt.c optional hwt coresight fdt
+arm64/coresight/coresight_if.m optional hwt coresight
+arm64/coresight/coresight_cmd.c optional hwt coresight
+arm64/coresight/coresight_cpu_debug.c optional hwt coresight fdt
+arm64/coresight/coresight_etm4x.c optional hwt coresight
+arm64/coresight/coresight_etm4x_acpi.c optional hwt coresight acpi
+arm64/coresight/coresight_etm4x_fdt.c optional hwt coresight fdt
+arm64/coresight/coresight_funnel.c optional hwt coresight
+arm64/coresight/coresight_funnel_acpi.c optional hwt coresight acpi
+arm64/coresight/coresight_funnel_fdt.c optional hwt coresight fdt
+arm64/coresight/coresight_replicator.c optional hwt coresight
+arm64/coresight/coresight_replicator_acpi.c optional hwt coresight acpi
+arm64/coresight/coresight_replicator_fdt.c optional hwt coresight fdt
+arm64/coresight/coresight_tmc.c optional hwt coresight
+arm64/coresight/coresight_tmc_acpi.c optional hwt coresight acpi
+arm64/coresight/coresight_tmc_fdt.c optional hwt coresight fdt
dev/smbios/smbios_subr.c standard
Index: sys/dts/arm64/arm/morello-coresight.dtsi
===================================================================
--- /dev/null
+++ sys/dts/arm64/arm/morello-coresight.dtsi
@@ -0,0 +1,349 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include
+#include
+
+/ {
+ cpu_debug0: cpu-debug@402010000 {
+ compatible = "arm,coresight-cpu-debug", "arm,primecell";
+ cpu = <&cpu0>;
+ reg = <0x4 0x02010000 0x0 0x1000>;
+ };
+
+ etm0: etm@402040000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ cpu = <&cpu0>;
+ reg = <0x4 0x02040000 0 0x1000>;
+
+ out-ports {
+ port {
+ cluster0_etm0_out_port: endpoint {
+ remote-endpoint = <&cluster0_static_funnel_in_port0>;
+ };
+ };
+ };
+ };
+
+ cpu_debug1: cpu-debug@402110000 {
+ compatible = "arm,coresight-cpu-debug", "arm,primecell";
+ cpu = <&cpu1>;
+ reg = <0x4 0x02110000 0x0 0x1000>;
+ };
+ etm1: etm@402140000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ cpu = <&cpu1>;
+ reg = <0x4 0x02140000 0 0x1000>;
+
+ out-ports {
+ port {
+ cluster0_etm1_out_port: endpoint {
+ remote-endpoint = <&cluster0_static_funnel_in_port1>;
+ };
+ };
+ };
+ };
+
+ cpu_debug2: cpu-debug@403010000 {
+ compatible = "arm,coresight-cpu-debug", "arm,primecell";
+ cpu = <&cpu2>;
+ reg = <0x4 0x03010000 0x0 0x1000>;
+ };
+
+ etm2: etm@403040000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ cpu = <&cpu2>;
+ reg = <0x4 0x03040000 0 0x1000>;
+
+ out-ports {
+ port {
+ cluster1_etm0_out_port: endpoint {
+ remote-endpoint = <&cluster1_static_funnel_in_port0>;
+ };
+ };
+ };
+ };
+
+ cpu_debug3: cpu-debug@403110000 {
+ compatible = "arm,coresight-cpu-debug", "arm,primecell";
+ cpu = <&cpu3>;
+ reg = <0x4 0x03110000 0x0 0x1000>;
+ };
+
+ etm3: etm@403140000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ cpu = <&cpu3>;
+ reg = <0x4 0x03140000 0 0x1000>;
+
+ out-ports {
+ port {
+ cluster1_etm1_out_port: endpoint {
+ remote-endpoint = <&cluster1_static_funnel_in_port1>;
+ };
+ };
+ };
+ };
+
+ sfunnel0: funnel@0 {
+ compatible = "arm,coresight-static-funnel";
+
+ out-ports {
+ port {
+ cluster0_static_funnel_out_port: endpoint {
+ remote-endpoint = <&etf0_in_port>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ cluster0_static_funnel_in_port0: endpoint {
+ remote-endpoint = <&cluster0_etm0_out_port>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ cluster0_static_funnel_in_port1: endpoint {
+ remote-endpoint = <&cluster0_etm1_out_port>;
+ };
+ };
+ };
+ };
+
+ sfunnel1: funnel@1 {
+ compatible = "arm,coresight-static-funnel";
+
+ out-ports {
+ port {
+ cluster1_static_funnel_out_port: endpoint {
+ remote-endpoint = <&etf1_in_port>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ cluster1_static_funnel_in_port0: endpoint {
+ remote-endpoint = <&cluster1_etm0_out_port>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ cluster1_static_funnel_in_port1: endpoint {
+ remote-endpoint = <&cluster1_etm1_out_port>;
+ };
+ };
+ };
+ };
+
+ tpiu@400130000 {
+ compatible = "arm,coresight-tpiu", "arm,primecell";
+ reg = <0x4 0x00130000 0 0x1000>;
+
+ in-ports {
+ port {
+ tpiu_in_port: endpoint {
+ remote-endpoint = <&replicator_out_port0>;
+ };
+ };
+ };
+ };
+
+ master_funnel: funnel@4000a0000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x4 0x000a0000 0 0x1000>;
+
+ out-ports {
+ port {
+ master_funnel_out_port: endpoint {
+ remote-endpoint = <&replicator_in_port>;
+ };
+ };
+ };
+
+ master_funnel_in_ports: in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ master_funnel_in_port0: endpoint {
+ remote-endpoint = <&cluster_funnel_out_port>;
+ };
+ };
+
+ port@5 {
+ reg = <5>;
+ master_funnel_in_port5: endpoint {
+ remote-endpoint = <&etf2_out_port>;
+ };
+ };
+ };
+ };
+
+ etr@400120000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0x4 0x00120000 0 0x1000>;
+ interrupts = ;
+ interrupt-names = "etrbufint";
+
+ arm,scatter-gather;
+ in-ports {
+ port {
+ etr_in_port: endpoint {
+ remote-endpoint = <&replicator_out_port1>;
+ };
+ };
+ };
+ };
+
+ replicator@400110000 {
+ compatible = "arm,coresight-dynamic-replicator", "arm,primecell";
+ reg = <0x4 0x00110000 0 0x1000>;
+
+ out-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ replicator_out_port0: endpoint {
+ remote-endpoint = <&tpiu_in_port>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ replicator_out_port1: endpoint {
+ remote-endpoint = <&etr_in_port>;
+ };
+ };
+ };
+ in-ports {
+ port {
+ replicator_in_port: endpoint {
+ remote-endpoint = <&master_funnel_out_port>;
+ };
+ };
+ };
+ };
+
+ cluster_funnel: funnel@4000b0000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0x4 0x000b0000 0 0x1000>;
+
+ out-ports {
+ port {
+ cluster_funnel_out_port: endpoint {
+ remote-endpoint = <&master_funnel_in_port0>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ cluster_funnel_in_port0: endpoint {
+ remote-endpoint = <&etf0_out_port>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ cluster_funnel_in_port1: endpoint {
+ remote-endpoint = <&etf1_out_port>;
+ };
+ };
+ };
+ };
+
+ etf0: etf@400410000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0x4 0x00410000 0 0x1000>;
+
+ in-ports {
+ port {
+ etf0_in_port: endpoint {
+ remote-endpoint = <&cluster0_static_funnel_out_port>;
+ };
+ };
+ };
+
+ out-ports {
+ port {
+ etf0_out_port: endpoint {
+ remote-endpoint = <&cluster_funnel_in_port0>;
+ };
+ };
+ };
+ };
+
+ etf1: etf@400420000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0x4 0x00420000 0 0x1000>;
+
+ in-ports {
+ port {
+ etf1_in_port: endpoint {
+ remote-endpoint = <&cluster1_static_funnel_out_port>;
+ };
+ };
+ };
+
+ out-ports {
+ port {
+ etf1_out_port: endpoint {
+ remote-endpoint = <&cluster_funnel_in_port1>;
+ };
+ };
+ };
+ };
+
+ stm_etf: etf@400010000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0x4 0x00010000 0 0x1000>;
+
+ in-ports {
+ port {
+ etf2_in_port: endpoint {
+ remote-endpoint = <&stm_out_port>;
+ };
+ };
+ };
+
+ out-ports {
+ port {
+ etf2_out_port: endpoint {
+ remote-endpoint = <&master_funnel_in_port5>;
+ };
+ };
+ };
+ };
+
+ stm@400800000 {
+ compatible = "arm,coresight-stm", "arm,primecell";
+ reg = <4 0x00800000 0 0x1000>,
+ <0 0x4d000000 0 0x1000000>;
+ reg-names = "stm-base", "stm-stimulus-base";
+
+ out-ports {
+ port {
+ stm_out_port: endpoint {
+ remote-endpoint = <&etf2_in_port>;
+ };
+ };
+ };
+ };
+};
Index: sys/dts/arm64/arm/morello-soc.dts
===================================================================
--- sys/dts/arm64/arm/morello-soc.dts
+++ sys/dts/arm64/arm/morello-soc.dts
@@ -6,6 +6,7 @@
/dts-v1/;
#include "morello.dtsi"
+#include "morello-coresight.dtsi"
/ {
@@ -27,28 +28,28 @@
cpus {
#address-cells = <2>;
#size-cells = <0>;
- cpu0@0 {
+ cpu0: cpu0@0 {
compatible = "arm,armv8";
reg = <0x0 0x0>;
device_type = "cpu";
enable-method = "psci";
clocks = <&scmi_dvfs 0>;
};
- cpu1@100 {
+ cpu1: cpu1@100 {
compatible = "arm,armv8";
reg = <0x0 0x100>;
device_type = "cpu";
enable-method = "psci";
clocks = <&scmi_dvfs 0>;
};
- cpu2@10000 {
+ cpu2: cpu2@10000 {
compatible = "arm,armv8";
reg = <0x0 0x10000>;
device_type = "cpu";
enable-method = "psci";
clocks = <&scmi_dvfs 1>;
};
- cpu3@10100 {
+ cpu3: cpu3@10100 {
compatible = "arm,armv8";
reg = <0x0 0x10100>;
device_type = "cpu";
Index: sys/modules/Makefile
===================================================================
--- sys/modules/Makefile
+++ sys/modules/Makefile
@@ -85,6 +85,7 @@
${_cfi} \
${_chromebook_platform} \
${_ciss} \
+ ${_coresight} \
${_coretemp} \
${_cpsw} \
${_cpuctl} \
@@ -139,6 +140,7 @@
${_hptnr} \
${_hptrr} \
hwpmc \
+ hwt \
${_hyperv} \
i2c \
${_iavf} \
@@ -383,6 +385,7 @@
tmpfs \
${_toecore} \
${_tpm} \
+ twe \
tws \
uart \
udf \
@@ -644,6 +647,12 @@
.endif
.endif
+.if ${MACHINE_CPUARCH} == "aarch64"
+.if !empty(OPT_FDT)
+_coresight= coresight
+.endif
+.endif
+
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm" || \
${MACHINE_CPUARCH} == "riscv"
.if !empty(OPT_FDT)
Index: sys/modules/coresight/Makefile
===================================================================
--- /dev/null
+++ sys/modules/coresight/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR = \
+ coresight \
+ cpu_debug \
+ etm4x \
+ funnel \
+ replicator \
+ tmc
+
+.include
Index: sys/modules/coresight/coresight/Makefile
===================================================================
--- /dev/null
+++ sys/modules/coresight/coresight/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+.PATH: ${SRCTOP}/sys/arm64/coresight
+
+KMOD = coresight
+SRCS = \
+ coresight.c \
+ coresight_acpi.c \
+ coresight_cmd.c \
+ coresight_fdt.c \
+ coresight_if.c \
+ coresight_if.h
+
+.include
Index: sys/modules/coresight/cpu_debug/Makefile
===================================================================
--- /dev/null
+++ sys/modules/coresight/cpu_debug/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${SRCTOP}/sys/arm64/coresight
+
+KMOD = coresight_cpu_debug
+SRCS = coresight_cpu_debug.c coresight_if.h
+
+.include
Index: sys/modules/coresight/etm4x/Makefile
===================================================================
--- /dev/null
+++ sys/modules/coresight/etm4x/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${SRCTOP}/sys/arm64/coresight
+
+KMOD = coresight_etm4x
+SRCS = coresight_etm4x.c coresight_etm4x_fdt.c coresight_if.h
+
+.include
Index: sys/modules/coresight/funnel/Makefile
===================================================================
--- /dev/null
+++ sys/modules/coresight/funnel/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${SRCTOP}/sys/arm64/coresight
+
+KMOD = coresight_funnel
+SRCS = coresight_funnel.c coresight_funnel_fdt.c coresight_if.h
+
+.include
Index: sys/modules/coresight/replicator/Makefile
===================================================================
--- /dev/null
+++ sys/modules/coresight/replicator/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${SRCTOP}/sys/arm64/coresight
+
+KMOD = coresight_replicator
+SRCS = coresight_replicator.c coresight_replicator_fdt.c coresight_if.h
+
+.include
Index: sys/modules/coresight/tmc/Makefile
===================================================================
--- /dev/null
+++ sys/modules/coresight/tmc/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${SRCTOP}/sys/arm64/coresight
+
+KMOD = coresight_tmc
+SRCS = coresight_tmc.c coresight_tmc_fdt.c coresight_if.h
+
+.include