diff options
Diffstat (limited to 'hw')
| -rw-r--r-- | hw/s390x/s390-virtio-ccw.c | 17 | ||||
| -rw-r--r-- | hw/s390x/virtio-ccw.c | 50 | ||||
| -rw-r--r-- | hw/s390x/virtio-ccw.h | 3 | ||||
| -rw-r--r-- | hw/vfio/pci.c | 4 | ||||
| -rw-r--r-- | hw/virtio/virtio-bus.c | 9 | ||||
| -rw-r--r-- | hw/virtio/virtio-pci.c | 36 | ||||
| -rw-r--r-- | hw/virtio/virtio-pci.h | 5 |
7 files changed, 99 insertions, 25 deletions
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index a63b4e8c61..e340eab36b 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -193,6 +193,7 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); s390mc->ri_allowed = true; + s390mc->cpu_model_allowed = true; mc->init = ccw_init; mc->reset = s390_machine_reset; mc->hot_add_cpu = s390_hot_add_cpu; @@ -258,6 +259,19 @@ bool ri_allowed(void) return 0; } +bool cpu_model_allowed(void) +{ + MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); + if (object_class_dynamic_cast(OBJECT_CLASS(mc), + TYPE_S390_CCW_MACHINE)) { + S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); + + return s390mc->cpu_model_allowed; + } + /* allow CPU model qmp queries with the "none" machine */ + return true; +} + static inline void s390_machine_initfn(Object *obj) { object_property_add_bool(obj, "aes-key-wrap", @@ -397,6 +411,9 @@ static void ccw_machine_2_7_instance_options(MachineState *machine) static void ccw_machine_2_7_class_options(MachineClass *mc) { + S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc); + + s390mc->cpu_model_allowed = false; ccw_machine_2_8_class_options(mc); SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_7); } diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 96789569a7..ee136ab940 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -455,6 +455,26 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) } } break; + case CCW_CMD_READ_STATUS: + if (check_len) { + if (ccw.count != sizeof(status)) { + ret = -EINVAL; + break; + } + } else if (ccw.count < sizeof(status)) { + /* Can't execute command. */ + ret = -EINVAL; + break; + } + if (!ccw.cda) { + ret = -EFAULT; + } else { + address_space_stb(&address_space_memory, ccw.cda, vdev->status, + MEMTXATTRS_UNSPECIFIED, NULL); + sch->curr_status.scsw.count = ccw.count - sizeof(vdev->status);; + ret = 0; + } + break; case CCW_CMD_WRITE_STATUS: if (check_len) { if (ccw.count != sizeof(status)) { @@ -1261,6 +1281,16 @@ static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f) return 0; } +static void virtio_ccw_pre_plugged(DeviceState *d, Error **errp) +{ + VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); + VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); + + if (dev->max_rev >= 1) { + virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1); + } +} + /* This is called by virtio-bus just after the device is plugged. */ static void virtio_ccw_device_plugged(DeviceState *d, Error **errp) { @@ -1270,6 +1300,10 @@ static void virtio_ccw_device_plugged(DeviceState *d, Error **errp) SubchDev *sch = ccw_dev->sch; int n = virtio_get_num_queues(vdev); + if (!virtio_has_feature(vdev->host_features, VIRTIO_F_VERSION_1)) { + dev->max_rev = 0; + } + if (virtio_get_num_queues(vdev) > VIRTIO_CCW_QUEUE_MAX) { error_setg(errp, "The number of virtqueues %d " "exceeds ccw limit %d", n, @@ -1283,25 +1317,11 @@ static void virtio_ccw_device_plugged(DeviceState *d, Error **errp) sch->id.cu_model = virtio_bus_get_vdev_id(&dev->bus); - if (dev->max_rev >= 1) { - virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1); - } css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, d->hotplugged, 1); } -static void virtio_ccw_post_plugged(DeviceState *d, Error **errp) -{ - VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); - VirtIODevice *vdev = virtio_bus_get_device(&dev->bus); - - if (!virtio_host_has_feature(vdev, VIRTIO_F_VERSION_1)) { - /* A backend didn't support modern virtio. */ - dev->max_rev = 0; - } -} - static void virtio_ccw_device_unplugged(DeviceState *d) { VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); @@ -1593,8 +1613,8 @@ static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data) k->load_queue = virtio_ccw_load_queue; k->save_config = virtio_ccw_save_config; k->load_config = virtio_ccw_load_config; + k->pre_plugged = virtio_ccw_pre_plugged; k->device_plugged = virtio_ccw_device_plugged; - k->post_plugged = virtio_ccw_post_plugged; k->device_unplugged = virtio_ccw_device_unplugged; k->ioeventfd_started = virtio_ccw_ioeventfd_started; k->ioeventfd_set_started = virtio_ccw_ioeventfd_set_started; diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h index b58ab21d4c..565094e4fb 100644 --- a/hw/s390x/virtio-ccw.h +++ b/hw/s390x/virtio-ccw.h @@ -45,6 +45,7 @@ #define CCW_CMD_SET_IND 0x43 #define CCW_CMD_SET_CONF_IND 0x53 #define CCW_CMD_READ_VQ_CONF 0x32 +#define CCW_CMD_READ_STATUS 0x72 #define CCW_CMD_SET_IND_ADAPTER 0x73 #define CCW_CMD_SET_VIRTIO_REV 0x83 @@ -98,7 +99,7 @@ struct VirtioCcwDevice { }; /* The maximum virtio revision we support. */ -#define VIRTIO_CCW_MAX_REV 1 +#define VIRTIO_CCW_MAX_REV 2 static inline int virtio_ccw_rev_max(VirtioCcwDevice *dev) { return dev->max_rev; diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 7bfa17ce38..a5a620a0c4 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -496,7 +496,9 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr, vfio_update_kvm_msi_virq(vector, *msg, pdev); } } else { - vfio_add_kvm_msi_virq(vdev, vector, nr, true); + if (msg) { + vfio_add_kvm_msi_virq(vdev, vector, nr, true); + } } /* diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c index 14927935ae..11f65bd225 100644 --- a/hw/virtio/virtio-bus.c +++ b/hw/virtio/virtio-bus.c @@ -49,16 +49,17 @@ void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp) DPRINTF("%s: plug device.\n", qbus->name); - if (klass->device_plugged != NULL) { - klass->device_plugged(qbus->parent, errp); + if (klass->pre_plugged != NULL) { + klass->pre_plugged(qbus->parent, errp); } /* Get the features of the plugged device. */ assert(vdc->get_features != NULL); vdev->host_features = vdc->get_features(vdev, vdev->host_features, errp); - if (klass->post_plugged != NULL) { - klass->post_plugged(qbus->parent, errp); + + if (klass->device_plugged != NULL) { + klass->device_plugged(qbus->parent, errp); } } diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index dde71a5965..2d60a005b6 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1576,18 +1576,48 @@ static void virtio_pci_modern_io_region_unmap(VirtIOPCIProxy *proxy, ®ion->mr); } +static void virtio_pci_pre_plugged(DeviceState *d, Error **errp) +{ + VirtIOPCIProxy *proxy = VIRTIO_PCI(d); + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + + if (virtio_pci_modern(proxy)) { + virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1); + } + + virtio_add_feature(&vdev->host_features, VIRTIO_F_BAD_FEATURE); +} + /* This is called by virtio-bus just after the device is plugged. */ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) { VirtIOPCIProxy *proxy = VIRTIO_PCI(d); VirtioBusState *bus = &proxy->bus; bool legacy = virtio_pci_legacy(proxy); - bool modern = virtio_pci_modern(proxy); + bool modern; bool modern_pio = proxy->flags & VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY; uint8_t *config; uint32_t size; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + /* + * Virtio capabilities present without + * VIRTIO_F_VERSION_1 confuses guests + */ + if (!virtio_has_feature(vdev->host_features, VIRTIO_F_VERSION_1)) { + virtio_pci_disable_modern(proxy); + + if (!legacy) { + error_setg(errp, "Device doesn't support modern mode, and legacy" + " mode is disabled"); + error_append_hint(errp, "Set disable-legacy to off\n"); + + return; + } + } + + modern = virtio_pci_modern(proxy); + config = proxy->pci_dev.config; if (proxy->class_code) { pci_config_set_class(config, proxy->class_code); @@ -1629,7 +1659,6 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) struct virtio_pci_cfg_cap *cfg_mask; - virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1); virtio_pci_modern_regions_init(proxy); virtio_pci_modern_mem_region_map(proxy, &proxy->common, &cap); @@ -1694,8 +1723,6 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp) if (!kvm_has_many_ioeventfds()) { proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD; } - - virtio_add_feature(&vdev->host_features, VIRTIO_F_BAD_FEATURE); } static void virtio_pci_device_unplugged(DeviceState *d) @@ -2508,6 +2535,7 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data) k->query_guest_notifiers = virtio_pci_query_guest_notifiers; k->set_guest_notifiers = virtio_pci_set_guest_notifiers; k->vmstate_change = virtio_pci_vmstate_change; + k->pre_plugged = virtio_pci_pre_plugged; k->device_plugged = virtio_pci_device_plugged; k->device_unplugged = virtio_pci_device_unplugged; k->query_nvectors = virtio_pci_query_nvectors; diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 0698157b32..541cbdbc2b 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -181,6 +181,11 @@ static inline void virtio_pci_force_virtio_1(VirtIOPCIProxy *proxy) proxy->disable_legacy = ON_OFF_AUTO_ON; } +static inline void virtio_pci_disable_modern(VirtIOPCIProxy *proxy) +{ + proxy->disable_modern = true; +} + /* * virtio-scsi-pci: This extends VirtioPCIProxy. */ |