qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Akihiko Odaki <akihiko.odaki@daynix.com>
To: "Michael S. Tsirkin" <mst@redhat.com>,
	"Marcel Apfelbaum" <marcel.apfelbaum@gmail.com>,
	"Alex Williamson" <alex.williamson@redhat.com>,
	"Cédric Le Goater" <clg@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Daniel P. Berrangé" <berrange@redhat.com>,
	"Eduardo Habkost" <eduardo@habkost.net>,
	"Jason Wang" <jasowang@redhat.com>,
	"Sriram Yagnaraman" <sriram.yagnaraman@est.tech>,
	"Keith Busch" <kbusch@kernel.org>,
	"Klaus Jensen" <its@irrelevant.dk>
Cc: qemu-devel@nongnu.org, qemu-block@nongnu.org,
	 Yui Washizu <yui.washidu@gmail.com>,
	 Akihiko Odaki <akihiko.odaki@daynix.com>
Subject: [PATCH 12/14] pcie_sriov: Allow to specify VF device options
Date: Sat, 02 Dec 2023 17:00:35 +0900	[thread overview]
Message-ID: <20231202-sriov-v1-12-32b3570f7bd6@daynix.com> (raw)
In-Reply-To: <20231202-sriov-v1-0-32b3570f7bd6@daynix.com>

Specifying VF device options will be useful to create VFs based on
conventional device emulation code which have user-configurable
options.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
 docs/pcie_sriov.txt         |  2 +-
 include/hw/pci/pcie_sriov.h | 13 ++++++--
 hw/net/igb.c                |  2 +-
 hw/nvme/ctrl.c              |  2 +-
 hw/pci/pcie_sriov.c         | 73 ++++++++++++++++++++++++++++++++++++---------
 5 files changed, 72 insertions(+), 20 deletions(-)

diff --git a/docs/pcie_sriov.txt b/docs/pcie_sriov.txt
index a47aad0bfa..dc70b40ae2 100644
--- a/docs/pcie_sriov.txt
+++ b/docs/pcie_sriov.txt
@@ -52,7 +52,7 @@ setting up a BAR for a VF.
       ...
 
       /* Add and initialize the SR/IOV capability */
-      pcie_sriov_pf_init(d, 0x200, "your_virtual_dev",
+      pcie_sriov_pf_init(d, 0x200, "your_virtual_dev", NULL,
                        vf_devid, initial_vfs, total_vfs,
                        fun_offset, stride);
 
diff --git a/include/hw/pci/pcie_sriov.h b/include/hw/pci/pcie_sriov.h
index 095fb0c9ed..aa3d81fa44 100644
--- a/include/hw/pci/pcie_sriov.h
+++ b/include/hw/pci/pcie_sriov.h
@@ -15,10 +15,16 @@
 
 #include "hw/pci/pci.h"
 
+typedef struct PCIESriovVFOpts {
+    QDict *device_opts;
+    bool from_json;
+} PCIESriovVFOpts;
+
 struct PCIESriovPF {
     uint16_t num_vfs;   /* Number of virtual functions created */
     uint8_t vf_bar_type[PCI_NUM_REGIONS];   /* Store type for each VF bar */
     const char *vfname; /* Reference to the device type used for the VFs */
+    PCIESriovVFOpts *vfopts; /* Poiner to an array of VF options */
     PCIDevice **vf;     /* Pointer to an array of num_vfs VF devices */
 };
 
@@ -28,9 +34,10 @@ struct PCIESriovVF {
 };
 
 void pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
-                        const char *vfname, uint16_t vf_dev_id,
-                        uint16_t init_vfs, uint16_t total_vfs,
-                        uint16_t vf_offset, uint16_t vf_stride);
+                        const char *vfname, PCIESriovVFOpts *vfopts,
+                        uint16_t vf_dev_id, uint16_t init_vfs,
+                        uint16_t total_vfs, uint16_t vf_offset,
+                        uint16_t vf_stride);
 void pcie_sriov_pf_exit(PCIDevice *dev);
 
 /* Set up a VF bar in the SR/IOV bar area */
diff --git a/hw/net/igb.c b/hw/net/igb.c
index 8089acfea4..8168d401cb 100644
--- a/hw/net/igb.c
+++ b/hw/net/igb.c
@@ -447,7 +447,7 @@ static void igb_pci_realize(PCIDevice *pci_dev, Error **errp)
 
     pcie_ari_init(pci_dev, 0x150);
 
