xref: /freebsd/sys/arm64/coresight/coresight_cmd.c (revision 315ee00f)
1 /*-
2  * Copyright (c) 2018-2020 Ruslan Bukin <br@bsdpad.com>
3  * All rights reserved.
4  *
5  * This software was developed by SRI International and the University of
6  * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
7  * ("CTSRD"), as part of the DARPA CRASH research programme.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/cdefs.h>
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/bus.h>
35 #include <sys/rman.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <machine/bus.h>
39 
40 #include <arm64/coresight/coresight.h>
41 
42 #include "coresight_if.h"
43 
44 extern struct coresight_device_list cs_devs;
45 
46 static struct coresight_device *
47 coresight_next_device(struct coresight_device *cs_dev,
48     struct coresight_event *event)
49 {
50 	struct coresight_device *out;
51 	struct endpoint *out_endp;
52 	struct endpoint *endp;
53 
54 	TAILQ_FOREACH(endp, &cs_dev->pdata->endpoints, link) {
55 		if (endp->input != 0)
56 			continue;
57 
58 		out = coresight_get_output_device(endp, &out_endp);
59 		if (out != NULL) {
60 			if (LIST_EMPTY(&event->endplist)) {
61 				/* Add source device */
62 				endp->cs_dev = cs_dev;
63 				LIST_INSERT_HEAD(&event->endplist, endp,
64 				    endplink);
65 			}
66 
67 			/* Add output device */
68 			if (bootverbose)
69 				printf("Adding device %s to the chain\n",
70 				    device_get_nameunit(out->dev));
71 			out_endp->cs_dev = out;
72 			LIST_INSERT_HEAD(&event->endplist, out_endp, endplink);
73 
74 			return (out);
75 		}
76 	}
77 
78 	return (NULL);
79 }
80 
81 static int
82 coresight_build_list(struct coresight_device *cs_dev,
83     struct coresight_event *event)
84 {
85 	struct coresight_device *out;
86 
87 	out = cs_dev;
88 	while (out != NULL)
89 		out = coresight_next_device(out, event);
90 
91 	return (0);
92 }
93 
94 int
95 coresight_init_event(int cpu, struct coresight_event *event)
96 {
97 	struct coresight_device *cs_dev;
98 	struct endpoint *endp;
99 
100 	/* Start building path from source device */
101 	TAILQ_FOREACH(cs_dev, &cs_devs, link) {
102 		if (cs_dev->dev_type == event->src &&
103 		    cs_dev->pdata->cpu == cpu) {
104 			LIST_INIT(&event->endplist);
105 			coresight_build_list(cs_dev, event);
106 			break;
107 		}
108 	}
109 
110 	/* Ensure Coresight is initialized for the CPU */
111 	TAILQ_FOREACH(cs_dev, &cs_devs, link) {
112 		if (cs_dev->dev_type == CORESIGHT_CPU_DEBUG &&
113 		    cs_dev->pdata->cpu == cpu)
114 			CORESIGHT_INIT(cs_dev->dev);
115 	}
116 
117 	/* Init all devices in the path */
118 	LIST_FOREACH(endp, &event->endplist, endplink) {
119 		cs_dev = endp->cs_dev;
120 		CORESIGHT_INIT(cs_dev->dev);
121 	}
122 
123 	return (0);
124 }
125 
126 void
127 coresight_enable(int cpu, struct coresight_event *event)
128 {
129 	struct coresight_device *cs_dev;
130 	struct endpoint *endp;
131 
132 	LIST_FOREACH(endp, &event->endplist, endplink) {
133 		cs_dev = endp->cs_dev;
134 		CORESIGHT_ENABLE(cs_dev->dev, endp, event);
135 	}
136 }
137 
138 void
139 coresight_disable(int cpu, struct coresight_event *event)
140 {
141 	struct coresight_device *cs_dev;
142 	struct endpoint *endp;
143 
144 	LIST_FOREACH(endp, &event->endplist, endplink) {
145 		cs_dev = endp->cs_dev;
146 		CORESIGHT_DISABLE(cs_dev->dev, endp, event);
147 	}
148 }
149 
150 void
151 coresight_read(int cpu, struct coresight_event *event)
152 {
153 	struct endpoint *endp;
154 
155 	LIST_FOREACH(endp, &event->endplist, endplink)
156 		CORESIGHT_READ(endp->cs_dev->dev, endp, event);
157 }
158