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/param.h>
32 #include <sys/systm.h>
33 #include <sys/bus.h>
34 #include <sys/rman.h>
35 #include <sys/kernel.h>
36 #include <sys/module.h>
37 #include <machine/bus.h>
38
39 #include <arm64/coresight/coresight.h>
40
41 #include "coresight_if.h"
42
43 extern struct coresight_device_list cs_devs;
44
45 static struct coresight_device *
coresight_next_device(struct coresight_device * cs_dev,struct coresight_event * event)46 coresight_next_device(struct coresight_device *cs_dev,
47 struct coresight_event *event)
48 {
49 struct coresight_device *out;
50 struct endpoint *out_endp;
51 struct endpoint *endp;
52
53 TAILQ_FOREACH(endp, &cs_dev->pdata->endpoints, link) {
54 if (endp->input != 0)
55 continue;
56
57 out = coresight_get_output_device(endp, &out_endp);
58 if (out != NULL) {
59 if (LIST_EMPTY(&event->endplist)) {
60 /* Add source device */
61 endp->cs_dev = cs_dev;
62 LIST_INSERT_HEAD(&event->endplist, endp,
63 endplink);
64 }
65
66 /* Add output device */
67 if (bootverbose)
68 printf("Adding device %s to the chain\n",
69 device_get_nameunit(out->dev));
70 out_endp->cs_dev = out;
71 LIST_INSERT_HEAD(&event->endplist, out_endp, endplink);
72
73 return (out);
74 }
75 }
76
77 return (NULL);
78 }
79
80 static int
coresight_build_list(struct coresight_device * cs_dev,struct coresight_event * event)81 coresight_build_list(struct coresight_device *cs_dev,
82 struct coresight_event *event)
83 {
84 struct coresight_device *out;
85
86 out = cs_dev;
87 while (out != NULL)
88 out = coresight_next_device(out, event);
89
90 return (0);
91 }
92
93 int
coresight_init_event(int cpu,struct coresight_event * event)94 coresight_init_event(int cpu, struct coresight_event *event)
95 {
96 struct coresight_device *cs_dev;
97 struct endpoint *endp;
98
99 /* Start building path from source device */
100 TAILQ_FOREACH(cs_dev, &cs_devs, link) {
101 if (cs_dev->dev_type == event->src &&
102 cs_dev->pdata->cpu == cpu) {
103 LIST_INIT(&event->endplist);
104 coresight_build_list(cs_dev, event);
105 break;
106 }
107 }
108
109 /* Ensure Coresight is initialized for the CPU */
110 TAILQ_FOREACH(cs_dev, &cs_devs, link) {
111 if (cs_dev->dev_type == CORESIGHT_CPU_DEBUG &&
112 cs_dev->pdata->cpu == cpu)
113 CORESIGHT_INIT(cs_dev->dev);
114 }
115
116 /* Init all devices in the path */
117 LIST_FOREACH(endp, &event->endplist, endplink) {
118 cs_dev = endp->cs_dev;
119 CORESIGHT_INIT(cs_dev->dev);
120 }
121
122 return (0);
123 }
124
125 void
coresight_enable(int cpu,struct coresight_event * event)126 coresight_enable(int cpu, struct coresight_event *event)
127 {
128 struct coresight_device *cs_dev;
129 struct endpoint *endp;
130
131 LIST_FOREACH(endp, &event->endplist, endplink) {
132 cs_dev = endp->cs_dev;
133 CORESIGHT_ENABLE(cs_dev->dev, endp, event);
134 }
135 }
136
137 void
coresight_disable(int cpu,struct coresight_event * event)138 coresight_disable(int cpu, struct coresight_event *event)
139 {
140 struct coresight_device *cs_dev;
141 struct endpoint *endp;
142
143 LIST_FOREACH(endp, &event->endplist, endplink) {
144 cs_dev = endp->cs_dev;
145 CORESIGHT_DISABLE(cs_dev->dev, endp, event);
146 }
147 }
148
149 void
coresight_read(int cpu,struct coresight_event * event)150 coresight_read(int cpu, struct coresight_event *event)
151 {
152 struct endpoint *endp;
153
154 LIST_FOREACH(endp, &event->endplist, endplink)
155 CORESIGHT_READ(endp->cs_dev->dev, endp, event);
156 }
157