xref: /openbsd-src/sys/arch/arm64/dev/rtkit.c (revision 25c4e8bd056e974b28f4a0ffd39d76c190a56013)
1 /*	$OpenBSD: rtkit.c,v 1.4 2022/06/12 16:00:12 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/device.h>
21 #include <sys/malloc.h>
22 
23 #include <machine/bus.h>
24 #include <machine/fdt.h>
25 
26 #include <dev/ofw/openfirm.h>
27 #include <dev/ofw/ofw_misc.h>
28 #include <dev/ofw/fdt.h>
29 
30 #include <arm64/dev/aplmbox.h>
31 #include <arm64/dev/rtkit.h>
32 
33 #define RTKIT_EP_MGMT			0
34 #define RTKIT_EP_CRASHLOG		1
35 #define RTKIT_EP_SYSLOG			2
36 #define RTKIT_EP_DEBUG			3
37 #define RTKIT_EP_IOREPORT		4
38 
39 #define RTKIT_MGMT_TYPE(x)		(((x) >> 52) & 0xff)
40 #define RTKIT_MGMT_TYPE_SHIFT		52
41 
42 #define RTKIT_MGMT_PWR_STATE(x)		(((x) >> 0) & 0xff)
43 #define RTKIT_MGMT_PWR_STATE_ON		0x20
44 
45 #define RTKIT_MGMT_HELLO		1
46 #define RTKIT_MGMT_HELLO_ACK		2
47 #define RTKIT_MGMT_STARTEP		5
48 #define RTKIT_MGMT_IOP_PWR_STATE	6
49 #define RTKIT_MGMT_IOP_PWR_STATE_ACK	7
50 #define RTKIT_MGMT_EPMAP		8
51 
52 #define RTKIT_MGMT_HELLO_MINVER(x)	(((x) >> 0) & 0xffff)
53 #define RTKIT_MGMT_HELLO_MINVER_SHIFT	0
54 #define RTKIT_MGMT_HELLO_MAXVER(x)	(((x) >> 16) & 0xffff)
55 #define RTKIT_MGMT_HELLO_MAXVER_SHIFT	16
56 
57 #define RTKIT_MGMT_STARTEP_EP_SHIFT	32
58 #define RTKIT_MGMT_STARTEP_START	(1ULL << 1)
59 
60 #define RTKIT_MGMT_EPMAP_LAST		(1ULL << 51)
61 #define RTKIT_MGMT_EPMAP_BASE(x)	(((x) >> 32) & 0x7)
62 #define RTKIT_MGMT_EPMAP_BASE_SHIFT	32
63 #define RTKIT_MGMT_EPMAP_BITMAP(x)	(((x) >> 0) & 0xffffffff)
64 #define RTKIT_MGMT_EPMAP_MORE		(1ULL << 0)
65 
66 #define RTKIT_BUFFER_REQUEST		1
67 #define RTKIT_BUFFER_ADDR(x)		(((x) >> 0) & 0xfffffffffff)
68 #define RTKIT_BUFFER_SIZE(x)		(((x) >> 44) & 0xff)
69 #define RTKIT_BUFFER_SIZE_SHIFT		44
70 
71 #define RTKIT_IOREPORT_UNKNOWN1		8
72 #define RTKIT_IOREPORT_UNKNOWN2		12
73 
74 /* Versions we support. */
75 #define RTKIT_MINVER			11
76 #define RTKIT_MAXVER			12
77 
78 struct rtkit_state {
79 	struct mbox_channel	*mc;
80 	struct rtkit		*rk;
81 	int			pwrstate;
82 	uint64_t		epmap;
83 	void			(*callback[32])(void *, uint64_t);
84 	void			*arg[32];
85 };
86 
87 int
88 rtkit_recv(struct mbox_channel *mc, struct aplmbox_msg *msg)
89 {
90 	int error, timo;
91 
92 	for (timo = 0; timo < 10000; timo++) {
93 		error = mbox_recv(mc, msg, sizeof(*msg));
94 		if (error == 0)
95 			break;
96 		delay(10);
97 	}
98 
99 	return error;
100 }
101 
102 int
103 rtkit_send(struct mbox_channel *mc, uint32_t endpoint,
104     uint64_t type, uint64_t data)
105 {
106 	struct aplmbox_msg msg;
107 
108 	msg.data0 = (type << RTKIT_MGMT_TYPE_SHIFT) | data;
109 	msg.data1 = endpoint;
110 	return mbox_send(mc, &msg, sizeof(msg));
111 }
112 
113 bus_addr_t
114 rtkit_alloc(struct rtkit *rk, bus_size_t size)
115 {
116 	bus_dma_segment_t seg;
117 	int nsegs;
118 
119 	if (bus_dmamem_alloc(rk->rk_dmat, size, 16384, 0,
120 	    &seg, 1, &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO))
121 		return (bus_addr_t)-1;
122 
123 	return seg.ds_addr;
124 }
125 
126 int
127 rtkit_start(struct rtkit_state *state, uint32_t endpoint)
128 {
129 	struct mbox_channel *mc = state->mc;
130 	uint64_t reply;
131 
132 	reply = ((uint64_t)endpoint << RTKIT_MGMT_STARTEP_EP_SHIFT);
133 	reply |= RTKIT_MGMT_STARTEP_START;
134 	return rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_STARTEP, reply);
135 }
136 
137 int
138 rtkit_handle_mgmt(struct rtkit_state *state, struct aplmbox_msg *msg)
139 {
140 	struct mbox_channel *mc = state->mc;
141 	uint64_t minver, maxver, ver;
142 	uint64_t base, bitmap, reply;
143 	uint32_t endpoint;
144 	int error;
145 
146 	switch (RTKIT_MGMT_TYPE(msg->data0)) {
147 	case RTKIT_MGMT_HELLO:
148 		minver = RTKIT_MGMT_HELLO_MINVER(msg->data0);
149 		maxver = RTKIT_MGMT_HELLO_MAXVER(msg->data0);
150 		if (minver > RTKIT_MAXVER) {
151 			printf("%s: unsupported minimum firmware version %lld\n",
152 			    __func__, minver);
153 			return EINVAL;
154 		}
155 		if (maxver < RTKIT_MINVER) {
156 			printf("%s: unsupported maximum firmware version %lld\n",
157 			    __func__, maxver);
158 			return EINVAL;
159 		}
160 		ver = min(RTKIT_MAXVER, maxver);
161 		error = rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_HELLO_ACK,
162 		    (ver << RTKIT_MGMT_HELLO_MINVER_SHIFT) |
163 		    (ver << RTKIT_MGMT_HELLO_MAXVER_SHIFT));
164 		if (error)
165 			return error;
166 		break;
167 
168 	case RTKIT_MGMT_IOP_PWR_STATE_ACK:
169 		state->pwrstate = RTKIT_MGMT_PWR_STATE(msg->data0);
170 		break;
171 
172 	case RTKIT_MGMT_EPMAP:
173 		base = RTKIT_MGMT_EPMAP_BASE(msg->data0);
174 		bitmap = RTKIT_MGMT_EPMAP_BITMAP(msg->data0);
175 		state->epmap |= (bitmap << (base * 32));
176 		reply = (base << RTKIT_MGMT_EPMAP_BASE_SHIFT);
177 		if (msg->data0 & RTKIT_MGMT_EPMAP_LAST)
178 			reply |= RTKIT_MGMT_EPMAP_LAST;
179 		else
180 			reply |= RTKIT_MGMT_EPMAP_MORE;
181 		error = rtkit_send(state->mc, RTKIT_EP_MGMT,
182 		    RTKIT_MGMT_EPMAP, reply);
183 		if (error)
184 			return error;
185 		if (msg->data0 & RTKIT_MGMT_EPMAP_LAST) {
186 			for (endpoint = 1; endpoint < 32; endpoint++) {
187 				if ((state->epmap & (1ULL << endpoint)) == 0)
188 					continue;
189 
190 				switch (endpoint) {
191 				case RTKIT_EP_CRASHLOG:
192 				case RTKIT_EP_SYSLOG:
193 				case RTKIT_EP_DEBUG:
194 				case RTKIT_EP_IOREPORT:
195 					error = rtkit_start(state, endpoint);
196 					if (error)
197 						return error;
198 					break;
199 				default:
200 					printf("%s: skipping endpoint %d\n",
201 					    __func__, endpoint);
202 					break;
203 				}
204 			}
205 		}
206 		break;
207 	default:
208 		printf("%s: unhandled management event 0x%016lld\n",
209 		    __func__, msg->data0);
210 		return EIO;
211 	}
212 
213 	return 0;
214 }
215 
216 int
217 rtkit_handle_crashlog(struct rtkit_state *state, struct aplmbox_msg *msg)
218 {
219 	struct mbox_channel *mc = state->mc;
220 	struct rtkit *rk = state->rk;
221 	bus_addr_t addr;
222 	bus_size_t size;
223 	int error;
224 
225 	switch (RTKIT_MGMT_TYPE(msg->data0)) {
226 	case RTKIT_BUFFER_REQUEST:
227 		addr = RTKIT_BUFFER_ADDR(msg->data0);
228 		size = RTKIT_BUFFER_SIZE(msg->data0);
229 		if (addr)
230 			break;
231 
232 		if (rk) {
233 			addr = rtkit_alloc(rk, size << PAGE_SHIFT);
234 			if (addr == (bus_addr_t)-1)
235 				return ENOMEM;
236 			error = rk->rk_map(rk->rk_cookie, addr,
237 			    size << PAGE_SHIFT);
238 			if (error)
239 				return error;
240 		}
241 
242 		error = rtkit_send(mc, RTKIT_EP_CRASHLOG, RTKIT_BUFFER_REQUEST,
243 		    (size << RTKIT_BUFFER_SIZE_SHIFT) | addr);
244 		if (error)
245 			return error;
246 		break;
247 	default:
248 		printf("%s: unhandled crashlog event 0x%016llx\n",
249 		    __func__, msg->data0);
250 		return EIO;
251 	}
252 
253 	return 0;
254 }
255 
256 int
257 rtkit_handle_ioreport(struct rtkit_state *state, struct aplmbox_msg *msg)
258 {
259 	struct mbox_channel *mc = state->mc;
260 	struct rtkit *rk = state->rk;
261 	bus_addr_t addr;
262 	bus_size_t size;
263 	int error;
264 
265 	switch (RTKIT_MGMT_TYPE(msg->data0)) {
266 	case RTKIT_BUFFER_REQUEST:
267 		addr = RTKIT_BUFFER_ADDR(msg->data0);
268 		size = RTKIT_BUFFER_SIZE(msg->data0);
269 		if (addr)
270 			break;
271 
272 		if (rk) {
273 			addr = rtkit_alloc(rk, size << PAGE_SHIFT);
274 			if (addr == (bus_addr_t)-1)
275 				return ENOMEM;
276 			error = rk->rk_map(rk->rk_cookie, addr,
277 			    size << PAGE_SHIFT);
278 			if (error)
279 				return error;
280 		}
281 
282 		error = rtkit_send(mc, RTKIT_EP_IOREPORT, RTKIT_BUFFER_REQUEST,
283 		    (size << RTKIT_BUFFER_SIZE_SHIFT) | addr);
284 		if (error)
285 			return error;
286 		break;
287 	case RTKIT_IOREPORT_UNKNOWN1:
288 	case RTKIT_IOREPORT_UNKNOWN2:
289 		/* These unknown events have to be acked to make progress. */
290 		error = rtkit_send(mc, RTKIT_EP_IOREPORT,
291 		    RTKIT_MGMT_TYPE(msg->data0), msg->data0);
292 		if (error)
293 			return error;
294 		break;
295 	default:
296 		printf("%s: unhandled ioreport event 0x%016llx\n",
297 		    __func__, msg->data0);
298 		return EIO;
299 	}
300 
301 	return 0;
302 }
303 
304 int
305 rtkit_poll(struct rtkit_state *state)
306 {
307 	struct mbox_channel *mc = state->mc;
308 	struct aplmbox_msg msg;
309 	void (*callback)(void *, uint64_t);
310 	void *arg;
311 	uint32_t endpoint;
312 	int error;
313 
314 	error = rtkit_recv(mc, &msg);
315 	if (error)
316 		return error;
317 
318 	endpoint = msg.data1;
319 	switch (endpoint) {
320 	case RTKIT_EP_MGMT:
321 		error = rtkit_handle_mgmt(state, &msg);
322 		if (error)
323 			return error;
324 		break;
325 	case RTKIT_EP_CRASHLOG:
326 		error = rtkit_handle_crashlog(state, &msg);
327 		if (error)
328 			return error;
329 		break;
330 	case RTKIT_EP_IOREPORT:
331 		error = rtkit_handle_ioreport(state, &msg);
332 		if (error)
333 			return error;
334 		break;
335 	default:
336 		if (endpoint >= 32 && endpoint < 64 &&
337 		    state->callback[endpoint - 32]) {
338 			callback = state->callback[endpoint - 32];
339 			arg = state->arg[endpoint - 32];
340 			callback(arg, msg.data0);
341 			break;
342 		}
343 
344 		printf("%s: unhandled endpoint %d\n", __func__, msg.data1);
345 		return EIO;
346 	}
347 
348 	return 0;
349 }
350 
351 void
352 rtkit_rx_callback(void *cookie)
353 {
354 	rtkit_poll(cookie);
355 }
356 
357 struct rtkit_state *
358 rtkit_init(int node, const char *name, struct rtkit *rk)
359 {
360 	struct rtkit_state *state;
361 	struct mbox_client client;
362 
363 	state = malloc(sizeof(*state), M_DEVBUF, M_WAITOK | M_ZERO);
364 	client.mc_rx_callback = rtkit_rx_callback;
365 	client.mc_rx_arg = state;
366 	state->mc = mbox_channel(node, name, &client);
367 	if (state->mc == NULL) {
368 		free(state, M_DEVBUF, sizeof(*state));
369 		return NULL;
370 	}
371 	state->rk = rk;
372 
373 	return state;
374 }
375 
376 int
377 rtkit_boot(struct rtkit_state *state)
378 {
379 	struct mbox_channel *mc = state->mc;
380 	int error;
381 
382 	/* Wake up! */
383 	error = rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_IOP_PWR_STATE,
384 	    RTKIT_MGMT_PWR_STATE_ON);
385 	if (error)
386 		return error;
387 
388 	while (state->pwrstate != RTKIT_MGMT_PWR_STATE_ON)
389 		rtkit_poll(state);
390 
391 	return 0;
392 }
393 
394 int
395 rtkit_start_endpoint(struct rtkit_state *state, uint32_t endpoint,
396     void (*callback)(void *, uint64_t), void *arg)
397 {
398 	if (endpoint < 32 || endpoint >= 64)
399 		return EINVAL;
400 
401 	if ((state->epmap & (1ULL << endpoint)) == 0)
402 		return EINVAL;
403 
404 	state->callback[endpoint - 32] = callback;
405 	state->arg[endpoint - 32] = arg;
406 	return rtkit_start(state, endpoint);
407 }
408 
409 int
410 rtkit_send_endpoint(struct rtkit_state *state, uint32_t endpoint,
411     uint64_t data)
412 {
413 	return rtkit_send(state->mc, endpoint, 0, data);
414 }
415