Revision 8172539d
b/hw/s390-virtio-bus.c | ||
---|---|---|
101 | 101 |
bus->dev_offs += dev_len; |
102 | 102 |
|
103 | 103 |
virtio_bind_device(vdev, &virtio_s390_bindings, dev); |
104 |
dev->host_features = vdev->get_features(vdev, dev->host_features); |
|
104 | 105 |
s390_virtio_device_sync(dev); |
105 | 106 |
|
106 | 107 |
return 0; |
... | ... | |
222 | 223 |
cur_offs += num_vq * VIRTIO_VQCONFIG_LEN; |
223 | 224 |
|
224 | 225 |
/* Sync feature bitmap */ |
225 |
if (dev->vdev->get_features) { |
|
226 |
stl_phys(cur_offs, dev->vdev->get_features(dev->vdev)); |
|
227 |
} |
|
226 |
stl_phys(cur_offs, dev->host_features); |
|
228 | 227 |
|
229 | 228 |
dev->feat_offs = cur_offs + dev->feat_len; |
230 | 229 |
cur_offs += dev->feat_len * 2; |
... | ... | |
310 | 309 |
kvm_s390_virtio_irq(s390_cpu_addr2state(0), 0, token); |
311 | 310 |
} |
312 | 311 |
|
312 |
static unsigned virtio_s390_get_features(void *opaque) |
|
313 |
{ |
|
314 |
VirtIOS390Device *dev = (VirtIOS390Device*)opaque; |
|
315 |
return dev->host_features; |
|
316 |
} |
|
317 |
|
|
313 | 318 |
/**************** S390 Virtio Bus Device Descriptions *******************/ |
314 | 319 |
|
315 | 320 |
static const VirtIOBindings virtio_s390_bindings = { |
316 | 321 |
.notify = virtio_s390_notify, |
322 |
.get_features = virtio_s390_get_features, |
|
317 | 323 |
}; |
318 | 324 |
|
319 | 325 |
static VirtIOS390DeviceInfo s390_virtio_net = { |
b/hw/s390-virtio-bus.h | ||
---|---|---|
40 | 40 |
VirtIODevice *vdev; |
41 | 41 |
DriveInfo *dinfo; |
42 | 42 |
NICConf nic; |
43 |
uint32_t host_features; |
|
43 | 44 |
} VirtIOS390Device; |
44 | 45 |
|
45 | 46 |
typedef struct VirtIOS390Bus { |
b/hw/syborg_virtio.c | ||
---|---|---|
25 | 25 |
#include "syborg.h" |
26 | 26 |
#include "sysbus.h" |
27 | 27 |
#include "virtio.h" |
28 |
#include "virtio-net.h" |
|
28 | 29 |
#include "sysemu.h" |
29 | 30 |
|
30 | 31 |
//#define DEBUG_SYBORG_VIRTIO |
... | ... | |
66 | 67 |
uint32_t int_enable; |
67 | 68 |
uint32_t id; |
68 | 69 |
NICConf nic; |
70 |
uint32_t host_features; |
|
69 | 71 |
} SyborgVirtIOProxy; |
70 | 72 |
|
71 | 73 |
static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset) |
... | ... | |
86 | 88 |
ret = s->id; |
87 | 89 |
break; |
88 | 90 |
case SYBORG_VIRTIO_HOST_FEATURES: |
89 |
ret = vdev->get_features(vdev); |
|
90 |
ret |= vdev->binding->get_features(s); |
|
91 |
ret = s->host_features; |
|
91 | 92 |
break; |
92 | 93 |
case SYBORG_VIRTIO_GUEST_FEATURES: |
93 | 94 |
ret = vdev->guest_features; |
... | ... | |
244 | 245 |
|
245 | 246 |
static unsigned syborg_virtio_get_features(void *opaque) |
246 | 247 |
{ |
247 |
unsigned ret = 0; |
|
248 |
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY); |
|
249 |
return ret; |
|
248 |
SyborgVirtIOProxy *proxy = opaque; |
|
249 |
return proxy->host_features; |
|
250 | 250 |
} |
251 | 251 |
|
252 | 252 |
static VirtIOBindings syborg_virtio_bindings = { |
... | ... | |
272 | 272 |
qemu_register_reset(virtio_reset, vdev); |
273 | 273 |
|
274 | 274 |
virtio_bind_device(vdev, &syborg_virtio_bindings, proxy); |
275 |
proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY); |
|
276 |
proxy->host_features = vdev->get_features(vdev, proxy->host_features); |
|
275 | 277 |
return 0; |
276 | 278 |
} |
277 | 279 |
|
... | ... | |
292 | 294 |
.qdev.size = sizeof(SyborgVirtIOProxy), |
293 | 295 |
.qdev.props = (Property[]) { |
294 | 296 |
DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic), |
297 |
DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features), |
|
295 | 298 |
DEFINE_PROP_END_OF_LIST(), |
296 | 299 |
} |
297 | 300 |
}; |
b/hw/virtio-balloon.c | ||
---|---|---|
124 | 124 |
dev->actual = config.actual; |
125 | 125 |
} |
126 | 126 |
|
127 |
static uint32_t virtio_balloon_get_features(VirtIODevice *vdev) |
|
127 |
static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f)
|
|
128 | 128 |
{ |
129 |
return 0;
|
|
129 |
return f;
|
|
130 | 130 |
} |
131 | 131 |
|
132 | 132 |
static ram_addr_t virtio_balloon_to_target(void *opaque, ram_addr_t target) |
b/hw/virtio-blk.c | ||
---|---|---|
432 | 432 |
memcpy(config, &blkcfg, s->config_size); |
433 | 433 |
} |
434 | 434 |
|
435 |
static uint32_t virtio_blk_get_features(VirtIODevice *vdev) |
|
435 |
static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
|
|
436 | 436 |
{ |
437 | 437 |
VirtIOBlock *s = to_virtio_blk(vdev); |
438 |
uint32_t features = 0; |
|
439 | 438 |
|
440 | 439 |
features |= (1 << VIRTIO_BLK_F_SEG_MAX); |
441 | 440 |
features |= (1 << VIRTIO_BLK_F_GEOMETRY); |
442 | 441 |
|
443 | 442 |
if (bdrv_enable_write_cache(s->bs)) |
444 | 443 |
features |= (1 << VIRTIO_BLK_F_WCACHE); |
445 |
#ifdef __linux__ |
|
446 |
features |= (1 << VIRTIO_BLK_F_SCSI); |
|
447 |
#endif |
|
448 | 444 |
if (strcmp(s->serial_str, "0")) |
449 | 445 |
features |= 1 << VIRTIO_BLK_F_IDENTIFY; |
450 | 446 |
|
b/hw/virtio-blk.h | ||
---|---|---|
92 | 92 |
uint32_t residual; |
93 | 93 |
}; |
94 | 94 |
|
95 |
#ifdef __linux__ |
|
96 |
#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \ |
|
97 |
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \ |
|
98 |
DEFINE_PROP_BIT("scsi", _state, _field, VIRTIO_BLK_F_SCSI, true) |
|
99 |
#else |
|
100 |
#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \ |
|
101 |
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) |
|
102 |
#endif |
|
95 | 103 |
#endif |
b/hw/virtio-console.c | ||
---|---|---|
51 | 51 |
{ |
52 | 52 |
} |
53 | 53 |
|
54 |
static uint32_t virtio_console_get_features(VirtIODevice *vdev) |
|
54 |
static uint32_t virtio_console_get_features(VirtIODevice *vdev, uint32_t f)
|
|
55 | 55 |
{ |
56 |
return 0;
|
|
56 |
return f;
|
|
57 | 57 |
} |
58 | 58 |
|
59 | 59 |
static int vcon_can_read(void *opaque) |
b/hw/virtio-net.c | ||
---|---|---|
147 | 147 |
return n->has_ufo; |
148 | 148 |
} |
149 | 149 |
|
150 |
static uint32_t virtio_net_get_features(VirtIODevice *vdev) |
|
150 |
static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
|
|
151 | 151 |
{ |
152 | 152 |
VirtIONet *n = to_virtio_net(vdev); |
153 |
uint32_t features = (1 << VIRTIO_NET_F_MAC) | |
|
154 |
(1 << VIRTIO_NET_F_MRG_RXBUF) | |
|
155 |
(1 << VIRTIO_NET_F_STATUS) | |
|
156 |
(1 << VIRTIO_NET_F_CTRL_VQ) | |
|
157 |
(1 << VIRTIO_NET_F_CTRL_RX) | |
|
158 |
(1 << VIRTIO_NET_F_CTRL_VLAN) | |
|
159 |
(1 << VIRTIO_NET_F_CTRL_RX_EXTRA); |
|
160 | 153 |
|
161 | 154 |
if (peer_has_vnet_hdr(n)) { |
162 | 155 |
tap_using_vnet_hdr(n->nic->nc.peer, 1); |
156 |
} else { |
|
157 |
features &= ~(0x1 << VIRTIO_NET_F_CSUM); |
|
158 |
features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO4); |
|
159 |
features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO6); |
|
160 |
features &= ~(0x1 << VIRTIO_NET_F_HOST_ECN); |
|
161 |
|
|
162 |
features &= ~(0x1 << VIRTIO_NET_F_GUEST_CSUM); |
|
163 |
features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO4); |
|
164 |
features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO6); |
|
165 |
features &= ~(0x1 << VIRTIO_NET_F_GUEST_ECN); |
|
166 |
} |
|
163 | 167 |
|
164 |
features |= (1 << VIRTIO_NET_F_CSUM); |
|
165 |
features |= (1 << VIRTIO_NET_F_HOST_TSO4); |
|
166 |
features |= (1 << VIRTIO_NET_F_HOST_TSO6); |
|
167 |
features |= (1 << VIRTIO_NET_F_HOST_ECN); |
|
168 |
|
|
169 |
features |= (1 << VIRTIO_NET_F_GUEST_CSUM); |
|
170 |
features |= (1 << VIRTIO_NET_F_GUEST_TSO4); |
|
171 |
features |= (1 << VIRTIO_NET_F_GUEST_TSO6); |
|
172 |
features |= (1 << VIRTIO_NET_F_GUEST_ECN); |
|
173 |
|
|
174 |
if (peer_has_ufo(n)) { |
|
175 |
features |= (1 << VIRTIO_NET_F_GUEST_UFO); |
|
176 |
features |= (1 << VIRTIO_NET_F_HOST_UFO); |
|
177 |
} |
|
168 |
if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) { |
|
169 |
features &= ~(0x1 << VIRTIO_NET_F_GUEST_UFO); |
|
170 |
features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO); |
|
178 | 171 |
} |
179 | 172 |
|
180 | 173 |
return features; |
... | ... | |
192 | 185 |
features |= (1 << VIRTIO_NET_F_HOST_TSO6); |
193 | 186 |
features |= (1 << VIRTIO_NET_F_HOST_ECN); |
194 | 187 |
|
195 |
return features & virtio_net_get_features(vdev);
|
|
188 |
return features; |
|
196 | 189 |
} |
197 | 190 |
|
198 | 191 |
static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) |
b/hw/virtio-net.h | ||
---|---|---|
153 | 153 |
#define VIRTIO_NET_CTRL_VLAN_ADD 0 |
154 | 154 |
#define VIRTIO_NET_CTRL_VLAN_DEL 1 |
155 | 155 |
|
156 |
#define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \ |
|
157 |
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \ |
|
158 |
DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \ |
|
159 |
DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \ |
|
160 |
DEFINE_PROP_BIT("mac", _state, _field, VIRTIO_NET_F_MAC, true), \ |
|
161 |
DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \ |
|
162 |
DEFINE_PROP_BIT("guest_tso4", _state, _field, VIRTIO_NET_F_GUEST_TSO4, true), \ |
|
163 |
DEFINE_PROP_BIT("guest_tso6", _state, _field, VIRTIO_NET_F_GUEST_TSO6, true), \ |
|
164 |
DEFINE_PROP_BIT("guest_ecn", _state, _field, VIRTIO_NET_F_GUEST_ECN, true), \ |
|
165 |
DEFINE_PROP_BIT("guest_ufo", _state, _field, VIRTIO_NET_F_GUEST_UFO, true), \ |
|
166 |
DEFINE_PROP_BIT("host_tso4", _state, _field, VIRTIO_NET_F_HOST_TSO4, true), \ |
|
167 |
DEFINE_PROP_BIT("host_tso6", _state, _field, VIRTIO_NET_F_HOST_TSO6, true), \ |
|
168 |
DEFINE_PROP_BIT("host_ecn", _state, _field, VIRTIO_NET_F_HOST_ECN, true), \ |
|
169 |
DEFINE_PROP_BIT("host_ufo", _state, _field, VIRTIO_NET_F_HOST_UFO, true), \ |
|
170 |
DEFINE_PROP_BIT("mrg_rxbuf", _state, _field, VIRTIO_NET_F_MRG_RXBUF, true), \ |
|
171 |
DEFINE_PROP_BIT("status", _state, _field, VIRTIO_NET_F_STATUS, true), \ |
|
172 |
DEFINE_PROP_BIT("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \ |
|
173 |
DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \ |
|
174 |
DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \ |
|
175 |
DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true) |
|
156 | 176 |
#endif |
b/hw/virtio-pci.c | ||
---|---|---|
16 | 16 |
#include <inttypes.h> |
17 | 17 |
|
18 | 18 |
#include "virtio.h" |
19 |
#include "virtio-blk.h" |
|
20 |
#include "virtio-net.h" |
|
19 | 21 |
#include "pci.h" |
20 | 22 |
#include "sysemu.h" |
21 | 23 |
#include "msix.h" |
... | ... | |
92 | 94 |
uint32_t nvectors; |
93 | 95 |
DriveInfo *dinfo; |
94 | 96 |
NICConf nic; |
97 |
uint32_t host_features; |
|
95 | 98 |
} VirtIOPCIProxy; |
96 | 99 |
|
97 | 100 |
/* virtio device */ |
... | ... | |
175 | 178 |
/* Guest does not negotiate properly? We have to assume nothing. */ |
176 | 179 |
if (val & (1 << VIRTIO_F_BAD_FEATURE)) { |
177 | 180 |
if (vdev->bad_features) |
178 |
val = vdev->bad_features(vdev); |
|
181 |
val = proxy->host_features & vdev->bad_features(vdev);
|
|
179 | 182 |
else |
180 | 183 |
val = 0; |
181 | 184 |
} |
... | ... | |
235 | 238 |
|
236 | 239 |
switch (addr) { |
237 | 240 |
case VIRTIO_PCI_HOST_FEATURES: |
238 |
ret = vdev->get_features(vdev); |
|
239 |
ret |= vdev->binding->get_features(proxy); |
|
241 |
ret = proxy->host_features; |
|
240 | 242 |
break; |
241 | 243 |
case VIRTIO_PCI_GUEST_FEATURES: |
242 | 244 |
ret = vdev->guest_features; |
... | ... | |
382 | 384 |
|
383 | 385 |
static unsigned virtio_pci_get_features(void *opaque) |
384 | 386 |
{ |
385 |
unsigned ret = 0; |
|
386 |
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY); |
|
387 |
ret |= (1 << VIRTIO_RING_F_INDIRECT_DESC); |
|
388 |
ret |= (1 << VIRTIO_F_BAD_FEATURE); |
|
389 |
return ret; |
|
387 |
VirtIOPCIProxy *proxy = opaque; |
|
388 |
return proxy->host_features; |
|
390 | 389 |
} |
391 | 390 |
|
392 | 391 |
static const VirtIOBindings virtio_pci_bindings = { |
... | ... | |
442 | 441 |
virtio_map); |
443 | 442 |
|
444 | 443 |
virtio_bind_device(vdev, &virtio_pci_bindings, proxy); |
444 |
proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY; |
|
445 |
proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE; |
|
446 |
proxy->host_features = vdev->get_features(vdev, proxy->host_features); |
|
445 | 447 |
} |
446 | 448 |
|
447 | 449 |
static int virtio_blk_init_pci(PCIDevice *pci_dev) |
... | ... | |
553 | 555 |
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), |
554 | 556 |
DEFINE_PROP_DRIVE("drive", VirtIOPCIProxy, dinfo), |
555 | 557 |
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), |
558 |
DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features), |
|
556 | 559 |
DEFINE_PROP_END_OF_LIST(), |
557 | 560 |
}, |
558 | 561 |
.qdev.reset = virtio_pci_reset, |
... | ... | |
564 | 567 |
.romfile = "pxe-virtio.bin", |
565 | 568 |
.qdev.props = (Property[]) { |
566 | 569 |
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3), |
570 |
DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features), |
|
567 | 571 |
DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic), |
568 | 572 |
DEFINE_PROP_END_OF_LIST(), |
569 | 573 |
}, |
... | ... | |
575 | 579 |
.exit = virtio_exit_pci, |
576 | 580 |
.qdev.props = (Property[]) { |
577 | 581 |
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), |
582 |
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), |
|
578 | 583 |
DEFINE_PROP_END_OF_LIST(), |
579 | 584 |
}, |
580 | 585 |
.qdev.reset = virtio_pci_reset, |
... | ... | |
583 | 588 |
.qdev.size = sizeof(VirtIOPCIProxy), |
584 | 589 |
.init = virtio_balloon_init_pci, |
585 | 590 |
.exit = virtio_exit_pci, |
591 |
.qdev.props = (Property[]) { |
|
592 |
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features), |
|
593 |
DEFINE_PROP_END_OF_LIST(), |
|
594 |
}, |
|
586 | 595 |
.qdev.reset = virtio_pci_reset, |
587 | 596 |
},{ |
588 | 597 |
/* end of list */ |
b/hw/virtio.c | ||
---|---|---|
652 | 652 |
{ |
653 | 653 |
int num, i, ret; |
654 | 654 |
uint32_t features; |
655 |
uint32_t supported_features = vdev->get_features(vdev) |
|
|
655 |
uint32_t supported_features = |
|
656 | 656 |
vdev->binding->get_features(vdev->binding_opaque); |
657 | 657 |
|
658 | 658 |
if (vdev->binding->load_config) { |
b/hw/virtio.h | ||
---|---|---|
105 | 105 |
void *config; |
106 | 106 |
uint16_t config_vector; |
107 | 107 |
int nvectors; |
108 |
uint32_t (*get_features)(VirtIODevice *vdev); |
|
108 |
uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
|
|
109 | 109 |
uint32_t (*bad_features)(VirtIODevice *vdev); |
110 | 110 |
void (*set_features)(VirtIODevice *vdev, uint32_t val); |
111 | 111 |
void (*get_config)(VirtIODevice *vdev, uint8_t *config); |
... | ... | |
176 | 176 |
|
177 | 177 |
void virtio_net_exit(VirtIODevice *vdev); |
178 | 178 |
|
179 |
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \ |
|
180 |
DEFINE_PROP_BIT("indirect_desc", _state, _field, \ |
|
181 |
VIRTIO_RING_F_INDIRECT_DESC, true) |
|
182 |
|
|
183 |
|
|
179 | 184 |
#endif |
Also available in: Unified diff