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 *
coresight_next_device(struct coresight_device * cs_dev,struct coresight_event * event)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
coresight_build_list(struct coresight_device * cs_dev,struct coresight_event * event)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
coresight_init_event(int cpu,struct coresight_event * event)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
coresight_enable(int cpu,struct coresight_event * event)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
coresight_disable(int cpu,struct coresight_event * event)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
coresight_read(int cpu,struct coresight_event * event)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