Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108594216
D40477.id125527.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
84 KB
Referenced Files
None
Subscribers
None
D40477.id125527.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
@@ -48,6 +48,8 @@
#include <dev/acpica/acpivar.h>
#endif
+#include <dev/hwt/hwt_thread.h>
+
#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 <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,17 +39,278 @@
#include <sys/lock.h>
#include <sys/module.h>
#include <sys/mutex.h>
+#include <sys/smp.h>
+#include <sys/hwt.h>
#include <machine/bus.h>
#include <arm64/coresight/coresight.h>
+#include <dev/hwt/hwt_config.h>
+#include <dev/hwt/hwt_context.h>
+#include <dev/hwt/hwt_config.h>
+#include <dev/hwt/hwt_cpu.h>
+#include <dev/hwt/hwt_thread.h>
+#include <dev/hwt/hwt_backend.h>
+#include <dev/hwt/hwt_vm.h>
+
+#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 <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
@@ -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 <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
@@ -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 <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
@@ -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 <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
@@ -43,6 +43,8 @@
#include <arm64/coresight/coresight.h>
#include <arm64/coresight/coresight_etm4x.h>
+#include <dev/hwt/hwt_context.h>
+
#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 <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
@@ -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 <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,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 <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
@@ -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 <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,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 <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 }
};
@@ -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 <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,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 <br@bsdpad.com>
+ * Copyright (c) 2023 Ruslan Bukin <br@bsdpad.com>
* 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 <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,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 <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
@@ -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 <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
@@ -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 <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,15 @@
#include <sys/module.h>
#include <machine/bus.h>
+#include <vm/vm.h>
+#include <vm/vm_object.h>
+#include <vm/vm_param.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,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 <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
@@ -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 <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+ 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 = <GIC_SPI 39 IRQ_TYPE_EDGE_RISING>;
+ 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 <bsd.subdir.mk>
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 <bsd.kmod.mk>
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 <bsd.kmod.mk>
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 <bsd.kmod.mk>
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 <bsd.kmod.mk>
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 <bsd.kmod.mk>
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 <bsd.kmod.mk>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jan 27, 6:16 PM (1 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16203600
Default Alt Text
D40477.id125527.diff (84 KB)
Attached To
Mode
D40477: HWT: ARM CoreSight support
Attached
Detach File
Event Timeline
Log In to Comment