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