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