1
The following changes since commit 23895cbd82be95428e90168b12e925d0d3ca2f06:
1
The following changes since commit 7dd9d7e0bd29abf590d1ac235c0a00606ef81153:
2
2
3
Merge remote-tracking branch 'remotes/awilliam/tags/vfio-update-20201123.0' into staging (2020-11-23 18:51:13 +0000)
3
Merge tag 'pull-ppc-20220831' of https://gitlab.com/danielhb/qemu into staging (2022-09-01 13:53:20 -0400)
4
4
5
are available in the git repository at:
5
are available in the git repository at:
6
6
7
https://github.com/jasowang/qemu.git tags/net-pull-request
7
https://github.com/jasowang/qemu.git tags/net-pull-request
8
8
9
for you to fetch changes up to 9925990d01a92564af55f6f69d0f5f59b47609b1:
9
for you to fetch changes up to 36a894aeb64a2e02871016da1c37d4a4ca109182:
10
10
11
net: Use correct default-path macro for downscript (2020-11-24 10:40:17 +0800)
11
net: tulip: Restrict DMA engine to memories (2022-09-02 10:22:39 +0800)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
14
15
----------------------------------------------------------------
15
----------------------------------------------------------------
16
Keqian Zhu (1):
16
Eugenio Pérez (19):
17
net: Use correct default-path macro for downscript
17
vdpa: Skip the maps not in the iova tree
18
vdpa: do not save failed dma maps in SVQ iova tree
19
util: accept iova_tree_remove_parameter by value
20
vdpa: Remove SVQ vring from iova_tree at shutdown
21
vdpa: Make SVQ vring unmapping return void
22
vhost: Always store new kick fd on vhost_svq_set_svq_kick_fd
23
vdpa: Use ring hwaddr at vhost_vdpa_svq_unmap_ring
24
vhost: stop transfer elem ownership in vhost_handle_guest_kick
25
vhost: use SVQ element ndescs instead of opaque data for desc validation
26
vhost: Delete useless read memory barrier
27
vhost: Do not depend on !NULL VirtQueueElement on vhost_svq_flush
28
vhost_net: Add NetClientInfo start callback
29
vhost_net: Add NetClientInfo stop callback
30
vdpa: add net_vhost_vdpa_cvq_info NetClientInfo
31
vdpa: Move command buffers map to start of net device
32
vdpa: extract vhost_vdpa_net_cvq_add from vhost_vdpa_net_handle_ctrl_avail
33
vhost_net: add NetClientState->load() callback
34
vdpa: Add virtio-net mac address via CVQ at start
35
vdpa: Delete CVQ migration blocker
18
36
19
Paolo Bonzini (1):
37
Zhang Chen (1):
20
net: do not exit on "netdev_add help" monitor command
38
net/colo.c: Fix the pointer issue reported by Coverity.
21
39
22
Prasad J Pandit (1):
40
Zheyu Ma (1):
23
hw/net/e1000e: advance desc_offset in case of null descriptor
41
net: tulip: Restrict DMA engine to memories
24
42
25
Yuri Benditovich (1):
43
hw/i386/intel_iommu.c | 6 +-
26
net: purge queued rx packets on queue deletion
44
hw/net/tulip.c | 4 +-
27
45
hw/net/vhost_net.c | 17 +++
28
yuanjungong (1):
46
hw/virtio/vhost-iova-tree.c | 2 +-
29
tap: fix a memory leak
47
hw/virtio/vhost-iova-tree.h | 2 +-
30
48
hw/virtio/vhost-shadow-virtqueue.c | 31 +++--
31
hw/net/e1000e_core.c | 8 +++---
49
hw/virtio/vhost-vdpa.c | 90 +++++++--------
32
include/net/net.h | 1 +
50
include/hw/virtio/vhost-vdpa.h | 1 -
33
monitor/hmp-cmds.c | 6 ++++
51
include/net/net.h | 6 +
34
net/net.c | 80 +++++++++++++++++++++++++++-------------------------
52
include/qemu/iova-tree.h | 2 +-
35
net/tap.c | 5 +++-
53
net/colo.c | 25 ++--
36
5 files changed, 57 insertions(+), 43 deletions(-)
54
net/colo.h | 1 +
55
net/trace-events | 2 +-
56
net/vhost-vdpa.c | 228 +++++++++++++++++++++++--------------
57
util/iova-tree.c | 4 +-
58
15 files changed, 248 insertions(+), 173 deletions(-)
37
59
38
60
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
Next patch will skip the registering of dma maps that the vdpa device
4
rejects in the iova tree. We need to consider that here or we cause a
5
SIGSEGV accessing result.
6
7
Reported-by: Lei Yang <leiyang@redhat.com>
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Acked-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
---
12
hw/virtio/vhost-vdpa.c | 4 ++++
13
1 file changed, 4 insertions(+)
14
15
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/virtio/vhost-vdpa.c
18
+++ b/hw/virtio/vhost-vdpa.c
19
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener,
20
};
21
22
result = vhost_iova_tree_find_iova(v->iova_tree, &mem_region);
23
+ if (!result) {
24
+ /* The memory listener map wasn't mapped */
25
+ return;
26
+ }
27
iova = result->iova;
28
vhost_iova_tree_remove(v->iova_tree, result);
29
}
30
--
31
2.7.4
32
33
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
If a map fails for whatever reason, it must not be saved in the tree.
4
Otherwise, qemu will try to unmap it in cleanup, leaving to more errors.
5
6
Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ")
7
Reported-by: Lei Yang <leiyang@redhat.com>
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Acked-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
---
12
hw/virtio/vhost-vdpa.c | 20 +++++++++++++-------
13
1 file changed, 13 insertions(+), 7 deletions(-)
14
15
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/virtio/vhost-vdpa.c
18
+++ b/hw/virtio/vhost-vdpa.c
19
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_listener_commit(MemoryListener *listener)
20
static void vhost_vdpa_listener_region_add(MemoryListener *listener,
21
MemoryRegionSection *section)
22
{
23
+ DMAMap mem_region = {};
24
struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener);
25
hwaddr iova;
26
Int128 llend, llsize;
27
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener,
28
29
llsize = int128_sub(llend, int128_make64(iova));
30
if (v->shadow_vqs_enabled) {
31
- DMAMap mem_region = {
32
- .translated_addr = (hwaddr)(uintptr_t)vaddr,
33
- .size = int128_get64(llsize) - 1,
34
- .perm = IOMMU_ACCESS_FLAG(true, section->readonly),
35
- };
36
+ int r;
37
38
- int r = vhost_iova_tree_map_alloc(v->iova_tree, &mem_region);
39
+ mem_region.translated_addr = (hwaddr)(uintptr_t)vaddr,
40
+ mem_region.size = int128_get64(llsize) - 1,
41
+ mem_region.perm = IOMMU_ACCESS_FLAG(true, section->readonly),
42
+
43
+ r = vhost_iova_tree_map_alloc(v->iova_tree, &mem_region);
44
if (unlikely(r != IOVA_OK)) {
45
error_report("Can't allocate a mapping (%d)", r);
46
goto fail;
47
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener,
48
vaddr, section->readonly);
49
if (ret) {
50
error_report("vhost vdpa map fail!");
51
- goto fail;
52
+ goto fail_map;
53
}
54
55
return;
56
57
+fail_map:
58
+ if (v->shadow_vqs_enabled) {
59
+ vhost_iova_tree_remove(v->iova_tree, &mem_region);
60
+ }
61
+
62
fail:
63
/*
64
* On the initfn path, store the first error in the container so we
65
--
66
2.7.4
67
68
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
It's convenient to call iova_tree_remove from a map returned from
4
iova_tree_find or iova_tree_find_iova. With the current code this is not
5
possible, since we will free it, and then we will try to search for it
6
again.
7
8
Fix it making accepting the map by value, forcing a copy of the
9
argument. Not applying a fixes tag, since there is no use like that at
10
the moment.
11
12
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
13
Signed-off-by: Jason Wang <jasowang@redhat.com>
14
---
15
hw/i386/intel_iommu.c | 6 +++---
16
hw/virtio/vhost-iova-tree.c | 2 +-
17
hw/virtio/vhost-iova-tree.h | 2 +-
18
hw/virtio/vhost-vdpa.c | 6 +++---
19
include/qemu/iova-tree.h | 2 +-
20
net/vhost-vdpa.c | 4 ++--
21
util/iova-tree.c | 4 ++--
22
7 files changed, 13 insertions(+), 13 deletions(-)
23
24
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/i386/intel_iommu.c
27
+++ b/hw/i386/intel_iommu.c
28
@@ -XXX,XX +XXX,XX @@ static int vtd_page_walk_one(IOMMUTLBEvent *event, vtd_page_walk_info *info)
29
return ret;
30
}
31
/* Drop any existing mapping */
32
- iova_tree_remove(as->iova_tree, &target);
33
+ iova_tree_remove(as->iova_tree, target);
34
/* Recover the correct type */
35
event->type = IOMMU_NOTIFIER_MAP;
36
entry->perm = cache_perm;
37
@@ -XXX,XX +XXX,XX @@ static int vtd_page_walk_one(IOMMUTLBEvent *event, vtd_page_walk_info *info)
38
trace_vtd_page_walk_one_skip_unmap(entry->iova, entry->addr_mask);
39
return 0;
40
}
41
- iova_tree_remove(as->iova_tree, &target);
42
+ iova_tree_remove(as->iova_tree, target);
43
}
44
45
trace_vtd_page_walk_one(info->domain_id, entry->iova,
46
@@ -XXX,XX +XXX,XX @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n)
47
48
map.iova = n->start;
49
map.size = size;
50
- iova_tree_remove(as->iova_tree, &map);
51
+ iova_tree_remove(as->iova_tree, map);
52
}
53
54
static void vtd_address_space_unmap_all(IntelIOMMUState *s)
55
diff --git a/hw/virtio/vhost-iova-tree.c b/hw/virtio/vhost-iova-tree.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/virtio/vhost-iova-tree.c
58
+++ b/hw/virtio/vhost-iova-tree.c
59
@@ -XXX,XX +XXX,XX @@ int vhost_iova_tree_map_alloc(VhostIOVATree *tree, DMAMap *map)
60
* @iova_tree: The vhost iova tree
61
* @map: The map to remove
62
*/
63
-void vhost_iova_tree_remove(VhostIOVATree *iova_tree, const DMAMap *map)
64
+void vhost_iova_tree_remove(VhostIOVATree *iova_tree, DMAMap map)
65
{
66
iova_tree_remove(iova_tree->iova_taddr_map, map);
67
}
68
diff --git a/hw/virtio/vhost-iova-tree.h b/hw/virtio/vhost-iova-tree.h
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/virtio/vhost-iova-tree.h
71
+++ b/hw/virtio/vhost-iova-tree.h
72
@@ -XXX,XX +XXX,XX @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostIOVATree, vhost_iova_tree_delete);
73
const DMAMap *vhost_iova_tree_find_iova(const VhostIOVATree *iova_tree,
74
const DMAMap *map);
75
int vhost_iova_tree_map_alloc(VhostIOVATree *iova_tree, DMAMap *map);
76
-void vhost_iova_tree_remove(VhostIOVATree *iova_tree, const DMAMap *map);
77
+void vhost_iova_tree_remove(VhostIOVATree *iova_tree, DMAMap map);
78
79
#endif
80
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/hw/virtio/vhost-vdpa.c
83
+++ b/hw/virtio/vhost-vdpa.c
84
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener,
85
86
fail_map:
87
if (v->shadow_vqs_enabled) {
88
- vhost_iova_tree_remove(v->iova_tree, &mem_region);
89
+ vhost_iova_tree_remove(v->iova_tree, mem_region);
90
}
91
92
fail:
93
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener,
94
return;
95
}
96
iova = result->iova;
97
- vhost_iova_tree_remove(v->iova_tree, result);
98
+ vhost_iova_tree_remove(v->iova_tree, *result);
99
}
100
vhost_vdpa_iotlb_batch_begin_once(v);
101
ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize));
102
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_svq_map_ring(struct vhost_vdpa *v, DMAMap *needle,
103
needle->perm == IOMMU_RO);
104
if (unlikely(r != 0)) {
105
error_setg_errno(errp, -r, "Cannot map region to device");
106
- vhost_iova_tree_remove(v->iova_tree, needle);
107
+ vhost_iova_tree_remove(v->iova_tree, *needle);
108
}
109
110
return r == 0;
111
diff --git a/include/qemu/iova-tree.h b/include/qemu/iova-tree.h
112
index XXXXXXX..XXXXXXX 100644
113
--- a/include/qemu/iova-tree.h
114
+++ b/include/qemu/iova-tree.h
115
@@ -XXX,XX +XXX,XX @@ int iova_tree_insert(IOVATree *tree, const DMAMap *map);
116
* all the mappings that are included in the provided range will be
117
* removed from the tree. Here map->translated_addr is meaningless.
118
*/
119
-void iova_tree_remove(IOVATree *tree, const DMAMap *map);
120
+void iova_tree_remove(IOVATree *tree, DMAMap map);
121
122
/**
123
* iova_tree_find:
124
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/net/vhost-vdpa.c
127
+++ b/net/vhost-vdpa.c
128
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_cvq_unmap_buf(struct vhost_vdpa *v, void *addr)
129
error_report("Device cannot unmap: %s(%d)", g_strerror(r), r);
130
}
131
132
- vhost_iova_tree_remove(tree, map);
133
+ vhost_iova_tree_remove(tree, *map);
134
}
135
136
static size_t vhost_vdpa_net_cvq_cmd_len(void)
137
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v,
138
return true;
139
140
dma_map_err:
141
- vhost_iova_tree_remove(v->iova_tree, &map);
142
+ vhost_iova_tree_remove(v->iova_tree, map);
143
return false;
144
}
145
146
diff --git a/util/iova-tree.c b/util/iova-tree.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/util/iova-tree.c
149
+++ b/util/iova-tree.c
150
@@ -XXX,XX +XXX,XX @@ void iova_tree_foreach(IOVATree *tree, iova_tree_iterator iterator)
151
g_tree_foreach(tree->tree, iova_tree_traverse, iterator);
152
}
153
154
-void iova_tree_remove(IOVATree *tree, const DMAMap *map)
155
+void iova_tree_remove(IOVATree *tree, DMAMap map)
156
{
157
const DMAMap *overlap;
158
159
- while ((overlap = iova_tree_find(tree, map))) {
160
+ while ((overlap = iova_tree_find(tree, &map))) {
161
g_tree_remove(tree->tree, overlap);
162
}
163
}
164
--
165
2.7.4
166
167
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
Although the device will be reset before usage, the right thing to do is
4
to clean it.
5
6
Reported-by: Lei Yang <leiyang@redhat.com>
7
Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ")
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/virtio/vhost-vdpa.c | 6 ++++++
12
1 file changed, 6 insertions(+)
13
14
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/virtio/vhost-vdpa.c
17
+++ b/hw/virtio/vhost-vdpa.c
18
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v,
19
20
size = ROUND_UP(result->size, qemu_real_host_page_size());
21
r = vhost_vdpa_dma_unmap(v, result->iova, size);
22
+ if (unlikely(r < 0)) {
23
+ error_report("Unable to unmap SVQ vring: %s (%d)", g_strerror(-r), -r);
24
+ return false;
25
+ }
26
+
27
+ vhost_iova_tree_remove(v->iova_tree, *result);
28
return r == 0;
29
}
30
31
--
32
2.7.4
33
34
diff view generated by jsdifflib
1
From: Yuri Benditovich <yuri.benditovich@daynix.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
https://bugzilla.redhat.com/show_bug.cgi?id=1829272
3
Nothing actually reads the return value, but an error in cleaning some
4
When deleting queue pair, purge pending RX packets if any.
4
entries could cause device stop to abort, making a restart impossible.
5
Example of problematic flow:
5
Better ignore explicitely the return value.
6
1. Bring up q35 VM with tap (vhost off) and virtio-net or e1000e
7
2. Run ping flood to the VM NIC ( 1 ms interval)
8
3. Hot unplug the NIC device (device_del)
9
During unplug process one or more packets come, the NIC
10
can't receive, tap disables read_poll
11
4. Hot plug the device (device_add) with the same netdev
12
The tap stays with read_poll disabled and does not receive
13
any packets anymore (tap_send never triggered)
14
6
15
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
7
Reported-by: Lei Yang <leiyang@redhat.com>
8
Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ")
9
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
10
Acked-by: Jason Wang <jasowang@redhat.com>
16
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
17
---
12
---
18
net/net.c | 12 ++++++++----
13
hw/virtio/vhost-vdpa.c | 32 ++++++++++----------------------
19
1 file changed, 8 insertions(+), 4 deletions(-)
14
1 file changed, 10 insertions(+), 22 deletions(-)
20
15
21
diff --git a/net/net.c b/net/net.c
16
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/net/net.c
18
--- a/hw/virtio/vhost-vdpa.c
24
+++ b/net/net.c
19
+++ b/hw/virtio/vhost-vdpa.c
25
@@ -XXX,XX +XXX,XX @@ void qemu_del_nic(NICState *nic)
20
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev,
26
21
/**
27
qemu_macaddr_set_free(&nic->conf->macaddr);
22
* Unmap a SVQ area in the device
28
23
*/
29
- /* If this is a peer NIC and peer has already been deleted, free it now. */
24
-static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v,
30
- if (nic->peer_deleted) {
25
+static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v,
31
- for (i = 0; i < queues; i++) {
26
const DMAMap *needle)
32
- qemu_free_net_client(qemu_get_subqueue(nic, i)->peer);
27
{
33
+ for (i = 0; i < queues; i++) {
28
const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, needle);
34
+ NetClientState *nc = qemu_get_subqueue(nic, i);
29
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v,
35
+ /* If this is a peer NIC and peer has already been deleted, free it now. */
30
36
+ if (nic->peer_deleted) {
31
if (unlikely(!result)) {
37
+ qemu_free_net_client(nc->peer);
32
error_report("Unable to find SVQ address to unmap");
38
+ } else if (nc->peer) {
33
- return false;
39
+ /* if there are RX packets pending, complete them */
34
+ return;
40
+ qemu_purge_queued_packets(nc->peer);
35
}
36
37
size = ROUND_UP(result->size, qemu_real_host_page_size());
38
r = vhost_vdpa_dma_unmap(v, result->iova, size);
39
if (unlikely(r < 0)) {
40
error_report("Unable to unmap SVQ vring: %s (%d)", g_strerror(-r), -r);
41
- return false;
42
+ return;
43
}
44
45
vhost_iova_tree_remove(v->iova_tree, *result);
46
- return r == 0;
47
}
48
49
-static bool vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev,
50
+static void vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev,
51
const VhostShadowVirtqueue *svq)
52
{
53
DMAMap needle = {};
54
struct vhost_vdpa *v = dev->opaque;
55
struct vhost_vring_addr svq_addr;
56
- bool ok;
57
58
vhost_svq_get_vring_addr(svq, &svq_addr);
59
60
needle.translated_addr = svq_addr.desc_user_addr;
61
- ok = vhost_vdpa_svq_unmap_ring(v, &needle);
62
- if (unlikely(!ok)) {
63
- return false;
64
- }
65
+ vhost_vdpa_svq_unmap_ring(v, &needle);
66
67
needle.translated_addr = svq_addr.used_user_addr;
68
- return vhost_vdpa_svq_unmap_ring(v, &needle);
69
+ vhost_vdpa_svq_unmap_ring(v, &needle);
70
}
71
72
/**
73
@@ -XXX,XX +XXX,XX @@ err:
74
return false;
75
}
76
77
-static bool vhost_vdpa_svqs_stop(struct vhost_dev *dev)
78
+static void vhost_vdpa_svqs_stop(struct vhost_dev *dev)
79
{
80
struct vhost_vdpa *v = dev->opaque;
81
82
if (!v->shadow_vqs) {
83
- return true;
84
+ return;
85
}
86
87
for (unsigned i = 0; i < v->shadow_vqs->len; ++i) {
88
VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
89
- bool ok = vhost_vdpa_svq_unmap_rings(dev, svq);
90
- if (unlikely(!ok)) {
91
- return false;
92
- }
93
+ vhost_vdpa_svq_unmap_rings(dev, svq);
94
}
95
96
if (v->migration_blocker) {
97
migrate_del_blocker(v->migration_blocker);
98
}
99
- return true;
100
}
101
102
static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
103
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
41
}
104
}
105
vhost_vdpa_set_vring_ready(dev);
106
} else {
107
- ok = vhost_vdpa_svqs_stop(dev);
108
- if (unlikely(!ok)) {
109
- return -1;
110
- }
111
+ vhost_vdpa_svqs_stop(dev);
112
vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
42
}
113
}
43
114
44
--
115
--
45
2.7.4
116
2.7.4
46
117
47
118
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
We can unbind twice a file descriptor if we call twice
4
vhost_svq_set_svq_kick_fd because of this. Since it comes from vhost and
5
not from SVQ, that file descriptor could be a different thing that
6
guest's vhost notifier.
7
8
Likewise, it can happens the same if a guest start and stop the device
9
multiple times.
10
11
Reported-by: Lei Yang <leiyang@redhat.com>
12
Fixes: dff4426fa6 ("vhost: Add Shadow VirtQueue kick forwarding capabilities")
13
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
14
Acked-by: Jason Wang <jasowang@redhat.com>
15
Signed-off-by: Jason Wang <jasowang@redhat.com>
16
---
17
hw/virtio/vhost-shadow-virtqueue.c | 4 ++--
18
1 file changed, 2 insertions(+), 2 deletions(-)
19
20
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/virtio/vhost-shadow-virtqueue.c
23
+++ b/hw/virtio/vhost-shadow-virtqueue.c
24
@@ -XXX,XX +XXX,XX @@ void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd)
25
event_notifier_set_handler(svq_kick, NULL);
26
}
27
28
+ event_notifier_init_fd(svq_kick, svq_kick_fd);
29
/*
30
* event_notifier_set_handler already checks for guest's notifications if
31
* they arrive at the new file descriptor in the switch, so there is no
32
* need to explicitly check for them.
33
*/
34
if (poll_start) {
35
- event_notifier_init_fd(svq_kick, svq_kick_fd);
36
event_notifier_set(svq_kick);
37
event_notifier_set_handler(svq_kick, vhost_handle_guest_kick_notifier);
38
}
39
@@ -XXX,XX +XXX,XX @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev,
40
*/
41
void vhost_svq_stop(VhostShadowVirtqueue *svq)
42
{
43
- event_notifier_set_handler(&svq->svq_kick, NULL);
44
+ vhost_svq_set_svq_kick_fd(svq, VHOST_FILE_UNBIND);
45
g_autofree VirtQueueElement *next_avail_elem = NULL;
46
47
if (!svq->vq) {
48
--
49
2.7.4
50
51
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
Reduce code duplication.
4
5
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
6
Acked-by: Jason Wang <jasowang@redhat.com>
7
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
---
9
hw/virtio/vhost-vdpa.c | 17 ++++++++---------
10
1 file changed, 8 insertions(+), 9 deletions(-)
11
12
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/virtio/vhost-vdpa.c
15
+++ b/hw/virtio/vhost-vdpa.c
16
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev,
17
/**
18
* Unmap a SVQ area in the device
19
*/
20
-static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v,
21
- const DMAMap *needle)
22
+static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, hwaddr addr)
23
{
24
- const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, needle);
25
+ const DMAMap needle = {
26
+ .translated_addr = addr,
27
+ };
28
+ const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, &needle);
29
hwaddr size;
30
int r;
31
32
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v,
33
static void vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev,
34
const VhostShadowVirtqueue *svq)
35
{
36
- DMAMap needle = {};
37
struct vhost_vdpa *v = dev->opaque;
38
struct vhost_vring_addr svq_addr;
39
40
vhost_svq_get_vring_addr(svq, &svq_addr);
41
42
- needle.translated_addr = svq_addr.desc_user_addr;
43
- vhost_vdpa_svq_unmap_ring(v, &needle);
44
+ vhost_vdpa_svq_unmap_ring(v, svq_addr.desc_user_addr);
45
46
- needle.translated_addr = svq_addr.used_user_addr;
47
- vhost_vdpa_svq_unmap_ring(v, &needle);
48
+ vhost_vdpa_svq_unmap_ring(v, svq_addr.used_user_addr);
49
}
50
51
/**
52
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_svq_map_rings(struct vhost_dev *dev,
53
ok = vhost_vdpa_svq_map_ring(v, &device_region, errp);
54
if (unlikely(!ok)) {
55
error_prepend(errp, "Cannot create vq device region: ");
56
- vhost_vdpa_svq_unmap_ring(v, &driver_region);
57
+ vhost_vdpa_svq_unmap_ring(v, driver_region.translated_addr);
58
}
59
addr->used_user_addr = device_region.iova;
60
61
--
62
2.7.4
63
64
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
It was easier to allow vhost_svq_add to handle the memory. Now that we
4
will allow qemu to add elements to a SVQ without the guest's knowledge,
5
it's better to handle it in the caller.
6
7
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
8
Acked-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
hw/virtio/vhost-shadow-virtqueue.c | 10 ++++------
12
1 file changed, 4 insertions(+), 6 deletions(-)
13
14
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/virtio/vhost-shadow-virtqueue.c
17
+++ b/hw/virtio/vhost-shadow-virtqueue.c
18
@@ -XXX,XX +XXX,XX @@ static void vhost_svq_kick(VhostShadowVirtqueue *svq)
19
/**
20
* Add an element to a SVQ.
21
*
22
- * The caller must check that there is enough slots for the new element. It
23
- * takes ownership of the element: In case of failure not ENOSPC, it is free.
24
- *
25
* Return -EINVAL if element is invalid, -ENOSPC if dev queue is full
26
*/
27
int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg,
28
@@ -XXX,XX +XXX,XX @@ int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg,
29
30
ok = vhost_svq_add_split(svq, out_sg, out_num, in_sg, in_num, &qemu_head);
31
if (unlikely(!ok)) {
32
- g_free(elem);
33
return -EINVAL;
34
}
35
36
@@ -XXX,XX +XXX,XX @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq)
37
virtio_queue_set_notification(svq->vq, false);
38
39
while (true) {
40
- VirtQueueElement *elem;
41
+ g_autofree VirtQueueElement *elem;
42
int r;
43
44
if (svq->next_guest_avail_elem) {
45
@@ -XXX,XX +XXX,XX @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq)
46
* queue the current guest descriptor and ignore kicks
47
* until some elements are used.
48
*/
49
- svq->next_guest_avail_elem = elem;
50
+ svq->next_guest_avail_elem = g_steal_pointer(&elem);
51
}
52
53
/* VQ is full or broken, just return and ignore kicks */
54
return;
55
}
56
+ /* elem belongs to SVQ or external caller now */
57
+ elem = NULL;
58
}
59
60
virtio_queue_set_notification(svq->vq, true);
61
--
62
2.7.4
63
64
diff view generated by jsdifflib
1
From: Keqian Zhu <zhukeqian1@huawei.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
Fixes: 63c4db4c2e6d (net: relocate paths to helpers and scripts)
3
Since we're going to allow SVQ to add elements without the guest's
4
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
4
knowledge and without its own VirtQueueElement, it's easier to check if
5
an element is a valid head checking a different thing than the
6
VirtQueueElement.
7
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Acked-by: Jason Wang <jasowang@redhat.com>
5
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
6
---
11
---
7
net/tap.c | 3 ++-
12
hw/virtio/vhost-shadow-virtqueue.c | 3 ++-
8
1 file changed, 2 insertions(+), 1 deletion(-)
13
1 file changed, 2 insertions(+), 1 deletion(-)
9
14
10
diff --git a/net/tap.c b/net/tap.c
15
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
11
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
12
--- a/net/tap.c
17
--- a/hw/virtio/vhost-shadow-virtqueue.c
13
+++ b/net/tap.c
18
+++ b/hw/virtio/vhost-shadow-virtqueue.c
14
@@ -XXX,XX +XXX,XX @@ free_fail:
19
@@ -XXX,XX +XXX,XX @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
15
script = default_script = get_relocated_path(DEFAULT_NETWORK_SCRIPT);
20
return NULL;
16
}
21
}
17
if (!downscript) {
22
18
- downscript = default_downscript = get_relocated_path(DEFAULT_NETWORK_SCRIPT);
23
- if (unlikely(!svq->desc_state[used_elem.id].elem)) {
19
+ downscript = default_downscript =
24
+ if (unlikely(!svq->desc_state[used_elem.id].ndescs)) {
20
+ get_relocated_path(DEFAULT_NETWORK_DOWN_SCRIPT);
25
qemu_log_mask(LOG_GUEST_ERROR,
21
}
26
"Device %s says index %u is used, but it was not available",
22
27
svq->vdev->name, used_elem.id);
23
if (tap->has_ifname) {
28
@@ -XXX,XX +XXX,XX @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq,
29
}
30
31
num = svq->desc_state[used_elem.id].ndescs;
32
+ svq->desc_state[used_elem.id].ndescs = 0;
33
last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id);
34
svq->desc_next[last_used_chain] = svq->free_head;
35
svq->free_head = used_elem.id;
24
--
36
--
25
2.7.4
37
2.7.4
26
38
27
39
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
As discussed in previous series [1], this memory barrier is useless with
4
the atomic read of used idx at vhost_svq_more_used. Deleting it.
5
6
[1] https://lists.nongnu.org/archive/html/qemu-devel/2022-07/msg02616.html
7
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Acked-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
---
12
hw/virtio/vhost-shadow-virtqueue.c | 3 ---
13
1 file changed, 3 deletions(-)
14
15
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/virtio/vhost-shadow-virtqueue.c
18
+++ b/hw/virtio/vhost-shadow-virtqueue.c
19
@@ -XXX,XX +XXX,XX @@ size_t vhost_svq_poll(VhostShadowVirtqueue *svq)
20
if (unlikely(g_get_monotonic_time() - start_us > 10e6)) {
21
return 0;
22
}
23
-
24
- /* Make sure we read new used_idx */
25
- smp_rmb();
26
} while (true);
27
}
28
29
--
30
2.7.4
31
32
diff view generated by jsdifflib
1
From: yuanjungong <ruc_gongyuanjun@163.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
Close fd before returning.
3
Since QEMU will be able to inject new elements on CVQ to restore the
4
state, we need not to depend on a VirtQueueElement to know if a new
5
element has been used by the device or not. Instead of check that, check
6
if there are new elements only using used idx on vhost_svq_flush.
4
7
5
Buglink: https://bugs.launchpad.net/qemu/+bug/1904486
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
6
9
Acked-by: Jason Wang <jasowang@redhat.com>
7
Signed-off-by: yuanjungong <ruc_gongyuanjun@163.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
---
11
net/tap.c | 2 ++
12
hw/virtio/vhost-shadow-virtqueue.c | 11 +++++++----
12
1 file changed, 2 insertions(+)
13
1 file changed, 7 insertions(+), 4 deletions(-)
13
14
14
diff --git a/net/tap.c b/net/tap.c
15
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/net/tap.c
17
--- a/hw/virtio/vhost-shadow-virtqueue.c
17
+++ b/net/tap.c
18
+++ b/hw/virtio/vhost-shadow-virtqueue.c
18
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
19
@@ -XXX,XX +XXX,XX @@ static void vhost_svq_flush(VhostShadowVirtqueue *svq,
19
if (ret < 0) {
20
size_t vhost_svq_poll(VhostShadowVirtqueue *svq)
20
error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d",
21
{
21
name, fd);
22
int64_t start_us = g_get_monotonic_time();
22
+ close(fd);
23
+ uint32_t len;
23
return -1;
24
+
25
do {
26
- uint32_t len;
27
- VirtQueueElement *elem = vhost_svq_get_buf(svq, &len);
28
- if (elem) {
29
- return len;
30
+ if (vhost_svq_more_used(svq)) {
31
+ break;
24
}
32
}
25
33
26
@@ -XXX,XX +XXX,XX @@ int net_init_tap(const Netdev *netdev, const char *name,
34
if (unlikely(g_get_monotonic_time() - start_us > 10e6)) {
27
vhostfdname, vnet_hdr, fd, &err);
35
return 0;
28
if (err) {
29
error_propagate(errp, err);
30
+ close(fd);
31
return -1;
32
}
36
}
33
} else if (tap->has_fds) {
37
} while (true);
38
+
39
+ vhost_svq_get_buf(svq, &len);
40
+ return len;
41
}
42
43
/**
34
--
44
--
35
2.7.4
45
2.7.4
36
46
37
47
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
This is used by the backend to perform actions before the device is
4
started.
5
6
In particular, vdpa net use it to map CVQ buffers to the device, so it
7
can send control commands using them.
8
9
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
10
Acked-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
hw/net/vhost_net.c | 7 +++++++
14
include/net/net.h | 2 ++
15
2 files changed, 9 insertions(+)
16
17
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/vhost_net.c
20
+++ b/hw/net/vhost_net.c
21
@@ -XXX,XX +XXX,XX @@ static int vhost_net_start_one(struct vhost_net *net,
22
struct vhost_vring_file file = { };
23
int r;
24
25
+ if (net->nc->info->start) {
26
+ r = net->nc->info->start(net->nc);
27
+ if (r < 0) {
28
+ return r;
29
+ }
30
+ }
31
+
32
r = vhost_dev_enable_notifiers(&net->dev, dev);
33
if (r < 0) {
34
goto fail_notifiers;
35
diff --git a/include/net/net.h b/include/net/net.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/net/net.h
38
+++ b/include/net/net.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct NICConf {
40
41
typedef void (NetPoll)(NetClientState *, bool enable);
42
typedef bool (NetCanReceive)(NetClientState *);
43
+typedef int (NetStart)(NetClientState *);
44
typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
45
typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
46
typedef void (NetCleanup) (NetClientState *);
47
@@ -XXX,XX +XXX,XX @@ typedef struct NetClientInfo {
48
NetReceive *receive_raw;
49
NetReceiveIOV *receive_iov;
50
NetCanReceive *can_receive;
51
+ NetStart *start;
52
NetCleanup *cleanup;
53
LinkStatusChanged *link_status_changed;
54
QueryRxFilter *query_rx_filter;
55
--
56
2.7.4
57
58
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
Used by the backend to perform actions after the device is stopped.
4
5
In particular, vdpa net use it to unmap CVQ buffers to the device,
6
cleaning the actions performed in prepare().
7
8
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
Acked-by: Jason Wang <jasowang@redhat.com>
10
Signed-off-by: Jason Wang <jasowang@redhat.com>
11
---
12
hw/net/vhost_net.c | 3 +++
13
include/net/net.h | 2 ++
14
2 files changed, 5 insertions(+)
15
16
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/vhost_net.c
19
+++ b/hw/net/vhost_net.c
20
@@ -XXX,XX +XXX,XX @@ static void vhost_net_stop_one(struct vhost_net *net,
21
net->nc->info->poll(net->nc, true);
22
}
23
vhost_dev_stop(&net->dev, dev);
24
+ if (net->nc->info->stop) {
25
+ net->nc->info->stop(net->nc);
26
+ }
27
vhost_dev_disable_notifiers(&net->dev, dev);
28
}
29
30
diff --git a/include/net/net.h b/include/net/net.h
31
index XXXXXXX..XXXXXXX 100644
32
--- a/include/net/net.h
33
+++ b/include/net/net.h
34
@@ -XXX,XX +XXX,XX @@ typedef struct NICConf {
35
typedef void (NetPoll)(NetClientState *, bool enable);
36
typedef bool (NetCanReceive)(NetClientState *);
37
typedef int (NetStart)(NetClientState *);
38
+typedef void (NetStop)(NetClientState *);
39
typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
40
typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
41
typedef void (NetCleanup) (NetClientState *);
42
@@ -XXX,XX +XXX,XX @@ typedef struct NetClientInfo {
43
NetReceiveIOV *receive_iov;
44
NetCanReceive *can_receive;
45
NetStart *start;
46
+ NetStop *stop;
47
NetCleanup *cleanup;
48
LinkStatusChanged *link_status_changed;
49
QueryRxFilter *query_rx_filter;
50
--
51
2.7.4
52
53
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
Next patches will add a new info callback to restore NIC status through
4
CVQ. Since only the CVQ vhost device is needed, create it with a new
5
NetClientInfo.
6
7
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
8
Acked-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
net/vhost-vdpa.c | 12 +++++++++++-
12
1 file changed, 11 insertions(+), 1 deletion(-)
13
14
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/net/vhost-vdpa.c
17
+++ b/net/vhost-vdpa.c
18
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s,
19
return true;
20
}
21
22
+static NetClientInfo net_vhost_vdpa_cvq_info = {
23
+ .type = NET_CLIENT_DRIVER_VHOST_VDPA,
24
+ .size = sizeof(VhostVDPAState),
25
+ .receive = vhost_vdpa_receive,
26
+ .cleanup = vhost_vdpa_cleanup,
27
+ .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
28
+ .has_ufo = vhost_vdpa_has_ufo,
29
+ .check_peer_type = vhost_vdpa_check_peer_type,
30
+};
31
+
32
/**
33
* Do not forward commands not supported by SVQ. Otherwise, the device could
34
* accept it and qemu would not know how to update the device model.
35
@@ -XXX,XX +XXX,XX @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
36
nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device,
37
name);
38
} else {
39
- nc = qemu_new_net_control_client(&net_vhost_vdpa_info, peer,
40
+ nc = qemu_new_net_control_client(&net_vhost_vdpa_cvq_info, peer,
41
device, name);
42
}
43
snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA);
44
--
45
2.7.4
46
47
diff view generated by jsdifflib
New patch
1
1
From: Eugenio Pérez <eperezma@redhat.com>
2
3
As this series will reuse them to restore the device state at the end of
4
a migration (or a device start), let's allocate only once at the device
5
start so we don't duplicate their map and unmap.
6
7
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
8
Acked-by: Jason Wang <jasowang@redhat.com>
9
Signed-off-by: Jason Wang <jasowang@redhat.com>
10
---
11
net/vhost-vdpa.c | 123 ++++++++++++++++++++++++++-----------------------------
12
1 file changed, 58 insertions(+), 65 deletions(-)
13
14
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/net/vhost-vdpa.c
17
+++ b/net/vhost-vdpa.c
18
@@ -XXX,XX +XXX,XX @@ static size_t vhost_vdpa_net_cvq_cmd_page_len(void)
19
return ROUND_UP(vhost_vdpa_net_cvq_cmd_len(), qemu_real_host_page_size());
20
}
21
22
-/** Copy and map a guest buffer. */
23
-static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v,
24
- const struct iovec *out_data,
25
- size_t out_num, size_t data_len, void *buf,
26
- size_t *written, bool write)
27
+/** Map CVQ buffer. */
28
+static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, size_t size,
29
+ bool write)
30
{
31
DMAMap map = {};
32
int r;
33
34
- if (unlikely(!data_len)) {
35
- qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid legnth of %s buffer\n",
36
- __func__, write ? "in" : "out");
37
- return false;
38
- }
39
-
40
- *written = iov_to_buf(out_data, out_num, 0, buf, data_len);
41
map.translated_addr = (hwaddr)(uintptr_t)buf;
42
- map.size = vhost_vdpa_net_cvq_cmd_page_len() - 1;
43
+ map.size = size - 1;
44
map.perm = write ? IOMMU_RW : IOMMU_RO,
45
r = vhost_iova_tree_map_alloc(v->iova_tree, &map);
46
if (unlikely(r != IOVA_OK)) {
47
error_report("Cannot map injected element");
48
- return false;
49
+ return r;
50
}
51
52
r = vhost_vdpa_dma_map(v, map.iova, vhost_vdpa_net_cvq_cmd_page_len(), buf,
53
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v,
54
goto dma_map_err;
55
}
56
57
- return true;
58
+ return 0;
59
60
dma_map_err:
61
vhost_iova_tree_remove(v->iova_tree, map);
62
- return false;
63
+ return r;
64
}
65
66
-/**
67
- * Copy the guest element into a dedicated buffer suitable to be sent to NIC
68
- *
69
- * @iov: [0] is the out buffer, [1] is the in one
70
- */
71
-static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s,
72
- VirtQueueElement *elem,
73
- struct iovec *iov)
74
+static int vhost_vdpa_net_cvq_start(NetClientState *nc)
75
{
76
- size_t in_copied;
77
- bool ok;
78
+ VhostVDPAState *s;
79
+ int r;
80
81
- iov[0].iov_base = s->cvq_cmd_out_buffer;
82
- ok = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, elem->out_sg, elem->out_num,
83
- vhost_vdpa_net_cvq_cmd_len(), iov[0].iov_base,
84
- &iov[0].iov_len, false);
85
- if (unlikely(!ok)) {
86
- return false;
87
+ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
88
+
89
+ s = DO_UPCAST(VhostVDPAState, nc, nc);
90
+ if (!s->vhost_vdpa.shadow_vqs_enabled) {
91
+ return 0;
92
}
93
94
- iov[1].iov_base = s->cvq_cmd_in_buffer;
95
- ok = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, NULL, 0,
96
- sizeof(virtio_net_ctrl_ack), iov[1].iov_base,
97
- &in_copied, true);
98
- if (unlikely(!ok)) {
99
+ r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer,
100
+ vhost_vdpa_net_cvq_cmd_page_len(), false);
101
+ if (unlikely(r < 0)) {
102
+ return r;
103
+ }
104
+
105
+ r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->cvq_cmd_in_buffer,
106
+ vhost_vdpa_net_cvq_cmd_page_len(), true);
107
+ if (unlikely(r < 0)) {
108
vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer);
109
- return false;
110
}
111
112
- iov[1].iov_len = sizeof(virtio_net_ctrl_ack);
113
- return true;
114
+ return r;
115
+}
116
+
117
+static void vhost_vdpa_net_cvq_stop(NetClientState *nc)
118
+{
119
+ VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
120
+
121
+ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
122
+
123
+ if (s->vhost_vdpa.shadow_vqs_enabled) {
124
+ vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer);
125
+ vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_in_buffer);
126
+ }
127
}
128
129
static NetClientInfo net_vhost_vdpa_cvq_info = {
130
.type = NET_CLIENT_DRIVER_VHOST_VDPA,
131
.size = sizeof(VhostVDPAState),
132
.receive = vhost_vdpa_receive,
133
+ .start = vhost_vdpa_net_cvq_start,
134
+ .stop = vhost_vdpa_net_cvq_stop,
135
.cleanup = vhost_vdpa_cleanup,
136
.has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
137
.has_ufo = vhost_vdpa_has_ufo,
138
@@ -XXX,XX +XXX,XX @@ static NetClientInfo net_vhost_vdpa_cvq_info = {
139
* Do not forward commands not supported by SVQ. Otherwise, the device could
140
* accept it and qemu would not know how to update the device model.
141
*/
142
-static bool vhost_vdpa_net_cvq_validate_cmd(const struct iovec *out,
143
- size_t out_num)
144
+static bool vhost_vdpa_net_cvq_validate_cmd(const void *out_buf, size_t len)
145
{
146
struct virtio_net_ctrl_hdr ctrl;
147
- size_t n;
148
149
- n = iov_to_buf(out, out_num, 0, &ctrl, sizeof(ctrl));
150
- if (unlikely(n < sizeof(ctrl))) {
151
+ if (unlikely(len < sizeof(ctrl))) {
152
qemu_log_mask(LOG_GUEST_ERROR,
153
- "%s: invalid legnth of out buffer %zu\n", __func__, n);
154
+ "%s: invalid legnth of out buffer %zu\n", __func__, len);
155
return false;
156
}
157
158
+ memcpy(&ctrl, out_buf, sizeof(ctrl));
159
switch (ctrl.class) {
160
case VIRTIO_NET_CTRL_MAC:
161
switch (ctrl.cmd) {
162
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
163
VhostVDPAState *s = opaque;
164
size_t in_len, dev_written;
165
virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
166
- /* out and in buffers sent to the device */
167
- struct iovec dev_buffers[2] = {
168
- { .iov_base = s->cvq_cmd_out_buffer },
169
- { .iov_base = s->cvq_cmd_in_buffer },
170
+ /* Out buffer sent to both the vdpa device and the device model */
171
+ struct iovec out = {
172
+ .iov_base = s->cvq_cmd_out_buffer,
173
+ };
174
+ /* In buffer sent to the device */
175
+ const struct iovec dev_in = {
176
+ .iov_base = s->cvq_cmd_in_buffer,
177
+ .iov_len = sizeof(virtio_net_ctrl_ack),
178
};
179
/* in buffer used for device model */
180
const struct iovec in = {
181
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
182
int r = -EINVAL;
183
bool ok;
184
185
- ok = vhost_vdpa_net_cvq_map_elem(s, elem, dev_buffers);
186
- if (unlikely(!ok)) {
187
- goto out;
188
- }
189
-
190
- ok = vhost_vdpa_net_cvq_validate_cmd(&dev_buffers[0], 1);
191
+ out.iov_len = iov_to_buf(elem->out_sg, elem->out_num, 0,
192
+ s->cvq_cmd_out_buffer,
193
+ vhost_vdpa_net_cvq_cmd_len());
194
+ ok = vhost_vdpa_net_cvq_validate_cmd(s->cvq_cmd_out_buffer, out.iov_len);
195
if (unlikely(!ok)) {
196
goto out;
197
}
198
199
- r = vhost_svq_add(svq, &dev_buffers[0], 1, &dev_buffers[1], 1, elem);
200
+ r = vhost_svq_add(svq, &out, 1, &dev_in, 1, elem);
201
if (unlikely(r != 0)) {
202
if (unlikely(r == -ENOSPC)) {
203
qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n",
204
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
205
goto out;
206
}
207
208
- memcpy(&status, dev_buffers[1].iov_base, sizeof(status));
209
+ memcpy(&status, s->cvq_cmd_in_buffer, sizeof(status));
210
if (status != VIRTIO_NET_OK) {
211
goto out;
212
}
213
214
status = VIRTIO_NET_ERR;
215
- virtio_net_handle_ctrl_iov(svq->vdev, &in, 1, dev_buffers, 1);
216
+ virtio_net_handle_ctrl_iov(svq->vdev, &in, 1, &out, 1);
217
if (status != VIRTIO_NET_OK) {
218
error_report("Bad CVQ processing in model");
219
}
220
@@ -XXX,XX +XXX,XX @@ out:
221
}
222
vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status)));
223
g_free(elem);
224
- if (dev_buffers[0].iov_base) {
225
- vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, dev_buffers[0].iov_base);
226
- }
227
- if (dev_buffers[1].iov_base) {
228
- vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, dev_buffers[1].iov_base);
229
- }
230
return r;
231
}
232
233
--
234
2.7.4
235
236
diff view generated by jsdifflib
1
From: Paolo Bonzini <pbonzini@redhat.com>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
"netdev_add help" is causing QEMU to exit because the code that
3
So we can reuse it to inject state messages.
4
invokes show_netdevs is shared between CLI and HMP processing.
5
Move the check to the callers so that exit(0) remains only
6
in the CLI flow.
7
4
8
"netdev_add help" is not fixed by this patch; that is left for
5
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
9
later work.
6
Acked-by: Jason Wang <jasowang@redhat.com>
7
--
8
v7:
9
* Remove double free error
10
10
11
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
11
v6:
12
* Do not assume in buffer sent to the device is sizeof(virtio_net_ctrl_ack)
13
14
v5:
15
* Do not use an artificial !NULL VirtQueueElement
16
* Use only out size instead of iovec dev_buffers for these functions.
17
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
18
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
19
---
14
include/net/net.h | 1 +
20
net/vhost-vdpa.c | 59 ++++++++++++++++++++++++++++++++++++--------------------
15
monitor/hmp-cmds.c | 6 +++++
21
1 file changed, 38 insertions(+), 21 deletions(-)
16
net/net.c | 68 +++++++++++++++++++++++++++---------------------------
17
3 files changed, 41 insertions(+), 34 deletions(-)
18
22
19
diff --git a/include/net/net.h b/include/net/net.h
23
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
20
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
21
--- a/include/net/net.h
25
--- a/net/vhost-vdpa.c
22
+++ b/include/net/net.h
26
+++ b/net/vhost-vdpa.c
23
@@ -XXX,XX +XXX,XX @@ extern const char *host_net_devices[];
27
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_net_cvq_stop(NetClientState *nc)
24
25
/* from net.c */
26
int net_client_parse(QemuOptsList *opts_list, const char *str);
27
+void show_netdevs(void);
28
int net_init_clients(Error **errp);
29
void net_check_clients(void);
30
void net_cleanup(void);
31
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/monitor/hmp-cmds.c
34
+++ b/monitor/hmp-cmds.c
35
@@ -XXX,XX +XXX,XX @@
36
#include "qemu/option.h"
37
#include "qemu/timer.h"
38
#include "qemu/sockets.h"
39
+#include "qemu/help_option.h"
40
#include "monitor/monitor-internal.h"
41
#include "qapi/error.h"
42
#include "qapi/clone-visitor.h"
43
@@ -XXX,XX +XXX,XX @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict)
44
{
45
Error *err = NULL;
46
QemuOpts *opts;
47
+ const char *type = qdict_get_try_str(qdict, "type");
48
49
+ if (type && is_help_option(type)) {
50
+ show_netdevs();
51
+ return;
52
+ }
53
opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err);
54
if (err) {
55
goto out;
56
diff --git a/net/net.c b/net/net.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/net/net.c
59
+++ b/net/net.c
60
@@ -XXX,XX +XXX,XX @@
61
#include "qemu/config-file.h"
62
#include "qemu/ctype.h"
63
#include "qemu/iov.h"
64
+#include "qemu/qemu-print.h"
65
#include "qemu/main-loop.h"
66
#include "qemu/option.h"
67
#include "qapi/error.h"
68
@@ -XXX,XX +XXX,XX @@ static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp)
69
return 0;
70
}
71
72
-static void show_netdevs(void)
73
+void show_netdevs(void)
74
{
75
int idx;
76
const char *available_netdevs[] = {
77
@@ -XXX,XX +XXX,XX @@ static void show_netdevs(void)
78
#endif
79
};
80
81
- printf("Available netdev backend types:\n");
82
+ qemu_printf("Available netdev backend types:\n");
83
for (idx = 0; idx < ARRAY_SIZE(available_netdevs); idx++) {
84
- puts(available_netdevs[idx]);
85
+ qemu_printf("%s\n", available_netdevs[idx]);
86
}
28
}
87
}
29
}
88
30
89
@@ -XXX,XX +XXX,XX @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp)
31
+static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len,
90
int ret = -1;
32
+ size_t in_len)
91
Visitor *v = opts_visitor_new(opts);
33
+{
92
34
+ /* Buffers for the device */
93
- const char *type = qemu_opt_get(opts, "type");
35
+ const struct iovec out = {
94
-
36
+ .iov_base = s->cvq_cmd_out_buffer,
95
- if (is_netdev && type && is_help_option(type)) {
37
+ .iov_len = out_len,
96
- show_netdevs();
38
+ };
97
- exit(0);
39
+ const struct iovec in = {
98
- } else {
40
+ .iov_base = s->cvq_cmd_in_buffer,
99
- /* Parse convenience option format ip6-net=fec0::0[/64] */
41
+ .iov_len = sizeof(virtio_net_ctrl_ack),
100
- const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
42
+ };
101
+ /* Parse convenience option format ip6-net=fec0::0[/64] */
43
+ VhostShadowVirtqueue *svq = g_ptr_array_index(s->vhost_vdpa.shadow_vqs, 0);
102
+ const char *ip6_net = qemu_opt_get(opts, "ipv6-net");
44
+ int r;
103
45
+
104
- if (ip6_net) {
46
+ r = vhost_svq_add(svq, &out, 1, &in, 1, NULL);
105
- char *prefix_addr;
47
+ if (unlikely(r != 0)) {
106
- unsigned long prefix_len = 64; /* Default 64bit prefix length. */
48
+ if (unlikely(r == -ENOSPC)) {
107
+ if (ip6_net) {
49
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n",
108
+ char *prefix_addr;
50
+ __func__);
109
+ unsigned long prefix_len = 64; /* Default 64bit prefix length. */
110
111
- substrings = g_strsplit(ip6_net, "/", 2);
112
- if (!substrings || !substrings[0]) {
113
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net",
114
- "a valid IPv6 prefix");
115
- goto out;
116
- }
117
+ substrings = g_strsplit(ip6_net, "/", 2);
118
+ if (!substrings || !substrings[0]) {
119
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "ipv6-net",
120
+ "a valid IPv6 prefix");
121
+ goto out;
122
+ }
51
+ }
123
52
+ return r;
124
- prefix_addr = substrings[0];
53
+ }
125
+ prefix_addr = substrings[0];
126
127
- /* Handle user-specified prefix length. */
128
- if (substrings[1] &&
129
- qemu_strtoul(substrings[1], NULL, 10, &prefix_len))
130
- {
131
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
132
- "ipv6-prefixlen", "a number");
133
- goto out;
134
- }
135
-
136
- qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort);
137
- qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len,
138
- &error_abort);
139
- qemu_opt_unset(opts, "ipv6-net");
140
+ /* Handle user-specified prefix length. */
141
+ if (substrings[1] &&
142
+ qemu_strtoul(substrings[1], NULL, 10, &prefix_len))
143
+ {
144
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
145
+ "ipv6-prefixlen", "a number");
146
+ goto out;
147
}
148
+
54
+
149
+ qemu_opt_set(opts, "ipv6-prefix", prefix_addr, &error_abort);
55
+ /*
150
+ qemu_opt_set_number(opts, "ipv6-prefixlen", prefix_len,
56
+ * We can poll here since we've had BQL from the time we sent the
151
+ &error_abort);
57
+ * descriptor. Also, we need to take the answer before SVQ pulls by itself,
152
+ qemu_opt_unset(opts, "ipv6-net");
58
+ * when BQL is released
59
+ */
60
+ return vhost_svq_poll(svq);
61
+}
62
+
63
static NetClientInfo net_vhost_vdpa_cvq_info = {
64
.type = NET_CLIENT_DRIVER_VHOST_VDPA,
65
.size = sizeof(VhostVDPAState),
66
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
67
void *opaque)
68
{
69
VhostVDPAState *s = opaque;
70
- size_t in_len, dev_written;
71
+ size_t in_len;
72
virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
73
/* Out buffer sent to both the vdpa device and the device model */
74
struct iovec out = {
75
.iov_base = s->cvq_cmd_out_buffer,
76
};
77
- /* In buffer sent to the device */
78
- const struct iovec dev_in = {
79
- .iov_base = s->cvq_cmd_in_buffer,
80
- .iov_len = sizeof(virtio_net_ctrl_ack),
81
- };
82
/* in buffer used for device model */
83
const struct iovec in = {
84
.iov_base = &status,
85
.iov_len = sizeof(status),
86
};
87
- int r = -EINVAL;
88
+ ssize_t dev_written = -EINVAL;
89
bool ok;
90
91
out.iov_len = iov_to_buf(elem->out_sg, elem->out_num, 0,
92
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
93
goto out;
153
}
94
}
154
95
155
/* Create an ID for -net if the user did not specify one */
96
- r = vhost_svq_add(svq, &out, 1, &dev_in, 1, elem);
156
@@ -XXX,XX +XXX,XX @@ static int net_init_client(void *dummy, QemuOpts *opts, Error **errp)
97
- if (unlikely(r != 0)) {
157
98
- if (unlikely(r == -ENOSPC)) {
158
static int net_init_netdev(void *dummy, QemuOpts *opts, Error **errp)
99
- qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n",
159
{
100
- __func__);
160
+ const char *type = qemu_opt_get(opts, "type");
101
- }
161
+
102
+ dev_written = vhost_vdpa_net_cvq_add(s, out.iov_len, sizeof(status));
162
+ if (type && is_help_option(type)) {
103
+ if (unlikely(dev_written < 0)) {
163
+ show_netdevs();
104
goto out;
164
+ exit(0);
105
}
165
+ }
106
166
return net_client_init(opts, true, errp);
107
- /*
108
- * We can poll here since we've had BQL from the time we sent the
109
- * descriptor. Also, we need to take the answer before SVQ pulls by itself,
110
- * when BQL is released
111
- */
112
- dev_written = vhost_svq_poll(svq);
113
if (unlikely(dev_written < sizeof(status))) {
114
error_report("Insufficient written data (%zu)", dev_written);
115
goto out;
116
@@ -XXX,XX +XXX,XX @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq,
117
118
memcpy(&status, s->cvq_cmd_in_buffer, sizeof(status));
119
if (status != VIRTIO_NET_OK) {
120
- goto out;
121
+ return VIRTIO_NET_ERR;
122
}
123
124
status = VIRTIO_NET_ERR;
125
@@ -XXX,XX +XXX,XX @@ out:
126
}
127
vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status)));
128
g_free(elem);
129
- return r;
130
+ return dev_written < 0 ? dev_written : 0;
167
}
131
}
168
132
133
static const VhostShadowVirtqueueOps vhost_vdpa_net_svq_ops = {
169
--
134
--
170
2.7.4
135
2.7.4
171
136
172
137
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
It allows per-net client operations right after device's successful
4
start. In particular, to load the device status.
5
6
Vhost-vdpa net will use it to add the CVQ buffers to restore the device
7
status.
8
9
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
10
Acked-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
13
hw/net/vhost_net.c | 7 +++++++
14
include/net/net.h | 2 ++
15
2 files changed, 9 insertions(+)
16
17
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/vhost_net.c
20
+++ b/hw/net/vhost_net.c
21
@@ -XXX,XX +XXX,XX @@ static int vhost_net_start_one(struct vhost_net *net,
22
}
23
}
24
}
25
+
26
+ if (net->nc->info->load) {
27
+ r = net->nc->info->load(net->nc);
28
+ if (r < 0) {
29
+ goto fail;
30
+ }
31
+ }
32
return 0;
33
fail:
34
file.fd = -1;
35
diff --git a/include/net/net.h b/include/net/net.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/net/net.h
38
+++ b/include/net/net.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct NICConf {
40
typedef void (NetPoll)(NetClientState *, bool enable);
41
typedef bool (NetCanReceive)(NetClientState *);
42
typedef int (NetStart)(NetClientState *);
43
+typedef int (NetLoad)(NetClientState *);
44
typedef void (NetStop)(NetClientState *);
45
typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
46
typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
47
@@ -XXX,XX +XXX,XX @@ typedef struct NetClientInfo {
48
NetReceiveIOV *receive_iov;
49
NetCanReceive *can_receive;
50
NetStart *start;
51
+ NetLoad *load;
52
NetStop *stop;
53
NetCleanup *cleanup;
54
LinkStatusChanged *link_status_changed;
55
--
56
2.7.4
57
58
diff view generated by jsdifflib
New patch
1
From: Eugenio Pérez <eperezma@redhat.com>
1
2
3
This is needed so the destination vdpa device see the same state a the
4
guest set in the source.
5
6
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
7
Acked-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
9
---
10
net/vhost-vdpa.c | 40 ++++++++++++++++++++++++++++++++++++++++
11
1 file changed, 40 insertions(+)
12
13
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/net/vhost-vdpa.c
16
+++ b/net/vhost-vdpa.c
17
@@ -XXX,XX +XXX,XX @@ static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len,
18
return vhost_svq_poll(svq);
19
}
20
21
+static int vhost_vdpa_net_load(NetClientState *nc)
22
+{
23
+ VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
24
+ const struct vhost_vdpa *v = &s->vhost_vdpa;
25
+ const VirtIONet *n;
26
+ uint64_t features;
27
+
28
+ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
29
+
30
+ if (!v->shadow_vqs_enabled) {
31
+ return 0;
32
+ }
33
+
34
+ n = VIRTIO_NET(v->dev->vdev);
35
+ features = n->parent_obj.guest_features;
36
+ if (features & BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR)) {
37
+ const struct virtio_net_ctrl_hdr ctrl = {
38
+ .class = VIRTIO_NET_CTRL_MAC,
39
+ .cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET,
40
+ };
41
+ char *cursor = s->cvq_cmd_out_buffer;
42
+ ssize_t dev_written;
43
+
44
+ memcpy(cursor, &ctrl, sizeof(ctrl));
45
+ cursor += sizeof(ctrl);
46
+ memcpy(cursor, n->mac, sizeof(n->mac));
47
+
48
+ dev_written = vhost_vdpa_net_cvq_add(s, sizeof(ctrl) + sizeof(n->mac),
49
+ sizeof(virtio_net_ctrl_ack));
50
+ if (unlikely(dev_written < 0)) {
51
+ return dev_written;
52
+ }
53
+
54
+ return *((virtio_net_ctrl_ack *)s->cvq_cmd_in_buffer) != VIRTIO_NET_OK;
55
+ }
56
+
57
+ return 0;
58
+}
59
+
60
static NetClientInfo net_vhost_vdpa_cvq_info = {
61
.type = NET_CLIENT_DRIVER_VHOST_VDPA,
62
.size = sizeof(VhostVDPAState),
63
.receive = vhost_vdpa_receive,
64
.start = vhost_vdpa_net_cvq_start,
65
+ .load = vhost_vdpa_net_load,
66
.stop = vhost_vdpa_net_cvq_stop,
67
.cleanup = vhost_vdpa_cleanup,
68
.has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
69
--
70
2.7.4
71
72
diff view generated by jsdifflib
1
From: Prasad J Pandit <pjp@fedoraproject.org>
1
From: Eugenio Pérez <eperezma@redhat.com>
2
2
3
While receiving packets via e1000e_write_packet_to_guest() routine,
3
We can restore the device state in the destination via CVQ now. Remove
4
'desc_offset' is advanced only when RX descriptor is processed. And
4
the migration blocker.
5
RX descriptor is not processed if it has NULL buffer address.
6
This may lead to an infinite loop condition. Increament 'desc_offset'
7
to process next descriptor in the ring to avoid infinite loop.
8
5
9
Reported-by: Cheol-woo Myung <330cjfdn@gmail.com>
6
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
10
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
7
Acked-by: Jason Wang <jasowang@redhat.com>
11
Signed-off-by: Jason Wang <jasowang@redhat.com>
8
Signed-off-by: Jason Wang <jasowang@redhat.com>
12
---
9
---
13
hw/net/e1000e_core.c | 8 ++++----
10
hw/virtio/vhost-vdpa.c | 15 ---------------
14
1 file changed, 4 insertions(+), 4 deletions(-)
11
include/hw/virtio/vhost-vdpa.h | 1 -
12
net/vhost-vdpa.c | 2 --
13
3 files changed, 18 deletions(-)
15
14
16
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
15
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/net/e1000e_core.c
17
--- a/hw/virtio/vhost-vdpa.c
19
+++ b/hw/net/e1000e_core.c
18
+++ b/hw/virtio/vhost-vdpa.c
20
@@ -XXX,XX +XXX,XX @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt,
19
@@ -XXX,XX +XXX,XX @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev)
21
(const char *) &fcs_pad, e1000x_fcs_len(core->mac));
20
return true;
22
}
21
}
23
}
22
24
- desc_offset += desc_size;
23
- if (v->migration_blocker) {
25
- if (desc_offset >= total_size) {
24
- int r = migrate_add_blocker(v->migration_blocker, &err);
26
- is_last = true;
25
- if (unlikely(r < 0)) {
27
- }
26
- return false;
28
} else { /* as per intel docs; skip descriptors with null buf addr */
27
- }
29
trace_e1000e_rx_null_descriptor();
28
- }
30
}
29
-
31
+ desc_offset += desc_size;
30
for (i = 0; i < v->shadow_vqs->len; ++i) {
32
+ if (desc_offset >= total_size) {
31
VirtQueue *vq = virtio_get_queue(dev->vdev, dev->vq_index + i);
33
+ is_last = true;
32
VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
34
+ }
33
@@ -XXX,XX +XXX,XX @@ err:
35
34
vhost_svq_stop(svq);
36
e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL,
35
}
37
rss_info, do_ps ? ps_hdr_len : 0, &bastate.written);
36
37
- if (v->migration_blocker) {
38
- migrate_del_blocker(v->migration_blocker);
39
- }
40
-
41
return false;
42
}
43
44
@@ -XXX,XX +XXX,XX @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev)
45
VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i);
46
vhost_vdpa_svq_unmap_rings(dev, svq);
47
}
48
-
49
- if (v->migration_blocker) {
50
- migrate_del_blocker(v->migration_blocker);
51
- }
52
}
53
54
static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
55
diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
56
index XXXXXXX..XXXXXXX 100644
57
--- a/include/hw/virtio/vhost-vdpa.h
58
+++ b/include/hw/virtio/vhost-vdpa.h
59
@@ -XXX,XX +XXX,XX @@ typedef struct vhost_vdpa {
60
bool shadow_vqs_enabled;
61
/* IOVA mapping used by the Shadow Virtqueue */
62
VhostIOVATree *iova_tree;
63
- Error *migration_blocker;
64
GPtrArray *shadow_vqs;
65
const VhostShadowVirtqueueOps *shadow_vq_ops;
66
void *shadow_vq_ops_opaque;
67
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/net/vhost-vdpa.c
70
+++ b/net/vhost-vdpa.c
71
@@ -XXX,XX +XXX,XX @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
72
73
s->vhost_vdpa.shadow_vq_ops = &vhost_vdpa_net_svq_ops;
74
s->vhost_vdpa.shadow_vq_ops_opaque = s;
75
- error_setg(&s->vhost_vdpa.migration_blocker,
76
- "Migration disabled: vhost-vdpa uses CVQ.");
77
}
78
ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa, queue_pair_index, nvqs);
79
if (ret) {
38
--
80
--
39
2.7.4
81
2.7.4
40
82
41
83
diff view generated by jsdifflib
New patch
1
From: Zhang Chen <chen.zhang@intel.com>
1
2
3
When enabled the virtio-net-pci, guest network packet will
4
load the vnet_hdr. In COLO status, the primary VM's network
5
packet maybe redirect to another VM, it needs filter-redirect
6
enable the vnet_hdr flag at the same time, COLO-proxy will
7
correctly parse the original network packet. If have any
8
misconfiguration here, the vnet_hdr_len is wrong for parse
9
the packet, the data+offset will point to wrong place.
10
11
Signed-off-by: Zhang Chen <chen.zhang@intel.com>
12
Signed-off-by: Jason Wang <jasowang@redhat.com>
13
---
14
net/colo.c | 25 ++++++++++++++++---------
15
net/colo.h | 1 +
16
net/trace-events | 2 +-
17
3 files changed, 18 insertions(+), 10 deletions(-)
18
19
diff --git a/net/colo.c b/net/colo.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/net/colo.c
22
+++ b/net/colo.c
23
@@ -XXX,XX +XXX,XX @@ int parse_packet_early(Packet *pkt)
24
{
25
int network_length;
26
static const uint8_t vlan[] = {0x81, 0x00};
27
- uint8_t *data = pkt->data + pkt->vnet_hdr_len;
28
+ uint8_t *data = pkt->data;
29
uint16_t l3_proto;
30
ssize_t l2hdr_len;
31
32
- if (data == NULL) {
33
- trace_colo_proxy_main_vnet_info("This packet is not parsed correctly, "
34
- "pkt->vnet_hdr_len", pkt->vnet_hdr_len);
35
+ assert(data);
36
+
37
+ /* Check the received vnet_hdr_len then add the offset */
38
+ if ((pkt->vnet_hdr_len > sizeof(struct virtio_net_hdr_v1_hash)) ||
39
+ (pkt->size < sizeof(struct eth_header) + sizeof(struct vlan_header) +
40
+ pkt->vnet_hdr_len)) {
41
+ /*
42
+ * The received remote packet maybe misconfiguration here,
43
+ * Please enable/disable filter module's the vnet_hdr flag at
44
+ * the same time.
45
+ */
46
+ trace_colo_proxy_main_vnet_info("This received packet load wrong ",
47
+ pkt->vnet_hdr_len, pkt->size);
48
return 1;
49
}
50
- l2hdr_len = eth_get_l2_hdr_length(data);
51
+ data += pkt->vnet_hdr_len;
52
53
- if (pkt->size < ETH_HLEN + pkt->vnet_hdr_len) {
54
- trace_colo_proxy_main("pkt->size < ETH_HLEN");
55
- return 1;
56
- }
57
+ l2hdr_len = eth_get_l2_hdr_length(data);
58
59
/*
60
* TODO: support vlan.
61
diff --git a/net/colo.h b/net/colo.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/net/colo.h
64
+++ b/net/colo.h
65
@@ -XXX,XX +XXX,XX @@
66
#include "qemu/jhash.h"
67
#include "qemu/timer.h"
68
#include "net/eth.h"
69
+#include "standard-headers/linux/virtio_net.h"
70
71
#define HASHTABLE_MAX_SIZE 16384
72
73
diff --git a/net/trace-events b/net/trace-events
74
index XXXXXXX..XXXXXXX 100644
75
--- a/net/trace-events
76
+++ b/net/trace-events
77
@@ -XXX,XX +XXX,XX @@ vhost_user_event(const char *chr, int event) "chr: %s got event: %d"
78
79
# colo.c
80
colo_proxy_main(const char *chr) ": %s"
81
-colo_proxy_main_vnet_info(const char *sta, int size) ": %s = %d"
82
+colo_proxy_main_vnet_info(const char *sta, uint32_t vnet_hdr, int size) ": %s pkt->vnet_hdr_len = %u, pkt->size = %d"
83
84
# colo-compare.c
85
colo_compare_main(const char *chr) ": %s"
86
--
87
2.7.4
diff view generated by jsdifflib
New patch
1
From: Zheyu Ma <zheyuma97@gmail.com>
1
2
3
The DMA engine is started by I/O access and then itself accesses the
4
I/O registers, triggering a reentrancy bug.
5
6
The following log can reveal it:
7
==5637==ERROR: AddressSanitizer: stack-overflow
8
#0 0x5595435f6078 in tulip_xmit_list_update qemu/hw/net/tulip.c:673
9
#1 0x5595435f204a in tulip_write qemu/hw/net/tulip.c:805:13
10
#2 0x559544637f86 in memory_region_write_accessor qemu/softmmu/memory.c:492:5
11
#3 0x5595446379fa in access_with_adjusted_size qemu/softmmu/memory.c:554:18
12
#4 0x5595446372fa in memory_region_dispatch_write qemu/softmmu/memory.c
13
#5 0x55954468b74c in flatview_write_continue qemu/softmmu/physmem.c:2825:23
14
#6 0x559544683662 in flatview_write qemu/softmmu/physmem.c:2867:12
15
#7 0x5595446833f3 in address_space_write qemu/softmmu/physmem.c:2963:18
16
#8 0x5595435fb082 in dma_memory_rw_relaxed qemu/include/sysemu/dma.h:87:12
17
#9 0x5595435fb082 in dma_memory_rw qemu/include/sysemu/dma.h:130:12
18
#10 0x5595435fb082 in dma_memory_write qemu/include/sysemu/dma.h:171:12
19
#11 0x5595435fb082 in stl_le_dma qemu/include/sysemu/dma.h:272:1
20
#12 0x5595435fb082 in stl_le_pci_dma qemu/include/hw/pci/pci.h:910:1
21
#13 0x5595435fb082 in tulip_desc_write qemu/hw/net/tulip.c:101:9
22
#14 0x5595435f7e3d in tulip_xmit_list_update qemu/hw/net/tulip.c:706:9
23
#15 0x5595435f204a in tulip_write qemu/hw/net/tulip.c:805:13
24
25
Fix this bug by restricting the DMA engine to memories regions.
26
27
Signed-off-by: Zheyu Ma <zheyuma97@gmail.com>
28
Signed-off-by: Jason Wang <jasowang@redhat.com>
29
---
30
hw/net/tulip.c | 4 ++--
31
1 file changed, 2 insertions(+), 2 deletions(-)
32
33
diff --git a/hw/net/tulip.c b/hw/net/tulip.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/net/tulip.c
36
+++ b/hw/net/tulip.c
37
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_pci_tulip = {
38
static void tulip_desc_read(TULIPState *s, hwaddr p,
39
struct tulip_descriptor *desc)
40
{
41
- const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
42
+ const MemTxAttrs attrs = { .memory = true };
43
44
if (s->csr[0] & CSR0_DBO) {
45
ldl_be_pci_dma(&s->dev, p, &desc->status, attrs);
46
@@ -XXX,XX +XXX,XX @@ static void tulip_desc_read(TULIPState *s, hwaddr p,
47
static void tulip_desc_write(TULIPState *s, hwaddr p,
48
struct tulip_descriptor *desc)
49
{
50
- const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
51
+ const MemTxAttrs attrs = { .memory = true };
52
53
if (s->csr[0] & CSR0_DBO) {
54
stl_be_pci_dma(&s->dev, p, desc->status, attrs);
55
--
56
2.7.4
diff view generated by jsdifflib