From 703f17d60f7fd2885b5041eec6734804dae49de7 Mon Sep 17 00:00:00 2001 From: Bryan Venteicher Date: Tue, 19 Jan 2021 04:55:23 +0000 Subject: [PATCH] virtio_pci: Add sysctl to show current features Reviewed by: grehan (mentor) Differential Revision: https://reviews.freebsd.org/D27898 --- sys/dev/virtio/pci/virtio_pci.c | 71 ++++++++++++++++++++++++++++++++- sys/dev/virtio/pci/virtio_pci.h | 1 + sys/dev/virtio/virtio.c | 57 ++++++++++++++++---------- sys/dev/virtio/virtio.h | 5 ++- 4 files changed, 112 insertions(+), 22 deletions(-) diff --git a/sys/dev/virtio/pci/virtio_pci.c b/sys/dev/virtio/pci/virtio_pci.c index 4d6fa929ef19..1a60196b5d02 100644 --- a/sys/dev/virtio/pci/virtio_pci.c +++ b/sys/dev/virtio/pci/virtio_pci.c @@ -33,6 +33,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include @@ -85,6 +87,8 @@ static int vtpci_vq_intr_filter(void *); static void vtpci_vq_intr(void *); static void vtpci_config_intr(void *); +static void vtpci_setup_sysctl(struct vtpci_common *); + #define vtpci_setup_msi_interrupt vtpci_setup_intx_interrupt /* @@ -156,6 +160,8 @@ vtpci_init(struct vtpci_common *cn, device_t dev, bool modern) cn->vtpci_flags |= VTPCI_FLAG_NO_MSI; if (pci_find_cap(dev, PCIY_MSIX, NULL) != 0) cn->vtpci_flags |= VTPCI_FLAG_NO_MSIX; + + vtpci_setup_sysctl(cn); } int @@ -202,6 +208,7 @@ vtpci_child_detached(struct vtpci_common *cn) vtpci_release_child_resources(cn); cn->vtpci_child_feat_desc = NULL; + cn->vtpci_host_features = 0; cn->vtpci_features = 0; } @@ -246,6 +253,7 @@ vtpci_negotiate_features(struct vtpci_common *cn, { uint64_t features; + cn->vtpci_host_features = host_features; vtpci_describe_features(cn, "host", host_features); /* @@ -254,9 +262,9 @@ vtpci_negotiate_features(struct vtpci_common *cn, */ features = host_features & child_features; features = virtio_filter_transport_features(features); - vtpci_describe_features(cn, "negotiated", features); cn->vtpci_features = features; + vtpci_describe_features(cn, "negotiated", features); return (features); } @@ -930,3 +938,64 @@ vtpci_config_intr(void *xcn) if (child != NULL) VIRTIO_CONFIG_CHANGE(child); } + +static int +vtpci_feature_sysctl(struct sysctl_req *req, struct vtpci_common *cn, + uint64_t features) +{ + struct sbuf *sb; + int error; + + sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); + if (sb == NULL) + return (ENOMEM); + + error = virtio_describe_sbuf(sb, features, cn->vtpci_child_feat_desc); + sbuf_delete(sb); + + return (error); +} + +static int +vtpci_host_features_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct vtpci_common *cn; + + cn = arg1; + + return (vtpci_feature_sysctl(req, cn, cn->vtpci_host_features)); +} + +static int +vtpci_negotiated_features_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct vtpci_common *cn; + + cn = arg1; + + return (vtpci_feature_sysctl(req, cn, cn->vtpci_features)); +} + +static void +vtpci_setup_sysctl(struct vtpci_common *cn) +{ + device_t dev; + struct sysctl_ctx_list *ctx; + struct sysctl_oid *tree; + struct sysctl_oid_list *child; + + dev = cn->vtpci_dev; + ctx = device_get_sysctl_ctx(dev); + tree = device_get_sysctl_tree(dev); + child = SYSCTL_CHILDREN(tree); + + SYSCTL_ADD_INT(ctx, child, OID_AUTO, "nvqs", + CTLFLAG_RD, &cn->vtpci_nvqs, 0, "Number of virtqueues"); + + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "host_features", + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, cn, 0, + vtpci_host_features_sysctl, "A", "Features supported by the host"); + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "negotiated_features", + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, cn, 0, + vtpci_negotiated_features_sysctl, "A", "Features negotiated"); +} diff --git a/sys/dev/virtio/pci/virtio_pci.h b/sys/dev/virtio/pci/virtio_pci.h index d65ed853c33e..4c9a0e1c4cbe 100644 --- a/sys/dev/virtio/pci/virtio_pci.h +++ b/sys/dev/virtio/pci/virtio_pci.h @@ -45,6 +45,7 @@ struct vtpci_virtqueue { struct vtpci_common { device_t vtpci_dev; + uint64_t vtpci_host_features; uint64_t vtpci_features; struct vtpci_virtqueue *vtpci_vqs; int vtpci_nvqs; diff --git a/sys/dev/virtio/virtio.c b/sys/dev/virtio/virtio.c index 18eace65a12b..53b47004610e 100644 --- a/sys/dev/virtio/virtio.c +++ b/sys/dev/virtio/virtio.c @@ -119,24 +119,15 @@ virtio_feature_name(uint64_t val, struct virtio_feature_desc *desc) return (NULL); } -void -virtio_describe(device_t dev, const char *msg, - uint64_t features, struct virtio_feature_desc *desc) +int +virtio_describe_sbuf(struct sbuf *sb, uint64_t features, + struct virtio_feature_desc *desc) { - struct sbuf sb; - uint64_t val; - char *buf; const char *name; + uint64_t val; int n; - if ((buf = malloc(1024, M_TEMP, M_NOWAIT)) == NULL) { - device_printf(dev, "%s features: %#jx\n", - msg, (uintmax_t) features); - return; - } - - sbuf_new(&sb, buf, 1024, SBUF_FIXEDLEN); - sbuf_printf(&sb, "%s features: %#jx", msg, (uintmax_t) features); + sbuf_printf(sb, "%#jx", (uintmax_t) features); for (n = 0, val = 1ULL << 63; val != 0; val >>= 1) { /* @@ -147,25 +138,51 @@ virtio_describe(device_t dev, const char *msg, continue; if (n++ == 0) - sbuf_cat(&sb, " <"); + sbuf_cat(sb, " <"); else - sbuf_cat(&sb, ","); + sbuf_cat(sb, ","); name = virtio_feature_name(val, desc); if (name == NULL) - sbuf_printf(&sb, "%#jx", (uintmax_t) val); + sbuf_printf(sb, "%#jx", (uintmax_t) val); else - sbuf_cat(&sb, name); + sbuf_cat(sb, name); } if (n > 0) - sbuf_cat(&sb, ">"); + sbuf_cat(sb, ">"); - if (sbuf_finish(&sb) == 0) + return (sbuf_finish(sb)); +} + +void +virtio_describe(device_t dev, const char *msg, uint64_t features, + struct virtio_feature_desc *desc) +{ + struct sbuf sb; + char *buf; + int error; + + if ((buf = malloc(1024, M_TEMP, M_NOWAIT)) == NULL) { + error = ENOMEM; + goto out; + } + + sbuf_new(&sb, buf, 1024, SBUF_FIXEDLEN); + sbuf_printf(&sb, "%s features: ", msg); + + error = virtio_describe_sbuf(&sb, features, desc); + if (error == 0) device_printf(dev, "%s\n", sbuf_data(&sb)); sbuf_delete(&sb); free(buf, M_TEMP); + +out: + if (error != 0) { + device_printf(dev, "%s features: %#jx\n", msg, + (uintmax_t) features); + } } uint64_t diff --git a/sys/dev/virtio/virtio.h b/sys/dev/virtio/virtio.h index 85160eb18d0d..ccac57a5ad96 100644 --- a/sys/dev/virtio/virtio.h +++ b/sys/dev/virtio/virtio.h @@ -35,6 +35,7 @@ #include #include +struct sbuf; struct vq_alloc_info; /* @@ -82,7 +83,9 @@ struct virtio_pnp_match { const char *virtio_device_name(uint16_t devid); void virtio_describe(device_t dev, const char *msg, - uint64_t features, struct virtio_feature_desc *feature_desc); + uint64_t features, struct virtio_feature_desc *desc); +int virtio_describe_sbuf(struct sbuf *sb, uint64_t features, + struct virtio_feature_desc *desc); uint64_t virtio_filter_transport_features(uint64_t features); int virtio_bus_is_modern(device_t dev); void virtio_read_device_config_array(device_t dev, bus_size_t offset,