Re: patch review: VirtIO early console support

Emile `iMil' Heitor <[email protected]>
Newsgroups gmane.os.netbsd.devel.kernel
Message-ID <[email protected]>
For future reference, here's the patch inlined:

---8<---

c5fc57dbf69fc9832722b277cb601ebc471bbfb7 viocon(4) console support for early kernel messages
diff --git a/share/man/man4/viocon.4 b/share/man/man4/viocon.4
index 26f2bd6c26d..f6ce5da46ad 100644
--- a/share/man/man4/viocon.4
+++ b/share/man/man4/viocon.4
@@ -58,9 +58,11 @@ by
  .An Stefan Fritsch Aq Mt [email protected] .
  It was ported to
  .Nx 10.0 .
-.Sh BUGS
-Use as a kernel console for
-.Nx
-is not yet supported.
  .Pp
+Kernel support was implemented by
+.An Taylor R. Campbell Aq Mt [email protected] .
+.Pp
+Early console support was implemented by
+.An Emile So iMil Sc Heitor Aq Mt [email protected] .
+.Sh BUGS
  The multiport feature is not yet supported.
diff --git a/sys/arch/x86/conf/MICROVM.common b/sys/arch/x86/conf/MICROVM.common
index 2969150a6fa..70701f66a4d 100644
--- a/sys/arch/x86/conf/MICROVM.common
+++ b/sys/arch/x86/conf/MICROVM.common
@@ -118,3 +118,5 @@ pseudo-device	drvctl

  file-system	PUFFS
  pseudo-device	putter
+
+options		VIOCON_CONSOLE
diff --git a/sys/arch/x86/x86/consinit.c b/sys/arch/x86/x86/consinit.c
index 9ef384c2c07..78f60c4e82b 100644
--- a/sys/arch/x86/x86/consinit.c
+++ b/sys/arch/x86/x86/consinit.c
@@ -32,6 +32,7 @@ __KERNEL_RCSID(0, "$NetBSD: consinit.c,v 1.41 2025/04/30 05:15:08 imil Exp $");
  #include "opt_kgdb.h"
  #include "opt_puc.h"
  #include "opt_xen.h"
+#include "opt_viocon.h"

  #include <sys/param.h>
  #include <sys/systm.h>
@@ -104,6 +105,13 @@ __KERNEL_RCSID(0, "$NetBSD: consinit.c,v 1.41 2025/04/30 05:15:08 imil Exp $");
  #include <xen/xen.h>
  #endif

+#ifdef VIOCON_CONSOLE
+#include <dev/virtio/virtio_vioconvar.h>
+#include <dev/virtio/virtio_mmiovar.h>
+#include <dev/virtio/arch/x86/virtio_mmio_parse.h>
+#include <uvm/uvm_extern.h> /* for kernel_map */
+#endif
+
  #ifndef CONSDEVNAME
  #define CONSDEVNAME "pc"
  #endif
@@ -263,6 +271,22 @@ dokbd:
  			       error);
  		return;
  	}
+#ifdef VIOCON_CONSOLE
+	if (!strcmp(console_devname, "viocon")) {
+		/* We need uvm to be ready before we can map the MMIO region */
+		if (!kernel_map) {
+			initted = 0;
+			return;
+		}
+		/*
+		 * In x86 microvm, mmio device enumeration is done by parsing
+		 * the kernel command line
+		 */
+		enumerate_mmio_devices = mmio_args_parse;
+		if (!viocon_earlyinit())
+			return;
+	}
+#endif
  #if (NCOM > 0)
  	if (!strcmp(console_devname, "com")) {
  		int addr = consinfo->addr;
diff --git a/sys/dev/virtio/arch/x86/virtio_mmio_cmdline.c b/sys/dev/virtio/arch/x86/virtio_mmio_cmdline.c
index 18a0ce9f8bc..b55c5a03ae4 100644
--- a/sys/dev/virtio/arch/x86/virtio_mmio_cmdline.c
+++ b/sys/dev/virtio/arch/x86/virtio_mmio_cmdline.c
@@ -63,21 +63,17 @@

  #define VIRTIO_PRIVATE
  #include <dev/virtio/virtio_mmiovar.h>
+#include <dev/virtio/arch/x86/virtio_mmio_parse.h>
  #include <arch/x86/pv/pvvar.h>
  #include <xen/hypervisor.h>
+#include <uvm/uvm_extern.h>
+#include <dev/cons.h>

  #include <machine/i82093var.h>
  #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;
@@ -112,6 +108,8 @@ parsearg(struct mmio_args *margs, const char *arg)
  {
  	char *p;

+	/* Bus space type */
+	margs->bst = x86_bus_space_mem;
  	/* <size> */
  	margs->sz = strtoull(arg, (char **)&p, 0);
  	if ((margs->sz == 0) || (margs->sz == UINT64_MAX))
@@ -186,50 +184,75 @@ bad:
  	aprint_error("Error parsing virtio_mmio parameter: %s\n", arg);
  }

+int
+mmio_args_parse(struct mmio_args *margs)
+{
+	int keylen = strlen(VMMIOSTR);
+	char *next;
+	static char cmdline[LINE_MAX], *parg;
+
+	/* first pass, or emptied parg from last pass */
+	if (parg == NULL) {
+		strlcpy(cmdline, xen_start_info.cmd_line, sizeof(cmdline));
+		parg = strstr(cmdline, VMMIOSTR);
+	}
+
+	/* no args were found */
+	if (parg == NULL) {
+		return MMIO_NO_ARG;
+	}
+
+	/* useless, no parameters */
+	if (strlen(parg) <= keylen) {
+		parg = NULL;
+		return MMIO_NO_ARG;
+	}
+
+	parg += keylen;
+
+	next = parg;
+	while (*next && *next != ' ') /* find end of argument */
+		next++;
+	if (*next) { /* space */
+		*next++ = '\0'; /* end the argument string */
+		next = strstr(next,VMMIOSTR);
+	}
+	parsearg(margs, parg);
+
+	if (next != NULL)
+		parg = next;
+
+	if (!*parg) {
+		parg = NULL;
+		return MMIO_LAST_ARG;
+	}
+
+	return MMIO_NEXT_ARG;
+}
+
  static void
  virtio_mmio_cmdline_attach(device_t parent, device_t self, void *aux)
  {
  	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;
+	int mmioarg;

  	aprint_normal("\n");
  	aprint_naive("\n");

-	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);
-	}
+	mmioarg = mmio_args_parse(margs);

-	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);
-		}
-
-		aprint_normal_dev(self, "viommio: %s\n", parg);
-		parsearg(margs, parg);
-
-		if (virtio_mmio_cmdline_do_attach(self, pvaa, margs))
-			return;
-
-		if (next) {
-			parg = next;
-			config_found(parent, pvaa, NULL, CFARGS_NONE);
-		}
-	}
+	if (mmioarg == MMIO_NO_ARG)
+		return;
+
+	aprint_normal_dev(self, "viommio: @%#" PRIxPADDR "\n", margs->baseaddr);
+
+	if (virtio_mmio_cmdline_do_attach(self, pvaa, margs))
+		return;
+
+	if (mmioarg == MMIO_NEXT_ARG)
+		config_found(parent, pvaa, NULL, CFARGS_NONE);
  }

  static int
@@ -250,11 +273,10 @@ virtio_mmio_cmdline_do_attach(device_t self,
  	error = bus_space_map(msc->sc_iot, margs->baseaddr, margs->sz, 0,
  	    &msc->sc_ioh);
  	if (error) {
-		aprint_error_dev(self, "couldn't map %#" PRIx64 ": %d",
+		aprint_error_dev(self, "couldn't map %#" PRIxPADDR ": %d",
  		    margs->baseaddr, error);
  		return error;
  	}
-
  	msc->sc_alloc_interrupts = virtio_mmio_cmdline_alloc_interrupts;
  	msc->sc_free_interrupts = virtio_mmio_cmdline_free_interrupts;

diff --git a/sys/dev/virtio/arch/x86/virtio_mmio_parse.h b/sys/dev/virtio/arch/x86/virtio_mmio_parse.h
new file mode 100644
index 00000000000..e78ac50b6d3
--- /dev/null
+++ b/sys/dev/virtio/arch/x86/virtio_mmio_parse.h
@@ -0,0 +1,41 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Emile 'iMil' Heitor.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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_MMIO_PARSE_H_
+#define _VIRTIO_MMIO_PARSE_H_
+
+#define MMIO_NEXT_ARG 2
+#define MMIO_LAST_ARG 1
+#define MMIO_NO_ARG 0
+
+int mmio_args_parse(struct mmio_args *);
+
+#endif /* _VIRTIO_MMIO_PARSE_H_ */
diff --git a/sys/dev/virtio/files.virtio b/sys/dev/virtio/files.virtio
index 4e399624ab0..4724a4c3347 100644
--- a/sys/dev/virtio/files.virtio
+++ b/sys/dev/virtio/files.virtio
@@ -5,6 +5,7 @@ include "dev/pci/files.virtio"

  file	dev/virtio/virtio_mmio.c	virtio_mmio

+defflag opt_viocon.h	VIOCON_CONSOLE
  device	viocon
  attach	viocon at virtio
  file	dev/virtio/viocon.c		viocon
diff --git a/sys/dev/virtio/viocon.c b/sys/dev/virtio/viocon.c
index 73c938936be..cce0b55c639 100644
--- a/sys/dev/virtio/viocon.c
+++ b/sys/dev/virtio/viocon.c
@@ -33,8 +33,16 @@ __KERNEL_RCSID(0, "$NetBSD: viocon.c,v 1.10 2024/08/05 19:13:34 riastradh Exp $"
  #include <sys/systm.h>
  #include <sys/tty.h>

+#include "opt_viocon.h"
+
+#ifdef VIOCON_CONSOLE
+#include <dev/cons.h>
+#include <uvm/uvm_extern.h>
+#include <dev/virtio/virtio_vioconvar.h>
+#endif
+
  #include <dev/pci/virtioreg.h>
-#include <dev/pci/virtiovar.h>
+#include <dev/virtio/virtio_mmiovar.h>

  #include "ioconf.h"

@@ -117,6 +125,13 @@ struct viocon_port {
  	uint16_t		 vp_cols;
  	u_char			*vp_rx_buf;
  	u_char			*vp_tx_buf;
+
+#ifdef VIOCON_CONSOLE
+	struct consdev		 vp_cntab;
+	unsigned int		 vp_pollpos;
+	unsigned int		 vp_polllen;
+	bool			 vp_polling;
+#endif
  };

  struct viocon_softc {
@@ -153,6 +168,26 @@ void	vioconstop(struct tty *, int);
  int	vioconioctl(dev_t, u_long, void *, int, struct lwp *);
  struct tty	*viocontty(dev_t dev);

+#ifdef VIOCON_CONSOLE
+static void viocon_cnpollc(dev_t, int);
+static int viocon_cngetc(dev_t);
+static void viocon_cnputc(dev_t, int);
+static void viocon_early_putc(dev_t, int);
+
+static uint32_t *early_console;
+static vaddr_t viocon_mmio_vaddr = 0;
+
+int (*enumerate_mmio_devices)(struct mmio_args *) = NULL;
+
+static struct consdev viocon_early_consdev = {
+    .cn_putc = viocon_early_putc,
+    .cn_getc = NULL,
+    .cn_pollc = NULL,
+    .cn_dev = NODEV,
+    .cn_pri = CN_NORMAL
+};
+#endif
+
  CFATTACH_DECL_NEW(viocon, sizeof(struct viocon_softc),
      viocon_match, viocon_attach, /*detach*/NULL, /*activate*/NULL);

@@ -183,7 +218,88 @@ dev2port(dev_t dev)
  	return dev2sc(dev)->sc_ports[VIOCONPORT(dev)];
  }

-int viocon_match(struct device *parent, struct cfdata *match, void *aux)
+#ifdef VIOCON_CONSOLE
+static void
+viocon_early_putc(dev_t dev, int c)
+{
+	*early_console = c;
+}
+
+static void
+free_viocon_mmio_vaddr(void)
+{
+	if (!viocon_mmio_vaddr)
+		return;
+
+	pmap_kremove(viocon_mmio_vaddr, PAGE_SIZE);
+	pmap_update(pmap_kernel());
+	uvm_km_free(kernel_map, viocon_mmio_vaddr, PAGE_SIZE, UVM_KMF_VAONLY);
+	viocon_mmio_vaddr = 0;
+}
+
+int
+viocon_earlyinit(void)
+{
+	struct mmio_args margs;
+	paddr_t mmio_baseaddr = 0;
+	struct virtio_mmio_softc sc;
+
+	if (enumerate_mmio_devices == NULL)
+		return -1;
+
+	while ((*enumerate_mmio_devices)(&margs)) {
+		if (!mmio_baseaddr) {
+			/* Fetch a page for early MMIO mapping */
+			viocon_mmio_vaddr = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
+			    UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
+			if (!viocon_mmio_vaddr)
+				return -1;
+			/* map a page for early virtio console */
+			mmio_baseaddr = margs.baseaddr & ~(PAGE_SIZE - 1);
+			pmap_kenter_pa(viocon_mmio_vaddr, mmio_baseaddr,
+			    VM_PROT_READ|VM_PROT_WRITE, PMAP_NOCACHE);
+			pmap_update(pmap_kernel());
+		}
+
+		sc.sc_iot = margs.bst;
+		/*
+		 * viocon_mmio_vaddr = reserved page
+		 * margs.baseaddr = pa
+		 * mmio_baseaddr = MMIO base address
+		 */
+		sc.sc_ioh = viocon_mmio_vaddr + (margs.baseaddr - mmio_baseaddr);
+		sc.sc_iosize = margs.sz;
+		sc.sc_le_regs = (BYTE_ORDER == LITTLE_ENDIAN);
+
+		aprint_verbose("mmio addr:%#" PRIxPADDR "\n", margs.baseaddr);
+
+		if (bus_space_read_4(sc.sc_iot, sc.sc_ioh,
+		    VIRTIO_MMIO_MAGIC_VALUE) != VIRTIO_MMIO_MAGIC)
+			continue;
+		if (virtio_mmio_reg_read(&sc, VIRTIO_MMIO_DEVICE_ID) !=
+		    VIRTIO_DEVICE_ID_CONSOLE)
+			continue;
+		if (!(virtio_mmio_reg_read(&sc, VIRTIO_MMIO_DEVICE_FEATURES) &
+		    VIRTIO_CONSOLE_F_EMERG_WRITE))
+			continue;
+
+		early_console =
+		    (uint32_t *)(sc.sc_ioh +
+		    VIRTIO_MMIO_CONFIG + VIRTIO_CONSOLE_EMERG_WR);
+
+		cn_tab = &viocon_early_consdev;
+
+		return 0;
+	}
+
+	free_viocon_mmio_vaddr();
+
+	return -1;
+}
+#endif
+
+int
+viocon_match(struct device *parent, struct cfdata *match, void *aux)
  {
  	struct virtio_attach_args *va = aux;
  	if (va->sc_childdevid == VIRTIO_DEVICE_ID_CONSOLE)
@@ -229,6 +345,22 @@ viocon_attach(struct device *parent, struct device *self, void *aux)

  	viocon_rx_fill(sc->sc_ports[0]);

+#ifdef VIOCON_CONSOLE
+	if (cn_tab == NULL || cn_tab->cn_dev == NODEV) {
+		sc->sc_ports[0]->vp_cntab = (struct consdev) {
+			.cn_pollc = viocon_cnpollc,
+			.cn_getc = viocon_cngetc,
+			.cn_putc = viocon_cnputc,
+			.cn_dev = VIOCONDEV(device_unit(self), 0),
+			.cn_pri = CN_REMOTE,
+		};
+		aprint_normal_dev(sc->sc_dev, "console\n");
+		cn_tab = &sc->sc_ports[0]->vp_cntab;
+		/* if a page was mapped for early console, free it */
+		free_viocon_mmio_vaddr();
+	}
+#endif
+
  	return;
  err:
  	kmem_free(sc->sc_vqs, nvqs * sizeof(sc->sc_vqs[0]));
@@ -634,3 +766,75 @@ vioconioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
  		return error2;
  	return ENOTTY;
  }
+
+#ifdef VIOCON_CONSOLE
+static void
+viocon_cnpollc(dev_t dev, int on)
+{
+	struct viocon_port *vp = dev2port(dev);
+	int s;
+
+	KASSERT((bool)on != vp->vp_polling);
+
+	s = spltty();
+	vp->vp_polling = on;
+	vioconhwiflow(vp->vp_tty, on);
+	splx(s);
+}
+
+static int
+viocon_cngetc(dev_t dev)
+{
+	struct viocon_softc *sc = dev2sc(dev);
+	struct viocon_port *vp = dev2port(dev);
+	struct virtqueue *vq = vp->vp_rx;
+	struct virtio_softc *vsc = sc->sc_virtio;
+	int slot, len;
+
+	KASSERT(vp->vp_polling);
+	while (vp->vp_polllen == 0) {
+		if (virtio_dequeue(vsc, vq, &slot, &len) == 0) {
+			KASSERTMSG(slot >= 0, "slot=%d", slot);
+			KASSERTMSG(slot < vq->vq_num, "slot=%d", slot);
+			KASSERTMSG(len > 0, "len=%d", len);
+			KASSERTMSG(len <= BUFSIZE, "len=%d", len);
+			bus_dmamap_sync(virtio_dmat(vsc), vp->vp_dmamap,
+			    slot * BUFSIZE, BUFSIZE, BUS_DMASYNC_POSTREAD);
+			vp->vp_polllen = len;
+			vp->vp_pollpos = slot * BUFSIZE;
+		}
+	}
+	KASSERT(vp->vp_pollpos <= vq->vq_num * BUFSIZE);
+	vp->vp_polllen--;
+	return vp->vp_rx_buf[vp->vp_pollpos++];
+}
+
+static void
+viocon_cnputc(dev_t dev, int c)
+{
+	struct viocon_softc *sc = dev2sc(dev);
+	struct viocon_port *vp = dev2port(dev);
+	struct virtqueue *vq = vp->vp_tx;
+	struct virtio_softc *vsc = sc->sc_virtio;
+	int slot;
+	int s, error;
+
+	s = spltty();
+	KERNEL_LOCK(1, NULL);
+	(void)viocon_tx_drain(vp, vq);
+	error = virtio_enqueue_prep(vsc, vq, &slot);
+	if (error == 0) {
+		error = virtio_enqueue_reserve(vsc, vq, slot, 1);
+		KASSERTMSG(error == 0, "error=%d", error);
+		vp->vp_tx_buf[slot * BUFSIZE] = c;
+		bus_dmamap_sync(virtio_dmat(vsc), vp->vp_dmamap,
+		    vp->vp_tx_buf - vp->vp_rx_buf + slot * BUFSIZE, 1,
+		    BUS_DMASYNC_PREWRITE);
+		virtio_enqueue_p(vsc, vq, slot, vp->vp_dmamap,
+		    vp->vp_tx_buf - vp->vp_rx_buf + slot * BUFSIZE, 1, 1);
+		virtio_enqueue_commit(vsc, vq, slot, 1);
+	}
+	KERNEL_UNLOCK_ONE(NULL);
+	splx(s);
+}
+#endif
diff --git a/sys/dev/virtio/virtio_mmio.c b/sys/dev/virtio/virtio_mmio.c
index eb827f528f7..5c3f085577b 100644
--- a/sys/dev/virtio/virtio_mmio.c
+++ b/sys/dev/virtio/virtio_mmio.c
@@ -66,39 +66,8 @@ __KERNEL_RCSID(0, "$NetBSD: virtio_mmio.c,v 1.14 2024/03/09 11:55:59 isaki Exp $
  #include <sys/device.h>
  #include <sys/mutex.h>

-#define VIRTIO_PRIVATE
  #include <dev/virtio/virtio_mmiovar.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
-
  /*
   * MMIO configuration space for virtio-mmio v1 is in guest byte order.
   *
@@ -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_mmiovar.h b/sys/dev/virtio/virtio_mmiovar.h
index c95ec285287..bcd4066b756 100644
--- a/sys/dev/virtio/virtio_mmiovar.h
+++ b/sys/dev/virtio/virtio_mmiovar.h
@@ -28,8 +28,40 @@
  #ifndef _VIRTIO_MMIOVAR_H_
  #define _VIRTIO_MMIOVAR_H_

+#define VIRTIO_PRIVATE
+
  #include <dev/pci/virtiovar.h> /* XXX: move to non-pci */

+#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
+
  struct virtio_mmio_softc {
  	struct virtio_softc	sc_sc;

@@ -46,9 +78,20 @@ struct virtio_mmio_softc {

  };

+struct mmio_args {
+	bus_space_tag_t		bst;
+	uint64_t		sz;
+	paddr_t			baseaddr;
+	uint64_t		irq;
+	uint64_t		id;
+};
+
+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 *);

+extern int (*enumerate_mmio_devices)(struct mmio_args *);
+
  #endif /* _VIRTIO_MMIOVAR_H_ */

--->8---

------------------------------------------------------------------------
Emile `iMil' Heitor <imil@{home.imil.net,NetBSD.org}> | https://imil.net
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.