提交 8172539d 编写于 作者: M Michael S. Tsirkin 提交者: Anthony Liguori

virtio: add features as qdev properties

Add feature bits as properties to virtio. This makes it possible to e.g. define
machine without indirect buffer support, which is required for 0.10
compatibility, or without hardware checksum support, which is required for 0.11
compatibility.  Since default values for optional features are now set by qdev,
get_features callback has been modified: it sets non-optional bits, and clears
bits not supported by host.
Signed-off-by: NMichael S. Tsirkin <mst@redhat.com>
Acked-by: NGerd Hoffmann <kraxel@redhat.com>
Signed-off-by: NAnthony Liguori <aliguori@us.ibm.com>
上级 704a76fc
...@@ -101,6 +101,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev) ...@@ -101,6 +101,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
bus->dev_offs += dev_len; bus->dev_offs += dev_len;
virtio_bind_device(vdev, &virtio_s390_bindings, dev); virtio_bind_device(vdev, &virtio_s390_bindings, dev);
dev->host_features = vdev->get_features(vdev, dev->host_features);
s390_virtio_device_sync(dev); s390_virtio_device_sync(dev);
return 0; return 0;
...@@ -222,9 +223,7 @@ static void s390_virtio_device_sync(VirtIOS390Device *dev) ...@@ -222,9 +223,7 @@ static void s390_virtio_device_sync(VirtIOS390Device *dev)
cur_offs += num_vq * VIRTIO_VQCONFIG_LEN; cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
/* Sync feature bitmap */ /* Sync feature bitmap */
if (dev->vdev->get_features) { stl_phys(cur_offs, dev->host_features);
stl_phys(cur_offs, dev->vdev->get_features(dev->vdev));
}
dev->feat_offs = cur_offs + dev->feat_len; dev->feat_offs = cur_offs + dev->feat_len;
cur_offs += dev->feat_len * 2; cur_offs += dev->feat_len * 2;
...@@ -310,10 +309,17 @@ static void virtio_s390_notify(void *opaque, uint16_t vector) ...@@ -310,10 +309,17 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
kvm_s390_virtio_irq(s390_cpu_addr2state(0), 0, token); kvm_s390_virtio_irq(s390_cpu_addr2state(0), 0, token);
} }
static unsigned virtio_s390_get_features(void *opaque)
{
VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
return dev->host_features;
}
/**************** S390 Virtio Bus Device Descriptions *******************/ /**************** S390 Virtio Bus Device Descriptions *******************/
static const VirtIOBindings virtio_s390_bindings = { static const VirtIOBindings virtio_s390_bindings = {
.notify = virtio_s390_notify, .notify = virtio_s390_notify,
.get_features = virtio_s390_get_features,
}; };
static VirtIOS390DeviceInfo s390_virtio_net = { static VirtIOS390DeviceInfo s390_virtio_net = {
......
...@@ -40,6 +40,7 @@ typedef struct VirtIOS390Device { ...@@ -40,6 +40,7 @@ typedef struct VirtIOS390Device {
VirtIODevice *vdev; VirtIODevice *vdev;
DriveInfo *dinfo; DriveInfo *dinfo;
NICConf nic; NICConf nic;
uint32_t host_features;
} VirtIOS390Device; } VirtIOS390Device;
typedef struct VirtIOS390Bus { typedef struct VirtIOS390Bus {
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "syborg.h" #include "syborg.h"
#include "sysbus.h" #include "sysbus.h"
#include "virtio.h" #include "virtio.h"
#include "virtio-net.h"
#include "sysemu.h" #include "sysemu.h"
//#define DEBUG_SYBORG_VIRTIO //#define DEBUG_SYBORG_VIRTIO
...@@ -66,6 +67,7 @@ typedef struct { ...@@ -66,6 +67,7 @@ typedef struct {
uint32_t int_enable; uint32_t int_enable;
uint32_t id; uint32_t id;
NICConf nic; NICConf nic;
uint32_t host_features;
} SyborgVirtIOProxy; } SyborgVirtIOProxy;
static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset) static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
...@@ -86,8 +88,7 @@ static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset) ...@@ -86,8 +88,7 @@ static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
ret = s->id; ret = s->id;
break; break;
case SYBORG_VIRTIO_HOST_FEATURES: case SYBORG_VIRTIO_HOST_FEATURES:
ret = vdev->get_features(vdev); ret = s->host_features;
ret |= vdev->binding->get_features(s);
break; break;
case SYBORG_VIRTIO_GUEST_FEATURES: case SYBORG_VIRTIO_GUEST_FEATURES:
ret = vdev->guest_features; ret = vdev->guest_features;
...@@ -244,9 +245,8 @@ static void syborg_virtio_update_irq(void *opaque, uint16_t vector) ...@@ -244,9 +245,8 @@ static void syborg_virtio_update_irq(void *opaque, uint16_t vector)
static unsigned syborg_virtio_get_features(void *opaque) static unsigned syborg_virtio_get_features(void *opaque)
{ {
unsigned ret = 0; SyborgVirtIOProxy *proxy = opaque;
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY); return proxy->host_features;
return ret;
} }
static VirtIOBindings syborg_virtio_bindings = { static VirtIOBindings syborg_virtio_bindings = {
...@@ -272,6 +272,8 @@ static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev) ...@@ -272,6 +272,8 @@ static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
qemu_register_reset(virtio_reset, vdev); qemu_register_reset(virtio_reset, vdev);
virtio_bind_device(vdev, &syborg_virtio_bindings, proxy); virtio_bind_device(vdev, &syborg_virtio_bindings, proxy);
proxy->host_features |= (0x1 << VIRTIO_F_NOTIFY_ON_EMPTY);
proxy->host_features = vdev->get_features(vdev, proxy->host_features);
return 0; return 0;
} }
...@@ -292,6 +294,7 @@ static SysBusDeviceInfo syborg_virtio_net_info = { ...@@ -292,6 +294,7 @@ static SysBusDeviceInfo syborg_virtio_net_info = {
.qdev.size = sizeof(SyborgVirtIOProxy), .qdev.size = sizeof(SyborgVirtIOProxy),
.qdev.props = (Property[]) { .qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic), DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic),
DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
} }
}; };
......
...@@ -124,9 +124,9 @@ static void virtio_balloon_set_config(VirtIODevice *vdev, ...@@ -124,9 +124,9 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
dev->actual = config.actual; dev->actual = config.actual;
} }
static uint32_t virtio_balloon_get_features(VirtIODevice *vdev) static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f)
{ {
return 0; return f;
} }
static ram_addr_t virtio_balloon_to_target(void *opaque, ram_addr_t target) static ram_addr_t virtio_balloon_to_target(void *opaque, ram_addr_t target)
......
...@@ -432,19 +432,15 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) ...@@ -432,19 +432,15 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
memcpy(config, &blkcfg, s->config_size); memcpy(config, &blkcfg, s->config_size);
} }
static uint32_t virtio_blk_get_features(VirtIODevice *vdev) static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
{ {
VirtIOBlock *s = to_virtio_blk(vdev); VirtIOBlock *s = to_virtio_blk(vdev);
uint32_t features = 0;
features |= (1 << VIRTIO_BLK_F_SEG_MAX); features |= (1 << VIRTIO_BLK_F_SEG_MAX);
features |= (1 << VIRTIO_BLK_F_GEOMETRY); features |= (1 << VIRTIO_BLK_F_GEOMETRY);
if (bdrv_enable_write_cache(s->bs)) if (bdrv_enable_write_cache(s->bs))
features |= (1 << VIRTIO_BLK_F_WCACHE); features |= (1 << VIRTIO_BLK_F_WCACHE);
#ifdef __linux__
features |= (1 << VIRTIO_BLK_F_SCSI);
#endif
if (strcmp(s->serial_str, "0")) if (strcmp(s->serial_str, "0"))
features |= 1 << VIRTIO_BLK_F_IDENTIFY; features |= 1 << VIRTIO_BLK_F_IDENTIFY;
......
...@@ -92,4 +92,12 @@ struct virtio_scsi_inhdr ...@@ -92,4 +92,12 @@ struct virtio_scsi_inhdr
uint32_t residual; uint32_t residual;
}; };
#ifdef __linux__
#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
DEFINE_PROP_BIT("scsi", _state, _field, VIRTIO_BLK_F_SCSI, true)
#else
#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field)
#endif
#endif #endif
...@@ -51,9 +51,9 @@ static void virtio_console_handle_input(VirtIODevice *vdev, VirtQueue *vq) ...@@ -51,9 +51,9 @@ static void virtio_console_handle_input(VirtIODevice *vdev, VirtQueue *vq)
{ {
} }
static uint32_t virtio_console_get_features(VirtIODevice *vdev) static uint32_t virtio_console_get_features(VirtIODevice *vdev, uint32_t f)
{ {
return 0; return f;
} }
static int vcon_can_read(void *opaque) static int vcon_can_read(void *opaque)
......
...@@ -147,34 +147,27 @@ static int peer_has_ufo(VirtIONet *n) ...@@ -147,34 +147,27 @@ static int peer_has_ufo(VirtIONet *n)
return n->has_ufo; return n->has_ufo;
} }
static uint32_t virtio_net_get_features(VirtIODevice *vdev) static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
{ {
VirtIONet *n = to_virtio_net(vdev); VirtIONet *n = to_virtio_net(vdev);
uint32_t features = (1 << VIRTIO_NET_F_MAC) |
(1 << VIRTIO_NET_F_MRG_RXBUF) |
(1 << VIRTIO_NET_F_STATUS) |
(1 << VIRTIO_NET_F_CTRL_VQ) |
(1 << VIRTIO_NET_F_CTRL_RX) |
(1 << VIRTIO_NET_F_CTRL_VLAN) |
(1 << VIRTIO_NET_F_CTRL_RX_EXTRA);
if (peer_has_vnet_hdr(n)) { if (peer_has_vnet_hdr(n)) {
tap_using_vnet_hdr(n->nic->nc.peer, 1); tap_using_vnet_hdr(n->nic->nc.peer, 1);
} else {
features &= ~(0x1 << VIRTIO_NET_F_CSUM);
features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO4);
features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO6);
features &= ~(0x1 << VIRTIO_NET_F_HOST_ECN);
features &= ~(0x1 << VIRTIO_NET_F_GUEST_CSUM);
features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO4);
features &= ~(0x1 << VIRTIO_NET_F_GUEST_TSO6);
features &= ~(0x1 << VIRTIO_NET_F_GUEST_ECN);
}
features |= (1 << VIRTIO_NET_F_CSUM); if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) {
features |= (1 << VIRTIO_NET_F_HOST_TSO4); features &= ~(0x1 << VIRTIO_NET_F_GUEST_UFO);
features |= (1 << VIRTIO_NET_F_HOST_TSO6); features &= ~(0x1 << VIRTIO_NET_F_HOST_UFO);
features |= (1 << VIRTIO_NET_F_HOST_ECN);
features |= (1 << VIRTIO_NET_F_GUEST_CSUM);
features |= (1 << VIRTIO_NET_F_GUEST_TSO4);
features |= (1 << VIRTIO_NET_F_GUEST_TSO6);
features |= (1 << VIRTIO_NET_F_GUEST_ECN);
if (peer_has_ufo(n)) {
features |= (1 << VIRTIO_NET_F_GUEST_UFO);
features |= (1 << VIRTIO_NET_F_HOST_UFO);
}
} }
return features; return features;
...@@ -192,7 +185,7 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev) ...@@ -192,7 +185,7 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
features |= (1 << VIRTIO_NET_F_HOST_TSO6); features |= (1 << VIRTIO_NET_F_HOST_TSO6);
features |= (1 << VIRTIO_NET_F_HOST_ECN); features |= (1 << VIRTIO_NET_F_HOST_ECN);
return features & virtio_net_get_features(vdev); return features;
} }
static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
......
...@@ -153,4 +153,24 @@ struct virtio_net_ctrl_mac { ...@@ -153,4 +153,24 @@ struct virtio_net_ctrl_mac {
#define VIRTIO_NET_CTRL_VLAN_ADD 0 #define VIRTIO_NET_CTRL_VLAN_ADD 0
#define VIRTIO_NET_CTRL_VLAN_DEL 1 #define VIRTIO_NET_CTRL_VLAN_DEL 1
#define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \
DEFINE_VIRTIO_COMMON_FEATURES(_state, _field), \
DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \
DEFINE_PROP_BIT("guest_csum", _state, _field, VIRTIO_NET_F_GUEST_CSUM, true), \
DEFINE_PROP_BIT("mac", _state, _field, VIRTIO_NET_F_MAC, true), \
DEFINE_PROP_BIT("gso", _state, _field, VIRTIO_NET_F_GSO, true), \
DEFINE_PROP_BIT("guest_tso4", _state, _field, VIRTIO_NET_F_GUEST_TSO4, true), \
DEFINE_PROP_BIT("guest_tso6", _state, _field, VIRTIO_NET_F_GUEST_TSO6, true), \
DEFINE_PROP_BIT("guest_ecn", _state, _field, VIRTIO_NET_F_GUEST_ECN, true), \
DEFINE_PROP_BIT("guest_ufo", _state, _field, VIRTIO_NET_F_GUEST_UFO, true), \
DEFINE_PROP_BIT("host_tso4", _state, _field, VIRTIO_NET_F_HOST_TSO4, true), \
DEFINE_PROP_BIT("host_tso6", _state, _field, VIRTIO_NET_F_HOST_TSO6, true), \
DEFINE_PROP_BIT("host_ecn", _state, _field, VIRTIO_NET_F_HOST_ECN, true), \
DEFINE_PROP_BIT("host_ufo", _state, _field, VIRTIO_NET_F_HOST_UFO, true), \
DEFINE_PROP_BIT("mrg_rxbuf", _state, _field, VIRTIO_NET_F_MRG_RXBUF, true), \
DEFINE_PROP_BIT("status", _state, _field, VIRTIO_NET_F_STATUS, true), \
DEFINE_PROP_BIT("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \
DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \
DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \
DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true)
#endif #endif
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include <inttypes.h> #include <inttypes.h>
#include "virtio.h" #include "virtio.h"
#include "virtio-blk.h"
#include "virtio-net.h"
#include "pci.h" #include "pci.h"
#include "sysemu.h" #include "sysemu.h"
#include "msix.h" #include "msix.h"
...@@ -92,6 +94,7 @@ typedef struct { ...@@ -92,6 +94,7 @@ typedef struct {
uint32_t nvectors; uint32_t nvectors;
DriveInfo *dinfo; DriveInfo *dinfo;
NICConf nic; NICConf nic;
uint32_t host_features;
} VirtIOPCIProxy; } VirtIOPCIProxy;
/* virtio device */ /* virtio device */
...@@ -175,7 +178,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) ...@@ -175,7 +178,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
/* Guest does not negotiate properly? We have to assume nothing. */ /* Guest does not negotiate properly? We have to assume nothing. */
if (val & (1 << VIRTIO_F_BAD_FEATURE)) { if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
if (vdev->bad_features) if (vdev->bad_features)
val = vdev->bad_features(vdev); val = proxy->host_features & vdev->bad_features(vdev);
else else
val = 0; val = 0;
} }
...@@ -235,8 +238,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr) ...@@ -235,8 +238,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
switch (addr) { switch (addr) {
case VIRTIO_PCI_HOST_FEATURES: case VIRTIO_PCI_HOST_FEATURES:
ret = vdev->get_features(vdev); ret = proxy->host_features;
ret |= vdev->binding->get_features(proxy);
break; break;
case VIRTIO_PCI_GUEST_FEATURES: case VIRTIO_PCI_GUEST_FEATURES:
ret = vdev->guest_features; ret = vdev->guest_features;
...@@ -382,11 +384,8 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, ...@@ -382,11 +384,8 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
static unsigned virtio_pci_get_features(void *opaque) static unsigned virtio_pci_get_features(void *opaque)
{ {
unsigned ret = 0; VirtIOPCIProxy *proxy = opaque;
ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY); return proxy->host_features;
ret |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
ret |= (1 << VIRTIO_F_BAD_FEATURE);
return ret;
} }
static const VirtIOBindings virtio_pci_bindings = { static const VirtIOBindings virtio_pci_bindings = {
...@@ -442,6 +441,9 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev, ...@@ -442,6 +441,9 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
virtio_map); virtio_map);
virtio_bind_device(vdev, &virtio_pci_bindings, proxy); virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
proxy->host_features = vdev->get_features(vdev, proxy->host_features);
} }
static int virtio_blk_init_pci(PCIDevice *pci_dev) static int virtio_blk_init_pci(PCIDevice *pci_dev)
...@@ -553,6 +555,7 @@ static PCIDeviceInfo virtio_info[] = { ...@@ -553,6 +555,7 @@ static PCIDeviceInfo virtio_info[] = {
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
DEFINE_PROP_DRIVE("drive", VirtIOPCIProxy, dinfo), DEFINE_PROP_DRIVE("drive", VirtIOPCIProxy, dinfo),
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}, },
.qdev.reset = virtio_pci_reset, .qdev.reset = virtio_pci_reset,
...@@ -564,6 +567,7 @@ static PCIDeviceInfo virtio_info[] = { ...@@ -564,6 +567,7 @@ static PCIDeviceInfo virtio_info[] = {
.romfile = "pxe-virtio.bin", .romfile = "pxe-virtio.bin",
.qdev.props = (Property[]) { .qdev.props = (Property[]) {
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3), DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic), DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}, },
...@@ -575,6 +579,7 @@ static PCIDeviceInfo virtio_info[] = { ...@@ -575,6 +579,7 @@ static PCIDeviceInfo virtio_info[] = {
.exit = virtio_exit_pci, .exit = virtio_exit_pci,
.qdev.props = (Property[]) { .qdev.props = (Property[]) {
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0), DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_END_OF_LIST(), DEFINE_PROP_END_OF_LIST(),
}, },
.qdev.reset = virtio_pci_reset, .qdev.reset = virtio_pci_reset,
...@@ -583,6 +588,10 @@ static PCIDeviceInfo virtio_info[] = { ...@@ -583,6 +588,10 @@ static PCIDeviceInfo virtio_info[] = {
.qdev.size = sizeof(VirtIOPCIProxy), .qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_balloon_init_pci, .init = virtio_balloon_init_pci,
.exit = virtio_exit_pci, .exit = virtio_exit_pci,
.qdev.props = (Property[]) {
DEFINE_VIRTIO_COMMON_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_END_OF_LIST(),
},
.qdev.reset = virtio_pci_reset, .qdev.reset = virtio_pci_reset,
},{ },{
/* end of list */ /* end of list */
......
...@@ -652,7 +652,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f) ...@@ -652,7 +652,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
{ {
int num, i, ret; int num, i, ret;
uint32_t features; uint32_t features;
uint32_t supported_features = vdev->get_features(vdev) | uint32_t supported_features =
vdev->binding->get_features(vdev->binding_opaque); vdev->binding->get_features(vdev->binding_opaque);
if (vdev->binding->load_config) { if (vdev->binding->load_config) {
......
...@@ -105,7 +105,7 @@ struct VirtIODevice ...@@ -105,7 +105,7 @@ struct VirtIODevice
void *config; void *config;
uint16_t config_vector; uint16_t config_vector;
int nvectors; int nvectors;
uint32_t (*get_features)(VirtIODevice *vdev); uint32_t (*get_features)(VirtIODevice *vdev, uint32_t requested_features);
uint32_t (*bad_features)(VirtIODevice *vdev); uint32_t (*bad_features)(VirtIODevice *vdev);
void (*set_features)(VirtIODevice *vdev, uint32_t val); void (*set_features)(VirtIODevice *vdev, uint32_t val);
void (*get_config)(VirtIODevice *vdev, uint8_t *config); void (*get_config)(VirtIODevice *vdev, uint8_t *config);
...@@ -176,4 +176,9 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev); ...@@ -176,4 +176,9 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev);
void virtio_net_exit(VirtIODevice *vdev); void virtio_net_exit(VirtIODevice *vdev);
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
DEFINE_PROP_BIT("indirect_desc", _state, _field, \
VIRTIO_RING_F_INDIRECT_DESC, true)
#endif #endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册