From 2ec5c6354d84dc370e72495a16755f036c4cc365 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sun, 12 Jun 2022 16:00:12 +0000 Subject: [PATCH] The NVMe firmware distributed with the macOS 13 developer beta does not like some of the shortcuts we've taken in the code that talks to RTKit. In particular it does not like our NAK of the request for ioreport buffers. So allocate the requested buffers and ACK the request instead. However, the hardware implements a address filter between the coprocessor that the firmware runs on and main memory. So we have to add a mapping into this address filter such that the firmware can access these buffers. Support for this address filter is implemented in a new aplsart(4) driver. ok dlg@ --- sys/arch/arm64/conf/GENERIC | 7 +- sys/arch/arm64/conf/RAMDISK | 7 +- sys/arch/arm64/conf/files.arm64 | 6 +- sys/arch/arm64/dev/aplns.c | 27 +++++- sys/arch/arm64/dev/aplsart.c | 166 ++++++++++++++++++++++++++++++++ sys/arch/arm64/dev/aplsmc.c | 4 +- sys/arch/arm64/dev/rtkit.c | 80 ++++++++++++--- sys/arch/arm64/dev/rtkit.h | 10 +- 8 files changed, 280 insertions(+), 27 deletions(-) create mode 100644 sys/arch/arm64/dev/aplsart.c diff --git a/sys/arch/arm64/conf/GENERIC b/sys/arch/arm64/conf/GENERIC index e49f4d2d14f..cb5632fc2cc 100644 --- a/sys/arch/arm64/conf/GENERIC +++ b/sys/arch/arm64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.229 2022/06/02 03:09:39 jmatthew Exp $ +# $OpenBSD: GENERIC,v 1.230 2022/06/12 16:00:12 kettenis Exp $ # # GENERIC machine description file # @@ -147,10 +147,13 @@ apliic* at fdt? iic* at apliic? aplintc* at fdt? early 1 aplmbox* at fdt? +aplns* at fdt? # Apple NVME Storage controllers +nvme* at aplns? aplpcie* at fdt? pci* at aplpcie? aplpinctrl* at fdt? early 1 aplpmgr* at fdt? early 1 +aplsart* at fdt? aplsmc* at fdt? aplspi* at fdt? aplhidev* at spi? @@ -161,8 +164,6 @@ wsmouse* at aplms? mux 0 aplspmi* at fdt? aplpmu* at aplspmi? exuart* at fdt? -aplns* at fdt? # Apple NVME Storage controllers -nvme* at aplns? # iMX imxccm* at fdt? early 1 diff --git a/sys/arch/arm64/conf/RAMDISK b/sys/arch/arm64/conf/RAMDISK index 7e9693fe700..6da753a0390 100644 --- a/sys/arch/arm64/conf/RAMDISK +++ b/sys/arch/arm64/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.172 2022/06/02 03:09:39 jmatthew Exp $ +# $OpenBSD: RAMDISK,v 1.173 2022/06/12 16:00:12 kettenis Exp $ machine arm64 maxusers 4 @@ -110,10 +110,13 @@ apliic* at fdt? iic* at apliic? aplintc* at fdt? early 1 aplmbox* at fdt? +aplns* at fdt? # Apple NVME Storage controllers +nvme* at aplns? aplpcie* at fdt? pci* at aplpcie? aplpinctrl* at fdt? early 1 aplpmgr* at fdt? early 1 +aplsart* at fdt? aplsmc* at fdt? aplspi* at fdt? aplhidev* at spi? @@ -122,8 +125,6 @@ wskbd* at aplkbd? mux 1 aplspmi* at fdt? aplpmu* at aplspmi? exuart* at fdt? -aplns* at fdt? # Apple NVME Storage controllers -nvme* at aplns? # iMX imxccm* at fdt? early 1 diff --git a/sys/arch/arm64/conf/files.arm64 b/sys/arch/arm64/conf/files.arm64 index 37e1532eb52..920455b71f2 100644 --- a/sys/arch/arm64/conf/files.arm64 +++ b/sys/arch/arm64/conf/files.arm64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.arm64,v 1.56 2022/02/20 19:25:57 kettenis Exp $ +# $OpenBSD: files.arm64,v 1.57 2022/06/12 16:00:12 kettenis Exp $ maxpartitions 16 maxusers 2 8 128 @@ -197,6 +197,10 @@ attach aplns at fdt attach nvme at aplns with nvme_ans file arch/arm64/dev/aplns.c aplns | nvme_ans +device aplsart +attach aplsart at fdt +file arch/arm64/dev/aplsart.c aplsart | aplns + device aplsmc attach aplsmc at fdt file arch/arm64/dev/aplsmc.c aplsmc diff --git a/sys/arch/arm64/dev/aplns.c b/sys/arch/arm64/dev/aplns.c index ddb085b576a..c59960b76d2 100644 --- a/sys/arch/arm64/dev/aplns.c +++ b/sys/arch/arm64/dev/aplns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplns.c,v 1.11 2022/04/06 18:59:26 naddy Exp $ */ +/* $OpenBSD: aplns.c,v 1.12 2022/06/12 16:00:12 kettenis Exp $ */ /* * Copyright (c) 2014, 2021 David Gwynne * @@ -93,6 +93,8 @@ struct cfdriver aplns_cd = { NULL, "aplns", DV_DULL }; +int nvme_ans_sart_map(void *, bus_addr_t, bus_size_t); + int aplns_match(struct device *parent, void *match, void *aux) { @@ -117,7 +119,9 @@ struct nvme_ans_softc { bus_space_tag_t asc_iot; bus_space_handle_t asc_ioh; - struct rtkit_state *asc_rtkit; + uint32_t asc_sart; + struct rtkit asc_rtkit; + struct rtkit_state *asc_rtkit_state; struct nvme_dmamem *asc_nvmmu; }; @@ -205,8 +209,13 @@ nvme_ans_attach(struct device *parent, struct device *self, void *aux) goto unmap; } - asc->asc_rtkit = rtkit_init(faa->fa_node, NULL); - if (asc->asc_rtkit == NULL) { + asc->asc_sart = OF_getpropint(faa->fa_node, "apple,sart", 0); + asc->asc_rtkit.rk_cookie = asc; + asc->asc_rtkit.rk_dmat = faa->fa_dmat; + asc->asc_rtkit.rk_map = nvme_ans_sart_map; + + asc->asc_rtkit_state = rtkit_init(faa->fa_node, NULL, &asc->asc_rtkit); + if (asc->asc_rtkit_state == NULL) { printf(": can't map mailbox channel\n"); goto disestablish; } @@ -217,7 +226,7 @@ nvme_ans_attach(struct device *parent, struct device *self, void *aux) status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ANS_BOOT_STATUS); if (status != ANS_BOOT_STATUS_OK) - rtkit_boot(asc->asc_rtkit); + rtkit_boot(asc->asc_rtkit_state); status = bus_space_read_4(sc->sc_iot, sc->sc_ioh, ANS_BOOT_STATUS); if (status != ANS_BOOT_STATUS_OK) { @@ -258,6 +267,14 @@ unmap: sc->sc_ios = 0; } +int +nvme_ans_sart_map(void *cookie, bus_addr_t addr, bus_size_t size) +{ + struct nvme_ans_softc *asc = cookie; + + return aplsart_map(asc->asc_sart, addr, size); +} + int nvme_ans_q_alloc(struct nvme_softc *sc, struct nvme_queue *q) diff --git a/sys/arch/arm64/dev/aplsart.c b/sys/arch/arm64/dev/aplsart.c new file mode 100644 index 00000000000..975ee9f4c17 --- /dev/null +++ b/sys/arch/arm64/dev/aplsart.c @@ -0,0 +1,166 @@ +/* $OpenBSD: aplsart.c,v 1.1 2022/06/12 16:00:12 kettenis Exp $ */ +/* + * Copyright (c) 2022 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define SART2_CONFIG(idx) (0x0000 + 4 * (idx)) +#define SART2_CONFIG_FLAGS_MASK 0xff000000 +#define SART2_CONFIG_FLAGS_ALLOW 0xff000000 +#define SART2_ADDR(idx) (0x0040 + 4 * (idx)) + +#define SART3_CONFIG(idx) (0x0000 + 4 * (idx)) +#define SART3_CONFIG_FLAGS_MASK 0x000000ff +#define SART3_CONFIG_FLAGS_ALLOW 0x000000ff +#define SART3_ADDR(idx) (0x0040 + 4 * (idx)) +#define SART3_SIZE(idx) (0x0080 + 4 * (idx)) + +#define SART_NUM_ENTRIES 16 +#define SART_ADDR_SHIFT 12 +#define SART_SIZE_SHIFT 12 + +#define HREAD4(sc, reg) \ + (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) +#define HWRITE4(sc, reg, val) \ + bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) + +struct aplsart_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + uint32_t sc_phandle; + int sc_version; +}; + +int aplsart_match(struct device *, void *, void *); +void aplsart_attach(struct device *, struct device *, void *); + +const struct cfattach aplsart_ca = { + sizeof (struct aplsart_softc), aplsart_match, aplsart_attach +}; + +struct cfdriver aplsart_cd = { + NULL, "aplsart", DV_DULL +}; + +int +aplsart_match(struct device *parent, void *match, void *aux) +{ + struct fdt_attach_args *faa = aux; + + return OF_is_compatible(faa->fa_node, "apple,sart2") || + OF_is_compatible(faa->fa_node, "apple,sart3"); +} + +void +aplsart_attach(struct device *parent, struct device *self, void *aux) +{ + struct aplsart_softc *sc = (struct aplsart_softc *)self; + struct fdt_attach_args *faa = aux; + + if (faa->fa_nreg < 1) { + printf(": no registers\n"); + return; + } + + sc->sc_iot = faa->fa_iot; + if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, + faa->fa_reg[0].size, 0, &sc->sc_ioh)) { + printf(": can't map registers\n"); + return; + } + + sc->sc_phandle = OF_getpropint(faa->fa_node, "phandle", 0); + + if (OF_is_compatible(faa->fa_node, "apple,sart2")) + sc->sc_version = 2; + if (OF_is_compatible(faa->fa_node, "apple,sart3")) + sc->sc_version = 3; + + printf("\n"); +} + +int +aplsart2_map(struct aplsart_softc *sc, bus_addr_t addr, bus_size_t size) +{ + uint32_t conf; + int i; + + for (i = 0; i < SART_NUM_ENTRIES; i++) { + conf = HREAD4(sc, SART2_CONFIG(i)); + if (conf & SART2_CONFIG_FLAGS_MASK) + continue; + + HWRITE4(sc, SART2_ADDR(i), addr >> SART_ADDR_SHIFT); + HWRITE4(sc, SART2_CONFIG(i), + size >> SART_SIZE_SHIFT | SART2_CONFIG_FLAGS_ALLOW); + return 0; + } + + return ENOENT; +} + +int +aplsart3_map(struct aplsart_softc *sc, bus_addr_t addr, bus_size_t size) +{ + uint32_t conf; + int i; + + for (i = 0; i < SART_NUM_ENTRIES; i++) { + conf = HREAD4(sc, SART3_CONFIG(i)); + if (conf & SART3_CONFIG_FLAGS_MASK) + continue; + + HWRITE4(sc, SART3_ADDR(i), addr >> SART_ADDR_SHIFT); + HWRITE4(sc, SART3_SIZE(i), size >> SART_SIZE_SHIFT); + HWRITE4(sc, SART3_CONFIG(i), SART3_CONFIG_FLAGS_ALLOW); + return 0; + } + + return ENOENT; +} + +int +aplsart_map(uint32_t phandle, bus_addr_t addr, bus_size_t size) +{ + struct aplsart_softc *sc; + int i; + + for (i = 0; i < aplsart_cd.cd_ndevs; i++) { + sc = (struct aplsart_softc *)aplsart_cd.cd_devs[i]; + + if (sc->sc_phandle == phandle) { + if (sc->sc_version == 2) + return aplsart2_map(sc, addr, size); + else + return aplsart3_map(sc, addr, size); + } + } + + return ENXIO; +} diff --git a/sys/arch/arm64/dev/aplsmc.c b/sys/arch/arm64/dev/aplsmc.c index b9cb2b5d69c..43ee3bc80ca 100644 --- a/sys/arch/arm64/dev/aplsmc.c +++ b/sys/arch/arm64/dev/aplsmc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aplsmc.c,v 1.11 2022/03/25 15:52:03 kettenis Exp $ */ +/* $OpenBSD: aplsmc.c,v 1.12 2022/06/12 16:00:12 kettenis Exp $ */ /* * Copyright (c) 2021 Mark Kettenis * @@ -194,7 +194,7 @@ aplsmc_attach(struct device *parent, struct device *self, void *aux) return; } - sc->sc_rs = rtkit_init(faa->fa_node, NULL); + sc->sc_rs = rtkit_init(faa->fa_node, NULL, NULL); if (sc->sc_rs == NULL) { printf(": can't map mailbox channel\n"); return; diff --git a/sys/arch/arm64/dev/rtkit.c b/sys/arch/arm64/dev/rtkit.c index fbf32c31e47..ef0012e687c 100644 --- a/sys/arch/arm64/dev/rtkit.c +++ b/sys/arch/arm64/dev/rtkit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtkit.c,v 1.3 2022/01/10 09:07:28 kettenis Exp $ */ +/* $OpenBSD: rtkit.c,v 1.4 2022/06/12 16:00:12 kettenis Exp $ */ /* * Copyright (c) 2021 Mark Kettenis * @@ -68,12 +68,16 @@ #define RTKIT_BUFFER_SIZE(x) (((x) >> 44) & 0xff) #define RTKIT_BUFFER_SIZE_SHIFT 44 +#define RTKIT_IOREPORT_UNKNOWN1 8 +#define RTKIT_IOREPORT_UNKNOWN2 12 + /* Versions we support. */ #define RTKIT_MINVER 11 #define RTKIT_MAXVER 12 struct rtkit_state { struct mbox_channel *mc; + struct rtkit *rk; int pwrstate; uint64_t epmap; void (*callback[32])(void *, uint64_t); @@ -106,6 +110,19 @@ rtkit_send(struct mbox_channel *mc, uint32_t endpoint, return mbox_send(mc, &msg, sizeof(msg)); } +bus_addr_t +rtkit_alloc(struct rtkit *rk, bus_size_t size) +{ + bus_dma_segment_t seg; + int nsegs; + + if (bus_dmamem_alloc(rk->rk_dmat, size, 16384, 0, + &seg, 1, &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO)) + return (bus_addr_t)-1; + + return seg.ds_addr; +} + int rtkit_start(struct rtkit_state *state, uint32_t endpoint) { @@ -131,13 +148,13 @@ rtkit_handle_mgmt(struct rtkit_state *state, struct aplmbox_msg *msg) minver = RTKIT_MGMT_HELLO_MINVER(msg->data0); maxver = RTKIT_MGMT_HELLO_MAXVER(msg->data0); if (minver > RTKIT_MAXVER) { - printf("unsupported minimum firmware version %lld\n", - minver); + printf("%s: unsupported minimum firmware version %lld\n", + __func__, minver); return EINVAL; } if (maxver < RTKIT_MINVER) { - printf("unsupported maximum firmware version %lld\n", - maxver); + printf("%s: unsupported maximum firmware version %lld\n", + __func__, maxver); return EINVAL; } ver = min(RTKIT_MAXVER, maxver); @@ -172,18 +189,24 @@ rtkit_handle_mgmt(struct rtkit_state *state, struct aplmbox_msg *msg) switch (endpoint) { case RTKIT_EP_CRASHLOG: + case RTKIT_EP_SYSLOG: case RTKIT_EP_DEBUG: case RTKIT_EP_IOREPORT: error = rtkit_start(state, endpoint); if (error) return error; break; + default: + printf("%s: skipping endpoint %d\n", + __func__, endpoint); + break; } } } break; default: - printf("unhandled management event 0x%016lld\n", msg->data0); + printf("%s: unhandled management event 0x%016lld\n", + __func__, msg->data0); return EIO; } @@ -194,6 +217,7 @@ int rtkit_handle_crashlog(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; @@ -205,13 +229,24 @@ rtkit_handle_crashlog(struct rtkit_state *state, struct aplmbox_msg *msg) if (addr) break; + if (rk) { + addr = rtkit_alloc(rk, size << PAGE_SHIFT); + if (addr == (bus_addr_t)-1) + return ENOMEM; + error = rk->rk_map(rk->rk_cookie, addr, + size << PAGE_SHIFT); + if (error) + return error; + } + error = rtkit_send(mc, RTKIT_EP_CRASHLOG, RTKIT_BUFFER_REQUEST, - size << RTKIT_BUFFER_SIZE_SHIFT | addr); + (size << RTKIT_BUFFER_SIZE_SHIFT) | addr); if (error) return error; break; default: - printf("unhandled crashlog event 0x%016llx\n", msg->data0); + printf("%s: unhandled crashlog event 0x%016llx\n", + __func__, msg->data0); return EIO; } @@ -222,6 +257,7 @@ 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; @@ -233,13 +269,32 @@ rtkit_handle_ioreport(struct rtkit_state *state, struct aplmbox_msg *msg) if (addr) break; + if (rk) { + addr = rtkit_alloc(rk, size << PAGE_SHIFT); + if (addr == (bus_addr_t)-1) + return ENOMEM; + error = rk->rk_map(rk->rk_cookie, addr, + size << PAGE_SHIFT); + if (error) + return error; + } + error = rtkit_send(mc, RTKIT_EP_IOREPORT, RTKIT_BUFFER_REQUEST, - size << RTKIT_BUFFER_SIZE_SHIFT | addr); + (size << RTKIT_BUFFER_SIZE_SHIFT) | addr); + if (error) + return error; + break; + case RTKIT_IOREPORT_UNKNOWN1: + case RTKIT_IOREPORT_UNKNOWN2: + /* These unknown events have to be acked to make progress. */ + error = rtkit_send(mc, RTKIT_EP_IOREPORT, + RTKIT_MGMT_TYPE(msg->data0), msg->data0); if (error) return error; break; default: - printf("unhandled ioreport event 0x%016llx\n", msg->data0); + printf("%s: unhandled ioreport event 0x%016llx\n", + __func__, msg->data0); return EIO; } @@ -286,7 +341,7 @@ rtkit_poll(struct rtkit_state *state) break; } - printf("unhandled endpoint %d\n", msg.data1); + printf("%s: unhandled endpoint %d\n", __func__, msg.data1); return EIO; } @@ -300,7 +355,7 @@ rtkit_rx_callback(void *cookie) } struct rtkit_state * -rtkit_init(int node, const char *name) +rtkit_init(int node, const char *name, struct rtkit *rk) { struct rtkit_state *state; struct mbox_client client; @@ -313,6 +368,7 @@ rtkit_init(int node, const char *name) free(state, M_DEVBUF, sizeof(*state)); return NULL; } + state->rk = rk; return state; } diff --git a/sys/arch/arm64/dev/rtkit.h b/sys/arch/arm64/dev/rtkit.h index cdfd7ca0260..1da40e307d6 100644 --- a/sys/arch/arm64/dev/rtkit.h +++ b/sys/arch/arm64/dev/rtkit.h @@ -2,9 +2,17 @@ struct rtkit_state; -struct rtkit_state *rtkit_init(int, const char *); +struct rtkit { + void *rk_cookie; + bus_dma_tag_t rk_dmat; + int (*rk_map)(void *, bus_addr_t, bus_size_t); +}; + +struct rtkit_state *rtkit_init(int, const char *, struct rtkit *); int rtkit_boot(struct rtkit_state *); int rtkit_poll(struct rtkit_state *); int rtkit_start_endpoint(struct rtkit_state *, uint32_t, void (*)(void *, uint64_t), void *); int rtkit_send_endpoint(struct rtkit_state *, uint32_t, uint64_t); + +int aplsart_map(uint32_t, bus_addr_t, bus_size_t); -- 2.20.1