xref: /freebsd/sys/arm64/coresight/coresight_etm4x.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
1b1670691SRuslan Bukin /*-
2c9ea007cSRuslan Bukin  * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
3b1670691SRuslan Bukin  * All rights reserved.
4b1670691SRuslan Bukin  *
5b1670691SRuslan Bukin  * This software was developed by BAE Systems, the University of Cambridge
6b1670691SRuslan Bukin  * Computer Laboratory, and Memorial University under DARPA/AFRL contract
7b1670691SRuslan Bukin  * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing
8b1670691SRuslan Bukin  * (TC) research program.
9b1670691SRuslan Bukin  *
10b1670691SRuslan Bukin  * Redistribution and use in source and binary forms, with or without
11b1670691SRuslan Bukin  * modification, are permitted provided that the following conditions
12b1670691SRuslan Bukin  * are met:
13b1670691SRuslan Bukin  * 1. Redistributions of source code must retain the above copyright
14b1670691SRuslan Bukin  *    notice, this list of conditions and the following disclaimer.
15b1670691SRuslan Bukin  * 2. Redistributions in binary form must reproduce the above copyright
16b1670691SRuslan Bukin  *    notice, this list of conditions and the following disclaimer in the
17b1670691SRuslan Bukin  *    documentation and/or other materials provided with the distribution.
18b1670691SRuslan Bukin  *
19b1670691SRuslan Bukin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20b1670691SRuslan Bukin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21b1670691SRuslan Bukin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22b1670691SRuslan Bukin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23b1670691SRuslan Bukin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24b1670691SRuslan Bukin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25b1670691SRuslan Bukin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26b1670691SRuslan Bukin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27b1670691SRuslan Bukin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28b1670691SRuslan Bukin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29b1670691SRuslan Bukin  * SUCH DAMAGE.
30b1670691SRuslan Bukin  */
31b1670691SRuslan Bukin 
32b1670691SRuslan Bukin #include <sys/param.h>
33b1670691SRuslan Bukin #include <sys/systm.h>
34b1670691SRuslan Bukin #include <sys/bus.h>
35b1670691SRuslan Bukin #include <sys/rman.h>
36b1670691SRuslan Bukin #include <sys/kernel.h>
37b1670691SRuslan Bukin #include <sys/module.h>
38b1670691SRuslan Bukin #include <machine/bus.h>
39b1670691SRuslan Bukin 
40b1670691SRuslan Bukin #include <arm64/coresight/coresight.h>
41b1670691SRuslan Bukin #include <arm64/coresight/coresight_etm4x.h>
42b1670691SRuslan Bukin 
43b1670691SRuslan Bukin #include "coresight_if.h"
44b1670691SRuslan Bukin 
45b1670691SRuslan Bukin #define	ETM_DEBUG
46b1670691SRuslan Bukin #undef ETM_DEBUG
47b1670691SRuslan Bukin 
48b1670691SRuslan Bukin #ifdef ETM_DEBUG
49b1670691SRuslan Bukin #define	dprintf(fmt, ...)	printf(fmt, ##__VA_ARGS__)
50b1670691SRuslan Bukin #else
51b1670691SRuslan Bukin #define	dprintf(fmt, ...)
52b1670691SRuslan Bukin #endif
53b1670691SRuslan Bukin 
54b1670691SRuslan Bukin /*
55b1670691SRuslan Bukin  * Typical trace flow:
56b1670691SRuslan Bukin  *
57b1670691SRuslan Bukin  * CPU0 -> ETM0 -> funnel1 -> funnel0 -> ETF -> replicator -> ETR -> DRAM
58b1670691SRuslan Bukin  * CPU1 -> ETM1 -> funnel1 -^
59b1670691SRuslan Bukin  * CPU2 -> ETM2 -> funnel1 -^
60b1670691SRuslan Bukin  * CPU3 -> ETM3 -> funnel1 -^
61b1670691SRuslan Bukin  */
62b1670691SRuslan Bukin 
63b1670691SRuslan Bukin static struct resource_spec etm_spec[] = {
64b1670691SRuslan Bukin 	{ SYS_RES_MEMORY,	0,	RF_ACTIVE },
65b1670691SRuslan Bukin 	{ -1, 0 }
66b1670691SRuslan Bukin };
67b1670691SRuslan Bukin 
68b1670691SRuslan Bukin static int
etm_prepare(device_t dev,struct coresight_event * event)69b1670691SRuslan Bukin etm_prepare(device_t dev, struct coresight_event *event)
70b1670691SRuslan Bukin {
71b1670691SRuslan Bukin 	struct etm_softc *sc;
72b1670691SRuslan Bukin 	uint32_t reg;
73b1670691SRuslan Bukin 	int i;
74b1670691SRuslan Bukin 
75b1670691SRuslan Bukin 	sc = device_get_softc(dev);
76b1670691SRuslan Bukin 
77b1670691SRuslan Bukin 	/* Configure ETM */
78b1670691SRuslan Bukin 
79b1670691SRuslan Bukin 	/*
80b1670691SRuslan Bukin 	 * Enable the return stack, global timestamping,
81b1670691SRuslan Bukin 	 * Context ID, and Virtual context identifier tracing.
82b1670691SRuslan Bukin 	 */
83b1670691SRuslan Bukin 	reg = TRCCONFIGR_RS | TRCCONFIGR_TS;
84b1670691SRuslan Bukin 	reg |= TRCCONFIGR_CID | TRCCONFIGR_VMID;
85b1670691SRuslan Bukin 	reg |= TRCCONFIGR_INSTP0_LDRSTR;
86b1670691SRuslan Bukin 	reg |= TRCCONFIGR_COND_ALL;
87b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCCONFIGR, reg);
88b1670691SRuslan Bukin 
89b1670691SRuslan Bukin 	/* Disable all event tracing. */
90b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCEVENTCTL0R, 0);
91b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCEVENTCTL1R, 0);
92b1670691SRuslan Bukin 
93b1670691SRuslan Bukin 	/* Disable stalling, if implemented. */
94b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCSTALLCTLR, 0);
95b1670691SRuslan Bukin 
96b1670691SRuslan Bukin 	/* Enable trace synchronization every 4096 bytes of trace. */
97b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCSYNCPR, TRCSYNCPR_4K);
98b1670691SRuslan Bukin 
99b1670691SRuslan Bukin 	/* Set a value for the trace ID */
100b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCTRACEIDR, event->etm.trace_id);
101b1670691SRuslan Bukin 
102b1670691SRuslan Bukin 	/*
103b1670691SRuslan Bukin 	 * Disable the timestamp event. The trace unit still generates
104b1670691SRuslan Bukin 	 * timestamps due to other reasons such as trace synchronization.
105b1670691SRuslan Bukin 	 */
106b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCTSCTLR, 0);
107b1670691SRuslan Bukin 
108b1670691SRuslan Bukin 	/*
109b1670691SRuslan Bukin 	 * Enable ViewInst to trace everything, with the start/stop
110b1670691SRuslan Bukin 	 * logic started.
111b1670691SRuslan Bukin 	 */
112b1670691SRuslan Bukin 	reg = TRCVICTLR_SSSTATUS;
113b1670691SRuslan Bukin 
114b1670691SRuslan Bukin 	/* The number of the single resource used to activate the event. */
115b1670691SRuslan Bukin 	reg |= (1 << EVENT_SEL_S);
116b1670691SRuslan Bukin 
117b1670691SRuslan Bukin 	if (event->excp_level > 2)
118b1670691SRuslan Bukin 		return (-1);
119b1670691SRuslan Bukin 
120b1670691SRuslan Bukin 	reg |= TRCVICTLR_EXLEVEL_NS_M;
121b1670691SRuslan Bukin 	reg &= ~TRCVICTLR_EXLEVEL_NS(event->excp_level);
122b1670691SRuslan Bukin 	reg |= TRCVICTLR_EXLEVEL_S_M;
123b1670691SRuslan Bukin 	reg &= ~TRCVICTLR_EXLEVEL_S(event->excp_level);
124b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCVICTLR, reg);
125b1670691SRuslan Bukin 
126b1670691SRuslan Bukin 	for (i = 0; i < event->naddr * 2; i++) {
127b1670691SRuslan Bukin 		dprintf("configure range %d, address %lx\n",
128b1670691SRuslan Bukin 		    i, event->addr[i]);
129b1670691SRuslan Bukin 		bus_write_8(sc->res, TRCACVR(i), event->addr[i]);
130b1670691SRuslan Bukin 
131b1670691SRuslan Bukin 		reg = 0;
132b1670691SRuslan Bukin 		/* Secure state */
133b1670691SRuslan Bukin 		reg |= TRCACATR_EXLEVEL_S_M;
134b1670691SRuslan Bukin 		reg &= ~TRCACATR_EXLEVEL_S(event->excp_level);
135b1670691SRuslan Bukin 		/* Non-secure state */
136b1670691SRuslan Bukin 		reg |= TRCACATR_EXLEVEL_NS_M;
137b1670691SRuslan Bukin 		reg &= ~TRCACATR_EXLEVEL_NS(event->excp_level);
138b1670691SRuslan Bukin 		bus_write_4(sc->res, TRCACATR(i), reg);
139b1670691SRuslan Bukin 
140b1670691SRuslan Bukin 		/* Address range is included */
141b1670691SRuslan Bukin 		reg = bus_read_4(sc->res, TRCVIIECTLR);
142b1670691SRuslan Bukin 		reg |= (1 << (TRCVIIECTLR_INCLUDE_S + i / 2));
143b1670691SRuslan Bukin 		bus_write_4(sc->res, TRCVIIECTLR, reg);
144b1670691SRuslan Bukin 	}
145b1670691SRuslan Bukin 
146b1670691SRuslan Bukin 	/* No address filtering for ViewData. */
147b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCVDARCCTLR, 0);
148b1670691SRuslan Bukin 
149b1670691SRuslan Bukin 	/* Clear the STATUS bit to zero */
150b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCSSCSR(0), 0);
151b1670691SRuslan Bukin 
152b1670691SRuslan Bukin 	if (event->naddr == 0) {
153b1670691SRuslan Bukin 		/* No address range filtering for ViewInst. */
154b1670691SRuslan Bukin 		bus_write_4(sc->res, TRCVIIECTLR, 0);
155b1670691SRuslan Bukin 	}
156b1670691SRuslan Bukin 
157b1670691SRuslan Bukin 	/* No start or stop points for ViewInst. */
158b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCVISSCTLR, 0);
159b1670691SRuslan Bukin 
160b1670691SRuslan Bukin 	/* Disable ViewData */
161b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCVDCTLR, 0);
162b1670691SRuslan Bukin 
163b1670691SRuslan Bukin 	/* No address filtering for ViewData. */
164b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCVDSACCTLR, 0);
165b1670691SRuslan Bukin 
166b1670691SRuslan Bukin 	return (0);
167b1670691SRuslan Bukin }
168b1670691SRuslan Bukin 
169b1670691SRuslan Bukin static int
etm_init(device_t dev)170b1670691SRuslan Bukin etm_init(device_t dev)
171b1670691SRuslan Bukin {
172b1670691SRuslan Bukin 	struct etm_softc *sc;
173*67f6cad3SJohn Baldwin 	uint32_t reg __unused;
174b1670691SRuslan Bukin 
175b1670691SRuslan Bukin 	sc = device_get_softc(dev);
176b1670691SRuslan Bukin 
177b1670691SRuslan Bukin 	/* Unlocking Coresight */
178b1670691SRuslan Bukin 	bus_write_4(sc->res, CORESIGHT_LAR, CORESIGHT_UNLOCK);
179b1670691SRuslan Bukin 
180b1670691SRuslan Bukin 	/* Unlocking ETM */
181b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCOSLAR, 0);
182b1670691SRuslan Bukin 
183b1670691SRuslan Bukin 	reg = bus_read_4(sc->res, TRCIDR(1));
184b1670691SRuslan Bukin 	dprintf("ETM Version: %d.%d\n",
185b1670691SRuslan Bukin 	    (reg & TRCIDR1_TRCARCHMAJ_M) >> TRCIDR1_TRCARCHMAJ_S,
186b1670691SRuslan Bukin 	    (reg & TRCIDR1_TRCARCHMIN_M) >> TRCIDR1_TRCARCHMIN_S);
187b1670691SRuslan Bukin 
188b1670691SRuslan Bukin 	return (0);
189b1670691SRuslan Bukin }
190b1670691SRuslan Bukin 
191b1670691SRuslan Bukin static int
etm_enable(device_t dev,struct endpoint * endp,struct coresight_event * event)192b1670691SRuslan Bukin etm_enable(device_t dev, struct endpoint *endp,
193b1670691SRuslan Bukin     struct coresight_event *event)
194b1670691SRuslan Bukin {
195b1670691SRuslan Bukin 	struct etm_softc *sc;
196b1670691SRuslan Bukin 	uint32_t reg;
197b1670691SRuslan Bukin 
198b1670691SRuslan Bukin 	sc = device_get_softc(dev);
199b1670691SRuslan Bukin 
200b1670691SRuslan Bukin 	etm_prepare(dev, event);
201b1670691SRuslan Bukin 
202b1670691SRuslan Bukin 	/* Enable the trace unit */
203b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCPRGCTLR, TRCPRGCTLR_EN);
204b1670691SRuslan Bukin 
205b1670691SRuslan Bukin 	/* Wait for an IDLE bit to be LOW */
206b1670691SRuslan Bukin 	do {
207b1670691SRuslan Bukin 		reg = bus_read_4(sc->res, TRCSTATR);
208b1670691SRuslan Bukin 	} while ((reg & TRCSTATR_IDLE) == 1);
209b1670691SRuslan Bukin 
210b1670691SRuslan Bukin 	if ((bus_read_4(sc->res, TRCPRGCTLR) & TRCPRGCTLR_EN) == 0)
211b1670691SRuslan Bukin 		panic("etm is not enabled\n");
212b1670691SRuslan Bukin 
213b1670691SRuslan Bukin 	return (0);
214b1670691SRuslan Bukin }
215b1670691SRuslan Bukin 
216b1670691SRuslan Bukin static void
etm_disable(device_t dev,struct endpoint * endp,struct coresight_event * event)217b1670691SRuslan Bukin etm_disable(device_t dev, struct endpoint *endp,
218b1670691SRuslan Bukin     struct coresight_event *event)
219b1670691SRuslan Bukin {
220b1670691SRuslan Bukin 	struct etm_softc *sc;
221b1670691SRuslan Bukin 	uint32_t reg;
222b1670691SRuslan Bukin 
223b1670691SRuslan Bukin 	sc = device_get_softc(dev);
224b1670691SRuslan Bukin 
225b1670691SRuslan Bukin 	/* Disable the trace unit */
226b1670691SRuslan Bukin 	bus_write_4(sc->res, TRCPRGCTLR, 0);
227b1670691SRuslan Bukin 
228b1670691SRuslan Bukin 	/* Wait for an IDLE bit */
229b1670691SRuslan Bukin 	do {
230b1670691SRuslan Bukin 		reg = bus_read_4(sc->res, TRCSTATR);
231b1670691SRuslan Bukin 	} while ((reg & TRCSTATR_IDLE) == 0);
232b1670691SRuslan Bukin }
233b1670691SRuslan Bukin 
234c9ea007cSRuslan Bukin int
etm_attach(device_t dev)235b1670691SRuslan Bukin etm_attach(device_t dev)
236b1670691SRuslan Bukin {
237b1670691SRuslan Bukin 	struct coresight_desc desc;
238b1670691SRuslan Bukin 	struct etm_softc *sc;
239b1670691SRuslan Bukin 
240b1670691SRuslan Bukin 	sc = device_get_softc(dev);
241b1670691SRuslan Bukin 
242b1670691SRuslan Bukin 	if (bus_alloc_resources(dev, etm_spec, &sc->res) != 0) {
243b1670691SRuslan Bukin 		device_printf(dev, "cannot allocate resources for device\n");
244b1670691SRuslan Bukin 		return (ENXIO);
245b1670691SRuslan Bukin 	}
246b1670691SRuslan Bukin 
247b1670691SRuslan Bukin 	desc.pdata = sc->pdata;
248b1670691SRuslan Bukin 	desc.dev = dev;
249b1670691SRuslan Bukin 	desc.dev_type = CORESIGHT_ETMV4;
250b1670691SRuslan Bukin 	coresight_register(&desc);
251b1670691SRuslan Bukin 
252b1670691SRuslan Bukin 	return (0);
253b1670691SRuslan Bukin }
254b1670691SRuslan Bukin 
255b1670691SRuslan Bukin static device_method_t etm_methods[] = {
256b1670691SRuslan Bukin 	/* Coresight interface */
257b1670691SRuslan Bukin 	DEVMETHOD(coresight_init,	etm_init),
258b1670691SRuslan Bukin 	DEVMETHOD(coresight_enable,	etm_enable),
259b1670691SRuslan Bukin 	DEVMETHOD(coresight_disable,	etm_disable),
260b1670691SRuslan Bukin 	DEVMETHOD_END
261b1670691SRuslan Bukin };
262b1670691SRuslan Bukin 
263b6f7bae4SRuslan Bukin DEFINE_CLASS_0(etm, etm_driver, etm_methods, sizeof(struct etm_softc));
264