59991624d5d9ac95c555b895b5fc6a51fc9a1d91 viocon(4) early console support diff --git a/share/man/man4/viocon.4 b/share/man/man4/viocon.4 index 4cdc1872d2c6..1498fdba58bb 100644 --- a/share/man/man4/viocon.4 +++ b/share/man/man4/viocon.4 @@ -62,3 +62,5 @@ It was ported to Kernel support was implemented by .An Taylor R. Campbell Aq Mt riastradh@NetBSD.org . .Pp +Early console support was implemented by +.An Emile So iMil Sc Heitor Aq Mt imil@NetBSD.org . diff --git a/sys/arch/x86/x86/consinit.c b/sys/arch/x86/x86/consinit.c index b300fb4aa4e8..f24f80d5c846 100644 --- a/sys/arch/x86/x86/consinit.c +++ b/sys/arch/x86/x86/consinit.c @@ -109,6 +109,17 @@ __KERNEL_RCSID(0, "$NetBSD: consinit.c,v 1.44 2025/11/29 01:33:40 manu Exp $"); #include #endif +#include "viocon.h" +#include "virtio_mmio.h" +#if (NVIOCON > 0) && (NVIRTIO_MMIO > 0) +#include +#include +#include +#include /* for kernel_map */ +#endif + +#include "pv.h" + #ifndef CONSDEVNAME #define CONSDEVNAME "pc" #endif @@ -159,6 +170,40 @@ int comkgdbmode = KGDB_DEVMODE; #endif /* KGDB */ +/* XXX only on VirtIO MMIO on pvbus for now, MMIO on ACPI could be added */ +#if (NVIOCON > 0) && (NVIRTIO_MMIO > 0) +static int +viocon_early_probe(void) +{ + struct mmio_cmdline_node *mmio_node; + + virtio_mmio_cmdline_parse(); + + SLIST_FOREACH(mmio_node, &virtio_mmio_cmdline_devs, n_nodes) { + bus_space_handle_t bsh; + + if (_x86_memio_map(mmio_node->margs.bst, + mmio_node->margs.baseaddr, mmio_node->margs.sz, 0, &bsh) != 0) { + aprint_error("%s: failed to map MMIO region at " + "%#" PRIxPADDR "\n", __func__,\ + mmio_node->margs.baseaddr); + continue; + } + + aprint_verbose("mmio addr:%#" PRIxPADDR "\n", + mmio_node->margs.baseaddr); + + if (viocon_earlyinit(mmio_node->margs.bst, bsh) == 0) + return 0; + + _x86_memio_unmap(mmio_node->margs.bst, bsh, mmio_node->margs.sz, NULL); + } + + aprint_error("%s: no virtio console found\n", __func__); + return -1; +} +#endif + /* * consinit: * initialize the system console. @@ -268,6 +313,19 @@ dokbd: error); return; } +#if (NVIOCON > 0) && (NVIRTIO_MMIO > 0) + if (!strcmp(console_devname, "viocon")) { + /* We need uvm to be ready before we can map the MMIO region */ + if (!kernel_map) { + initted = 0; + return; + } +#if NPV > 0 + if (viocon_early_probe() == 0) + return; +#endif + } +#endif #if (NCOM > 0) if (!strcmp(console_devname, "com")) { int addr = consinfo->addr; diff --git a/sys/dev/virtio/files.virtio b/sys/dev/virtio/files.virtio index 4e399624ab0b..8d3d8def6ea3 100644 --- a/sys/dev/virtio/files.virtio +++ b/sys/dev/virtio/files.virtio @@ -3,8 +3,8 @@ # XXX the contents of the following included file should be moved here include "dev/pci/files.virtio" -file dev/virtio/virtio_mmio.c virtio_mmio +file dev/virtio/virtio_mmio.c virtio_mmio needs-flag device viocon attach viocon at virtio -file dev/virtio/viocon.c viocon +file dev/virtio/viocon.c viocon needs-flag diff --git a/sys/dev/virtio/viocon.c b/sys/dev/virtio/viocon.c index e19ed91a892c..e452dd9780e3 100644 --- a/sys/dev/virtio/viocon.c +++ b/sys/dev/virtio/viocon.c @@ -17,8 +17,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define VIOCON_CONSOLE - #include __KERNEL_RCSID(0, "$NetBSD: viocon.c,v 1.10 2024/08/05 19:13:34 riastradh Exp $"); @@ -35,10 +33,11 @@ __KERNEL_RCSID(0, "$NetBSD: viocon.c,v 1.10 2024/08/05 19:13:34 riastradh Exp $" #include #include -#ifdef VIOCON_CONSOLE #include -#endif +#include +#include +#define VIRTIO_PRIVATE #include #include @@ -124,12 +123,10 @@ struct viocon_port { 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 { @@ -166,11 +163,10 @@ 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); -#endif +static void viocon_early_putc(dev_t, int); CFATTACH_DECL_NEW(viocon, sizeof(struct viocon_softc), viocon_match, viocon_attach, /*detach*/NULL, /*activate*/NULL); @@ -202,7 +198,65 @@ dev2port(dev_t dev) return dev2sc(dev)->sc_ports[VIOCONPORT(dev)]; } -int viocon_match(struct device *parent, struct cfdata *match, void *aux) +static struct { + bus_space_tag_t ec_bst; + bus_space_handle_t ec_bsh; + bus_addr_t ec_reg_offset; +} early_console; + +static void +viocon_early_putc(dev_t dev, int c) +{ + bus_space_write_4(early_console.ec_bst, early_console.ec_bsh, + early_console.ec_reg_offset, c); +} + +int +viocon_earlyinit(bus_space_tag_t bst, bus_space_handle_t bsh) +{ + static struct consdev viocon_early_consdev = { + .cn_putc = viocon_early_putc, + .cn_getc = NULL, + .cn_pollc = NULL, + .cn_dev = NODEV, + .cn_pri = CN_NORMAL + }; + + if (bus_space_read_4(bst, bsh, VIRTIO_MMIO_MAGIC_VALUE) != + VIRTIO_MMIO_MAGIC) { + return -1; + } + + if (bus_space_read_4(bst, bsh, VIRTIO_MMIO_DEVICE_ID) != + VIRTIO_DEVICE_ID_CONSOLE) { + return -1; + } + + if (!(bus_space_read_4(bst, bsh, VIRTIO_MMIO_DEVICE_FEATURES) & + VIRTIO_CONSOLE_F_EMERG_WRITE)) { + return -1; + } + + /* + * https://docs.oasis-open.org/virtio/virtio/v1.3/csd01/virtio-v1.3-csd01.html#x1-3250004 + * emerg_wr is 32 bits long + */ + if (bus_space_subregion(bst, bsh, + VIRTIO_MMIO_CONFIG + VIRTIO_CONSOLE_EMERG_WR_OFFSET, + sizeof(uint32_t), &early_console.ec_bsh) != 0) { + return -1; + } + + early_console.ec_bst = bst; + early_console.ec_reg_offset = 0; /* already adjusted by subregion */ + + cn_tab = &viocon_early_consdev; + + return 0; +} + +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) @@ -248,7 +302,6 @@ 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, @@ -260,7 +313,6 @@ viocon_attach(struct device *parent, struct device *self, void *aux) aprint_normal_dev(sc->sc_dev, "console\n"); cn_tab = &sc->sc_ports[0]->vp_cntab; } -#endif return; err: @@ -668,8 +720,6 @@ vioconioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) return ENOTTY; } -#ifdef VIOCON_CONSOLE - static void viocon_cnpollc(dev_t dev, int on) { @@ -739,5 +789,3 @@ viocon_cnputc(dev_t dev, int c) KERNEL_UNLOCK_ONE(NULL); splx(s); } - -#endif diff --git a/sys/dev/virtio/virtio_vioconvar.h b/sys/dev/virtio/virtio_vioconvar.h new file mode 100644 index 000000000000..6d75186ff0b1 --- /dev/null +++ b/sys/dev/virtio/virtio_vioconvar.h @@ -0,0 +1,9 @@ + +#ifndef _VIRTIO_VIOCONVAR_H_ +#define _VIRTIO_VIOCONVAR_H_ + +#include + +int viocon_earlyinit(bus_space_tag_t, bus_space_handle_t); + +#endif /* _VIRTIO_VIOCONVAR_H_ */