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