diff options
-rw-r--r-- | MAINTAINERS | 59 | ||||
-rw-r--r-- | docs/writing-qmp-commands.txt | 2 | ||||
-rw-r--r-- | hw/core/irq.c | 8 | ||||
-rw-r--r-- | hw/core/qdev.c | 70 | ||||
-rw-r--r-- | hw/core/sysbus.c | 20 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-bus.c | 6 | ||||
-rw-r--r-- | hw/s390x/virtio-ccw.c | 6 | ||||
-rw-r--r-- | hw/scsi/virtio-scsi-dataplane.c | 102 | ||||
-rw-r--r-- | hw/scsi/virtio-scsi.c | 31 | ||||
-rw-r--r-- | hw/usb/hcd-uhci.c | 3 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 15 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.c | 7 | ||||
-rw-r--r-- | include/hw/irq.h | 1 | ||||
-rw-r--r-- | include/hw/qdev-core.h | 6 | ||||
-rw-r--r-- | include/hw/sysbus.h | 7 | ||||
-rw-r--r-- | include/hw/virtio/virtio-scsi.h | 2 | ||||
-rw-r--r-- | libcacard/cac.c | 10 | ||||
-rw-r--r-- | libcacard/vcard.c | 5 | ||||
-rw-r--r-- | libcacard/vcard_emul.h | 1 | ||||
-rw-r--r-- | libcacard/vcard_emul_nss.c | 16 | ||||
-rw-r--r-- | qemu-options.hx | 12 | ||||
-rw-r--r-- | qom/object.c | 16 | ||||
-rw-r--r-- | qtest.c | 24 | ||||
-rwxr-xr-x | scripts/get_maintainer.pl | 28 | ||||
-rw-r--r-- | target-i386/cpu.c | 36 | ||||
-rw-r--r-- | target-i386/cpu.h | 61 | ||||
-rw-r--r-- | target-i386/kvm.c | 19 | ||||
-rw-r--r-- | target-i386/machine.c | 87 | ||||
-rw-r--r-- | ui/gtk.c | 14 |
29 files changed, 542 insertions, 132 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index bf7b447..94366ef 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -62,11 +62,23 @@ L: secalert@redhat.com Guest CPU cores (TCG): ---------------------- +Overall +L: qemu-devel@nongnu.org +S: Odd fixes +F: cpu-exec.c +F: cputlb.c +F: softmmu_template.h +F: translate-all.c +F: include/exec/cpu_ldst.h +F: include/exec/cpu_ldst_template.h +F: include/exec/helper*.h + Alpha M: Richard Henderson <rth@twiddle.net> S: Maintained F: target-alpha/ F: hw/alpha/ +F: tests/tcg/alpha/ ARM M: Peter Maydell <peter.maydell@linaro.org> @@ -80,6 +92,7 @@ M: Edgar E. Iglesias <edgar.iglesias@gmail.com> S: Maintained F: target-cris/ F: hw/cris/ +F: tests/tcg/cris/ LM32 M: Michael Walle <michael@walle.cc> @@ -87,6 +100,7 @@ S: Maintained F: target-lm32/ F: hw/lm32/ F: hw/char/lm32_* +F: tests/tcg/lm32/ M68K S: Orphan @@ -105,6 +119,7 @@ M: Leon Alrae <leon.alrae@imgtec.com> S: Maintained F: target-mips/ F: hw/mips/ +F: tests/tcg/mips/ Moxie M: Anthony Green <green@moxielogic.com> @@ -116,6 +131,7 @@ M: Jia Liu <proljc@gmail.com> S: Maintained F: target-openrisc/ F: hw/openrisc/ +F: tests/tcg/openrisc/ PowerPC M: Alexander Graf <agraf@suse.de> @@ -151,7 +167,8 @@ F: target-unicore32/ F: hw/unicore32/ X86 -M: qemu-devel@nongnu.org +M: Paolo Bonzini <pbonzini@redhat.com> +M: Richard Henderson <rth@twiddle.net> S: Odd Fixes F: target-i386/ F: hw/i386/ @@ -162,6 +179,7 @@ W: http://wiki.osll.spb.ru/doku.php?id=etc:users:jcmvbkbc:qemu-target-xtensa S: Maintained F: target-xtensa/ F: hw/xtensa/ +F: tests/tcg/xtensa/ TriCore M: Bastian Koppelmann <kbastian@mail.uni-paderborn.de> @@ -205,6 +223,7 @@ F: hw/intc/s390_flic_kvm.c F: include/hw/s390x/s390_flic.h X86 +M: Paolo Bonzini <pbonzini@redhat.com> M: Marcelo Tosatti <mtosatti@redhat.com> L: kvm@vger.kernel.org S: Supported @@ -270,7 +289,7 @@ F: include/hw/arm/digic.h F: hw/*/digic* Gumstix -M: qemu-devel@nongnu.org +L: qemu-devel@nongnu.org S: Orphan F: hw/arm/gumstix.c @@ -286,7 +305,7 @@ S: Maintained F: hw/arm/integratorcp.c Mainstone -M: qemu-devel@nongnu.org +L: qemu-devel@nongnu.org S: Orphan F: hw/arm/mainstone.c @@ -392,7 +411,7 @@ S: Maintained F: hw/mips/mips_malta.c Mipssim -M: qemu-devel@nongnu.org +L: qemu-devel@nongnu.org S: Orphan F: hw/mips/mips_mipssim.c @@ -628,6 +647,12 @@ S: Maintained F: hw/usb/* F: tests/usb-*-test.c +USB (serial adapter) +M: Gerd Hoffmann <kraxel@redhat.com> +M: Samuel Thibault <samuel.thibault@ens-lyon.org> +S: Maintained +F: hw/usb/dev-serial.c + VFIO M: Alex Williamson <alex.williamson@redhat.com> S: Supported @@ -726,8 +751,16 @@ T: git git://github.com/stefanha/qemu.git block Character Devices M: Anthony Liguori <aliguori@amazon.com> +M: Paolo Bonzini <pbonzini@redhat.com> S: Maintained F: qemu-char.c +F: backends/msmouse.c +F: backends/testdev.c + +Character Devices (Braille) +M: Samuel Thibault <samuel.thibault@ens-lyon.org> +S: Maintained +F: backends/baum.c CPU M: Andreas Färber <afaerber@suse.de> @@ -749,7 +782,7 @@ S: Maintained F: device_tree.[ch] GDB stub -M: qemu-devel@nongnu.org +L: qemu-devel@nongnu.org S: Odd Fixes F: gdbstub* F: gdb-xml/ @@ -786,7 +819,11 @@ F: ui/cocoa.m Main loop M: Anthony Liguori <aliguori@amazon.com> -S: Supported +M: Paolo Bonzini <pbonzini@redhat.com> +S: Maintained +F: cpus.c +F: main-loop.c +F: qemu-timer.c F: vl.c Human Monitor (HMP) @@ -825,6 +862,7 @@ M: Luiz Capitulino <lcapitulino@redhat.com> M: Michael Roth <mdroth@linux.vnet.ibm.com> S: Maintained F: qapi/ +F: tests/qapi-schema/ T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp QAPI Schema @@ -889,6 +927,12 @@ F: include/sysemu/seccomp.h Usermode Emulation ------------------ +Overall +M: Riku Voipio <riku.voipio@iki.fi> +S: Maintained +F: thunk.c +F: user-exec.c + BSD user M: Blue Swirl <blauwirbel@gmail.com> S: Maintained @@ -902,7 +946,6 @@ F: linux-user/ Tiny Code Generator (TCG) ------------------------- Common code -M: qemu-devel@nongnu.org M: Richard Henderson <rth@twiddle.net> S: Maintained F: tcg/ @@ -919,7 +962,7 @@ S: Maintained F: tcg/arm/ i386 target -M: qemu-devel@nongnu.org +L: qemu-devel@nongnu.org S: Maintained F: tcg/i386/ diff --git a/docs/writing-qmp-commands.txt b/docs/writing-qmp-commands.txt index 4d86c24..f3df206 100644 --- a/docs/writing-qmp-commands.txt +++ b/docs/writing-qmp-commands.txt @@ -365,6 +365,8 @@ documentation for information about the other types. === User Defined Types === +FIXME This example needs to be redone after commit 6d32717 + For this example we will write the query-alarm-clock command, which returns information about QEMU's timer alarm. For more information about it, please check the "-clock" command-line option. diff --git a/hw/core/irq.c b/hw/core/irq.c index cffced0..8a62a36 100644 --- a/hw/core/irq.c +++ b/hw/core/irq.c @@ -140,16 +140,10 @@ void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n) for (i = 0; i < n; i++) { *old_irqs[i] = *gpio_in[i]; gpio_in[i]->handler = handler; - gpio_in[i]->opaque = old_irqs; + gpio_in[i]->opaque = &old_irqs[i]; } } -void qemu_irq_intercept_out(qemu_irq **gpio_out, qemu_irq_handler handler, int n) -{ - qemu_irq *old_irqs = *gpio_out; - *gpio_out = qemu_allocate_irqs(handler, old_irqs, n); -} - static const TypeInfo irq_type_info = { .name = TYPE_IRQ, .parent = TYPE_OBJECT, diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 9357aba..b3d5196 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -404,9 +404,7 @@ void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, char *propname = g_strdup_printf("%s[*]", name ? name : "unnamed-gpio-out"); assert(gpio_list->num_in == 0 || !name); - assert(gpio_list->num_out == 0); - gpio_list->num_out = n; - gpio_list->out = pins; + gpio_list->num_out += n; for (i = 0; i < n; ++i) { memset(&pins[i], 0, sizeof(*pins)); @@ -440,10 +438,44 @@ qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, qemu_irq pin) { - NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); + char *propname = g_strdup_printf("%s[%d]", + name ? name : "unnamed-gpio-out", n); + if (pin) { + /* We need a name for object_property_set_link to work. If the + * object has a parent, object_property_add_child will come back + * with an error without doing anything. If it has none, it will + * never fail. So we can just call it with a NULL Error pointer. + */ + object_property_add_child(qdev_get_machine(), "non-qdev-gpio[*]", + OBJECT(pin), NULL); + } + object_property_set_link(OBJECT(dev), OBJECT(pin), propname, &error_abort); + g_free(propname); +} + +/* disconnect a GPIO ouput, returning the disconnected input (if any) */ + +static qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev, + const char *name, int n) +{ + char *propname = g_strdup_printf("%s[%d]", + name ? name : "unnamed-gpio-out", n); + + qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname, + NULL); + if (ret) { + object_property_set_link(OBJECT(dev), NULL, propname, NULL); + } + g_free(propname); + return ret; +} - assert(n >= 0 && n < gpio_list->num_out); - gpio_list->out[n] = pin; +qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt, + const char *name, int n) +{ + qemu_irq disconnected = qdev_disconnect_gpio_out_named(dev, name, n); + qdev_connect_gpio_out_named(dev, name, n, icpt); + return disconnected; } void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) @@ -451,6 +483,32 @@ void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) qdev_connect_gpio_out_named(dev, NULL, n, pin); } +void qdev_pass_gpios(DeviceState *dev, DeviceState *container, + const char *name) +{ + int i; + NamedGPIOList *ngl = qdev_get_named_gpio_list(dev, name); + + for (i = 0; i < ngl->num_in; i++) { + const char *nm = ngl->name ? ngl->name : "unnamed-gpio-in"; + char *propname = g_strdup_printf("%s[%d]", nm, i); + + object_property_add_alias(OBJECT(container), propname, + OBJECT(dev), propname, + &error_abort); + } + for (i = 0; i < ngl->num_out; i++) { + const char *nm = ngl->name ? ngl->name : "unnamed-gpio-out"; + char *propname = g_strdup_printf("%s[%d]", nm, i); + + object_property_add_alias(OBJECT(container), propname, + OBJECT(dev), propname, + &error_abort); + } + QLIST_REMOVE(ngl, node); + QLIST_INSERT_HEAD(&container->gpios, ngl, node); +} + BusState *qdev_get_child_bus(DeviceState *dev, const char *name) { BusState *bus; diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c index 414e2a1..e55c3c1 100644 --- a/hw/core/sysbus.c +++ b/hw/core/sysbus.c @@ -41,11 +41,7 @@ static const TypeInfo system_bus_info = { void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) { - assert(n >= 0 && n < dev->num_irq); - dev->irqs[n] = NULL; - if (dev->irqp[n]) { - *dev->irqp[n] = irq; - } + qdev_connect_gpio_out_named(DEVICE(dev), SYSBUS_DEVICE_GPIO_IRQ, n, irq); } static void sysbus_mmio_map_common(SysBusDevice *dev, int n, hwaddr addr, @@ -89,22 +85,13 @@ void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr, /* Request an IRQ source. The actual IRQ object may be populated later. */ void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p) { - int n; - - assert(dev->num_irq < QDEV_MAX_IRQ); - n = dev->num_irq++; - dev->irqp[n] = p; + qdev_init_gpio_out_named(DEVICE(dev), p, SYSBUS_DEVICE_GPIO_IRQ, 1); } /* Pass IRQs from a target device. */ void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target) { - int i; - assert(dev->num_irq == 0); - dev->num_irq = target->num_irq; - for (i = 0; i < dev->num_irq; i++) { - dev->irqp[i] = target->irqp[i]; - } + qdev_pass_gpios(DEVICE(target), DEVICE(dev), SYSBUS_DEVICE_GPIO_IRQ); } void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory) @@ -210,7 +197,6 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent) hwaddr size; int i; - monitor_printf(mon, "%*sirq %d\n", indent, "", s->num_irq); for (i = 0; i < s->num_mmio; i++) { size = memory_region_size(s->mmio[i].memory); monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n", diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index 2059874..39dc201 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -311,10 +311,8 @@ static void s390_virtio_rng_instance_init(Object *obj) virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG); - object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, - (Object **)&dev->vdev.conf.rng, - qdev_prop_allow_set_link_before_realize, - OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL); + object_property_add_alias(obj, "rng", OBJECT(&dev->vdev), + "rng", &error_abort); } static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 1c0d913..ea236c9 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1544,10 +1544,8 @@ static void virtio_ccw_rng_instance_init(Object *obj) virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG); - object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, - (Object **)&dev->vdev.conf.rng, - qdev_prop_allow_set_link_before_realize, - OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL); + object_property_add_alias(obj, "rng", OBJECT(&dev->vdev), + "rng", &error_abort); } static Property virtio_ccw_rng_properties[] = { diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 48dcfd2..3097d54 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -46,11 +46,15 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s, BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); VirtIOSCSIVring *r = g_slice_new(VirtIOSCSIVring); + int rc; /* Set up virtqueue notify */ - if (k->set_host_notifier(qbus->parent, n, true) != 0) { - fprintf(stderr, "virtio-scsi: Failed to set host notifier\n"); - exit(1); + rc = k->set_host_notifier(qbus->parent, n, true); + if (rc != 0) { + fprintf(stderr, "virtio-scsi: Failed to set host notifier (%d)\n", + rc); + s->dataplane_fenced = true; + return NULL; } r->host_notifier = *virtio_queue_get_host_notifier(vq); r->guest_notifier = *virtio_queue_get_guest_notifier(vq); @@ -60,9 +64,15 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s, if (!vring_setup(&r->vring, VIRTIO_DEVICE(s), n)) { fprintf(stderr, "virtio-scsi: VRing setup failed\n"); - exit(1); + goto fail_vring; } return r; + +fail_vring: + aio_set_event_notifier(s->ctx, &r->host_notifier, NULL); + k->set_host_notifier(qbus->parent, n, false); + g_slice_free(VirtIOSCSIVring, r); + return NULL; } VirtIOSCSIReq *virtio_scsi_pop_req_vring(VirtIOSCSI *s, @@ -138,6 +148,46 @@ static void virtio_scsi_iothread_handle_cmd(EventNotifier *notifier) } } +/* assumes s->ctx held */ +static void virtio_scsi_clear_aio(VirtIOSCSI *s) +{ + VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s); + int i; + + if (s->ctrl_vring) { + aio_set_event_notifier(s->ctx, &s->ctrl_vring->host_notifier, NULL); + } + if (s->event_vring) { + aio_set_event_notifier(s->ctx, &s->event_vring->host_notifier, NULL); + } + if (s->cmd_vrings) { + for (i = 0; i < vs->conf.num_queues && s->cmd_vrings[i]; i++) { + aio_set_event_notifier(s->ctx, &s->cmd_vrings[i]->host_notifier, NULL); + } + } +} + +static void virtio_scsi_vring_teardown(VirtIOSCSI *s) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(s); + VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s); + int i; + + if (s->ctrl_vring) { + vring_teardown(&s->ctrl_vring->vring, vdev, 0); + } + if (s->event_vring) { + vring_teardown(&s->event_vring->vring, vdev, 1); + } + if (s->cmd_vrings) { + for (i = 0; i < vs->conf.num_queues && s->cmd_vrings[i]; i++) { + vring_teardown(&s->cmd_vrings[i]->vring, vdev, 2 + i); + } + free(s->cmd_vrings); + s->cmd_vrings = NULL; + } +} + /* Context: QEMU global mutex held */ void virtio_scsi_dataplane_start(VirtIOSCSI *s) { @@ -149,38 +199,62 @@ void virtio_scsi_dataplane_start(VirtIOSCSI *s) if (s->dataplane_started || s->dataplane_starting || + s->dataplane_fenced || s->ctx != iothread_get_aio_context(vs->conf.iothread)) { return; } s->dataplane_starting = true; + assert(!s->blocker); + error_setg(&s->blocker, "block device is in use by data plane"); /* Set up guest notifier (irq) */ rc = k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, true); if (rc != 0) { - fprintf(stderr, "virtio-scsi: Failed to set guest notifiers, " - "ensure -enable-kvm is set\n"); - exit(1); + fprintf(stderr, "virtio-scsi: Failed to set guest notifiers (%d), " + "ensure -enable-kvm is set\n", rc); + s->dataplane_fenced = true; + goto fail_guest_notifiers; } aio_context_acquire(s->ctx); s->ctrl_vring = virtio_scsi_vring_init(s, vs->ctrl_vq, virtio_scsi_iothread_handle_ctrl, 0); + if (!s->ctrl_vring) { + goto fail_vrings; + } s->event_vring = virtio_scsi_vring_init(s, vs->event_vq, virtio_scsi_iothread_handle_event, 1); + if (!s->event_vring) { + goto fail_vrings; + } s->cmd_vrings = g_malloc0(sizeof(VirtIOSCSIVring) * vs->conf.num_queues); for (i = 0; i < vs->conf.num_queues; i++) { s->cmd_vrings[i] = virtio_scsi_vring_init(s, vs->cmd_vqs[i], virtio_scsi_iothread_handle_cmd, i + 2); + if (!s->cmd_vrings[i]) { + goto fail_vrings; + } } aio_context_release(s->ctx); s->dataplane_starting = false; s->dataplane_started = true; + +fail_vrings: + virtio_scsi_clear_aio(s); + aio_context_release(s->ctx); + virtio_scsi_vring_teardown(s); + for (i = 0; i < vs->conf.num_queues + 2; i++) { + k->set_host_notifier(qbus->parent, i, false); + } + k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, false); +fail_guest_notifiers: + s->dataplane_starting = false; } /* Context: QEMU global mutex held */ @@ -188,13 +262,19 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s) { BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); - VirtIODevice *vdev = VIRTIO_DEVICE(s); VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s); int i; + /* Better luck next time. */ + if (s->dataplane_fenced) { + s->dataplane_fenced = false; + return; + } if (!s->dataplane_started || s->dataplane_stopping) { return; } + error_free(s->blocker); + s->blocker = NULL; s->dataplane_stopping = true; assert(s->ctx == iothread_get_aio_context(vs->conf.iothread)); @@ -213,11 +293,7 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s) /* Sync vring state back to virtqueue so that non-dataplane request * processing can continue when we disable the host notifier below. */ - vring_teardown(&s->ctrl_vring->vring, vdev, 0); - vring_teardown(&s->event_vring->vring, vdev, 1); - for (i = 0; i < vs->conf.num_queues; i++) { - vring_teardown(&s->cmd_vrings[i]->vring, vdev, 2 + i); - } + virtio_scsi_vring_teardown(s); for (i = 0; i < vs->conf.num_queues + 2; i++) { k->set_host_notifier(qbus->parent, i, false); diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index a1725b8..7d40ecc 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -369,7 +369,7 @@ fail: void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req) { VirtIODevice *vdev = (VirtIODevice *)s; - int type; + uint32_t type; int r = 0; if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0, @@ -378,8 +378,8 @@ void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req) return; } - virtio_tswap32s(vdev, &req->req.tmf.type); - if (req->req.tmf.type == VIRTIO_SCSI_T_TMF) { + virtio_tswap32s(vdev, &type); + if (type == VIRTIO_SCSI_T_TMF) { if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlTMFReq), sizeof(VirtIOSCSICtrlTMFResp)) < 0) { virtio_scsi_bad_req(); @@ -387,8 +387,8 @@ void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req) r = virtio_scsi_do_tmf(s, req); } - } else if (req->req.tmf.type == VIRTIO_SCSI_T_AN_QUERY || - req->req.tmf.type == VIRTIO_SCSI_T_AN_SUBSCRIBE) { + } else if (type == VIRTIO_SCSI_T_AN_QUERY || + type == VIRTIO_SCSI_T_AN_SUBSCRIBE) { if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlANReq), sizeof(VirtIOSCSICtrlANResp)) < 0) { virtio_scsi_bad_req(); @@ -448,7 +448,7 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status, sense_len = scsi_req_get_sense(r, sense, sizeof(sense)); sense_len = MIN(sense_len, req->resp_iov.size - sizeof(req->resp.cmd)); qemu_iovec_from_buf(&req->resp_iov, sizeof(req->resp.cmd), - &req->resp, sense_len); + sense, sense_len); req->resp.cmd.sense_len = virtio_tswap32(vdev, sense_len); } virtio_scsi_complete_cmd_req(req); @@ -742,9 +742,18 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev); + VirtIOSCSI *s = VIRTIO_SCSI(vdev); + SCSIDevice *sd = SCSI_DEVICE(dev); + + if (s->ctx && !s->dataplane_disabled) { + if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) { + return; + } + blk_op_block_all(sd->conf.blk, s->blocker); + } if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { - virtio_scsi_push_event(VIRTIO_SCSI(hotplug_dev), SCSI_DEVICE(dev), + virtio_scsi_push_event(s, sd, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_RESCAN); } @@ -754,12 +763,18 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev); + VirtIOSCSI *s = VIRTIO_SCSI(vdev); + SCSIDevice *sd = SCSI_DEVICE(dev); if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { - virtio_scsi_push_event(VIRTIO_SCSI(hotplug_dev), SCSI_DEVICE(dev), + virtio_scsi_push_event(s, sd, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_REMOVED); } + + if (s->ctx) { + blk_op_unblock_all(sd->conf.blk, s->blocker); + } qdev_simple_device_unplug_cb(hotplug_dev, dev, errp); } diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 5b88f30..4a4215d 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -35,9 +35,6 @@ #include "trace.h" #include "qemu/main-loop.h" -//#define DEBUG -//#define DEBUG_DUMP_DATA - #define FRAME_TIMER_FREQ 1000 #define FRAME_MAX_LOOPS 256 diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index a27c9d3..2930b72 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -459,6 +459,7 @@ struct XHCIState { uint32_t numintrs; uint32_t numslots; uint32_t flags; + uint32_t max_pstreams_mask; /* Operational Registers */ uint32_t usbcmd; @@ -500,6 +501,7 @@ enum xhci_flags { XHCI_FLAG_USE_MSI_X, XHCI_FLAG_SS_FIRST, XHCI_FLAG_FORCE_PCIE_ENDCAP, + XHCI_FLAG_ENABLE_STREAMS, }; static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, @@ -1384,7 +1386,7 @@ static void xhci_init_epctx(XHCIEPContext *epctx, epctx->pctx = pctx; epctx->max_psize = ctx[1]>>16; epctx->max_psize *= 1+((ctx[1]>>8)&0xff); - epctx->max_pstreams = (ctx[0] >> 10) & 0xf; + epctx->max_pstreams = (ctx[0] >> 10) & epctx->xhci->max_pstreams_mask; epctx->lsa = (ctx[0] >> 15) & 1; if (epctx->max_pstreams) { xhci_alloc_streams(epctx, dequeue); @@ -2956,9 +2958,9 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size) break; case 0x10: /* HCCPARAMS */ if (sizeof(dma_addr_t) == 4) { - ret = 0x00087000; + ret = 0x00080000 | (xhci->max_pstreams_mask << 12); } else { - ret = 0x00087001; + ret = 0x00080001 | (xhci->max_pstreams_mask << 12); } break; case 0x14: /* DBOFF */ @@ -3590,6 +3592,11 @@ static int usb_xhci_initfn(struct PCIDevice *dev) if (xhci->numslots < 1) { xhci->numslots = 1; } + if (xhci_get_flag(xhci, XHCI_FLAG_ENABLE_STREAMS)) { + xhci->max_pstreams_mask = 7; /* == 256 primary streams */ + } else { + xhci->max_pstreams_mask = 0; + } xhci->mfwrap_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_mfwrap_timer, xhci); @@ -3853,6 +3860,8 @@ static Property xhci_properties[] = { XHCIState, flags, XHCI_FLAG_SS_FIRST, true), DEFINE_PROP_BIT("force-pcie-endcap", XHCIState, flags, XHCI_FLAG_FORCE_PCIE_ENDCAP, false), + DEFINE_PROP_BIT("streams", XHCIState, flags, + XHCI_FLAG_ENABLE_STREAMS, true), DEFINE_PROP_UINT32("intrs", XHCIState, numintrs, MAXINTRS), DEFINE_PROP_UINT32("slots", XHCIState, numslots, MAXSLOTS), DEFINE_PROP_UINT32("p2", XHCIState, numports_2, 4), diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 542fb9e..e490ade 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1525,11 +1525,8 @@ static void virtio_rng_initfn(Object *obj) virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG); - object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, - (Object **)&dev->vdev.conf.rng, - qdev_prop_allow_set_link_before_realize, - OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL); - + object_property_add_alias(obj, "rng", OBJECT(&dev->vdev), "rng", + &error_abort); } static const TypeInfo virtio_rng_pci_info = { diff --git a/include/hw/irq.h b/include/hw/irq.h index 6f874f5..4c4c2ea 100644 --- a/include/hw/irq.h +++ b/include/hw/irq.h @@ -61,6 +61,5 @@ qemu_irq *qemu_irq_proxy(qemu_irq **target, int n); /* For internal use in qtest. Similar to qemu_irq_split, but operating on an existing vector of qemu_irq. */ void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n); -void qemu_irq_intercept_out(qemu_irq **gpio_out, qemu_irq_handler handler, int n); #endif diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 22820fe..00a15a3 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -136,7 +136,6 @@ struct NamedGPIOList { char *name; qemu_irq *in; int num_in; - qemu_irq *out; int num_out; QLIST_ENTRY(NamedGPIOList) node; }; @@ -273,6 +272,8 @@ qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n); void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, qemu_irq pin); +qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt, + const char *name, int n); BusState *qdev_get_child_bus(DeviceState *dev, const char *name); @@ -287,6 +288,9 @@ void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler, void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, const char *name, int n); +void qdev_pass_gpios(DeviceState *dev, DeviceState *container, + const char *name); + BusState *qdev_get_parent_bus(DeviceState *dev); /*** BUS API. ***/ diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h index 0bb91a8..9fb1782 100644 --- a/include/hw/sysbus.h +++ b/include/hw/sysbus.h @@ -8,7 +8,6 @@ #define QDEV_MAX_MMIO 32 #define QDEV_MAX_PIO 32 -#define QDEV_MAX_IRQ 512 #define TYPE_SYSTEM_BUS "System" #define SYSTEM_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS) @@ -33,6 +32,9 @@ typedef struct SysBusDevice SysBusDevice; * SysBusDeviceClass is not overriding #DeviceClass.realize, so derived * classes overriding it are not required to invoke its implementation. */ + +#define SYSBUS_DEVICE_GPIO_IRQ "sysbus-irq" + typedef struct SysBusDeviceClass { /*< private >*/ DeviceClass parent_class; @@ -46,9 +48,6 @@ struct SysBusDevice { DeviceState parent_obj; /*< public >*/ - int num_irq; - qemu_irq irqs[QDEV_MAX_IRQ]; - qemu_irq *irqp[QDEV_MAX_IRQ]; int num_mmio; struct { hwaddr addr; diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index d6e5e79..9e1a49c 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -195,6 +195,8 @@ typedef struct VirtIOSCSI { bool dataplane_starting; bool dataplane_stopping; bool dataplane_disabled; + bool dataplane_fenced; + Error *blocker; Notifier migration_state_notifier; } VirtIOSCSI; diff --git a/libcacard/cac.c b/libcacard/cac.c index ae8c378..f38fdce 100644 --- a/libcacard/cac.c +++ b/libcacard/cac.c @@ -115,6 +115,7 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu, VCardAppletPrivate *applet_private; int size, next; unsigned char *sign_buffer; + bool retain_sign_buffer = FALSE; vcard_7816_status_t status; VCardStatus ret = VCARD_FAIL; @@ -178,6 +179,7 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu, pki_applet->sign_buffer = sign_buffer; pki_applet->sign_buffer_len = size; *response = vcard_make_response(VCARD7816_STATUS_SUCCESS); + retain_sign_buffer = TRUE; break; case 0x00: /* we now have the whole buffer, do the operation, result will be @@ -200,9 +202,11 @@ cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu, VCARD7816_STATUS_ERROR_P1_P2_INCORRECT); break; } - g_free(sign_buffer); - pki_applet->sign_buffer = NULL; - pki_applet->sign_buffer_len = 0; + if (!retain_sign_buffer) { + g_free(sign_buffer); + pki_applet->sign_buffer = NULL; + pki_applet->sign_buffer_len = 0; + } ret = VCARD_DONE; break; case CAC_READ_BUFFER: diff --git a/libcacard/vcard.c b/libcacard/vcard.c index 87ad516..d140a8e 100644 --- a/libcacard/vcard.c +++ b/libcacard/vcard.c @@ -250,6 +250,11 @@ void vcard_select_applet(VCard *card, int channel, VCardApplet *applet) { assert(channel < MAX_CHANNEL); + + /* If using an emulated card, make sure to log out of any already logged in + * session. */ + vcard_emul_logout(card); + card->current_applet[channel] = applet; /* reset the applet */ if (applet && applet->reset_applet) { diff --git a/libcacard/vcard_emul.h b/libcacard/vcard_emul.h index 963563f..f09ee98 100644 --- a/libcacard/vcard_emul.h +++ b/libcacard/vcard_emul.h @@ -40,6 +40,7 @@ int vcard_emul_get_login_count(VCard *card); /* login into the card, return the 7816 status word (sw2 || sw1) */ vcard_7816_status_t vcard_emul_login(VCard *card, unsigned char *pin, int pin_len); +void vcard_emul_logout(VCard *card); /* * key functions diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c index 07b4464..950edee 100644 --- a/libcacard/vcard_emul_nss.c +++ b/libcacard/vcard_emul_nss.c @@ -401,7 +401,7 @@ vcard_emul_login(VCard *card, unsigned char *pin, int pin_len) } void -vcard_emul_reset(VCard *card, VCardPower power) +vcard_emul_logout(VCard *card) { PK11SlotInfo *slot; @@ -409,16 +409,24 @@ vcard_emul_reset(VCard *card, VCardPower power) return; } + slot = vcard_emul_card_get_slot(card); + if (PK11_IsLoggedIn(slot, NULL)) { + PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */ + } +} + +void +vcard_emul_reset(VCard *card, VCardPower power) +{ /* * if we reset the card (either power on or power off), we lose our login * state */ + vcard_emul_logout(card); + /* TODO: we may also need to send insertion/removal events? */ - slot = vcard_emul_card_get_slot(card); - PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */ } - static VReader * vcard_emul_find_vreader_from_slot(PK11SlotInfo *slot) { diff --git a/qemu-options.hx b/qemu-options.hx index 22cf3b9..1e7d5b8 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2989,16 +2989,8 @@ Load the contents of @var{file} as an option ROM. This option is useful to load things like EtherBoot. ETEXI -DEF("clock", HAS_ARG, QEMU_OPTION_clock, \ - "-clock force the use of the given methods for timer alarm.\n" \ - " To see what timers are available use '-clock help'\n", - QEMU_ARCH_ALL) -STEXI -@item -clock @var{method} -@findex -clock -Force the use of the given methods for timer alarm. To see what timers -are available use @code{-clock help}. -ETEXI +HXCOMM Silently ignored for compatibility +DEF("clock", HAS_ARG, QEMU_OPTION_clock, "", QEMU_ARCH_ALL) HXCOMM Options deprecated by -rtc DEF("localtime", 0, QEMU_OPTION_localtime, "", QEMU_ARCH_ALL) diff --git a/qom/object.c b/qom/object.c index a751367..1812c73 100644 --- a/qom/object.c +++ b/qom/object.c @@ -872,9 +872,13 @@ char *object_property_get_str(Object *obj, const char *name, void object_property_set_link(Object *obj, Object *value, const char *name, Error **errp) { - gchar *path = object_get_canonical_path(value); - object_property_set_str(obj, path, name, errp); - g_free(path); + if (value) { + gchar *path = object_get_canonical_path(value); + object_property_set_str(obj, path, name, errp); + g_free(path); + } else { + object_property_set_str(obj, "", name, errp); + } } Object *object_property_get_link(Object *obj, const char *name, @@ -1085,6 +1089,11 @@ void object_property_add_child(Object *obj, const char *name, gchar *type; ObjectProperty *op; + if (child->parent != NULL) { + error_setg(errp, "child object is already parented"); + return; + } + type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child))); op = object_property_add(obj, name, type, object_get_child_property, NULL, @@ -1096,7 +1105,6 @@ void object_property_add_child(Object *obj, const char *name, op->resolve = object_resolve_child_property; object_ref(child); - g_assert(child->parent == NULL); child->parent = obj; out: @@ -201,8 +201,8 @@ static void GCC_FMT_ATTR(2, 3) qtest_send(CharDriverState *chr, static void qtest_irq_handler(void *opaque, int n, int level) { - qemu_irq *old_irqs = opaque; - qemu_set_irq(old_irqs[n], level); + qemu_irq old_irq = *(qemu_irq *)opaque; + qemu_set_irq(old_irq, level); if (irq_levels[n] != level) { CharDriverState *chr = qtest_chr; @@ -264,8 +264,15 @@ static void qtest_process_command(CharDriverState *chr, gchar **words) continue; } if (words[0][14] == 'o') { - qemu_irq_intercept_out(&ngl->out, qtest_irq_handler, - ngl->num_out); + int i; + for (i = 0; i < ngl->num_out; ++i) { + qemu_irq *disconnected = g_new0(qemu_irq, 1); + qemu_irq icpt = qemu_allocate_irq(qtest_irq_handler, + disconnected, i); + + *disconnected = qdev_intercept_gpio_out(dev, icpt, + ngl->name, i); + } } else { qemu_irq_intercept_in(ngl->in, qtest_irq_handler, ngl->num_in); @@ -538,11 +545,6 @@ void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp) return; } - qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr); - qemu_chr_fe_set_echo(chr, true); - - inbuf = g_string_new(""); - if (qtest_log) { if (strcmp(qtest_log, "none") != 0) { qtest_log_fp = fopen(qtest_log, "w+"); @@ -551,6 +553,10 @@ void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp) qtest_log_fp = stderr; } + qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr); + qemu_chr_fe_set_echo(chr, true); + + inbuf = g_string_new(""); qtest_chr = chr; } diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 38334de..af68c6c 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -651,18 +651,26 @@ sub get_maintainers { $email->[0] = deduplicate_email($email->[0]); } - foreach my $file (@files) { - if ($email && - ($email_git || ($email_git_fallback && - !$exact_pattern_match_hash{$file}))) { - vcs_file_signoffs($file); - } - if ($email && $email_git_blame) { - vcs_file_blame($file); + if ($email) { + if (! $interactive) { + $email_git_fallback = 0 if @email_to > 0 || @list_to > 0 || $email_git || $email_git_blame; + if ($email_git_fallback) { + print STDERR "get_maintainer.pl: No maintainers found, printing recent contributors.\n"; + print STDERR "get_maintainer.pl: Do not blindly cc: them on patches! Use common sense.\n"; + print STDERR "\n"; + } + } + + foreach my $file (@files) { + if ($email_git || ($email_git_fallback && + !$exact_pattern_match_hash{$file})) { + vcs_file_signoffs($file); + } + if ($email_git_blame) { + vcs_file_blame($file); + } } - } - if ($email) { foreach my $chief (@penguin_chief) { if ($chief =~ m/^(.*):(.*)/) { my $email_address; diff --git a/target-i386/cpu.c b/target-i386/cpu.c index e7bf9de..e194601 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -259,8 +259,8 @@ static const char *svm_feature_name[] = { static const char *cpuid_7_0_ebx_feature_name[] = { "fsgsbase", "tsc_adjust", NULL, "bmi1", "hle", "avx2", NULL, "smep", "bmi2", "erms", "invpcid", "rtm", NULL, NULL, "mpx", NULL, - NULL, NULL, "rdseed", "adx", "smap", NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "avx512f", NULL, "rdseed", "adx", "smap", NULL, NULL, NULL, + NULL, NULL, "avx512pf", "avx512er", "avx512cd", NULL, NULL, NULL, }; static const char *cpuid_apm_edx_feature_name[] = { @@ -426,6 +426,12 @@ static const ExtSaveArea ext_save_areas[] = { .offset = 0x3c0, .size = 0x40 }, [4] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX, .offset = 0x400, .size = 0x40 }, + [5] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, + .offset = 0x440, .size = 0x40 }, + [6] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, + .offset = 0x480, .size = 0x200 }, + [7] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F, + .offset = 0x680, .size = 0x400 }, }; const char *get_register_name_32(unsigned int reg) @@ -2696,6 +2702,13 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp) } #endif + +#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \ + (env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \ + (env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3) +#define IS_AMD_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \ + (env)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \ + (env)->cpuid_vendor3 == CPUID_VENDOR_AMD_3) static void x86_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); @@ -2703,6 +2716,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) X86CPUClass *xcc = X86_CPU_GET_CLASS(dev); CPUX86State *env = &cpu->env; Error *local_err = NULL; + static bool ht_warned; if (env->features[FEAT_7_0_EBX] && env->cpuid_level < 7) { env->cpuid_level = 7; @@ -2711,9 +2725,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on * CPUID[1].EDX. */ - if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && - env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && - env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) { + if (IS_AMD_CPU(env)) { env->features[FEAT_8000_0001_EDX] &= ~CPUID_EXT2_AMD_ALIASES; env->features[FEAT_8000_0001_EDX] |= (env->features[FEAT_1_EDX] & CPUID_EXT2_AMD_ALIASES); @@ -2742,6 +2754,20 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) mce_init(cpu); qemu_init_vcpu(cs); + /* Only Intel CPUs support hyperthreading. Even though QEMU fixes this + * issue by adjusting CPUID_0000_0001_EBX and CPUID_8000_0008_ECX + * based on inputs (sockets,cores,threads), it is still better to gives + * users a warning. + * + * NOTE: the following code has to follow qemu_init_vcpu(). Otherwise + * cs->nr_threads hasn't be populated yet and the checking is incorrect. + */ + if (!IS_INTEL_CPU(env) && cs->nr_threads > 1 && !ht_warned) { + error_report("AMD CPU doesn't support hyperthreading. Please configure" + " -smp options properly."); + ht_warned = true; + } + x86_cpu_apic_realize(cpu, &local_err); if (local_err != NULL) { goto out; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 2968749..9f01831 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -395,6 +395,9 @@ #define XSTATE_YMM (1ULL << 2) #define XSTATE_BNDREGS (1ULL << 3) #define XSTATE_BNDCSR (1ULL << 4) +#define XSTATE_OPMASK (1ULL << 5) +#define XSTATE_ZMM_Hi256 (1ULL << 6) +#define XSTATE_Hi16_ZMM (1ULL << 7) /* CPUID feature words */ @@ -560,9 +563,13 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; #define CPUID_7_0_EBX_INVPCID (1U << 10) #define CPUID_7_0_EBX_RTM (1U << 11) #define CPUID_7_0_EBX_MPX (1U << 14) +#define CPUID_7_0_EBX_AVX512F (1U << 16) /* AVX-512 Foundation */ #define CPUID_7_0_EBX_RDSEED (1U << 18) #define CPUID_7_0_EBX_ADX (1U << 19) #define CPUID_7_0_EBX_SMAP (1U << 20) +#define CPUID_7_0_EBX_AVX512PF (1U << 26) /* AVX-512 Prefetch */ +#define CPUID_7_0_EBX_AVX512ER (1U << 27) /* AVX-512 Exponential and Reciprocal */ +#define CPUID_7_0_EBX_AVX512CD (1U << 28) /* AVX-512 Conflict Detection */ /* CPUID[0x80000007].EDX flags: */ #define CPUID_APM_INVTSC (1U << 8) @@ -707,6 +714,24 @@ typedef union { } XMMReg; typedef union { + uint8_t _b[32]; + uint16_t _w[16]; + uint32_t _l[8]; + uint64_t _q[4]; + float32 _s[8]; + float64 _d[4]; +} YMMReg; + +typedef union { + uint8_t _b[64]; + uint16_t _w[32]; + uint32_t _l[16]; + uint64_t _q[8]; + float32 _s[16]; + float64 _d[8]; +} ZMMReg; + +typedef union { uint8_t _b[8]; uint16_t _w[4]; uint32_t _l[2]; @@ -725,6 +750,20 @@ typedef struct BNDCSReg { } BNDCSReg; #ifdef HOST_WORDS_BIGENDIAN +#define ZMM_B(n) _b[63 - (n)] +#define ZMM_W(n) _w[31 - (n)] +#define ZMM_L(n) _l[15 - (n)] +#define ZMM_S(n) _s[15 - (n)] +#define ZMM_Q(n) _q[7 - (n)] +#define ZMM_D(n) _d[7 - (n)] + +#define YMM_B(n) _b[31 - (n)] +#define YMM_W(n) _w[15 - (n)] +#define YMM_L(n) _l[7 - (n)] +#define YMM_S(n) _s[7 - (n)] +#define YMM_Q(n) _q[3 - (n)] +#define YMM_D(n) _d[3 - (n)] + #define XMM_B(n) _b[15 - (n)] #define XMM_W(n) _w[7 - (n)] #define XMM_L(n) _l[3 - (n)] @@ -737,6 +776,20 @@ typedef struct BNDCSReg { #define MMX_L(n) _l[1 - (n)] #define MMX_S(n) _s[1 - (n)] #else +#define ZMM_B(n) _b[n] +#define ZMM_W(n) _w[n] +#define ZMM_L(n) _l[n] +#define ZMM_S(n) _s[n] +#define ZMM_Q(n) _q[n] +#define ZMM_D(n) _d[n] + +#define YMM_B(n) _b[n] +#define YMM_W(n) _w[n] +#define YMM_L(n) _l[n] +#define YMM_S(n) _s[n] +#define YMM_Q(n) _q[n] +#define YMM_D(n) _d[n] + #define XMM_B(n) _b[n] #define XMM_W(n) _w[n] #define XMM_L(n) _l[n] @@ -775,6 +828,8 @@ typedef struct { #define NB_MMU_MODES 3 +#define NB_OPMASK_REGS 8 + typedef enum TPRAccess { TPR_ACCESS_READ, TPR_ACCESS_WRITE, @@ -839,6 +894,12 @@ typedef struct CPUX86State { XMMReg ymmh_regs[CPU_NB_REGS]; + uint64_t opmask_regs[NB_OPMASK_REGS]; + YMMReg zmmh_regs[CPU_NB_REGS]; +#ifdef TARGET_X86_64 + ZMMReg hi16_zmm_regs[CPU_NB_REGS]; +#endif + /* sysenter registers */ uint32_t sysenter_cs; target_ulong sysenter_esp; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index ddedc73..ccf36e8 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1031,6 +1031,9 @@ static int kvm_put_fpu(X86CPU *cpu) #define XSAVE_YMMH_SPACE 144 #define XSAVE_BNDREGS 240 #define XSAVE_BNDCSR 256 +#define XSAVE_OPMASK 272 +#define XSAVE_ZMM_Hi256 288 +#define XSAVE_Hi16_ZMM 416 static int kvm_put_xsave(X86CPU *cpu) { @@ -1067,6 +1070,14 @@ static int kvm_put_xsave(X86CPU *cpu) sizeof env->bnd_regs); memcpy(&xsave->region[XSAVE_BNDCSR], &env->bndcs_regs, sizeof(env->bndcs_regs)); + memcpy(&xsave->region[XSAVE_OPMASK], env->opmask_regs, + sizeof env->opmask_regs); + memcpy(&xsave->region[XSAVE_ZMM_Hi256], env->zmmh_regs, + sizeof env->zmmh_regs); +#ifdef TARGET_X86_64 + memcpy(&xsave->region[XSAVE_Hi16_ZMM], env->hi16_zmm_regs, + sizeof env->hi16_zmm_regs); +#endif r = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave); return r; } @@ -1402,6 +1413,14 @@ static int kvm_get_xsave(X86CPU *cpu) sizeof env->bnd_regs); memcpy(&env->bndcs_regs, &xsave->region[XSAVE_BNDCSR], sizeof(env->bndcs_regs)); + memcpy(env->opmask_regs, &xsave->region[XSAVE_OPMASK], + sizeof env->opmask_regs); + memcpy(env->zmmh_regs, &xsave->region[XSAVE_ZMM_Hi256], + sizeof env->zmmh_regs); +#ifdef TARGET_X86_64 + memcpy(env->hi16_zmm_regs, &xsave->region[XSAVE_Hi16_ZMM], + sizeof env->hi16_zmm_regs); +#endif return 0; } diff --git a/target-i386/machine.c b/target-i386/machine.c index 0dd49f0..1c13b14 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -60,6 +60,44 @@ static const VMStateDescription vmstate_ymmh_reg = { #define VMSTATE_YMMH_REGS_VARS(_field, _state, _n, _v) \ VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_ymmh_reg, XMMReg) +static const VMStateDescription vmstate_zmmh_reg = { + .name = "zmmh_reg", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT64(YMM_Q(0), YMMReg), + VMSTATE_UINT64(YMM_Q(1), YMMReg), + VMSTATE_UINT64(YMM_Q(2), YMMReg), + VMSTATE_UINT64(YMM_Q(3), YMMReg), + VMSTATE_END_OF_LIST() + } +}; + +#define VMSTATE_ZMMH_REGS_VARS(_field, _state, _n) \ + VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_zmmh_reg, YMMReg) + +#ifdef TARGET_X86_64 +static const VMStateDescription vmstate_hi16_zmm_reg = { + .name = "hi16_zmm_reg", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT64(ZMM_Q(0), ZMMReg), + VMSTATE_UINT64(ZMM_Q(1), ZMMReg), + VMSTATE_UINT64(ZMM_Q(2), ZMMReg), + VMSTATE_UINT64(ZMM_Q(3), ZMMReg), + VMSTATE_UINT64(ZMM_Q(4), ZMMReg), + VMSTATE_UINT64(ZMM_Q(5), ZMMReg), + VMSTATE_UINT64(ZMM_Q(6), ZMMReg), + VMSTATE_UINT64(ZMM_Q(7), ZMMReg), + VMSTATE_END_OF_LIST() + } +}; + +#define VMSTATE_Hi16_ZMM_REGS_VARS(_field, _state, _n) \ + VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_hi16_zmm_reg, ZMMReg) +#endif + static const VMStateDescription vmstate_bnd_regs = { .name = "bnd_regs", .version_id = 1, @@ -603,6 +641,52 @@ static const VMStateDescription vmstate_msr_hyperv_time = { } }; +static bool avx512_needed(void *opaque) +{ + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + unsigned int i; + + for (i = 0; i < NB_OPMASK_REGS; i++) { + if (env->opmask_regs[i]) { + return true; + } + } + + for (i = 0; i < CPU_NB_REGS; i++) { +#define ENV_ZMMH(reg, field) (env->zmmh_regs[reg].YMM_Q(field)) + if (ENV_ZMMH(i, 0) || ENV_ZMMH(i, 1) || + ENV_ZMMH(i, 2) || ENV_ZMMH(i, 3)) { + return true; + } +#ifdef TARGET_X86_64 +#define ENV_Hi16_ZMM(reg, field) (env->hi16_zmm_regs[reg].ZMM_Q(field)) + if (ENV_Hi16_ZMM(i, 0) || ENV_Hi16_ZMM(i, 1) || + ENV_Hi16_ZMM(i, 2) || ENV_Hi16_ZMM(i, 3) || + ENV_Hi16_ZMM(i, 4) || ENV_Hi16_ZMM(i, 5) || + ENV_Hi16_ZMM(i, 6) || ENV_Hi16_ZMM(i, 7)) { + return true; + } +#endif + } + + return false; +} + +static const VMStateDescription vmstate_avx512 = { + .name = "cpu/avx512", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT64_ARRAY(env.opmask_regs, X86CPU, NB_OPMASK_REGS), + VMSTATE_ZMMH_REGS_VARS(env.zmmh_regs, X86CPU, CPU_NB_REGS), +#ifdef TARGET_X86_64 + VMSTATE_Hi16_ZMM_REGS_VARS(env.hi16_zmm_regs, X86CPU, CPU_NB_REGS), +#endif + VMSTATE_END_OF_LIST() + } +}; + VMStateDescription vmstate_x86_cpu = { .name = "cpu", .version_id = 12, @@ -745,6 +829,9 @@ VMStateDescription vmstate_x86_cpu = { }, { .vmsd = &vmstate_msr_hyperv_time, .needed = hyperv_time_enable_needed, + }, { + .vmsd = &vmstate_avx512, + .needed = avx512_needed, } , { /* empty */ } @@ -435,6 +435,15 @@ static void gtk_release_modifiers(GtkDisplayState *s) } } +static void gd_widget_reparent(GtkWidget *from, GtkWidget *to, + GtkWidget *widget) +{ + g_object_ref(G_OBJECT(widget)); + gtk_container_remove(GTK_CONTAINER(from), widget); + gtk_container_add(GTK_CONTAINER(to), widget); + g_object_unref(G_OBJECT(widget)); +} + /** DisplayState Callbacks **/ static void gd_update(DisplayChangeListener *dcl, @@ -1031,7 +1040,7 @@ static gboolean gd_tab_window_close(GtkWidget *widget, GdkEvent *event, GtkDisplayState *s = vc->s; gtk_widget_set_sensitive(vc->menu_item, true); - gtk_widget_reparent(vc->tab_item, s->notebook); + gd_widget_reparent(vc->window, s->notebook, vc->tab_item); gtk_notebook_set_tab_label_text(GTK_NOTEBOOK(s->notebook), vc->tab_item, vc->label); gtk_widget_destroy(vc->window); @@ -1065,7 +1074,7 @@ static void gd_menu_untabify(GtkMenuItem *item, void *opaque) if (!vc->window) { gtk_widget_set_sensitive(vc->menu_item, false); vc->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_widget_reparent(vc->tab_item, vc->window); + gd_widget_reparent(s->notebook, vc->window, vc->tab_item); g_signal_connect(vc->window, "delete-event", G_CALLBACK(gd_tab_window_close), vc); @@ -1666,7 +1675,6 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc, GDK_LEAVE_NOTIFY_MASK | GDK_SCROLL_MASK | GDK_KEY_PRESS_MASK); - gtk_widget_set_double_buffered(vc->gfx.drawing_area, FALSE); gtk_widget_set_can_focus(vc->gfx.drawing_area, TRUE); vc->type = GD_VC_GFX; |