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):
|
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
|
Alpha
|
||||||
M: Richard Henderson <rth@twiddle.net>
|
M: Richard Henderson <rth@twiddle.net>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-alpha/
|
F: target-alpha/
|
||||||
F: hw/alpha/
|
F: hw/alpha/
|
||||||
|
F: tests/tcg/alpha/
|
||||||
|
|
||||||
ARM
|
ARM
|
||||||
M: Peter Maydell <peter.maydell@linaro.org>
|
M: Peter Maydell <peter.maydell@linaro.org>
|
||||||
|
@ -80,6 +92,7 @@ M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-cris/
|
F: target-cris/
|
||||||
F: hw/cris/
|
F: hw/cris/
|
||||||
|
F: tests/tcg/cris/
|
||||||
|
|
||||||
LM32
|
LM32
|
||||||
M: Michael Walle <michael@walle.cc>
|
M: Michael Walle <michael@walle.cc>
|
||||||
|
@ -87,6 +100,7 @@ S: Maintained
|
||||||
F: target-lm32/
|
F: target-lm32/
|
||||||
F: hw/lm32/
|
F: hw/lm32/
|
||||||
F: hw/char/lm32_*
|
F: hw/char/lm32_*
|
||||||
|
F: tests/tcg/lm32/
|
||||||
|
|
||||||
M68K
|
M68K
|
||||||
S: Orphan
|
S: Orphan
|
||||||
|
@ -105,6 +119,7 @@ M: Leon Alrae <leon.alrae@imgtec.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-mips/
|
F: target-mips/
|
||||||
F: hw/mips/
|
F: hw/mips/
|
||||||
|
F: tests/tcg/mips/
|
||||||
|
|
||||||
Moxie
|
Moxie
|
||||||
M: Anthony Green <green@moxielogic.com>
|
M: Anthony Green <green@moxielogic.com>
|
||||||
|
@ -116,6 +131,7 @@ M: Jia Liu <proljc@gmail.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target-openrisc/
|
F: target-openrisc/
|
||||||
F: hw/openrisc/
|
F: hw/openrisc/
|
||||||
|
F: tests/tcg/openrisc/
|
||||||
|
|
||||||
PowerPC
|
PowerPC
|
||||||
M: Alexander Graf <agraf@suse.de>
|
M: Alexander Graf <agraf@suse.de>
|
||||||
|
@ -151,7 +167,8 @@ F: target-unicore32/
|
||||||
F: hw/unicore32/
|
F: hw/unicore32/
|
||||||
|
|
||||||
X86
|
X86
|
||||||
M: qemu-devel@nongnu.org
|
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
M: Richard Henderson <rth@twiddle.net>
|
||||||
S: Odd Fixes
|
S: Odd Fixes
|
||||||
F: target-i386/
|
F: target-i386/
|
||||||
F: hw/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
|
S: Maintained
|
||||||
F: target-xtensa/
|
F: target-xtensa/
|
||||||
F: hw/xtensa/
|
F: hw/xtensa/
|
||||||
|
F: tests/tcg/xtensa/
|
||||||
|
|
||||||
TriCore
|
TriCore
|
||||||
M: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
|
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
|
F: include/hw/s390x/s390_flic.h
|
||||||
|
|
||||||
X86
|
X86
|
||||||
|
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
M: Marcelo Tosatti <mtosatti@redhat.com>
|
M: Marcelo Tosatti <mtosatti@redhat.com>
|
||||||
L: kvm@vger.kernel.org
|
L: kvm@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
@ -270,7 +289,7 @@ F: include/hw/arm/digic.h
|
||||||
F: hw/*/digic*
|
F: hw/*/digic*
|
||||||
|
|
||||||
Gumstix
|
Gumstix
|
||||||
M: qemu-devel@nongnu.org
|
L: qemu-devel@nongnu.org
|
||||||
S: Orphan
|
S: Orphan
|
||||||
F: hw/arm/gumstix.c
|
F: hw/arm/gumstix.c
|
||||||
|
|
||||||
|
@ -286,7 +305,7 @@ S: Maintained
|
||||||
F: hw/arm/integratorcp.c
|
F: hw/arm/integratorcp.c
|
||||||
|
|
||||||
Mainstone
|
Mainstone
|
||||||
M: qemu-devel@nongnu.org
|
L: qemu-devel@nongnu.org
|
||||||
S: Orphan
|
S: Orphan
|
||||||
F: hw/arm/mainstone.c
|
F: hw/arm/mainstone.c
|
||||||
|
|
||||||
|
@ -392,7 +411,7 @@ S: Maintained
|
||||||
F: hw/mips/mips_malta.c
|
F: hw/mips/mips_malta.c
|
||||||
|
|
||||||
Mipssim
|
Mipssim
|
||||||
M: qemu-devel@nongnu.org
|
L: qemu-devel@nongnu.org
|
||||||
S: Orphan
|
S: Orphan
|
||||||
F: hw/mips/mips_mipssim.c
|
F: hw/mips/mips_mipssim.c
|
||||||
|
|
||||||
|
@ -628,6 +647,12 @@ S: Maintained
|
||||||
F: hw/usb/*
|
F: hw/usb/*
|
||||||
F: tests/usb-*-test.c
|
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
|
VFIO
|
||||||
M: Alex Williamson <alex.williamson@redhat.com>
|
M: Alex Williamson <alex.williamson@redhat.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
|
@ -726,8 +751,16 @@ T: git git://github.com/stefanha/qemu.git block
|
||||||
|
|
||||||
Character Devices
|
Character Devices
|
||||||
M: Anthony Liguori <aliguori@amazon.com>
|
M: Anthony Liguori <aliguori@amazon.com>
|
||||||
|
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: qemu-char.c
|
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
|
CPU
|
||||||
M: Andreas Färber <afaerber@suse.de>
|
M: Andreas Färber <afaerber@suse.de>
|
||||||
|
@ -749,7 +782,7 @@ S: Maintained
|
||||||
F: device_tree.[ch]
|
F: device_tree.[ch]
|
||||||
|
|
||||||
GDB stub
|
GDB stub
|
||||||
M: qemu-devel@nongnu.org
|
L: qemu-devel@nongnu.org
|
||||||
S: Odd Fixes
|
S: Odd Fixes
|
||||||
F: gdbstub*
|
F: gdbstub*
|
||||||
F: gdb-xml/
|
F: gdb-xml/
|
||||||
|
@ -786,7 +819,11 @@ F: ui/cocoa.m
|
||||||
|
|
||||||
Main loop
|
Main loop
|
||||||
M: Anthony Liguori <aliguori@amazon.com>
|
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
|
F: vl.c
|
||||||
|
|
||||||
Human Monitor (HMP)
|
Human Monitor (HMP)
|
||||||
|
@ -825,6 +862,7 @@ M: Luiz Capitulino <lcapitulino@redhat.com>
|
||||||
M: Michael Roth <mdroth@linux.vnet.ibm.com>
|
M: Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: qapi/
|
F: qapi/
|
||||||
|
F: tests/qapi-schema/
|
||||||
T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
|
T: git git://repo.or.cz/qemu/qmp-unstable.git queue/qmp
|
||||||
|
|
||||||
QAPI Schema
|
QAPI Schema
|
||||||
|
@ -889,6 +927,12 @@ F: include/sysemu/seccomp.h
|
||||||
|
|
||||||
Usermode Emulation
|
Usermode Emulation
|
||||||
------------------
|
------------------
|
||||||
|
Overall
|
||||||
|
M: Riku Voipio <riku.voipio@iki.fi>
|
||||||
|
S: Maintained
|
||||||
|
F: thunk.c
|
||||||
|
F: user-exec.c
|
||||||
|
|
||||||
BSD user
|
BSD user
|
||||||
M: Blue Swirl <blauwirbel@gmail.com>
|
M: Blue Swirl <blauwirbel@gmail.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
@ -902,7 +946,6 @@ F: linux-user/
|
||||||
Tiny Code Generator (TCG)
|
Tiny Code Generator (TCG)
|
||||||
-------------------------
|
-------------------------
|
||||||
Common code
|
Common code
|
||||||
M: qemu-devel@nongnu.org
|
|
||||||
M: Richard Henderson <rth@twiddle.net>
|
M: Richard Henderson <rth@twiddle.net>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: tcg/
|
F: tcg/
|
||||||
|
@ -919,7 +962,7 @@ S: Maintained
|
||||||
F: tcg/arm/
|
F: tcg/arm/
|
||||||
|
|
||||||
i386 target
|
i386 target
|
||||||
M: qemu-devel@nongnu.org
|
L: qemu-devel@nongnu.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: tcg/i386/
|
F: tcg/i386/
|
||||||
|
|
||||||
|
|
|
@ -365,6 +365,8 @@ documentation for information about the other types.
|
||||||
|
|
||||||
=== User Defined 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
|
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
|
information about QEMU's timer alarm. For more information about it, please
|
||||||
check the "-clock" command-line option.
|
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++) {
|
for (i = 0; i < n; i++) {
|
||||||
*old_irqs[i] = *gpio_in[i];
|
*old_irqs[i] = *gpio_in[i];
|
||||||
gpio_in[i]->handler = handler;
|
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 = {
|
static const TypeInfo irq_type_info = {
|
||||||
.name = TYPE_IRQ,
|
.name = TYPE_IRQ,
|
||||||
.parent = TYPE_OBJECT,
|
.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");
|
char *propname = g_strdup_printf("%s[*]", name ? name : "unnamed-gpio-out");
|
||||||
|
|
||||||
assert(gpio_list->num_in == 0 || !name);
|
assert(gpio_list->num_in == 0 || !name);
|
||||||
assert(gpio_list->num_out == 0);
|
gpio_list->num_out += n;
|
||||||
gpio_list->num_out = n;
|
|
||||||
gpio_list->out = pins;
|
|
||||||
|
|
||||||
for (i = 0; i < n; ++i) {
|
for (i = 0; i < n; ++i) {
|
||||||
memset(&pins[i], 0, sizeof(*pins));
|
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,
|
void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
|
||||||
qemu_irq pin)
|
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);
|
/* disconnect a GPIO ouput, returning the disconnected input (if any) */
|
||||||
gpio_list->out[n] = pin;
|
|
||||||
|
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)
|
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);
|
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 *qdev_get_child_bus(DeviceState *dev, const char *name)
|
||||||
{
|
{
|
||||||
BusState *bus;
|
BusState *bus;
|
||||||
|
|
|
@ -41,11 +41,7 @@ static const TypeInfo system_bus_info = {
|
||||||
|
|
||||||
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
|
void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq)
|
||||||
{
|
{
|
||||||
assert(n >= 0 && n < dev->num_irq);
|
qdev_connect_gpio_out_named(DEVICE(dev), SYSBUS_DEVICE_GPIO_IRQ, n, irq);
|
||||||
dev->irqs[n] = NULL;
|
|
||||||
if (dev->irqp[n]) {
|
|
||||||
*dev->irqp[n] = irq;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sysbus_mmio_map_common(SysBusDevice *dev, int n, hwaddr addr,
|
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. */
|
/* Request an IRQ source. The actual IRQ object may be populated later. */
|
||||||
void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p)
|
void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p)
|
||||||
{
|
{
|
||||||
int n;
|
qdev_init_gpio_out_named(DEVICE(dev), p, SYSBUS_DEVICE_GPIO_IRQ, 1);
|
||||||
|
|
||||||
assert(dev->num_irq < QDEV_MAX_IRQ);
|
|
||||||
n = dev->num_irq++;
|
|
||||||
dev->irqp[n] = p;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pass IRQs from a target device. */
|
/* Pass IRQs from a target device. */
|
||||||
void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target)
|
void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target)
|
||||||
{
|
{
|
||||||
int i;
|
qdev_pass_gpios(DEVICE(target), DEVICE(dev), SYSBUS_DEVICE_GPIO_IRQ);
|
||||||
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];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory)
|
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;
|
hwaddr size;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
monitor_printf(mon, "%*sirq %d\n", indent, "", s->num_irq);
|
|
||||||
for (i = 0; i < s->num_mmio; i++) {
|
for (i = 0; i < s->num_mmio; i++) {
|
||||||
size = memory_region_size(s->mmio[i].memory);
|
size = memory_region_size(s->mmio[i].memory);
|
||||||
monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
|
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)));
|
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
|
||||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||||
VirtIOSCSIVring *r = g_slice_new(VirtIOSCSIVring);
|
VirtIOSCSIVring *r = g_slice_new(VirtIOSCSIVring);
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* Set up virtqueue notify */
|
/* Set up virtqueue notify */
|
||||||
if (k->set_host_notifier(qbus->parent, n, true) != 0) {
|
rc = k->set_host_notifier(qbus->parent, n, true);
|
||||||
fprintf(stderr, "virtio-scsi: Failed to set host notifier\n");
|
if (rc != 0) {
|
||||||
exit(1);
|
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->host_notifier = *virtio_queue_get_host_notifier(vq);
|
||||||
r->guest_notifier = *virtio_queue_get_guest_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)) {
|
if (!vring_setup(&r->vring, VIRTIO_DEVICE(s), n)) {
|
||||||
fprintf(stderr, "virtio-scsi: VRing setup failed\n");
|
fprintf(stderr, "virtio-scsi: VRing setup failed\n");
|
||||||
exit(1);
|
goto fail_vring;
|
||||||
}
|
}
|
||||||
return r;
|
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,
|
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 */
|
/* Context: QEMU global mutex held */
|
||||||
void virtio_scsi_dataplane_start(VirtIOSCSI *s)
|
void virtio_scsi_dataplane_start(VirtIOSCSI *s)
|
||||||
{
|
{
|
||||||
|
@ -149,38 +199,62 @@ void virtio_scsi_dataplane_start(VirtIOSCSI *s)
|
||||||
|
|
||||||
if (s->dataplane_started ||
|
if (s->dataplane_started ||
|
||||||
s->dataplane_starting ||
|
s->dataplane_starting ||
|
||||||
|
s->dataplane_fenced ||
|
||||||
s->ctx != iothread_get_aio_context(vs->conf.iothread)) {
|
s->ctx != iothread_get_aio_context(vs->conf.iothread)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->dataplane_starting = true;
|
s->dataplane_starting = true;
|
||||||
|
|
||||||
|
assert(!s->blocker);
|
||||||
|
error_setg(&s->blocker, "block device is in use by data plane");
|
||||||
/* Set up guest notifier (irq) */
|
/* Set up guest notifier (irq) */
|
||||||
rc = k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, true);
|
rc = k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, true);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
fprintf(stderr, "virtio-scsi: Failed to set guest notifiers, "
|
fprintf(stderr, "virtio-scsi: Failed to set guest notifiers (%d), "
|
||||||
"ensure -enable-kvm is set\n");
|
"ensure -enable-kvm is set\n", rc);
|
||||||
exit(1);
|
s->dataplane_fenced = true;
|
||||||
|
goto fail_guest_notifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
aio_context_acquire(s->ctx);
|
aio_context_acquire(s->ctx);
|
||||||
s->ctrl_vring = virtio_scsi_vring_init(s, vs->ctrl_vq,
|
s->ctrl_vring = virtio_scsi_vring_init(s, vs->ctrl_vq,
|
||||||
virtio_scsi_iothread_handle_ctrl,
|
virtio_scsi_iothread_handle_ctrl,
|
||||||
0);
|
0);
|
||||||
|
if (!s->ctrl_vring) {
|
||||||
|
goto fail_vrings;
|
||||||
|
}
|
||||||
s->event_vring = virtio_scsi_vring_init(s, vs->event_vq,
|
s->event_vring = virtio_scsi_vring_init(s, vs->event_vq,
|
||||||
virtio_scsi_iothread_handle_event,
|
virtio_scsi_iothread_handle_event,
|
||||||
1);
|
1);
|
||||||
|
if (!s->event_vring) {
|
||||||
|
goto fail_vrings;
|
||||||
|
}
|
||||||
s->cmd_vrings = g_malloc0(sizeof(VirtIOSCSIVring) * vs->conf.num_queues);
|
s->cmd_vrings = g_malloc0(sizeof(VirtIOSCSIVring) * vs->conf.num_queues);
|
||||||
for (i = 0; i < vs->conf.num_queues; i++) {
|
for (i = 0; i < vs->conf.num_queues; i++) {
|
||||||
s->cmd_vrings[i] =
|
s->cmd_vrings[i] =
|
||||||
virtio_scsi_vring_init(s, vs->cmd_vqs[i],
|
virtio_scsi_vring_init(s, vs->cmd_vqs[i],
|
||||||
virtio_scsi_iothread_handle_cmd,
|
virtio_scsi_iothread_handle_cmd,
|
||||||
i + 2);
|
i + 2);
|
||||||
|
if (!s->cmd_vrings[i]) {
|
||||||
|
goto fail_vrings;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aio_context_release(s->ctx);
|
aio_context_release(s->ctx);
|
||||||
s->dataplane_starting = false;
|
s->dataplane_starting = false;
|
||||||
s->dataplane_started = true;
|
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 */
|
/* 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)));
|
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s)));
|
||||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(s);
|
|
||||||
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
|
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Better luck next time. */
|
||||||
|
if (s->dataplane_fenced) {
|
||||||
|
s->dataplane_fenced = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!s->dataplane_started || s->dataplane_stopping) {
|
if (!s->dataplane_started || s->dataplane_stopping) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
error_free(s->blocker);
|
||||||
|
s->blocker = NULL;
|
||||||
s->dataplane_stopping = true;
|
s->dataplane_stopping = true;
|
||||||
assert(s->ctx == iothread_get_aio_context(vs->conf.iothread));
|
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
|
/* Sync vring state back to virtqueue so that non-dataplane request
|
||||||
* processing can continue when we disable the host notifier below.
|
* processing can continue when we disable the host notifier below.
|
||||||
*/
|
*/
|
||||||
vring_teardown(&s->ctrl_vring->vring, vdev, 0);
|
virtio_scsi_vring_teardown(s);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < vs->conf.num_queues + 2; i++) {
|
for (i = 0; i < vs->conf.num_queues + 2; i++) {
|
||||||
k->set_host_notifier(qbus->parent, i, false);
|
k->set_host_notifier(qbus->parent, i, false);
|
||||||
|
|
|
@ -369,7 +369,7 @@ fail:
|
||||||
void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = (VirtIODevice *)s;
|
VirtIODevice *vdev = (VirtIODevice *)s;
|
||||||
int type;
|
uint32_t type;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtio_tswap32s(vdev, &req->req.tmf.type);
|
virtio_tswap32s(vdev, &type);
|
||||||
if (req->req.tmf.type == VIRTIO_SCSI_T_TMF) {
|
if (type == VIRTIO_SCSI_T_TMF) {
|
||||||
if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlTMFReq),
|
if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlTMFReq),
|
||||||
sizeof(VirtIOSCSICtrlTMFResp)) < 0) {
|
sizeof(VirtIOSCSICtrlTMFResp)) < 0) {
|
||||||
virtio_scsi_bad_req();
|
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);
|
r = virtio_scsi_do_tmf(s, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (req->req.tmf.type == VIRTIO_SCSI_T_AN_QUERY ||
|
} else if (type == VIRTIO_SCSI_T_AN_QUERY ||
|
||||||
req->req.tmf.type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
|
type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
|
||||||
if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlANReq),
|
if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlANReq),
|
||||||
sizeof(VirtIOSCSICtrlANResp)) < 0) {
|
sizeof(VirtIOSCSICtrlANResp)) < 0) {
|
||||||
virtio_scsi_bad_req();
|
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 = scsi_req_get_sense(r, sense, sizeof(sense));
|
||||||
sense_len = MIN(sense_len, req->resp_iov.size - sizeof(req->resp.cmd));
|
sense_len = MIN(sense_len, req->resp_iov.size - sizeof(req->resp.cmd));
|
||||||
qemu_iovec_from_buf(&req->resp_iov, 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);
|
req->resp.cmd.sense_len = virtio_tswap32(vdev, sense_len);
|
||||||
}
|
}
|
||||||
virtio_scsi_complete_cmd_req(req);
|
virtio_scsi_complete_cmd_req(req);
|
||||||
|
@ -742,9 +742,18 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
|
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) {
|
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_T_TRANSPORT_RESET,
|
||||||
VIRTIO_SCSI_EVT_RESET_RESCAN);
|
VIRTIO_SCSI_EVT_RESET_RESCAN);
|
||||||
}
|
}
|
||||||
|
@ -754,12 +763,18 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
|
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) {
|
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_T_TRANSPORT_RESET,
|
||||||
VIRTIO_SCSI_EVT_RESET_REMOVED);
|
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);
|
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
|
/* For internal use in qtest. Similar to qemu_irq_split, but operating
|
||||||
on an existing vector of qemu_irq. */
|
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_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
|
#endif
|
||||||
|
|
|
@ -136,7 +136,6 @@ struct NamedGPIOList {
|
||||||
char *name;
|
char *name;
|
||||||
qemu_irq *in;
|
qemu_irq *in;
|
||||||
int num_in;
|
int num_in;
|
||||||
qemu_irq *out;
|
|
||||||
int num_out;
|
int num_out;
|
||||||
QLIST_ENTRY(NamedGPIOList) node;
|
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(DeviceState *dev, int n, qemu_irq pin);
|
||||||
void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
|
void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
|
||||||
qemu_irq pin);
|
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);
|
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,
|
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
|
||||||
const char *name, int n);
|
const char *name, int n);
|
||||||
|
|
||||||
|
void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
BusState *qdev_get_parent_bus(DeviceState *dev);
|
BusState *qdev_get_parent_bus(DeviceState *dev);
|
||||||
|
|
||||||
/*** BUS API. ***/
|
/*** BUS API. ***/
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
#define QDEV_MAX_MMIO 32
|
#define QDEV_MAX_MMIO 32
|
||||||
#define QDEV_MAX_PIO 32
|
#define QDEV_MAX_PIO 32
|
||||||
#define QDEV_MAX_IRQ 512
|
|
||||||
|
|
||||||
#define TYPE_SYSTEM_BUS "System"
|
#define TYPE_SYSTEM_BUS "System"
|
||||||
#define SYSTEM_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS)
|
#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
|
* SysBusDeviceClass is not overriding #DeviceClass.realize, so derived
|
||||||
* classes overriding it are not required to invoke its implementation.
|
* classes overriding it are not required to invoke its implementation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define SYSBUS_DEVICE_GPIO_IRQ "sysbus-irq"
|
||||||
|
|
||||||
typedef struct SysBusDeviceClass {
|
typedef struct SysBusDeviceClass {
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
DeviceClass parent_class;
|
DeviceClass parent_class;
|
||||||
|
@ -46,9 +48,6 @@ struct SysBusDevice {
|
||||||
DeviceState parent_obj;
|
DeviceState parent_obj;
|
||||||
/*< public >*/
|
/*< public >*/
|
||||||
|
|
||||||
int num_irq;
|
|
||||||
qemu_irq irqs[QDEV_MAX_IRQ];
|
|
||||||
qemu_irq *irqp[QDEV_MAX_IRQ];
|
|
||||||
int num_mmio;
|
int num_mmio;
|
||||||
struct {
|
struct {
|
||||||
hwaddr addr;
|
hwaddr addr;
|
||||||
|
|
|
@ -195,6 +195,8 @@ typedef struct VirtIOSCSI {
|
||||||
bool dataplane_starting;
|
bool dataplane_starting;
|
||||||
bool dataplane_stopping;
|
bool dataplane_stopping;
|
||||||
bool dataplane_disabled;
|
bool dataplane_disabled;
|
||||||
|
bool dataplane_fenced;
|
||||||
|
Error *blocker;
|
||||||
Notifier migration_state_notifier;
|
Notifier migration_state_notifier;
|
||||||
} VirtIOSCSI;
|
} VirtIOSCSI;
|
||||||
|
|
||||||
|
|
|
@ -2989,16 +2989,8 @@ Load the contents of @var{file} as an option ROM.
|
||||||
This option is useful to load things like EtherBoot.
|
This option is useful to load things like EtherBoot.
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
DEF("clock", HAS_ARG, QEMU_OPTION_clock, \
|
HXCOMM Silently ignored for compatibility
|
||||||
"-clock force the use of the given methods for timer alarm.\n" \
|
DEF("clock", HAS_ARG, QEMU_OPTION_clock, "", QEMU_ARCH_ALL)
|
||||||
" 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 Options deprecated by -rtc
|
HXCOMM Options deprecated by -rtc
|
||||||
DEF("localtime", 0, QEMU_OPTION_localtime, "", QEMU_ARCH_ALL)
|
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,
|
void object_property_set_link(Object *obj, Object *value,
|
||||||
const char *name, Error **errp)
|
const char *name, Error **errp)
|
||||||
{
|
{
|
||||||
gchar *path = object_get_canonical_path(value);
|
if (value) {
|
||||||
object_property_set_str(obj, path, name, errp);
|
gchar *path = object_get_canonical_path(value);
|
||||||
g_free(path);
|
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,
|
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;
|
gchar *type;
|
||||||
ObjectProperty *op;
|
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)));
|
type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
|
||||||
|
|
||||||
op = object_property_add(obj, name, type, object_get_child_property, NULL,
|
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;
|
op->resolve = object_resolve_child_property;
|
||||||
object_ref(child);
|
object_ref(child);
|
||||||
g_assert(child->parent == NULL);
|
|
||||||
child->parent = obj;
|
child->parent = obj;
|
||||||
|
|
||||||
out:
|
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)
|
static void qtest_irq_handler(void *opaque, int n, int level)
|
||||||
{
|
{
|
||||||
qemu_irq *old_irqs = opaque;
|
qemu_irq old_irq = *(qemu_irq *)opaque;
|
||||||
qemu_set_irq(old_irqs[n], level);
|
qemu_set_irq(old_irq, level);
|
||||||
|
|
||||||
if (irq_levels[n] != level) {
|
if (irq_levels[n] != level) {
|
||||||
CharDriverState *chr = qtest_chr;
|
CharDriverState *chr = qtest_chr;
|
||||||
|
@ -264,8 +264,15 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (words[0][14] == 'o') {
|
if (words[0][14] == 'o') {
|
||||||
qemu_irq_intercept_out(&ngl->out, qtest_irq_handler,
|
int i;
|
||||||
ngl->num_out);
|
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 {
|
} else {
|
||||||
qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
|
qemu_irq_intercept_in(ngl->in, qtest_irq_handler,
|
||||||
ngl->num_in);
|
ngl->num_in);
|
||||||
|
@ -538,11 +545,6 @@ void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
|
||||||
return;
|
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 (qtest_log) {
|
||||||
if (strcmp(qtest_log, "none") != 0) {
|
if (strcmp(qtest_log, "none") != 0) {
|
||||||
qtest_log_fp = fopen(qtest_log, "w+");
|
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;
|
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;
|
qtest_chr = chr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -651,18 +651,26 @@ sub get_maintainers {
|
||||||
$email->[0] = deduplicate_email($email->[0]);
|
$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 ($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) {
|
foreach my $chief (@penguin_chief) {
|
||||||
if ($chief =~ m/^(.*):(.*)/) {
|
if ($chief =~ m/^(.*):(.*)/) {
|
||||||
my $email_address;
|
my $email_address;
|
||||||
|
|
|
@ -259,8 +259,8 @@ static const char *svm_feature_name[] = {
|
||||||
static const char *cpuid_7_0_ebx_feature_name[] = {
|
static const char *cpuid_7_0_ebx_feature_name[] = {
|
||||||
"fsgsbase", "tsc_adjust", NULL, "bmi1", "hle", "avx2", NULL, "smep",
|
"fsgsbase", "tsc_adjust", NULL, "bmi1", "hle", "avx2", NULL, "smep",
|
||||||
"bmi2", "erms", "invpcid", "rtm", NULL, NULL, "mpx", NULL,
|
"bmi2", "erms", "invpcid", "rtm", NULL, NULL, "mpx", NULL,
|
||||||
NULL, NULL, "rdseed", "adx", "smap", NULL, NULL, NULL,
|
"avx512f", NULL, "rdseed", "adx", "smap", NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, "avx512pf", "avx512er", "avx512cd", NULL, NULL, NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *cpuid_apm_edx_feature_name[] = {
|
static const char *cpuid_apm_edx_feature_name[] = {
|
||||||
|
@ -426,6 +426,12 @@ static const ExtSaveArea ext_save_areas[] = {
|
||||||
.offset = 0x3c0, .size = 0x40 },
|
.offset = 0x3c0, .size = 0x40 },
|
||||||
[4] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
|
[4] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
|
||||||
.offset = 0x400, .size = 0x40 },
|
.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)
|
const char *get_register_name_32(unsigned int reg)
|
||||||
|
@ -2696,6 +2702,13 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
CPUState *cs = CPU(dev);
|
CPUState *cs = CPU(dev);
|
||||||
|
@ -2703,6 +2716,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
X86CPUClass *xcc = X86_CPU_GET_CLASS(dev);
|
X86CPUClass *xcc = X86_CPU_GET_CLASS(dev);
|
||||||
CPUX86State *env = &cpu->env;
|
CPUX86State *env = &cpu->env;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
static bool ht_warned;
|
||||||
|
|
||||||
if (env->features[FEAT_7_0_EBX] && env->cpuid_level < 7) {
|
if (env->features[FEAT_7_0_EBX] && env->cpuid_level < 7) {
|
||||||
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
|
/* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on
|
||||||
* CPUID[1].EDX.
|
* CPUID[1].EDX.
|
||||||
*/
|
*/
|
||||||
if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 &&
|
if (IS_AMD_CPU(env)) {
|
||||||
env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 &&
|
|
||||||
env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) {
|
|
||||||
env->features[FEAT_8000_0001_EDX] &= ~CPUID_EXT2_AMD_ALIASES;
|
env->features[FEAT_8000_0001_EDX] &= ~CPUID_EXT2_AMD_ALIASES;
|
||||||
env->features[FEAT_8000_0001_EDX] |= (env->features[FEAT_1_EDX]
|
env->features[FEAT_8000_0001_EDX] |= (env->features[FEAT_1_EDX]
|
||||||
& CPUID_EXT2_AMD_ALIASES);
|
& CPUID_EXT2_AMD_ALIASES);
|
||||||
|
@ -2742,6 +2754,20 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||||
mce_init(cpu);
|
mce_init(cpu);
|
||||||
qemu_init_vcpu(cs);
|
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);
|
x86_cpu_apic_realize(cpu, &local_err);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -395,6 +395,9 @@
|
||||||
#define XSTATE_YMM (1ULL << 2)
|
#define XSTATE_YMM (1ULL << 2)
|
||||||
#define XSTATE_BNDREGS (1ULL << 3)
|
#define XSTATE_BNDREGS (1ULL << 3)
|
||||||
#define XSTATE_BNDCSR (1ULL << 4)
|
#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 */
|
/* 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_INVPCID (1U << 10)
|
||||||
#define CPUID_7_0_EBX_RTM (1U << 11)
|
#define CPUID_7_0_EBX_RTM (1U << 11)
|
||||||
#define CPUID_7_0_EBX_MPX (1U << 14)
|
#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_RDSEED (1U << 18)
|
||||||
#define CPUID_7_0_EBX_ADX (1U << 19)
|
#define CPUID_7_0_EBX_ADX (1U << 19)
|
||||||
#define CPUID_7_0_EBX_SMAP (1U << 20)
|
#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: */
|
/* CPUID[0x80000007].EDX flags: */
|
||||||
#define CPUID_APM_INVTSC (1U << 8)
|
#define CPUID_APM_INVTSC (1U << 8)
|
||||||
|
@ -706,6 +713,24 @@ typedef union {
|
||||||
float64 _d[2];
|
float64 _d[2];
|
||||||
} XMMReg;
|
} 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 {
|
typedef union {
|
||||||
uint8_t _b[8];
|
uint8_t _b[8];
|
||||||
uint16_t _w[4];
|
uint16_t _w[4];
|
||||||
|
@ -725,6 +750,20 @@ typedef struct BNDCSReg {
|
||||||
} BNDCSReg;
|
} BNDCSReg;
|
||||||
|
|
||||||
#ifdef HOST_WORDS_BIGENDIAN
|
#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_B(n) _b[15 - (n)]
|
||||||
#define XMM_W(n) _w[7 - (n)]
|
#define XMM_W(n) _w[7 - (n)]
|
||||||
#define XMM_L(n) _l[3 - (n)]
|
#define XMM_L(n) _l[3 - (n)]
|
||||||
|
@ -737,6 +776,20 @@ typedef struct BNDCSReg {
|
||||||
#define MMX_L(n) _l[1 - (n)]
|
#define MMX_L(n) _l[1 - (n)]
|
||||||
#define MMX_S(n) _s[1 - (n)]
|
#define MMX_S(n) _s[1 - (n)]
|
||||||
#else
|
#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_B(n) _b[n]
|
||||||
#define XMM_W(n) _w[n]
|
#define XMM_W(n) _w[n]
|
||||||
#define XMM_L(n) _l[n]
|
#define XMM_L(n) _l[n]
|
||||||
|
@ -775,6 +828,8 @@ typedef struct {
|
||||||
|
|
||||||
#define NB_MMU_MODES 3
|
#define NB_MMU_MODES 3
|
||||||
|
|
||||||
|
#define NB_OPMASK_REGS 8
|
||||||
|
|
||||||
typedef enum TPRAccess {
|
typedef enum TPRAccess {
|
||||||
TPR_ACCESS_READ,
|
TPR_ACCESS_READ,
|
||||||
TPR_ACCESS_WRITE,
|
TPR_ACCESS_WRITE,
|
||||||
|
@ -839,6 +894,12 @@ typedef struct CPUX86State {
|
||||||
|
|
||||||
XMMReg ymmh_regs[CPU_NB_REGS];
|
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 */
|
/* sysenter registers */
|
||||||
uint32_t sysenter_cs;
|
uint32_t sysenter_cs;
|
||||||
target_ulong sysenter_esp;
|
target_ulong sysenter_esp;
|
||||||
|
|
|
@ -1031,6 +1031,9 @@ static int kvm_put_fpu(X86CPU *cpu)
|
||||||
#define XSAVE_YMMH_SPACE 144
|
#define XSAVE_YMMH_SPACE 144
|
||||||
#define XSAVE_BNDREGS 240
|
#define XSAVE_BNDREGS 240
|
||||||
#define XSAVE_BNDCSR 256
|
#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)
|
static int kvm_put_xsave(X86CPU *cpu)
|
||||||
{
|
{
|
||||||
|
@ -1067,6 +1070,14 @@ static int kvm_put_xsave(X86CPU *cpu)
|
||||||
sizeof env->bnd_regs);
|
sizeof env->bnd_regs);
|
||||||
memcpy(&xsave->region[XSAVE_BNDCSR], &env->bndcs_regs,
|
memcpy(&xsave->region[XSAVE_BNDCSR], &env->bndcs_regs,
|
||||||
sizeof(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);
|
r = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -1402,6 +1413,14 @@ static int kvm_get_xsave(X86CPU *cpu)
|
||||||
sizeof env->bnd_regs);
|
sizeof env->bnd_regs);
|
||||||
memcpy(&env->bndcs_regs, &xsave->region[XSAVE_BNDCSR],
|
memcpy(&env->bndcs_regs, &xsave->region[XSAVE_BNDCSR],
|
||||||
sizeof(env->bndcs_regs));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,44 @@ static const VMStateDescription vmstate_ymmh_reg = {
|
||||||
#define VMSTATE_YMMH_REGS_VARS(_field, _state, _n, _v) \
|
#define VMSTATE_YMMH_REGS_VARS(_field, _state, _n, _v) \
|
||||||
VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_ymmh_reg, XMMReg)
|
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 = {
|
static const VMStateDescription vmstate_bnd_regs = {
|
||||||
.name = "bnd_regs",
|
.name = "bnd_regs",
|
||||||
.version_id = 1,
|
.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 = {
|
VMStateDescription vmstate_x86_cpu = {
|
||||||
.name = "cpu",
|
.name = "cpu",
|
||||||
.version_id = 12,
|
.version_id = 12,
|
||||||
|
@ -745,6 +829,9 @@ VMStateDescription vmstate_x86_cpu = {
|
||||||
}, {
|
}, {
|
||||||
.vmsd = &vmstate_msr_hyperv_time,
|
.vmsd = &vmstate_msr_hyperv_time,
|
||||||
.needed = hyperv_time_enable_needed,
|
.needed = hyperv_time_enable_needed,
|
||||||
|
}, {
|
||||||
|
.vmsd = &vmstate_avx512,
|
||||||
|
.needed = avx512_needed,
|
||||||
} , {
|
} , {
|
||||||
/* empty */
|
/* empty */
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue