@@ -20,6 +20,12 @@
#include "virtio-9p-xattr.h"
#include "virtio-9p-coth.h"
+static VirtIOFeature feature_sizes[] = {
+ {.flags = 0xffffffff, /* dummy table -- all features included. */
+ .end = endof(struct virtio_9p_config, tag) + MAX_TAG_LEN},
+ {}
+};
+
static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
{
features |= 1 << VIRTIO_9P_MOUNT_TAG;
@@ -54,11 +60,10 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
FsDriverEntry *fse;
V9fsPath path;
- s = (V9fsState *)virtio_common_init("virtio-9p",
- VIRTIO_ID_9P,
- sizeof(struct virtio_9p_config)+
- MAX_TAG_LEN,
- sizeof(V9fsState));
+ s = (V9fsState *)virtio_common_init("virtio-9p", VIRTIO_ID_9P,
+ host_features, feature_sizes,
+ sizeof(struct virtio_9p_config) +
+ MAX_TAG_LEN, sizeof(V9fsState));
/* initialize pdu allocator */
QLIST_INIT(&s->free_list);
QLIST_INIT(&s->active_list);
@@ -29,6 +29,12 @@
#include <sys/mman.h>
#endif
+static VirtIOFeature feature_sizes[] = {
+ {.flags = 0xffffffff, /* dummy table -- all features included. */
+ .end = sizeof(struct virtio_balloon_config)},
+ {}
+};
+
typedef struct VirtIOBalloon
{
VirtIODevice vdev;
@@ -278,7 +284,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
config.num_pages = cpu_to_le32(dev->num_pages);
config.actual = cpu_to_le32(dev->actual);
- memcpy(config_data, &config, 8);
+ memcpy(config_data, &config, vdev->config_len);
}
static void virtio_balloon_set_config(VirtIODevice *vdev,
@@ -287,7 +293,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev,
VirtIOBalloon *dev = to_virtio_balloon(vdev);
struct virtio_balloon_config config;
uint32_t oldactual = dev->actual;
- memcpy(&config, config_data, 8);
+ memcpy(&config, config_data, vdev->config_len);
dev->actual = le32_to_cpu(config.actual);
if (dev->actual != oldactual) {
qemu_balloon_changed(ram_size -
@@ -356,7 +362,10 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev, uint32_t host_features)
s = (VirtIOBalloon *)virtio_common_init("virtio-balloon",
VIRTIO_ID_BALLOON,
- 8, sizeof(VirtIOBalloon));
+ host_features, feature_sizes,
+ endof(struct virtio_balloon_config,
+ actual),
+ sizeof(VirtIOBalloon));
s->vdev.get_config = virtio_balloon_get_config;
s->vdev.set_config = virtio_balloon_set_config;
@@ -25,6 +25,12 @@
# include <scsi/sg.h>
#endif
+static VirtIOFeature feature_sizes[] = {
+ {.flags = 0xffffffff, /* dummy table -- all features included */
+ .end = sizeof(struct virtio_blk_config)},
+ {}
+};
+
typedef struct VirtIOBlock
{
VirtIODevice vdev;
@@ -531,7 +537,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
blkcfg.alignment_offset = 0;
blkcfg.wce = bdrv_enable_write_cache(s->bs);
- memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
+ memcpy(config, &blkcfg, vdev->config_len);
}
static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
@@ -539,7 +545,7 @@ static void virtio_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
VirtIOBlock *s = to_virtio_blk(vdev);
struct virtio_blk_config blkcfg;
- memcpy(&blkcfg, config, sizeof(blkcfg));
+ memcpy(&blkcfg, config, vdev->config_len);
bdrv_set_enable_write_cache(s->bs, blkcfg.wce != 0);
}
@@ -660,7 +666,9 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, VirtIOBlkConf *blk,
}
s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
- sizeof(struct virtio_blk_config),
+ host_features, feature_sizes,
+ endof(struct virtio_blk_config,
+ blk_size),
sizeof(VirtIOBlock));
s->vdev.get_config = virtio_blk_update_config;
@@ -1292,16 +1292,11 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
virtio_net_conf *net, uint32_t host_features)
{
VirtIONet *n;
- int i, config_size = 0;
-
- for (i = 0; feature_sizes[i].flags != 0; i++) {
- if (host_features & feature_sizes[i].flags) {
- config_size = MAX(feature_sizes[i].end, config_size);
- }
- }
+ int i;
n = (VirtIONet *)virtio_common_init("virtio-net", VIRTIO_ID_NET,
- config_size, sizeof(VirtIONet));
+ host_features, feature_sizes, 0,
+ sizeof(VirtIONet));
n->vdev.get_config = virtio_net_get_config;
n->vdev.set_config = virtio_net_set_config;
@@ -15,6 +15,12 @@
#include "virtio-rng.h"
#include "qemu/rng.h"
+static VirtIOFeature feature_sizes[] = {
+ {.flags = 0xffffffff, /* dummy table -- all features included. */
+ .end = endof(struct VirtIORNGConf, default_backend)},
+ {}
+};
+
typedef struct VirtIORNG {
VirtIODevice vdev;
@@ -155,7 +161,7 @@ VirtIODevice *virtio_rng_init(DeviceState *dev, VirtIORNGConf *conf)
VirtIODevice *vdev;
Error *local_err = NULL;
- vdev = virtio_common_init("virtio-rng", VIRTIO_ID_RNG, 0,
+ vdev = virtio_common_init("virtio-rng", VIRTIO_ID_RNG, 0, feature_sizes, 0,
sizeof(VirtIORNG));
vrng = DO_UPCAST(VirtIORNG, vdev, vdev);
@@ -17,6 +17,12 @@
#include <hw/scsi.h>
#include <hw/scsi-defs.h>
+static VirtIOFeature feature_sizes[] = {
+ {.flags = 0xffffffff,
+ .end = sizeof(struct VirtIOSCSIConf)},
+ {}
+};
+
#define VIRTIO_SCSI_VQ_SIZE 128
#define VIRTIO_SCSI_CDB_SIZE 32
#define VIRTIO_SCSI_SENSE_SIZE 96
@@ -710,7 +716,9 @@ VirtIODevice *virtio_scsi_init(DeviceState *dev, VirtIOSCSIConf *proxyconf,
sz = sizeof(VirtIOSCSI) + proxyconf->num_queues * sizeof(VirtQueue *);
s = (VirtIOSCSI *)virtio_common_init("virtio-scsi", VIRTIO_ID_SCSI,
- sizeof(VirtIOSCSIConfig), sz);
+ host_features, feature_sizes,
+ endof(struct VirtIOSCSIConf,
+ cmd_per_lun), sz);
s->qdev = dev;
s->conf = proxyconf;
@@ -25,6 +25,12 @@
#include "trace.h"
#include "virtio-serial.h"
+static VirtIOFeature feature_sizes[] = {
+ {.flags = 0xffffffff, /* dummy table -- all features included. */
+ .end = sizeof(struct virtio_console_config)},
+ {}
+};
+
/* The virtio-serial bus on top of which the ports will ride as devices */
struct VirtIOSerialBus {
BusState qbus;
@@ -523,14 +529,14 @@ static void get_config(VirtIODevice *vdev, uint8_t *config_data)
VirtIOSerial *vser;
vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
- memcpy(config_data, &vser->config, sizeof(struct virtio_console_config));
+ memcpy(config_data, &vser->config, vdev->config_len);
}
static void set_config(VirtIODevice *vdev, const uint8_t *config_data)
{
struct virtio_console_config config;
- memcpy(&config, config_data, sizeof(config));
+ memcpy(&config, config_data, vdev->config_len);
}
static void guest_reset(VirtIOSerial *vser)
@@ -964,7 +970,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf,
}
vdev = virtio_common_init("virtio-serial", VIRTIO_ID_CONSOLE,
- sizeof(struct virtio_console_config),
+ host_features, feature_sizes,
+ endof(struct virtio_console_config, rows),
sizeof(VirtIOSerial));
vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
@@ -948,10 +948,21 @@ void virtio_init(VirtIODevice *vdev, const char *name,
}
VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
- size_t config_size, size_t struct_size)
+ uint32_t host_features,
+ const VirtIOFeature *feature_table,
+ size_t min_config_size, size_t struct_size)
{
+ int i, config_size = min_config_size;
VirtIODevice *vdev;
+
vdev = g_malloc0(struct_size);
+
+ for (i = 0; feature_table && feature_table[i].flags != 0; i++) {
+ if (host_features & feature_table[i].flags) {
+ config_size = MAX(feature_table[i].end, config_size);
+ }
+ }
+
virtio_init(vdev, name, device_id, config_size);
return vdev;
}
@@ -229,7 +229,9 @@ int virtio_queue_empty(VirtQueue *vq);
/* Host binding interface. */
VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
- size_t config_size, size_t struct_size);
+ uint32_t host_features,
+ const VirtIOFeature *feature_table,
+ size_t min_config_size, size_t struct_size);
uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr);
uint32_t virtio_config_readw(VirtIODevice *vdev, uint32_t addr);
uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr);
Move the config size calculation from virtio_net_init() to virtio_common_init() so that all virtio devices can benefit. This requires that the host_features be passed to virtio_common_init(), and the size of the config struct will be calculated based on which feature bits are enabled. This calculation is performed using a per-driver table that maps each feature bit to the size of the config struct at the time that the feature was introduced. virtio_common_init() also takes a minimum config size to use in the case that all feature bits are disabled. For now, each driver contains a dummy table that uses the full size of the config struct. These dummy tables will be replaced on a per-driver basis. Signed-off-by: Jesse Larrew <jlarrew@linux.vnet.ibm.com> --- hw/9pfs/virtio-9p-device.c | 15 ++++++++++----- hw/virtio-balloon.c | 15 ++++++++++++--- hw/virtio-blk.c | 14 +++++++++++--- hw/virtio-net.c | 11 +++-------- hw/virtio-rng.c | 8 +++++++- hw/virtio-scsi.c | 10 +++++++++- hw/virtio-serial-bus.c | 13 ++++++++++--- hw/virtio.c | 13 ++++++++++++- hw/virtio.h | 4 +++- 9 files changed, 77 insertions(+), 26 deletions(-)