From 24bfa207efb9b9d591552eefc1f414ff33ef0eac Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 4 Jun 2015 23:05:58 -0400 Subject: vhost: put log correctly in vhost_dev_start() We allocate an dummy log even if the size is zero. So we should put it unconditionally too. Signed-off-by: Jason Wang Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 01f1e0490f..3a52a4d037 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1111,9 +1111,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) return 0; fail_log: - if (hdev->log_size) { - vhost_log_put(hdev, false); - } + vhost_log_put(hdev, false); fail_vq: while (--i >= 0) { vhost_virtqueue_stop(hdev, -- cgit v1.2.3 From 3c185597c86b8cd0a07c46e7a5bd5aac28bb7200 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 4 Jun 2015 12:34:11 +0200 Subject: virtio: endianness checks for virtio 1.0 devices Add code that checks for the VERSION_1 feature bit in order to make decisions about the device's endianness. This allows us to support transitional devices. Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 6 +++++- include/hw/virtio/virtio-access.h | 4 ++++ include/hw/virtio/virtio.h | 8 ++++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 8ac6156861..d37d27b4ea 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -903,7 +903,11 @@ static bool virtio_device_endian_needed(void *opaque) VirtIODevice *vdev = opaque; assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); - return vdev->device_endian != virtio_default_endian(); + if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + return vdev->device_endian != virtio_default_endian(); + } + /* Devices conforming to VIRTIO 1.0 or later are always LE. */ + return vdev->device_endian != VIRTIO_DEVICE_ENDIAN_LITTLE; } static bool virtio_64bit_features_needed(void *opaque) diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h index 46456fd9da..ee28c21fef 100644 --- a/include/hw/virtio/virtio-access.h +++ b/include/hw/virtio/virtio-access.h @@ -19,6 +19,10 @@ static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) { + if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + /* Devices conforming to VIRTIO 1.0 or later are always LE. */ + return false; + } #if defined(TARGET_IS_BIENDIAN) return virtio_is_big_endian(vdev); #elif defined(TARGET_WORDS_BIGENDIAN) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 2bb7c1ad1a..13e8549dcf 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -252,7 +252,11 @@ static inline bool virtio_has_feature(VirtIODevice *vdev, unsigned int fbit) static inline bool virtio_is_big_endian(VirtIODevice *vdev) { - assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); - return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG; + if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + assert(vdev->device_endian != VIRTIO_DEVICE_ENDIAN_UNKNOWN); + return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG; + } + /* Devices conforming to VIRTIO 1.0 or later are always LE. */ + return false; } #endif -- cgit v1.2.3 From ab223c9518e8c7eb542ef3133de1a34475b69790 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 4 Jun 2015 12:34:12 +0200 Subject: virtio: allow virtio-1 queue layout For virtio-1 devices, we allow a more complex queue layout that doesn't require descriptor table and rings on a physically-contigous memory area: add virtio_queue_set_rings() to allow transports to set this up. Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio-mmio.c | 3 +++ hw/virtio/virtio.c | 53 +++++++++++++++++++++++++++++----------------- include/hw/virtio/virtio.h | 3 +++ 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index c8f72947d4..18660b07b1 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -333,8 +333,11 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value, case VIRTIO_MMIO_QUEUENUM: DPRINTF("mmio_queue write %d max %d\n", (int)value, VIRTQUEUE_MAX_SIZE); virtio_queue_set_num(vdev, vdev->queue_sel, value); + /* Note: only call this function for legacy devices */ + virtio_queue_update_rings(vdev, vdev->queue_sel); break; case VIRTIO_MMIO_QUEUEALIGN: + /* Note: this is only valid for legacy devices */ virtio_queue_set_align(vdev, vdev->queue_sel, value); break; case VIRTIO_MMIO_QUEUEPFN: diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index d37d27b4ea..c27e975853 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -69,7 +69,6 @@ typedef struct VRing struct VirtQueue { VRing vring; - hwaddr pa; uint16_t last_avail_idx; /* Last used index value we have signalled on */ uint16_t signalled_used; @@ -93,15 +92,18 @@ struct VirtQueue }; /* virt queue functions */ -static void virtqueue_init(VirtQueue *vq) +void virtio_queue_update_rings(VirtIODevice *vdev, int n) { - hwaddr pa = vq->pa; + VRing *vring = &vdev->vq[n].vring; - vq->vring.desc = pa; - vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc); - vq->vring.used = vring_align(vq->vring.avail + - offsetof(VRingAvail, ring[vq->vring.num]), - vq->vring.align); + if (!vring->desc) { + /* not yet setup -> nothing to do */ + return; + } + vring->avail = vring->desc + vring->num * sizeof(VRingDesc); + vring->used = vring_align(vring->avail + + offsetof(VRingAvail, ring[vring->num]), + vring->align); } static inline uint64_t vring_desc_addr(VirtIODevice *vdev, hwaddr desc_pa, @@ -605,7 +607,6 @@ void virtio_reset(void *opaque) vdev->vq[i].vring.avail = 0; vdev->vq[i].vring.used = 0; vdev->vq[i].last_avail_idx = 0; - vdev->vq[i].pa = 0; virtio_queue_set_vector(vdev, i, VIRTIO_NO_VECTOR); vdev->vq[i].signalled_used = 0; vdev->vq[i].signalled_used_valid = false; @@ -708,13 +709,21 @@ void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data) void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr) { - vdev->vq[n].pa = addr; - virtqueue_init(&vdev->vq[n]); + vdev->vq[n].vring.desc = addr; + virtio_queue_update_rings(vdev, n); } hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n) { - return vdev->vq[n].pa; + return vdev->vq[n].vring.desc; +} + +void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc, + hwaddr avail, hwaddr used) +{ + vdev->vq[n].vring.desc = desc; + vdev->vq[n].vring.avail = avail; + vdev->vq[n].vring.used = used; } void virtio_queue_set_num(VirtIODevice *vdev, int n, int num) @@ -728,7 +737,6 @@ void virtio_queue_set_num(VirtIODevice *vdev, int n, int num) return; } vdev->vq[n].vring.num = num; - virtqueue_init(&vdev->vq[n]); } VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector) @@ -771,6 +779,11 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align) BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + /* virtio-1 compliant devices cannot change the alignment */ + if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + error_report("tried to modify queue alignment for virtio-1 device"); + return; + } /* Check that the transport told us it was going to do this * (so a buggy transport will immediately assert rather than * silently failing to migrate this state) @@ -778,7 +791,7 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align) assert(k->has_variable_vring_alignment); vdev->vq[n].vring.align = align; - virtqueue_init(&vdev->vq[n]); + virtio_queue_update_rings(vdev, n); } void virtio_queue_notify_vq(VirtQueue *vq) @@ -992,7 +1005,8 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) if (k->has_variable_vring_alignment) { qemu_put_be32(f, vdev->vq[i].vring.align); } - qemu_put_be64(f, vdev->vq[i].pa); + /* XXX virtio-1 devices */ + qemu_put_be64(f, vdev->vq[i].vring.desc); qemu_put_be16s(f, &vdev->vq[i].last_avail_idx); if (k->save_queue) { k->save_queue(qbus->parent, i, f); @@ -1076,13 +1090,14 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) if (k->has_variable_vring_alignment) { vdev->vq[i].vring.align = qemu_get_be32(f); } - vdev->vq[i].pa = qemu_get_be64(f); + vdev->vq[i].vring.desc = qemu_get_be64(f); qemu_get_be16s(f, &vdev->vq[i].last_avail_idx); vdev->vq[i].signalled_used_valid = false; vdev->vq[i].notification = true; - if (vdev->vq[i].pa) { - virtqueue_init(&vdev->vq[i]); + if (vdev->vq[i].vring.desc) { + /* XXX virtio-1 devices */ + virtio_queue_update_rings(vdev, i); } else if (vdev->vq[i].last_avail_idx) { error_report("VQ %d address 0x0 " "inconsistent with Host index 0x%x", @@ -1138,7 +1153,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) } for (i = 0; i < num; i++) { - if (vdev->vq[i].pa) { + if (vdev->vq[i].vring.desc) { uint16_t nheads; nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx; /* Check it isn't doing strange things with descriptor numbers. */ diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 13e8549dcf..b877a93be5 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -177,6 +177,9 @@ hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n); void virtio_queue_set_num(VirtIODevice *vdev, int n, int num); int virtio_queue_get_num(VirtIODevice *vdev, int n); int virtio_get_num_queues(VirtIODevice *vdev); +void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc, + hwaddr avail, hwaddr used); +void virtio_queue_update_rings(VirtIODevice *vdev, int n); void virtio_queue_set_align(VirtIODevice *vdev, int n, int align); void virtio_queue_notify(VirtIODevice *vdev, int n); uint16_t virtio_queue_vector(VirtIODevice *vdev, int n); -- cgit v1.2.3 From f5a5628cf0b65b223fa0c9031714578dfac4cf04 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 4 Jun 2015 12:34:13 +0200 Subject: dataplane: allow virtio-1 devices Handle endianness conversion for virtio-1 virtqueues correctly. Note that dataplane now needs to be built per-target. Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/dataplane/vring.c | 47 +++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c index 5c7b8c20fa..fabb8103e9 100644 --- a/hw/virtio/dataplane/vring.c +++ b/hw/virtio/dataplane/vring.c @@ -157,15 +157,18 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring) } -static int get_desc(Vring *vring, VirtQueueElement *elem, +static int get_desc(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem, struct vring_desc *desc) { unsigned *num; struct iovec *iov; hwaddr *addr; MemoryRegion *mr; + int is_write = virtio_tswap16(vdev, desc->flags) & VRING_DESC_F_WRITE; + uint32_t len = virtio_tswap32(vdev, desc->len); + uint64_t desc_addr = virtio_tswap64(vdev, desc->addr); - if (desc->flags & VRING_DESC_F_WRITE) { + if (is_write) { num = &elem->in_num; iov = &elem->in_sg[*num]; addr = &elem->in_addr[*num]; @@ -189,18 +192,17 @@ static int get_desc(Vring *vring, VirtQueueElement *elem, } /* TODO handle non-contiguous memory across region boundaries */ - iov->iov_base = vring_map(&mr, desc->addr, desc->len, - desc->flags & VRING_DESC_F_WRITE); + iov->iov_base = vring_map(&mr, desc_addr, len, is_write); if (!iov->iov_base) { error_report("Failed to map descriptor addr %#" PRIx64 " len %u", - (uint64_t)desc->addr, desc->len); + (uint64_t)desc_addr, len); return -EFAULT; } /* The MemoryRegion is looked up again and unref'ed later, leave the * ref in place. */ - iov->iov_len = desc->len; - *addr = desc->addr; + iov->iov_len = len; + *addr = desc_addr; *num += 1; return 0; } @@ -222,21 +224,23 @@ static int get_indirect(VirtIODevice *vdev, Vring *vring, struct vring_desc desc; unsigned int i = 0, count, found = 0; int ret; + uint32_t len = virtio_tswap32(vdev, indirect->len); + uint64_t addr = virtio_tswap64(vdev, indirect->addr); /* Sanity check */ - if (unlikely(indirect->len % sizeof(desc))) { + if (unlikely(len % sizeof(desc))) { error_report("Invalid length in indirect descriptor: " "len %#x not multiple of %#zx", - indirect->len, sizeof(desc)); + len, sizeof(desc)); vring->broken = true; return -EFAULT; } - count = indirect->len / sizeof(desc); + count = len / sizeof(desc); /* Buffers are chained via a 16 bit next field, so * we can have at most 2^16 of these. */ if (unlikely(count > USHRT_MAX + 1)) { - error_report("Indirect buffer length too big: %d", indirect->len); + error_report("Indirect buffer length too big: %d", len); vring->broken = true; return -EFAULT; } @@ -247,12 +251,12 @@ static int get_indirect(VirtIODevice *vdev, Vring *vring, /* Translate indirect descriptor */ desc_ptr = vring_map(&mr, - indirect->addr + found * sizeof(desc), + addr + found * sizeof(desc), sizeof(desc), false); if (!desc_ptr) { error_report("Failed to map indirect descriptor " "addr %#" PRIx64 " len %zu", - (uint64_t)indirect->addr + found * sizeof(desc), + (uint64_t)addr + found * sizeof(desc), sizeof(desc)); vring->broken = true; return -EFAULT; @@ -270,19 +274,20 @@ static int get_indirect(VirtIODevice *vdev, Vring *vring, return -EFAULT; } - if (unlikely(desc.flags & VRING_DESC_F_INDIRECT)) { + if (unlikely(virtio_tswap16(vdev, desc.flags) + & VRING_DESC_F_INDIRECT)) { error_report("Nested indirect descriptor"); vring->broken = true; return -EFAULT; } - ret = get_desc(vring, elem, &desc); + ret = get_desc(vdev, vring, elem, &desc); if (ret < 0) { vring->broken |= (ret == -EFAULT); return ret; } - i = desc.next; - } while (desc.flags & VRING_DESC_F_NEXT); + i = virtio_tswap16(vdev, desc.next); + } while (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_NEXT); return 0; } @@ -383,7 +388,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, /* Ensure descriptor is loaded before accessing fields */ barrier(); - if (desc.flags & VRING_DESC_F_INDIRECT) { + if (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_INDIRECT) { ret = get_indirect(vdev, vring, elem, &desc); if (ret < 0) { goto out; @@ -391,13 +396,13 @@ int vring_pop(VirtIODevice *vdev, Vring *vring, continue; } - ret = get_desc(vring, elem, &desc); + ret = get_desc(vdev, vring, elem, &desc); if (ret < 0) { goto out; } - i = desc.next; - } while (desc.flags & VRING_DESC_F_NEXT); + i = virtio_tswap16(vdev, desc.next); + } while (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_NEXT); /* On success, increment avail index. */ vring->last_avail_idx++; -- cgit v1.2.3 From 6c0196d702e8482a17638ee79f45ce27cdd1ef5d Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 4 Jun 2015 12:34:14 +0200 Subject: virtio: disallow late feature changes for virtio-1 For virtio-1 devices, the driver must not attempt to set feature bits after it set FEATURES_OK in the device status. Simply reject it in that case. Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index c27e975853..336710009f 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1021,7 +1021,7 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f) vmstate_save_state(f, &vmstate_virtio, vdev, NULL); } -int virtio_set_features(VirtIODevice *vdev, uint64_t val) +static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val) { VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); bool bad = (val & ~(vdev->host_features)) != 0; @@ -1034,6 +1034,18 @@ int virtio_set_features(VirtIODevice *vdev, uint64_t val) return bad ? -1 : 0; } +int virtio_set_features(VirtIODevice *vdev, uint64_t val) +{ + /* + * The driver must not attempt to set features after feature negotiation + * has finished. + */ + if (vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) { + return -EINVAL; + } + return virtio_set_features_nocheck(vdev, val); +} + int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) { int i, ret; @@ -1137,14 +1149,14 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) * host_features. */ uint64_t features64 = vdev->guest_features; - if (virtio_set_features(vdev, features64) < 0) { + if (virtio_set_features_nocheck(vdev, features64) < 0) { error_report("Features 0x%" PRIx64 " unsupported. " "Allowed features: 0x%" PRIx64, features64, vdev->host_features); return -1; } } else { - if (virtio_set_features(vdev, features) < 0) { + if (virtio_set_features_nocheck(vdev, features) < 0) { error_report("Features 0x%x unsupported. " "Allowed features: 0x%" PRIx64, features, vdev->host_features); -- cgit v1.2.3 From 0b352fd680e1ca7827ddea47b5e9b603320913b6 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 4 Jun 2015 12:34:15 +0200 Subject: virtio: allow to fail setting status virtio-1 allow setting of the FEATURES_OK status bit to fail if the negotiated feature bits are inconsistent: let's fail virtio_set_status() in that case and update virtio-ccw to post an error to the guest. Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/s390x/virtio-ccw.c | 20 ++++++++++++-------- hw/virtio/virtio.c | 24 +++++++++++++++++++++++- include/hw/virtio/virtio.h | 3 ++- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index ef90feddea..3ef0055126 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -497,15 +497,19 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) { virtio_ccw_stop_ioeventfd(dev); } - virtio_set_status(vdev, status); - if (vdev->status == 0) { - virtio_reset(vdev); - } - if (status & VIRTIO_CONFIG_S_DRIVER_OK) { - virtio_ccw_start_ioeventfd(dev); + if (virtio_set_status(vdev, status) == 0) { + if (vdev->status == 0) { + virtio_reset(vdev); + } + if (status & VIRTIO_CONFIG_S_DRIVER_OK) { + virtio_ccw_start_ioeventfd(dev); + } + sch->curr_status.scsw.count = ccw.count - sizeof(status); + ret = 0; + } else { + /* Trigger a command reject. */ + ret = -ENOSYS; } - sch->curr_status.scsw.count = ccw.count - sizeof(status); - ret = 0; } break; case CCW_CMD_SET_IND: diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 336710009f..8a6ebae368 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -544,15 +544,37 @@ void virtio_update_irq(VirtIODevice *vdev) virtio_notify_vector(vdev, VIRTIO_NO_VECTOR); } -void virtio_set_status(VirtIODevice *vdev, uint8_t val) +static int virtio_validate_features(VirtIODevice *vdev) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + + if (k->validate_features) { + return k->validate_features(vdev); + } else { + return 0; + } +} + +int virtio_set_status(VirtIODevice *vdev, uint8_t val) { VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); trace_virtio_set_status(vdev, val); + if (virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { + if (!(vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) && + val & VIRTIO_CONFIG_S_FEATURES_OK) { + int ret = virtio_validate_features(vdev); + + if (ret) { + return ret; + } + } + } if (k->set_status) { k->set_status(vdev, val); } vdev->status = val; + return 0; } bool target_words_bigendian(void); diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index b877a93be5..df8991357f 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -99,6 +99,7 @@ typedef struct VirtioDeviceClass { uint64_t (*get_features)(VirtIODevice *vdev, uint64_t requested_features); uint64_t (*bad_features)(VirtIODevice *vdev); void (*set_features)(VirtIODevice *vdev, uint64_t val); + int (*validate_features)(VirtIODevice *vdev); void (*get_config)(VirtIODevice *vdev, uint8_t *config); void (*set_config)(VirtIODevice *vdev, const uint8_t *config); void (*reset)(VirtIODevice *vdev); @@ -184,7 +185,7 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align); void virtio_queue_notify(VirtIODevice *vdev, int n); uint16_t virtio_queue_vector(VirtIODevice *vdev, int n); void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector); -void virtio_set_status(VirtIODevice *vdev, uint8_t val); +int virtio_set_status(VirtIODevice *vdev, uint8_t val); void virtio_reset(void *opaque); void virtio_update_irq(VirtIODevice *vdev); int virtio_set_features(VirtIODevice *vdev, uint64_t val); -- cgit v1.2.3 From b6a3cddb22d3f0f729e267d45f350ae31bdebbcf Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 4 Jun 2015 12:34:16 +0200 Subject: virtio-net: no writeable mac for virtio-1 Devices operating as virtio 1.0 may not allow writes to the mac address in config space. Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/net/virtio-net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 0d3bf0fb89..e2d2ab5bee 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -87,6 +87,7 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config) memcpy(&netcfg, config, n->config_size); if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR) && + !virtio_has_feature(vdev, VIRTIO_F_VERSION_1) && memcmp(netcfg.mac, n->mac, ETH_ALEN)) { memcpy(n->mac, netcfg.mac, ETH_ALEN); qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); -- cgit v1.2.3 From bb9d17f831fa8e70494eab8421d83a542e3d8508 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 4 Jun 2015 12:34:17 +0200 Subject: virtio-net: support longer header virtio-1 devices always use num_buffers in the header, even if mergeable rx buffers have not been negotiated. Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/net/virtio-net.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index e2d2ab5bee..a01c4d19de 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -367,15 +367,21 @@ static int peer_has_ufo(VirtIONet *n) return n->has_ufo; } -static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs) +static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs, + int version_1) { int i; NetClientState *nc; n->mergeable_rx_bufs = mergeable_rx_bufs; - n->guest_hdr_len = n->mergeable_rx_bufs ? - sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); + if (version_1) { + n->guest_hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); + } else { + n->guest_hdr_len = n->mergeable_rx_bufs ? + sizeof(struct virtio_net_hdr_mrg_rxbuf) : + sizeof(struct virtio_net_hdr); + } for (i = 0; i < n->max_queues; i++) { nc = qemu_get_subqueue(n->nic, i); @@ -522,7 +528,9 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features) virtio_net_set_mrg_rx_bufs(n, __virtio_has_feature(features, - VIRTIO_NET_F_MRG_RXBUF)); + VIRTIO_NET_F_MRG_RXBUF), + __virtio_has_feature(features, + VIRTIO_F_VERSION_1)); if (n->has_vnet_hdr) { n->curr_guest_offloads = @@ -1375,7 +1383,8 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, qemu_get_buffer(f, n->mac, ETH_ALEN); n->vqs[0].tx_waiting = qemu_get_be32(f); - virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f)); + virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f), + virtio_has_feature(vdev, VIRTIO_F_VERSION_1)); if (version_id >= 3) n->status = qemu_get_be16(f); @@ -1627,7 +1636,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) n->vqs[0].tx_waiting = 0; n->tx_burst = n->net_conf.txburst; - virtio_net_set_mrg_rx_bufs(n, 0); + virtio_net_set_mrg_rx_bufs(n, 0, 0); n->promisc = 1; /* for compatibility */ n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN); -- cgit v1.2.3 From df91055db5c9cee93d70ca8c08d72119a240b987 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 4 Jun 2015 12:34:18 +0200 Subject: virtio-net: enable virtio 1.0 virtio-net (non-vhost) now should have everything in place to support virtio 1.0: let's enable the feature bit for it. Note that VIRTIO_F_VERSION_1 is technically a transport feature; once every device is ready for virtio 1.0, we can move setting this feature bit out of the individual devices. Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/net/virtio-net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index a01c4d19de..49fa13f161 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -470,6 +470,7 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features) } if (!get_vhost_net(nc->peer)) { + virtio_add_feature(&features, VIRTIO_F_VERSION_1); return features; } return vhost_net_get_features(get_vhost_net(nc->peer), features); -- cgit v1.2.3 From b1506132001eee6b11cf23b5968cd66ec141a9ed Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 4 Jun 2015 12:34:19 +0200 Subject: vhost_net: add version_1 feature Add VERSION_1 to list of features that we should test at the backend. Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/net/vhost_net.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 426b23e7e3..dc48ece695 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -52,6 +52,7 @@ static const int kernel_feature_bits[] = { VIRTIO_RING_F_INDIRECT_DESC, VIRTIO_RING_F_EVENT_IDX, VIRTIO_NET_F_MRG_RXBUF, + VIRTIO_F_VERSION_1, VHOST_INVALID_FEATURE_BIT }; @@ -62,6 +63,7 @@ static const int user_feature_bits[] = { VIRTIO_RING_F_EVENT_IDX, VIRTIO_F_ANY_LAYOUT, + VIRTIO_F_VERSION_1, VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GSO, -- cgit v1.2.3 From 9a2ba82302bea7faf3b9579f9168b89c73ae34ad Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 4 Jun 2015 12:34:20 +0200 Subject: vhost: 64 bit features Make sure that all vhost interfaces use 64 bit features, as the virtio core does, and make sure to use ULL everywhere possible to be on the safe side. Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/net/vhost_net.c | 12 ++++++------ hw/virtio/vhost.c | 14 +++++++------- include/hw/virtio/vhost.h | 6 +++--- include/net/vhost_net.h | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index dc48ece695..1c55517e36 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -109,13 +109,13 @@ static const int *vhost_net_get_feature_bits(struct vhost_net *net) return feature_bits; } -unsigned vhost_net_get_features(struct vhost_net *net, unsigned features) +uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features) { return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net), features); } -void vhost_net_ack_features(struct vhost_net *net, unsigned features) +void vhost_net_ack_features(struct vhost_net *net, uint64_t features) { net->dev.acked_features = net->dev.backend_features; vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features); @@ -149,7 +149,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options) goto fail; } net->dev.backend_features = qemu_has_vnet_hdr(options->net_backend) - ? 0 : (1 << VHOST_NET_F_VIRTIO_NET_HDR); + ? 0 : (1ULL << VHOST_NET_F_VIRTIO_NET_HDR); net->backend = r; } else { net->dev.backend_features = 0; @@ -169,7 +169,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options) if (backend_kernel) { if (!qemu_has_vnet_hdr_len(options->net_backend, sizeof(struct virtio_net_hdr_mrg_rxbuf))) { - net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF); + net->dev.features &= ~(1ULL << VIRTIO_NET_F_MRG_RXBUF); } if (~net->dev.features & net->dev.backend_features) { fprintf(stderr, "vhost lacks feature mask %" PRIu64 @@ -433,11 +433,11 @@ void vhost_net_cleanup(struct vhost_net *net) { } -unsigned vhost_net_get_features(struct vhost_net *net, unsigned features) +uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features) { return features; } -void vhost_net_ack_features(struct vhost_net *net, unsigned features) +void vhost_net_ack_features(struct vhost_net *net, uint64_t features) { } diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 3a52a4d037..7908255503 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -590,7 +590,7 @@ static int vhost_dev_set_features(struct vhost_dev *dev, bool enable_log) uint64_t features = dev->acked_features; int r; if (enable_log) { - features |= 0x1 << VHOST_F_LOG_ALL; + features |= 0x1ULL << VHOST_F_LOG_ALL; } r = dev->vhost_ops->vhost_call(dev, VHOST_SET_FEATURES, &features); return r < 0 ? -errno : 0; @@ -899,7 +899,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, .priority = 10 }; hdev->migration_blocker = NULL; - if (!(hdev->features & (0x1 << VHOST_F_LOG_ALL))) { + if (!(hdev->features & (0x1ULL << VHOST_F_LOG_ALL))) { error_setg(&hdev->migration_blocker, "Migration disabled: vhost lacks VHOST_F_LOG_ALL feature."); migrate_add_blocker(hdev->migration_blocker); @@ -1042,12 +1042,12 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, assert(r >= 0); } -unsigned vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, - unsigned features) +uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, + uint64_t features) { const int *bit = feature_bits; while (*bit != VHOST_INVALID_FEATURE_BIT) { - unsigned bit_mask = (1 << *bit); + uint64_t bit_mask = (1ULL << *bit); if (!(hdev->features & bit_mask)) { features &= ~bit_mask; } @@ -1057,11 +1057,11 @@ unsigned vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, } void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits, - unsigned features) + uint64_t features) { const int *bit = feature_bits; while (*bit != VHOST_INVALID_FEATURE_BIT) { - unsigned bit_mask = (1 << *bit); + uint64_t bit_mask = (1ULL << *bit); if (features & bit_mask) { hdev->acked_features |= bit_mask; } diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 816a2e8db2..84f170e789 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -78,8 +78,8 @@ bool vhost_virtqueue_pending(struct vhost_dev *hdev, int n); */ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, bool mask); -unsigned vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, - unsigned features); +uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, + uint64_t features); void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits, - unsigned features); + uint64_t features); #endif diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index b1c18a3f3b..9eb493efc3 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -22,8 +22,8 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs, int total_queues); void vhost_net_cleanup(VHostNetState *net); -unsigned vhost_net_get_features(VHostNetState *net, unsigned features); -void vhost_net_ack_features(VHostNetState *net, unsigned features); +uint64_t vhost_net_get_features(VHostNetState *net, uint64_t features); +void vhost_net_ack_features(VHostNetState *net, uint64_t features); bool vhost_net_virtqueue_pending(VHostNetState *net, int n); void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, -- cgit v1.2.3 From c17bef33601737e24a3d53259ddb6db28ac4d6d2 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 4 Jun 2015 12:34:21 +0200 Subject: linux-headers: add virtio_pci Easier than duplicating code. Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 2 + linux-headers/linux/virtio_pci.h | 192 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 linux-headers/linux/virtio_pci.h diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 6d4f64e282..8dca87c34d 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -38,6 +38,8 @@ #define VIRTIO_PCI_REGION_SIZE(dev) VIRTIO_PCI_CONFIG_OFF(msix_present(dev)) +#undef VIRTIO_PCI_CONFIG + /* The remaining space is defined by each driver as the per-driver * configuration space */ #define VIRTIO_PCI_CONFIG_SIZE(dev) VIRTIO_PCI_CONFIG_OFF(msix_enabled(dev)) diff --git a/linux-headers/linux/virtio_pci.h b/linux-headers/linux/virtio_pci.h new file mode 100644 index 0000000000..92624e5310 --- /dev/null +++ b/linux-headers/linux/virtio_pci.h @@ -0,0 +1,192 @@ +/* + * Virtio PCI driver + * + * This module allows virtio devices to be used over a virtual PCI device. + * This can be used with QEMU based VMMs like KVM or Xen. + * + * Copyright IBM Corp. 2007 + * + * Authors: + * Anthony Liguori + * + * This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _LINUX_VIRTIO_PCI_H +#define _LINUX_VIRTIO_PCI_H + +#include + +#ifndef VIRTIO_PCI_NO_LEGACY + +/* A 32-bit r/o bitmask of the features supported by the host */ +#define VIRTIO_PCI_HOST_FEATURES 0 + +/* A 32-bit r/w bitmask of features activated by the guest */ +#define VIRTIO_PCI_GUEST_FEATURES 4 + +/* A 32-bit r/w PFN for the currently selected queue */ +#define VIRTIO_PCI_QUEUE_PFN 8 + +/* A 16-bit r/o queue size for the currently selected queue */ +#define VIRTIO_PCI_QUEUE_NUM 12 + +/* A 16-bit r/w queue selector */ +#define VIRTIO_PCI_QUEUE_SEL 14 + +/* A 16-bit r/w queue notifier */ +#define VIRTIO_PCI_QUEUE_NOTIFY 16 + +/* An 8-bit device status register. */ +#define VIRTIO_PCI_STATUS 18 + +/* An 8-bit r/o interrupt status register. Reading the value will return the + * current contents of the ISR and will also clear it. This is effectively + * a read-and-acknowledge. */ +#define VIRTIO_PCI_ISR 19 + +/* MSI-X registers: only enabled if MSI-X is enabled. */ +/* A 16-bit vector for configuration changes. */ +#define VIRTIO_MSI_CONFIG_VECTOR 20 +/* A 16-bit vector for selected queue notifications. */ +#define VIRTIO_MSI_QUEUE_VECTOR 22 + +/* The remaining space is defined by each driver as the per-driver + * configuration space */ +#define VIRTIO_PCI_CONFIG_OFF(msix_enabled) ((msix_enabled) ? 24 : 20) +/* Deprecated: please use VIRTIO_PCI_CONFIG_OFF instead */ +#define VIRTIO_PCI_CONFIG(dev) VIRTIO_PCI_CONFIG_OFF((dev)->msix_enabled) + +/* Virtio ABI version, this must match exactly */ +#define VIRTIO_PCI_ABI_VERSION 0 + +/* How many bits to shift physical queue address written to QUEUE_PFN. + * 12 is historical, and due to x86 page size. */ +#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12 + +/* The alignment to use between consumer and producer parts of vring. + * x86 pagesize again. */ +#define VIRTIO_PCI_VRING_ALIGN 4096 + +#endif /* VIRTIO_PCI_NO_LEGACY */ + +/* The bit of the ISR which indicates a device configuration change. */ +#define VIRTIO_PCI_ISR_CONFIG 0x2 +/* Vector value used to disable MSI for queue */ +#define VIRTIO_MSI_NO_VECTOR 0xffff + +#ifndef VIRTIO_PCI_NO_MODERN + +/* IDs for different capabilities. Must all exist. */ + +/* Common configuration */ +#define VIRTIO_PCI_CAP_COMMON_CFG 1 +/* Notifications */ +#define VIRTIO_PCI_CAP_NOTIFY_CFG 2 +/* ISR access */ +#define VIRTIO_PCI_CAP_ISR_CFG 3 +/* Device specific confiuration */ +#define VIRTIO_PCI_CAP_DEVICE_CFG 4 + +/* This is the PCI capability header: */ +struct virtio_pci_cap { + __u8 cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */ + __u8 cap_next; /* Generic PCI field: next ptr. */ + __u8 cap_len; /* Generic PCI field: capability length */ + __u8 cfg_type; /* Identifies the structure. */ + __u8 bar; /* Where to find it. */ + __u8 padding[3]; /* Pad to full dword. */ + __le32 offset; /* Offset within bar. */ + __le32 length; /* Length of the structure, in bytes. */ +}; + +struct virtio_pci_notify_cap { + struct virtio_pci_cap cap; + __le32 notify_off_multiplier; /* Multiplier for queue_notify_off. */ +}; + +/* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */ +struct virtio_pci_common_cfg { + /* About the whole device. */ + __le32 device_feature_select; /* read-write */ + __le32 device_feature; /* read-only */ + __le32 guest_feature_select; /* read-write */ + __le32 guest_feature; /* read-write */ + __le16 msix_config; /* read-write */ + __le16 num_queues; /* read-only */ + __u8 device_status; /* read-write */ + __u8 config_generation; /* read-only */ + + /* About a specific virtqueue. */ + __le16 queue_select; /* read-write */ + __le16 queue_size; /* read-write, power of 2. */ + __le16 queue_msix_vector; /* read-write */ + __le16 queue_enable; /* read-write */ + __le16 queue_notify_off; /* read-only */ + __le32 queue_desc_lo; /* read-write */ + __le32 queue_desc_hi; /* read-write */ + __le32 queue_avail_lo; /* read-write */ + __le32 queue_avail_hi; /* read-write */ + __le32 queue_used_lo; /* read-write */ + __le32 queue_used_hi; /* read-write */ +}; + +/* Macro versions of offsets for the Old Timers! */ +#define VIRTIO_PCI_CAP_VNDR 0 +#define VIRTIO_PCI_CAP_NEXT 1 +#define VIRTIO_PCI_CAP_LEN 2 +#define VIRTIO_PCI_CAP_CFG_TYPE 3 +#define VIRTIO_PCI_CAP_BAR 4 +#define VIRTIO_PCI_CAP_OFFSET 8 +#define VIRTIO_PCI_CAP_LENGTH 12 + +#define VIRTIO_PCI_NOTIFY_CAP_MULT 16 + + +#define VIRTIO_PCI_COMMON_DFSELECT 0 +#define VIRTIO_PCI_COMMON_DF 4 +#define VIRTIO_PCI_COMMON_GFSELECT 8 +#define VIRTIO_PCI_COMMON_GF 12 +#define VIRTIO_PCI_COMMON_MSIX 16 +#define VIRTIO_PCI_COMMON_NUMQ 18 +#define VIRTIO_PCI_COMMON_STATUS 20 +#define VIRTIO_PCI_COMMON_CFGGENERATION 21 +#define VIRTIO_PCI_COMMON_Q_SELECT 22 +#define VIRTIO_PCI_COMMON_Q_SIZE 24 +#define VIRTIO_PCI_COMMON_Q_MSIX 26 +#define VIRTIO_PCI_COMMON_Q_ENABLE 28 +#define VIRTIO_PCI_COMMON_Q_NOFF 30 +#define VIRTIO_PCI_COMMON_Q_DESCLO 32 +#define VIRTIO_PCI_COMMON_Q_DESCHI 36 +#define VIRTIO_PCI_COMMON_Q_AVAILLO 40 +#define VIRTIO_PCI_COMMON_Q_AVAILHI 44 +#define VIRTIO_PCI_COMMON_Q_USEDLO 48 +#define VIRTIO_PCI_COMMON_Q_USEDHI 52 + +#endif /* VIRTIO_PCI_NO_MODERN */ + +#endif -- cgit v1.2.3 From dfb8e184db758bff275f94f7aa634300886cfe21 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 4 Jun 2015 12:34:22 +0200 Subject: virtio-pci: initial virtio 1.0 support This is somewhat functional. With this, and linux driver from my tree, I was able to use virtio net as virtio 1.0 device for light browsing. At the moment, dataplane and vhost code is still missing. Based on Cornelia's virtio 1.0 patchset: Date: Thu, 11 Dec 2014 14:25:02 +0100 From: Cornelia Huck To: virtualization@lists.linux-foundation.org, qemu-devel@nongnu.org Cc: rusty@rustcorp.com.au, thuth@linux.vnet.ibm.com, mst@redhat.com, Cornelia Huck Subject: [PATCH RFC v6 00/20] qemu: towards virtio-1 host support Message-Id: <1418304322-7546-1-git-send-email-cornelia.huck@de.ibm.com> which is itself still missing some core bits. Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 379 +++++++++++++++++++++++++++++++++++++++++++++++++ hw/virtio/virtio-pci.h | 16 +++ 2 files changed, 395 insertions(+) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 8dca87c34d..8fc3c4ea9b 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -920,6 +920,278 @@ static int virtio_pci_query_nvectors(DeviceState *d) return proxy->nvectors; } +static void virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy, + struct virtio_pci_cap *cap) +{ + PCIDevice *dev = &proxy->pci_dev; + int offset; + + cap->bar = 2; + + offset = pci_add_capability(dev, PCI_CAP_ID_VNDR, 0, cap->cap_len); + assert(offset > 0); + + assert(cap->cap_len >= sizeof *cap); + memcpy(dev->config + offset + PCI_CAP_FLAGS, &cap->cap_len, + cap->cap_len - PCI_CAP_FLAGS); +} + +#define QEMU_VIRTIO_PCI_QUEUE_MEM_MULT 0x10000 + +static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr, + unsigned size) +{ + VirtIOPCIProxy *proxy = opaque; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + uint32_t val = 0; + int i; + + switch (addr) { + case VIRTIO_PCI_COMMON_DFSELECT: + val = proxy->dfselect; + break; + case VIRTIO_PCI_COMMON_DF: + if (proxy->dfselect <= 1) { + val = vdev->host_features >> (32 * proxy->dfselect); + } + break; + case VIRTIO_PCI_COMMON_GFSELECT: + val = proxy->gfselect; + break; + case VIRTIO_PCI_COMMON_GF: + if (proxy->gfselect <= ARRAY_SIZE(proxy->guest_features)) { + val = proxy->guest_features[proxy->gfselect]; + } + break; + case VIRTIO_PCI_COMMON_MSIX: + val = vdev->config_vector; + break; + case VIRTIO_PCI_COMMON_NUMQ: + for (i = 0; i < VIRTIO_QUEUE_MAX; ++i) { + if (virtio_queue_get_num(vdev, i)) { + val = i + 1; + } + } + break; + case VIRTIO_PCI_COMMON_STATUS: + val = vdev->status; + break; + case VIRTIO_PCI_COMMON_CFGGENERATION: + val = 0; /* TODO */ + break; + case VIRTIO_PCI_COMMON_Q_SELECT: + val = vdev->queue_sel; + break; + case VIRTIO_PCI_COMMON_Q_SIZE: + val = virtio_queue_get_num(vdev, vdev->queue_sel); + break; + case VIRTIO_PCI_COMMON_Q_MSIX: + val = virtio_queue_vector(vdev, vdev->queue_sel); + break; + case VIRTIO_PCI_COMMON_Q_ENABLE: + val = proxy->vqs[vdev->queue_sel].enabled; + break; + case VIRTIO_PCI_COMMON_Q_NOFF: + /* Simply map queues in order */ + val = vdev->queue_sel; + break; + case VIRTIO_PCI_COMMON_Q_DESCLO: + val = proxy->vqs[vdev->queue_sel].desc[0]; + break; + case VIRTIO_PCI_COMMON_Q_DESCHI: + val = proxy->vqs[vdev->queue_sel].desc[1]; + break; + case VIRTIO_PCI_COMMON_Q_AVAILLO: + val = proxy->vqs[vdev->queue_sel].avail[0]; + break; + case VIRTIO_PCI_COMMON_Q_AVAILHI: + val = proxy->vqs[vdev->queue_sel].avail[1]; + break; + case VIRTIO_PCI_COMMON_Q_USEDLO: + val = proxy->vqs[vdev->queue_sel].used[0]; + break; + case VIRTIO_PCI_COMMON_Q_USEDHI: + val = proxy->vqs[vdev->queue_sel].used[1]; + break; + default: + val = 0; + } + + return val; +} + +static void virtio_pci_common_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + VirtIOPCIProxy *proxy = opaque; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + + switch (addr) { + case VIRTIO_PCI_COMMON_DFSELECT: + proxy->dfselect = val; + break; + case VIRTIO_PCI_COMMON_GFSELECT: + proxy->gfselect = val; + break; + case VIRTIO_PCI_COMMON_GF: + if (proxy->gfselect <= ARRAY_SIZE(proxy->guest_features)) { + proxy->guest_features[proxy->gfselect] = val; + virtio_set_features(vdev, + (((uint64_t)proxy->guest_features[1]) << 32) | + proxy->guest_features[0]); + } + break; + case VIRTIO_PCI_COMMON_MSIX: + msix_vector_unuse(&proxy->pci_dev, vdev->config_vector); + /* Make it possible for guest to discover an error took place. */ + if (msix_vector_use(&proxy->pci_dev, val) < 0) { + val = VIRTIO_NO_VECTOR; + } + vdev->config_vector = val; + break; + case VIRTIO_PCI_COMMON_STATUS: + if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) { + virtio_pci_stop_ioeventfd(proxy); + } + + virtio_set_status(vdev, val & 0xFF); + + if (val & VIRTIO_CONFIG_S_DRIVER_OK) { + virtio_pci_start_ioeventfd(proxy); + } + + if (vdev->status == 0) { + virtio_reset(vdev); + msix_unuse_all_vectors(&proxy->pci_dev); + } + + break; + case VIRTIO_PCI_COMMON_Q_SELECT: + if (val < VIRTIO_QUEUE_MAX) { + vdev->queue_sel = val; + } + break; + case VIRTIO_PCI_COMMON_Q_SIZE: + proxy->vqs[vdev->queue_sel].num = val; + break; + case VIRTIO_PCI_COMMON_Q_MSIX: + msix_vector_unuse(&proxy->pci_dev, + virtio_queue_vector(vdev, vdev->queue_sel)); + /* Make it possible for guest to discover an error took place. */ + if (msix_vector_use(&proxy->pci_dev, val) < 0) { + val = VIRTIO_NO_VECTOR; + } + virtio_queue_set_vector(vdev, vdev->queue_sel, val); + break; + case VIRTIO_PCI_COMMON_Q_ENABLE: + /* TODO: need a way to put num back on reset. */ + virtio_queue_set_num(vdev, vdev->queue_sel, + proxy->vqs[vdev->queue_sel].num); + virtio_queue_set_rings(vdev, vdev->queue_sel, + ((uint64_t)proxy->vqs[vdev->queue_sel].desc[1]) << 32 | + proxy->vqs[vdev->queue_sel].desc[0], + ((uint64_t)proxy->vqs[vdev->queue_sel].avail[1]) << 32 | + proxy->vqs[vdev->queue_sel].avail[0], + ((uint64_t)proxy->vqs[vdev->queue_sel].used[1]) << 32 | + proxy->vqs[vdev->queue_sel].used[0]); + break; + case VIRTIO_PCI_COMMON_Q_DESCLO: + proxy->vqs[vdev->queue_sel].desc[0] = val; + break; + case VIRTIO_PCI_COMMON_Q_DESCHI: + proxy->vqs[vdev->queue_sel].desc[1] = val; + break; + case VIRTIO_PCI_COMMON_Q_AVAILLO: + proxy->vqs[vdev->queue_sel].avail[0] = val; + break; + case VIRTIO_PCI_COMMON_Q_AVAILHI: + proxy->vqs[vdev->queue_sel].avail[1] = val; + break; + case VIRTIO_PCI_COMMON_Q_USEDLO: + proxy->vqs[vdev->queue_sel].used[0] = val; + break; + case VIRTIO_PCI_COMMON_Q_USEDHI: + proxy->vqs[vdev->queue_sel].used[1] = val; + break; + default: + break; + } +} + + +static uint64_t virtio_pci_notify_read(void *opaque, hwaddr addr, + unsigned size) +{ + return 0; +} + +static void virtio_pci_notify_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + VirtIODevice *vdev = opaque; + unsigned queue = addr / QEMU_VIRTIO_PCI_QUEUE_MEM_MULT; + + if (queue < VIRTIO_QUEUE_MAX) { + virtio_queue_notify(vdev, queue); + } +} + +static uint64_t virtio_pci_isr_read(void *opaque, hwaddr addr, + unsigned size) +{ + VirtIOPCIProxy *proxy = opaque; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + uint64_t val = vdev->isr; + + vdev->isr = 0; + pci_irq_deassert(&proxy->pci_dev); + + return val; +} + +static void virtio_pci_isr_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ +} + +static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr, + unsigned size) +{ + VirtIODevice *vdev = opaque; + uint64_t val = 0; + + switch (size) { + case 1: + val = virtio_config_readb(vdev, addr); + break; + case 2: + val = virtio_config_readw(vdev, addr); + break; + case 4: + val = virtio_config_readl(vdev, addr); + break; + } + return val; +} + +static void virtio_pci_device_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + VirtIODevice *vdev = opaque; + switch (size) { + case 1: + virtio_config_writeb(vdev, addr, val); + break; + case 2: + virtio_config_writew(vdev, addr, val); + break; + case 4: + virtio_config_writel(vdev, addr, val); + break; + } +} + + /* This is called by virtio-bus just after the device is plugged. */ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) { @@ -938,6 +1210,112 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus)); config[PCI_INTERRUPT_PIN] = 1; + + if (1) { /* TODO: Make this optional, dependent on virtio 1.0 */ + struct virtio_pci_cap common = { + .cfg_type = VIRTIO_PCI_CAP_COMMON_CFG, + .cap_len = sizeof common, + .offset = cpu_to_le32(0x0), + .length = cpu_to_le32(0x1000), + }; + struct virtio_pci_cap isr = { + .cfg_type = VIRTIO_PCI_CAP_ISR_CFG, + .cap_len = sizeof isr, + .offset = cpu_to_le32(0x1000), + .length = cpu_to_le32(0x1000), + }; + struct virtio_pci_cap device = { + .cfg_type = VIRTIO_PCI_CAP_DEVICE_CFG, + .cap_len = sizeof device, + .offset = cpu_to_le32(0x2000), + .length = cpu_to_le32(0x1000), + }; + struct virtio_pci_notify_cap notify = { + .cap.cfg_type = VIRTIO_PCI_CAP_NOTIFY_CFG, + .cap.cap_len = sizeof notify, + .cap.offset = cpu_to_le32(0x3000), + .cap.length = cpu_to_le32(QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * + VIRTIO_QUEUE_MAX), + .notify_off_multiplier = + cpu_to_le32(QEMU_VIRTIO_PCI_QUEUE_MEM_MULT), + }; + + static const MemoryRegionOps common_ops = { + .read = virtio_pci_common_read, + .write = virtio_pci_common_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_LITTLE_ENDIAN, + }; + + static const MemoryRegionOps isr_ops = { + .read = virtio_pci_isr_read, + .write = virtio_pci_isr_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_LITTLE_ENDIAN, + }; + + static const MemoryRegionOps device_ops = { + .read = virtio_pci_device_read, + .write = virtio_pci_device_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_LITTLE_ENDIAN, + }; + + static const MemoryRegionOps notify_ops = { + .read = virtio_pci_notify_read, + .write = virtio_pci_notify_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_LITTLE_ENDIAN, + }; + + /* TODO: add io access for speed */ + virtio_pci_add_mem_cap(proxy, &common); + virtio_pci_add_mem_cap(proxy, &isr); + virtio_pci_add_mem_cap(proxy, &device); + virtio_pci_add_mem_cap(proxy, ¬ify.cap); + + virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1); + memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci", + 2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * + VIRTIO_QUEUE_MAX); + memory_region_init_io(&proxy->common, OBJECT(proxy), + &common_ops, + proxy, + "virtio-pci-common", 0x1000); + memory_region_add_subregion(&proxy->modern_bar, 0, &proxy->common); + memory_region_init_io(&proxy->isr, OBJECT(proxy), + &isr_ops, + proxy, + "virtio-pci-isr", 0x1000); + memory_region_add_subregion(&proxy->modern_bar, 0x1000, &proxy->isr); + memory_region_init_io(&proxy->device, OBJECT(proxy), + &device_ops, + virtio_bus_get_device(&proxy->bus), + "virtio-pci-device", 0x1000); + memory_region_add_subregion(&proxy->modern_bar, 0x2000, &proxy->device); + memory_region_init_io(&proxy->notify, OBJECT(proxy), + ¬ify_ops, + virtio_bus_get_device(&proxy->bus), + "virtio-pci-notify", + QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * + VIRTIO_QUEUE_MAX); + memory_region_add_subregion(&proxy->modern_bar, 0x3000, &proxy->notify); + pci_register_bar(&proxy->pci_dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, + &proxy->modern_bar); + } + if (proxy->nvectors && msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, 1)) { error_report("unable to init msix vectors to %" PRIu32, @@ -955,6 +1333,7 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) memory_region_init_io(&proxy->bar, OBJECT(proxy), &virtio_pci_config_ops, proxy, "virtio-pci", size); + pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &proxy->bar); diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index de394687ef..7a6481f96d 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -88,9 +88,25 @@ typedef struct VirtioPCIClass { struct VirtIOPCIProxy { PCIDevice pci_dev; MemoryRegion bar; + MemoryRegion common; + MemoryRegion isr; + MemoryRegion device; + MemoryRegion notify; + MemoryRegion modern_bar; uint32_t flags; uint32_t class_code; uint32_t nvectors; + uint32_t dfselect; + uint32_t gfselect; + uint32_t guest_features[2]; + struct { + uint16_t num; + bool enabled; + uint32_t desc[2]; + uint32_t avail[2]; + uint32_t used[2]; + } vqs[VIRTIO_QUEUE_MAX]; + bool ioeventfd_disabled; bool ioeventfd_started; VirtIOIRQFD *vector_irqfd; -- cgit v1.2.3 From b8f059081d93f1802480059d1d49fe5c1d32f60c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 4 Jun 2015 12:34:23 +0200 Subject: virtio: generation counter support Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 2 +- hw/virtio/virtio.c | 1 + include/hw/virtio/virtio.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 8fc3c4ea9b..7805bddc74 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -977,7 +977,7 @@ static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr, val = vdev->status; break; case VIRTIO_PCI_COMMON_CFGGENERATION: - val = 0; /* TODO */ + val = vdev->generation; break; case VIRTIO_PCI_COMMON_Q_SELECT: val = vdev->queue_sel; diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 8a6ebae368..cae5ecab19 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -930,6 +930,7 @@ void virtio_notify_config(VirtIODevice *vdev) return; vdev->isr |= 0x03; + vdev->generation++; virtio_notify_vector(vdev, vdev->config_vector); } diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index df8991357f..b9e36f95d3 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -78,6 +78,7 @@ struct VirtIODevice size_t config_len; void *config; uint16_t config_vector; + uint32_t generation; int nvectors; VirtQueue *vq; uint16_t device_id; -- cgit v1.2.3 From adfb743c90c7aa5e92907ce875e4f35747ee1963 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 4 Jun 2015 12:34:24 +0200 Subject: virtio: add modern config accessors virtio 1.0 defines config space as LE, as opposed to pre-1.0 which was native endian. Add API for transports to execute word/dword accesses in little endian format - will be useful for mmio and pci (byte access is also wrapped, for completeness). For simplicity, we still keep config in host native endian format, byteswap to LE on guest access. Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++ include/hw/virtio/virtio.h | 9 +++++ 2 files changed, 105 insertions(+) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index cae5ecab19..fb49ffcb2d 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -729,6 +729,102 @@ void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data) } } +uint32_t virtio_config_modern_readb(VirtIODevice *vdev, uint32_t addr) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint8_t val; + + if (addr + sizeof(val) > vdev->config_len) { + return (uint32_t)-1; + } + + k->get_config(vdev, vdev->config); + + val = ldub_p(vdev->config + addr); + return val; +} + +uint32_t virtio_config_modern_readw(VirtIODevice *vdev, uint32_t addr) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint16_t val; + + if (addr + sizeof(val) > vdev->config_len) { + return (uint32_t)-1; + } + + k->get_config(vdev, vdev->config); + + val = lduw_le_p(vdev->config + addr); + return val; +} + +uint32_t virtio_config_modern_readl(VirtIODevice *vdev, uint32_t addr) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint32_t val; + + if (addr + sizeof(val) > vdev->config_len) { + return (uint32_t)-1; + } + + k->get_config(vdev, vdev->config); + + val = ldl_le_p(vdev->config + addr); + return val; +} + +void virtio_config_modern_writeb(VirtIODevice *vdev, + uint32_t addr, uint32_t data) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint8_t val = data; + + if (addr + sizeof(val) > vdev->config_len) { + return; + } + + stb_p(vdev->config + addr, val); + + if (k->set_config) { + k->set_config(vdev, vdev->config); + } +} + +void virtio_config_modern_writew(VirtIODevice *vdev, + uint32_t addr, uint32_t data) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint16_t val = data; + + if (addr + sizeof(val) > vdev->config_len) { + return; + } + + stw_le_p(vdev->config + addr, val); + + if (k->set_config) { + k->set_config(vdev, vdev->config); + } +} + +void virtio_config_modern_writel(VirtIODevice *vdev, + uint32_t addr, uint32_t data) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint32_t val = data; + + if (addr + sizeof(val) > vdev->config_len) { + return; + } + + stl_le_p(vdev->config + addr, val); + + if (k->set_config) { + k->set_config(vdev, vdev->config); + } +} + void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr) { vdev->vq[n].vring.desc = addr; diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index b9e36f95d3..473fb75e28 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -174,6 +174,15 @@ uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr); void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data); void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data); void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data); +uint32_t virtio_config_modern_readb(VirtIODevice *vdev, uint32_t addr); +uint32_t virtio_config_modern_readw(VirtIODevice *vdev, uint32_t addr); +uint32_t virtio_config_modern_readl(VirtIODevice *vdev, uint32_t addr); +void virtio_config_modern_writeb(VirtIODevice *vdev, + uint32_t addr, uint32_t data); +void virtio_config_modern_writew(VirtIODevice *vdev, + uint32_t addr, uint32_t data); +void virtio_config_modern_writel(VirtIODevice *vdev, + uint32_t addr, uint32_t data); void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr); hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n); void virtio_queue_set_num(VirtIODevice *vdev, int n, int num); -- cgit v1.2.3 From 54c720d49d3f9741b52ac95c65a5cc990254a5d8 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 4 Jun 2015 12:34:25 +0200 Subject: virtio-pci: switch to modern accessors for 1.0 virtio 1.0 config space is in LE format for all devices, use modern wrappers when accessed through the 1.0 BAR. Reported-by: Rusty Russell Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 7805bddc74..d6d76684fc 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1162,13 +1162,13 @@ static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr, switch (size) { case 1: - val = virtio_config_readb(vdev, addr); + val = virtio_config_modern_readb(vdev, addr); break; case 2: - val = virtio_config_readw(vdev, addr); + val = virtio_config_modern_readw(vdev, addr); break; case 4: - val = virtio_config_readl(vdev, addr); + val = virtio_config_modern_readl(vdev, addr); break; } return val; @@ -1180,13 +1180,13 @@ static void virtio_pci_device_write(void *opaque, hwaddr addr, VirtIODevice *vdev = opaque; switch (size) { case 1: - virtio_config_writeb(vdev, addr, val); + virtio_config_modern_writeb(vdev, addr, val); break; case 2: - virtio_config_writew(vdev, addr, val); + virtio_config_modern_writew(vdev, addr, val); break; case 4: - virtio_config_writel(vdev, addr, val); + virtio_config_modern_writel(vdev, addr, val); break; } } -- cgit v1.2.3 From e266d421490e0ae83044bbebb209b2d3650c0ba6 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:26 +0200 Subject: virtio-pci: add flags to enable/disable legacy/modern Add VIRTIO_PCI_FLAG_DISABLE_LEGACY and VIRTIO_PCI_FLAG_DISABLE_MODERN for VirtIOPCIProxy->flags. Also add properties for them. They can be used to disable modern (virtio 1.0) or legacy (virtio 0.9) modes. By default only legacy is advertized, modern will be turned on by default once all remaining spec compilance issues are addressed. Signed-off-by: Gerd Hoffmann Acked-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 46 +++++++++++++++++++++++++++++++++------------- hw/virtio/virtio-pci.h | 6 ++++++ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index d6d76684fc..37c45330b7 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1197,6 +1197,8 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) { VirtIOPCIProxy *proxy = VIRTIO_PCI(d); VirtioBusState *bus = &proxy->bus; + bool legacy = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_LEGACY); + bool modern = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_MODERN); uint8_t *config; uint32_t size; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); @@ -1205,13 +1207,24 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) if (proxy->class_code) { pci_config_set_class(config, proxy->class_code); } - pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID, - pci_get_word(config + PCI_VENDOR_ID)); - pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus)); + + if (legacy) { + /* legacy and transitional */ + pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID, + pci_get_word(config + PCI_VENDOR_ID)); + pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus)); + } else { + /* pure virtio-1.0 */ + pci_set_word(config + PCI_VENDOR_ID, + PCI_VENDOR_ID_REDHAT_QUMRANET); + pci_set_word(config + PCI_DEVICE_ID, + 0x1040 + virtio_bus_get_vdev_id(bus)); + pci_config_set_revision(config, 1); + } config[PCI_INTERRUPT_PIN] = 1; - if (1) { /* TODO: Make this optional, dependent on virtio 1.0 */ + if (modern) { struct virtio_pci_cap common = { .cfg_type = VIRTIO_PCI_CAP_COMMON_CFG, .cap_len = sizeof common, @@ -1325,17 +1338,20 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) proxy->pci_dev.config_write = virtio_write_config; - size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) - + virtio_bus_get_vdev_config_len(bus); - if (size & (size - 1)) { - size = 1 << qemu_fls(size); - } + if (legacy) { + size = VIRTIO_PCI_REGION_SIZE(&proxy->pci_dev) + + virtio_bus_get_vdev_config_len(bus); + if (size & (size - 1)) { + size = 1 << qemu_fls(size); + } - memory_region_init_io(&proxy->bar, OBJECT(proxy), &virtio_pci_config_ops, - proxy, "virtio-pci", size); + memory_region_init_io(&proxy->bar, OBJECT(proxy), + &virtio_pci_config_ops, + proxy, "virtio-pci", size); - pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, - &proxy->bar); + pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, + &proxy->bar); + } if (!kvm_has_many_ioeventfds()) { proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD; @@ -1379,6 +1395,10 @@ static void virtio_pci_reset(DeviceState *qdev) static Property virtio_pci_properties[] = { DEFINE_PROP_BIT("virtio-pci-bus-master-bug-migration", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_BUS_MASTER_BUG_MIGRATION_BIT, false), + DEFINE_PROP_BIT("disable-legacy", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_DISABLE_LEGACY_BIT, false), + DEFINE_PROP_BIT("disable-modern", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_DISABLE_MODERN_BIT, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 7a6481f96d..4e9b2dbdac 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -63,6 +63,12 @@ typedef struct VirtioBusClass VirtioPCIBusClass; #define VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT 1 #define VIRTIO_PCI_FLAG_USE_IOEVENTFD (1 << VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT) +/* virtio version flags */ +#define VIRTIO_PCI_FLAG_DISABLE_LEGACY_BIT 2 +#define VIRTIO_PCI_FLAG_DISABLE_MODERN_BIT 3 +#define VIRTIO_PCI_FLAG_DISABLE_LEGACY (1 << VIRTIO_PCI_FLAG_DISABLE_LEGACY_BIT) +#define VIRTIO_PCI_FLAG_DISABLE_MODERN (1 << VIRTIO_PCI_FLAG_DISABLE_MODERN_BIT) + typedef struct { MSIMessage msg; int virq; -- cgit v1.2.3 From 8aca0d75869f8ad0aa0032c50d8c85dcad65302f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:27 +0200 Subject: virtio-pci: make QEMU_VIRTIO_PCI_QUEUE_MEM_MULT smaller Signed-off-by: Gerd Hoffmann Acked-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 37c45330b7..94815845a1 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -936,7 +936,7 @@ static void virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy, cap->cap_len - PCI_CAP_FLAGS); } -#define QEMU_VIRTIO_PCI_QUEUE_MEM_MULT 0x10000 +#define QEMU_VIRTIO_PCI_QUEUE_MEM_MULT 0x1000 static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr, unsigned size) -- cgit v1.2.3 From 23c5e3977502a1b57fa2d8cf8cf4b5c9e45f0d1f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:28 +0200 Subject: virtio-pci: change & document virtio pci bar layout. This patch adds variables for the pci bars (to get rid of the magic numbers in the code) and moves the modern virtio bar to region 4 so regions 2+3 are kept free. virtio-vga wants use them. Signed-off-by: Gerd Hoffmann Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 94815845a1..16d6e69a55 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -926,8 +926,6 @@ static void virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy, PCIDevice *dev = &proxy->pci_dev; int offset; - cap->bar = 2; - offset = pci_add_capability(dev, PCI_CAP_ID_VNDR, 0, cap->cap_len); assert(offset > 0); @@ -1203,6 +1201,22 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) uint32_t size; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + /* + * virtio pci bar layout + * + * region 0 -- virtio legacy io bar + * region 1 -- msi-x bar + * region 2+3 -- not used by virtio-pci + * region 4+5 -- virtio modern memory (64bit) bar + * + * Regions 2+3 can be used by VirtIOPCIProxy subclasses. + * virtio-vga places the vga framebuffer there. + * + */ + uint32_t legacy_io_bar = 0; + uint32_t msix_bar = 1; + uint32_t modern_mem_bar = 4; + config = proxy->pci_dev.config; if (proxy->class_code) { pci_config_set_class(config, proxy->class_code); @@ -1228,24 +1242,28 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) struct virtio_pci_cap common = { .cfg_type = VIRTIO_PCI_CAP_COMMON_CFG, .cap_len = sizeof common, + .bar = modern_mem_bar, .offset = cpu_to_le32(0x0), .length = cpu_to_le32(0x1000), }; struct virtio_pci_cap isr = { .cfg_type = VIRTIO_PCI_CAP_ISR_CFG, .cap_len = sizeof isr, + .bar = modern_mem_bar, .offset = cpu_to_le32(0x1000), .length = cpu_to_le32(0x1000), }; struct virtio_pci_cap device = { .cfg_type = VIRTIO_PCI_CAP_DEVICE_CFG, .cap_len = sizeof device, + .bar = modern_mem_bar, .offset = cpu_to_le32(0x2000), .length = cpu_to_le32(0x1000), }; struct virtio_pci_notify_cap notify = { .cap.cfg_type = VIRTIO_PCI_CAP_NOTIFY_CFG, .cap.cap_len = sizeof notify, + .cap.bar = modern_mem_bar, .cap.offset = cpu_to_le32(0x3000), .cap.length = cpu_to_le32(QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX), @@ -1325,12 +1343,13 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX); memory_region_add_subregion(&proxy->modern_bar, 0x3000, &proxy->notify); - pci_register_bar(&proxy->pci_dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, + pci_register_bar(&proxy->pci_dev, modern_mem_bar, + PCI_BASE_ADDRESS_SPACE_MEMORY, &proxy->modern_bar); } if (proxy->nvectors && - msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, 1)) { + msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, msix_bar)) { error_report("unable to init msix vectors to %" PRIu32, proxy->nvectors); proxy->nvectors = 0; @@ -1349,8 +1368,8 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) &virtio_pci_config_ops, proxy, "virtio-pci", size); - pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, - &proxy->bar); + pci_register_bar(&proxy->pci_dev, legacy_io_bar, + PCI_BASE_ADDRESS_SPACE_IO, &proxy->bar); } if (!kvm_has_many_ioeventfds()) { -- cgit v1.2.3 From 4e93a68eb369b2f7adbef7a4f6afd7a30a0ed927 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:29 +0200 Subject: virtio-pci: make modern bar 64bit + prefetchable Signed-off-by: Gerd Hoffmann Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 16d6e69a55..7804361ecc 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1344,7 +1344,9 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) VIRTIO_QUEUE_MAX); memory_region_add_subregion(&proxy->modern_bar, 0x3000, &proxy->notify); pci_register_bar(&proxy->pci_dev, modern_mem_bar, - PCI_BASE_ADDRESS_SPACE_MEMORY, + PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_PREFETCH | + PCI_BASE_ADDRESS_MEM_TYPE_64, &proxy->modern_bar); } -- cgit v1.2.3 From 975acc0ae6d60260859884a9235ae3c62e2969a2 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 4 Jun 2015 12:34:30 +0200 Subject: virtio-pci: correctly set host notifiers for modern bar Currently, during host notifier set. We only add eventfd for legacy bar, this is not correct since: - Non-transitional device does not have legacy bar, so qemu will crash since proxy->bar was not initialized. - Modern device uses modern bar and notify cap to notify the device, we should add eventfd for proxy->notify. So this patch fixes the above two issues by adding eventfd based on whether legacy or modern device were supported. Signed-off-by: Jason Wang Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 7804361ecc..b7beddd6c1 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -135,12 +135,21 @@ static int virtio_pci_load_queue(DeviceState *d, int n, QEMUFile *f) return 0; } +#define QEMU_VIRTIO_PCI_QUEUE_MEM_MULT 0x1000 + static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy, int n, bool assign, bool set_handler) { VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); VirtQueue *vq = virtio_get_queue(vdev, n); EventNotifier *notifier = virtio_queue_get_host_notifier(vq); + bool legacy = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_LEGACY); + bool modern = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_MODERN); + MemoryRegion *modern_mr = &proxy->notify; + MemoryRegion *legacy_mr = &proxy->bar; + hwaddr modern_addr = QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * + virtio_get_queue_index(vq); + hwaddr legacy_addr = VIRTIO_PCI_QUEUE_NOTIFY; int r = 0; if (assign) { @@ -151,11 +160,23 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy, return r; } virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler); - memory_region_add_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2, - true, n, notifier); + if (modern) { + memory_region_add_eventfd(modern_mr, modern_addr, 2, + true, n, notifier); + } + if (legacy) { + memory_region_add_eventfd(legacy_mr, legacy_addr, 2, + true, n, notifier); + } } else { - memory_region_del_eventfd(&proxy->bar, VIRTIO_PCI_QUEUE_NOTIFY, 2, - true, n, notifier); + if (modern) { + memory_region_del_eventfd(modern_mr, modern_addr, 2, + true, n, notifier); + } + if (legacy) { + memory_region_del_eventfd(legacy_mr, legacy_addr, 2, + true, n, notifier); + } virtio_queue_set_host_notifier_fd_handler(vq, false, false); event_notifier_cleanup(notifier); } @@ -934,8 +955,6 @@ static void virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy, cap->cap_len - PCI_CAP_FLAGS); } -#define QEMU_VIRTIO_PCI_QUEUE_MEM_MULT 0x1000 - static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr, unsigned size) { -- cgit v1.2.3 From fbdc6892dd8a842a3d86b8315ff56399e0387b74 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 4 Jun 2015 12:34:31 +0200 Subject: virtio_balloon: header update add modern header Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- include/hw/virtio/virtio-balloon.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h index 4ab8f541b0..346a9fdb7d 100644 --- a/include/hw/virtio/virtio-balloon.h +++ b/include/hw/virtio/virtio-balloon.h @@ -25,6 +25,12 @@ typedef struct virtio_balloon_stat VirtIOBalloonStat; +typedef struct virtio_balloon_stat_modern { + uint16_t tag; + uint8_t reserved[6]; + uint64_t val; +} VirtIOBalloonStatModern; + typedef struct VirtIOBalloon { VirtIODevice parent_obj; VirtQueue *ivq, *dvq, *svq; -- cgit v1.2.3 From 40de55affda76392627e68d3b1ba5a6a11c492bc Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 4 Jun 2015 12:34:32 +0200 Subject: virtio-balloon: switch to virtio_add_feature This was missed during the conversion of feature bit manipulation. Signed-off-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin --- hw/virtio/virtio-balloon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index f915c7bd73..78bc14fc85 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -312,7 +312,7 @@ static void virtio_balloon_set_config(VirtIODevice *vdev, static uint64_t virtio_balloon_get_features(VirtIODevice *vdev, uint64_t f) { - f |= (1 << VIRTIO_BALLOON_F_STATS_VQ); + virtio_add_feature(&f, VIRTIO_BALLOON_F_STATS_VQ); return f; } -- cgit v1.2.3 From 588255ad5021f06789f438f7b045015c54e30841 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:33 +0200 Subject: virtio-pci: add struct VirtIOPCIRegion for virtio-1 regions For now just place the MemoryRegion there, following patches will add more. Signed-off-by: Gerd Hoffmann Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 20 +++++++++++--------- hw/virtio/virtio-pci.h | 12 ++++++++---- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index b7beddd6c1..ebba2d1e51 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -145,7 +145,7 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy, EventNotifier *notifier = virtio_queue_get_host_notifier(vq); bool legacy = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_LEGACY); bool modern = !(proxy->flags & VIRTIO_PCI_FLAG_DISABLE_MODERN); - MemoryRegion *modern_mr = &proxy->notify; + MemoryRegion *modern_mr = &proxy->notify.mr; MemoryRegion *legacy_mr = &proxy->bar; hwaddr modern_addr = QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * virtio_get_queue_index(vq); @@ -1340,28 +1340,30 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci", 2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX); - memory_region_init_io(&proxy->common, OBJECT(proxy), + memory_region_init_io(&proxy->common.mr, OBJECT(proxy), &common_ops, proxy, "virtio-pci-common", 0x1000); - memory_region_add_subregion(&proxy->modern_bar, 0, &proxy->common); - memory_region_init_io(&proxy->isr, OBJECT(proxy), + memory_region_add_subregion(&proxy->modern_bar, 0, &proxy->common.mr); + memory_region_init_io(&proxy->isr.mr, OBJECT(proxy), &isr_ops, proxy, "virtio-pci-isr", 0x1000); - memory_region_add_subregion(&proxy->modern_bar, 0x1000, &proxy->isr); - memory_region_init_io(&proxy->device, OBJECT(proxy), + memory_region_add_subregion(&proxy->modern_bar, 0x1000, &proxy->isr.mr); + memory_region_init_io(&proxy->device.mr, OBJECT(proxy), &device_ops, virtio_bus_get_device(&proxy->bus), "virtio-pci-device", 0x1000); - memory_region_add_subregion(&proxy->modern_bar, 0x2000, &proxy->device); - memory_region_init_io(&proxy->notify, OBJECT(proxy), + memory_region_add_subregion(&proxy->modern_bar, 0x2000, + &proxy->device.mr); + memory_region_init_io(&proxy->notify.mr, OBJECT(proxy), ¬ify_ops, virtio_bus_get_device(&proxy->bus), "virtio-pci-notify", QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX); - memory_region_add_subregion(&proxy->modern_bar, 0x3000, &proxy->notify); + memory_region_add_subregion(&proxy->modern_bar, 0x3000, + &proxy->notify.mr); pci_register_bar(&proxy->pci_dev, modern_mem_bar, PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_PREFETCH | diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 4e9b2dbdac..8f1fc025d3 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -91,13 +91,17 @@ typedef struct VirtioPCIClass { void (*realize)(VirtIOPCIProxy *vpci_dev, Error **errp); } VirtioPCIClass; +typedef struct VirtIOPCIRegion { + MemoryRegion mr; +} VirtIOPCIRegion; + struct VirtIOPCIProxy { PCIDevice pci_dev; MemoryRegion bar; - MemoryRegion common; - MemoryRegion isr; - MemoryRegion device; - MemoryRegion notify; + VirtIOPCIRegion common; + VirtIOPCIRegion isr; + VirtIOPCIRegion device; + VirtIOPCIRegion notify; MemoryRegion modern_bar; uint32_t flags; uint32_t class_code; -- cgit v1.2.3 From 1141ce2190c85daacfa9b874476651ed0f7dc6df Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:34 +0200 Subject: virtio-pci: add virtio_pci_modern_regions_init() Add init function for the modern pci regions, move over the init code. Signed-off-by: Gerd Hoffmann Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 117 +++++++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index ebba2d1e51..090e95b572 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1208,6 +1208,64 @@ static void virtio_pci_device_write(void *opaque, hwaddr addr, } } +static void virtio_pci_modern_regions_init(VirtIOPCIProxy *proxy) +{ + static const MemoryRegionOps common_ops = { + .read = virtio_pci_common_read, + .write = virtio_pci_common_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_LITTLE_ENDIAN, + }; + static const MemoryRegionOps isr_ops = { + .read = virtio_pci_isr_read, + .write = virtio_pci_isr_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_LITTLE_ENDIAN, + }; + static const MemoryRegionOps device_ops = { + .read = virtio_pci_device_read, + .write = virtio_pci_device_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_LITTLE_ENDIAN, + }; + static const MemoryRegionOps notify_ops = { + .read = virtio_pci_notify_read, + .write = virtio_pci_notify_write, + .impl = { + .min_access_size = 1, + .max_access_size = 4, + }, + .endianness = DEVICE_LITTLE_ENDIAN, + }; + + memory_region_init_io(&proxy->common.mr, OBJECT(proxy), + &common_ops, + proxy, + "virtio-pci-common", 0x1000); + memory_region_init_io(&proxy->isr.mr, OBJECT(proxy), + &isr_ops, + proxy, + "virtio-pci-isr", 0x1000); + memory_region_init_io(&proxy->device.mr, OBJECT(proxy), + &device_ops, + virtio_bus_get_device(&proxy->bus), + "virtio-pci-device", 0x1000); + memory_region_init_io(&proxy->notify.mr, OBJECT(proxy), + ¬ify_ops, + virtio_bus_get_device(&proxy->bus), + "virtio-pci-notify", + QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * + VIRTIO_QUEUE_MAX); +} /* This is called by virtio-bus just after the device is plugged. */ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) @@ -1290,46 +1348,6 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) cpu_to_le32(QEMU_VIRTIO_PCI_QUEUE_MEM_MULT), }; - static const MemoryRegionOps common_ops = { - .read = virtio_pci_common_read, - .write = virtio_pci_common_write, - .impl = { - .min_access_size = 1, - .max_access_size = 4, - }, - .endianness = DEVICE_LITTLE_ENDIAN, - }; - - static const MemoryRegionOps isr_ops = { - .read = virtio_pci_isr_read, - .write = virtio_pci_isr_write, - .impl = { - .min_access_size = 1, - .max_access_size = 4, - }, - .endianness = DEVICE_LITTLE_ENDIAN, - }; - - static const MemoryRegionOps device_ops = { - .read = virtio_pci_device_read, - .write = virtio_pci_device_write, - .impl = { - .min_access_size = 1, - .max_access_size = 4, - }, - .endianness = DEVICE_LITTLE_ENDIAN, - }; - - static const MemoryRegionOps notify_ops = { - .read = virtio_pci_notify_read, - .write = virtio_pci_notify_write, - .impl = { - .min_access_size = 1, - .max_access_size = 4, - }, - .endianness = DEVICE_LITTLE_ENDIAN, - }; - /* TODO: add io access for speed */ virtio_pci_add_mem_cap(proxy, &common); virtio_pci_add_mem_cap(proxy, &isr); @@ -1340,28 +1358,11 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci", 2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX); - memory_region_init_io(&proxy->common.mr, OBJECT(proxy), - &common_ops, - proxy, - "virtio-pci-common", 0x1000); + virtio_pci_modern_regions_init(proxy); memory_region_add_subregion(&proxy->modern_bar, 0, &proxy->common.mr); - memory_region_init_io(&proxy->isr.mr, OBJECT(proxy), - &isr_ops, - proxy, - "virtio-pci-isr", 0x1000); memory_region_add_subregion(&proxy->modern_bar, 0x1000, &proxy->isr.mr); - memory_region_init_io(&proxy->device.mr, OBJECT(proxy), - &device_ops, - virtio_bus_get_device(&proxy->bus), - "virtio-pci-device", 0x1000); memory_region_add_subregion(&proxy->modern_bar, 0x2000, &proxy->device.mr); - memory_region_init_io(&proxy->notify.mr, OBJECT(proxy), - ¬ify_ops, - virtio_bus_get_device(&proxy->bus), - "virtio-pci-notify", - QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * - VIRTIO_QUEUE_MAX); memory_region_add_subregion(&proxy->modern_bar, 0x3000, &proxy->notify.mr); pci_register_bar(&proxy->pci_dev, modern_mem_bar, -- cgit v1.2.3 From a3cc2e81592aba6d818005c078b94b16ba47a02c Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:35 +0200 Subject: virtio-pci: add virtio_pci_modern_region_map() Add function to map modern virtio regions. Add offset to VirtIOPCIRegion. Signed-off-by: Gerd Hoffmann Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 25 +++++++++++++++++++------ hw/virtio/virtio-pci.h | 1 + 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 090e95b572..759cfc4592 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1251,20 +1251,35 @@ static void virtio_pci_modern_regions_init(VirtIOPCIProxy *proxy) &common_ops, proxy, "virtio-pci-common", 0x1000); + proxy->common.offset = 0x0; + memory_region_init_io(&proxy->isr.mr, OBJECT(proxy), &isr_ops, proxy, "virtio-pci-isr", 0x1000); + proxy->isr.offset = 0x1000; + memory_region_init_io(&proxy->device.mr, OBJECT(proxy), &device_ops, virtio_bus_get_device(&proxy->bus), "virtio-pci-device", 0x1000); + proxy->device.offset = 0x2000; + memory_region_init_io(&proxy->notify.mr, OBJECT(proxy), ¬ify_ops, virtio_bus_get_device(&proxy->bus), "virtio-pci-notify", QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX); + proxy->notify.offset = 0x3000; +} + +static void virtio_pci_modern_region_map(VirtIOPCIProxy *proxy, + VirtIOPCIRegion *region) +{ + memory_region_add_subregion(&proxy->modern_bar, + region->offset, + ®ion->mr); } /* This is called by virtio-bus just after the device is plugged. */ @@ -1359,12 +1374,10 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) 2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX); virtio_pci_modern_regions_init(proxy); - memory_region_add_subregion(&proxy->modern_bar, 0, &proxy->common.mr); - memory_region_add_subregion(&proxy->modern_bar, 0x1000, &proxy->isr.mr); - memory_region_add_subregion(&proxy->modern_bar, 0x2000, - &proxy->device.mr); - memory_region_add_subregion(&proxy->modern_bar, 0x3000, - &proxy->notify.mr); + virtio_pci_modern_region_map(proxy, &proxy->common); + virtio_pci_modern_region_map(proxy, &proxy->isr); + virtio_pci_modern_region_map(proxy, &proxy->device); + virtio_pci_modern_region_map(proxy, &proxy->notify); pci_register_bar(&proxy->pci_dev, modern_mem_bar, PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_PREFETCH | diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 8f1fc025d3..f5829b07a5 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -93,6 +93,7 @@ typedef struct VirtioPCIClass { typedef struct VirtIOPCIRegion { MemoryRegion mr; + uint32_t offset; } VirtIOPCIRegion; struct VirtIOPCIProxy { -- cgit v1.2.3 From 54790d71e4adcfaae95dac3c7019b10721e609de Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:36 +0200 Subject: virtio-pci: move virtio_pci_add_mem_cap call to virtio_pci_modern_region_map Also fill offset and length automatically, from VirtIOPCIRegion->offset and region size. Signed-off-by: Gerd Hoffmann Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 759cfc4592..f4bdd1c66b 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1275,11 +1275,16 @@ static void virtio_pci_modern_regions_init(VirtIOPCIProxy *proxy) } static void virtio_pci_modern_region_map(VirtIOPCIProxy *proxy, - VirtIOPCIRegion *region) + VirtIOPCIRegion *region, + struct virtio_pci_cap *cap) { memory_region_add_subregion(&proxy->modern_bar, region->offset, ®ion->mr); + + cap->offset = cpu_to_le32(region->offset); + cap->length = cpu_to_le32(memory_region_size(®ion->mr)); + virtio_pci_add_mem_cap(proxy, cap); } /* This is called by virtio-bus just after the device is plugged. */ @@ -1335,49 +1340,36 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) .cfg_type = VIRTIO_PCI_CAP_COMMON_CFG, .cap_len = sizeof common, .bar = modern_mem_bar, - .offset = cpu_to_le32(0x0), - .length = cpu_to_le32(0x1000), }; struct virtio_pci_cap isr = { .cfg_type = VIRTIO_PCI_CAP_ISR_CFG, .cap_len = sizeof isr, .bar = modern_mem_bar, - .offset = cpu_to_le32(0x1000), - .length = cpu_to_le32(0x1000), }; struct virtio_pci_cap device = { .cfg_type = VIRTIO_PCI_CAP_DEVICE_CFG, .cap_len = sizeof device, .bar = modern_mem_bar, - .offset = cpu_to_le32(0x2000), - .length = cpu_to_le32(0x1000), }; struct virtio_pci_notify_cap notify = { .cap.cfg_type = VIRTIO_PCI_CAP_NOTIFY_CFG, .cap.cap_len = sizeof notify, .cap.bar = modern_mem_bar, - .cap.offset = cpu_to_le32(0x3000), - .cap.length = cpu_to_le32(QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * - VIRTIO_QUEUE_MAX), .notify_off_multiplier = cpu_to_le32(QEMU_VIRTIO_PCI_QUEUE_MEM_MULT), }; /* TODO: add io access for speed */ - virtio_pci_add_mem_cap(proxy, &common); - virtio_pci_add_mem_cap(proxy, &isr); - virtio_pci_add_mem_cap(proxy, &device); - virtio_pci_add_mem_cap(proxy, ¬ify.cap); virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1); memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci", 2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX); virtio_pci_modern_regions_init(proxy); - virtio_pci_modern_region_map(proxy, &proxy->common); - virtio_pci_modern_region_map(proxy, &proxy->isr); - virtio_pci_modern_region_map(proxy, &proxy->device); - virtio_pci_modern_region_map(proxy, &proxy->notify); + virtio_pci_modern_region_map(proxy, &proxy->common, &common); + virtio_pci_modern_region_map(proxy, &proxy->isr, &isr); + virtio_pci_modern_region_map(proxy, &proxy->device, &device); + virtio_pci_modern_region_map(proxy, &proxy->notify, ¬ify.cap); pci_register_bar(&proxy->pci_dev, modern_mem_bar, PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_PREFETCH | -- cgit v1.2.3 From fc004905c5b4b7568aad50087c156a5f4dfae1a7 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:37 +0200 Subject: virtio-pci: move cap type to VirtIOPCIRegion Signed-off-by: Gerd Hoffmann Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 9 +++++---- hw/virtio/virtio-pci.h | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index f4bdd1c66b..440db10339 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1252,18 +1252,21 @@ static void virtio_pci_modern_regions_init(VirtIOPCIProxy *proxy) proxy, "virtio-pci-common", 0x1000); proxy->common.offset = 0x0; + proxy->common.type = VIRTIO_PCI_CAP_COMMON_CFG; memory_region_init_io(&proxy->isr.mr, OBJECT(proxy), &isr_ops, proxy, "virtio-pci-isr", 0x1000); proxy->isr.offset = 0x1000; + proxy->isr.type = VIRTIO_PCI_CAP_ISR_CFG; memory_region_init_io(&proxy->device.mr, OBJECT(proxy), &device_ops, virtio_bus_get_device(&proxy->bus), "virtio-pci-device", 0x1000); proxy->device.offset = 0x2000; + proxy->device.type = VIRTIO_PCI_CAP_DEVICE_CFG; memory_region_init_io(&proxy->notify.mr, OBJECT(proxy), ¬ify_ops, @@ -1272,6 +1275,7 @@ static void virtio_pci_modern_regions_init(VirtIOPCIProxy *proxy) QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX); proxy->notify.offset = 0x3000; + proxy->notify.type = VIRTIO_PCI_CAP_NOTIFY_CFG; } static void virtio_pci_modern_region_map(VirtIOPCIProxy *proxy, @@ -1282,6 +1286,7 @@ static void virtio_pci_modern_region_map(VirtIOPCIProxy *proxy, region->offset, ®ion->mr); + cap->cfg_type = region->type; cap->offset = cpu_to_le32(region->offset); cap->length = cpu_to_le32(memory_region_size(®ion->mr)); virtio_pci_add_mem_cap(proxy, cap); @@ -1337,22 +1342,18 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) if (modern) { struct virtio_pci_cap common = { - .cfg_type = VIRTIO_PCI_CAP_COMMON_CFG, .cap_len = sizeof common, .bar = modern_mem_bar, }; struct virtio_pci_cap isr = { - .cfg_type = VIRTIO_PCI_CAP_ISR_CFG, .cap_len = sizeof isr, .bar = modern_mem_bar, }; struct virtio_pci_cap device = { - .cfg_type = VIRTIO_PCI_CAP_DEVICE_CFG, .cap_len = sizeof device, .bar = modern_mem_bar, }; struct virtio_pci_notify_cap notify = { - .cap.cfg_type = VIRTIO_PCI_CAP_NOTIFY_CFG, .cap.cap_len = sizeof notify, .cap.bar = modern_mem_bar, .notify_off_multiplier = diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index f5829b07a5..ea1343ded3 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -94,6 +94,7 @@ typedef struct VirtioPCIClass { typedef struct VirtIOPCIRegion { MemoryRegion mr; uint32_t offset; + uint32_t type; } VirtIOPCIRegion; struct VirtIOPCIProxy { -- cgit v1.2.3 From cc52ea90f835aa66d431db712b22f8b15bec2e46 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:38 +0200 Subject: virtio-pci: drop identical virtio_pci_cap Now the three struct virtio_pci_caps are identical, lets drop two of them ;) Signed-off-by: Gerd Hoffmann Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 440db10339..771bbd5224 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1341,16 +1341,8 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) if (modern) { - struct virtio_pci_cap common = { - .cap_len = sizeof common, - .bar = modern_mem_bar, - }; - struct virtio_pci_cap isr = { - .cap_len = sizeof isr, - .bar = modern_mem_bar, - }; - struct virtio_pci_cap device = { - .cap_len = sizeof device, + struct virtio_pci_cap cap = { + .cap_len = sizeof cap, .bar = modern_mem_bar, }; struct virtio_pci_notify_cap notify = { @@ -1367,9 +1359,9 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) 2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX); virtio_pci_modern_regions_init(proxy); - virtio_pci_modern_region_map(proxy, &proxy->common, &common); - virtio_pci_modern_region_map(proxy, &proxy->isr, &isr); - virtio_pci_modern_region_map(proxy, &proxy->device, &device); + virtio_pci_modern_region_map(proxy, &proxy->common, &cap); + virtio_pci_modern_region_map(proxy, &proxy->isr, &cap); + virtio_pci_modern_region_map(proxy, &proxy->device, &cap); virtio_pci_modern_region_map(proxy, &proxy->notify, ¬ify.cap); pci_register_bar(&proxy->pci_dev, modern_mem_bar, PCI_BASE_ADDRESS_SPACE_MEMORY | -- cgit v1.2.3 From b6ce27a593ab39ac28baebc3045901925046bebd Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:39 +0200 Subject: virtio-pci: fill VirtIOPCIRegions early. Initialize the modern bar and the VirtIOPCIRegion fields early, in realize. Also add a size field to VirtIOPCIRegion and variables for pci bars to VirtIOPCIProxy. This allows virtio-pci subclasses to change things before the device_plugged callback applies them. virtio-vga will use that to arrange regions in a way that virtio-vga is compatible to both stdvga (in vga mode) and virtio-gpu-pci (in pci mode). Signed-off-by: Gerd Hoffmann Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 92 ++++++++++++++++++++++++++++---------------------- hw/virtio/virtio-pci.h | 4 +++ 2 files changed, 55 insertions(+), 41 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 771bbd5224..76653a7fcd 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1250,32 +1250,26 @@ static void virtio_pci_modern_regions_init(VirtIOPCIProxy *proxy) memory_region_init_io(&proxy->common.mr, OBJECT(proxy), &common_ops, proxy, - "virtio-pci-common", 0x1000); - proxy->common.offset = 0x0; - proxy->common.type = VIRTIO_PCI_CAP_COMMON_CFG; + "virtio-pci-common", + proxy->common.size); memory_region_init_io(&proxy->isr.mr, OBJECT(proxy), &isr_ops, proxy, - "virtio-pci-isr", 0x1000); - proxy->isr.offset = 0x1000; - proxy->isr.type = VIRTIO_PCI_CAP_ISR_CFG; + "virtio-pci-isr", + proxy->isr.size); memory_region_init_io(&proxy->device.mr, OBJECT(proxy), &device_ops, virtio_bus_get_device(&proxy->bus), - "virtio-pci-device", 0x1000); - proxy->device.offset = 0x2000; - proxy->device.type = VIRTIO_PCI_CAP_DEVICE_CFG; + "virtio-pci-device", + proxy->device.size); memory_region_init_io(&proxy->notify.mr, OBJECT(proxy), ¬ify_ops, virtio_bus_get_device(&proxy->bus), "virtio-pci-notify", - QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * - VIRTIO_QUEUE_MAX); - proxy->notify.offset = 0x3000; - proxy->notify.type = VIRTIO_PCI_CAP_NOTIFY_CFG; + proxy->notify.size); } static void virtio_pci_modern_region_map(VirtIOPCIProxy *proxy, @@ -1287,8 +1281,9 @@ static void virtio_pci_modern_region_map(VirtIOPCIProxy *proxy, ®ion->mr); cap->cfg_type = region->type; + cap->bar = proxy->modern_mem_bar; cap->offset = cpu_to_le32(region->offset); - cap->length = cpu_to_le32(memory_region_size(®ion->mr)); + cap->length = cpu_to_le32(region->size); virtio_pci_add_mem_cap(proxy, cap); } @@ -1303,22 +1298,6 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) uint32_t size; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - /* - * virtio pci bar layout - * - * region 0 -- virtio legacy io bar - * region 1 -- msi-x bar - * region 2+3 -- not used by virtio-pci - * region 4+5 -- virtio modern memory (64bit) bar - * - * Regions 2+3 can be used by VirtIOPCIProxy subclasses. - * virtio-vga places the vga framebuffer there. - * - */ - uint32_t legacy_io_bar = 0; - uint32_t msix_bar = 1; - uint32_t modern_mem_bar = 4; - config = proxy->pci_dev.config; if (proxy->class_code) { pci_config_set_class(config, proxy->class_code); @@ -1343,11 +1322,9 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) if (modern) { struct virtio_pci_cap cap = { .cap_len = sizeof cap, - .bar = modern_mem_bar, }; struct virtio_pci_notify_cap notify = { .cap.cap_len = sizeof notify, - .cap.bar = modern_mem_bar, .notify_off_multiplier = cpu_to_le32(QEMU_VIRTIO_PCI_QUEUE_MEM_MULT), }; @@ -1355,15 +1332,12 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) /* TODO: add io access for speed */ virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1); - memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci", - 2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * - VIRTIO_QUEUE_MAX); virtio_pci_modern_regions_init(proxy); virtio_pci_modern_region_map(proxy, &proxy->common, &cap); virtio_pci_modern_region_map(proxy, &proxy->isr, &cap); virtio_pci_modern_region_map(proxy, &proxy->device, &cap); virtio_pci_modern_region_map(proxy, &proxy->notify, ¬ify.cap); - pci_register_bar(&proxy->pci_dev, modern_mem_bar, + pci_register_bar(&proxy->pci_dev, proxy->modern_mem_bar, PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_PREFETCH | PCI_BASE_ADDRESS_MEM_TYPE_64, @@ -1371,7 +1345,8 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) } if (proxy->nvectors && - msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, msix_bar)) { + msix_init_exclusive_bar(&proxy->pci_dev, proxy->nvectors, + proxy->msix_bar)) { error_report("unable to init msix vectors to %" PRIu32, proxy->nvectors); proxy->nvectors = 0; @@ -1390,7 +1365,7 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) &virtio_pci_config_ops, proxy, "virtio-pci", size); - pci_register_bar(&proxy->pci_dev, legacy_io_bar, + pci_register_bar(&proxy->pci_dev, proxy->legacy_io_bar, PCI_BASE_ADDRESS_SPACE_IO, &proxy->bar); } @@ -1410,12 +1385,47 @@ static void virtio_pci_device_unplugged(DeviceState *d) static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) { - VirtIOPCIProxy *dev = VIRTIO_PCI(pci_dev); + VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev); VirtioPCIClass *k = VIRTIO_PCI_GET_CLASS(pci_dev); - virtio_pci_bus_new(&dev->bus, sizeof(dev->bus), dev); + /* + * virtio pci bar layout used by default. + * subclasses can re-arrange things if needed. + * + * region 0 -- virtio legacy io bar + * region 1 -- msi-x bar + * region 4+5 -- virtio modern memory (64bit) bar + * + */ + proxy->legacy_io_bar = 0; + proxy->msix_bar = 1; + proxy->modern_mem_bar = 4; + + proxy->common.offset = 0x0; + proxy->common.size = 0x1000; + proxy->common.type = VIRTIO_PCI_CAP_COMMON_CFG; + + proxy->isr.offset = 0x1000; + proxy->isr.size = 0x1000; + proxy->isr.type = VIRTIO_PCI_CAP_ISR_CFG; + + proxy->device.offset = 0x2000; + proxy->device.size = 0x1000; + proxy->device.type = VIRTIO_PCI_CAP_DEVICE_CFG; + + proxy->notify.offset = 0x3000; + proxy->notify.size = + QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * VIRTIO_QUEUE_MAX; + proxy->notify.type = VIRTIO_PCI_CAP_NOTIFY_CFG; + + /* subclasses can enforce modern, so do this unconditionally */ + memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci", + 2 * QEMU_VIRTIO_PCI_QUEUE_MEM_MULT * + VIRTIO_QUEUE_MAX); + + virtio_pci_bus_new(&proxy->bus, sizeof(proxy->bus), proxy); if (k->realize) { - k->realize(dev, errp); + k->realize(proxy, errp); } } diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index ea1343ded3..ff5ab71e76 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -94,6 +94,7 @@ typedef struct VirtioPCIClass { typedef struct VirtIOPCIRegion { MemoryRegion mr; uint32_t offset; + uint32_t size; uint32_t type; } VirtIOPCIRegion; @@ -105,6 +106,9 @@ struct VirtIOPCIProxy { VirtIOPCIRegion device; VirtIOPCIRegion notify; MemoryRegion modern_bar; + uint32_t legacy_io_bar; + uint32_t msix_bar; + uint32_t modern_mem_bar; uint32_t flags; uint32_t class_code; uint32_t nvectors; -- cgit v1.2.3 From ffaa05037134d48e3ccd7ebbf2d58db26590b96d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:40 +0200 Subject: pci: add PCI_CLASS_INPUT_* Signed-off-by: Gerd Hoffmann Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/pci/pci_ids.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index c6de71030b..49c062b8ce 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -47,6 +47,13 @@ #define PCI_CLASS_COMMUNICATION_SERIAL 0x0700 #define PCI_CLASS_COMMUNICATION_OTHER 0x0780 +#define PCI_CLASS_INPUT_KEYBOARD 0x0900 +#define PCI_CLASS_INPUT_PEN 0x0901 +#define PCI_CLASS_INPUT_MOUSE 0x0902 +#define PCI_CLASS_INPUT_SCANNER 0x0903 +#define PCI_CLASS_INPUT_GAMEPORT 0x0904 +#define PCI_CLASS_INPUT_OTHER 0x0980 + #define PCI_CLASS_PROCESSOR_CO 0x0b40 #define PCI_CLASS_PROCESSOR_POWERPC 0x0b20 -- cgit v1.2.3 From f958c8aa138718b8126a300d6faece522f7674b8 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:41 +0200 Subject: virtio-input: core code & base class [pci] This patch adds the virtio-pci support bits for virtio-input-device. Signed-off-by: Gerd Hoffmann Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 36 ++++++++++++++++++++++++++++++++++++ hw/virtio/virtio-pci.h | 14 ++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 76653a7fcd..8ec741b184 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -24,6 +24,7 @@ #include "hw/virtio/virtio-serial.h" #include "hw/virtio/virtio-scsi.h" #include "hw/virtio/virtio-balloon.h" +#include "hw/virtio/virtio-input.h" #include "hw/pci/pci.h" #include "qemu/error-report.h" #include "hw/pci/msi.h" @@ -1897,6 +1898,40 @@ static const TypeInfo virtio_rng_pci_info = { .class_init = virtio_rng_pci_class_init, }; +/* virtio-input-pci */ + +static void virtio_input_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +{ + VirtIOInputPCI *vinput = VIRTIO_INPUT_PCI(vpci_dev); + DeviceState *vdev = DEVICE(&vinput->vdev); + + qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus)); + /* force virtio-1.0 */ + vpci_dev->flags &= ~VIRTIO_PCI_FLAG_DISABLE_MODERN; + vpci_dev->flags |= VIRTIO_PCI_FLAG_DISABLE_LEGACY; + object_property_set_bool(OBJECT(vdev), true, "realized", errp); +} + +static void virtio_input_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + + k->realize = virtio_input_pci_realize; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + + pcidev_k->class_id = PCI_CLASS_INPUT_OTHER; +} + +static const TypeInfo virtio_input_pci_info = { + .name = TYPE_VIRTIO_INPUT_PCI, + .parent = TYPE_VIRTIO_PCI, + .instance_size = sizeof(VirtIOInputPCI), + .class_init = virtio_input_pci_class_init, + .abstract = true, +}; + /* virtio-pci-bus */ static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, @@ -1938,6 +1973,7 @@ static const TypeInfo virtio_pci_bus_info = { static void virtio_pci_register_types(void) { type_register_static(&virtio_rng_pci_info); + type_register_static(&virtio_input_pci_info); type_register_static(&virtio_pci_bus_info); type_register_static(&virtio_pci_info); #ifdef CONFIG_VIRTFS diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index ff5ab71e76..754971f720 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -24,6 +24,7 @@ #include "hw/virtio/virtio-balloon.h" #include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-9p.h" +#include "hw/virtio/virtio-input.h" #ifdef CONFIG_VIRTFS #include "hw/9pfs/virtio-9p.h" #endif @@ -39,6 +40,7 @@ typedef struct VirtIOSerialPCI VirtIOSerialPCI; typedef struct VirtIONetPCI VirtIONetPCI; typedef struct VHostSCSIPCI VHostSCSIPCI; typedef struct VirtIORngPCI VirtIORngPCI; +typedef struct VirtIOInputPCI VirtIOInputPCI; /* virtio-pci-bus */ @@ -234,6 +236,18 @@ struct VirtIORngPCI { VirtIORNG vdev; }; +/* + * virtio-input-pci: This extends VirtioPCIProxy. + */ +#define TYPE_VIRTIO_INPUT_PCI "virtio-input-pci" +#define VIRTIO_INPUT_PCI(obj) \ + OBJECT_CHECK(VirtIOInputPCI, (obj), TYPE_VIRTIO_INPUT_PCI) + +struct VirtIOInputPCI { + VirtIOPCIProxy parent_obj; + VirtIOInput vdev; +}; + /* Virtio ABI version, if we increment this, we break the guest driver. */ #define VIRTIO_PCI_ABI_VERSION 0 -- cgit v1.2.3 From 710e2d90da1a16807f7885d37b203ce739fdc53a Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 4 Jun 2015 12:34:42 +0200 Subject: virtio-input: emulated devices [pci] This patch adds virtio-pci support for the emulated virtio-input devices. Using them is as simple as adding "-device virtio-tablet-pci" to your command line. If you want add multiple devices but don't want waste a pci slot for each you can compose a multifunction device this way: qemu -device virtio-keyboard-pci,addr=0d.0,multifunction=on \ -device virtio-tablet-pci,addr=0d.1,multifunction=on Signed-off-by: Gerd Hoffmann Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ hw/virtio/virtio-pci.h | 13 ++++++++ 2 files changed, 97 insertions(+) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 8ec741b184..d7cf34cee9 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1900,6 +1900,12 @@ static const TypeInfo virtio_rng_pci_info = { /* virtio-input-pci */ +static Property virtio_input_hid_pci_properties[] = { + DEFINE_VIRTIO_INPUT_PROPERTIES(VirtIOInputPCI, vdev.input), + DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2), + DEFINE_PROP_END_OF_LIST(), +}; + static void virtio_input_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { VirtIOInputPCI *vinput = VIRTIO_INPUT_PCI(vpci_dev); @@ -1924,6 +1930,49 @@ static void virtio_input_pci_class_init(ObjectClass *klass, void *data) pcidev_k->class_id = PCI_CLASS_INPUT_OTHER; } +static void virtio_input_hid_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->props = virtio_input_hid_pci_properties; +} + +static void virtio_input_hid_kbd_pci_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + + pcidev_k->class_id = PCI_CLASS_INPUT_KEYBOARD; +} + +static void virtio_input_hid_mouse_pci_class_init(ObjectClass *klass, + void *data) +{ + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + + pcidev_k->class_id = PCI_CLASS_INPUT_MOUSE; +} + +static void virtio_keyboard_initfn(Object *obj) +{ + VirtIOInputHIDPCI *dev = VIRTIO_INPUT_HID_PCI(obj); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_KEYBOARD); + object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); +} + +static void virtio_mouse_initfn(Object *obj) +{ + VirtIOInputHIDPCI *dev = VIRTIO_INPUT_HID_PCI(obj); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_MOUSE); + object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); +} + +static void virtio_tablet_initfn(Object *obj) +{ + VirtIOInputHIDPCI *dev = VIRTIO_INPUT_HID_PCI(obj); + object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_TABLET); + object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL); +} + static const TypeInfo virtio_input_pci_info = { .name = TYPE_VIRTIO_INPUT_PCI, .parent = TYPE_VIRTIO_PCI, @@ -1932,6 +1981,37 @@ static const TypeInfo virtio_input_pci_info = { .abstract = true, }; +static const TypeInfo virtio_input_hid_pci_info = { + .name = TYPE_VIRTIO_INPUT_HID_PCI, + .parent = TYPE_VIRTIO_INPUT_PCI, + .instance_size = sizeof(VirtIOInputHIDPCI), + .class_init = virtio_input_hid_pci_class_init, + .abstract = true, +}; + +static const TypeInfo virtio_keyboard_pci_info = { + .name = TYPE_VIRTIO_KEYBOARD_PCI, + .parent = TYPE_VIRTIO_INPUT_HID_PCI, + .class_init = virtio_input_hid_kbd_pci_class_init, + .instance_size = sizeof(VirtIOInputHIDPCI), + .instance_init = virtio_keyboard_initfn, +}; + +static const TypeInfo virtio_mouse_pci_info = { + .name = TYPE_VIRTIO_MOUSE_PCI, + .parent = TYPE_VIRTIO_INPUT_HID_PCI, + .class_init = virtio_input_hid_mouse_pci_class_init, + .instance_size = sizeof(VirtIOInputHIDPCI), + .instance_init = virtio_mouse_initfn, +}; + +static const TypeInfo virtio_tablet_pci_info = { + .name = TYPE_VIRTIO_TABLET_PCI, + .parent = TYPE_VIRTIO_INPUT_HID_PCI, + .instance_size = sizeof(VirtIOInputHIDPCI), + .instance_init = virtio_tablet_initfn, +}; + /* virtio-pci-bus */ static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, @@ -1974,6 +2054,10 @@ static void virtio_pci_register_types(void) { type_register_static(&virtio_rng_pci_info); type_register_static(&virtio_input_pci_info); + type_register_static(&virtio_input_hid_pci_info); + type_register_static(&virtio_keyboard_pci_info); + type_register_static(&virtio_mouse_pci_info); + type_register_static(&virtio_tablet_pci_info); type_register_static(&virtio_pci_bus_info); type_register_static(&virtio_pci_info); #ifdef CONFIG_VIRTFS diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 754971f720..d962125351 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -41,6 +41,7 @@ typedef struct VirtIONetPCI VirtIONetPCI; typedef struct VHostSCSIPCI VHostSCSIPCI; typedef struct VirtIORngPCI VirtIORngPCI; typedef struct VirtIOInputPCI VirtIOInputPCI; +typedef struct VirtIOInputHIDPCI VirtIOInputHIDPCI; /* virtio-pci-bus */ @@ -248,6 +249,18 @@ struct VirtIOInputPCI { VirtIOInput vdev; }; +#define TYPE_VIRTIO_INPUT_HID_PCI "virtio-input-hid-pci" +#define TYPE_VIRTIO_KEYBOARD_PCI "virtio-keyboard-pci" +#define TYPE_VIRTIO_MOUSE_PCI "virtio-mouse-pci" +#define TYPE_VIRTIO_TABLET_PCI "virtio-tablet-pci" +#define VIRTIO_INPUT_HID_PCI(obj) \ + OBJECT_CHECK(VirtIOInputHIDPCI, (obj), TYPE_VIRTIO_INPUT_HID_PCI) + +struct VirtIOInputHIDPCI { + VirtIOPCIProxy parent_obj; + VirtIOInputHID vdev; +}; + /* Virtio ABI version, if we increment this, we break the guest driver. */ #define VIRTIO_PCI_ABI_VERSION 0 -- cgit v1.2.3 From 87108bb26ce04637980c0897caeabee8901e72c9 Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Wed, 10 Jun 2015 23:04:30 +0800 Subject: virtio-net: move qdev properties into virtio-net.c As only one place in virtio-net.c uses DEFINE_VIRTIO_NET_FEATURES, there is no need to expose it. Inline it into virtio-net.c to avoid wrongly use. Signed-off-by: Shannon Zhao Signed-off-by: Shannon Zhao Reviewed-by: Paolo Bonzini Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/net/virtio-net.c | 44 ++++++++++++++++++++++++++++++++++++++++-- include/hw/virtio/virtio-net.h | 24 ----------------------- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 49fa13f161..9281aa107c 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -1707,10 +1707,50 @@ static void virtio_net_instance_init(Object *obj) } static Property virtio_net_properties[] = { - DEFINE_VIRTIO_NET_FEATURES(VirtIONet, host_features), + DEFINE_PROP_BIT("any_layout", VirtIONet, host_features, + VIRTIO_F_ANY_LAYOUT, true), + DEFINE_PROP_BIT("csum", VirtIONet, host_features, VIRTIO_NET_F_CSUM, true), + DEFINE_PROP_BIT("guest_csum", VirtIONet, host_features, + VIRTIO_NET_F_GUEST_CSUM, true), + DEFINE_PROP_BIT("gso", VirtIONet, host_features, VIRTIO_NET_F_GSO, true), + DEFINE_PROP_BIT("guest_tso4", VirtIONet, host_features, + VIRTIO_NET_F_GUEST_TSO4, true), + DEFINE_PROP_BIT("guest_tso6", VirtIONet, host_features, + VIRTIO_NET_F_GUEST_TSO6, true), + DEFINE_PROP_BIT("guest_ecn", VirtIONet, host_features, + VIRTIO_NET_F_GUEST_ECN, true), + DEFINE_PROP_BIT("guest_ufo", VirtIONet, host_features, + VIRTIO_NET_F_GUEST_UFO, true), + DEFINE_PROP_BIT("guest_announce", VirtIONet, host_features, + VIRTIO_NET_F_GUEST_ANNOUNCE, true), + DEFINE_PROP_BIT("host_tso4", VirtIONet, host_features, + VIRTIO_NET_F_HOST_TSO4, true), + DEFINE_PROP_BIT("host_tso6", VirtIONet, host_features, + VIRTIO_NET_F_HOST_TSO6, true), + DEFINE_PROP_BIT("host_ecn", VirtIONet, host_features, + VIRTIO_NET_F_HOST_ECN, true), + DEFINE_PROP_BIT("host_ufo", VirtIONet, host_features, + VIRTIO_NET_F_HOST_UFO, true), + DEFINE_PROP_BIT("mrg_rxbuf", VirtIONet, host_features, + VIRTIO_NET_F_MRG_RXBUF, true), + DEFINE_PROP_BIT("status", VirtIONet, host_features, + VIRTIO_NET_F_STATUS, true), + DEFINE_PROP_BIT("ctrl_vq", VirtIONet, host_features, + VIRTIO_NET_F_CTRL_VQ, true), + DEFINE_PROP_BIT("ctrl_rx", VirtIONet, host_features, + VIRTIO_NET_F_CTRL_RX, true), + DEFINE_PROP_BIT("ctrl_vlan", VirtIONet, host_features, + VIRTIO_NET_F_CTRL_VLAN, true), + DEFINE_PROP_BIT("ctrl_rx_extra", VirtIONet, host_features, + VIRTIO_NET_F_CTRL_RX_EXTRA, true), + DEFINE_PROP_BIT("ctrl_mac_addr", VirtIONet, host_features, + VIRTIO_NET_F_CTRL_MAC_ADDR, true), + DEFINE_PROP_BIT("ctrl_guest_offloads", VirtIONet, host_features, + VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, true), + DEFINE_PROP_BIT("mq", VirtIONet, host_features, VIRTIO_NET_F_MQ, false), DEFINE_NIC_PROPERTIES(VirtIONet, nic_conf), DEFINE_PROP_UINT32("x-txtimer", VirtIONet, net_conf.txtimer, - TX_TIMER_INTERVAL), + TX_TIMER_INTERVAL), DEFINE_PROP_INT32("x-txburst", VirtIONet, net_conf.txburst, TX_BURST), DEFINE_PROP_STRING("tx", VirtIONet, net_conf.tx), DEFINE_PROP_END_OF_LIST(), diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index e0dbb418ad..c142b42a2f 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -109,30 +109,6 @@ typedef struct VirtIONet { #define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5 #define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0 -#define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \ - DEFINE_PROP_BIT("any_layout", _state, _field, VIRTIO_F_ANY_LAYOUT, true), \ - 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("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("guest_announce", _state, _field, VIRTIO_NET_F_GUEST_ANNOUNCE, 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), \ - DEFINE_PROP_BIT("ctrl_mac_addr", _state, _field, VIRTIO_NET_F_CTRL_MAC_ADDR, true), \ - DEFINE_PROP_BIT("ctrl_guest_offloads", _state, _field, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, true), \ - DEFINE_PROP_BIT("mq", _state, _field, VIRTIO_NET_F_MQ, false) - #define DEFINE_VIRTIO_NET_PROPERTIES(_state, _field) \ DEFINE_PROP_UINT32("x-txtimer", _state, _field.txtimer, TX_TIMER_INTERVAL),\ DEFINE_PROP_INT32("x-txburst", _state, _field.txburst, TX_BURST), \ -- cgit v1.2.3 From db58c063e159f02f0232d1557f0930fd32a6580f Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Wed, 10 Jun 2015 23:04:31 +0800 Subject: virtio-net.h: Remove unsed DEFINE_VIRTIO_NET_PROPERTIES Remove unsed DEFINE_VIRTIO_NET_PROPERTIES in virtio-net.h and delete a space typo. Signed-off-by: Shannon Zhao Signed-off-by: Shannon Zhao Reviewed-by: Paolo Bonzini Acked-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/virtio/virtio-net.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index c142b42a2f..280dacfbe9 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -107,12 +107,7 @@ typedef struct VirtIONet { * VIRTIO_NET_F_CTRL_GUEST_OFFLOADS feature bit. */ #define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5 - #define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0 - -#define DEFINE_VIRTIO_NET_PROPERTIES(_state, _field) \ - DEFINE_PROP_UINT32("x-txtimer", _state, _field.txtimer, TX_TIMER_INTERVAL),\ - DEFINE_PROP_INT32("x-txburst", _state, _field.txburst, TX_BURST), \ - DEFINE_PROP_STRING("tx", _state, _field.tx) +#define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0 void virtio_net_set_netclient_name(VirtIONet *n, const char *name, const char *type); -- cgit v1.2.3 From 0c63237a90f37fffe8a8016f24f61bb228653e86 Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Wed, 10 Jun 2015 23:04:32 +0800 Subject: virtio-scsi: move qdev properties into virtio-scsi.c As only one place in virtio-scsi.c uses DEFINE_VIRTIO_SCSI_PROPERTIES and DEFINE_VIRTIO_SCSI_FEATURES, there is no need to expose them. Inline them into virtio-scsi.c to avoid wrongly use. Signed-off-by: Shannon Zhao Signed-off-by: Shannon Zhao Reviewed-by: Paolo Bonzini Acked-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/scsi/virtio-scsi.c | 13 +++++++++++-- include/hw/virtio/virtio-scsi.h | 13 ------------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index b0dee295d8..f7d3c7c48a 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -948,8 +948,17 @@ static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp) } static Property virtio_scsi_properties[] = { - DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI, parent_obj.conf), - DEFINE_VIRTIO_SCSI_FEATURES(VirtIOSCSI, host_features), + DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues, 1), + DEFINE_PROP_UINT32("max_sectors", VirtIOSCSI, parent_obj.conf.max_sectors, + 0xFFFF), + DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSI, parent_obj.conf.cmd_per_lun, + 128), + DEFINE_PROP_BIT("any_layout", VirtIOSCSI, host_features, + VIRTIO_F_ANY_LAYOUT, true), + DEFINE_PROP_BIT("hotplug", VirtIOSCSI, host_features, + VIRTIO_SCSI_F_HOTPLUG, true), + DEFINE_PROP_BIT("param_change", VirtIOSCSI, host_features, + VIRTIO_SCSI_F_CHANGE, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index b42e7f1379..088fe9f4b9 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -141,19 +141,6 @@ typedef struct VirtIOSCSIReq { } req; } VirtIOSCSIReq; -#define DEFINE_VIRTIO_SCSI_PROPERTIES(_state, _conf_field) \ - DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \ - DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF),\ - DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128) - -#define DEFINE_VIRTIO_SCSI_FEATURES(_state, _feature_field) \ - DEFINE_PROP_BIT("any_layout", _state, _feature_field, \ - VIRTIO_F_ANY_LAYOUT, true), \ - DEFINE_PROP_BIT("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG, \ - true), \ - DEFINE_PROP_BIT("param_change", _state, _feature_field, \ - VIRTIO_SCSI_F_CHANGE, true) - typedef void (*HandleOutput)(VirtIODevice *, VirtQueue *); void virtio_scsi_common_realize(DeviceState *dev, Error **errp, -- cgit v1.2.3 From fe704809b974d8dd8e020b4d3f48ede338a886fe Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Wed, 10 Jun 2015 23:04:33 +0800 Subject: virtio-rng: move qdev properties into virtio-rng.c As only one place in virtio-rng.c uses DEFINE_VIRTIO_RNG_PROPERTIES, there is no need to expose it. Inline it into virtio-rng.c to avoid wrongly use. Signed-off-by: Shannon Zhao Signed-off-by: Shannon Zhao Reviewed-by: Paolo Bonzini Acked-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-rng.c | 8 +++++++- include/hw/virtio/virtio-rng.h | 10 ---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/hw/virtio/virtio-rng.c b/hw/virtio/virtio-rng.c index 420c39fb50..22b1d87d0e 100644 --- a/hw/virtio/virtio-rng.c +++ b/hw/virtio/virtio-rng.c @@ -219,7 +219,13 @@ static void virtio_rng_device_unrealize(DeviceState *dev, Error **errp) } static Property virtio_rng_properties[] = { - DEFINE_VIRTIO_RNG_PROPERTIES(VirtIORNG, conf), + /* Set a default rate limit of 2^47 bytes per minute or roughly 2TB/s. If + * you have an entropy source capable of generating more entropy than this + * and you can pass it through via virtio-rng, then hats off to you. Until + * then, this is unlimited for all practical purposes. + */ + DEFINE_PROP_UINT64("max-bytes", VirtIORNG, conf.max_bytes, INT64_MAX), + DEFINE_PROP_UINT32("period", VirtIORNG, conf.period_ms, 1 << 16), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/virtio/virtio-rng.h b/include/hw/virtio/virtio-rng.h index 7702ff4749..0316488733 100644 --- a/include/hw/virtio/virtio-rng.h +++ b/include/hw/virtio/virtio-rng.h @@ -46,14 +46,4 @@ typedef struct VirtIORNG { int64_t quota_remaining; } VirtIORNG; -/* Set a default rate limit of 2^47 bytes per minute or roughly 2TB/s. If - you have an entropy source capable of generating more entropy than this - and you can pass it through via virtio-rng, then hats off to you. Until - then, this is unlimited for all practical purposes. -*/ -#define DEFINE_VIRTIO_RNG_PROPERTIES(_state, _conf_field) \ - DEFINE_PROP_UINT64("max-bytes", _state, _conf_field.max_bytes, \ - INT64_MAX), \ - DEFINE_PROP_UINT32("period", _state, _conf_field.period_ms, 1 << 16) - #endif -- cgit v1.2.3 From 448777c411b80df0263eb00b9df2f829cdc7cc9b Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Wed, 10 Jun 2015 23:04:34 +0800 Subject: virtio-serial-bus: move qdev properties into virtio-serial-bus.c As only one place in virtio-serial-bus.c uses DEFINE_VIRTIO_SERIAL_PROPERTIES, there is no need to expose it. Inline it into virtio-serial-bus.c to avoid wrongly use. Signed-off-by: Shannon Zhao Signed-off-by: Shannon Zhao Reviewed-by: Paolo Bonzini Acked-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/char/virtio-serial-bus.c | 3 ++- include/hw/virtio/virtio-serial.h | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index f893523ef1..d451b22386 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -1083,7 +1083,8 @@ static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp) } static Property virtio_serial_properties[] = { - DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtIOSerial, serial), + DEFINE_PROP_UINT32("max_ports", VirtIOSerial, serial.max_virtserial_ports, + 31), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h index 18d1bccd0b..527d0bf624 100644 --- a/include/hw/virtio/virtio-serial.h +++ b/include/hw/virtio/virtio-serial.h @@ -221,7 +221,4 @@ void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle); #define VIRTIO_SERIAL(obj) \ OBJECT_CHECK(VirtIOSerial, (obj), TYPE_VIRTIO_SERIAL) -#define DEFINE_VIRTIO_SERIAL_PROPERTIES(_state, _field) \ - DEFINE_PROP_UINT32("max_ports", _state, _field.max_virtserial_ports, 31) - #endif -- cgit v1.2.3 From 83a84878da2e00b4d350bd90d6775c1f6320e7b4 Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Wed, 10 Jun 2015 23:04:35 +0800 Subject: virtio-9p-device: move qdev properties into virtio-9p-device.c As only one place in virtio-9p-device.c uses DEFINE_VIRTIO_9P_PROPERTIES, there is no need to expose it. Inline it into virtio-9p-device.c to avoid wrongly use. Signed-off-by: Shannon Zhao Signed-off-by: Shannon Zhao Reviewed-by: Paolo Bonzini Acked-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/9pfs/virtio-9p-device.c | 3 ++- hw/9pfs/virtio-9p.h | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 60f9ff9a31..3f4c9e7a02 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -140,7 +140,8 @@ out: /* virtio-9p device */ static Property virtio_9p_properties[] = { - DEFINE_VIRTIO_9P_PROPERTIES(V9fsState, fsconf), + DEFINE_PROP_STRING("mount_tag", V9fsState, fsconf.tag), + DEFINE_PROP_STRING("fsdev", V9fsState, fsconf.fsdev_id), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h index 58dafa9e14..2e7d488570 100644 --- a/hw/9pfs/virtio-9p.h +++ b/hw/9pfs/virtio-9p.h @@ -391,8 +391,4 @@ extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath, #define VIRTIO_9P(obj) \ OBJECT_CHECK(V9fsState, (obj), TYPE_VIRTIO_9P) -#define DEFINE_VIRTIO_9P_PROPERTIES(_state, _field) \ - DEFINE_PROP_STRING("mount_tag", _state, _field.tag), \ - DEFINE_PROP_STRING("fsdev", _state, _field.fsdev_id) - #endif -- cgit v1.2.3 From 21549a4642e1f1b438ffc31dd9dc35f134b10e5b Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Wed, 10 Jun 2015 23:04:36 +0800 Subject: vhost-scsi: move qdev properties into vhost-scsi.c As only one place in vhost-scsi.c uses DEFINE_VHOST_SCSI_PROPERTIES, there is no need to expose it. Inline it into vhost-scsi.c to avoid wrongly use. Signed-off-by: Shannon Zhao Signed-off-by: Shannon Zhao Reviewed-by: Paolo Bonzini Acked-by: Cornelia Huck Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/scsi/vhost-scsi.c | 9 ++++++++- include/hw/virtio/vhost-scsi.h | 9 --------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index 9c76486fa9..1941aa15c0 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -294,7 +294,14 @@ static char *vhost_scsi_get_fw_dev_path(FWPathProvider *p, BusState *bus, } static Property vhost_scsi_properties[] = { - DEFINE_VHOST_SCSI_PROPERTIES(VHostSCSI, parent_obj.conf), + DEFINE_PROP_STRING("vhostfd", VHostSCSI, parent_obj.conf.vhostfd), + DEFINE_PROP_STRING("wwpn", VHostSCSI, parent_obj.conf.wwpn), + DEFINE_PROP_UINT32("boot_tpgt", VHostSCSI, parent_obj.conf.boot_tpgt, 0), + DEFINE_PROP_UINT32("num_queues", VHostSCSI, parent_obj.conf.num_queues, 1), + DEFINE_PROP_UINT32("max_sectors", VHostSCSI, parent_obj.conf.max_sectors, + 0xFFFF), + DEFINE_PROP_UINT32("cmd_per_lun", VHostSCSI, parent_obj.conf.cmd_per_lun, + 128), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/virtio/vhost-scsi.h b/include/hw/virtio/vhost-scsi.h index dea0075626..701bfee619 100644 --- a/include/hw/virtio/vhost-scsi.h +++ b/include/hw/virtio/vhost-scsi.h @@ -66,13 +66,4 @@ typedef struct VHostSCSI { int lun; } VHostSCSI; -#define DEFINE_VHOST_SCSI_PROPERTIES(_state, _conf_field) \ - DEFINE_PROP_STRING("vhostfd", _state, _conf_field.vhostfd), \ - DEFINE_PROP_STRING("wwpn", _state, _conf_field.wwpn), \ - DEFINE_PROP_UINT32("boot_tpgt", _state, _conf_field.boot_tpgt, 0), \ - DEFINE_PROP_UINT32("num_queues", _state, _conf_field.num_queues, 1), \ - DEFINE_PROP_UINT32("max_sectors", _state, _conf_field.max_sectors, 0xFFFF), \ - DEFINE_PROP_UINT32("cmd_per_lun", _state, _conf_field.cmd_per_lun, 128) - - #endif -- cgit v1.2.3 From c96d9286a6d70452e5fa4f1e3f840715e325be95 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Thu, 11 Jun 2015 02:37:58 +0200 Subject: i386/acpi-build: more traditional _UID and _HID for PXB root buses The ACPI specification permits the _HID and _UID objects to evaluate to strings. (See "6.1.5 _HID (Hardware ID)" and "6.1.12 _UID (Unique ID)" in the ACPI v6.0 spec.) With regard to related standards, the UEFI specification can also express a device address composed from string _HID and _UID identifiers, inside the Expanded ACPI Device Path Node. (See "9.3.3 ACPI Device Path", Table 49, in the UEFI v2.5 spec.) However, numeric (integer) contents for both _HID and _UID are more traditional. They are recommended by the UEFI spec for size reasons: [...] the ACPI Device Path node is smaller and should be used if possible to reduce the size of device paths that may potentially be stored in nonvolatile storage [...] External tools support them better (for example the --acpi_hid and --acpi_uid options of "efibootmgr" only take numeric identifiers). Finally, numeric _HID and _UID contents are existing practice in the QEMU source. This patch was tested with a Fedora 20 LiveCD and a preexistent Windows Server 2012 R2 guest. Using "acpidump" and "iasl" in the Fedora guest, we get, in the SSDT: > Scope (\_SB) > { > Device (PC04) > { > Name (_UID, 0x04) // _UID: Unique ID > Name (_HID, EisaId ("PNP0A03") /* PCI Bus */) // _HID: Hardware ID Cc: Marcel Apfelbaum Cc: Michael S. Tsirkin Signed-off-by: Laszlo Ersek Reviewed-by: Marcel Apfelbaum Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index db32fd1526..8fae3b9037 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -944,9 +944,8 @@ build_ssdt(GArray *table_data, GArray *linker, scope = aml_scope("\\_SB"); dev = aml_device("PC%.02X", bus_num); - aml_append(dev, - aml_name_decl("_UID", aml_string("PC%.02X", bus_num))); - aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A03"))); + aml_append(dev, aml_name_decl("_UID", aml_int(bus_num))); + aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03"))); aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num))); if (numa_node != NUMA_NODE_UNASSIGNED) { -- cgit v1.2.3 From 4ebc736e9938a7e88ecc785734b17145bf802a56 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Thu, 11 Jun 2015 02:37:59 +0200 Subject: i386/acpi-build: fix PXB workarounds for unsupported BIOSes The patch apci: fix PXB behaviour if used with unsupported BIOS uses the following condition to see if a "PXB mem/IO chunk" has *not* been configured by the BIOS: (!range_base || range_base > range_limit) When this condition evaluates to true, said patch *omits* the corresponding entry from the _CRS. Later on the patch checks for the opposite condition (with the intent of *adding* entries to the _CRS if the "PXB mem/IO chunks" *have* been configured). Unfortunately, the condition was negated incorrectly: only the first ! operator was removed, which led to the nonsensical expression (range_base || range_base > range_limit) leading to bogus entries in the _CRS, and causing BSOD in Windows Server 2012 R2 when it runs on OVMF. The correct negative of the condition seen at the top is (range_base && range_base <= range_limit) Fix the expressions. Cc: Marcel Apfelbaum Cc: Michael S. Tsirkin Signed-off-by: Laszlo Ersek Reviewed-by: Marcel Apfelbaum Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 8fae3b9037..8e88aded9f 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -832,7 +832,7 @@ static Aml *build_crs(PCIHostState *host, * Work-around for old bioses * that do not support multiple root buses */ - if (range_base || range_base > range_limit) { + if (range_base && range_base <= range_limit) { aml_append(crs, aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, AML_ENTIRE_RANGE, @@ -853,7 +853,7 @@ static Aml *build_crs(PCIHostState *host, * Work-around for old bioses * that do not support multiple root buses */ - if (range_base || range_base > range_limit) { + if (range_base && range_base <= range_limit) { aml_append(crs, aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, AML_NON_CACHEABLE, @@ -864,7 +864,7 @@ static Aml *build_crs(PCIHostState *host, 0, range_limit - range_base + 1)); crs_range_insert(mem_ranges, range_base, range_limit); - } + } range_base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); @@ -875,7 +875,7 @@ static Aml *build_crs(PCIHostState *host, * Work-around for old bioses * that do not support multiple root buses */ - if (range_base || range_base > range_limit) { + if (range_base && range_base <= range_limit) { aml_append(crs, aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, AML_NON_CACHEABLE, -- cgit v1.2.3