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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 817 rtkit_rx_callback(void *cookie) 818 { 819 rtkit_poll(cookie); 820 } 821 822 struct rtkit_state * 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 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 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 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 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 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 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