-    pcie_sriov_pf_init(pci_dev, IGB_CAP_SRIOV_OFFSET, TYPE_IGBVF,
+    pcie_sriov_pf_init(pci_dev, IGB_CAP_SRIOV_OFFSET, TYPE_IGBVF, NULL,
         IGB_82576_VF_DEV_ID, IGB_MAX_VF_FUNCTIONS, IGB_MAX_VF_FUNCTIONS,
         IGB_VF_OFFSET, IGB_VF_STRIDE);
 
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
index f026245d1e..91bbccb49f 100644
--- a/hw/nvme/ctrl.c
+++ b/hw/nvme/ctrl.c
@@ -8040,7 +8040,7 @@ static void nvme_init_sriov(NvmeCtrl *n, PCIDevice *pci_dev, uint16_t offset)
                                       le16_to_cpu(cap->vifrsm),
                                       NULL, NULL);
 
-    pcie_sriov_pf_init(pci_dev, offset, "nvme", vf_dev_id,
+    pcie_sriov_pf_init(pci_dev, offset, "nvme", NULL, vf_dev_id,
                        n->params.sriov_max_vfs, n->params.sriov_max_vfs,
                        NVME_VF_OFFSET, NVME_VF_STRIDE);
 
diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c
index 3ec786d341..4e73559dc1 100644
--- a/hw/pci/pcie_sriov.c
+++ b/hw/pci/pcie_sriov.c
@@ -15,8 +15,11 @@
 #include "hw/pci/pcie.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/qdev-properties.h"
+#include "monitor/qdev.h"
 #include "qemu/error-report.h"
 #include "qemu/range.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qobject.h"
 #include "qapi/error.h"
 #include "trace.h"
 
@@ -25,9 +28,10 @@ static PCIDevice *register_vf(PCIDevice *pf, int devfn,
 static void unregister_vfs(PCIDevice *dev);
 
 void pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
-                        const char *vfname, uint16_t vf_dev_id,
-                        uint16_t init_vfs, uint16_t total_vfs,
-                        uint16_t vf_offset, uint16_t vf_stride)
+                        const char *vfname, PCIESriovVFOpts *vfopts,
+                        uint16_t vf_dev_id, uint16_t init_vfs,
+                        uint16_t total_vfs, uint16_t vf_offset,
+                        uint16_t vf_stride)
 {
     uint8_t *cfg = dev->config + offset;
     uint8_t *wmask;
@@ -37,6 +41,7 @@ void pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
     dev->exp.sriov_cap = offset;
     dev->exp.sriov_pf.num_vfs = 0;
     dev->exp.sriov_pf.vfname = g_strdup(vfname);
+    dev->exp.sriov_pf.vfopts = vfopts;
     dev->exp.sriov_pf.vf = NULL;
 
     pci_set_word(cfg + PCI_SRIOV_VF_OFFSET, vf_offset);
@@ -76,6 +81,16 @@ void pcie_sriov_pf_exit(PCIDevice *dev)
     unregister_vfs(dev);
     g_free((char *)dev->exp.sriov_pf.vfname);
     dev->exp.sriov_pf.vfname = NULL;
+
+    if (dev->exp.sriov_pf.vfopts) {
+        uint8_t *cfg = dev->config + dev->exp.sriov_cap;
+
+        for (uint16_t i = 0; i < pci_get_word(cfg + PCI_SRIOV_TOTAL_VF); i++) {
+            qobject_unref(dev->exp.sriov_pf.vfopts[i].device_opts);
+        }
+
+        g_free(dev->exp.sriov_pf.vfopts);
+    }
 }
 
 void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num,
@@ -144,25 +159,50 @@ void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num,
 static PCIDevice *register_vf(PCIDevice *pf, int devfn, const char *name,
                               uint16_t vf_num)
 {
-    PCIDevice *dev = pci_new(devfn, name);
-    dev->exp.sriov_vf.pf = pf;
-    dev->exp.sriov_vf.vf_number = vf_num;
-    PCIBus *bus = pci_get_bus(pf);
+    PCIDevice *pci_dev;
+    BusState *bus = qdev_get_parent_bus(DEVICE(pf));
     Error *local_err = NULL;
 
-    qdev_realize(&dev->qdev, &bus->qbus, &local_err);
+    if (pf->exp.sriov_pf.vfopts) {
+        BusState *local_bus;
+        PCIESriovVFOpts *vfopts = pf->exp.sriov_pf.vfopts + vf_num;
+        DeviceState *dev = qdev_device_new_from_qdict(vfopts->device_opts,
+                                                      vfopts->from_json,
+                                                      &local_bus, &local_err);
+        if (!dev) {
+            error_report_err(local_err);
+            return NULL;
+        }
+
+        pci_dev = PCI_DEVICE(dev);
+
+        if (bus != local_bus) {
+            error_report("unexpected SR-IOV VF parent bus");
+            goto fail;
+        }
+    } else {
+        pci_dev = pci_new(devfn, name);
+    }
+
+    pci_dev->exp.sriov_vf.pf = pf;
+    pci_dev->exp.sriov_vf.vf_number = vf_num;
+
+    qdev_realize(&pci_dev->qdev, bus, &local_err);
     if (local_err) {
         error_report_err(local_err);
-        object_unparent(OBJECT(dev));
-        object_unref(dev);
-        return NULL;
+        goto fail;
     }
 
     /* set vid/did according to sr/iov spec - they are not used */
-    pci_config_set_vendor_id(dev->config, 0xffff);
-    pci_config_set_device_id(dev->config, 0xffff);
+    pci_config_set_vendor_id(pci_dev->config, 0xffff);
+    pci_config_set_device_id(pci_dev->config, 0xffff);
 
-    return dev;
+    return pci_dev;
+
+fail:
+    object_unparent(OBJECT(pci_dev));
+    object_unref(pci_dev);
+    return NULL;
 }
 
 static void register_vfs(PCIDevice *dev)
