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@
-# $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
#
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?
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
-# $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
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?
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
-# $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
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
-/* $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 <dlg@openbsd.org>
*
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)
{
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;
};
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;
}
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) {
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)
--- /dev/null
+/* $OpenBSD: aplsart.c,v 1.1 2022/06/12 16:00:12 kettenis Exp $ */
+/*
+ * Copyright (c) 2022 Mark Kettenis <kettenis@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;
+}
-/* $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 <kettenis@openbsd.org>
*
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;
-/* $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 <kettenis@openbsd.org>
*
#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);
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)
{
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);
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;
}
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;
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;
}
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;
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;
}
break;
}
- printf("unhandled endpoint %d\n", msg.data1);
+ printf("%s: unhandled endpoint %d\n", __func__, msg.data1);
return EIO;
}
}
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;
free(state, M_DEVBUF, sizeof(*state));
return NULL;
}
+ state->rk = rk;
return state;
}
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);