xref: /openbsd-src/sys/arch/arm64/dev/rtkit.c (revision 44aabc179b474a8312765241465fb752139a1bb1)
1 /*	$OpenBSD: rtkit.c,v 1.17 2024/10/29 21:19:25 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 #include <sys/task.h>
23 
24 #include <machine/bus.h>
25 #include <machine/fdt.h>
26 
27 #include <uvm/uvm_extern.h>
28 
29 #include <dev/ofw/openfirm.h>
30 #include <dev/ofw/ofw_misc.h>
31 #include <dev/ofw/fdt.h>
32 
33 #include <arm64/dev/aplmbox.h>
34 #include <arm64/dev/rtkit.h>
35 
36 #define RTKIT_EP_MGMT			0
37 #define RTKIT_EP_CRASHLOG		1
38 #define RTKIT_EP_SYSLOG			2
39 #define RTKIT_EP_DEBUG			3
40 #define RTKIT_EP_IOREPORT		4
41 #define RTKIT_EP_OSLOG			8
42 #define RTKIT_EP_UNKNOWN		10
43 
44 #define RTKIT_MGMT_TYPE(x)		(((x) >> 52) & 0xff)
45 #define RTKIT_MGMT_TYPE_SHIFT		52
46 
47 #define RTKIT_MGMT_PWR_STATE(x)		(((x) >> 0) & 0xffff)
48 
49 #define RTKIT_MGMT_HELLO		1
50 #define RTKIT_MGMT_HELLO_ACK		2
51 #define RTKIT_MGMT_STARTEP		5
52 #define RTKIT_MGMT_IOP_PWR_STATE	6
53 #define RTKIT_MGMT_IOP_PWR_STATE_ACK	7
54 #define RTKIT_MGMT_EPMAP		8
55 #define RTKIT_MGMT_AP_PWR_STATE		11
56 
57 #define RTKIT_MGMT_HELLO_MINVER(x)	(((x) >> 0) & 0xffff)
58 #define RTKIT_MGMT_HELLO_MINVER_SHIFT	0
59 #define RTKIT_MGMT_HELLO_MAXVER(x)	(((x) >> 16) & 0xffff)
60 #define RTKIT_MGMT_HELLO_MAXVER_SHIFT	16
61 
62 #define RTKIT_MGMT_STARTEP_EP_SHIFT	32
63 #define RTKIT_MGMT_STARTEP_START	(1ULL << 1)
64 
65 #define RTKIT_MGMT_EPMAP_LAST		(1ULL << 51)
66 #define RTKIT_MGMT_EPMAP_BASE(x)	(((x) >> 32) & 0x7)
67 #define RTKIT_MGMT_EPMAP_BASE_SHIFT	32
68 #define RTKIT_MGMT_EPMAP_BITMAP(x)	(((x) >> 0) & 0xffffffff)
69 #define RTKIT_MGMT_EPMAP_MORE		(1ULL << 0)
70 
71 #define RTKIT_BUFFER_REQUEST		1
72 #define RTKIT_BUFFER_ADDR(x)		(((x) >> 0) & 0xfffffffffff)
73 #define RTKIT_BUFFER_SIZE(x)		(((x) >> 44) & 0xff)
74 #define RTKIT_BUFFER_SIZE_SHIFT		44
75 
76 #define RTKIT_SYSLOG_LOG		5
77 #define RTKIT_SYSLOG_LOG_IDX(x)		(((x) >> 0) & 0xff)
78 #define RTKIT_SYSLOG_INIT		8
79 #define RTKIT_SYSLOG_INIT_N_ENTRIES(x)	(((x) >> 0) & 0xff)
80 #define RTKIT_SYSLOG_INIT_MSG_SIZE(x)	(((x) >> 24) & 0xff)
81 
82 #define RTKIT_IOREPORT_UNKNOWN1		8
83 #define RTKIT_IOREPORT_UNKNOWN2		12
84 
85 #define RTKIT_OSLOG_TYPE(x)		(((x) >> 56) & 0xff)
86 #define RTKIT_OSLOG_TYPE_SHIFT		(56 - RTKIT_MGMT_TYPE_SHIFT)
87 #define RTKIT_OSLOG_BUFFER_REQUEST	1
88 #define RTKIT_OSLOG_BUFFER_ADDR(x)	(((x) >> 0) & 0xfffffffff)
89 #define RTKIT_OSLOG_BUFFER_SIZE(x)	(((x) >> 36) & 0xfffff)
90 #define RTKIT_OSLOG_BUFFER_SIZE_SHIFT	36
91 #define RTKIT_OSLOG_UNKNOWN1		3
92 #define RTKIT_OSLOG_UNKNOWN2		4
93 #define RTKIT_OSLOG_UNKNOWN3		5
94 
95 /* Versions we support. */
96 #define RTKIT_MINVER			11
97 #define RTKIT_MAXVER			12
98 
99 struct rtkit_dmamem {
100 	bus_dmamap_t		rdm_map;
101 	bus_dma_segment_t	rdm_seg;
102 	size_t			rdm_size;
103 	caddr_t			rdm_kva;
104 };
105 
106 struct rtkit_state {
107 	struct mbox_channel	*mc;
108 	struct rtkit		*rk;
109 	int			flags;
110 	char			*crashlog;
111 	bus_addr_t		crashlog_addr;
112 	bus_size_t		crashlog_size;
113 	struct task		crashlog_task;
114 	char			*ioreport;
115 	bus_addr_t		ioreport_addr;
116 	bus_size_t		ioreport_size;
117 	struct task		ioreport_task;
118 	char			*oslog;
119 	bus_addr_t		oslog_addr;
120 	bus_size_t		oslog_size;
121 	struct task		oslog_task;
122 	char			*syslog;
123 	bus_addr_t		syslog_addr;
124 	bus_size_t		syslog_size;
125 	struct task		syslog_task;
126 	uint8_t			syslog_n_entries;
127 	uint8_t			syslog_msg_size;
128 	char			*syslog_msg;
129 	uint16_t		iop_pwrstate;
130 	uint16_t		ap_pwrstate;
131 	uint64_t		epmap;
132 	void			(*callback[32])(void *, uint64_t);
133 	void			*arg[32];
134 	struct rtkit_dmamem	dmamem[32];
135 	int			ndmamem;
136 };
137 
138 int
139 rtkit_recv(struct mbox_channel *mc, struct aplmbox_msg *msg)
140 {
141 	return mbox_recv(mc, msg, sizeof(*msg));
142 }
143 
144 int
145 rtkit_send(struct rtkit_state *state, uint32_t endpoint,
146     uint64_t type, uint64_t data)
147 {
148 	struct aplmbox_msg msg;
149 
150 	msg.data0 = (type << RTKIT_MGMT_TYPE_SHIFT) | data;
151 	msg.data1 = endpoint;
152 
153 	if (state->flags & RK_DEBUG) {
154 		printf("%s: 0x%016llx 0x%02x\n", __func__,
155 		    msg.data0, msg.data1);
156 	}
157 
158 	return mbox_send(state->mc, &msg, sizeof(msg));
159 }
160 
161 bus_addr_t
162 rtkit_alloc(struct rtkit_state *state, bus_size_t size, caddr_t *kvap)
163 {
164 	struct rtkit *rk = state->rk;
165 	bus_dma_segment_t seg;
166 	bus_dmamap_t map;
167 	caddr_t kva;
168 	int nsegs;
169 
170 	if (state->ndmamem >= nitems(state->dmamem))
171 		return (bus_addr_t)-1;
172 
173 	if (bus_dmamem_alloc(rk->rk_dmat, size, 16384, 0,
174 	    &seg, 1, &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO))
175 		return (bus_addr_t)-1;
176 
177 	if (bus_dmamem_map(rk->rk_dmat, &seg, 1, size,
178 	    &kva, BUS_DMA_WAITOK | BUS_DMA_COHERENT)) {
179 		bus_dmamem_free(rk->rk_dmat, &seg, 1);
180 		return (bus_addr_t)-1;
181 	}
182 
183 	if (bus_dmamap_create(rk->rk_dmat, size, 1, size, 0,
184 	    BUS_DMA_WAITOK, &map)) {
185 		bus_dmamem_unmap(rk->rk_dmat, kva, size);
186 		bus_dmamem_free(rk->rk_dmat, &seg, 1);
187 		return (bus_addr_t)-1;
188 	}
189 
190 	if (bus_dmamap_load_raw(rk->rk_dmat, map, &seg, 1, size,
191 	    BUS_DMA_WAITOK)) {
192 		bus_dmamap_destroy(rk->rk_dmat, map);
193 		bus_dmamem_unmap(rk->rk_dmat, kva, size);
194 		bus_dmamem_free(rk->rk_dmat, &seg, 1);
195 		return (bus_addr_t)-1;
196 	}
197 
198 	if (rk->rk_map) {
199 		if (rk->rk_map(rk->rk_cookie, seg.ds_addr, seg.ds_len)) {
200 			bus_dmamap_unload(rk->rk_dmat, map);
201 			bus_dmamap_destroy(rk->rk_dmat, map);
202 			bus_dmamem_unmap(rk->rk_dmat, kva, size);
203 			bus_dmamem_free(rk->rk_dmat, &seg, 1);
204 			return (bus_addr_t)-1;
205 		}
206 	}
207 
208 	state->dmamem[state->ndmamem].rdm_map = map;
209 	state->dmamem[state->ndmamem].rdm_seg = seg;
210 	state->dmamem[state->ndmamem].rdm_size = size;
211 	state->dmamem[state->ndmamem].rdm_kva = kva;
212 	state->ndmamem++;
213 
214 	*kvap = kva;
215 	return map->dm_segs[0].ds_addr;
216 }
217 
218 int
219 rtkit_start(struct rtkit_state *state, uint32_t endpoint)
220 {
221 	uint64_t reply;
222 
223 	reply = ((uint64_t)endpoint << RTKIT_MGMT_STARTEP_EP_SHIFT);
224 	reply |= RTKIT_MGMT_STARTEP_START;
225 	return rtkit_send(state, RTKIT_EP_MGMT, RTKIT_MGMT_STARTEP, reply);
226 }
227 
228 int
229 rtkit_handle_mgmt(struct rtkit_state *state, struct aplmbox_msg *msg)
230 {
231 	uint64_t minver, maxver, ver;
232 	uint64_t base, bitmap, reply;
233 	uint32_t endpoint;
234 	int error;
235 
236 	switch (RTKIT_MGMT_TYPE(msg->data0)) {
237 	case RTKIT_MGMT_HELLO:
238 		minver = RTKIT_MGMT_HELLO_MINVER(msg->data0);
239 		maxver = RTKIT_MGMT_HELLO_MAXVER(msg->data0);
240 		if (minver > RTKIT_MAXVER) {
241 			printf("%s: unsupported minimum firmware version %lld\n",
242 			    __func__, minver);
243 			return EINVAL;
244 		}
245 		if (maxver < RTKIT_MINVER) {
246 			printf("%s: unsupported maximum firmware version %lld\n",
247 			    __func__, maxver);
248 			return EINVAL;
249 		}
250 		ver = min(RTKIT_MAXVER, maxver);
251 		error = rtkit_send(state, RTKIT_EP_MGMT, RTKIT_MGMT_HELLO_ACK,
252 		    (ver << RTKIT_MGMT_HELLO_MINVER_SHIFT) |
253 		    (ver << RTKIT_MGMT_HELLO_MAXVER_SHIFT));
254 		if (error)
255 			return error;
256 		break;
257 	case RTKIT_MGMT_IOP_PWR_STATE_ACK:
258 		state->iop_pwrstate = RTKIT_MGMT_PWR_STATE(msg->data0);
259 		wakeup(&state->iop_pwrstate);
260 		break;
261 	case RTKIT_MGMT_AP_PWR_STATE:
262 		state->ap_pwrstate = RTKIT_MGMT_PWR_STATE(msg->data0);
263 		wakeup(&state->ap_pwrstate);
264 		break;
265 	case RTKIT_MGMT_EPMAP:
266 		base = RTKIT_MGMT_EPMAP_BASE(msg->data0);
267 		bitmap = RTKIT_MGMT_EPMAP_BITMAP(msg->data0);
268 		state->epmap |= (bitmap << (base * 32));
269 		reply = (base << RTKIT_MGMT_EPMAP_BASE_SHIFT);
270 		if (msg->data0 & RTKIT_MGMT_EPMAP_LAST)
271 			reply |= RTKIT_MGMT_EPMAP_LAST;
272 		else
273 			reply |= RTKIT_MGMT_EPMAP_MORE;
274 		error = rtkit_send(state, RTKIT_EP_MGMT,
275 		    RTKIT_MGMT_EPMAP, reply);
276 		if (error)
277 			return error;
278 		if (msg->data0 & RTKIT_MGMT_EPMAP_LAST) {
279 			for (endpoint = 1; endpoint < 32; endpoint++) {
280 				if ((state->epmap & (1ULL << endpoint)) == 0)
281 					continue;
282 
283 				switch (endpoint) {
284 				case RTKIT_EP_CRASHLOG:
285 				case RTKIT_EP_SYSLOG:
286 				case RTKIT_EP_DEBUG:
287 				case RTKIT_EP_IOREPORT:
288 				case RTKIT_EP_OSLOG:
289 					error = rtkit_start(state, endpoint);
290 					if (error)
291 						return error;
292 					break;
293 				case RTKIT_EP_UNKNOWN:
294 					break;
295 				default:
296 					printf("%s: skipping endpoint %d\n",
297 					    __func__, endpoint);
298 					break;
299 				}
300 			}
301 		}
302 		break;
303 	default:
304 		printf("%s: unhandled management event 0x%016lld\n",
305 		    __func__, msg->data0);
306 		break;
307 	}
308 
309 	return 0;
310 }
311 
312 struct rtkit_crashlog_header {
313 	uint32_t	fourcc;
314 	uint32_t	version;
315 	uint32_t	size;
316 	uint32_t	flags;
317 	uint8_t		unknown[16];
318 };
319 
320 struct rtkit_crashlog_mbx {
321 	uint64_t	msg1;
322 	uint64_t	msg0;
323 	uint32_t	timestamp;
324 	uint8_t		unknown[4];
325 };
326 
327 struct rtkit_crashlog_rg8 {
328 	uint64_t	unknown0;
329 	uint64_t	reg[31];
330 	uint64_t	sp;
331 	uint64_t	pc;
332 	uint64_t	psr;
333 	uint64_t	cpacr;
334 	uint64_t	fpsr;
335 	uint64_t	fpcr;
336 	uint64_t	fpreg[64];
337 	uint64_t	far;
338 	uint64_t	unknown1;
339 	uint64_t	esr;
340 	uint64_t	unknown2;
341 };
342 
343 #define RTKIT_FOURCC(s)	((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3])
344 
345 void
346 rtkit_crashlog_dump_str(char *buf, size_t size)
347 {
348 	char *end = buf + size - 1;
349 	char *newl;
350 	uint32_t idx;
351 
352 	if (size < 5)
353 		return;
354 
355 	idx = lemtoh32((uint32_t *)buf);
356 	buf += sizeof(uint32_t);
357 
358 	*end = 0;
359 	while (buf < end) {
360 		if (*buf == 0)
361 			return;
362 		newl = memchr(buf, '\n', buf - end);
363 		if (newl)
364 			*newl = 0;
365 		printf("RTKit Cstr %x: %s\n", idx, buf);
366 		if (!newl)
367 			return;
368 		buf = newl + 1;
369 	}
370 }
371 
372 void
373 rtkit_crashlog_dump_ver(char *buf, size_t size)
374 {
375 	char *end = buf + size - 1;
376 
377 	if (size < 17)
378 		return;
379 
380 	buf += 16;
381 
382 	*end = 0;
383 	printf("RTKit Cver %s\n", buf);
384 }
385 
386 void
387 rtkit_crashlog_dump_mbx(char *buf, size_t size)
388 {
389 	struct rtkit_crashlog_mbx mbx;
390 	char *end = buf + size;
391 
392 	buf += 28;
393 	size -= 28;
394 
395 	while (buf + sizeof(mbx) <= end) {
396 		memcpy(&mbx, buf, sizeof(mbx));
397 		printf("RTKit Cmbx: 0x%016llx 0x%016llx @0x%08x\n",
398 		    mbx.msg0, mbx.msg1, mbx.timestamp);
399 		buf += sizeof(mbx);
400 	}
401 }
402 
403 void
404 rtkit_crashlog_dump_rg8(char *buf, size_t size)
405 {
406 	struct rtkit_crashlog_rg8 rg8;
407 	int i;
408 
409 	if (size < sizeof(rg8))
410 		return;
411 
412 	memcpy(&rg8, buf, sizeof(rg8));
413 	printf("RTKit Crg8: psr %016llx\n", rg8.psr);
414 	printf("RTKit Crg8: pc  %016llx\n", rg8.pc);
415 	printf("RTKit Crg8: esr %016llx\n", rg8.esr);
416 	printf("RTKit Crg8: far %016llx\n", rg8.far);
417 	printf("RTKit Crg8: sp  %016llx\n", rg8.sp);
418 	for (i = 0; i < nitems(rg8.reg); i++)
419 		printf("RTKit Crg8: reg[%d] %016llx\n", i, rg8.reg[i]);
420 }
421 
422 void
423 rtkit_crashlog_dump(char *buf, size_t size)
424 {
425 	struct rtkit_crashlog_header hdr;
426 	size_t off;
427 
428 	if (size < sizeof(hdr))
429 		return;
430 
431 	memcpy(&hdr, buf, sizeof(hdr));
432 	if (letoh32(hdr.fourcc) != RTKIT_FOURCC("CLHE")) {
433 		printf("RTKit: Invalid header\n");
434 		return;
435 	}
436 
437 	if (letoh32(hdr.size) > size) {
438 		printf("RTKit: Invalid header size\n");
439 		return;
440 	}
441 
442 	off = sizeof(hdr);
443 	while (off < letoh32(hdr.size)) {
444 		uint32_t fourcc, size;
445 
446 		fourcc = lemtoh32((uint32_t *)(buf + off));
447 		size = lemtoh32((uint32_t *)(buf + off + 12));
448 		if (fourcc == RTKIT_FOURCC("CLHE"))
449 			break;
450 		if (fourcc == RTKIT_FOURCC("Cstr"))
451 			rtkit_crashlog_dump_str(buf + off + 16, size - 16);
452 		if (fourcc == RTKIT_FOURCC("Cver"))
453 			rtkit_crashlog_dump_ver(buf + off + 16, size - 16);
454 		if (fourcc == RTKIT_FOURCC("Cmbx"))
455 			rtkit_crashlog_dump_mbx(buf + off + 16, size - 16);
456 		if (fourcc == RTKIT_FOURCC("Crg8"))
457 			rtkit_crashlog_dump_rg8(buf + off + 16, size - 16);
458 		off += size;
459 	}
460 }
461 
462 void
463 rtkit_handle_crashlog_buffer(void *arg)
464 {
465 	struct rtkit_state *state = arg;
466 	struct rtkit *rk = state->rk;
467 	bus_addr_t addr = state->crashlog_addr;
468 	bus_size_t size = state->crashlog_size;
469 
470 	if (addr) {
471 		paddr_t pa = addr;
472 		vaddr_t va;
473 
474 		if (rk && rk->rk_logmap) {
475 			pa = rk->rk_logmap(rk->rk_cookie, addr);
476 			if (pa == (paddr_t)-1)
477 				return;
478 		}
479 
480 		state->crashlog = km_alloc(size * PAGE_SIZE,
481 		    &kv_any, &kp_none, &kd_waitok);
482 		va = (vaddr_t)state->crashlog;
483 
484 		while (size-- > 0) {
485 			pmap_kenter_cache(va, pa, PROT_READ,
486 			    PMAP_CACHE_CI);
487 			va += PAGE_SIZE;
488 			pa += PAGE_SIZE;
489 		}
490 		return;
491 	}
492 
493 	if (rk) {
494 		addr = rtkit_alloc(state, size << PAGE_SHIFT,
495 		    &state->crashlog);
496 		if (addr == (bus_addr_t)-1)
497 			return;
498 	}
499 
500 	rtkit_send(state, RTKIT_EP_CRASHLOG, RTKIT_BUFFER_REQUEST,
501 	    (size << RTKIT_BUFFER_SIZE_SHIFT) | addr);
502 }
503 
504 int
505 rtkit_handle_crashlog(struct rtkit_state *state, struct aplmbox_msg *msg)
506 {
507 	bus_addr_t addr;
508 	bus_size_t size;
509 
510 	switch (RTKIT_MGMT_TYPE(msg->data0)) {
511 	case RTKIT_BUFFER_REQUEST:
512 		addr = RTKIT_BUFFER_ADDR(msg->data0);
513 		size = RTKIT_BUFFER_SIZE(msg->data0);
514 
515 		if (state->crashlog) {
516 			char *buf;
517 
518 			printf("\nRTKit crashed:\n");
519 
520 			buf = malloc(size * PAGE_SIZE, M_TEMP, M_NOWAIT);
521 			if (buf) {
522 				memcpy(buf, state->crashlog, size * PAGE_SIZE);
523 				rtkit_crashlog_dump(buf, size * PAGE_SIZE);
524 			}
525 			break;
526 		}
527 
528 		state->crashlog_addr = addr;
529 		state->crashlog_size = size;
530 		if (cold)
531 			rtkit_handle_crashlog_buffer(state);
532 		else
533 			task_add(systq, &state->crashlog_task);
534 		break;
535 	default:
536 		printf("%s: unhandled crashlog event 0x%016llx\n",
537 		    __func__, msg->data0);
538 		break;
539 	}
540 
541 	return 0;
542 }
543 
544 void
545 rtkit_handle_syslog_log(struct rtkit_state *state, struct aplmbox_msg *msg)
546 {
547 	char context[24];
548 	size_t syslog_msg_size;
549 	char *syslog_msg;
550 	int idx, pos;
551 
552 	if ((state->flags & RK_SYSLOG) == 0)
553 		return;
554 
555 	if (state->syslog_msg == NULL)
556 		return;
557 	idx = RTKIT_SYSLOG_LOG_IDX(msg->data0);
558 	if (idx > state->syslog_n_entries)
559 		return;
560 
561 	syslog_msg_size = state->syslog_msg_size + 32;
562 	syslog_msg = state->syslog + (idx * syslog_msg_size + 8);
563 	memcpy(context, syslog_msg, sizeof(context));
564 	context[sizeof(context) - 1] = 0;
565 
566 	syslog_msg += sizeof(context);
567 	memcpy(state->syslog_msg, syslog_msg, state->syslog_msg_size);
568 	state->syslog_msg[state->syslog_msg_size - 1] = 0;
569 
570 	pos = strlen(state->syslog_msg) - 1;
571 	while (pos >= 0) {
572 		if (state->syslog_msg[pos] != ' ' &&
573 		    state->syslog_msg[pos] != '\n' &&
574 		    state->syslog_msg[pos] != '\r')
575 			break;
576 		state->syslog_msg[pos--] = 0;
577 	}
578 
579 	printf("RTKit syslog %d: %s:%s\n", idx, context, state->syslog_msg);
580 }
581 
582 void
583 rtkit_handle_syslog_buffer(void *arg)
584 {
585 	struct rtkit_state *state = arg;
586 	struct rtkit *rk = state->rk;
587 	bus_addr_t addr = state->syslog_addr;
588 	bus_size_t size = state->syslog_size;
589 
590 	if (rk) {
591 		addr = rtkit_alloc(state, size << PAGE_SHIFT,
592 		    &state->syslog);
593 		if (addr == (bus_addr_t)-1)
594 			return;
595 	}
596 
597 	rtkit_send(state, RTKIT_EP_SYSLOG, RTKIT_BUFFER_REQUEST,
598 	    (size << RTKIT_BUFFER_SIZE_SHIFT) | addr);
599 }
600 
601 int
602 rtkit_handle_syslog(struct rtkit_state *state, struct aplmbox_msg *msg)
603 {
604 	bus_addr_t addr;
605 	bus_size_t size;
606 	int error;
607 
608 	switch (RTKIT_MGMT_TYPE(msg->data0)) {
609 	case RTKIT_BUFFER_REQUEST:
610 		addr = RTKIT_BUFFER_ADDR(msg->data0);
611 		size = RTKIT_BUFFER_SIZE(msg->data0);
612 		if (addr)
613 			break;
614 
615 		state->syslog_addr = addr;
616 		state->syslog_size = size;
617 		if (cold)
618 			rtkit_handle_syslog_buffer(state);
619 		else
620 			task_add(systq, &state->syslog_task);
621 		break;
622 	case RTKIT_SYSLOG_INIT:
623 		state->syslog_n_entries =
624 		    RTKIT_SYSLOG_INIT_N_ENTRIES(msg->data0);
625 		state->syslog_msg_size =
626 		    RTKIT_SYSLOG_INIT_MSG_SIZE(msg->data0);
627 		state->syslog_msg = malloc(state->syslog_msg_size,
628 		    M_DEVBUF, M_NOWAIT);
629 		break;
630 	case RTKIT_SYSLOG_LOG:
631 		rtkit_handle_syslog_log(state, msg);
632 		error = rtkit_send(state, RTKIT_EP_SYSLOG,
633 		    RTKIT_MGMT_TYPE(msg->data0), msg->data0);
634 		if (error)
635 			return error;
636 		break;
637 	default:
638 		printf("%s: unhandled syslog event 0x%016llx\n",
639 		    __func__, msg->data0);
640 		break;
641 	}
642 
643 	return 0;
644 }
645 
646 void
647 rtkit_handle_ioreport_buffer(void *arg)
648 {
649 	struct rtkit_state *state = arg;
650 	struct rtkit *rk = state->rk;
651 	bus_addr_t addr = state->ioreport_addr;
652 	bus_size_t size = state->ioreport_size;
653 
654 	if (rk) {
655 		addr = rtkit_alloc(state, size << PAGE_SHIFT,
656 		    &state->ioreport);
657 		if (addr == (bus_addr_t)-1)
658 			return;
659 	}
660 
661 	rtkit_send(state, RTKIT_EP_IOREPORT, RTKIT_BUFFER_REQUEST,
662 	    (size << RTKIT_BUFFER_SIZE_SHIFT) | addr);
663 }
664 
665 int
666 rtkit_handle_ioreport(struct rtkit_state *state, struct aplmbox_msg *msg)
667 {
668 	bus_addr_t addr;
669 	bus_size_t size;
670 	int error;
671 
672 	switch (RTKIT_MGMT_TYPE(msg->data0)) {
673 	case RTKIT_BUFFER_REQUEST:
674 		addr = RTKIT_BUFFER_ADDR(msg->data0);
675 		size = RTKIT_BUFFER_SIZE(msg->data0);
676 		if (addr)
677 			break;
678 
679 		state->ioreport_addr = addr;
680 		state->ioreport_size = size;
681 		if (cold)
682 			rtkit_handle_ioreport_buffer(state);
683 		else
684 			task_add(systq, &state->ioreport_task);
685 		break;
686 	case RTKIT_IOREPORT_UNKNOWN1:
687 	case RTKIT_IOREPORT_UNKNOWN2:
688 		/* These unknown events have to be acked to make progress. */
689 		error = rtkit_send(state, RTKIT_EP_IOREPORT,
690 		    RTKIT_MGMT_TYPE(msg->data0), msg->data0);
691 		if (error)
692 			return error;
693 		break;
694 	default:
695 		printf("%s: unhandled ioreport event 0x%016llx\n",
696 		    __func__, msg->data0);
697 		break;
698 	}
699 
700 	return 0;
701 }
702 
703 void
704 rtkit_handle_oslog_buffer(void *arg)
705 {
706 	struct rtkit_state *state = arg;
707 	struct rtkit *rk = state->rk;
708 	bus_addr_t addr = state->oslog_addr;
709 	bus_size_t size = state->oslog_size;
710 
711 	if (rk) {
712 		addr = rtkit_alloc(state, size, &state->oslog);
713 		if (addr == (bus_addr_t)-1)
714 			return;
715 	}
716 
717 	rtkit_send(state, RTKIT_EP_OSLOG,
718 	    (RTKIT_OSLOG_BUFFER_REQUEST << RTKIT_OSLOG_TYPE_SHIFT),
719 	    (size << RTKIT_OSLOG_BUFFER_SIZE_SHIFT) | (addr >> PAGE_SHIFT));
720 }
721 
722 int
723 rtkit_handle_oslog(struct rtkit_state *state, struct aplmbox_msg *msg)
724 {
725 	bus_addr_t addr;
726 	bus_size_t size;
727 
728 	switch (RTKIT_OSLOG_TYPE(msg->data0)) {
729 	case RTKIT_OSLOG_BUFFER_REQUEST:
730 		addr = RTKIT_OSLOG_BUFFER_ADDR(msg->data0) << PAGE_SHIFT;
731 		size = RTKIT_OSLOG_BUFFER_SIZE(msg->data0);
732 		if (addr)
733 			break;
734 
735 		state->oslog_addr = addr;
736 		state->oslog_size = size;
737 		if (cold)
738 			rtkit_handle_oslog_buffer(state);
739 		else
740 			task_add(systq, &state->oslog_task);
741 		break;
742 	case RTKIT_OSLOG_UNKNOWN1:
743 	case RTKIT_OSLOG_UNKNOWN2:
744 	case RTKIT_OSLOG_UNKNOWN3:
745 		break;
746 	default:
747 		printf("%s: unhandled oslog event 0x%016llx\n",
748 		    __func__, msg->data0);
749 		break;
750 	}
751 
752 	return 0;
753 }
754 
755 int
756 rtkit_poll(struct rtkit_state *state)
757 {
758 	struct mbox_channel *mc = state->mc;
759 	struct aplmbox_msg msg;
760 	void (*callback)(void *, uint64_t);
761 	void *arg;
762 	uint32_t endpoint;
763 	int error;
764 
765 	error = rtkit_recv(mc, &msg);
766 	if (error)
767 		return error;
768 
769 	if (state->flags & RK_DEBUG) {
770 		printf("%s: 0x%016llx 0x%02x\n", __func__,
771 		    msg.data0, msg.data1);
772 	}
773 
774 	endpoint = msg.data1;
775 	switch (endpoint) {
776 	case RTKIT_EP_MGMT:
777 		error = rtkit_handle_mgmt(state, &msg);
778 		if (error)
779 			return error;
780 		break;
781 	case RTKIT_EP_CRASHLOG:
782 		error = rtkit_handle_crashlog(state, &msg);
783 		if (error)
784 			return error;
785 		break;
786 	case RTKIT_EP_SYSLOG:
787 		error = rtkit_handle_syslog(state, &msg);
788 		if (error)
789 			return error;
790 		break;
791 	case RTKIT_EP_IOREPORT:
792 		error = rtkit_handle_ioreport(state, &msg);
793 		if (error)
794 			return error;
795 		break;
796 	case RTKIT_EP_OSLOG:
797 		error = rtkit_handle_oslog(state, &msg);
798 		if (error)
799 			return error;
800 		break;
801 	default:
802 		if (endpoint >= 32 && endpoint < 64 &&
803 		    state->callback[endpoint - 32]) {
804 			callback = state->callback[endpoint - 32];
805 			arg = state->arg[endpoint - 32];
806 			callback(arg, msg.data0);
807 			break;
808 		}
809 
810 		printf("%s: unhandled endpoint %d\n", __func__, msg.data1);
811 		break;
812 	}
813 
814 	return 0;
815 }
816 
817 void
818 rtkit_rx_callback(void *cookie)
819 {
820 	rtkit_poll(cookie);
821 }
822 
823 struct rtkit_state *
824 rtkit_init(int node, const char *name, int flags, struct rtkit *rk)
825 {
826 	struct rtkit_state *state;
827 	struct mbox_client client;
828 
829 	state = malloc(sizeof(*state), M_DEVBUF, M_WAITOK | M_ZERO);
830 	client.mc_rx_callback = rtkit_rx_callback;
831 	client.mc_rx_arg = state;
832 	if (flags & RK_WAKEUP)
833 		client.mc_flags = MC_WAKEUP;
834 	else
835 		client.mc_flags = 0;
836 
837 	state->mc = mbox_channel(node, name, &client);
838 	if (state->mc == NULL) {
839 		free(state, M_DEVBUF, sizeof(*state));
840 		return NULL;
841 	}
842 	state->rk = rk;
843 	state->flags = flags;
844 
845 	state->iop_pwrstate = RTKIT_MGMT_PWR_STATE_SLEEP;
846 	state->ap_pwrstate = RTKIT_MGMT_PWR_STATE_QUIESCED;
847 
848 	task_set(&state->crashlog_task, rtkit_handle_crashlog_buffer, state);
849 	task_set(&state->syslog_task, rtkit_handle_syslog_buffer, state);
850 	task_set(&state->ioreport_task, rtkit_handle_ioreport_buffer, state);
851 	task_set(&state->oslog_task, rtkit_handle_oslog_buffer, state);
852 
853 	return state;
854 }
855 
856 int
857 rtkit_boot(struct rtkit_state *state)
858 {
859 	int error;
860 
861 	/* Wake up! */
862 	error = rtkit_set_iop_pwrstate(state, RTKIT_MGMT_PWR_STATE_INIT);
863 	if (error)
864 		return error;
865 
866 	return rtkit_set_ap_pwrstate(state, RTKIT_MGMT_PWR_STATE_ON);
867 }
868 
869 void
870 rtkit_shutdown(struct rtkit_state *state)
871 {
872 	struct rtkit *rk = state->rk;
873 	int i;
874 
875 	rtkit_set_ap_pwrstate(state, RTKIT_MGMT_PWR_STATE_QUIESCED);
876 	rtkit_set_iop_pwrstate(state, RTKIT_MGMT_PWR_STATE_SLEEP);
877 
878 	KASSERT(state->iop_pwrstate == RTKIT_MGMT_PWR_STATE_SLEEP);
879 	KASSERT(state->ap_pwrstate == RTKIT_MGMT_PWR_STATE_QUIESCED);
880 	state->epmap = 0;
881 
882 	state->crashlog = NULL;
883 	state->ioreport = NULL;
884 	state->oslog = NULL;
885 	state->syslog = NULL;
886 
887 	/* Clean up our memory allocations. */
888 	for (i = 0; i < state->ndmamem; i++) {
889 		if (rk->rk_unmap) {
890 			rk->rk_unmap(rk->rk_cookie,
891 			    state->dmamem[i].rdm_seg.ds_addr,
892 			    state->dmamem[i].rdm_seg.ds_len);
893 		}
894 		bus_dmamap_unload(rk->rk_dmat, state->dmamem[i].rdm_map);
895 		bus_dmamap_destroy(rk->rk_dmat, state->dmamem[i].rdm_map);
896 		bus_dmamem_unmap(rk->rk_dmat, state->dmamem[i].rdm_kva,
897 		    state->dmamem[i].rdm_size);
898 		bus_dmamem_free(rk->rk_dmat, &state->dmamem[i].rdm_seg, 1);
899 	}
900 	state->ndmamem = 0;
901 }
902 
903 int
904 rtkit_set_ap_pwrstate(struct rtkit_state *state, uint16_t pwrstate)
905 {
906 	int error, timo;
907 
908 	if (state->ap_pwrstate == pwrstate)
909 		return 0;
910 
911 	error = rtkit_send(state, RTKIT_EP_MGMT, RTKIT_MGMT_AP_PWR_STATE,
912 	    pwrstate);
913 	if (error)
914 		return error;
915 
916 	if (cold) {
917 		for (timo = 0; timo < 100000; timo++) {
918 			error = rtkit_poll(state);
919 			if (error == EWOULDBLOCK) {
920 				delay(10);
921 				continue;
922 			}
923 			if (error)
924 				return error;
925 
926 			if (state->ap_pwrstate == pwrstate)
927 				return 0;
928 		}
929 	}
930 
931 	while (state->ap_pwrstate != pwrstate) {
932 		error = tsleep_nsec(&state->ap_pwrstate, PWAIT, "appwr",
933 		    SEC_TO_NSEC(1));
934 		if (error)
935 			return error;
936 	}
937 
938 	return 0;
939 }
940 
941 int
942 rtkit_set_iop_pwrstate(struct rtkit_state *state, uint16_t pwrstate)
943 {
944 	int error, timo;
945 
946 	if (state->iop_pwrstate == (pwrstate & 0xff))
947 		return 0;
948 
949 	error = rtkit_send(state, RTKIT_EP_MGMT, RTKIT_MGMT_IOP_PWR_STATE,
950 	    pwrstate);
951 	if (error)
952 		return error;
953 
954 	if (cold) {
955 		for (timo = 0; timo < 100000; timo++) {
956 			error = rtkit_poll(state);
957 			if (error == EWOULDBLOCK) {
958 				delay(10);
959 				continue;
960 			}
961 			if (error)
962 				return error;
963 
964 			if (state->iop_pwrstate == (pwrstate & 0xff))
965 				return 0;
966 		}
967 	}
968 
969 	while (state->iop_pwrstate != (pwrstate & 0xff)) {
970 		error = tsleep_nsec(&state->iop_pwrstate, PWAIT, "ioppwr",
971 		    SEC_TO_NSEC(1));
972 		if (error)
973 			return error;
974 	}
975 
976 	return 0;
977 }
978 
979 int
980 rtkit_start_endpoint(struct rtkit_state *state, uint32_t endpoint,
981     void (*callback)(void *, uint64_t), void *arg)
982 {
983 	if (endpoint < 32 || endpoint >= 64)
984 		return EINVAL;
985 
986 	if ((state->epmap & (1ULL << endpoint)) == 0)
987 		return EINVAL;
988 
989 	state->callback[endpoint - 32] = callback;
990 	state->arg[endpoint - 32] = arg;
991 	return rtkit_start(state, endpoint);
992 }
993 
994 int
995 rtkit_send_endpoint(struct rtkit_state *state, uint32_t endpoint,
996     uint64_t data)
997 {
998 	return rtkit_send(state, endpoint, 0, data);
999 }
1000