The macOS 13 beta release apparently comes with new RTKit-based NVMe
firmware that doesn't like some of the shortcuts I've taken in the
OpenBSD drivers and U-Boot.  U-Boot is being fixed and here is a diff
that attempts to fix OpenBSD.

* For now, don't update your Apple M1 machines to macOS 13 if you want
  to keep running OpenBSD on them!!! *

The issue is that our code doesn't allocate the memory that RTKit asks
for.  Instead we effectively NAK the request.  This works fine with
the current firmware, but apparently not with the new one.  The diff
below changes this and allocates the requested memory.  There is a
complication though.  The hardware has an address filter to prevent
the firmware from accessing arbitrary bits of memory.  So we need to
program this address filter when we allocate the memory.  This is done
by a new driver that is called aplsart(4).

ok?


Index: arch/arm64/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/arm64/conf/GENERIC,v
retrieving revision 1.229
diff -u -p -r1.229 GENERIC
--- arch/arm64/conf/GENERIC     2 Jun 2022 03:09:39 -0000       1.229
+++ arch/arm64/conf/GENERIC     11 Jun 2022 19:27:57 -0000
@@ -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
Index: arch/arm64/conf/RAMDISK
===================================================================
RCS file: /cvs/src/sys/arch/arm64/conf/RAMDISK,v
retrieving revision 1.172
diff -u -p -r1.172 RAMDISK
--- arch/arm64/conf/RAMDISK     2 Jun 2022 03:09:39 -0000       1.172
+++ arch/arm64/conf/RAMDISK     11 Jun 2022 19:27:57 -0000
@@ -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
Index: arch/arm64/conf/files.arm64
===================================================================
RCS file: /cvs/src/sys/arch/arm64/conf/files.arm64,v
retrieving revision 1.56
diff -u -p -r1.56 files.arm64
--- arch/arm64/conf/files.arm64 20 Feb 2022 19:25:57 -0000      1.56
+++ arch/arm64/conf/files.arm64 11 Jun 2022 19:27:57 -0000
@@ -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
Index: arch/arm64/dev/aplns.c
===================================================================
RCS file: /cvs/src/sys/arch/arm64/dev/aplns.c,v
retrieving revision 1.11
diff -u -p -r1.11 aplns.c
--- arch/arm64/dev/aplns.c      6 Apr 2022 18:59:26 -0000       1.11
+++ arch/arm64/dev/aplns.c      11 Jun 2022 19:27:57 -0000
@@ -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, s
                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, s
 
        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) {
@@ -256,6 +265,14 @@ unmap:
        bus_space_unmap(asc->asc_iot, asc->asc_ioh, faa->fa_reg[1].size);
        bus_space_unmap(sc->sc_iot, sc->sc_ioh, faa->fa_reg[0].size);
        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
Index: arch/arm64/dev/aplsart.c
===================================================================
RCS file: arch/arm64/dev/aplsart.c
diff -N arch/arm64/dev/aplsart.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ arch/arm64/dev/aplsart.c    11 Jun 2022 19:27:57 -0000
@@ -0,0 +1,166 @@
+/*     $OpenBSD$       */
+/*
+ * Copyright (c) 2022 Mark Kettenis <kette...@openbsd.org>
+ *
+ * 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/extent.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+#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;
+}
Index: arch/arm64/dev/aplsmc.c
===================================================================
RCS file: /cvs/src/sys/arch/arm64/dev/aplsmc.c,v
retrieving revision 1.11
diff -u -p -r1.11 aplsmc.c
--- arch/arm64/dev/aplsmc.c     25 Mar 2022 15:52:03 -0000      1.11
+++ arch/arm64/dev/aplsmc.c     11 Jun 2022 19:27:57 -0000
@@ -194,7 +194,7 @@ aplsmc_attach(struct device *parent, str
                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;
Index: arch/arm64/dev/rtkit.c
===================================================================
RCS file: /cvs/src/sys/arch/arm64/dev/rtkit.c,v
retrieving revision 1.3
diff -u -p -r1.3 rtkit.c
--- arch/arm64/dev/rtkit.c      10 Jan 2022 09:07:28 -0000      1.3
+++ arch/arm64/dev/rtkit.c      11 Jun 2022 19:27:57 -0000
@@ -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, uint
        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 *st
                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 *st
 
                                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
                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
                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;
 }
Index: arch/arm64/dev/rtkit.h
===================================================================
RCS file: /cvs/src/sys/arch/arm64/dev/rtkit.h,v
retrieving revision 1.2
diff -u -p -r1.2 rtkit.h
--- arch/arm64/dev/rtkit.h      10 Jan 2022 09:07:28 -0000      1.2
+++ arch/arm64/dev/rtkit.h      11 Jun 2022 19:27:57 -0000
@@ -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);

Reply via email to