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
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 rtkit_state * state,uint32_t endpoint,uint64_t type,uint64_t data)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
rtkit_alloc(struct rtkit_state * state,bus_size_t size,caddr_t * kvap)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
rtkit_start(struct rtkit_state * state,uint32_t endpoint)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
rtkit_handle_mgmt(struct rtkit_state * state,struct aplmbox_msg * msg)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
rtkit_crashlog_dump_str(char * buf,size_t size)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
rtkit_crashlog_dump_ver(char * buf,size_t size)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
rtkit_crashlog_dump_mbx(char * buf,size_t size)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
rtkit_crashlog_dump_rg8(char * buf,size_t size)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
rtkit_crashlog_dump(char * buf,size_t size)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
rtkit_handle_crashlog_buffer(void * arg)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
rtkit_handle_crashlog(struct rtkit_state * state,struct aplmbox_msg * msg)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
rtkit_handle_syslog_log(struct rtkit_state * state,struct aplmbox_msg * msg)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
rtkit_handle_syslog_buffer(void * arg)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
rtkit_handle_syslog(struct rtkit_state * state,struct aplmbox_msg * msg)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
rtkit_handle_ioreport_buffer(void * arg)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
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 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
rtkit_handle_oslog_buffer(void * arg)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
rtkit_handle_oslog(struct rtkit_state * state,struct aplmbox_msg * msg)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
rtkit_poll(struct rtkit_state * state)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
rtkit_rx_callback(void * cookie)818 rtkit_rx_callback(void *cookie)
819 {
820 rtkit_poll(cookie);
821 }
822
823 struct rtkit_state *
rtkit_init(int node,const char * name,int flags,struct rtkit * rk)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
rtkit_boot(struct rtkit_state * state)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
rtkit_shutdown(struct rtkit_state * state)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
rtkit_set_ap_pwrstate(struct rtkit_state * state,uint16_t pwrstate)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
rtkit_set_iop_pwrstate(struct rtkit_state * state,uint16_t pwrstate)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
rtkit_start_endpoint(struct rtkit_state * state,uint32_t endpoint,void (* callback)(void *,uint64_t),void * arg)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
rtkit_send_endpoint(struct rtkit_state * state,uint32_t endpoint,uint64_t data)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