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,
@@ -119,15 +122,13 @@
};
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;
};
struct coresight_event {
@@ -149,16 +150,30 @@
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);
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_event(struct coresight_event *event, int cpu);
+int coresight_setup(struct coresight_event *event);
+int coresight_configure(struct coresight_event *event,
+ struct hwt_context *ctx);
+void coresight_deconfigure(struct coresight_event *event);
+
+int coresight_start(struct coresight_event *event);
+void coresight_stop(struct coresight_event *event);
+
+void coresight_enable(struct coresight_event *event);
+void coresight_disable(struct coresight_event *event);
+
+int coresight_read(struct coresight_event *event);
+void coresight_dump(struct coresight_event *event);
#endif /* !_ARM64_CORESIGHT_CORESIGHT_H_ */
Index: sys/arm64/coresight/coresight.c
===================================================================
--- sys/arm64/coresight/coresight.c
+++ sys/arm64/coresight/coresight.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -39,17 +39,270 @@
#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_event cs_event[MAXCPU];
+
+static int
+coresight_backend_init_thread(struct hwt_context *ctx)
+{
+ struct coresight_event *event;
+ 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++) {
+ event = &cs_event[cpu_id];
+ memset(event, 0, sizeof(struct coresight_event));
+ event->excp_level = 0;
+ event->src = CORESIGHT_ETMV4;
+ event->sink = CORESIGHT_TMC_ETR;
+
+ error = coresight_init_event(event, cpu_id);
+ if (error)
+ return (error);
+
+ if (cpu_id == 0) {
+ event->etr.low = 0;
+ event->etr.high = 0;
+ event->etr.pages = vm->pages;
+ event->etr.npages = vm->npages;
+ event->etr.bufsize = vm->npages * PAGE_SIZE;
+
+ /*
+ * These methods are TMC only. We have single
+ * TMC(ETR) per system, so call them on CPU0 only.
+ */
+ error = coresight_setup(event);
+ if (error)
+ return (error);
+
+ error = coresight_start(event);
+ if (error)
+ return (error);
+ }
+ }
+
+ return (0);
+}
+
+static int
+coresight_backend_init_cpu(struct hwt_context *ctx)
+{
+ struct coresight_event *event;
+ struct hwt_vm *vm;
+ int error;
+
+ vm = ctx->vm;
+
+ event = &cs_event[ctx->cpu];
+ memset(event, 0, sizeof(struct coresight_event));
+
+ event->excp_level = 1;
+ event->src = CORESIGHT_ETMV4;
+ event->sink = CORESIGHT_TMC_ETR;
+
+ error = coresight_init_event(event, ctx->cpu);
+ if (error)
+ return (error);
+
+ /* The following is TMC (ETR) only, so pick first event for that. */
+ if (ctx->cpu != 0) {
+ event = &cs_event[0];
+ memset(event, 0, sizeof(struct coresight_event));
+
+ event->excp_level = 1;
+ event->src = CORESIGHT_ETMV4;
+ event->sink = CORESIGHT_TMC_ETR;
+
+ error = coresight_init_event(event, ctx->cpu);
+ if (error)
+ return (error);
+ }
+
+ /* TMC(ETR) configuration. */
+ event->etr.low = 0;
+ event->etr.high = 0;
+ event->etr.pages = vm->pages;
+ event->etr.npages = vm->npages;
+ event->etr.bufsize = vm->npages * PAGE_SIZE;
+
+ error = coresight_setup(event);
+ if (error)
+ return (error);
+
+ error = coresight_start(event);
+ 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_event *event;
+ int cpu_id;
+
+ for (cpu_id = 0; cpu_id < mp_ncpus; cpu_id++) {
+ event = &cs_event[cpu_id];
+ coresight_disable(event);
+ if (cpu_id == 0)
+ coresight_stop(event);
+ }
+}
+
+static int
+coresight_backend_configure(struct hwt_context *ctx, int cpu_id, int session_id)
+{
+ struct coresight_event *event;
+ int error;
+
+ event = &cs_event[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.
+ */
+ event->etm.trace_id = session_id + 1;
+
+ error = coresight_configure(event, ctx);
+
+ return (error);
+}
+
+static void
+coresight_backend_enable(int cpu_id)
+{
+ struct coresight_event *event;
+
+ event = &cs_event[cpu_id];
+
+ coresight_enable(event);
+}
+
+static void
+coresight_backend_disable(int cpu_id)
+{
+ struct coresight_event *event;
+
+ event = &cs_event[cpu_id];
+
+ coresight_disable(event);
+}
+
+static int
+coresight_backend_read(int cpu_id, int *curpage, vm_offset_t *curpage_offset)
+{
+ struct coresight_event *event;
+ int error;
+
+ /*
+ * coresight_read() is TMC(ETR) only method. Also, we have a single
+ * TMC(ETR) per system configured from event 0. So read data from
+ * event 0.
+ */
+
+ event = &cs_event[0];
+
+ KASSERT(event != NULL, ("No event found"));
+
+ error = coresight_read(event);
+ if (error == 0) {
+ *curpage = event->etr.curpage;
+ *curpage_offset = event->etr.curpage_offset;
+ }
+
+ return (error);
+}
+
+static void
+coresight_backend_dump(int cpu_id)
+{
+ struct coresight_event *event;
+
+ event = &cs_event[cpu_id];
+
+ coresight_dump(event);
+}
+
+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);
@@ -61,6 +314,12 @@
TAILQ_INSERT_TAIL(&cs_devs, cs_dev, link);
mtx_unlock(&cs_mtx);
+ if (desc->dev_type == CORESIGHT_TMC_ETR) {
+ error = hwt_backend_register(&backend);
+ if (error != 0)
+ return (error);
+ }
+
return (0);
}
@@ -81,7 +340,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 +354,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 +367,11 @@
case CORESIGHT_BUS_ACPI:
#ifdef DEV_ACPI
if (endp->their_handle == endp2->my_handle) {
- *out_endp = endp2;
+ *out_endp =
+ malloc(sizeof(struct endpoint),
+ M_CORESIGHT, M_WAITOK | M_ZERO);
+ memcpy(*out_endp, endp2,
+ sizeof(struct endpoint));
return (cs_dev);
}
#endif
Index: sys/arm64/coresight/coresight_cmd.c
===================================================================
--- sys/arm64/coresight/coresight_cmd.c
+++ sys/arm64/coresight/coresight_cmd.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -57,7 +57,7 @@
if (endp->input != 0)
continue;
- out = coresight_get_output_device(endp, &out_endp);
+ out = coresight_get_output_device(cs_dev, endp, &out_endp);
if (out != NULL) {
if (LIST_EMPTY(&event->endplist)) {
/* Add source device */
@@ -94,7 +94,7 @@
}
int
-coresight_init_event(int cpu, struct coresight_event *event)
+coresight_init_event(struct coresight_event *event, int cpu)
{
struct coresight_device *cs_dev;
struct endpoint *endp;
@@ -125,8 +125,71 @@
return (0);
}
+int
+coresight_setup(struct coresight_event *event)
+{
+ struct coresight_device *cs_dev;
+ struct endpoint *endp;
+ int error;
+
+ LIST_FOREACH(endp, &event->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ error = CORESIGHT_SETUP(cs_dev->dev, endp, event);
+ if (error != ENXIO && error != 0)
+ return (error);
+ }
+
+ return (0);
+}
+
+int
+coresight_configure(struct coresight_event *event, struct hwt_context *ctx)
+{
+ struct coresight_device *cs_dev;
+ struct endpoint *endp;
+ int error;
+
+ LIST_FOREACH(endp, &event->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ error = CORESIGHT_CONFIGURE(cs_dev->dev, endp, event, ctx);
+ if (error != ENXIO && error != 0)
+ return (error);
+ }
+
+ return (0);
+}
+
+int
+coresight_start(struct coresight_event *event)
+{
+ struct coresight_device *cs_dev;
+ struct endpoint *endp;
+ int error;
+
+ LIST_FOREACH(endp, &event->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ error = CORESIGHT_START(cs_dev->dev, endp, event);
+ if (error != ENXIO && error != 0)
+ return (error);
+ }
+
+ return (0);
+}
+
+void
+coresight_stop(struct coresight_event *event)
+{
+ struct coresight_device *cs_dev;
+ struct endpoint *endp;
+
+ LIST_FOREACH(endp, &event->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ CORESIGHT_STOP(cs_dev->dev, endp, event);
+ }
+}
+
void
-coresight_enable(int cpu, struct coresight_event *event)
+coresight_enable(struct coresight_event *event)
{
struct coresight_device *cs_dev;
struct endpoint *endp;
@@ -138,7 +201,7 @@
}
void
-coresight_disable(int cpu, struct coresight_event *event)
+coresight_disable(struct coresight_event *event)
{
struct coresight_device *cs_dev;
struct endpoint *endp;
@@ -150,10 +213,30 @@
}
void
-coresight_read(int cpu, struct coresight_event *event)
+coresight_dump(struct coresight_event *event)
{
+ struct coresight_device *cs_dev;
struct endpoint *endp;
- LIST_FOREACH(endp, &event->endplist, endplink)
- CORESIGHT_READ(endp->cs_dev->dev, endp, event);
+ LIST_FOREACH(endp, &event->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ CORESIGHT_DUMP(cs_dev->dev);
+ }
+}
+
+int
+coresight_read(struct coresight_event *event)
+{
+ struct coresight_device *cs_dev;
+ struct endpoint *endp;
+ int error;
+
+ LIST_FOREACH(endp, &event->endplist, endplink) {
+ cs_dev = endp->cs_dev;
+ error = CORESIGHT_READ(cs_dev->dev, endp, event);
+ if (error != ENXIO && error != 0)
+ return (error);
+ }
+
+ return (0);
}
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;
@@ -181,4 +240,6 @@
int etm_attach(device_t dev);
+DECLARE_CLASS(etm_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_event *event)
{
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
@@ -169,6 +259,26 @@
return (0);
}
+static int
+etm_configure(device_t dev, struct endpoint *endp,
+ struct coresight_event *event, 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, event);
+
+ return (error);
+}
+
static int
etm_init(device_t dev)
{
@@ -200,15 +310,20 @@
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, event->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 */
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");
@@ -225,8 +340,12 @@
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 {
@@ -258,6 +377,7 @@
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
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",
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_event *event, struct hwt_context *ctx)
{
struct funnel_softc *sc;
uint32_t reg;
@@ -96,7 +96,7 @@
}
static void
-funnel_disable(device_t dev, struct endpoint *endp,
+funnel_deconfigure(device_t dev, struct endpoint *endp,
struct coresight_event *event)
{
struct funnel_softc *sc;
@@ -135,8 +135,8 @@
static device_method_t funnel_methods[] = {
/* Coresight interface */
DEVMETHOD(coresight_init, funnel_init),
- DEVMETHOD(coresight_enable, funnel_enable),
- DEVMETHOD(coresight_disable, funnel_disable),
+ DEVMETHOD(coresight_configure, funnel_configure),
+ DEVMETHOD(coresight_deconfigure,funnel_deconfigure),
DEVMETHOD_END
};
Index: sys/arm64/coresight/coresight_funnel_fdt.c
===================================================================
--- sys/arm64/coresight/coresight_funnel_fdt.c
+++ sys/arm64/coresight/coresight_funnel_fdt.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin
+ * 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 }
};
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,6 +39,37 @@
device_t dev;
};
+METHOD int setup {
+ device_t dev;
+ struct endpoint *endp;
+ struct coresight_event *event;
+};
+
+METHOD int configure {
+ device_t dev;
+ struct endpoint *endp;
+ struct coresight_event *event;
+ struct hwt_context *ctx;
+};
+
+METHOD void deconfigure {
+ device_t dev;
+ struct endpoint *endp;
+ struct coresight_event *event;
+};
+
+METHOD int start {
+ device_t dev;
+ struct endpoint *endp;
+ struct coresight_event *event;
+};
+
+METHOD void stop {
+ device_t dev;
+ struct endpoint *endp;
+ struct coresight_event *event;
+}
+
METHOD int enable {
device_t dev;
struct endpoint *endp;
@@ -51,6 +82,10 @@
struct coresight_event *event;
};
+METHOD void dump {
+ device_t dev;
+};
+
METHOD int read {
device_t dev;
struct endpoint *endp;
Index: sys/arm64/coresight/coresight_replicator.c
===================================================================
--- sys/arm64/coresight/coresight_replicator.c
+++ sys/arm64/coresight/coresight_replicator.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin
+ * 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_event *event, struct hwt_context *ctx)
{
struct replicator_softc *sc;
@@ -84,7 +84,7 @@
}
static void
-replicator_disable(device_t dev, struct endpoint *endp,
+replicator_deconfigure(device_t dev, struct endpoint *endp,
struct coresight_event *event)
{
struct replicator_softc *sc;
@@ -119,8 +119,8 @@
static device_method_t replicator_methods[] = {
/* Coresight interface */
DEVMETHOD(coresight_init, replicator_init),
- DEVMETHOD(coresight_enable, replicator_enable),
- DEVMETHOD(coresight_disable, replicator_disable),
+ DEVMETHOD(coresight_configure, replicator_configure),
+ DEVMETHOD(coresight_deconfigure,replicator_deconfigure),
DEVMETHOD_END
};
Index: sys/arm64/coresight/coresight_tmc.h
===================================================================
--- sys/arm64/coresight/coresight_tmc.h
+++ sys/arm64/coresight/coresight_tmc.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2018-2020 Ruslan Bukin
+ * Copyright (c) 2018-2023 Ruslan Bukin
* All rights reserved.
*
* This software was developed by SRI International and the University of
@@ -119,19 +119,21 @@
DECLARE_CLASS(tmc_driver);
struct tmc_softc {
- struct resource *res;
+ struct resource *res[2];
device_t dev;
- uint64_t cycle;
struct coresight_platform_data *pdata;
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);
#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,14 @@
#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
#include
#include
@@ -46,63 +54,168 @@
#define TMC_DEBUG
#undef TMC_DEBUG
-
+
#ifdef TMC_DEBUG
#define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define dprintf(fmt, ...)
#endif
+#define SG_PT_ENTIRES_PER_PAGE (PAGE_SIZE / sizeof(sgte_t))
+#define ETR_SG_ET_MASK 0x3
+#define ETR_SG_ET_LAST 0x1
+#define ETR_SG_ET_NORMAL 0x2
+#define ETR_SG_ET_LINK 0x3
+
+#define ETR_SG_PAGE_SHIFT 12
+#define ETR_SG_ADDR_SHIFT 4
+
+#define ETR_SG_ENTRY(addr, type) \
+ (sgte_t)((((addr) >> ETR_SG_PAGE_SHIFT) << ETR_SG_ADDR_SHIFT) | \
+ (type & ETR_SG_ET_MASK))
+
static struct resource_spec tmc_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE | RF_OPTIONAL },
{ -1, 0 }
};
static int
-tmc_start(device_t dev)
+tmc_alloc_pages(struct tmc_softc *sc, vm_page_t *pages, int npages)
+{
+ vm_paddr_t low, high, boundary;
+ vm_memattr_t memattr;
+ int alignment;
+ vm_pointer_t va;
+ int pflags;
+ vm_page_t m;
+ int tries;
+ int i;
+
+ alignment = PAGE_SIZE;
+ low = 0;
+ high = -1UL;
+ boundary = 0;
+ pflags = VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY | VM_ALLOC_WIRED |
+ VM_ALLOC_ZERO;
+ memattr = VM_MEMATTR_DEFAULT;
+
+ for (i = 0; i < npages; i++) {
+ tries = 0;
+retry:
+ m = vm_page_alloc_noobj_contig(pflags, 1, low, high,
+ alignment, boundary, memattr);
+ if (m == NULL) {
+ if (tries < 3) {
+ if (!vm_page_reclaim_contig(pflags, 1, low,
+ high, alignment, boundary))
+ vm_wait(NULL);
+ tries++;
+ goto retry;
+ }
+
+ return (ENOMEM);
+ }
+
+ if ((m->flags & PG_ZERO) == 0)
+ pmap_zero_page(m);
+
+ va = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m));
+ cpu_dcache_wb_range(va, PAGE_SIZE);
+ cpu_dcache_inv_range(va, PAGE_SIZE);
+ m->valid = VM_PAGE_BITS_ALL;
+ m->oflags &= ~VPO_UNMANAGED;
+ m->flags |= PG_FICTITIOUS;
+
+ pages[i] = m;
+ }
+
+ return (0);
+}
+
+static int
+tmc_enable(device_t dev)
{
struct tmc_softc *sc;
uint32_t reg;
sc = device_get_softc(dev);
- if (bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN)
+ if (sc->dev_type == CORESIGHT_ETR) {
+ dprintf("%s%d\n", __func__, device_get_unit(dev));
+ }
+
+ if (bus_read_4(sc->res[0], TMC_CTL) & CTL_TRACECAPTEN)
return (-1);
/* Enable TMC */
- bus_write_4(sc->res, TMC_CTL, CTL_TRACECAPTEN);
- if ((bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN) == 0)
+ bus_write_4(sc->res[0], TMC_CTL, CTL_TRACECAPTEN);
+ if ((bus_read_4(sc->res[0], TMC_CTL) & CTL_TRACECAPTEN) == 0)
panic("Not enabled\n");
do {
- reg = bus_read_4(sc->res, TMC_STS);
+ reg = bus_read_4(sc->res[0], TMC_STS);
} while ((reg & STS_TMCREADY) == 1);
- if ((bus_read_4(sc->res, TMC_CTL) & CTL_TRACECAPTEN) == 0)
+ if ((bus_read_4(sc->res[0], TMC_CTL) & CTL_TRACECAPTEN) == 0)
panic("Not enabled\n");
+ dprintf("%s: enabled\n", __func__);
+
return (0);
}
static int
-tmc_stop(device_t dev)
+tmc_disable(device_t dev)
{
struct tmc_softc *sc;
uint32_t reg;
sc = device_get_softc(dev);
- reg = bus_read_4(sc->res, TMC_CTL);
+ dprintf("%s\n", __func__);
+
+ reg = bus_read_4(sc->res[0], TMC_CTL);
reg &= ~CTL_TRACECAPTEN;
- bus_write_4(sc->res, TMC_CTL, reg);
+ bus_write_4(sc->res[0], TMC_CTL, reg);
do {
- reg = bus_read_4(sc->res, TMC_STS);
+ reg = bus_read_4(sc->res[0], TMC_STS);
} while ((reg & STS_TMCREADY) == 1);
return (0);
}
+static void
+tmc_dump(device_t dev)
+{
+ struct tmc_softc *sc;
+ uint32_t reg;
+ size_t hi, lo;
+ size_t rrp, rwp;
+
+ sc = device_get_softc(dev);
+
+ lo = bus_read_4(sc->res[0], TMC_RRP);
+ hi = bus_read_4(sc->res[0], TMC_RRPHI);
+ rrp = lo | (hi << 32);
+
+ lo = bus_read_4(sc->res[0], TMC_RWP);
+ hi = bus_read_4(sc->res[0], TMC_RWPHI);
+ rwp = lo | (hi << 32);
+
+ reg = bus_read_4(sc->res[0], TMC_DEVID);
+ if ((reg & DEVID_CONFIGTYPE_M) == DEVID_CONFIGTYPE_ETR)
+ printf("%s%d: STS %x CTL %x RSZ %x RRP %lx RWP %lx AXICTL %x\n",
+ __func__,
+ device_get_unit(dev),
+ bus_read_4(sc->res[0], TMC_STS),
+ bus_read_4(sc->res[0], TMC_CTL),
+ bus_read_4(sc->res[0], TMC_RSZ),
+ rrp, rwp,
+ bus_read_4(sc->res[0], TMC_AXICTL));
+}
+
static int
tmc_configure_etf(device_t dev)
{
@@ -112,23 +225,13 @@
sc = device_get_softc(dev);
do {
- reg = bus_read_4(sc->res, TMC_STS);
+ reg = bus_read_4(sc->res[0], TMC_STS);
} while ((reg & STS_TMCREADY) == 0);
- bus_write_4(sc->res, TMC_MODE, MODE_HW_FIFO);
- bus_write_4(sc->res, TMC_FFCR, FFCR_EN_FMT | FFCR_EN_TI);
+ bus_write_4(sc->res[0], TMC_MODE, MODE_HW_FIFO);
+ bus_write_4(sc->res[0], TMC_FFCR, FFCR_EN_FMT | FFCR_EN_TI);
- tmc_start(dev);
-
- dprintf("%s: STS %x, CTL %x, RSZ %x, RRP %x, RWP %x, "
- "LBUFLEVEL %x, CBUFLEVEL %x\n", __func__,
- bus_read_4(sc->res, TMC_STS),
- bus_read_4(sc->res, TMC_CTL),
- bus_read_4(sc->res, TMC_RSZ),
- bus_read_4(sc->res, TMC_RRP),
- bus_read_4(sc->res, TMC_RWP),
- bus_read_4(sc->res, TMC_CBUFLEVEL),
- bus_read_4(sc->res, TMC_LBUFLEVEL));
+ tmc_enable(dev);
return (0);
}
@@ -142,44 +245,180 @@
sc = device_get_softc(dev);
- tmc_stop(dev);
-
do {
- reg = bus_read_4(sc->res, TMC_STS);
+ reg = bus_read_4(sc->res[0], TMC_STS);
} while ((reg & STS_TMCREADY) == 0);
/* Configure TMC */
- bus_write_4(sc->res, TMC_MODE, MODE_CIRCULAR_BUFFER);
+ bus_write_4(sc->res[0], TMC_MODE, MODE_CIRCULAR_BUFFER);
reg = AXICTL_PROT_CTRL_BIT1;
reg |= AXICTL_WRBURSTLEN_16;
-
- /*
- * SG operation is broken on DragonBoard 410c
- * reg |= AXICTL_SG_MODE;
- */
-
- reg |= AXICTL_AXCACHE_OS;
- bus_write_4(sc->res, TMC_AXICTL, reg);
+ if (sc->scatter_gather)
+ reg |= AXICTL_SG_MODE;
+ /* reg |= AXICTL_AXCACHE_OS; */
+ bus_write_4(sc->res[0], TMC_AXICTL, reg);
reg = FFCR_EN_FMT | FFCR_EN_TI | FFCR_FON_FLIN |
FFCR_FON_TRIG_EVT | FFCR_TRIGON_TRIGIN;
- bus_write_4(sc->res, TMC_FFCR, reg);
+ bus_write_4(sc->res[0], TMC_FFCR, reg);
- bus_write_4(sc->res, TMC_TRG, 8);
+ bus_write_4(sc->res[0], TMC_TRG, 0x3ff);
- bus_write_4(sc->res, TMC_DBALO, event->etr.low);
- bus_write_4(sc->res, TMC_DBAHI, event->etr.high);
- bus_write_4(sc->res, TMC_RSZ, event->etr.bufsize / 4);
-
- bus_write_4(sc->res, TMC_RRP, event->etr.low);
- bus_write_4(sc->res, TMC_RWP, event->etr.low);
+ if (sc->scatter_gather) {
+ dprintf("%s: event->etr.pages %p\n", __func__,
+ event->etr.pages);
+ dprintf("%s: event->etr.npages %d\n", __func__,
+ event->etr.npages);
+ } else {
+ bus_write_4(sc->res[0], TMC_DBALO, event->etr.low);
+ bus_write_4(sc->res[0], TMC_DBAHI, event->etr.high);
+ bus_write_4(sc->res[0], TMC_RSZ, event->etr.bufsize / 4);
+ bus_write_4(sc->res[0], TMC_RRP, event->etr.low);
+ bus_write_4(sc->res[0], TMC_RWP, event->etr.low);
+ }
- reg = bus_read_4(sc->res, TMC_STS);
+ reg = bus_read_4(sc->res[0], TMC_STS);
reg &= ~STS_FULL;
- bus_write_4(sc->res, TMC_STS, reg);
+ bus_write_4(sc->res[0], TMC_STS, reg);
+
+ return (0);
+}
+
+static vm_page_t *
+tmc_allocate_pgdir(struct tmc_softc *sc, vm_page_t *pages, int nentries,
+ int npt)
+{
+ vm_page_t *pt_dir;
+ vm_paddr_t paddr;
+ int sgtentry;
+ sgte_t *ptr;
+ uint32_t dirpg;
+ int curpg;
+ int type;
+ int error;
+ int i;
+
+ pt_dir = malloc(sizeof(struct vm_page *) * npt, M_DEVBUF,
+ M_WAITOK | M_ZERO);
+ error = tmc_alloc_pages(sc, pt_dir, npt);
+ if (error) {
+ printf("%s: could not allocate pages\n", __func__);
+ return (NULL);
+ }
+
+ sgtentry = 0;
+ curpg = 0;
+ ptr = (sgte_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(pt_dir[0]));
+ dirpg = 1;
+
+ for (i = 0; i < nentries - 1; i++) {
+ dprintf("entry %d dirpg %d\n", i, dirpg);
+
+ if (sgtentry == (SG_PT_ENTIRES_PER_PAGE - 1)) {
+ type = ETR_SG_ET_LINK;
+ paddr = VM_PAGE_TO_PHYS(pt_dir[dirpg]);
+ } else {
+ type = ETR_SG_ET_NORMAL;
+ paddr = VM_PAGE_TO_PHYS(pages[curpg]);
+
+#ifdef TMC_DEBUG
+ if ((i % 100) == 0)
+ dprintf("%s: entry (%d/%d) type %d dirpg %d "
+ "curpg %d paddr %lx\n", __func__, i,
+ nentries, type, dirpg, curpg, paddr);
+#endif
+
+ curpg++;
+ }
- tmc_start(dev);
+ *ptr = ETR_SG_ENTRY(paddr, type);
+ cpu_dcache_wb_range((vm_pointer_t)ptr, sizeof(sgte_t));
+ ptr++;
+
+ /* Take next directory page. */
+ if (type == ETR_SG_ET_LINK) {
+ ptr = (sgte_t *)PHYS_TO_DMAP(
+ VM_PAGE_TO_PHYS(pt_dir[dirpg]));
+ dirpg++;
+ }
+
+ sgtentry = (sgtentry + 1) % SG_PT_ENTIRES_PER_PAGE;
+ }
+
+ /* Last entry. */
+ paddr = VM_PAGE_TO_PHYS(pages[curpg]);
+ *ptr = ETR_SG_ENTRY(paddr, ETR_SG_ET_LAST);
+ cpu_dcache_wb_range((vm_pointer_t)ptr, sizeof(sgte_t));
+
+ return (pt_dir);
+}
+
+static int
+tmc_configure(device_t dev, struct endpoint *endp,
+ struct coresight_event *event, struct hwt_context *ctx)
+{
+
+ return (0);
+}
+
+static int
+tmc_setup(device_t dev, struct endpoint *endp, struct coresight_event *event)
+{
+ struct tmc_softc *sc;
+ vm_page_t *pt_dir;
+ vm_page_t *pages;
+ uint64_t pbase;
+ uint32_t reg;
+ int nentries;
+ int nlinks;
+ int npages;
+ int npt;
+
+ sc = device_get_softc(dev);
+
+ reg = bus_read_4(sc->res[0], TMC_DEVID);
+ if ((reg & DEVID_CONFIGTYPE_M) != DEVID_CONFIGTYPE_ETR)
+ return (0);
+
+ if (!sc->scatter_gather)
+ return (0);
+
+ npages = event->etr.npages;
+ pages = event->etr.pages;
+
+ if (npages == 0 || pages == NULL)
+ return (EINVAL);
+
+ nlinks = npages / (SG_PT_ENTIRES_PER_PAGE - 1);
+ if (nlinks && ((npages % (SG_PT_ENTIRES_PER_PAGE - 1)) < 2))
+ nlinks--;
+ nentries = nlinks + npages;
+
+ npt = howmany(nentries, SG_PT_ENTIRES_PER_PAGE);
+
+ dprintf("%s: nentries %d, npt %d\n", __func__, nentries, npt);
+
+ pt_dir = tmc_allocate_pgdir(sc, pages, nentries, npt);
+ if (pt_dir == NULL)
+ return (ENOMEM);
+
+#ifdef TMC_DEBUG
+ ptr = (sgte_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(pt_dir[0]));
+ for (i = 0; i < nentries; i++)
+ dprintf("%s: entry %x\n", __func__, *ptr++);
+#endif
+
+ dprintf("%s: event->etr.pages %p\n", __func__, event->etr.pages);
+ dprintf("%s: event->etr.npages %d\n", __func__, event->etr.npages);
+
+ pbase = (uint64_t)VM_PAGE_TO_PHYS(pt_dir[0]);
+
+ dprintf("%s: pbase %lx\n", __func__, pbase);
+
+ bus_write_4(sc->res[0], TMC_DBALO, pbase & 0xffffffff);
+ bus_write_4(sc->res[0], TMC_DBAHI, pbase >> 32);
+ bus_write_4(sc->res[0], TMC_RSZ, (event->etr.npages * 4096) / 4);
return (0);
}
@@ -193,12 +432,12 @@
sc = device_get_softc(dev);
/* Unlock Coresight */
- bus_write_4(sc->res, CORESIGHT_LAR, CORESIGHT_UNLOCK);
+ bus_write_4(sc->res[0], CORESIGHT_LAR, CORESIGHT_UNLOCK);
/* Unlock TMC */
- bus_write_4(sc->res, TMC_LAR, CORESIGHT_UNLOCK);
+ bus_write_4(sc->res[0], TMC_LAR, CORESIGHT_UNLOCK);
- reg = bus_read_4(sc->res, TMC_DEVID);
+ reg = bus_read_4(sc->res[0], TMC_DEVID);
reg &= DEVID_CONFIGTYPE_M;
switch (reg) {
case DEVID_CONFIGTYPE_ETR:
@@ -222,94 +461,90 @@
}
static int
-tmc_enable(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+tmc_start(device_t dev, struct endpoint *endp, struct coresight_event *event)
{
struct tmc_softc *sc;
- uint32_t nev;
sc = device_get_softc(dev);
if (sc->dev_type == CORESIGHT_ETF)
return (0);
- 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);
- }
- }
+ KASSERT(sc->dev_type == CORESIGHT_ETR, ("Wrong dev_type"));
+
+ tmc_configure_etr(dev, endp, event);
+ tmc_enable(dev);
return (0);
}
-static void
-tmc_disable(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+static int
+tmc_read(device_t dev, struct endpoint *endp, struct coresight_event *event)
{
struct tmc_softc *sc;
- uint32_t nev;
+ vm_page_t page;
+ bool found;
+ uint64_t lo, hi;
+ uint64_t ptr;
+ int i;
sc = device_get_softc(dev);
-
- /* ETF configuration is static */
if (sc->dev_type == CORESIGHT_ETF)
- return;
+ return (ENXIO);
- KASSERT(sc->dev_type == CORESIGHT_ETR, ("Wrong dev_type"));
+ 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);
- 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;
+ found = false;
+
+ for (i = 0; i < event->etr.npages; i++) {
+ if (event->etr.pages[i] == page) {
+ found = true;
+ break;
}
}
+
+ if (found) {
+ event->etr.curpage = i;
+ event->etr.curpage_offset = ptr & 0xfff;
+ dprintf("CUR_PTR %lx, page %d of %d, offset %ld\n",
+ ptr, i, event->etr.npages, event->etr.curpage_offset);
+
+ return (0);
+ }
+
+ return (ENOENT);
}
-static int
-tmc_read(device_t dev, struct endpoint *endp,
- struct coresight_event *event)
+static void
+tmc_stop(device_t dev, struct endpoint *endp, struct coresight_event *event)
{
struct tmc_softc *sc;
- uint32_t cur_ptr;
sc = device_get_softc(dev);
+ /* ETF configuration is static */
if (sc->dev_type == CORESIGHT_ETF)
- return (0);
+ return;
- /*
- * Ensure the event we are reading information for
- * is currently configured one.
- */
- if (sc->event != event)
- return (0);
+ KASSERT(sc->dev_type == CORESIGHT_ETR, ("Wrong 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);
- }
+ /* Make final readings before stopping TMC. */
+ tmc_read(dev, endp, event);
- return (0);
+ tmc_disable(dev);
+}
+
+static void
+tmc_intr(void *arg)
+{
+
+ /* TODO */
+
+ panic("unhandled interrupt");
}
int
@@ -317,18 +552,36 @@
{
struct coresight_desc desc;
struct tmc_softc *sc;
+ uint32_t reg;
sc = device_get_softc(dev);
sc->dev = dev;
- if (bus_alloc_resources(dev, tmc_spec, &sc->res) != 0) {
+ if (bus_alloc_resources(dev, tmc_spec, sc->res) != 0) {
device_printf(dev, "cannot allocate resources for device\n");
return (ENXIO);
}
+ if (sc->res[1] != NULL) {
+ if (bus_setup_intr(dev, sc->res[1],
+ INTR_TYPE_MISC | INTR_MPSAFE, NULL, tmc_intr, sc,
+ &sc->intrhand)) {
+ bus_release_resources(dev, tmc_spec, sc->res);
+ device_printf(dev, "cannot setup interrupt handler\n");
+ return (ENXIO);
+ }
+ }
+
desc.pdata = sc->pdata;
desc.dev = dev;
- desc.dev_type = CORESIGHT_TMC;
+
+ reg = bus_read_4(sc->res[0], TMC_DEVID);
+ reg &= DEVID_CONFIGTYPE_M;
+ if (reg == DEVID_CONFIGTYPE_ETR)
+ desc.dev_type = CORESIGHT_TMC_ETR;
+ else
+ desc.dev_type = CORESIGHT_TMC_ETF;
+
coresight_register(&desc);
return (0);
@@ -340,8 +593,11 @@
/* Coresight interface */
DEVMETHOD(coresight_init, tmc_init),
- DEVMETHOD(coresight_enable, tmc_enable),
- DEVMETHOD(coresight_disable, tmc_disable),
+ DEVMETHOD(coresight_setup, tmc_setup),
+ DEVMETHOD(coresight_configure, tmc_configure),
+ DEVMETHOD(coresight_start, tmc_start),
+ DEVMETHOD(coresight_stop, tmc_stop),
+ DEVMETHOD(coresight_dump, tmc_dump),
DEVMETHOD(coresight_read, tmc_read),
DEVMETHOD_END
};
Index: sys/arm64/coresight/coresight_tmc_fdt.c
===================================================================
--- sys/arm64/coresight/coresight_tmc_fdt.c
+++ sys/arm64/coresight/coresight_tmc_fdt.c
@@ -71,10 +71,20 @@
tmc_fdt_attach(device_t dev)
{
struct tmc_softc *sc;
+ phandle_t node;
+ ssize_t len;
sc = device_get_softc(dev);
sc->pdata = coresight_fdt_get_platform_data(dev);
+ node = ofw_bus_get_node(dev);
+
+ len = OF_getproplen(node, "arm,scatter-gather");
+ if (len >= 0)
+ sc->scatter_gather = true;
+ else
+ sc->scatter_gather = false;
+
return (tmc_attach(dev));
}
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
+arm64/coresight/coresight_acpi.c optional hwt acpi
+arm64/coresight/coresight_fdt.c optional hwt fdt
+arm64/coresight/coresight_if.m optional hwt
+arm64/coresight/coresight_cmd.c optional hwt
+arm64/coresight/coresight_cpu_debug.c optional hwt fdt
+arm64/coresight/coresight_etm4x.c optional hwt
+arm64/coresight/coresight_etm4x_acpi.c optional hwt acpi
+arm64/coresight/coresight_etm4x_fdt.c optional hwt fdt
+arm64/coresight/coresight_funnel.c optional hwt
+arm64/coresight/coresight_funnel_acpi.c optional hwt acpi
+arm64/coresight/coresight_funnel_fdt.c optional hwt fdt
+arm64/coresight/coresight_replicator.c optional hwt
+arm64/coresight/coresight_replicator_acpi.c optional hwt acpi
+arm64/coresight/coresight_replicator_fdt.c optional hwt fdt
+arm64/coresight/coresight_tmc.c optional hwt
+arm64/coresight/coresight_tmc_acpi.c optional hwt acpi
+arm64/coresight/coresight_tmc_fdt.c optional hwt 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";