1 | Based-on: <20240228-reuse-v8-0-282660281e60@daynix.com> | 1 | Based-on: <20240315-reuse-v9-0-67aa69af4d53@daynix.com> |
---|---|---|---|
2 | ("[PATCH v8 00/15] hw/pci: SR-IOV related fixes and improvements") | 2 | ("[PATCH for 9.1 v9 00/11] hw/pci: SR-IOV related fixes and improvements") |
3 | 3 | ||
4 | Introduction | 4 | Introduction |
5 | ------------ | 5 | ------------ |
6 | 6 | ||
7 | This series is based on the RFC series submitted by Yui Washizu[1]. | 7 | This series is based on the RFC series submitted by Yui Washizu[1]. |
... | ... | ||
55 | Summary | 55 | Summary |
56 | ------- | 56 | ------- |
57 | 57 | ||
58 | Patch 1 disables ROM BAR, which virtio-net-pci enables by default, for | 58 | Patch 1 disables ROM BAR, which virtio-net-pci enables by default, for |
59 | VFs. | 59 | VFs. |
60 | Patch 2 and 3 adds validations. | 60 | Patch 2 makes zero stride valid for 1 VF configuration. |
61 | Patch 4 adds user-created SR-IOV VF infrastructure. | 61 | Patch 3 and 4 adds validations. |
62 | Patch 5 makes virtio-pci work as SR-IOV PF for user-created VFs. | 62 | Patch 5 adds user-created SR-IOV VF infrastructure. |
63 | Patch 6 allows user to create SR-IOV VFs with virtio-net-pci. | 63 | Patch 6 makes virtio-pci work as SR-IOV PF for user-created VFs. |
64 | Patch 7 allows user to create SR-IOV VFs with virtio-net-pci. | ||
64 | 65 | ||
65 | [1] https://patchew.org/QEMU/1689731808-3009-1-git-send-email-yui.washidu@gmail.com/ | 66 | [1] https://patchew.org/QEMU/1689731808-3009-1-git-send-email-yui.washidu@gmail.com/ |
66 | [2] https://lore.kernel.org/all/5d46f455-f530-4e5e-9ae7-13a2297d4bc5@daynix.com/ | 67 | [2] https://lore.kernel.org/all/5d46f455-f530-4e5e-9ae7-13a2297d4bc5@daynix.com/ |
67 | 68 | ||
68 | Co-developed-by: Yui Washizu <yui.washidu@gmail.com> | 69 | Co-developed-by: Yui Washizu <yui.washidu@gmail.com> |
69 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | 70 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> |
70 | --- | 71 | --- |
72 | Changes in v4: | ||
73 | - Added patch "hw/pci: Fix SR-IOV VF number calculation" to fix division | ||
74 | by zero reported by Yui Washizu. | ||
75 | - Rebased. | ||
76 | - Link to v3: https://lore.kernel.org/r/20240305-sriov-v3-0-abdb75770372@daynix.com | ||
77 | |||
71 | Changes in v3: | 78 | Changes in v3: |
72 | - Rebased. | 79 | - Rebased. |
73 | - Link to v2: https://lore.kernel.org/r/20231210-sriov-v2-0-b959e8a6dfaf@daynix.com | 80 | - Link to v2: https://lore.kernel.org/r/20231210-sriov-v2-0-b959e8a6dfaf@daynix.com |
74 | 81 | ||
75 | Changes in v2: | 82 | Changes in v2: |
76 | - Changed to keep VF instances. | 83 | - Changed to keep VF instances. |
77 | - Link to v1: https://lore.kernel.org/r/20231202-sriov-v1-0-32b3570f7bd6@daynix.com | 84 | - Link to v1: https://lore.kernel.org/r/20231202-sriov-v1-0-32b3570f7bd6@daynix.com |
78 | 85 | ||
79 | --- | 86 | --- |
80 | Akihiko Odaki (6): | 87 | Akihiko Odaki (7): |
81 | hw/pci: Do not add ROM BAR for SR-IOV VF | 88 | hw/pci: Do not add ROM BAR for SR-IOV VF |
89 | hw/pci: Fix SR-IOV VF number calculation | ||
82 | pcie_sriov: Ensure PF and VF are mutually exclusive | 90 | pcie_sriov: Ensure PF and VF are mutually exclusive |
83 | pcie_sriov: Check PCI Express for SR-IOV PF | 91 | pcie_sriov: Check PCI Express for SR-IOV PF |
84 | pcie_sriov: Allow user to create SR-IOV device | 92 | pcie_sriov: Allow user to create SR-IOV device |
85 | virtio-pci: Implement SR-IOV PF | 93 | virtio-pci: Implement SR-IOV PF |
86 | virtio-net: Implement SR-IOV VF | 94 | virtio-net: Implement SR-IOV VF |
87 | 95 | ||
88 | include/hw/pci/pci_device.h | 6 +- | 96 | include/hw/pci/pci_device.h | 6 +- |
89 | include/hw/pci/pcie_sriov.h | 19 +++ | 97 | include/hw/pci/pcie_sriov.h | 19 +++ |
90 | hw/pci/pci.c | 70 +++++++---- | 98 | hw/pci/pci.c | 76 +++++++---- |
91 | hw/pci/pcie_sriov.c | 299 +++++++++++++++++++++++++++++++++++--------- | 99 | hw/pci/pcie_sriov.c | 298 +++++++++++++++++++++++++++++++++++--------- |
92 | hw/virtio/virtio-net-pci.c | 1 + | 100 | hw/virtio/virtio-net-pci.c | 1 + |
93 | hw/virtio/virtio-pci.c | 7 ++ | 101 | hw/virtio/virtio-pci.c | 7 ++ |
94 | 6 files changed, 319 insertions(+), 83 deletions(-) | 102 | 6 files changed, 323 insertions(+), 84 deletions(-) |
95 | --- | 103 | --- |
96 | base-commit: 2c4eb0476e461b8a4b2f745d25f987e831c7f640 | 104 | base-commit: 2ac5458086ab61282f30c2f8bdf2ae9a0a06a75d |
97 | change-id: 20231202-sriov-9402fb262be8 | 105 | change-id: 20231202-sriov-9402fb262be8 |
98 | 106 | ||
99 | Best regards, | 107 | Best regards, |
100 | -- | 108 | -- |
101 | Akihiko Odaki <akihiko.odaki@daynix.com> | 109 | Akihiko Odaki <akihiko.odaki@daynix.com> | diff view generated by jsdifflib |
1 | A SR-IOV VF cannot have a ROM BAR. | 1 | A SR-IOV VF cannot have a ROM BAR. |
---|---|---|---|
2 | 2 | ||
3 | Co-developed-by: Yui Washizu <yui.washidu@gmail.com> | 3 | Co-developed-by: Yui Washizu <yui.washidu@gmail.com> |
4 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | 4 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> |
5 | --- | 5 | --- |
6 | hw/pci/pci.c | 8 ++++++++ | 6 | hw/pci/pci.c | 8 ++++++++ |
7 | 1 file changed, 8 insertions(+) | 7 | 1 file changed, 8 insertions(+) |
8 | 8 | ||
9 | diff --git a/hw/pci/pci.c b/hw/pci/pci.c | 9 | diff --git a/hw/pci/pci.c b/hw/pci/pci.c |
10 | index XXXXXXX..XXXXXXX 100644 | 10 | index XXXXXXX..XXXXXXX 100644 |
11 | --- a/hw/pci/pci.c | 11 | --- a/hw/pci/pci.c |
12 | +++ b/hw/pci/pci.c | 12 | +++ b/hw/pci/pci.c |
13 | @@ -XXX,XX +XXX,XX @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, | 13 | @@ -XXX,XX +XXX,XX @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, |
14 | return; | 14 | return; |
15 | } | 15 | } |
16 | 16 | ||
17 | + if (pci_is_vf(pdev)) { | 17 | + if (pci_is_vf(pdev)) { |
18 | + if (pdev->rom_bar != UINT32_MAX) { | 18 | + if (pdev->rom_bar != UINT32_MAX) { |
19 | + error_setg(errp, "ROM BAR cannot be enabled for SR-IOV VF"); | 19 | + error_setg(errp, "ROM BAR cannot be enabled for SR-IOV VF"); |
20 | + } | 20 | + } |
21 | + | 21 | + |
22 | + return; | 22 | + return; |
23 | + } | 23 | + } |
24 | + | 24 | + |
25 | if (load_file || pdev->romsize == UINT32_MAX) { | 25 | if (load_file || pdev->romsize == UINT32_MAX) { |
26 | path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile); | 26 | path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile); |
27 | if (path == NULL) { | 27 | if (path == NULL) { |
28 | 28 | ||
29 | -- | 29 | -- |
30 | 2.44.0 | 30 | 2.44.0 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | pci_config_get_bar_addr() had a division by vf_stride. vf_stride needs | ||
2 | to be non-zero when there are multiple VFs, but the specification does | ||
3 | not prohibit to make it zero when there is only one VF. | ||
1 | 4 | ||
5 | Do not perform the division for the first VF to avoid division by zero. | ||
6 | |||
7 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
8 | --- | ||
9 | hw/pci/pci.c | 6 +++++- | ||
10 | 1 file changed, 5 insertions(+), 1 deletion(-) | ||
11 | |||
12 | diff --git a/hw/pci/pci.c b/hw/pci/pci.c | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/hw/pci/pci.c | ||
15 | +++ b/hw/pci/pci.c | ||
16 | @@ -XXX,XX +XXX,XX @@ static pcibus_t pci_config_get_bar_addr(PCIDevice *d, int reg, | ||
17 | pci_get_word(pf->config + sriov_cap + PCI_SRIOV_VF_OFFSET); | ||
18 | uint16_t vf_stride = | ||
19 | pci_get_word(pf->config + sriov_cap + PCI_SRIOV_VF_STRIDE); | ||
20 | - uint32_t vf_num = (d->devfn - (pf->devfn + vf_offset)) / vf_stride; | ||
21 | + uint32_t vf_num = d->devfn - (pf->devfn + vf_offset); | ||
22 | + | ||
23 | + if (vf_num) { | ||
24 | + vf_num /= vf_stride; | ||
25 | + } | ||
26 | |||
27 | if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) { | ||
28 | new_addr = pci_get_quad(pf->config + bar); | ||
29 | |||
30 | -- | ||
31 | 2.44.0 | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
16 | + if (pci_is_vf(dev)) { | 16 | + if (pci_is_vf(dev)) { |
17 | + error_setg(errp, "a device cannot be a SR-IOV PF and a VF at the same time"); | 17 | + error_setg(errp, "a device cannot be a SR-IOV PF and a VF at the same time"); |
18 | + return false; | 18 | + return false; |
19 | + } | 19 | + } |
20 | + | 20 | + |
21 | pcie_add_capability(dev, PCI_EXT_CAP_ID_SRIOV, 1, | 21 | if (total_vfs) { |
22 | offset, PCI_EXT_CAP_SRIOV_SIZEOF); | 22 | uint16_t ari_cap = pcie_find_capability(dev, PCI_EXT_CAP_ID_ARI); |
23 | dev->exp.sriov_cap = offset; | 23 | uint16_t first_vf_devfn = dev->devfn + vf_offset; |
24 | 24 | ||
25 | -- | 25 | -- |
26 | 2.44.0 | 26 | 2.44.0 | diff view generated by jsdifflib |
1 | SR-IOV requires PCI Express. | 1 | SR-IOV requires PCI Express. |
---|---|---|---|
2 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | 3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> |
4 | --- | 4 | --- |
5 | hw/pci/pcie_sriov.c | 5 +++++ | 5 | hw/pci/pcie_sriov.c | 5 +++++ |
6 | 1 file changed, 5 insertions(+) | 6 | 1 file changed, 5 insertions(+) |
7 | 7 | ||
8 | diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c | 8 | diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c |
9 | index XXXXXXX..XXXXXXX 100644 | 9 | index XXXXXXX..XXXXXXX 100644 |
10 | --- a/hw/pci/pcie_sriov.c | 10 | --- a/hw/pci/pcie_sriov.c |
11 | +++ b/hw/pci/pcie_sriov.c | 11 | +++ b/hw/pci/pcie_sriov.c |
12 | @@ -XXX,XX +XXX,XX @@ bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset, | 12 | @@ -XXX,XX +XXX,XX @@ bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset, |
13 | uint8_t *cfg = dev->config + offset; | 13 | uint8_t *cfg = dev->config + offset; |
14 | uint8_t *wmask; | 14 | uint8_t *wmask; |
15 | 15 | ||
16 | + if (!pci_is_express(dev)) { | 16 | + if (!pci_is_express(dev)) { |
17 | + error_setg(errp, "PCI Express is required for SR-IOV PF"); | 17 | + error_setg(errp, "PCI Express is required for SR-IOV PF"); |
18 | + return false; | 18 | + return false; |
19 | + } | 19 | + } |
20 | + | 20 | + |
21 | if (pci_is_vf(dev)) { | 21 | if (pci_is_vf(dev)) { |
22 | error_setg(errp, "a device cannot be a SR-IOV PF and a VF at the same time"); | 22 | error_setg(errp, "a device cannot be a SR-IOV PF and a VF at the same time"); |
23 | return false; | 23 | return false; |
24 | 24 | ||
25 | -- | 25 | -- |
26 | 2.44.0 | 26 | 2.44.0 | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
12 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | 12 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> |
13 | --- | 13 | --- |
14 | include/hw/pci/pci_device.h | 6 +- | 14 | include/hw/pci/pci_device.h | 6 +- |
15 | include/hw/pci/pcie_sriov.h | 19 +++ | 15 | include/hw/pci/pcie_sriov.h | 19 +++ |
16 | hw/pci/pci.c | 62 ++++++---- | 16 | hw/pci/pci.c | 62 ++++++---- |
17 | hw/pci/pcie_sriov.c | 289 +++++++++++++++++++++++++++++++++++--------- | 17 | hw/pci/pcie_sriov.c | 288 +++++++++++++++++++++++++++++++++++--------- |
18 | 4 files changed, 293 insertions(+), 83 deletions(-) | 18 | 4 files changed, 292 insertions(+), 83 deletions(-) |
19 | 19 | ||
20 | diff --git a/include/hw/pci/pci_device.h b/include/hw/pci/pci_device.h | 20 | diff --git a/include/hw/pci/pci_device.h b/include/hw/pci/pci_device.h |
21 | index XXXXXXX..XXXXXXX 100644 | 21 | index XXXXXXX..XXXXXXX 100644 |
22 | --- a/include/hw/pci/pci_device.h | 22 | --- a/include/hw/pci/pci_device.h |
23 | +++ b/include/hw/pci/pci_device.h | 23 | +++ b/include/hw/pci/pci_device.h |
... | ... | ||
212 | diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c | 212 | diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c |
213 | index XXXXXXX..XXXXXXX 100644 | 213 | index XXXXXXX..XXXXXXX 100644 |
214 | --- a/hw/pci/pcie_sriov.c | 214 | --- a/hw/pci/pcie_sriov.c |
215 | +++ b/hw/pci/pcie_sriov.c | 215 | +++ b/hw/pci/pcie_sriov.c |
216 | @@ -XXX,XX +XXX,XX @@ | 216 | @@ -XXX,XX +XXX,XX @@ |
217 | #include "hw/qdev-properties.h" | 217 | #include "qapi/error.h" |
218 | #include "qemu/error-report.h" | ||
219 | #include "qemu/range.h" | ||
220 | +#include "qapi/error.h" | ||
221 | #include "trace.h" | 218 | #include "trace.h" |
222 | 219 | ||
223 | +static GHashTable *pfs; | 220 | +static GHashTable *pfs; |
224 | + | 221 | + |
225 | static void unparent_vfs(PCIDevice *dev, uint16_t total_vfs) | 222 | static void unparent_vfs(PCIDevice *dev, uint16_t total_vfs) |
... | ... | diff view generated by jsdifflib |
1 | Allow user to attach SR-IOV VF to a virtio-pci PF. | 1 | Allow user to attach SR-IOV VF to a virtio-pci PF. |
---|---|---|---|
2 | 2 | ||
3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | 3 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> |
4 | --- | 4 | --- |
5 | hw/virtio/virtio-pci.c | 7 +++++++ | 5 | hw/virtio/virtio-pci.c | 7 +++++++ |
6 | 1 file changed, 7 insertions(+) | 6 | 1 file changed, 7 insertions(+) |
7 | 7 | ||
8 | diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c | 8 | diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c |
9 | index XXXXXXX..XXXXXXX 100644 | 9 | index XXXXXXX..XXXXXXX 100644 |
10 | --- a/hw/virtio/virtio-pci.c | 10 | --- a/hw/virtio/virtio-pci.c |
11 | +++ b/hw/virtio/virtio-pci.c | 11 | +++ b/hw/virtio/virtio-pci.c |
12 | @@ -XXX,XX +XXX,XX @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) | 12 | @@ -XXX,XX +XXX,XX @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) |
13 | pci_register_bar(&proxy->pci_dev, proxy->legacy_io_bar_idx, | 13 | pci_register_bar(&proxy->pci_dev, proxy->legacy_io_bar_idx, |
14 | PCI_BASE_ADDRESS_SPACE_IO, &proxy->bar); | 14 | PCI_BASE_ADDRESS_SPACE_IO, &proxy->bar); |
15 | } | 15 | } |
16 | + | 16 | + |
17 | + if (pcie_sriov_pf_init_from_user_created_vfs(&proxy->pci_dev, | 17 | + if (pcie_sriov_pf_init_from_user_created_vfs(&proxy->pci_dev, |
18 | + PCI_CONFIG_SPACE_SIZE, | 18 | + PCI_CONFIG_SPACE_SIZE, |
19 | + errp)) { | 19 | + errp)) { |
20 | + virtio_add_feature(&vdev->host_features, VIRTIO_F_SR_IOV); | 20 | + virtio_add_feature(&vdev->host_features, VIRTIO_F_SR_IOV); |
21 | + } | 21 | + } |
22 | } | 22 | } |
23 | 23 | ||
24 | static void virtio_pci_device_unplugged(DeviceState *d) | 24 | static void virtio_pci_device_unplugged(DeviceState *d) |
25 | @@ -XXX,XX +XXX,XX @@ static void virtio_pci_device_unplugged(DeviceState *d) | 25 | @@ -XXX,XX +XXX,XX @@ static void virtio_pci_device_unplugged(DeviceState *d) |
26 | bool modern = virtio_pci_modern(proxy); | 26 | bool modern = virtio_pci_modern(proxy); |
27 | bool modern_pio = proxy->flags & VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY; | 27 | bool modern_pio = proxy->flags & VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY; |
28 | 28 | ||
29 | + pcie_sriov_pf_exit(&proxy->pci_dev); | 29 | + pcie_sriov_pf_exit(&proxy->pci_dev); |
30 | virtio_pci_stop_ioeventfd(proxy); | 30 | virtio_pci_stop_ioeventfd(proxy); |
31 | 31 | ||
32 | if (modern) { | 32 | if (modern) { |
33 | 33 | ||
34 | -- | 34 | -- |
35 | 2.44.0 | 35 | 2.44.0 | diff view generated by jsdifflib |
1 | A virtio-net device can be added as a SR-IOV VF to another virtio-pci | 1 | A virtio-net device can be added as a SR-IOV VF to another virtio-pci |
---|---|---|---|
2 | device that will be the PF. | 2 | device that will be the PF. |
3 | 3 | ||
4 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> | 4 | Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com> |
5 | --- | 5 | --- |
6 | hw/virtio/virtio-net-pci.c | 1 + | 6 | hw/virtio/virtio-net-pci.c | 1 + |
7 | 1 file changed, 1 insertion(+) | 7 | 1 file changed, 1 insertion(+) |
8 | 8 | ||
9 | diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c | 9 | diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c |
10 | index XXXXXXX..XXXXXXX 100644 | 10 | index XXXXXXX..XXXXXXX 100644 |
11 | --- a/hw/virtio/virtio-net-pci.c | 11 | --- a/hw/virtio/virtio-net-pci.c |
12 | +++ b/hw/virtio/virtio-net-pci.c | 12 | +++ b/hw/virtio/virtio-net-pci.c |
13 | @@ -XXX,XX +XXX,XX @@ static void virtio_net_pci_class_init(ObjectClass *klass, void *data) | 13 | @@ -XXX,XX +XXX,XX @@ static void virtio_net_pci_class_init(ObjectClass *klass, void *data) |
14 | k->device_id = PCI_DEVICE_ID_VIRTIO_NET; | 14 | k->device_id = PCI_DEVICE_ID_VIRTIO_NET; |
15 | k->revision = VIRTIO_PCI_ABI_VERSION; | 15 | k->revision = VIRTIO_PCI_ABI_VERSION; |
16 | k->class_id = PCI_CLASS_NETWORK_ETHERNET; | 16 | k->class_id = PCI_CLASS_NETWORK_ETHERNET; |
17 | + k->sriov_vf_user_creatable = true; | 17 | + k->sriov_vf_user_creatable = true; |
18 | set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); | 18 | set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); |
19 | device_class_set_props(dc, virtio_net_properties); | 19 | device_class_set_props(dc, virtio_net_properties); |
20 | vpciklass->realize = virtio_net_pci_realize; | 20 | vpciklass->realize = virtio_net_pci_realize; |
21 | 21 | ||
22 | -- | 22 | -- |
23 | 2.44.0 | 23 | 2.44.0 | diff view generated by jsdifflib |