Message ID | 0e58df1510d7d8c0186da6620882b7c4e4035ab0.1670839220.git.viresh.kumar@linaro.org (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | toolstack support for generic virtio devices on Arm | expand |
On Mon, Dec 12, 2022 at 03:35:53PM +0530, Viresh Kumar wrote: > This patch adds basic support for configuring and assisting generic > Virtio backends, which could run in any domain. > > An example of domain configuration for mmio based Virtio I2C device is: > virtio = ["type=virtio,device22,transport=mmio"] > > To make this work on Arm, allocate Virtio MMIO params (IRQ and memory > region) and pass them to the backend and update guest device-tree to > create a DT node for the Virtio devices. > > Add special support for I2C and GPIO devices, which require the > "compatible" DT property to be set, among other device specific > properties. Support for generic virtio devices is also added, which just > need a MMIO node but not any special DT properties, for such devices the > user needs to pass "virtio,device" in the "type" string. > > The parsing of generic virtio device configurations will be done in a > separate commit. > > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Anthony PERARD <anthony.perard@citrix.com> Thanks,
On Mon, Dec 12, 2022 at 12:10 PM Viresh Kumar <viresh.kumar@linaro.org> wrote: Hello Viresh [sorry for the possible format issues] This patch adds basic support for configuring and assisting generic > Virtio backends, which could run in any domain. > > An example of domain configuration for mmio based Virtio I2C device is: > virtio = ["type=virtio,device22,transport=mmio"] > > To make this work on Arm, allocate Virtio MMIO params (IRQ and memory > region) and pass them to the backend and update guest device-tree to > create a DT node for the Virtio devices. > > Add special support for I2C and GPIO devices, which require the > "compatible" DT property to be set, among other device specific > properties. Support for generic virtio devices is also added, which just > need a MMIO node but not any special DT properties, for such devices the > user needs to pass "virtio,device" in the "type" string. > > The parsing of generic virtio device configurations will be done in a > separate commit. > > Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> > Reviewed-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com> with one NIT addressed ... > --- > tools/libs/light/Makefile | 1 + > tools/libs/light/libxl_arm.c | 100 +++++++++++++++ > tools/libs/light/libxl_create.c | 4 + > tools/libs/light/libxl_internal.h | 6 + > tools/libs/light/libxl_types.idl | 18 +++ > tools/libs/light/libxl_types_internal.idl | 1 + > tools/libs/light/libxl_virtio.c | 144 ++++++++++++++++++++++ > 7 files changed, 274 insertions(+) > create mode 100644 tools/libs/light/libxl_virtio.c > > diff --git a/tools/libs/light/Makefile b/tools/libs/light/Makefile > index 374be1cfab25..4fddcc6f51d7 100644 > --- a/tools/libs/light/Makefile > +++ b/tools/libs/light/Makefile > @@ -106,6 +106,7 @@ OBJS-y += libxl_vdispl.o > OBJS-y += libxl_pvcalls.o > OBJS-y += libxl_vsnd.o > OBJS-y += libxl_vkb.o > +OBJS-y += libxl_virtio.o > OBJS-y += libxl_genid.o > OBJS-y += _libxl_types.o > OBJS-y += libxl_flask.o > diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c > index fa3d61f1e882..292b31881210 100644 > --- a/tools/libs/light/libxl_arm.c > +++ b/tools/libs/light/libxl_arm.c > @@ -113,6 +113,19 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc, > } > } > > + for (i = 0; i < d_config->num_virtios; i++) { > + libxl_device_virtio *virtio = &d_config->virtios[i]; > + > + if (virtio->transport != LIBXL_VIRTIO_TRANSPORT_MMIO) > + continue; > + > + rc = alloc_virtio_mmio_params(gc, &virtio->base, &virtio->irq, > + &virtio_mmio_base, > &virtio_mmio_irq); > + > + if (rc) > + return rc; > + } > + > /* > * Every virtio-mmio device uses one emulated SPI. If Virtio devices > are > * present, make sure that we allocate enough SPIs for them. > @@ -956,6 +969,79 @@ static int make_virtio_mmio_node(libxl__gc *gc, void > *fdt, uint64_t base, > return fdt_end_node(fdt); > } > > +/* > + * The DT bindings for GPIO device are present here: > ... here, s/GPIO/I2C I hope this could be done when committing ... > + * > + * > https://www.kernel.org/doc/Documentation/devicetree/bindings/i2c/i2c-virtio.yaml > + */ > +static int make_virtio_mmio_node_i2c(libxl__gc *gc, void *fdt) > +{ > + int res; > + > + res = fdt_begin_node(fdt, "i2c"); > + if (res) return res; > + > + res = fdt_property_compat(gc, fdt, 1, VIRTIO_DEVICE_TYPE_I2C); > + if (res) return res; > + > + return fdt_end_node(fdt); > +} > + > +/* > + * The DT bindings for GPIO device are present here: > + * > + * > https://www.kernel.org/doc/Documentation/devicetree/bindings/gpio/gpio-virtio.yaml > + */ > +static int make_virtio_mmio_node_gpio(libxl__gc *gc, void *fdt) > +{ > + int res; > + > + res = fdt_begin_node(fdt, "gpio"); > + if (res) return res; > + > + res = fdt_property_compat(gc, fdt, 1, VIRTIO_DEVICE_TYPE_GPIO); > + if (res) return res; > + > + res = fdt_property(fdt, "gpio-controller", NULL, 0); > + if (res) return res; > + > + res = fdt_property_cell(fdt, "#gpio-cells", 2); > + if (res) return res; > + > + res = fdt_property(fdt, "interrupt-controller", NULL, 0); > + if (res) return res; > + > + res = fdt_property_cell(fdt, "#interrupt-cells", 2); > + if (res) return res; > + > + return fdt_end_node(fdt); > +} > + > +static int make_virtio_mmio_node_device(libxl__gc *gc, void *fdt, > uint64_t base, > + uint32_t irq, const char *type, > + uint32_t backend_domid) > +{ > + int res; > + > + res = make_virtio_mmio_node_common(gc, fdt, base, irq, backend_domid); > + if (res) return res; > + > + /* Add device specific nodes */ > + if (!strcmp(type, VIRTIO_DEVICE_TYPE_I2C)) { > + res = make_virtio_mmio_node_i2c(gc, fdt); > + if (res) return res; > + } else if (!strcmp(type, VIRTIO_DEVICE_TYPE_GPIO)) { > + res = make_virtio_mmio_node_gpio(gc, fdt); > + if (res) return res; > + } else if (strcmp(type, VIRTIO_DEVICE_TYPE_GENERIC)) { > + /* Doesn't match generic virtio device */ > + LOG(ERROR, "Invalid type for virtio device: %s", type); > + return -EINVAL; > + } > + > + return fdt_end_node(fdt); > +} > + > static const struct arch_info *get_arch_info(libxl__gc *gc, > const struct xc_dom_image > *dom) > { > @@ -1277,6 +1363,20 @@ static int libxl__prepare_dtb(libxl__gc *gc, > libxl_domain_config *d_config, > } > } > > + for (i = 0; i < d_config->num_virtios; i++) { > + libxl_device_virtio *virtio = &d_config->virtios[i]; > + > + if (virtio->transport != LIBXL_VIRTIO_TRANSPORT_MMIO) > + continue; > + > + if (virtio->backend_domid != LIBXL_TOOLSTACK_DOMID) > + iommu_needed = true; > + > + FDT( make_virtio_mmio_node_device(gc, fdt, virtio->base, > + virtio->irq, virtio->type, > + virtio->backend_domid) ); > + } > + > /* > * The iommu node should be created only once for all virtio-mmio > * devices. > diff --git a/tools/libs/light/libxl_create.c > b/tools/libs/light/libxl_create.c > index 612eacfc7fac..beec3f6b6fec 100644 > --- a/tools/libs/light/libxl_create.c > +++ b/tools/libs/light/libxl_create.c > @@ -1752,6 +1752,10 @@ static void domcreate_launch_dm(libxl__egc *egc, > libxl__multidev *multidev, > libxl__device_add(gc, domid, &libxl__pvcallsif_devtype, > &d_config->pvcallsifs[i]); > > + for (i = 0; i < d_config->num_virtios; i++) > + libxl__device_add(gc, domid, &libxl__virtio_devtype, > + &d_config->virtios[i]); > + > switch (d_config->c_info.type) { > case LIBXL_DOMAIN_TYPE_HVM: > { > diff --git a/tools/libs/light/libxl_internal.h > b/tools/libs/light/libxl_internal.h > index a7c447c10e5f..97e1e66d98af 100644 > --- a/tools/libs/light/libxl_internal.h > +++ b/tools/libs/light/libxl_internal.h > @@ -166,6 +166,11 @@ > /* Convert pfn to physical address space. */ > #define pfn_to_paddr(x) ((uint64_t)(x) << XC_PAGE_SHIFT) > > +/* Virtio device types */ > +#define VIRTIO_DEVICE_TYPE_GENERIC "virtio,device" > +#define VIRTIO_DEVICE_TYPE_GPIO "virtio,device22" > +#define VIRTIO_DEVICE_TYPE_I2C "virtio,device29" > + > /* logging */ > _hidden void libxl__logv(libxl_ctx *ctx, xentoollog_level msglevel, int > errnoval, > const char *file /* may be 0 */, int line /* ignored if > !file */, > @@ -4003,6 +4008,7 @@ static inline int *libxl__device_type_get_num( > > extern const libxl__device_type libxl__vfb_devtype; > extern const libxl__device_type libxl__vkb_devtype; > +extern const libxl__device_type libxl__virtio_devtype; > extern const libxl__device_type libxl__disk_devtype; > extern const libxl__device_type libxl__nic_devtype; > extern const libxl__device_type libxl__vtpm_devtype; > diff --git a/tools/libs/light/libxl_types.idl > b/tools/libs/light/libxl_types.idl > index 9e3d33cb5a59..0cfad8508dbd 100644 > --- a/tools/libs/light/libxl_types.idl > +++ b/tools/libs/light/libxl_types.idl > @@ -278,6 +278,11 @@ libxl_vkb_backend = Enumeration("vkb_backend", [ > (2, "LINUX") > ]) > > +libxl_virtio_transport = Enumeration("virtio_transport", [ > + (0, "UNKNOWN"), > + (1, "MMIO"), > + ]) > + > libxl_passthrough = Enumeration("passthrough", [ > (0, "default"), > (1, "disabled"), > @@ -703,6 +708,18 @@ libxl_device_vkb = Struct("device_vkb", [ > ("multi_touch_num_contacts", uint32) > ]) > > +libxl_device_virtio = Struct("device_virtio", [ > + ("backend_domid", libxl_domid), > + ("backend_domname", string), > + ("type", string), > + ("transport", libxl_virtio_transport), > + ("devid", libxl_devid), > + # Note that virtio-mmio parameters (irq and base) are for internal > + # use by libxl and can't be modified. > + ("irq", uint32), > + ("base", uint64) > + ]) > + > libxl_device_disk = Struct("device_disk", [ > ("backend_domid", libxl_domid), > ("backend_domname", string), > @@ -980,6 +997,7 @@ libxl_domain_config = Struct("domain_config", [ > ("dtdevs", Array(libxl_device_dtdev, "num_dtdevs")), > ("vfbs", Array(libxl_device_vfb, "num_vfbs")), > ("vkbs", Array(libxl_device_vkb, "num_vkbs")), > + ("virtios", Array(libxl_device_virtio, "num_virtios")), > ("vtpms", Array(libxl_device_vtpm, "num_vtpms")), > ("p9s", Array(libxl_device_p9, "num_p9s")), > ("pvcallsifs", Array(libxl_device_pvcallsif, "num_pvcallsifs")), > diff --git a/tools/libs/light/libxl_types_internal.idl > b/tools/libs/light/libxl_types_internal.idl > index fb0f4f23d7c2..e24288f1a59e 100644 > --- a/tools/libs/light/libxl_types_internal.idl > +++ b/tools/libs/light/libxl_types_internal.idl > @@ -33,6 +33,7 @@ libxl__device_kind = Enumeration("device_kind", [ > (15, "VSND"), > (16, "VINPUT"), > (17, "VIRTIO_DISK"), > + (18, "VIRTIO"), > ]) > > libxl__console_backend = Enumeration("console_backend", [ > diff --git a/tools/libs/light/libxl_virtio.c > b/tools/libs/light/libxl_virtio.c > new file mode 100644 > index 000000000000..6a38def2faf5 > --- /dev/null > +++ b/tools/libs/light/libxl_virtio.c > @@ -0,0 +1,144 @@ > +/* > + * Copyright (C) 2022 Linaro Ltd. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU Lesser General Public License as > published > + * by the Free Software Foundation; version 2.1 only. with the special > + * exception on linking described in file LICENSE. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU Lesser General Public License for more details. > + */ > + > +#include "libxl_internal.h" > + > +static int libxl__device_virtio_setdefault(libxl__gc *gc, uint32_t domid, > + libxl_device_virtio *virtio, > + bool hotplug) > +{ > + return libxl__resolve_domid(gc, virtio->backend_domname, > + &virtio->backend_domid); > +} > + > +static int libxl__device_from_virtio(libxl__gc *gc, uint32_t domid, > + libxl_device_virtio *virtio, > + libxl__device *device) > +{ > + device->backend_devid = virtio->devid; > + device->backend_domid = virtio->backend_domid; > + device->devid = virtio->devid; > + device->domid = domid; > + > + device->backend_kind = LIBXL__DEVICE_KIND_VIRTIO; > + device->kind = LIBXL__DEVICE_KIND_VIRTIO; > + > + return 0; > +} > + > +static int libxl__set_xenstore_virtio(libxl__gc *gc, uint32_t domid, > + libxl_device_virtio *virtio, > + flexarray_t *back, flexarray_t > *front, > + flexarray_t *ro_front) > +{ > + const char *transport = > libxl_virtio_transport_to_string(virtio->transport); > + > + flexarray_append_pair(back, "irq", GCSPRINTF("%u", virtio->irq)); > + flexarray_append_pair(back, "base", GCSPRINTF("%lu", virtio->base)); > + flexarray_append_pair(back, "type", GCSPRINTF("%s", virtio->type)); > + flexarray_append_pair(back, "transport", GCSPRINTF("%s", transport)); > + > + flexarray_append_pair(front, "irq", GCSPRINTF("%u", virtio->irq)); > + flexarray_append_pair(front, "base", GCSPRINTF("%lu", virtio->base)); > + flexarray_append_pair(front, "type", GCSPRINTF("%s", virtio->type)); > + flexarray_append_pair(front, "transport", GCSPRINTF("%s", transport)); > + > + return 0; > +} > + > +static int libxl__virtio_from_xenstore(libxl__gc *gc, const char > *libxl_path, > + libxl_devid devid, > + libxl_device_virtio *virtio) > +{ > + const char *be_path, *tmp = NULL; > + int rc; > + > + virtio->devid = devid; > + > + rc = libxl__xs_read_mandatory(gc, XBT_NULL, > + GCSPRINTF("%s/backend", libxl_path), > + &be_path); > + if (rc) goto out; > + > + rc = libxl__backendpath_parse_domid(gc, be_path, > &virtio->backend_domid); > + if (rc) goto out; > + > + rc = libxl__xs_read_checked(gc, XBT_NULL, > + GCSPRINTF("%s/irq", be_path), &tmp); > + if (rc) goto out; > + > + if (tmp) { > + virtio->irq = strtoul(tmp, NULL, 0); > + } > + > + tmp = NULL; > + rc = libxl__xs_read_checked(gc, XBT_NULL, > + GCSPRINTF("%s/base", be_path), &tmp); > + if (rc) goto out; > + > + if (tmp) { > + virtio->base = strtoul(tmp, NULL, 0); > + } > + > + tmp = NULL; > + rc = libxl__xs_read_checked(gc, XBT_NULL, > + GCSPRINTF("%s/transport", be_path), &tmp); > + if (rc) goto out; > + > + if (tmp) { > + if (!strcmp(tmp, "mmio")) { > + virtio->transport = LIBXL_VIRTIO_TRANSPORT_MMIO; > + } else { > + return ERROR_INVAL; > + } > + } > + > + tmp = NULL; > + rc = libxl__xs_read_checked(gc, XBT_NULL, > + GCSPRINTF("%s/type", be_path), &tmp); > + if (rc) goto out; > + > + if (tmp) { > + int len = sizeof(VIRTIO_DEVICE_TYPE_GENERIC) - 1; > + > + if (!strncmp(tmp, VIRTIO_DEVICE_TYPE_GENERIC, len)) { > + virtio->type = libxl__strdup(NOGC, tmp); > + } else { > + return ERROR_INVAL; > + } > + } > + > +out: > + return rc; > +} > + > +static LIBXL_DEFINE_UPDATE_DEVID(virtio) > + > +#define libxl__add_virtios NULL > +#define libxl_device_virtio_compare NULL > + > +DEFINE_DEVICE_TYPE_STRUCT(virtio, VIRTIO, virtios, > + .set_xenstore_config = (device_set_xenstore_config_fn_t) > + libxl__set_xenstore_virtio, > + .from_xenstore = > (device_from_xenstore_fn_t)libxl__virtio_from_xenstore, > + .skip_attach = 1 > +); > + > +/* > + * Local variables: > + * mode: C > + * c-basic-offset: 4 > + * indent-tabs-mode: nil > + * End: > + */ > -- > 2.31.1.272.g89b43f80a514 > > >
diff --git a/tools/libs/light/Makefile b/tools/libs/light/Makefile index 374be1cfab25..4fddcc6f51d7 100644 --- a/tools/libs/light/Makefile +++ b/tools/libs/light/Makefile @@ -106,6 +106,7 @@ OBJS-y += libxl_vdispl.o OBJS-y += libxl_pvcalls.o OBJS-y += libxl_vsnd.o OBJS-y += libxl_vkb.o +OBJS-y += libxl_virtio.o OBJS-y += libxl_genid.o OBJS-y += _libxl_types.o OBJS-y += libxl_flask.o diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c index fa3d61f1e882..292b31881210 100644 --- a/tools/libs/light/libxl_arm.c +++ b/tools/libs/light/libxl_arm.c @@ -113,6 +113,19 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc, } } + for (i = 0; i < d_config->num_virtios; i++) { + libxl_device_virtio *virtio = &d_config->virtios[i]; + + if (virtio->transport != LIBXL_VIRTIO_TRANSPORT_MMIO) + continue; + + rc = alloc_virtio_mmio_params(gc, &virtio->base, &virtio->irq, + &virtio_mmio_base, &virtio_mmio_irq); + + if (rc) + return rc; + } + /* * Every virtio-mmio device uses one emulated SPI. If Virtio devices are * present, make sure that we allocate enough SPIs for them. @@ -956,6 +969,79 @@ static int make_virtio_mmio_node(libxl__gc *gc, void *fdt, uint64_t base, return fdt_end_node(fdt); } +/* + * The DT bindings for GPIO device are present here: + * + * https://www.kernel.org/doc/Documentation/devicetree/bindings/i2c/i2c-virtio.yaml + */ +static int make_virtio_mmio_node_i2c(libxl__gc *gc, void *fdt) +{ + int res; + + res = fdt_begin_node(fdt, "i2c"); + if (res) return res; + + res = fdt_property_compat(gc, fdt, 1, VIRTIO_DEVICE_TYPE_I2C); + if (res) return res; + + return fdt_end_node(fdt); +} + +/* + * The DT bindings for GPIO device are present here: + * + * https://www.kernel.org/doc/Documentation/devicetree/bindings/gpio/gpio-virtio.yaml + */ +static int make_virtio_mmio_node_gpio(libxl__gc *gc, void *fdt) +{ + int res; + + res = fdt_begin_node(fdt, "gpio"); + if (res) return res; + + res = fdt_property_compat(gc, fdt, 1, VIRTIO_DEVICE_TYPE_GPIO); + if (res) return res; + + res = fdt_property(fdt, "gpio-controller", NULL, 0); + if (res) return res; + + res = fdt_property_cell(fdt, "#gpio-cells", 2); + if (res) return res; + + res = fdt_property(fdt, "interrupt-controller", NULL, 0); + if (res) return res; + + res = fdt_property_cell(fdt, "#interrupt-cells", 2); + if (res) return res; + + return fdt_end_node(fdt); +} + +static int make_virtio_mmio_node_device(libxl__gc *gc, void *fdt, uint64_t base, + uint32_t irq, const char *type, + uint32_t backend_domid) +{ + int res; + + res = make_virtio_mmio_node_common(gc, fdt, base, irq, backend_domid); + if (res) return res; + + /* Add device specific nodes */ + if (!strcmp(type, VIRTIO_DEVICE_TYPE_I2C)) { + res = make_virtio_mmio_node_i2c(gc, fdt); + if (res) return res; + } else if (!strcmp(type, VIRTIO_DEVICE_TYPE_GPIO)) { + res = make_virtio_mmio_node_gpio(gc, fdt); + if (res) return res; + } else if (strcmp(type, VIRTIO_DEVICE_TYPE_GENERIC)) { + /* Doesn't match generic virtio device */ + LOG(ERROR, "Invalid type for virtio device: %s", type); + return -EINVAL; + } + + return fdt_end_node(fdt); +} + static const struct arch_info *get_arch_info(libxl__gc *gc, const struct xc_dom_image *dom) { @@ -1277,6 +1363,20 @@ static int libxl__prepare_dtb(libxl__gc *gc, libxl_domain_config *d_config, } } + for (i = 0; i < d_config->num_virtios; i++) { + libxl_device_virtio *virtio = &d_config->virtios[i]; + + if (virtio->transport != LIBXL_VIRTIO_TRANSPORT_MMIO) + continue; + + if (virtio->backend_domid != LIBXL_TOOLSTACK_DOMID) + iommu_needed = true; + + FDT( make_virtio_mmio_node_device(gc, fdt, virtio->base, + virtio->irq, virtio->type, + virtio->backend_domid) ); + } + /* * The iommu node should be created only once for all virtio-mmio * devices. diff --git a/tools/libs/light/libxl_create.c b/tools/libs/light/libxl_create.c index 612eacfc7fac..beec3f6b6fec 100644 --- a/tools/libs/light/libxl_create.c +++ b/tools/libs/light/libxl_create.c @@ -1752,6 +1752,10 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev, libxl__device_add(gc, domid, &libxl__pvcallsif_devtype, &d_config->pvcallsifs[i]); + for (i = 0; i < d_config->num_virtios; i++) + libxl__device_add(gc, domid, &libxl__virtio_devtype, + &d_config->virtios[i]); + switch (d_config->c_info.type) { case LIBXL_DOMAIN_TYPE_HVM: { diff --git a/tools/libs/light/libxl_internal.h b/tools/libs/light/libxl_internal.h index a7c447c10e5f..97e1e66d98af 100644 --- a/tools/libs/light/libxl_internal.h +++ b/tools/libs/light/libxl_internal.h @@ -166,6 +166,11 @@ /* Convert pfn to physical address space. */ #define pfn_to_paddr(x) ((uint64_t)(x) << XC_PAGE_SHIFT) +/* Virtio device types */ +#define VIRTIO_DEVICE_TYPE_GENERIC "virtio,device" +#define VIRTIO_DEVICE_TYPE_GPIO "virtio,device22" +#define VIRTIO_DEVICE_TYPE_I2C "virtio,device29" + /* logging */ _hidden void libxl__logv(libxl_ctx *ctx, xentoollog_level msglevel, int errnoval, const char *file /* may be 0 */, int line /* ignored if !file */, @@ -4003,6 +4008,7 @@ static inline int *libxl__device_type_get_num( extern const libxl__device_type libxl__vfb_devtype; extern const libxl__device_type libxl__vkb_devtype; +extern const libxl__device_type libxl__virtio_devtype; extern const libxl__device_type libxl__disk_devtype; extern const libxl__device_type libxl__nic_devtype; extern const libxl__device_type libxl__vtpm_devtype; diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl index 9e3d33cb5a59..0cfad8508dbd 100644 --- a/tools/libs/light/libxl_types.idl +++ b/tools/libs/light/libxl_types.idl @@ -278,6 +278,11 @@ libxl_vkb_backend = Enumeration("vkb_backend", [ (2, "LINUX") ]) +libxl_virtio_transport = Enumeration("virtio_transport", [ + (0, "UNKNOWN"), + (1, "MMIO"), + ]) + libxl_passthrough = Enumeration("passthrough", [ (0, "default"), (1, "disabled"), @@ -703,6 +708,18 @@ libxl_device_vkb = Struct("device_vkb", [ ("multi_touch_num_contacts", uint32) ]) +libxl_device_virtio = Struct("device_virtio", [ + ("backend_domid", libxl_domid), + ("backend_domname", string), + ("type", string), + ("transport", libxl_virtio_transport), + ("devid", libxl_devid), + # Note that virtio-mmio parameters (irq and base) are for internal + # use by libxl and can't be modified. + ("irq", uint32), + ("base", uint64) + ]) + libxl_device_disk = Struct("device_disk", [ ("backend_domid", libxl_domid), ("backend_domname", string), @@ -980,6 +997,7 @@ libxl_domain_config = Struct("domain_config", [ ("dtdevs", Array(libxl_device_dtdev, "num_dtdevs")), ("vfbs", Array(libxl_device_vfb, "num_vfbs")), ("vkbs", Array(libxl_device_vkb, "num_vkbs")), + ("virtios", Array(libxl_device_virtio, "num_virtios")), ("vtpms", Array(libxl_device_vtpm, "num_vtpms")), ("p9s", Array(libxl_device_p9, "num_p9s")), ("pvcallsifs", Array(libxl_device_pvcallsif, "num_pvcallsifs")), diff --git a/tools/libs/light/libxl_types_internal.idl b/tools/libs/light/libxl_types_internal.idl index fb0f4f23d7c2..e24288f1a59e 100644 --- a/tools/libs/light/libxl_types_internal.idl +++ b/tools/libs/light/libxl_types_internal.idl @@ -33,6 +33,7 @@ libxl__device_kind = Enumeration("device_kind", [ (15, "VSND"), (16, "VINPUT"), (17, "VIRTIO_DISK"), + (18, "VIRTIO"), ]) libxl__console_backend = Enumeration("console_backend", [ diff --git a/tools/libs/light/libxl_virtio.c b/tools/libs/light/libxl_virtio.c new file mode 100644 index 000000000000..6a38def2faf5 --- /dev/null +++ b/tools/libs/light/libxl_virtio.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2022 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; version 2.1 only. with the special + * exception on linking described in file LICENSE. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +#include "libxl_internal.h" + +static int libxl__device_virtio_setdefault(libxl__gc *gc, uint32_t domid, + libxl_device_virtio *virtio, + bool hotplug) +{ + return libxl__resolve_domid(gc, virtio->backend_domname, + &virtio->backend_domid); +} + +static int libxl__device_from_virtio(libxl__gc *gc, uint32_t domid, + libxl_device_virtio *virtio, + libxl__device *device) +{ + device->backend_devid = virtio->devid; + device->backend_domid = virtio->backend_domid; + device->devid = virtio->devid; + device->domid = domid; + + device->backend_kind = LIBXL__DEVICE_KIND_VIRTIO; + device->kind = LIBXL__DEVICE_KIND_VIRTIO; + + return 0; +} + +static int libxl__set_xenstore_virtio(libxl__gc *gc, uint32_t domid, + libxl_device_virtio *virtio, + flexarray_t *back, flexarray_t *front, + flexarray_t *ro_front) +{ + const char *transport = libxl_virtio_transport_to_string(virtio->transport); + + flexarray_append_pair(back, "irq", GCSPRINTF("%u", virtio->irq)); + flexarray_append_pair(back, "base", GCSPRINTF("%lu", virtio->base)); + flexarray_append_pair(back, "type", GCSPRINTF("%s", virtio->type)); + flexarray_append_pair(back, "transport", GCSPRINTF("%s", transport)); + + flexarray_append_pair(front, "irq", GCSPRINTF("%u", virtio->irq)); + flexarray_append_pair(front, "base", GCSPRINTF("%lu", virtio->base)); + flexarray_append_pair(front, "type", GCSPRINTF("%s", virtio->type)); + flexarray_append_pair(front, "transport", GCSPRINTF("%s", transport)); + + return 0; +} + +static int libxl__virtio_from_xenstore(libxl__gc *gc, const char *libxl_path, + libxl_devid devid, + libxl_device_virtio *virtio) +{ + const char *be_path, *tmp = NULL; + int rc; + + virtio->devid = devid; + + rc = libxl__xs_read_mandatory(gc, XBT_NULL, + GCSPRINTF("%s/backend", libxl_path), + &be_path); + if (rc) goto out; + + rc = libxl__backendpath_parse_domid(gc, be_path, &virtio->backend_domid); + if (rc) goto out; + + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/irq", be_path), &tmp); + if (rc) goto out; + + if (tmp) { + virtio->irq = strtoul(tmp, NULL, 0); + } + + tmp = NULL; + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/base", be_path), &tmp); + if (rc) goto out; + + if (tmp) { + virtio->base = strtoul(tmp, NULL, 0); + } + + tmp = NULL; + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/transport", be_path), &tmp); + if (rc) goto out; + + if (tmp) { + if (!strcmp(tmp, "mmio")) { + virtio->transport = LIBXL_VIRTIO_TRANSPORT_MMIO; + } else { + return ERROR_INVAL; + } + } + + tmp = NULL; + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/type", be_path), &tmp); + if (rc) goto out; + + if (tmp) { + int len = sizeof(VIRTIO_DEVICE_TYPE_GENERIC) - 1; + + if (!strncmp(tmp, VIRTIO_DEVICE_TYPE_GENERIC, len)) { + virtio->type = libxl__strdup(NOGC, tmp); + } else { + return ERROR_INVAL; + } + } + +out: + return rc; +} + +static LIBXL_DEFINE_UPDATE_DEVID(virtio) + +#define libxl__add_virtios NULL +#define libxl_device_virtio_compare NULL + +DEFINE_DEVICE_TYPE_STRUCT(virtio, VIRTIO, virtios, + .set_xenstore_config = (device_set_xenstore_config_fn_t) + libxl__set_xenstore_virtio, + .from_xenstore = (device_from_xenstore_fn_t)libxl__virtio_from_xenstore, + .skip_attach = 1 +); + +/* + * Local variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */
This patch adds basic support for configuring and assisting generic Virtio backends, which could run in any domain. An example of domain configuration for mmio based Virtio I2C device is: virtio = ["type=virtio,device22,transport=mmio"] To make this work on Arm, allocate Virtio MMIO params (IRQ and memory region) and pass them to the backend and update guest device-tree to create a DT node for the Virtio devices. Add special support for I2C and GPIO devices, which require the "compatible" DT property to be set, among other device specific properties. Support for generic virtio devices is also added, which just need a MMIO node but not any special DT properties, for such devices the user needs to pass "virtio,device" in the "type" string. The parsing of generic virtio device configurations will be done in a separate commit. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> --- tools/libs/light/Makefile | 1 + tools/libs/light/libxl_arm.c | 100 +++++++++++++++ tools/libs/light/libxl_create.c | 4 + tools/libs/light/libxl_internal.h | 6 + tools/libs/light/libxl_types.idl | 18 +++ tools/libs/light/libxl_types_internal.idl | 1 + tools/libs/light/libxl_virtio.c | 144 ++++++++++++++++++++++ 7 files changed, 274 insertions(+) create mode 100644 tools/libs/light/libxl_virtio.c