5821d8849470675a8a546db6a16ce16ae3dbc60c MMIO cmdline rework diff --git a/sys/arch/x86/pv/pvbus.c b/sys/arch/x86/pv/pvbus.c index 85946ea104a8..62020e6bd1a2 100644 --- a/sys/arch/x86/pv/pvbus.c +++ b/sys/arch/x86/pv/pvbus.c @@ -44,7 +44,6 @@ static int _pv_dma_may_bounce(bus_dma_tag_t, bus_dmamap_t, int, int *); static int pv_match(device_t, cfdata_t, void *); static void pv_attach(device_t, device_t, void *); -static int pv_submatch(device_t, cfdata_t, const int *, void *); struct x86_bus_dma_tag pvbus_bus_dma_tag = { ._tag_needs_free = 0, @@ -71,7 +70,6 @@ _pv_dma_may_bounce(bus_dma_tag_t t, bus_dmamap_t map, int flags, static int pv_match(device_t parent, cfdata_t match, void *aux) { - return 1; } @@ -79,6 +77,7 @@ static void pv_attach(device_t parent, device_t self, void *aux) { struct pv_attach_args pvaa; + struct mmio_cmdline_node *mmio_node; pvaa.pvaa_memt = x86_bus_space_mem; pvaa.pvaa_dmat = &pvbus_bus_dma_tag; @@ -86,17 +85,16 @@ pv_attach(device_t parent, device_t self, void *aux) aprint_naive("\n"); aprint_normal("\n"); - config_found(self, &pvaa, NULL, CFARGS(.search = pv_submatch)); -} + pvaa.mmio_node = NULL; -static int -pv_submatch(device_t parent, cfdata_t cf, const int *ldesc, void *aux) -{ - struct pv_attach_args *pvaa = aux; + /* Non MMIO devices */ + while (config_found(self, &pvaa, NULL, CFARGS_NONE) != NULL) + continue; + + virtio_mmio_cmdline_parse(); - if (config_probe(parent, cf, pvaa)) { - config_attach(parent, cf, pvaa, NULL, CFARGS_NONE); - return 0; + SLIST_FOREACH(mmio_node, &virtio_mmio_cmdline_devs, n_nodes) { + pvaa.mmio_node = mmio_node; + config_found(self, &pvaa, NULL, CFARGS_NONE); } - return 0; } diff --git a/sys/arch/x86/pv/pvvar.h b/sys/arch/x86/pv/pvvar.h index 607f6f0a2ffa..414ce5b7c63f 100644 --- a/sys/arch/x86/pv/pvvar.h +++ b/sys/arch/x86/pv/pvvar.h @@ -32,6 +32,8 @@ #ifndef _PVBUS_PVVAR_H_ #define _PVBUS_PVVAR_H_ +#include + struct pv_softc { device_t sc_dev; }; @@ -41,8 +43,9 @@ struct pvbus_attach_args { }; struct pv_attach_args { - bus_space_tag_t pvaa_memt; - bus_dma_tag_t pvaa_dmat; + bus_space_tag_t pvaa_memt; + bus_dma_tag_t pvaa_dmat; + struct mmio_cmdline_node *mmio_node; }; #endif diff --git a/sys/dev/virtio/arch/x86/virtio_mmio_cmdline.c b/sys/dev/virtio/arch/x86/virtio_mmio_cmdline.c index 18a0ce9f8bc3..92aca13eced4 100644 --- a/sys/dev/virtio/arch/x86/virtio_mmio_cmdline.c +++ b/sys/dev/virtio/arch/x86/virtio_mmio_cmdline.c @@ -58,6 +58,7 @@ #include #include #include +#include #include #include @@ -65,28 +66,24 @@ #include #include #include +#include +#include #include #include "ioapic.h" #define VMMIOSTR "virtio_mmio.device=" -struct mmio_args { - uint64_t sz; - uint64_t baseaddr; - uint64_t irq; - uint64_t id; -}; - struct virtio_mmio_cmdline_softc { struct virtio_mmio_softc sc_msc; struct mmio_args margs; }; +struct mmio_cmdline_devs_head virtio_mmio_cmdline_devs = + SLIST_HEAD_INITIALIZER(virtio_mmio_cmdline_devs); + static int virtio_mmio_cmdline_match(device_t, cfdata_t, void *); static void virtio_mmio_cmdline_attach(device_t, device_t, void *); -static int virtio_mmio_cmdline_do_attach(device_t, - struct pv_attach_args *, struct mmio_args *); static int virtio_mmio_cmdline_detach(device_t, int); static int virtio_mmio_cmdline_rescan(device_t, const char *, const int *); static int virtio_mmio_cmdline_alloc_interrupts(struct virtio_mmio_softc *); @@ -98,20 +95,14 @@ CFATTACH_DECL3_NEW(mmio_cmdline, virtio_mmio_cmdline_detach, NULL, virtio_mmio_cmdline_rescan, NULL, 0); -static int -virtio_mmio_cmdline_match(device_t parent, cfdata_t match, void *aux) -{ - if (strstr(xen_start_info.cmd_line, VMMIOSTR) == NULL) - return 0; - - return 1; -} -static void +static int parsearg(struct mmio_args *margs, const char *arg) { char *p; + /* Bus space type */ + margs->bst = x86_bus_space_mem; /* */ margs->sz = strtoull(arg, (char **)&p, 0); if ((margs->sz == 0) || (margs->sz == UINT64_MAX)) @@ -180,88 +171,96 @@ parsearg(struct mmio_args *margs, const char *arg) if (*p) goto bad; - return; + return 0; bad: aprint_error("Error parsing virtio_mmio parameter: %s\n", arg); + return -1; } -static void -virtio_mmio_cmdline_attach(device_t parent, device_t self, void *aux) +void +virtio_mmio_cmdline_parse(void) { - struct virtio_mmio_cmdline_softc *sc = device_private(self); - struct pv_attach_args *pvaa = aux; - struct mmio_args *margs = &sc->margs; int keylen = strlen(VMMIOSTR); - char *next; - static char cmdline[LINE_MAX], *parg = NULL; + char tmpcmdline[sizeof(xen_start_info.cmd_line)]; + struct mmio_args margs; + struct mmio_cmdline_node *mmio_node; + static bool mmio_cmdline_parsed = false; - aprint_normal("\n"); - aprint_naive("\n"); + if (mmio_cmdline_parsed) + return; - if (parg == NULL) { /* first pass */ - strlcpy(cmdline, xen_start_info.cmd_line, sizeof(cmdline)); - aprint_verbose_dev(self, "kernel parameters: %s\n", - cmdline); - parg = strstr(cmdline, VMMIOSTR); - } + mmio_cmdline_parsed = true; - if (parg != NULL) { - parg += keylen; - if (!*parg) - return; - - next = parg; - while (*next && *next != ' ') /* find end of argument */ - next++; - if (*next) { /* space */ - *next++ = '\0'; /* end the argument string */ - next = strstr(next, VMMIOSTR); - } + strlcpy(tmpcmdline, xen_start_info.cmd_line, sizeof(tmpcmdline)); - aprint_normal_dev(self, "viommio: %s\n", parg); - parsearg(margs, parg); + for (char *p = strstr(tmpcmdline, VMMIOSTR); + (p = strstr(p, VMMIOSTR)) != NULL && strlen(p) > keylen;) { + char *end = strchr(p, ' '); + p += keylen; - if (virtio_mmio_cmdline_do_attach(self, pvaa, margs)) - return; + if (end) + while (*end == ' ') + *end++ = 0; - if (next) { - parg = next; - config_found(parent, pvaa, NULL, CFARGS_NONE); + if (parsearg(&margs, p) == 0) { + mmio_node = kmem_zalloc(sizeof(*mmio_node), KM_SLEEP); + mmio_node->margs = margs; + + SLIST_INSERT_HEAD(&virtio_mmio_cmdline_devs, + mmio_node, n_nodes); } + + if (end) + p = end; } } static int -virtio_mmio_cmdline_do_attach(device_t self, - struct pv_attach_args *pvaa, - struct mmio_args *margs) +virtio_mmio_cmdline_match(device_t parent, cfdata_t match, void *aux) +{ + struct pv_attach_args *pvaa = aux; + + if (pvaa->mmio_node != NULL) + return 1; + + return 0; +} + +static void +virtio_mmio_cmdline_attach(device_t parent, device_t self, void *aux) { + struct pv_attach_args *pvaa = aux; + struct mmio_cmdline_node *mmio_node = pvaa->mmio_node; struct virtio_mmio_cmdline_softc *sc = device_private(self); struct virtio_mmio_softc *const msc = &sc->sc_msc; struct virtio_softc *const vsc = &msc->sc_sc; int error; + aprint_normal("\n"); + aprint_naive("\n"); + + aprint_normal_dev(self, "viommio: @%#" PRIxPADDR "\n", + mmio_node->margs.baseaddr); + msc->sc_iot = pvaa->pvaa_memt; vsc->sc_dmat = pvaa->pvaa_dmat; - msc->sc_iosize = margs->sz; + msc->sc_iosize = mmio_node->margs.sz; vsc->sc_dev = self; + sc->margs = mmio_node->margs; - error = bus_space_map(msc->sc_iot, margs->baseaddr, margs->sz, 0, - &msc->sc_ioh); + error = bus_space_map(msc->sc_iot, mmio_node->margs.baseaddr, + mmio_node->margs.sz, 0, &msc->sc_ioh); if (error) { - aprint_error_dev(self, "couldn't map %#" PRIx64 ": %d", - margs->baseaddr, error); - return error; + aprint_error_dev(self, "couldn't map %#" PRIxPADDR ": %d", + mmio_node->margs.baseaddr, error); + return; } - msc->sc_alloc_interrupts = virtio_mmio_cmdline_alloc_interrupts; msc->sc_free_interrupts = virtio_mmio_cmdline_free_interrupts; virtio_mmio_common_attach(msc); virtio_mmio_cmdline_rescan(self, "virtio", NULL); - - return 0; } static int diff --git a/sys/dev/virtio/virtio_mmio.c b/sys/dev/virtio/virtio_mmio.c index ba9307b198e0..97c17a5a3814 100644 --- a/sys/dev/virtio/virtio_mmio.c +++ b/sys/dev/virtio/virtio_mmio.c @@ -66,39 +66,9 @@ __KERNEL_RCSID(0, "$NetBSD: virtio_mmio.c,v 1.15 2025/07/26 14:18:14 martin Exp #include #include -#define VIRTIO_PRIVATE +#include #include -#define VIRTIO_MMIO_MAGIC ('v' | 'i' << 8 | 'r' << 16 | 't' << 24) - -#define VIRTIO_MMIO_MAGIC_VALUE 0x000 -#define VIRTIO_MMIO_VERSION 0x004 -#define VIRTIO_MMIO_DEVICE_ID 0x008 -#define VIRTIO_MMIO_VENDOR_ID 0x00c -#define VIRTIO_MMIO_DEVICE_FEATURES 0x010 /* "HostFeatures" in v1 */ -#define VIRTIO_MMIO_DEVICE_FEATURES_SEL 0x014 /* "HostFeaturesSel" in v1 */ -#define VIRTIO_MMIO_DRIVER_FEATURES 0x020 /* "GuestFeatures" in v1 */ -#define VIRTIO_MMIO_DRIVER_FEATURES_SEL 0x024 /* "GuestFeaturesSel" in v1 */ -#define VIRTIO_MMIO_V1_GUEST_PAGE_SIZE 0x028 -#define VIRTIO_MMIO_QUEUE_SEL 0x030 -#define VIRTIO_MMIO_QUEUE_NUM_MAX 0x034 -#define VIRTIO_MMIO_QUEUE_NUM 0x038 -#define VIRTIO_MMIO_V1_QUEUE_ALIGN 0x03c -#define VIRTIO_MMIO_V1_QUEUE_PFN 0x040 -#define VIRTIO_MMIO_QUEUE_READY 0x044 -#define VIRTIO_MMIO_QUEUE_NOTIFY 0x050 -#define VIRTIO_MMIO_INTERRUPT_STATUS 0x060 -#define VIRTIO_MMIO_INTERRUPT_ACK 0x064 -#define VIRTIO_MMIO_STATUS 0x070 -#define VIRTIO_MMIO_V2_QUEUE_DESC_LOW 0x080 -#define VIRTIO_MMIO_V2_QUEUE_DESC_HIGH 0x084 -#define VIRTIO_MMIO_V2_QUEUE_AVAIL_LOW 0x090 -#define VIRTIO_MMIO_V2_QUEUE_AVAIL_HIGH 0x094 -#define VIRTIO_MMIO_V2_QUEUE_USED_LOW 0x0a0 -#define VIRTIO_MMIO_V2_QUEUE_USED_HIGH 0x0a4 -#define VIRTIO_MMIO_V2_CONFIG_GEN 0x0fc -#define VIRTIO_MMIO_CONFIG 0x100 - /* * MMIO configuration space for virtio-mmio v1 is in guest byte order. * @@ -116,7 +86,6 @@ __KERNEL_RCSID(0, "$NetBSD: virtio_mmio.c,v 1.15 2025/07/26 14:18:14 martin Exp # define STRUCT_ENDIAN LITTLE_ENDIAN #endif - static void virtio_mmio_kick(struct virtio_softc *, uint16_t); static uint16_t virtio_mmio_read_queue_size(struct virtio_softc *, uint16_t); static void virtio_mmio_v1_setup_queue(struct virtio_softc *, uint16_t, uint64_t); @@ -128,7 +97,7 @@ static int virtio_mmio_alloc_interrupts(struct virtio_softc *); static void virtio_mmio_free_interrupts(struct virtio_softc *); static int virtio_mmio_setup_interrupts(struct virtio_softc *, int); -static uint32_t +uint32_t virtio_mmio_reg_read(struct virtio_mmio_softc *sc, bus_addr_t reg) { uint32_t val; diff --git a/sys/dev/virtio/virtio_mmioreg.h b/sys/dev/virtio/virtio_mmioreg.h new file mode 100644 index 000000000000..b0ccfa71e330 --- /dev/null +++ b/sys/dev/virtio/virtio_mmioreg.h @@ -0,0 +1,64 @@ +/* $NetBSD$ */ +/* + * Copyright (c) 2018 Jonathan A. Kollasch + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VIRTIO_MMIOREG_H_ +#define _VIRTIO_MMIOREG_H_ + +#define VIRTIO_MMIO_MAGIC ('v' | 'i' << 8 | 'r' << 16 | 't' << 24) + +#define VIRTIO_MMIO_MAGIC_VALUE 0x000 +#define VIRTIO_MMIO_VERSION 0x004 +#define VIRTIO_MMIO_DEVICE_ID 0x008 +#define VIRTIO_MMIO_VENDOR_ID 0x00c +#define VIRTIO_MMIO_DEVICE_FEATURES 0x010 /* "HostFeatures" in v1 */ +#define VIRTIO_MMIO_DEVICE_FEATURES_SEL 0x014 /* "HostFeaturesSel" in v1 */ +#define VIRTIO_MMIO_DRIVER_FEATURES 0x020 /* "GuestFeatures" in v1 */ +#define VIRTIO_MMIO_DRIVER_FEATURES_SEL 0x024 /* "GuestFeaturesSel" in v1 */ +#define VIRTIO_MMIO_V1_GUEST_PAGE_SIZE 0x028 +#define VIRTIO_MMIO_QUEUE_SEL 0x030 +#define VIRTIO_MMIO_QUEUE_NUM_MAX 0x034 +#define VIRTIO_MMIO_QUEUE_NUM 0x038 +#define VIRTIO_MMIO_V1_QUEUE_ALIGN 0x03c +#define VIRTIO_MMIO_V1_QUEUE_PFN 0x040 +#define VIRTIO_MMIO_QUEUE_READY 0x044 +#define VIRTIO_MMIO_QUEUE_NOTIFY 0x050 +#define VIRTIO_MMIO_INTERRUPT_STATUS 0x060 +#define VIRTIO_MMIO_INTERRUPT_ACK 0x064 +#define VIRTIO_MMIO_STATUS 0x070 +#define VIRTIO_MMIO_V2_QUEUE_DESC_LOW 0x080 +#define VIRTIO_MMIO_V2_QUEUE_DESC_HIGH 0x084 +#define VIRTIO_MMIO_V2_QUEUE_AVAIL_LOW 0x090 +#define VIRTIO_MMIO_V2_QUEUE_AVAIL_HIGH 0x094 +#define VIRTIO_MMIO_V2_QUEUE_USED_LOW 0x0a0 +#define VIRTIO_MMIO_V2_QUEUE_USED_HIGH 0x0a4 +#define VIRTIO_MMIO_V2_CONFIG_GEN 0x0fc +#define VIRTIO_MMIO_CONFIG 0x100 + +/* VirtIO Console MMIO register offsets */ +#define VIRTIO_CONSOLE_EMERG_WR_OFFSET 8 /* from VIRTIO_MMIO_CONFIG */ + +#endif /* _VIRTIO_MMIOREG_H_ */ diff --git a/sys/dev/virtio/virtio_mmiovar.h b/sys/dev/virtio/virtio_mmiovar.h index c95ec285287b..14465a1e2161 100644 --- a/sys/dev/virtio/virtio_mmiovar.h +++ b/sys/dev/virtio/virtio_mmiovar.h @@ -28,6 +28,8 @@ #ifndef _VIRTIO_MMIOVAR_H_ #define _VIRTIO_MMIOVAR_H_ +#define VIRTIO_PRIVATE + #include /* XXX: move to non-pci */ struct virtio_mmio_softc { @@ -46,9 +48,28 @@ struct virtio_mmio_softc { }; +struct mmio_args { + bus_space_tag_t bst; + uint64_t sz; + paddr_t baseaddr; + uint64_t irq; + uint64_t id; +}; + +struct mmio_cmdline_node { + struct mmio_args margs; + + SLIST_ENTRY(mmio_cmdline_node) n_nodes; +}; + +SLIST_HEAD(mmio_cmdline_devs_head, mmio_cmdline_node); +extern struct mmio_cmdline_devs_head virtio_mmio_cmdline_devs; + +uint32_t virtio_mmio_reg_read(struct virtio_mmio_softc *, bus_addr_t); bool virtio_mmio_common_probe_present(struct virtio_mmio_softc *); void virtio_mmio_common_attach(struct virtio_mmio_softc *); int virtio_mmio_common_detach(struct virtio_mmio_softc *, int); int virtio_mmio_intr(void *); +void virtio_mmio_cmdline_parse(void); #endif /* _VIRTIO_MMIOVAR_H_ */