diff options
Diffstat (limited to 'sys/arch/arm64/dev/rtkit.c')
-rw-r--r-- | sys/arch/arm64/dev/rtkit.c | 285 |
1 files changed, 188 insertions, 97 deletions
diff --git a/sys/arch/arm64/dev/rtkit.c b/sys/arch/arm64/dev/rtkit.c index a47a903dd38..192429b1769 100644 --- a/sys/arch/arm64/dev/rtkit.c +++ b/sys/arch/arm64/dev/rtkit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtkit.c,v 1.14 2023/12/30 13:13:11 kettenis Exp $ */ +/* $OpenBSD: rtkit.c,v 1.15 2024/01/15 16:57:31 kettenis Exp $ */ /* * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org> * @@ -19,6 +19,7 @@ #include <sys/systm.h> #include <sys/device.h> #include <sys/malloc.h> +#include <sys/task.h> #include <machine/bus.h> #include <machine/fdt.h> @@ -107,9 +108,21 @@ struct rtkit_state { struct rtkit *rk; int flags; char *crashlog; + bus_addr_t crashlog_addr; + bus_size_t crashlog_size; + struct task crashlog_task; char *ioreport; + bus_addr_t ioreport_addr; + bus_size_t ioreport_size; + struct task ioreport_task; char *oslog; + bus_addr_t oslog_addr; + bus_size_t oslog_size; + struct task oslog_task; char *syslog; + bus_addr_t syslog_addr; + bus_size_t syslog_size; + struct task syslog_task; uint8_t syslog_n_entries; uint8_t syslog_msg_size; char *syslog_msg; @@ -239,9 +252,11 @@ rtkit_handle_mgmt(struct rtkit_state *state, struct aplmbox_msg *msg) break; case RTKIT_MGMT_IOP_PWR_STATE_ACK: state->iop_pwrstate = RTKIT_MGMT_PWR_STATE(msg->data0); + wakeup(&state->iop_pwrstate); break; case RTKIT_MGMT_AP_PWR_STATE: state->ap_pwrstate = RTKIT_MGMT_PWR_STATE(msg->data0); + wakeup(&state->ap_pwrstate); break; case RTKIT_MGMT_EPMAP: base = RTKIT_MGMT_EPMAP_BASE(msg->data0); @@ -440,14 +455,54 @@ rtkit_crashlog_dump(char *buf, size_t size) } } -int -rtkit_handle_crashlog(struct rtkit_state *state, struct aplmbox_msg *msg) +void +rtkit_handle_crashlog_buffer(void *arg) { + struct rtkit_state *state = arg; struct mbox_channel *mc = state->mc; struct rtkit *rk = state->rk; + bus_addr_t addr = state->crashlog_addr; + bus_size_t size = state->crashlog_size; + + if (addr) { + paddr_t pa = addr; + vaddr_t va; + + if (rk && rk->rk_logmap) { + pa = rk->rk_logmap(rk->rk_cookie, addr); + if (pa == (paddr_t)-1) + return; + } + + state->crashlog = km_alloc(size * PAGE_SIZE, + &kv_any, &kp_none, &kd_waitok); + va = (vaddr_t)state->crashlog; + + while (size-- > 0) { + pmap_kenter_cache(va, pa, PROT_READ, + PMAP_CACHE_CI); + va += PAGE_SIZE; + pa += PAGE_SIZE; + } + return; + } + + if (rk) { + addr = rtkit_alloc(state, size << PAGE_SHIFT, + &state->crashlog); + if (addr == (bus_addr_t)-1) + return; + } + + rtkit_send(mc, RTKIT_EP_CRASHLOG, RTKIT_BUFFER_REQUEST, + (size << RTKIT_BUFFER_SIZE_SHIFT) | addr); +} + +int +rtkit_handle_crashlog(struct rtkit_state *state, struct aplmbox_msg *msg) +{ bus_addr_t addr; bus_size_t size; - int error; switch (RTKIT_MGMT_TYPE(msg->data0)) { case RTKIT_BUFFER_REQUEST: @@ -467,40 +522,12 @@ rtkit_handle_crashlog(struct rtkit_state *state, struct aplmbox_msg *msg) break; } - if (addr) { - paddr_t pa = addr; - vaddr_t va; - - if (rk && rk->rk_logmap) { - pa = rk->rk_logmap(rk->rk_cookie, addr); - if (pa == (paddr_t)-1) - break; - } - - state->crashlog = km_alloc(size * PAGE_SIZE, - &kv_any, &kp_none, &kd_waitok); - va = (vaddr_t)state->crashlog; - - while (size-- > 0) { - pmap_kenter_cache(va, pa, PROT_READ, - PMAP_CACHE_CI); - va += PAGE_SIZE; - pa += PAGE_SIZE; - } - break; - } - - if (rk) { - addr = rtkit_alloc(state, size << PAGE_SHIFT, - &state->crashlog); - if (addr == (bus_addr_t)-1) - return ENOMEM; - } - - error = rtkit_send(mc, RTKIT_EP_CRASHLOG, RTKIT_BUFFER_REQUEST, - (size << RTKIT_BUFFER_SIZE_SHIFT) | addr); - if (error) - return error; + state->crashlog_addr = addr; + state->crashlog_size = size; + if (cold) + rtkit_handle_crashlog_buffer(state); + else + task_add(systq, &state->crashlog_task); break; default: printf("%s: unhandled crashlog event 0x%016llx\n", @@ -522,6 +549,8 @@ rtkit_handle_syslog_log(struct rtkit_state *state, struct aplmbox_msg *msg) if ((state->flags & RK_SYSLOG) == 0) return; + if (state->syslog_msg == NULL) + return; idx = RTKIT_SYSLOG_LOG_IDX(msg->data0); if (idx > state->syslog_n_entries) return; @@ -547,11 +576,30 @@ rtkit_handle_syslog_log(struct rtkit_state *state, struct aplmbox_msg *msg) printf("RTKit syslog %d: %s:%s\n", idx, context, state->syslog_msg); } +void +rtkit_handle_syslog_buffer(void *arg) +{ + struct rtkit_state *state = arg; + struct mbox_channel *mc = state->mc; + struct rtkit *rk = state->rk; + bus_addr_t addr = state->syslog_addr; + bus_size_t size = state->syslog_size; + + if (rk) { + addr = rtkit_alloc(state, size << PAGE_SHIFT, + &state->syslog); + if (addr == (bus_addr_t)-1) + return; + } + + rtkit_send(mc, RTKIT_EP_SYSLOG, RTKIT_BUFFER_REQUEST, + (size << RTKIT_BUFFER_SIZE_SHIFT) | addr); +} + int rtkit_handle_syslog(struct rtkit_state *state, struct aplmbox_msg *msg) { struct mbox_channel *mc = state->mc; - struct rtkit *rk = state->rk; bus_addr_t addr; bus_size_t size; int error; @@ -563,17 +611,12 @@ rtkit_handle_syslog(struct rtkit_state *state, struct aplmbox_msg *msg) if (addr) break; - if (rk) { - addr = rtkit_alloc(state, size << PAGE_SHIFT, - &state->syslog); - if (addr == (bus_addr_t)-1) - return ENOMEM; - } - - error = rtkit_send(mc, RTKIT_EP_SYSLOG, RTKIT_BUFFER_REQUEST, - (size << RTKIT_BUFFER_SIZE_SHIFT) | addr); - if (error) - return error; + state->syslog_addr = addr; + state->syslog_size = size; + if (cold) + rtkit_handle_syslog_buffer(state); + else + task_add(systq, &state->syslog_task); break; case RTKIT_SYSLOG_INIT: state->syslog_n_entries = @@ -581,7 +624,7 @@ rtkit_handle_syslog(struct rtkit_state *state, struct aplmbox_msg *msg) state->syslog_msg_size = RTKIT_SYSLOG_INIT_MSG_SIZE(msg->data0); state->syslog_msg = malloc(state->syslog_msg_size, - M_DEVBUF, M_WAITOK); + M_DEVBUF, M_NOWAIT); break; case RTKIT_SYSLOG_LOG: rtkit_handle_syslog_log(state, msg); @@ -599,11 +642,30 @@ rtkit_handle_syslog(struct rtkit_state *state, struct aplmbox_msg *msg) return 0; } +void +rtkit_handle_ioreport_buffer(void *arg) +{ + struct rtkit_state *state = arg; + struct mbox_channel *mc = state->mc; + struct rtkit *rk = state->rk; + bus_addr_t addr = state->ioreport_addr; + bus_size_t size = state->ioreport_size; + + if (rk) { + addr = rtkit_alloc(state, size << PAGE_SHIFT, + &state->ioreport); + if (addr == (bus_addr_t)-1) + return; + } + + rtkit_send(mc, RTKIT_EP_IOREPORT, RTKIT_BUFFER_REQUEST, + (size << RTKIT_BUFFER_SIZE_SHIFT) | addr); +} + int rtkit_handle_ioreport(struct rtkit_state *state, struct aplmbox_msg *msg) { struct mbox_channel *mc = state->mc; - struct rtkit *rk = state->rk; bus_addr_t addr; bus_size_t size; int error; @@ -615,17 +677,12 @@ rtkit_handle_ioreport(struct rtkit_state *state, struct aplmbox_msg *msg) if (addr) break; - if (rk) { - addr = rtkit_alloc(state, size << PAGE_SHIFT, - &state->ioreport); - if (addr == (bus_addr_t)-1) - return ENOMEM; - } - - error = rtkit_send(mc, RTKIT_EP_IOREPORT, RTKIT_BUFFER_REQUEST, - (size << RTKIT_BUFFER_SIZE_SHIFT) | addr); - if (error) - return error; + state->ioreport_addr = addr; + state->ioreport_size = size; + if (cold) + rtkit_handle_ioreport_buffer(state); + else + task_add(systq, &state->ioreport_task); break; case RTKIT_IOREPORT_UNKNOWN1: case RTKIT_IOREPORT_UNKNOWN2: @@ -644,14 +701,31 @@ rtkit_handle_ioreport(struct rtkit_state *state, struct aplmbox_msg *msg) return 0; } -int -rtkit_handle_oslog(struct rtkit_state *state, struct aplmbox_msg *msg) +void +rtkit_handle_oslog_buffer(void *arg) { + struct rtkit_state *state = arg; struct mbox_channel *mc = state->mc; struct rtkit *rk = state->rk; + bus_addr_t addr = state->oslog_addr; + bus_size_t size = state->oslog_size; + + if (rk) { + addr = rtkit_alloc(state, size, &state->oslog); + if (addr == (bus_addr_t)-1) + return; + } + + rtkit_send(mc, RTKIT_EP_OSLOG, + (RTKIT_OSLOG_BUFFER_REQUEST << RTKIT_OSLOG_TYPE_SHIFT), + (size << RTKIT_OSLOG_BUFFER_SIZE_SHIFT) | (addr >> PAGE_SHIFT)); +} + +int +rtkit_handle_oslog(struct rtkit_state *state, struct aplmbox_msg *msg) +{ bus_addr_t addr; bus_size_t size; - int error; switch (RTKIT_OSLOG_TYPE(msg->data0)) { case RTKIT_OSLOG_BUFFER_REQUEST: @@ -660,18 +734,12 @@ rtkit_handle_oslog(struct rtkit_state *state, struct aplmbox_msg *msg) if (addr) break; - if (rk) { - addr = rtkit_alloc(state, size, &state->oslog); - if (addr == (bus_addr_t)-1) - return ENOMEM; - } - - error = rtkit_send(mc, RTKIT_EP_OSLOG, - (RTKIT_OSLOG_BUFFER_REQUEST << RTKIT_OSLOG_TYPE_SHIFT), - (size << RTKIT_OSLOG_BUFFER_SIZE_SHIFT) | - (addr >> PAGE_SHIFT)); - if (error) - return error; + state->oslog_addr = addr; + state->oslog_size = size; + if (cold) + rtkit_handle_oslog_buffer(state); + else + task_add(systq, &state->oslog_task); break; case RTKIT_OSLOG_UNKNOWN1: case RTKIT_OSLOG_UNKNOWN2: @@ -776,6 +844,11 @@ rtkit_init(int node, const char *name, int flags, struct rtkit *rk) state->iop_pwrstate = RTKIT_MGMT_PWR_STATE_SLEEP; state->ap_pwrstate = RTKIT_MGMT_PWR_STATE_QUIESCED; + task_set(&state->crashlog_task, rtkit_handle_crashlog_buffer, state); + task_set(&state->syslog_task, rtkit_handle_syslog_buffer, state); + task_set(&state->ioreport_task, rtkit_handle_ioreport_buffer, state); + task_set(&state->oslog_task, rtkit_handle_oslog_buffer, state); + return state; } @@ -834,20 +907,29 @@ rtkit_set_ap_pwrstate(struct rtkit_state *state, uint16_t pwrstate) if (error) return error; - for (timo = 0; timo < 100000; timo++) { - error = rtkit_poll(state); - if (error == EWOULDBLOCK) { - delay(10); - continue; + if (cold) { + for (timo = 0; timo < 100000; timo++) { + error = rtkit_poll(state); + if (error == EWOULDBLOCK) { + delay(10); + continue; + } + if (error) + return error; + + if (state->ap_pwrstate == pwrstate) + return 0; } + } + + while (state->ap_pwrstate != pwrstate) { + error = tsleep_nsec(&state->ap_pwrstate, PWAIT, "appwr", + SEC_TO_NSEC(1)); if (error) return error; - - if (state->ap_pwrstate == pwrstate) - break; } - return error; + return 0; } int @@ -856,7 +938,7 @@ rtkit_set_iop_pwrstate(struct rtkit_state *state, uint16_t pwrstate) struct mbox_channel *mc = state->mc; int error, timo; - if (state->iop_pwrstate == pwrstate) + if (state->iop_pwrstate == (pwrstate & 0xff)) return 0; error = rtkit_send(mc, RTKIT_EP_MGMT, RTKIT_MGMT_IOP_PWR_STATE, @@ -864,20 +946,29 @@ rtkit_set_iop_pwrstate(struct rtkit_state *state, uint16_t pwrstate) if (error) return error; - for (timo = 0; timo < 100000; timo++) { - error = rtkit_poll(state); - if (error == EWOULDBLOCK) { - delay(10); - continue; + if (cold) { + for (timo = 0; timo < 100000; timo++) { + error = rtkit_poll(state); + if (error == EWOULDBLOCK) { + delay(10); + continue; + } + if (error) + return error; + + if (state->iop_pwrstate == (pwrstate & 0xff)) + return 0; } + } + + while (state->iop_pwrstate != (pwrstate & 0xff)) { + error = tsleep_nsec(&state->iop_pwrstate, PWAIT, "ioppwr", + SEC_TO_NSEC(1)); if (error) return error; - - if (state->iop_pwrstate == (pwrstate & 0xff)) - break; } - return error; + return 0; } int |