diff options
41 files changed, 691 insertions, 304 deletions
diff --git a/configure b/configure index b18aa9ebd5..1f0f485768 100755 --- a/configure +++ b/configure @@ -1556,6 +1556,17 @@ if test "$static" = "yes" ; then fi fi +# Unconditional check for compiler __thread support + cat > $TMPC << EOF +static __thread int tls_var; +int main(void) { return tls_var; } +EOF + +if ! compile_prog "-Werror" "" ; then + error_exit "Your compiler does not support the __thread specifier for " \ + "Thread-Local Storage (TLS). Please upgrade to a version that does." +fi + if test "$pie" = ""; then case "$cpu-$targetos" in i386-Linux|x86_64-Linux|x32-Linux|i386-OpenBSD|x86_64-OpenBSD) diff --git a/exec.c b/exec.c index ae37b98e8c..e19ab22cd6 100644 --- a/exec.c +++ b/exec.c @@ -373,6 +373,7 @@ static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write) return false; } +/* Called from RCU critical section */ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, hwaddr *xlat, hwaddr *plen, bool is_write) @@ -381,7 +382,6 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, MemoryRegionSection *section; MemoryRegion *mr; - rcu_read_lock(); for (;;) { AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch); section = address_space_translate_internal(d, addr, &addr, plen, true); @@ -409,7 +409,6 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, } *xlat = addr; - rcu_read_unlock(); return mr; } @@ -2329,6 +2328,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, MemoryRegion *mr; MemTxResult result = MEMTX_OK; + rcu_read_lock(); while (len > 0) { l = len; mr = address_space_translate(as, addr, &addr1, &l, is_write); @@ -2415,6 +2415,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, buf += l; addr += l; } + rcu_read_unlock(); return result; } @@ -2452,6 +2453,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as, hwaddr addr1; MemoryRegion *mr; + rcu_read_lock(); while (len > 0) { l = len; mr = address_space_translate(as, addr, &addr1, &l, true); @@ -2477,6 +2479,7 @@ static inline void cpu_physical_memory_write_rom_internal(AddressSpace *as, buf += l; addr += l; } + rcu_read_unlock(); } /* used for ROM loading : can write in RAM and ROM */ @@ -2585,6 +2588,7 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_ MemoryRegion *mr; hwaddr l, xlat; + rcu_read_lock(); while (len > 0) { l = len; mr = address_space_translate(as, addr, &xlat, &l, is_write); @@ -2598,6 +2602,7 @@ bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_ len -= l; addr += l; } + rcu_read_unlock(); return true; } @@ -2624,9 +2629,12 @@ void *address_space_map(AddressSpace *as, } l = len; + rcu_read_lock(); mr = address_space_translate(as, addr, &xlat, &l, is_write); + if (!memory_access_is_direct(mr, is_write)) { if (atomic_xchg(&bounce.in_use, true)) { + rcu_read_unlock(); return NULL; } /* Avoid unbounded allocations */ @@ -2642,6 +2650,7 @@ void *address_space_map(AddressSpace *as, bounce.buffer, l); } + rcu_read_unlock(); *plen = l; return bounce.buffer; } @@ -2665,6 +2674,7 @@ void *address_space_map(AddressSpace *as, } memory_region_ref(mr); + rcu_read_unlock(); *plen = done; return qemu_ram_ptr_length(raddr + base, plen); } @@ -2728,6 +2738,7 @@ static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr, hwaddr addr1; MemTxResult r; + rcu_read_lock(); mr = address_space_translate(as, addr, &addr1, &l, false); if (l < 4 || !memory_access_is_direct(mr, false)) { /* I/O case */ @@ -2762,6 +2773,7 @@ static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr, if (result) { *result = r; } + rcu_read_unlock(); return val; } @@ -2814,6 +2826,7 @@ static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr, hwaddr addr1; MemTxResult r; + rcu_read_lock(); mr = address_space_translate(as, addr, &addr1, &l, false); if (l < 8 || !memory_access_is_direct(mr, false)) { @@ -2849,6 +2862,7 @@ static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr, if (result) { *result = r; } + rcu_read_unlock(); return val; } @@ -2921,6 +2935,7 @@ static inline uint32_t address_space_lduw_internal(AddressSpace *as, hwaddr addr1; MemTxResult r; + rcu_read_lock(); mr = address_space_translate(as, addr, &addr1, &l, false); if (l < 2 || !memory_access_is_direct(mr, false)) { @@ -2956,6 +2971,7 @@ static inline uint32_t address_space_lduw_internal(AddressSpace *as, if (result) { *result = r; } + rcu_read_unlock(); return val; } @@ -3007,6 +3023,7 @@ void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val, hwaddr addr1; MemTxResult r; + rcu_read_lock(); mr = address_space_translate(as, addr, &addr1, &l, true); if (l < 4 || !memory_access_is_direct(mr, true)) { @@ -3029,6 +3046,7 @@ void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val, if (result) { *result = r; } + rcu_read_unlock(); } void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val) @@ -3049,6 +3067,7 @@ static inline void address_space_stl_internal(AddressSpace *as, hwaddr addr1; MemTxResult r; + rcu_read_lock(); mr = address_space_translate(as, addr, &addr1, &l, true); if (l < 4 || !memory_access_is_direct(mr, true)) { @@ -3083,6 +3102,7 @@ static inline void address_space_stl_internal(AddressSpace *as, if (result) { *result = r; } + rcu_read_unlock(); } void address_space_stl(AddressSpace *as, hwaddr addr, uint32_t val, @@ -3152,6 +3172,7 @@ static inline void address_space_stw_internal(AddressSpace *as, hwaddr addr1; MemTxResult r; + rcu_read_lock(); mr = address_space_translate(as, addr, &addr1, &l, true); if (l < 2 || !memory_access_is_direct(mr, true)) { #if defined(TARGET_WORDS_BIGENDIAN) @@ -3185,6 +3206,7 @@ static inline void address_space_stw_internal(AddressSpace *as, if (result) { *result = r; } + rcu_read_unlock(); } void address_space_stw(AddressSpace *as, hwaddr addr, uint32_t val, @@ -3322,12 +3344,15 @@ bool cpu_physical_memory_is_io(hwaddr phys_addr) { MemoryRegion*mr; hwaddr l = 1; + bool res; + rcu_read_lock(); mr = address_space_translate(&address_space_memory, phys_addr, &phys_addr, &l, false); - return !(memory_region_is_ram(mr) || - memory_region_is_romd(mr)); + res = !(memory_region_is_ram(mr) || memory_region_is_romd(mr)); + rcu_read_unlock(); + return res; } void qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque) diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index d38d24b814..d595d63a51 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -233,11 +233,10 @@ static void apic_reset_common(DeviceState *dev) { APICCommonState *s = APIC_COMMON(dev); APICCommonClass *info = APIC_COMMON_GET_CLASS(s); - bool bsp; + uint32_t bsp; - bsp = cpu_is_bsp(s->cpu); - s->apicbase = APIC_DEFAULT_ADDRESS | - (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE; + bsp = s->apicbase & MSR_IA32_APICBASE_BSP; + s->apicbase = APIC_DEFAULT_ADDRESS | bsp | MSR_IA32_APICBASE_ENABLE; s->vapic_paddr = 0; info->vapic_base_update(s); diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index c27f8a531b..4f69cbbb70 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -77,10 +77,18 @@ void s390_virtio_reset_idx(VirtIOS390Device *dev) VIRTIO_VRING_AVAIL_IDX_OFFS; address_space_stw(&address_space_memory, idx_addr, 0, MEMTXATTRS_UNSPECIFIED, NULL); + idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) + + virtio_queue_get_avail_size(dev->vdev, i); + address_space_stw(&address_space_memory, idx_addr, 0, + MEMTXATTRS_UNSPECIFIED, NULL); idx_addr = virtio_queue_get_used_addr(dev->vdev, i) + VIRTIO_VRING_USED_IDX_OFFS; address_space_stw(&address_space_memory, idx_addr, 0, MEMTXATTRS_UNSPECIFIED, NULL); + idx_addr = virtio_queue_get_used_addr(dev->vdev, i) + + virtio_queue_get_used_size(dev->vdev, i); + address_space_stw(&address_space_memory, idx_addr, 0, + MEMTXATTRS_UNSPECIFIED, NULL); } } @@ -530,7 +538,6 @@ static unsigned virtio_s390_get_features(DeviceState *d) /**************** S390 Virtio Bus Device Descriptions *******************/ static Property s390_virtio_net_properties[] = { - DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features), DEFINE_VIRTIO_NET_FEATURES(VirtIOS390Device, host_features), DEFINE_PROP_END_OF_LIST(), }; @@ -592,18 +599,12 @@ static const TypeInfo s390_virtio_serial = { .class_init = s390_virtio_serial_class_init, }; -static Property s390_virtio_rng_properties[] = { - DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features), - DEFINE_PROP_END_OF_LIST(), -}; - static void s390_virtio_rng_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); k->realize = s390_virtio_rng_realize; - dc->props = s390_virtio_rng_properties; set_bit(DEVICE_CATEGORY_MISC, dc->categories); } @@ -632,10 +633,16 @@ static void s390_virtio_busdev_reset(DeviceState *dev) virtio_reset(_dev->vdev); } +static Property virtio_s390_properties[] = { + DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features), + DEFINE_PROP_END_OF_LIST(), +}; + static void virtio_s390_device_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + dc->props = virtio_s390_properties; dc->realize = s390_virtio_busdev_realize; dc->bus_type = TYPE_S390_VIRTIO_BUS; dc->reset = s390_virtio_busdev_reset; @@ -651,7 +658,6 @@ static const TypeInfo virtio_s390_device_info = { }; static Property s390_virtio_scsi_properties[] = { - DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features), DEFINE_VIRTIO_SCSI_FEATURES(VirtIOS390Device, host_features), DEFINE_PROP_END_OF_LIST(), }; @@ -675,18 +681,12 @@ static const TypeInfo s390_virtio_scsi = { }; #ifdef CONFIG_VHOST_SCSI -static Property s390_vhost_scsi_properties[] = { - DEFINE_VIRTIO_COMMON_FEATURES(VirtIOS390Device, host_features), - DEFINE_PROP_END_OF_LIST(), -}; - static void s390_vhost_scsi_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass); k->realize = s390_vhost_scsi_realize; - dc->props = s390_vhost_scsi_properties; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); } diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c index 3a1b9ee2d0..59750dbfcd 100644 --- a/hw/s390x/s390-virtio.c +++ b/hw/s390x/s390-virtio.c @@ -77,6 +77,16 @@ static int s390_virtio_hcall_notify(const uint64_t *args) if (mem > ram_size) { VirtIOS390Device *dev = s390_virtio_bus_find_vring(s390_bus, mem, &i); if (dev) { + /* + * Older kernels will use the virtqueue before setting DRIVER_OK. + * In this case the feature bits are not yet up to date, meaning + * that several funny things can happen, e.g. the guest thinks + * EVENT_IDX is on and QEMU thinks it is off. Let's force a feature + * and status sync. + */ + if (!(dev->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) { + s390_virtio_device_update_status(dev); + } virtio_queue_notify(dev->vdev, i); } else { r = -EINVAL; diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index c1d8288b71..430cc6f017 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -642,8 +642,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) return ret; } -static void virtio_ccw_device_realize(VirtioCcwDevice *dev, - VirtIODevice *vdev, Error **errp) +static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp) { unsigned int cssid = 0; unsigned int ssid = 0; @@ -653,7 +652,8 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, bool found = false; SubchDev *sch; int num; - DeviceState *parent = DEVICE(dev); + Error *err = NULL; + VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev); sch = g_malloc0(sizeof(SubchDev)); @@ -766,17 +766,16 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, memset(&sch->id, 0, sizeof(SenseId)); sch->id.reserved = 0xff; sch->id.cu_type = VIRTIO_CCW_CU_TYPE; - sch->id.cu_model = vdev->device_id; - - /* Only the first 32 feature bits are used. */ - dev->host_features[0] = virtio_bus_get_vdev_features(&dev->bus, - dev->host_features[0]); - virtio_add_feature(&dev->host_features[0], VIRTIO_F_NOTIFY_ON_EMPTY); - virtio_add_feature(&dev->host_features[0], VIRTIO_F_BAD_FEATURE); + if (k->realize) { + k->realize(dev, &err); + } + if (err) { + error_propagate(errp, err); + css_subch_assign(cssid, ssid, schid, devno, NULL); + goto out_err; + } - css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, - parent->hotplugged, 1); return; out_err: @@ -813,10 +812,7 @@ static void virtio_ccw_net_realize(VirtioCcwDevice *ccw_dev, Error **errp) object_property_set_bool(OBJECT(vdev), true, "realized", &err); if (err) { error_propagate(errp, err); - return; } - - virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp); } static void virtio_ccw_net_instance_init(Object *obj) @@ -839,10 +835,7 @@ static void virtio_ccw_blk_realize(VirtioCcwDevice *ccw_dev, Error **errp) object_property_set_bool(OBJECT(vdev), true, "realized", &err); if (err) { error_propagate(errp, err); - return; } - - virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp); } static void virtio_ccw_blk_instance_init(Object *obj) @@ -879,10 +872,7 @@ static void virtio_ccw_serial_realize(VirtioCcwDevice *ccw_dev, Error **errp) object_property_set_bool(OBJECT(vdev), true, "realized", &err); if (err) { error_propagate(errp, err); - return; } - - virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp); } @@ -904,10 +894,7 @@ static void virtio_ccw_balloon_realize(VirtioCcwDevice *ccw_dev, Error **errp) object_property_set_bool(OBJECT(vdev), true, "realized", &err); if (err) { error_propagate(errp, err); - return; } - - virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp); } static void balloon_ccw_stats_get_all(Object *obj, struct Visitor *v, @@ -972,10 +959,7 @@ static void virtio_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp) object_property_set_bool(OBJECT(vdev), true, "realized", &err); if (err) { error_propagate(errp, err); - return; } - - virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp); } static void virtio_ccw_scsi_instance_init(Object *obj) @@ -999,10 +983,7 @@ static void vhost_ccw_scsi_realize(VirtioCcwDevice *ccw_dev, Error **errp) object_property_set_bool(OBJECT(vdev), true, "realized", &err); if (err) { error_propagate(errp, err); - return; } - - virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp); } static void vhost_ccw_scsi_instance_init(Object *obj) @@ -1030,8 +1011,6 @@ static void virtio_ccw_rng_realize(VirtioCcwDevice *ccw_dev, Error **errp) object_property_set_link(OBJECT(dev), OBJECT(dev->vdev.conf.rng), "rng", NULL); - - virtio_ccw_device_realize(ccw_dev, VIRTIO_DEVICE(vdev), errp); } /* DeviceState to VirtioCcwDevice. Note: used on datapath, @@ -1434,6 +1413,30 @@ static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f) return 0; } +/* This is called by virtio-bus just after the device is plugged. */ +static void virtio_ccw_device_plugged(DeviceState *d) +{ + VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); + SubchDev *sch = dev->sch; + + sch->id.cu_model = virtio_bus_get_vdev_id(&dev->bus); + + /* Only the first 32 feature bits are used. */ + virtio_add_feature(&dev->host_features[0], VIRTIO_F_NOTIFY_ON_EMPTY); + virtio_add_feature(&dev->host_features[0], VIRTIO_F_BAD_FEATURE); + dev->host_features[0] = virtio_bus_get_vdev_features(&dev->bus, + dev->host_features[0]); + + css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, + d->hotplugged, 1); +} + +static void virtio_ccw_device_unplugged(DeviceState *d) +{ + VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d); + + virtio_ccw_stop_ioeventfd(dev); +} /**************** Virtio-ccw Bus Device Descriptions *******************/ static Property virtio_ccw_net_properties[] = { @@ -1640,10 +1643,9 @@ static const TypeInfo virtio_ccw_rng = { static void virtio_ccw_busdev_realize(DeviceState *dev, Error **errp) { VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev; - VirtIOCCWDeviceClass *_info = VIRTIO_CCW_DEVICE_GET_CLASS(dev); virtio_ccw_bus_new(&_dev->bus, sizeof(_dev->bus), _dev); - _info->realize(_dev, errp); + virtio_ccw_device_realize(_dev, errp); } static int virtio_ccw_busdev_exit(DeviceState *dev) @@ -1759,6 +1761,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->device_plugged = virtio_ccw_device_plugged; + k->device_unplugged = virtio_ccw_device_unplugged; } static const TypeInfo virtio_ccw_bus_info = { diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c index 67deffebcf..f092bb8496 100644 --- a/hw/usb/dev-audio.c +++ b/hw/usb/dev-audio.c @@ -361,6 +361,9 @@ typedef struct USBAudioState { uint32_t buffer; } USBAudioState; +#define TYPE_USB_AUDIO "usb-audio" +#define USB_AUDIO(obj) OBJECT_CHECK(USBAudioState, (obj), TYPE_USB_AUDIO) + static void output_callback(void *opaque, int avail) { USBAudioState *s = opaque; @@ -506,7 +509,7 @@ static void usb_audio_handle_control(USBDevice *dev, USBPacket *p, int request, int value, int index, int length, uint8_t *data) { - USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev); + USBAudioState *s = USB_AUDIO(dev); int ret = 0; if (s->debug) { @@ -565,7 +568,7 @@ fail: static void usb_audio_set_interface(USBDevice *dev, int iface, int old, int value) { - USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev); + USBAudioState *s = USB_AUDIO(dev); if (iface == 1) { usb_audio_set_output_altset(s, value); @@ -574,7 +577,7 @@ static void usb_audio_set_interface(USBDevice *dev, int iface, static void usb_audio_handle_reset(USBDevice *dev) { - USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev); + USBAudioState *s = USB_AUDIO(dev); if (s->debug) { fprintf(stderr, "usb-audio: reset\n"); @@ -615,7 +618,7 @@ static void usb_audio_handle_data(USBDevice *dev, USBPacket *p) static void usb_audio_handle_destroy(USBDevice *dev) { - USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev); + USBAudioState *s = USB_AUDIO(dev); if (s->debug) { fprintf(stderr, "usb-audio: destroy\n"); @@ -630,12 +633,12 @@ static void usb_audio_handle_destroy(USBDevice *dev) static void usb_audio_realize(USBDevice *dev, Error **errp) { - USBAudioState *s = DO_UPCAST(USBAudioState, dev, dev); + USBAudioState *s = USB_AUDIO(dev); usb_desc_create_serial(dev); usb_desc_init(dev); s->dev.opaque = s; - AUD_register_card("usb-audio", &s->card); + AUD_register_card(TYPE_USB_AUDIO, &s->card); s->out.altset = ALTSET_OFF; s->out.mute = false; @@ -647,14 +650,14 @@ static void usb_audio_realize(USBDevice *dev, Error **errp) s->out.as.endianness = 0; streambuf_init(&s->out.buf, s->buffer); - s->out.voice = AUD_open_out(&s->card, s->out.voice, "usb-audio", + s->out.voice = AUD_open_out(&s->card, s->out.voice, TYPE_USB_AUDIO, s, output_callback, &s->out.as); AUD_set_volume_out(s->out.voice, s->out.mute, s->out.vol[0], s->out.vol[1]); AUD_set_active_out(s->out.voice, 0); } static const VMStateDescription vmstate_usb_audio = { - .name = "usb-audio", + .name = TYPE_USB_AUDIO, .unmigratable = 1, }; @@ -684,7 +687,7 @@ static void usb_audio_class_init(ObjectClass *klass, void *data) } static const TypeInfo usb_audio_info = { - .name = "usb-audio", + .name = TYPE_USB_AUDIO, .parent = TYPE_USB_DEVICE, .instance_size = sizeof(USBAudioState), .class_init = usb_audio_class_init, @@ -693,7 +696,7 @@ static const TypeInfo usb_audio_info = { static void usb_audio_register_types(void) { type_register_static(&usb_audio_info); - usb_legacy_register("usb-audio", "audio", NULL); + usb_legacy_register(TYPE_USB_AUDIO, "audio", NULL); } type_init(usb_audio_register_types) diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c index 9bf673057a..b19ec76b00 100644 --- a/hw/usb/dev-bluetooth.c +++ b/hw/usb/dev-bluetooth.c @@ -49,6 +49,9 @@ struct USBBtState { } outcmd, outacl, outsco; }; +#define TYPE_USB_BT "usb-bt-dongle" +#define USB_BT(obj) OBJECT_CHECK(struct USBBtState, (obj), TYPE_USB_BT) + #define USB_EVT_EP 1 #define USB_ACL_EP 2 #define USB_SCO_EP 3 @@ -503,7 +506,7 @@ static void usb_bt_handle_destroy(USBDevice *dev) static void usb_bt_realize(USBDevice *dev, Error **errp) { - struct USBBtState *s = DO_UPCAST(struct USBBtState, dev, dev); + struct USBBtState *s = USB_BT(dev); usb_desc_create_serial(dev); usb_desc_init(dev); @@ -523,7 +526,7 @@ static USBDevice *usb_bt_init(USBBus *bus, const char *cmdline) USBDevice *dev; struct USBBtState *s; HCIInfo *hci; - const char *name = "usb-bt-dongle"; + const char *name = TYPE_USB_BT; if (*cmdline) { hci = hci_init(cmdline); @@ -534,7 +537,7 @@ static USBDevice *usb_bt_init(USBBus *bus, const char *cmdline) return NULL; dev = usb_create(bus, name); - s = DO_UPCAST(struct USBBtState, dev, dev); + s = USB_BT(dev); s->hci = hci; return dev; } @@ -561,7 +564,7 @@ static void usb_bt_class_initfn(ObjectClass *klass, void *data) } static const TypeInfo bt_info = { - .name = "usb-bt-dongle", + .name = TYPE_USB_BT, .parent = TYPE_USB_DEVICE, .instance_size = sizeof(struct USBBtState), .class_init = usb_bt_class_initfn, @@ -570,7 +573,7 @@ static const TypeInfo bt_info = { static void usb_bt_register_types(void) { type_register_static(&bt_info); - usb_legacy_register("usb-bt-dongle", "bt", usb_bt_init); + usb_legacy_register(TYPE_USB_BT, "bt", usb_bt_init); } type_init(usb_bt_register_types) diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c index 507c9663c5..2e7dcd96cb 100644 --- a/hw/usb/dev-hid.c +++ b/hw/usb/dev-hid.c @@ -51,6 +51,9 @@ typedef struct USBHIDState { uint32_t head; } USBHIDState; +#define TYPE_USB_HID "usb-hid" +#define USB_HID(obj) OBJECT_CHECK(USBHIDState, (obj), TYPE_USB_HID) + enum { STR_MANUFACTURER = 1, STR_PRODUCT_MOUSE, @@ -564,7 +567,7 @@ static void usb_hid_changed(HIDState *hs) static void usb_hid_handle_reset(USBDevice *dev) { - USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); + USBHIDState *us = USB_HID(dev); hid_reset(&us->hid); } @@ -572,7 +575,7 @@ static void usb_hid_handle_reset(USBDevice *dev) static void usb_hid_handle_control(USBDevice *dev, USBPacket *p, int request, int value, int index, int length, uint8_t *data) { - USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); + USBHIDState *us = USB_HID(dev); HIDState *hs = &us->hid; int ret; @@ -651,7 +654,7 @@ static void usb_hid_handle_control(USBDevice *dev, USBPacket *p, static void usb_hid_handle_data(USBDevice *dev, USBPacket *p) { - USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); + USBHIDState *us = USB_HID(dev); HIDState *hs = &us->hid; uint8_t buf[p->iov.size]; int len = 0; @@ -687,7 +690,7 @@ static void usb_hid_handle_data(USBDevice *dev, USBPacket *p) static void usb_hid_handle_destroy(USBDevice *dev) { - USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); + USBHIDState *us = USB_HID(dev); hid_free(&us->hid); } @@ -696,7 +699,7 @@ static void usb_hid_initfn(USBDevice *dev, int kind, const USBDesc *usb1, const USBDesc *usb2, Error **errp) { - USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev); + USBHIDState *us = USB_HID(dev); switch (us->usb_version) { case 1: dev->usb_desc = usb1; @@ -784,6 +787,14 @@ static void usb_hid_class_initfn(ObjectClass *klass, void *data) uc->handle_attach = usb_desc_attach; } +static const TypeInfo usb_hid_type_info = { + .name = TYPE_USB_HID, + .parent = TYPE_USB_DEVICE, + .instance_size = sizeof(USBHIDState), + .abstract = true, + .class_init = usb_hid_class_initfn, +}; + static Property usb_tablet_properties[] = { DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2), DEFINE_PROP_STRING("display", USBHIDState, display), @@ -796,7 +807,6 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - usb_hid_class_initfn(klass, data); uc->realize = usb_tablet_realize; uc->product_desc = "QEMU USB Tablet"; dc->vmsd = &vmstate_usb_ptr; @@ -806,8 +816,7 @@ static void usb_tablet_class_initfn(ObjectClass *klass, void *data) static const TypeInfo usb_tablet_info = { .name = "usb-tablet", - .parent = TYPE_USB_DEVICE, - .instance_size = sizeof(USBHIDState), + .parent = TYPE_USB_HID, .class_init = usb_tablet_class_initfn, }; @@ -821,7 +830,6 @@ static void usb_mouse_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - usb_hid_class_initfn(klass, data); uc->realize = usb_mouse_realize; uc->product_desc = "QEMU USB Mouse"; dc->vmsd = &vmstate_usb_ptr; @@ -831,8 +839,7 @@ static void usb_mouse_class_initfn(ObjectClass *klass, void *data) static const TypeInfo usb_mouse_info = { .name = "usb-mouse", - .parent = TYPE_USB_DEVICE, - .instance_size = sizeof(USBHIDState), + .parent = TYPE_USB_HID, .class_init = usb_mouse_class_initfn, }; @@ -847,7 +854,6 @@ static void usb_keyboard_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - usb_hid_class_initfn(klass, data); uc->realize = usb_keyboard_realize; uc->product_desc = "QEMU USB Keyboard"; dc->vmsd = &vmstate_usb_kbd; @@ -857,13 +863,13 @@ static void usb_keyboard_class_initfn(ObjectClass *klass, void *data) static const TypeInfo usb_keyboard_info = { .name = "usb-kbd", - .parent = TYPE_USB_DEVICE, - .instance_size = sizeof(USBHIDState), + .parent = TYPE_USB_HID, .class_init = usb_keyboard_class_initfn, }; static void usb_hid_register_types(void) { + type_register_static(&usb_hid_type_info); type_register_static(&usb_tablet_info); usb_legacy_register("usb-tablet", "tablet", NULL); type_register_static(&usb_mouse_info); diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c index 0482f58719..c8c6855505 100644 --- a/hw/usb/dev-hub.c +++ b/hw/usb/dev-hub.c @@ -41,6 +41,9 @@ typedef struct USBHubState { USBHubPort ports[NUM_PORTS]; } USBHubState; +#define TYPE_USB_HUB "usb-hub" +#define USB_HUB(obj) OBJECT_CHECK(USBHubState, (obj), TYPE_USB_HUB) + #define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE) #define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE) #define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR) @@ -227,7 +230,7 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet) static USBDevice *usb_hub_find_device(USBDevice *dev, uint8_t addr) { - USBHubState *s = DO_UPCAST(USBHubState, dev, dev); + USBHubState *s = USB_HUB(dev); USBHubPort *port; USBDevice *downstream; int i; @@ -247,7 +250,7 @@ static USBDevice *usb_hub_find_device(USBDevice *dev, uint8_t addr) static void usb_hub_handle_reset(USBDevice *dev) { - USBHubState *s = DO_UPCAST(USBHubState, dev, dev); + USBHubState *s = USB_HUB(dev); USBHubPort *port; int i; @@ -513,7 +516,7 @@ static USBPortOps usb_hub_port_ops = { static void usb_hub_realize(USBDevice *dev, Error **errp) { - USBHubState *s = DO_UPCAST(USBHubState, dev, dev); + USBHubState *s = USB_HUB(dev); USBHubPort *port; int i; @@ -577,7 +580,7 @@ static void usb_hub_class_initfn(ObjectClass *klass, void *data) } static const TypeInfo hub_info = { - .name = "usb-hub", + .name = TYPE_USB_HUB, .parent = TYPE_USB_DEVICE, .instance_size = sizeof(USBHubState), .class_init = usb_hub_class_initfn, diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c index 108ece8190..809b1cb118 100644 --- a/hw/usb/dev-mtp.c +++ b/hw/usb/dev-mtp.c @@ -130,6 +130,9 @@ struct MTPState { QTAILQ_HEAD(, MTPObject) objects; }; +#define TYPE_USB_MTP "usb-mtp" +#define USB_MTP(obj) OBJECT_CHECK(MTPState, (obj), TYPE_USB_MTP) + #define QEMU_STORAGE_ID 0x00010001 #define MTP_FLAG_WRITABLE 0 @@ -878,7 +881,7 @@ static void usb_mtp_command(MTPState *s, MTPControl *c) static void usb_mtp_handle_reset(USBDevice *dev) { - MTPState *s = DO_UPCAST(MTPState, dev, dev); + MTPState *s = USB_MTP(dev); trace_usb_mtp_reset(s->dev.addr); @@ -914,7 +917,7 @@ static void usb_mtp_cancel_packet(USBDevice *dev, USBPacket *p) static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p) { - MTPState *s = DO_UPCAST(MTPState, dev, dev); + MTPState *s = USB_MTP(dev); MTPControl cmd; mtp_container container; uint32_t params[5]; @@ -1062,12 +1065,16 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p) static void usb_mtp_realize(USBDevice *dev, Error **errp) { - MTPState *s = DO_UPCAST(MTPState, dev, dev); + MTPState *s = USB_MTP(dev); usb_desc_create_serial(dev); usb_desc_init(dev); QTAILQ_INIT(&s->objects); if (s->desc == NULL) { + if (s->root == NULL) { + error_setg(errp, "usb-mtp: x-root property must be configured"); + return; + } s->desc = strrchr(s->root, '/'); if (s->desc && s->desc[0]) { s->desc = g_strdup(s->desc + 1); @@ -1113,7 +1120,7 @@ static void usb_mtp_class_initfn(ObjectClass *klass, void *data) } static TypeInfo mtp_info = { - .name = "usb-mtp", + .name = TYPE_USB_MTP, .parent = TYPE_USB_DEVICE, .instance_size = sizeof(MTPState), .class_init = usb_mtp_class_initfn, diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 18669917f5..743c231d6b 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -648,6 +648,9 @@ typedef struct USBNetState { QTAILQ_HEAD(rndis_resp_head, rndis_response) rndis_resp; } USBNetState; +#define TYPE_USB_NET "usb-net" +#define USB_NET(obj) OBJECT_CHECK(USBNetState, (obj), TYPE_USB_NET) + static int is_rndis(USBNetState *s) { return s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE; @@ -1310,6 +1313,10 @@ static int usbnet_can_receive(NetClientState *nc) { USBNetState *s = qemu_get_nic_opaque(nc); + if (!s->dev.config) { + return 0; + } + if (is_rndis(s) && s->rndis_state != RNDIS_DATA_INITIALIZED) { return 1; } @@ -1343,7 +1350,7 @@ static NetClientInfo net_usbnet_info = { static void usb_net_realize(USBDevice *dev, Error **errrp) { - USBNetState *s = DO_UPCAST(USBNetState, dev, dev); + USBNetState *s = USB_NET(dev); usb_desc_create_serial(dev); usb_desc_init(dev); @@ -1376,7 +1383,7 @@ static void usb_net_realize(USBDevice *dev, Error **errrp) static void usb_net_instance_init(Object *obj) { USBDevice *dev = USB_DEVICE(obj); - USBNetState *s = DO_UPCAST(USBNetState, dev, dev); + USBNetState *s = USB_NET(dev); device_add_bootindex_property(obj, &s->conf.bootindex, "bootindex", "/ethernet-phy@0", @@ -1437,7 +1444,7 @@ static void usb_net_class_initfn(ObjectClass *klass, void *data) } static const TypeInfo net_info = { - .name = "usb-net", + .name = TYPE_USB_NET, .parent = TYPE_USB_DEVICE, .instance_size = sizeof(USBNetState), .class_init = usb_net_class_initfn, @@ -1447,7 +1454,7 @@ static const TypeInfo net_info = { static void usb_net_register_types(void) { type_register_static(&net_info); - usb_legacy_register("usb-net", "net", usb_net_init); + usb_legacy_register(TYPE_USB_NET, "net", usb_net_init); } type_init(usb_net_register_types) diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 67c2072ce7..6ca3da9727 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -103,6 +103,9 @@ typedef struct { CharDriverState *cs; } USBSerialState; +#define TYPE_USB_SERIAL "usb-serial-dev" +#define USB_SERIAL_DEV(obj) OBJECT_CHECK(USBSerialState, (obj), TYPE_USB_SERIAL) + enum { STR_MANUFACTURER = 1, STR_PRODUCT_SERIAL, @@ -473,7 +476,7 @@ static void usb_serial_event(void *opaque, int event) static void usb_serial_realize(USBDevice *dev, Error **errp) { - USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev); + USBSerialState *s = USB_SERIAL_DEV(dev); Error *local_err = NULL; usb_desc_create_serial(dev); @@ -576,26 +579,40 @@ static Property serial_properties[] = { DEFINE_PROP_END_OF_LIST(), }; -static void usb_serial_class_initfn(ObjectClass *klass, void *data) +static void usb_serial_dev_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->realize = usb_serial_realize; - uc->product_desc = "QEMU USB Serial"; - uc->usb_desc = &desc_serial; + uc->realize = usb_serial_realize; uc->handle_reset = usb_serial_handle_reset; uc->handle_control = usb_serial_handle_control; uc->handle_data = usb_serial_handle_data; dc->vmsd = &vmstate_usb_serial; - dc->props = serial_properties; set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } +static const TypeInfo usb_serial_dev_type_info = { + .name = TYPE_USB_SERIAL, + .parent = TYPE_USB_DEVICE, + .instance_size = sizeof(USBSerialState), + .abstract = true, + .class_init = usb_serial_dev_class_init, +}; + +static void usb_serial_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + USBDeviceClass *uc = USB_DEVICE_CLASS(klass); + + uc->product_desc = "QEMU USB Serial"; + uc->usb_desc = &desc_serial; + dc->props = serial_properties; +} + static const TypeInfo serial_info = { .name = "usb-serial", - .parent = TYPE_USB_DEVICE, - .instance_size = sizeof(USBSerialState), + .parent = TYPE_USB_SERIAL, .class_init = usb_serial_class_initfn, }; @@ -609,26 +626,20 @@ static void usb_braille_class_initfn(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); - uc->realize = usb_serial_realize; uc->product_desc = "QEMU USB Braille"; uc->usb_desc = &desc_braille; - uc->handle_reset = usb_serial_handle_reset; - uc->handle_control = usb_serial_handle_control; - uc->handle_data = usb_serial_handle_data; - dc->vmsd = &vmstate_usb_serial; dc->props = braille_properties; - set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } static const TypeInfo braille_info = { .name = "usb-braille", - .parent = TYPE_USB_DEVICE, - .instance_size = sizeof(USBSerialState), + .parent = TYPE_USB_SERIAL, .class_init = usb_braille_class_initfn, }; static void usb_serial_register_types(void) { + type_register_static(&usb_serial_dev_type_info); type_register_static(&serial_info); usb_legacy_register("usb-serial", "serial", usb_serial_init); type_register_static(&braille_info); diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index 78ce681671..2d29367ae7 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -55,7 +55,7 @@ do { \ #define D_VERBOSE 4 #define CCID_DEV_NAME "usb-ccid" - +#define USB_CCID_DEV(obj) OBJECT_CHECK(USBCCIDState, (obj), CCID_DEV_NAME) /* * The two options for variable sized buffers: * make them constant size, for large enough constant, @@ -649,7 +649,7 @@ static void ccid_detach(USBCCIDState *s) static void ccid_handle_reset(USBDevice *dev) { - USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev); + USBCCIDState *s = USB_CCID_DEV(dev); DPRINTF(s, 1, "Reset\n"); @@ -692,7 +692,7 @@ static const char *ccid_control_to_str(USBCCIDState *s, int request) static void ccid_handle_control(USBDevice *dev, USBPacket *p, int request, int value, int index, int length, uint8_t *data) { - USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev); + USBCCIDState *s = USB_CCID_DEV(dev); int ret; DPRINTF(s, 1, "%s: got control %s (%x), value %x\n", __func__, @@ -1104,7 +1104,7 @@ static void ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p) static void ccid_handle_data(USBDevice *dev, USBPacket *p) { - USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev); + USBCCIDState *s = USB_CCID_DEV(dev); uint8_t buf[2]; switch (p->pid) { @@ -1148,7 +1148,7 @@ static void ccid_handle_data(USBDevice *dev, USBPacket *p) static void ccid_handle_destroy(USBDevice *dev) { - USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev); + USBCCIDState *s = USB_CCID_DEV(dev); ccid_bulk_in_clear(s); } @@ -1184,8 +1184,9 @@ static const TypeInfo ccid_bus_info = { void ccid_card_send_apdu_to_guest(CCIDCardState *card, uint8_t *apdu, uint32_t len) { - USBCCIDState *s = DO_UPCAST(USBCCIDState, dev.qdev, - card->qdev.parent_bus->parent); + DeviceState *qdev = DEVICE(card); + USBDevice *dev = USB_DEVICE(qdev); + USBCCIDState *s = USB_CCID_DEV(dev); Answer *answer; if (!ccid_has_pending_answers(s)) { @@ -1206,8 +1207,9 @@ void ccid_card_send_apdu_to_guest(CCIDCardState *card, void ccid_card_card_removed(CCIDCardState *card) { - USBCCIDState *s = - DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent); + DeviceState *qdev = DEVICE(card); + USBDevice *dev = USB_DEVICE(qdev); + USBCCIDState *s = USB_CCID_DEV(dev); ccid_on_slot_change(s, false); ccid_flush_pending_answers(s); @@ -1216,8 +1218,9 @@ void ccid_card_card_removed(CCIDCardState *card) int ccid_card_ccid_attach(CCIDCardState *card) { - USBCCIDState *s = - DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent); + DeviceState *qdev = DEVICE(card); + USBDevice *dev = USB_DEVICE(qdev); + USBCCIDState *s = USB_CCID_DEV(dev); DPRINTF(s, 1, "CCID Attach\n"); if (s->migration_state == MIGRATION_MIGRATED) { @@ -1228,8 +1231,9 @@ int ccid_card_ccid_attach(CCIDCardState *card) void ccid_card_ccid_detach(CCIDCardState *card) { - USBCCIDState *s = - DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent); + DeviceState *qdev = DEVICE(card); + USBDevice *dev = USB_DEVICE(qdev); + USBCCIDState *s = USB_CCID_DEV(dev); DPRINTF(s, 1, "CCID Detach\n"); if (ccid_card_inserted(s)) { @@ -1240,8 +1244,9 @@ void ccid_card_ccid_detach(CCIDCardState *card) void ccid_card_card_error(CCIDCardState *card, uint64_t error) { - USBCCIDState *s = - DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent); + DeviceState *qdev = DEVICE(card); + USBDevice *dev = USB_DEVICE(qdev); + USBCCIDState *s = USB_CCID_DEV(dev); s->bmCommandStatus = COMMAND_STATUS_FAILED; s->last_answer_error = error; @@ -1258,8 +1263,9 @@ void ccid_card_card_error(CCIDCardState *card, uint64_t error) void ccid_card_card_inserted(CCIDCardState *card) { - USBCCIDState *s = - DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent); + DeviceState *qdev = DEVICE(card); + USBDevice *dev = USB_DEVICE(qdev); + USBCCIDState *s = USB_CCID_DEV(dev); s->bmCommandStatus = COMMAND_STATUS_NO_ERROR; ccid_flush_pending_answers(s); @@ -1270,8 +1276,8 @@ static int ccid_card_exit(DeviceState *qdev) { int ret = 0; CCIDCardState *card = CCID_CARD(qdev); - USBCCIDState *s = - DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent); + USBDevice *dev = USB_DEVICE(qdev); + USBCCIDState *s = USB_CCID_DEV(dev); if (ccid_card_inserted(s)) { ccid_card_card_removed(card); @@ -1284,8 +1290,8 @@ static int ccid_card_exit(DeviceState *qdev) static int ccid_card_init(DeviceState *qdev) { CCIDCardState *card = CCID_CARD(qdev); - USBCCIDState *s = - DO_UPCAST(USBCCIDState, dev.qdev, card->qdev.parent_bus->parent); + USBDevice *dev = USB_DEVICE(qdev); + USBCCIDState *s = USB_CCID_DEV(dev); int ret = 0; if (card->slot != 0) { @@ -1306,7 +1312,7 @@ static int ccid_card_init(DeviceState *qdev) static void ccid_realize(USBDevice *dev, Error **errp) { - USBCCIDState *s = DO_UPCAST(USBCCIDState, dev, dev); + USBCCIDState *s = USB_CCID_DEV(dev); usb_desc_create_serial(dev); usb_desc_init(dev); diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index ae8d40dc77..abe0e1d6a1 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -64,6 +64,9 @@ typedef struct { SCSIDevice *scsi_dev; } MSDState; +#define TYPE_USB_STORAGE "usb-storage-dev" +#define USB_STORAGE_DEV(obj) OBJECT_CHECK(MSDState, (obj), TYPE_USB_STORAGE) + struct usb_msd_cbw { uint32_t sig; uint32_t tag; @@ -385,7 +388,7 @@ static void usb_msd_handle_control(USBDevice *dev, USBPacket *p, static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p) { - MSDState *s = DO_UPCAST(MSDState, dev, dev); + MSDState *s = USB_STORAGE_DEV(dev); assert(s->packet == p); s->packet = NULL; @@ -599,7 +602,7 @@ static const struct SCSIBusInfo usb_msd_scsi_info_bot = { static void usb_msd_realize_storage(USBDevice *dev, Error **errp) { - MSDState *s = DO_UPCAST(MSDState, dev, dev); + MSDState *s = USB_STORAGE_DEV(dev); BlockBackend *blk = s->conf.blk; SCSIDevice *scsi_dev; Error *err = NULL; @@ -658,7 +661,7 @@ static void usb_msd_realize_storage(USBDevice *dev, Error **errp) static void usb_msd_realize_bot(USBDevice *dev, Error **errp) { - MSDState *s = DO_UPCAST(MSDState, dev, dev); + MSDState *s = USB_STORAGE_DEV(dev); usb_desc_create_serial(dev); usb_desc_init(dev); @@ -748,7 +751,7 @@ static Property msd_properties[] = { DEFINE_PROP_END_OF_LIST(), }; -static void usb_msd_class_initfn_common(ObjectClass *klass) +static void usb_msd_class_initfn_common(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); USBDeviceClass *uc = USB_DEVICE_CLASS(klass); @@ -772,14 +775,13 @@ static void usb_msd_class_initfn_storage(ObjectClass *klass, void *data) uc->realize = usb_msd_realize_storage; dc->props = msd_properties; - usb_msd_class_initfn_common(klass); } static void usb_msd_get_bootindex(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { USBDevice *dev = USB_DEVICE(obj); - MSDState *s = DO_UPCAST(MSDState, dev, dev); + MSDState *s = USB_STORAGE_DEV(dev); visit_type_int32(v, &s->conf.bootindex, name, errp); } @@ -788,7 +790,7 @@ static void usb_msd_set_bootindex(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { USBDevice *dev = USB_DEVICE(obj); - MSDState *s = DO_UPCAST(MSDState, dev, dev); + MSDState *s = USB_STORAGE_DEV(dev); int32_t boot_index; Error *local_err = NULL; @@ -815,6 +817,14 @@ out: } } +static const TypeInfo usb_storage_dev_type_info = { + .name = TYPE_USB_STORAGE, + .parent = TYPE_USB_DEVICE, + .instance_size = sizeof(MSDState), + .abstract = true, + .class_init = usb_msd_class_initfn_common, +}; + static void usb_msd_instance_init(Object *obj) { object_property_add(obj, "bootindex", "int32", @@ -829,27 +839,25 @@ static void usb_msd_class_initfn_bot(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); uc->realize = usb_msd_realize_bot; - usb_msd_class_initfn_common(klass); dc->hotpluggable = false; } static const TypeInfo msd_info = { .name = "usb-storage", - .parent = TYPE_USB_DEVICE, - .instance_size = sizeof(MSDState), + .parent = TYPE_USB_STORAGE, .class_init = usb_msd_class_initfn_storage, .instance_init = usb_msd_instance_init, }; static const TypeInfo bot_info = { .name = "usb-bot", - .parent = TYPE_USB_DEVICE, - .instance_size = sizeof(MSDState), + .parent = TYPE_USB_STORAGE, .class_init = usb_msd_class_initfn_bot, }; static void usb_msd_register_types(void) { + type_register_static(&usb_storage_dev_type_info); type_register_static(&msd_info); type_register_static(&bot_info); usb_legacy_register("usb-storage", "disk", usb_msd_init); diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index 04fc515dbe..38b26c586d 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -127,6 +127,9 @@ struct UASDevice { USBPacket *status3[UAS_MAX_STREAMS + 1]; }; +#define TYPE_USB_UAS "usb-uas" +#define USB_UAS(obj) OBJECT_CHECK(UASDevice, (obj), TYPE_USB_UAS) + struct UASRequest { uint16_t tag; uint64_t lun; @@ -626,7 +629,7 @@ static const struct SCSIBusInfo usb_uas_scsi_info = { static void usb_uas_handle_reset(USBDevice *dev) { - UASDevice *uas = DO_UPCAST(UASDevice, dev, dev); + UASDevice *uas = USB_UAS(dev); UASRequest *req, *nreq; UASStatus *st, *nst; @@ -655,7 +658,7 @@ static void usb_uas_handle_control(USBDevice *dev, USBPacket *p, static void usb_uas_cancel_io(USBDevice *dev, USBPacket *p) { - UASDevice *uas = DO_UPCAST(UASDevice, dev, dev); + UASDevice *uas = USB_UAS(dev); UASRequest *req, *nreq; int i; @@ -797,7 +800,7 @@ incorrect_lun: static void usb_uas_handle_data(USBDevice *dev, USBPacket *p) { - UASDevice *uas = DO_UPCAST(UASDevice, dev, dev); + UASDevice *uas = USB_UAS(dev); uas_iu iu; UASStatus *st; UASRequest *req; @@ -888,14 +891,14 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p) static void usb_uas_handle_destroy(USBDevice *dev) { - UASDevice *uas = DO_UPCAST(UASDevice, dev, dev); + UASDevice *uas = USB_UAS(dev); qemu_bh_delete(uas->status_bh); } static void usb_uas_realize(USBDevice *dev, Error **errp) { - UASDevice *uas = DO_UPCAST(UASDevice, dev, dev); + UASDevice *uas = USB_UAS(dev); usb_desc_create_serial(dev); usb_desc_init(dev); @@ -943,7 +946,7 @@ static void usb_uas_class_initfn(ObjectClass *klass, void *data) } static const TypeInfo uas_info = { - .name = "usb-uas", + .name = TYPE_USB_UAS, .parent = TYPE_USB_DEVICE, .instance_size = sizeof(UASDevice), .class_init = usb_uas_class_initfn, diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c index 844eafadf7..c2450e7297 100644 --- a/hw/usb/dev-wacom.c +++ b/hw/usb/dev-wacom.c @@ -56,6 +56,9 @@ typedef struct USBWacomState { int changed; } USBWacomState; +#define TYPE_USB_WACOM "usb-wacom-tablet" +#define USB_WACOM(obj) OBJECT_CHECK(USBWacomState, (obj), TYPE_USB_WACOM) + enum { STR_MANUFACTURER = 1, STR_PRODUCT, @@ -337,7 +340,7 @@ static void usb_wacom_handle_destroy(USBDevice *dev) static void usb_wacom_realize(USBDevice *dev, Error **errp) { - USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev); + USBWacomState *s = USB_WACOM(dev); usb_desc_create_serial(dev); usb_desc_init(dev); s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); @@ -367,7 +370,7 @@ static void usb_wacom_class_init(ObjectClass *klass, void *data) } static const TypeInfo wacom_info = { - .name = "usb-wacom-tablet", + .name = TYPE_USB_WACOM, .parent = TYPE_USB_DEVICE, .instance_size = sizeof(USBWacomState), .class_init = usb_wacom_class_init, @@ -376,7 +379,7 @@ static const TypeInfo wacom_info = { static void usb_wacom_register_types(void) { type_register_static(&wacom_info); - usb_legacy_register("usb-wacom-tablet", "wacom-tablet", NULL); + usb_legacy_register(TYPE_USB_WACOM, "wacom-tablet", NULL); } type_init(usb_wacom_register_types) diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 327f26da70..3f0ed62689 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -154,6 +154,9 @@ static void uhci_async_cancel(UHCIAsync *async); static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td); static void uhci_resume(void *opaque); +#define TYPE_UHCI "pci-uhci-usb" +#define UHCI(obj) OBJECT_CHECK(UHCIState, (obj), TYPE_UHCI) + static inline int32_t uhci_queue_token(UHCI_TD *td) { if ((td->token & (0xf << 15)) == 0) { @@ -351,7 +354,7 @@ static void uhci_update_irq(UHCIState *s) static void uhci_reset(DeviceState *dev) { PCIDevice *d = PCI_DEVICE(dev); - UHCIState *s = DO_UPCAST(UHCIState, dev, d); + UHCIState *s = UHCI(d); uint8_t *pci_conf; int i; UHCIPort *port; @@ -363,7 +366,7 @@ static void uhci_reset(DeviceState *dev) pci_conf[0x6a] = 0x01; /* usb clock */ pci_conf[0x6b] = 0x00; s->cmd = 0; - s->status = 0; + s->status = UHCI_STS_HCHALTED; s->status2 = 0; s->intr = 0; s->fl_base_addr = 0; @@ -1196,7 +1199,7 @@ static void usb_uhci_common_realize(PCIDevice *dev, Error **errp) Error *err = NULL; PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); UHCIPCIDeviceClass *u = container_of(pc, UHCIPCIDeviceClass, parent_class); - UHCIState *s = DO_UPCAST(UHCIState, dev, dev); + UHCIState *s = UHCI(dev); uint8_t *pci_conf = s->dev.config; int i; @@ -1241,7 +1244,7 @@ static void usb_uhci_common_realize(PCIDevice *dev, Error **errp) static void usb_uhci_vt82c686b_realize(PCIDevice *dev, Error **errp) { - UHCIState *s = DO_UPCAST(UHCIState, dev, dev); + UHCIState *s = UHCI(dev); uint8_t *pci_conf = s->dev.config; /* USB misc control 1/2 */ @@ -1256,7 +1259,7 @@ static void usb_uhci_vt82c686b_realize(PCIDevice *dev, Error **errp) static void usb_uhci_exit(PCIDevice *dev) { - UHCIState *s = DO_UPCAST(UHCIState, dev, dev); + UHCIState *s = UHCI(dev); trace_usb_uhci_exit(); @@ -1294,6 +1297,26 @@ static void uhci_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->class_id = PCI_CLASS_SERIAL_USB; + dc->vmsd = &vmstate_uhci; + dc->reset = uhci_reset; + set_bit(DEVICE_CATEGORY_USB, dc->categories); +} + +static const TypeInfo uhci_pci_type_info = { + .name = TYPE_UHCI, + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(UHCIState), + .class_size = sizeof(UHCIPCIDeviceClass), + .abstract = true, + .class_init = uhci_class_init, +}; + +static void uhci_data_class_init(ObjectClass *klass, void *data) +{ + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); UHCIPCIDeviceClass *u = container_of(k, UHCIPCIDeviceClass, parent_class); UHCIInfo *info = data; @@ -1302,9 +1325,6 @@ static void uhci_class_init(ObjectClass *klass, void *data) k->vendor_id = info->vendor_id; k->device_id = info->device_id; k->revision = info->revision; - k->class_id = PCI_CLASS_SERIAL_USB; - dc->vmsd = &vmstate_uhci; - dc->reset = uhci_reset; if (!info->unplug) { /* uhci controllers in companion setups can't be hotplugged */ dc->hotpluggable = false; @@ -1312,7 +1332,6 @@ static void uhci_class_init(ObjectClass *klass, void *data) } else { dc->props = uhci_properties_standalone; } - set_bit(DEVICE_CATEGORY_USB, dc->categories); u->info = *info; } @@ -1387,13 +1406,13 @@ static UHCIInfo uhci_info[] = { static void uhci_register_types(void) { TypeInfo uhci_type_info = { - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(UHCIState), - .class_size = sizeof(UHCIPCIDeviceClass), - .class_init = uhci_class_init, + .parent = TYPE_UHCI, + .class_init = uhci_data_class_init, }; int i; + type_register_static(&uhci_pci_type_info); + for (i = 0; i < ARRAY_SIZE(uhci_info); i++) { uhci_type_info.name = uhci_info[i].name; uhci_type_info.class_data = uhci_info + i; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 99f11fcbb3..90a5fbff29 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1767,18 +1767,9 @@ static void xhci_xfer_report(XHCITransfer *xfer) break; } - /* - * XHCI 1.1, 4.11.3.1 Transfer Event TRB -- "each Transfer TRB - * encountered with its IOC flag set to '1' shall generate a Transfer - * Event." - * - * Otherwise, longer transfers can have multiple data TRBs (for scatter - * gather). Short transfers and errors should be reported once per - * transfer only. - */ - if ((trb->control & TRB_TR_IOC) || - (!reported && ((shortpkt && (trb->control & TRB_TR_ISP)) || - (xfer->status != CC_SUCCESS && left == 0)))) { + if (!reported && ((trb->control & TRB_TR_IOC) || + (shortpkt && (trb->control & TRB_TR_ISP)) || + (xfer->status != CC_SUCCESS && left == 0))) { event.slotid = xfer->slotid; event.epid = xfer->epid; event.length = (trb->status & 0x1ffff) - chunk; @@ -1802,6 +1793,14 @@ static void xhci_xfer_report(XHCITransfer *xfer) return; } } + + switch (TRB_TYPE(*trb)) { + case TR_SETUP: + reported = 0; + shortpkt = 0; + break; + } + } } @@ -2223,6 +2222,8 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, if (xfer->running_retry) { DPRINTF("xhci: xfer nacked, stopping schedule\n"); epctx->retry = xfer; + timer_mod(epctx->kick_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + epctx->interval * 125000); break; } } diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index 2416de83e9..242a654583 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -130,6 +130,9 @@ struct USBRedirDevice { int compatible_speedmask; }; +#define TYPE_USB_REDIR "usb-redir" +#define USB_REDIRECT(obj) OBJECT_CHECK(USBRedirDevice, (obj), TYPE_USB_REDIR) + static void usbredir_hello(void *priv, struct usb_redir_hello_header *h); static void usbredir_device_connect(void *priv, struct usb_redir_device_connect_header *device_connect); @@ -360,7 +363,7 @@ static void packet_id_queue_empty(struct PacketIdQueue *q) static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p) { - USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + USBRedirDevice *dev = USB_REDIRECT(udev); int i = USBEP2I(p->ep); if (p->combined) { @@ -500,7 +503,7 @@ static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep) static void usbredir_handle_reset(USBDevice *udev) { - USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + USBRedirDevice *dev = USB_REDIRECT(udev); DPRINTF("reset device\n"); usbredirparser_send_reset(dev->parser); @@ -907,7 +910,7 @@ static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev, static void usbredir_handle_data(USBDevice *udev, USBPacket *p) { - USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + USBRedirDevice *dev = USB_REDIRECT(udev); uint8_t ep; ep = p->ep->nr; @@ -976,7 +979,7 @@ static void usbredir_stop_ep(USBRedirDevice *dev, int i) static void usbredir_ep_stopped(USBDevice *udev, USBEndpoint *uep) { - USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + USBRedirDevice *dev = USB_REDIRECT(udev); usbredir_stop_ep(dev, USBEP2I(uep)); usbredirparser_do_write(dev->parser); @@ -1046,7 +1049,7 @@ static void usbredir_get_interface(USBRedirDevice *dev, USBPacket *p, static void usbredir_handle_control(USBDevice *udev, USBPacket *p, int request, int value, int index, int length, uint8_t *data) { - USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + USBRedirDevice *dev = USB_REDIRECT(udev); struct usb_redir_control_packet_header control_packet; if (usbredir_already_in_flight(dev, p->id)) { @@ -1101,7 +1104,7 @@ static void usbredir_handle_control(USBDevice *udev, USBPacket *p, static int usbredir_alloc_streams(USBDevice *udev, USBEndpoint **eps, int nr_eps, int streams) { - USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + USBRedirDevice *dev = USB_REDIRECT(udev); #if USBREDIR_VERSION >= 0x000700 struct usb_redir_alloc_bulk_streams_header alloc_streams; int i; @@ -1140,7 +1143,7 @@ static void usbredir_free_streams(USBDevice *udev, USBEndpoint **eps, int nr_eps) { #if USBREDIR_VERSION >= 0x000700 - USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + USBRedirDevice *dev = USB_REDIRECT(udev); struct usb_redir_free_bulk_streams_header free_streams; int i; @@ -1362,7 +1365,7 @@ static void usbredir_init_endpoints(USBRedirDevice *dev) static void usbredir_realize(USBDevice *udev, Error **errp) { - USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + USBRedirDevice *dev = USB_REDIRECT(udev); int i; if (dev->cs == NULL) { @@ -1415,7 +1418,7 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev) static void usbredir_handle_destroy(USBDevice *udev) { - USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + USBRedirDevice *dev = USB_REDIRECT(udev); qemu_chr_delete(dev->cs); dev->cs = NULL; @@ -2496,7 +2499,7 @@ static void usbredir_class_initfn(ObjectClass *klass, void *data) static void usbredir_instance_init(Object *obj) { USBDevice *udev = USB_DEVICE(obj); - USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev); + USBRedirDevice *dev = USB_REDIRECT(udev); device_add_bootindex_property(obj, &dev->bootindex, "bootindex", NULL, @@ -2504,7 +2507,7 @@ static void usbredir_instance_init(Object *obj) } static const TypeInfo usbredir_dev_info = { - .name = "usb-redir", + .name = TYPE_USB_REDIR, .parent = TYPE_USB_DEVICE, .instance_size = sizeof(USBRedirDevice), .class_init = usbredir_class_initfn, diff --git a/hw/vfio/common.c b/hw/vfio/common.c index b01262063d..b1045da857 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -270,13 +270,14 @@ static void vfio_iommu_map_notify(Notifier *n, void *data) * this IOMMU to its immediate target. We need to translate * it the rest of the way through to memory. */ + rcu_read_lock(); mr = address_space_translate(&address_space_memory, iotlb->translated_addr, &xlat, &len, iotlb->perm & IOMMU_WO); if (!memory_region_is_ram(mr)) { error_report("iommu map to non memory area %"HWADDR_PRIx"", xlat); - return; + goto out; } /* * Translation truncates length to the IOMMU page size, @@ -284,7 +285,7 @@ static void vfio_iommu_map_notify(Notifier *n, void *data) */ if (len & iotlb->addr_mask) { error_report("iommu has granularity incompatible with target AS"); - return; + goto out; } if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) { @@ -307,6 +308,8 @@ static void vfio_iommu_map_notify(Notifier *n, void *data) iotlb->addr_mask + 1, ret); } } +out: + rcu_read_unlock(); } static void vfio_listener_region_add(MemoryListener *listener, diff --git a/include/exec/memory.h b/include/exec/memory.h index 0ccfd3b42a..b61c84f62a 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -1233,7 +1233,9 @@ void address_space_stq(AddressSpace *as, hwaddr addr, uint64_t val, #endif /* address_space_translate: translate an address range into an address space - * into a MemoryRegion and an address range into that section + * into a MemoryRegion and an address range into that section. Should be + * called from an RCU critical section, to avoid that the last reference + * to the returned region disappears after address_space_translate returns. * * @as: #AddressSpace to be accessed * @addr: address within that address space diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 197e6c0214..4878959404 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -18,6 +18,7 @@ #include "config-host.h" #include "qemu/queue.h" #include "qom/cpu.h" +#include "exec/memattrs.h" #ifdef CONFIG_KVM #include <linux/kvm.h> @@ -254,7 +255,7 @@ int kvm_create_device(KVMState *s, uint64_t type, bool test); extern const KVMCapabilityInfo kvm_arch_required_capabilities[]; void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run); -void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run); +MemTxAttrs kvm_arch_post_run(CPUState *cpu, struct kvm_run *run); int kvm_arch_handle_exit(CPUState *cpu, struct kvm_run *run); diff --git a/include/ui/console.h b/include/ui/console.h index 0b7589600b..e8b3a9ea8d 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -228,6 +228,7 @@ void update_displaychangelistener(DisplayChangeListener *dcl, uint64_t interval); void unregister_displaychangelistener(DisplayChangeListener *dcl); +bool dpy_ui_info_supported(QemuConsole *con); int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info); void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h); diff --git a/include/ui/gtk.h b/include/ui/gtk.h new file mode 100644 index 0000000000..b750845ab5 --- /dev/null +++ b/include/ui/gtk.h @@ -0,0 +1,76 @@ +#ifndef UI_GTK_H +#define UI_GTK_H + +#ifdef _WIN32 +# define _WIN32_WINNT 0x0601 /* needed to get definition of MAPVK_VK_TO_VSC */ +#endif + +#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE +/* Work around an -Wstrict-prototypes warning in GTK headers */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-prototypes" +#endif +#include <gtk/gtk.h> +#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE +#pragma GCC diagnostic pop +#endif + +#include <gdk/gdkkeysyms.h> + +#ifdef GDK_WINDOWING_X11 +#include <gdk/gdkx.h> +#include <X11/XKBlib.h> +#endif + +/* Compatibility define to let us build on both Gtk2 and Gtk3 */ +#if GTK_CHECK_VERSION(3, 0, 0) +static inline void gdk_drawable_get_size(GdkWindow *w, gint *ww, gint *wh) +{ + *ww = gdk_window_get_width(w); + *wh = gdk_window_get_height(w); +} +#endif + +typedef struct GtkDisplayState GtkDisplayState; + +typedef struct VirtualGfxConsole { + GtkWidget *drawing_area; + DisplayChangeListener dcl; + DisplaySurface *ds; + pixman_image_t *convert; + cairo_surface_t *surface; + double scale_x; + double scale_y; +} VirtualGfxConsole; + +#if defined(CONFIG_VTE) +typedef struct VirtualVteConsole { + GtkWidget *box; + GtkWidget *scrollbar; + GtkWidget *terminal; + CharDriverState *chr; +} VirtualVteConsole; +#endif + +typedef enum VirtualConsoleType { + GD_VC_GFX, + GD_VC_VTE, +} VirtualConsoleType; + +typedef struct VirtualConsole { + GtkDisplayState *s; + char *label; + GtkWidget *window; + GtkWidget *menu_item; + GtkWidget *tab_item; + GtkWidget *focus; + VirtualConsoleType type; + union { + VirtualGfxConsole gfx; +#if defined(CONFIG_VTE) + VirtualVteConsole vte; +#endif + }; +} VirtualConsole; + +#endif /* UI_GTK_H */ diff --git a/kvm-all.c b/kvm-all.c index 28f4589219..17a3771efe 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -1669,14 +1669,14 @@ void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len) s->sigmask_len = sigmask_len; } -static void kvm_handle_io(uint16_t port, void *data, int direction, int size, - uint32_t count) +static void kvm_handle_io(uint16_t port, MemTxAttrs attrs, void *data, int direction, + int size, uint32_t count) { int i; uint8_t *ptr = data; for (i = 0; i < count; i++) { - address_space_rw(&address_space_io, port, MEMTXATTRS_UNSPECIFIED, + address_space_rw(&address_space_io, port, attrs, ptr, size, direction == KVM_EXIT_IO_OUT); ptr += size; @@ -1796,6 +1796,8 @@ int kvm_cpu_exec(CPUState *cpu) } do { + MemTxAttrs attrs; + if (cpu->kvm_vcpu_dirty) { kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE); cpu->kvm_vcpu_dirty = false; @@ -1816,7 +1818,7 @@ int kvm_cpu_exec(CPUState *cpu) run_ret = kvm_vcpu_ioctl(cpu, KVM_RUN, 0); qemu_mutex_lock_iothread(); - kvm_arch_post_run(cpu, run); + attrs = kvm_arch_post_run(cpu, run); if (run_ret < 0) { if (run_ret == -EINTR || run_ret == -EAGAIN) { @@ -1834,7 +1836,7 @@ int kvm_cpu_exec(CPUState *cpu) switch (run->exit_reason) { case KVM_EXIT_IO: DPRINTF("handle_io\n"); - kvm_handle_io(run->io.port, + kvm_handle_io(run->io.port, attrs, (uint8_t *)run + run->io.data_offset, run->io.direction, run->io.size, @@ -1843,10 +1845,11 @@ int kvm_cpu_exec(CPUState *cpu) break; case KVM_EXIT_MMIO: DPRINTF("handle_mmio\n"); - cpu_physical_memory_rw(run->mmio.phys_addr, - run->mmio.data, - run->mmio.len, - run->mmio.is_write); + address_space_rw(&address_space_memory, + run->mmio.phys_addr, attrs, + run->mmio.data, + run->mmio.len, + run->mmio.is_write); ret = 0; break; case KVM_EXIT_IRQ_WINDOW_OPEN: diff --git a/memory.c b/memory.c index 0f6cb812db..03c536b857 100644 --- a/memory.c +++ b/memory.c @@ -2089,7 +2089,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, const MemoryRegion *submr; unsigned int i; - if (!mr || !mr->enabled) { + if (!mr) { return; } @@ -2115,7 +2115,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, } mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %c%c): alias %s @%s " TARGET_FMT_plx - "-" TARGET_FMT_plx "\n", + "-" TARGET_FMT_plx "%s\n", base + mr->addr, base + mr->addr + (int128_nz(mr->size) ? @@ -2131,10 +2131,11 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, mr->alias_offset + (int128_nz(mr->size) ? (hwaddr)int128_get64(int128_sub(mr->size, - int128_one())) : 0)); + int128_one())) : 0), + mr->enabled ? "" : " [disabled]"); } else { mon_printf(f, - TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %c%c): %s\n", + TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %c%c): %s%s\n", base + mr->addr, base + mr->addr + (int128_nz(mr->size) ? @@ -2144,7 +2145,8 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f, mr->romd_mode ? 'R' : '-', !mr->readonly && !(mr->rom_device && mr->romd_mode) ? 'W' : '-', - memory_region_name(mr)); + memory_region_name(mr), + mr->enabled ? "" : " [disabled]"); } QTAILQ_INIT(&submr_print_queue); @@ -2185,15 +2187,16 @@ void mtree_info(fprintf_function mon_printf, void *f) QTAILQ_INIT(&ml_head); QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - mon_printf(f, "%s\n", as->name); - mtree_print_mr(mon_printf, f, as->root, 0, 0, &ml_head); + mon_printf(f, "address-space: %s\n", as->name); + mtree_print_mr(mon_printf, f, as->root, 1, 0, &ml_head); + mon_printf(f, "\n"); } - mon_printf(f, "aliases\n"); /* print aliased regions */ QTAILQ_FOREACH(ml, &ml_head, queue) { - mon_printf(f, "%s\n", memory_region_name(ml->mr)); - mtree_print_mr(mon_printf, f, ml->mr, 0, 0, &ml_head); + mon_printf(f, "memory-region: %s\n", memory_region_name(ml->mr)); + mtree_print_mr(mon_printf, f, ml->mr, 1, 0, &ml_head); + mon_printf(f, "\n"); } QTAILQ_FOREACH_SAFE(ml, &ml_head, queue, ml2) { diff --git a/nbd.c b/nbd.c index cb1b9bbf7c..06b501ba67 100644 --- a/nbd.c +++ b/nbd.c @@ -86,6 +86,59 @@ #define NBD_OPT_ABORT (2) #define NBD_OPT_LIST (3) +/* NBD errors are based on errno numbers, so there is a 1:1 mapping, + * but only a limited set of errno values is specified in the protocol. + * Everything else is squashed to EINVAL. + */ +#define NBD_SUCCESS 0 +#define NBD_EPERM 1 +#define NBD_EIO 5 +#define NBD_ENOMEM 12 +#define NBD_EINVAL 22 +#define NBD_ENOSPC 28 + +static int system_errno_to_nbd_errno(int err) +{ + switch (err) { + case 0: + return NBD_SUCCESS; + case EPERM: + return NBD_EPERM; + case EIO: + return NBD_EIO; + case ENOMEM: + return NBD_ENOMEM; +#ifdef EDQUOT + case EDQUOT: +#endif + case EFBIG: + case ENOSPC: + return NBD_ENOSPC; + case EINVAL: + default: + return NBD_EINVAL; + } +} + +static int nbd_errno_to_system_errno(int err) +{ + switch (err) { + case NBD_SUCCESS: + return 0; + case NBD_EPERM: + return EPERM; + case NBD_EIO: + return EIO; + case NBD_ENOMEM: + return ENOMEM; + case NBD_ENOSPC: + return ENOSPC; + case NBD_EINVAL: + default: + return EINVAL; + } +} + /* Definitions for opaque data types */ typedef struct NBDRequest NBDRequest; @@ -856,6 +909,8 @@ ssize_t nbd_receive_reply(int csock, struct nbd_reply *reply) reply->error = be32_to_cpup((uint32_t*)(buf + 4)); reply->handle = be64_to_cpup((uint64_t*)(buf + 8)); + reply->error = nbd_errno_to_system_errno(reply->error); + TRACE("Got reply: " "{ magic = 0x%x, .error = %d, handle = %" PRIu64" }", magic, reply->error, reply->handle); @@ -872,6 +927,8 @@ static ssize_t nbd_send_reply(int csock, struct nbd_reply *reply) uint8_t buf[NBD_REPLY_SIZE]; ssize_t ret; + reply->error = system_errno_to_nbd_errno(reply->error); + /* Reply [ 0 .. 3] magic (NBD_REPLY_MAGIC) [ 4 .. 7] error (0 == no error) diff --git a/rules.mak b/rules.mak index 3a056272e2..aec27f81db 100644 --- a/rules.mak +++ b/rules.mak @@ -102,7 +102,8 @@ endif %.o: %.dtrace $(call quiet-command,dtrace -o $@ -G -s $<, " GEN $(TARGET_DIR)$@") -%$(DSOSUF): CFLAGS += -fPIC -DBUILD_DSO +DSO_OBJ_CFLAGS := -fPIC -DBUILD_DSO +module-common.o: CFLAGS += $(DSO_OBJ_CFLAGS) %$(DSOSUF): LDFLAGS += $(LDFLAGS_SHARED) %$(DSOSUF): %.mo $(call LINK,$^) @@ -351,6 +352,7 @@ define unnest-vars # For non-module build, add -m to -y $(if $(CONFIG_MODULES), $(foreach o,$($v), + $(eval $($o-objs): CFLAGS += $(DSO_OBJ_CFLAGS)) $(eval $o: $($o-objs))) $(eval $(patsubst %-m,%-y,$v) += $($v)) $(eval modules: $($v:%.mo=%$(DSOSUF))), diff --git a/target-arm/kvm.c b/target-arm/kvm.c index fdd9ba3f1d..16abbf198c 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -23,6 +23,7 @@ #include "cpu.h" #include "internals.h" #include "hw/arm/arm.h" +#include "exec/memattrs.h" const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO @@ -506,8 +507,9 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) { } -void kvm_arch_post_run(CPUState *cs, struct kvm_run *run) +MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) { + return MEMTXATTRS_UNSPECIFIED; } int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 41d09e52de..a26d25a81f 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -37,6 +37,7 @@ #include "hw/pci/pci.h" #include "migration/migration.h" #include "qapi/qmp/qerror.h" +#include "exec/memattrs.h" //#define DEBUG_KVM @@ -2246,7 +2247,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run) } } -void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run) +MemTxAttrs kvm_arch_post_run(CPUState *cpu, struct kvm_run *run) { X86CPU *x86_cpu = X86_CPU(cpu); CPUX86State *env = &x86_cpu->env; @@ -2258,6 +2259,7 @@ void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run) } cpu_set_apic_tpr(x86_cpu->apic_state, run->cr8); cpu_set_apic_base(x86_cpu->apic_state, run->apic_base); + return MEMTXATTRS_UNSPECIFIED; } int kvm_arch_process_async_events(CPUState *cs) diff --git a/target-mips/kvm.c b/target-mips/kvm.c index 4d1f7ead81..59eb11105a 100644 --- a/target-mips/kvm.c +++ b/target-mips/kvm.c @@ -23,6 +23,7 @@ #include "cpu.h" #include "sysemu/cpus.h" #include "kvm_mips.h" +#include "exec/memattrs.h" #define DEBUG_KVM 0 @@ -110,9 +111,10 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) } } -void kvm_arch_post_run(CPUState *cs, struct kvm_run *run) +MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) { DPRINTF("%s\n", __func__); + return MEMTXATTRS_UNSPECIFIED; } int kvm_arch_process_async_events(CPUState *cs) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 12328a4027..1da9ea81e5 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -39,6 +39,7 @@ #include "sysemu/watchdog.h" #include "trace.h" #include "exec/gdbstub.h" +#include "exec/memattrs.h" //#define DEBUG_KVM @@ -1270,8 +1271,9 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) * anyways, so we will get a chance to deliver the rest. */ } -void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run) +MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) { + return MEMTXATTRS_UNSPECIFIED; } int kvm_arch_process_async_events(CPUState *cs) diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h index 8b376df1b7..936ae21e06 100644 --- a/target-s390x/cpu-qom.h +++ b/target-s390x/cpu-qom.h @@ -66,6 +66,9 @@ typedef struct S390CPU { /*< public >*/ CPUS390XState env; + /* needed for live migration */ + void *irqstate; + uint32_t irqstate_saved_size; } S390CPU; static inline S390CPU *s390_env_get_cpu(CPUS390XState *env) diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index e0537fa222..d2f9836e86 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -213,6 +213,7 @@ static void s390_cpu_finalize(Object *obj) S390CPU *cpu = S390_CPU(obj); qemu_unregister_reset(s390_cpu_machine_reset_cb, cpu); + g_free(cpu->irqstate); #endif } diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index ba7d250962..c55721114e 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1079,6 +1079,8 @@ void kvm_s390_clear_cmma_callback(void *opaque); int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); void kvm_s390_reset_vcpu(S390CPU *cpu); int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit); +void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu); +int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu); #else static inline void kvm_s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, @@ -1121,6 +1123,13 @@ static inline int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, { return 0; } +static inline void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu) +{ +} +static inline int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu) +{ + return 0; +} #endif static inline int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 8e65e43f02..ea18015793 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -45,6 +45,7 @@ #include "hw/s390x/s390-pci-bus.h" #include "hw/s390x/ipl.h" #include "hw/s390x/ebcdic.h" +#include "exec/memattrs.h" /* #define DEBUG_KVM */ @@ -109,6 +110,14 @@ #define ICPT_CPU_STOP 0x28 #define ICPT_IO 0x40 +#define NR_LOCAL_IRQS 32 +/* + * Needs to be big enough to contain max_cpus emergency signals + * and in addition NR_LOCAL_IRQS interrupts + */ +#define VCPU_IRQ_BUF_SIZE (sizeof(struct kvm_s390_irq) * \ + (max_cpus + NR_LOCAL_IRQS)) + static CPUWatchpoint hw_watchpoint; /* * We don't use a list because this structure is also used to transmit the @@ -124,6 +133,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { static int cap_sync_regs; static int cap_async_pf; static int cap_mem_op; +static int cap_s390_irq; static void *legacy_s390_alloc(size_t size, uint64_t *align); @@ -249,6 +259,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS); cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF); cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP); + cap_s390_irq = kvm_check_extension(s, KVM_CAP_S390_INJECT_IRQ); kvm_s390_enable_cmma(s); @@ -272,6 +283,7 @@ int kvm_arch_init_vcpu(CPUState *cs) { S390CPU *cpu = S390_CPU(cs); kvm_s390_set_cpu_state(cpu, cpu->env.cpu_state); + cpu->irqstate = g_malloc0(VCPU_IRQ_BUF_SIZE); return 0; } @@ -769,8 +781,9 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run) { } -void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run) +MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) { + return MEMTXATTRS_UNSPECIFIED; } int kvm_arch_process_async_events(CPUState *cs) @@ -827,10 +840,9 @@ static int s390_kvm_irq_to_interrupt(struct kvm_s390_irq *irq, return r; } -void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq) +static void inject_vcpu_irq_legacy(CPUState *cs, struct kvm_s390_irq *irq) { struct kvm_s390_interrupt kvmint = {}; - CPUState *cs = CPU(cpu); int r; r = s390_kvm_irq_to_interrupt(irq, &kvmint); @@ -846,6 +858,23 @@ void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq) } } +void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq) +{ + CPUState *cs = CPU(cpu); + int r; + + if (cap_s390_irq) { + r = kvm_vcpu_ioctl(cs, KVM_S390_IRQ, irq); + if (!r) { + return; + } + error_report("KVM failed to inject interrupt %llx", irq->type); + exit(1); + } + + inject_vcpu_irq_legacy(cs, irq); +} + static void __kvm_s390_floating_interrupt(struct kvm_s390_irq *irq) { struct kvm_s390_interrupt kvmint = {}; @@ -2041,6 +2070,52 @@ int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) return ret; } +void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu) +{ + struct kvm_s390_irq_state irq_state; + CPUState *cs = CPU(cpu); + int32_t bytes; + + if (!kvm_check_extension(kvm_state, KVM_CAP_S390_IRQ_STATE)) { + return; + } + + irq_state.buf = (uint64_t) cpu->irqstate; + irq_state.len = VCPU_IRQ_BUF_SIZE; + + bytes = kvm_vcpu_ioctl(cs, KVM_S390_GET_IRQ_STATE, &irq_state); + if (bytes < 0) { + cpu->irqstate_saved_size = 0; + error_report("Migration of interrupt state failed"); + return; + } + + cpu->irqstate_saved_size = bytes; +} + +int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu) +{ + CPUState *cs = CPU(cpu); + struct kvm_s390_irq_state irq_state; + int r; + + if (!kvm_check_extension(kvm_state, KVM_CAP_S390_IRQ_STATE)) { + return -ENOSYS; + } + + if (cpu->irqstate_saved_size == 0) { + return 0; + } + irq_state.buf = (uint64_t) cpu->irqstate; + irq_state.len = cpu->irqstate_saved_size; + + r = kvm_vcpu_ioctl(cs, KVM_S390_SET_IRQ_STATE, &irq_state); + if (r) { + error_report("Setting interrupt state failed %d", r); + } + return r; +} + int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, uint64_t address, uint32_t data) { diff --git a/target-s390x/machine.c b/target-s390x/machine.c index bd4cea726d..7853e3c989 100644 --- a/target-s390x/machine.c +++ b/target-s390x/machine.c @@ -28,17 +28,25 @@ static int cpu_post_load(void *opaque, int version_id) */ if (kvm_enabled()) { kvm_s390_set_cpu_state(cpu, cpu->env.cpu_state); + return kvm_s390_vcpu_interrupt_post_load(cpu); } return 0; } +static void cpu_pre_save(void *opaque) +{ + S390CPU *cpu = opaque; -const VMStateDescription vmstate_s390_cpu = { - .name = "cpu", - .post_load = cpu_post_load, - .version_id = 2, - .minimum_version_id = 2, - .fields = (VMStateField[]) { + if (kvm_enabled()) { + kvm_s390_vcpu_interrupt_pre_save(cpu); + } +} + +const VMStateDescription vmstate_fpu = { + .name = "cpu/fpu", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { VMSTATE_UINT64(env.fregs[0].ll, S390CPU), VMSTATE_UINT64(env.fregs[1].ll, S390CPU), VMSTATE_UINT64(env.fregs[2].ll, S390CPU), @@ -55,11 +63,27 @@ const VMStateDescription vmstate_s390_cpu = { VMSTATE_UINT64(env.fregs[13].ll, S390CPU), VMSTATE_UINT64(env.fregs[14].ll, S390CPU), VMSTATE_UINT64(env.fregs[15].ll, S390CPU), + VMSTATE_UINT32(env.fpc, S390CPU), + VMSTATE_END_OF_LIST() + } +}; + +static inline bool fpu_needed(void *opaque) +{ + return true; +} + +const VMStateDescription vmstate_s390_cpu = { + .name = "cpu", + .post_load = cpu_post_load, + .pre_save = cpu_pre_save, + .version_id = 4, + .minimum_version_id = 3, + .fields = (VMStateField[]) { VMSTATE_UINT64_ARRAY(env.regs, S390CPU, 16), VMSTATE_UINT64(env.psw.mask, S390CPU), VMSTATE_UINT64(env.psw.addr, S390CPU), VMSTATE_UINT64(env.psa, S390CPU), - VMSTATE_UINT32(env.fpc, S390CPU), VMSTATE_UINT32(env.todpr, S390CPU), VMSTATE_UINT64(env.pfault_token, S390CPU), VMSTATE_UINT64(env.pfault_compare, S390CPU), @@ -72,6 +96,17 @@ const VMStateDescription vmstate_s390_cpu = { VMSTATE_UINT64_ARRAY(env.cregs, S390CPU, 16), VMSTATE_UINT8(env.cpu_state, S390CPU), VMSTATE_UINT8(env.sigp_order, S390CPU), + VMSTATE_UINT32_V(irqstate_saved_size, S390CPU, 4), + VMSTATE_VBUFFER_UINT32(irqstate, S390CPU, 4, NULL, 0, + irqstate_saved_size), VMSTATE_END_OF_LIST() }, + .subsections = (VMStateSubsection[]) { + { + .vmsd = &vmstate_fpu, + .needed = fpu_needed, + } , { + /* empty */ + } + }, }; diff --git a/translate-all.c b/translate-all.c index 65a76c5b9f..536008f52d 100644 --- a/translate-all.c +++ b/translate-all.c @@ -1416,14 +1416,17 @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr) MemoryRegion *mr; hwaddr l = 1; + rcu_read_lock(); mr = address_space_translate(as, addr, &addr, &l, false); if (!(memory_region_is_ram(mr) || memory_region_is_romd(mr))) { + rcu_read_unlock(); return; } ram_addr = (memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK) + addr; tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0); + rcu_read_unlock(); } #endif /* !defined(CONFIG_USER_ONLY) */ diff --git a/ui/console.c b/ui/console.c index f5295c4688..406c36b864 100644 --- a/ui/console.c +++ b/ui/console.c @@ -126,6 +126,7 @@ struct QemuConsole { Object *device; uint32_t head; QemuUIInfo ui_info; + QEMUTimer *ui_timer; const GraphicHwOps *hw_ops; void *hw; @@ -1383,14 +1384,33 @@ void unregister_displaychangelistener(DisplayChangeListener *dcl) gui_setup_refresh(ds); } +static void dpy_set_ui_info_timer(void *opaque) +{ + QemuConsole *con = opaque; + + con->hw_ops->ui_info(con->hw, con->head, &con->ui_info); +} + +bool dpy_ui_info_supported(QemuConsole *con) +{ + return con->hw_ops->ui_info != NULL; +} + int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info) { assert(con != NULL); con->ui_info = *info; - if (con->hw_ops->ui_info) { - return con->hw_ops->ui_info(con->hw, con->head, info); + if (!dpy_ui_info_supported(con)) { + return -1; } - return -1; + + /* + * Typically we get a flood of these as the user resizes the window. + * Wait until the dust has settled (one second without updates), then + * go notify the guest. + */ + timer_mod(con->ui_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000); + return 0; } void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h) @@ -1724,6 +1744,7 @@ QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head, ds = get_alloc_displaystate(); trace_console_gfx_new(); s = new_console(ds, GRAPHIC_CONSOLE, head); + s->ui_timer = timer_new_ms(QEMU_CLOCK_REALTIME, dpy_set_ui_info_timer, s); graphic_console_set_hwops(s, hw_ops, opaque); if (dev) { object_property_set_link(OBJECT(s), OBJECT(dev), "device", diff --git a/ui/gtk.c b/ui/gtk.c index 51ea1b95ee..c58028f172 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -34,24 +34,11 @@ #define GETTEXT_PACKAGE "qemu" #define LOCALEDIR "po" -#ifdef _WIN32 -# define _WIN32_WINNT 0x0601 /* needed to get definition of MAPVK_VK_TO_VSC */ -#endif - #include "qemu-common.h" -#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE -/* Work around an -Wstrict-prototypes warning in GTK headers */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#endif -#include <gtk/gtk.h> -#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE -#pragma GCC diagnostic pop -#endif - +#include "ui/console.h" +#include "ui/gtk.h" -#include <gdk/gdkkeysyms.h> #include <glib/gi18n.h> #include <locale.h> #if defined(CONFIG_VTE) @@ -60,7 +47,6 @@ #include <math.h> #include "trace.h" -#include "ui/console.h" #include "ui/input.h" #include "sysemu/sysemu.h" #include "qmp-commands.h" @@ -68,10 +54,6 @@ #include "keymaps.h" #include "sysemu/char.h" #include "qom/object.h" -#ifdef GDK_WINDOWING_X11 -#include <gdk/gdkx.h> -#include <X11/XKBlib.h> -#endif #define MAX_VCS 10 #define VC_WINDOW_X_MIN 320 @@ -99,15 +81,6 @@ # define VTE_RESIZE_HACK 1 #endif -/* Compatibility define to let us build on both Gtk2 and Gtk3 */ -#if GTK_CHECK_VERSION(3, 0, 0) -static inline void gdk_drawable_get_size(GdkWindow *w, gint *ww, gint *wh) -{ - *ww = gdk_window_get_width(w); - *wh = gdk_window_get_height(w); -} -#endif - #if !GTK_CHECK_VERSION(2, 20, 0) #define gtk_widget_get_realized(widget) GTK_WIDGET_REALIZED(widget) #endif @@ -138,48 +111,6 @@ static const int modifier_keycode[] = { 0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8, 0xdb, 0xdd, }; -typedef struct GtkDisplayState GtkDisplayState; - -typedef struct VirtualGfxConsole { - GtkWidget *drawing_area; - DisplayChangeListener dcl; - DisplaySurface *ds; - pixman_image_t *convert; - cairo_surface_t *surface; - double scale_x; - double scale_y; -} VirtualGfxConsole; - -#if defined(CONFIG_VTE) -typedef struct VirtualVteConsole { - GtkWidget *box; - GtkWidget *scrollbar; - GtkWidget *terminal; - CharDriverState *chr; -} VirtualVteConsole; -#endif - -typedef enum VirtualConsoleType { - GD_VC_GFX, - GD_VC_VTE, -} VirtualConsoleType; - -typedef struct VirtualConsole { - GtkDisplayState *s; - char *label; - GtkWidget *window; - GtkWidget *menu_item; - GtkWidget *tab_item; - GtkWidget *focus; - VirtualConsoleType type; - union { - VirtualGfxConsole gfx; -#if defined(CONFIG_VTE) - VirtualVteConsole vte; -#endif - }; -} VirtualConsole; - struct GtkDisplayState { GtkWidget *window; @@ -532,6 +463,8 @@ static void gd_mouse_set(DisplayChangeListener *dcl, gdk_device_warp(gdk_device_manager_get_client_pointer(mgr), gtk_widget_get_screen(vc->gfx.drawing_area), x_root, y_root); + vc->s->last_x = x; + vc->s->last_y = y; } #else static void gd_mouse_set(DisplayChangeListener *dcl, @@ -1478,6 +1411,19 @@ static gboolean gd_focus_out_event(GtkWidget *widget, return TRUE; } +static gboolean gd_configure(GtkWidget *widget, + GdkEventConfigure *cfg, gpointer opaque) +{ + VirtualConsole *vc = opaque; + QemuUIInfo info; + + memset(&info, 0, sizeof(info)); + info.width = cfg->width; + info.height = cfg->height; + dpy_set_ui_info(vc->gfx.dcl.con, &info); + return FALSE; +} + /** Virtual Console Callbacks **/ static GSList *gd_vc_menu_init(GtkDisplayState *s, VirtualConsole *vc, @@ -1655,6 +1601,8 @@ static void gd_connect_vc_gfx_signals(VirtualConsole *vc) G_CALLBACK(gd_leave_event), vc); g_signal_connect(vc->gfx.drawing_area, "focus-out-event", G_CALLBACK(gd_focus_out_event), vc); + g_signal_connect(vc->gfx.drawing_area, "configure-event", + G_CALLBACK(gd_configure), vc); } else { g_signal_connect(vc->gfx.drawing_area, "key-press-event", G_CALLBACK(gd_text_key_down), vc); @@ -1772,6 +1720,10 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc, gd_connect_vc_gfx_signals(vc); group = gd_vc_menu_init(s, vc, idx, group, view_menu); + if (dpy_ui_info_supported(vc->gfx.dcl.con)) { + gtk_menu_item_activate(GTK_MENU_ITEM(s->zoom_fit_item)); + } + return group; } |