virtio-scsi fixes, the first part of dynamic sysbus devices,
MAINTAINERS updates, and AVX512 support. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEcBAABAgAGBQJUTmDNAAoJEL/70l94x66DPb0IAKKhf8IRfQZPEQgOWD2YeANd vwAZ4JcqAl2/dbeOTrs5TXOWdoNVXUFDmeHh4zsgUB7poxsOqZ/M7N844UGR5duC f4fKYXAkjyqocKH7dbpf/S+YuJtU40qowI02HQeEmGpZaJUjmfMAFwrguqerdMaB pGA79948XeoAjP8jNgf1EqCqLi31GBEfiU2q05xLKxd+M0xSFIM7IM2hGZfFv7Hq bbE2CGuCyj4NST/GH2C/22QBz9MyqFaL2prtDqoMugAHTKE7vO/rpFti9oTDRCXa x8U/JcBf/puBNI+Kq+cdxTJicwIuqrcBkNmjP9sLv/nJ37QwEG06VDCd4Xj9mEs= =zXqD -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging virtio-scsi fixes, the first part of dynamic sysbus devices, MAINTAINERS updates, and AVX512 support. # gpg: Signature made Mon 27 Oct 2014 15:12:13 GMT using RSA key ID 78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: (28 commits) aio / timers: De-document -clock hw/scsi/virtio-scsi.c: fix the "type" use error in virtio_scsi_handle_ctrl virtio-scsi: sense in virtio_scsi_command_complete target-i386: add Intel AVX-512 support get_maintainer.pl: restrict cases where it falls back to --git get_maintainer.pl: move git loop under "if ($email) {" qtest: fix qtest log fd should be initialized before qtest chardev MAINTAINERS: avoid M entries that point to mailing lists MAINTAINERS: add some tests directories MAINTAINERS: Add more TCG files MAINTAINERS: add myself for X86 MAINTAINERS: add Samuel Thibault as usb-serial.c and baum.c maintainer MAINTAINERS: grab more files from Anthony's pile target-i386: warns users when CPU threads>1 for non-Intel CPUs sysbus: Use TYPE_DEVICE GPIO functionality qdev: gpio: Define qdev_pass_gpios() qdev: gpio: Remove qdev_init_gpio_out x1 restriction qdev: gpio: delete NamedGPIOList::out irq: Remove qemu_irq_intercept_out qtest/irq: Rework IRQ interception ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
08118672d0
59
MAINTAINERS
59
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/
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
assert(n >= 0 && n < gpio_list->num_out);
|
||||
gpio_list->out[n] = pin;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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. ***/
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
16
qom/object.c
16
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:
|
||||
|
24
qtest.c
24
qtest.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $chief (@penguin_chief) {
|
||||
if ($chief =~ m/^(.*):(.*)/) {
|
||||
my $email_address;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
@ -706,6 +713,24 @@ typedef union {
|
||||
float64 _d[2];
|
||||
} 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];
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user