@@ -170,6 +210,8 @@ static void register_vfs(PCIDevice *dev)
     uint16_t num_vfs;
     uint16_t i;
     uint16_t sriov_cap = dev->exp.sriov_cap;
+    uint16_t total_vfs =
+        pci_get_word(dev->config + sriov_cap + PCI_SRIOV_TOTAL_VF);
     uint16_t vf_offset =
         pci_get_word(dev->config + sriov_cap + PCI_SRIOV_VF_OFFSET);
     uint16_t vf_stride =
@@ -178,6 +220,9 @@ static void register_vfs(PCIDevice *dev)
 
     assert(sriov_cap > 0);
     num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF);
+    if (num_vfs > total_vfs) {
+        return;
+    }
 
     dev->exp.sriov_pf.vf = g_new(PCIDevice *, num_vfs);
     assert(dev->exp.sriov_pf.vf);

-- 
2.43.0



  parent reply	other threads:[~2023-12-02  8:03 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-02  8:00 [PATCH 00/14] virtio-net: add support for SR-IOV emulation Akihiko Odaki
2023-12-02  8:00 ` [PATCH 01/14] vfio: Avoid inspecting option QDict for rombar Akihiko Odaki
2023-12-02  8:00 ` [PATCH 02/14] hw/qdev: Remove opts member Akihiko Odaki
2023-12-02  8:00 ` [PATCH 03/14] qdev: Add DeviceClass::hide() Akihiko Odaki
2023-12-02  8:00 ` [PATCH 04/14] hw/pci: Add pci-failover Akihiko Odaki
2023-12-02  8:00 ` [PATCH 05/14] virtio-net: Implement pci-failover Akihiko Odaki
2023-12-02  8:00 ` [PATCH 06/14] qdev: Remove DeviceListener::hide_device() Akihiko Odaki
2023-12-02  8:00 ` [PATCH 07/14] hw/pci: Add hide() Akihiko Odaki
2023-12-02  8:00 ` [PATCH 08/14] qdev: Add qdev_device_new_from_qdict() Akihiko Odaki
2023-12-02  8:00 ` [PATCH 09/14] hw/pci: Do not add ROM BAR for SR-IOV VF Akihiko Odaki
2023-12-02  8:00 ` [PATCH 10/14] msix: Call pcie_sriov_vf_register_bar() " Akihiko Odaki
2023-12-02  8:00 ` [PATCH 11/14] pcie_sriov: Release VFs failed to realize Akihiko Odaki
2023-12-02  8:00 ` Akihiko Odaki [this message]
2023-12-02  8:00 ` [PATCH 13/14] virtio-pci: add SR-IOV capability Akihiko Odaki
2023-12-02  8:00 ` [PATCH 14/14] virtio-net: Add " Akihiko Odaki
2023-12-02  8:08 ` [PATCH 00/14] virtio-net: add support for SR-IOV emulation Akihiko Odaki
2023-12-04  9:04   ` Yui Washizu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231202-sriov-v1-12-32b3570f7bd6@daynix.com \
    --to=akihiko.odaki@daynix.com \
    --cc=alex.williamson@redhat.com \
    --cc=berrange@redhat.com \
    --cc=clg@redhat.com \
    --cc=eduardo@habkost.net \
    --cc=its@irrelevant.dk \
    --cc=jasowang@redhat.com \
    --cc=kbusch@kernel.org \
    --cc=marcel.apfelbaum@gmail.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=sriram.yagnaraman@est.tech \
    --cc=yui.washidu@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).