1 /* $OpenBSD: rtkit.c,v 1.4 2022/06/12 16:00:12 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 23 #include <machine/bus.h> 24 #include <machine/fdt.h> 25 26 #include <dev/ofw/openfirm.h> 27 #include <dev/ofw/ofw_misc.h> 28 #include <dev/ofw/fdt.h> 29 30 #include <arm64/dev/aplmbox.h> 31 #include <arm64/dev/rtkit.h> 32 33 #define RTKIT_EP_MGMT 0 34 #define RTKIT_EP_CRASHLOG 1 35 #define RTKIT_EP_SYSLOG 2 36 #define RTKIT_EP_DEBUG 3 37 #define RTKIT_EP_IOREPORT 4 38 39 #define RTKIT_MGMT_TYPE(x) (((x) >> 52) & 0xff) 40 #define RTKIT_MGMT_TYPE_SHIFT 52 41 42 #define RTKIT_MGMT_PWR_STATE(x) (((x) >> 0) & 0xff) 43 #define RTKIT_MGMT_PWR_STATE_ON 0x20 44 45 #define RTKIT_MGMT_HELLO 1 46 #define RTKIT_MGMT_HELLO_ACK 2 47 #define RTKIT_MGMT_STARTEP 5 48 #define RTKIT_MGMT_IOP_PWR_STATE 6 49 #define RTKIT_MGMT_IOP_PWR_STATE_ACK 7 50 #define RTKIT_MGMT_EPMAP 8 51 52 #define RTKIT_MGMT_HELLO_MINVER(x) (((x) >> 0) & 0xffff) 53 #define RTKIT_MGMT_HELLO_MINVER_SHIFT 0 54 #define RTKIT_MGMT_HELLO_MAXVER(x) (((x) >> 16) & 0xffff) 55 #define RTKIT_MGMT_HELLO_MAXVER_SHIFT 16 56 57 #define RTKIT_MGMT_STARTEP_EP_SHIFT 32 58 #define RTKIT_MGMT_STARTEP_START (1ULL << 1) 59 60 #define RTKIT_MGMT_EPMAP_LAST (1ULL << 51) 61 #define RTKIT_MGMT_EPMAP_BASE(x) (((x) >> 32) & 0x7) 62 #define RTKIT_MGMT_EPMAP_BASE_SHIFT 32 63 #define RTKIT_MGMT_EPMAP_BITMAP(x) (((x) >> 0) & 0xffffffff) 64 #define RTKIT_MGMT_EPMAP_MORE (1ULL << 0) 65 66 #define RTKIT_BUFFER_REQUEST 1 67 #define RTKIT_BUFFER_ADDR(x) (((x) >> 0) & 0xfffffffffff) 68 #define RTKIT_BUFFER_SIZE(x) (((x) >> 44) & 0xff) 69 #define RTKIT_BUFFER_SIZE_SHIFT 44 70 71 #define RTKIT_IOREPORT_UNKNOWN1 8 72 #define RTKIT_IOREPORT_UNKNOWN2 12 73 74 /* Versions we support. */ 75 #define RTKIT_MINVER 11 76 #define RTKIT_MAXVER 12 77 78 struct rtkit_state { 79 struct mbox_channel *mc; 80 struct rtkit *rk; 81 int pwrstate; 82 uint64_t epmap; 83 void (*callback[32])(void *, uint64_t); 84 void *arg[32]; 85 }; 86 87 int 88 rtkit_recv(struct mbox_channel *mc, struct aplmbox_msg *msg) 89 { 90 int error, timo; 91 92 for (timo = 0; timo < 10000; timo++) { 93 error = mbox_recv(mc, msg, sizeof(*msg)); 94 if (error == 0) 95 break; 96 delay(10); 97 } 98 99 return error; 100 } 101 102 int 103 rtkit_send(struct mbox_channel *mc, uint32_t endpoint, 104 uint64_t type, uint64_t data) 105 { 106 struct aplmbox_msg msg; 107 108 msg.data0 = (type << RTKIT_MGMT_TYPE_SHIFT) | data; 109 msg.data1 = endpoint; 110 return mbox_send(mc, &msg, sizeof(msg)); 111 } 112 113 bus_addr_t 114 rtkit_alloc(struct rtkit *rk, bus_size_t size) 115 { 116 bus_dma_segment_t seg; 117 int nsegs; 118 119 if (bus_dmamem_alloc(rk->rk_dmat, size, 16384, 0, 120 &seg, 1, &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO)) 121 return (bus_addr_t)-1; 122 123 return seg.ds_addr; 124 } 125 126 int 127 rtkit_start(struct rtkit_state *state, uint32_t endpoint) 128 { 129 struct mbox_channel *mc = state->mc; 130 uint64_t reply; 131 132 reply = ((uint64_t)endpoint << RTKIT_MGMT_STARTEP_EP_SHIFT); 133 reply |= RTKIT_MGMT_STARTEP_START; 134 return rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_STARTEP, reply); 135 } 136 137 int 138 rtkit_handle_mgmt(struct rtkit_state *state, struct aplmbox_msg *msg) 139 { 140 struct mbox_channel *mc = state->mc; 141 uint64_t minver, maxver, ver; 142 uint64_t base, bitmap, reply; 143 uint32_t endpoint; 144 int error; 145 146 switch (RTKIT_MGMT_TYPE(msg->data0)) { 147 case RTKIT_MGMT_HELLO: 148 minver = RTKIT_MGMT_HELLO_MINVER(msg->data0); 149 maxver = RTKIT_MGMT_HELLO_MAXVER(msg->data0); 150 if (minver > RTKIT_MAXVER) { 151 printf("%s: unsupported minimum firmware version %lld\n", 152 __func__, minver); 153 return EINVAL; 154 } 155 if (maxver < RTKIT_MINVER) { 156 printf("%s: unsupported maximum firmware version %lld\n", 157 __func__, maxver); 158 return EINVAL; 159 } 160 ver = min(RTKIT_MAXVER, maxver); 161 error = rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_HELLO_ACK, 162 (ver << RTKIT_MGMT_HELLO_MINVER_SHIFT) | 163 (ver << RTKIT_MGMT_HELLO_MAXVER_SHIFT)); 164 if (error) 165 return error; 166 break; 167 168 case RTKIT_MGMT_IOP_PWR_STATE_ACK: 169 state->pwrstate = RTKIT_MGMT_PWR_STATE(msg->data0); 170 break; 171 172 case RTKIT_MGMT_EPMAP: 173 base = RTKIT_MGMT_EPMAP_BASE(msg->data0); 174 bitmap = RTKIT_MGMT_EPMAP_BITMAP(msg->data0); 175 state->epmap |= (bitmap << (base * 32)); 176 reply = (base << RTKIT_MGMT_EPMAP_BASE_SHIFT); 177 if (msg->data0 & RTKIT_MGMT_EPMAP_LAST) 178 reply |= RTKIT_MGMT_EPMAP_LAST; 179 else 180 reply |= RTKIT_MGMT_EPMAP_MORE; 181 error = rtkit_send(state->mc, RTKIT_EP_MGMT, 182 RTKIT_MGMT_EPMAP, reply); 183 if (error) 184 return error; 185 if (msg->data0 & RTKIT_MGMT_EPMAP_LAST) { 186 for (endpoint = 1; endpoint < 32; endpoint++) { 187 if ((state->epmap & (1ULL << endpoint)) == 0) 188 continue; 189 190 switch (endpoint) { 191 case RTKIT_EP_CRASHLOG: 192 case RTKIT_EP_SYSLOG: 193 case RTKIT_EP_DEBUG: 194 case RTKIT_EP_IOREPORT: 195 error = rtkit_start(state, endpoint); 196 if (error) 197 return error; 198 break; 199 default: 200 printf("%s: skipping endpoint %d\n", 201 __func__, endpoint); 202 break; 203 } 204 } 205 } 206 break; 207 default: 208 printf("%s: unhandled management event 0x%016lld\n", 209 __func__, msg->data0); 210 return EIO; 211 } 212 213 return 0; 214 } 215 216 int 217 rtkit_handle_crashlog(struct rtkit_state *state, struct aplmbox_msg *msg) 218 { 219 struct mbox_channel *mc = state->mc; 220 struct rtkit *rk = state->rk; 221 bus_addr_t addr; 222 bus_size_t size; 223 int error; 224 225 switch (RTKIT_MGMT_TYPE(msg->data0)) { 226 case RTKIT_BUFFER_REQUEST: 227 addr = RTKIT_BUFFER_ADDR(msg->data0); 228 size = RTKIT_BUFFER_SIZE(msg->data0); 229 if (addr) 230 break; 231 232 if (rk) { 233 addr = rtkit_alloc(rk, size << PAGE_SHIFT); 234 if (addr == (bus_addr_t)-1) 235 return ENOMEM; 236 error = rk->rk_map(rk->rk_cookie, addr, 237 size << PAGE_SHIFT); 238 if (error) 239 return error; 240 } 241 242 error = rtkit_send(mc, RTKIT_EP_CRASHLOG, RTKIT_BUFFER_REQUEST, 243 (size << RTKIT_BUFFER_SIZE_SHIFT) | addr); 244 if (error) 245 return error; 246 break; 247 default: 248 printf("%s: unhandled crashlog event 0x%016llx\n", 249 __func__, msg->data0); 250 return EIO; 251 } 252 253 return 0; 254 } 255 256 int 257 rtkit_handle_ioreport(struct rtkit_state *state, struct aplmbox_msg *msg) 258 { 259 struct mbox_channel *mc = state->mc; 260 struct rtkit *rk = state->rk; 261 bus_addr_t addr; 262 bus_size_t size; 263 int error; 264 265 switch (RTKIT_MGMT_TYPE(msg->data0)) { 266 case RTKIT_BUFFER_REQUEST: 267 addr = RTKIT_BUFFER_ADDR(msg->data0); 268 size = RTKIT_BUFFER_SIZE(msg->data0); 269 if (addr) 270 break; 271 272 if (rk) { 273 addr = rtkit_alloc(rk, size << PAGE_SHIFT); 274 if (addr == (bus_addr_t)-1) 275 return ENOMEM; 276 error = rk->rk_map(rk->rk_cookie, addr, 277 size << PAGE_SHIFT); 278 if (error) 279 return error; 280 } 281 282 error = rtkit_send(mc, RTKIT_EP_IOREPORT, RTKIT_BUFFER_REQUEST, 283 (size << RTKIT_BUFFER_SIZE_SHIFT) | addr); 284 if (error) 285 return error; 286 break; 287 case RTKIT_IOREPORT_UNKNOWN1: 288 case RTKIT_IOREPORT_UNKNOWN2: 289 /* These unknown events have to be acked to make progress. */ 290 error = rtkit_send(mc, RTKIT_EP_IOREPORT, 291 RTKIT_MGMT_TYPE(msg->data0), msg->data0); 292 if (error) 293 return error; 294 break; 295 default: 296 printf("%s: unhandled ioreport event 0x%016llx\n", 297 __func__, msg->data0); 298 return EIO; 299 } 300 301 return 0; 302 } 303 304 int 305 rtkit_poll(struct rtkit_state *state) 306 { 307 struct mbox_channel *mc = state->mc; 308 struct aplmbox_msg msg; 309 void (*callback)(void *, uint64_t); 310 void *arg; 311 uint32_t endpoint; 312 int error; 313 314 error = rtkit_recv(mc, &msg); 315 if (error) 316 return error; 317 318 endpoint = msg.data1; 319 switch (endpoint) { 320 case RTKIT_EP_MGMT: 321 error = rtkit_handle_mgmt(state, &msg); 322 if (error) 323 return error; 324 break; 325 case RTKIT_EP_CRASHLOG: 326 error = rtkit_handle_crashlog(state, &msg); 327 if (error) 328 return error; 329 break; 330 case RTKIT_EP_IOREPORT: 331 error = rtkit_handle_ioreport(state, &msg); 332 if (error) 333 return error; 334 break; 335 default: 336 if (endpoint >= 32 && endpoint < 64 && 337 state->callback[endpoint - 32]) { 338 callback = state->callback[endpoint - 32]; 339 arg = state->arg[endpoint - 32]; 340 callback(arg, msg.data0); 341 break; 342 } 343 344 printf("%s: unhandled endpoint %d\n", __func__, msg.data1); 345 return EIO; 346 } 347 348 return 0; 349 } 350 351 void 352 rtkit_rx_callback(void *cookie) 353 { 354 rtkit_poll(cookie); 355 } 356 357 struct rtkit_state * 358 rtkit_init(int node, const char *name, struct rtkit *rk) 359 { 360 struct rtkit_state *state; 361 struct mbox_client client; 362 363 state = malloc(sizeof(*state), M_DEVBUF, M_WAITOK | M_ZERO); 364 client.mc_rx_callback = rtkit_rx_callback; 365 client.mc_rx_arg = state; 366 state->mc = mbox_channel(node, name, &client); 367 if (state->mc == NULL) { 368 free(state, M_DEVBUF, sizeof(*state)); 369 return NULL; 370 } 371 state->rk = rk; 372 373 return state; 374 } 375 376 int 377 rtkit_boot(struct rtkit_state *state) 378 { 379 struct mbox_channel *mc = state->mc; 380 int error; 381 382 /* Wake up! */ 383 error = rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_IOP_PWR_STATE, 384 RTKIT_MGMT_PWR_STATE_ON); 385 if (error) 386 return error; 387 388 while (state->pwrstate != RTKIT_MGMT_PWR_STATE_ON) 389 rtkit_poll(state); 390 391 return 0; 392 } 393 394 int 395 rtkit_start_endpoint(struct rtkit_state *state, uint32_t endpoint, 396 void (*callback)(void *, uint64_t), void *arg) 397 { 398 if (endpoint < 32 || endpoint >= 64) 399 return EINVAL; 400 401 if ((state->epmap & (1ULL << endpoint)) == 0) 402 return EINVAL; 403 404 state->callback[endpoint - 32] = callback; 405 state->arg[endpoint - 32] = arg; 406 return rtkit_start(state, endpoint); 407 } 408 409 int 410 rtkit_send_endpoint(struct rtkit_state *state, uint32_t endpoint, 411 uint64_t data) 412 { 413 return rtkit_send(state->mc, endpoint, 0, data); 414 } 415