aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-10-19 10:52:39 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-10-19 10:52:39 +0100
commit526d5809a0714edc7f19196f14ec2e607dbd9753 (patch)
tree4ac5abd443d968ce5c6495cf8030a1301ecae3ee
parentaedc8806172dd1ae904f04169ee3b19fce1d7893 (diff)
parent1c4a55dbed9a47fde9294f7de6c8bb060d874c88 (diff)
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* KVM page size fix for PPC * Support for Linux 4.4's new Hyper-V features * Eliminate g_slice from areas I maintain * checkpatch fix * Peter's cpu_reload_memory_map() cleanups * More changes to MAINTAINERS * Require Python 2.6 * chardev creation fixes * PCI requester id for ARM KVM * cleanups and doc fixes * Allow customization of the Hyper-V vendor id # gpg: Signature made Mon 19 Oct 2015 09:13:10 BST using RSA key ID 78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" * remotes/bonzini/tags/for-upstream: (49 commits) kvm: Allow the Hyper-V vendor ID to be specified kvm: Move x86-specific functions into target-i386/kvm.c kvm: Pass PCI device pointer to MSI routing functions hw/pci: Introduce pci_requester_id() kvm: Make KVM_CAP_SIGNAL_MSI globally available doc/rcu: fix g_free_rcu() usage example qemu-char: cleanup after completed conversion to cd->create qemu-char: convert ringbuf backend to data-driven creation qemu-char: convert vc backend to data-driven creation qemu-char: convert spice backend to data-driven creation qemu-char: convert console backend to data-driven creation qemu-char: convert stdio backend to data-driven creation qemu-char: convert testdev backend to data-driven creation qemu-char: convert braille backend to data-driven creation qemu-char: convert msmouse backend to data-driven creation qemu-char: convert mux backend to data-driven creation qemu-char: convert null backend to data-driven creation qemu-char: convert pty backend to data-driven creation qemu-char: convert UDP backend to data-driven creation qemu-char: convert socket backend to data-driven creation ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--MAINTAINERS51
-rw-r--r--README108
-rw-r--r--backends/baum.c17
-rw-r--r--backends/msmouse.c8
-rw-r--r--backends/testdev.c8
-rwxr-xr-xconfigure12
-rw-r--r--cpu-exec-common.c33
-rw-r--r--docs/rcu.txt2
-rw-r--r--exec.c57
-rw-r--r--hw/i386/kvm/pci-assign.c11
-rw-r--r--hw/pci/msi.c2
-rw-r--r--hw/pci/pcie_aer.c2
-rw-r--r--hw/scsi/megasas.c2
-rw-r--r--hw/scsi/scsi-bus.c4
-rw-r--r--hw/scsi/virtio-scsi-dataplane.c10
-rw-r--r--hw/scsi/virtio-scsi.c12
-rw-r--r--hw/vfio/pci.c11
-rw-r--r--hw/virtio/virtio-pci.c5
-rw-r--r--include/exec/exec-all.h8
-rw-r--r--include/exec/memattrs.h4
-rw-r--r--include/exec/ram_addr.h1
-rw-r--r--include/hw/pci/pci.h5
-rw-r--r--include/qemu/typedefs.h1
-rw-r--r--include/qom/cpu.h7
-rw-r--r--include/standard-headers/asm-x86/hyperv.h6
-rw-r--r--include/sysemu/char.h18
-rw-r--r--include/sysemu/cpus.h1
-rw-r--r--include/sysemu/kvm.h22
-rw-r--r--include/ui/qemu-spice.h2
-rw-r--r--kvm-all.c56
-rw-r--r--kvm-stub.c10
-rw-r--r--linux-headers/asm-arm64/kvm.h37
-rw-r--r--linux-headers/linux/kvm.h12
-rw-r--r--nbd.c4
-rw-r--r--qemu-char.c395
-rwxr-xr-xscripts/checkpatch.pl9
-rw-r--r--spice-qemu-char.c21
-rw-r--r--stubs/Makefile.objs5
-rw-r--r--stubs/chr-baum-init.c7
-rw-r--r--stubs/chr-msmouse.c7
-rw-r--r--stubs/chr-testdev.c7
-rw-r--r--stubs/qemu-chr-open-spice.c14
-rw-r--r--stubs/vc-init.c7
-rw-r--r--target-arm/kvm.c2
-rw-r--r--target-i386/cpu-qom.h4
-rw-r--r--target-i386/cpu.c4
-rw-r--r--target-i386/cpu.h1
-rw-r--r--target-i386/kvm.c87
-rw-r--r--target-i386/machine.c20
-rw-r--r--target-mips/kvm.c2
-rw-r--r--target-ppc/kvm.c2
-rw-r--r--target-s390x/kvm.c2
-rw-r--r--ui/console.c11
-rw-r--r--ui/gtk.c2
-rw-r--r--util/qemu-sockets.c9
55 files changed, 723 insertions, 444 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 9bd2b8f678..01fb6e26e2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -255,6 +255,12 @@ L: xen-devel@lists.xensource.com
S: Supported
F: xen-*
F: */xen*
+F: hw/char/xen_console.c
+F: hw/display/xenfb.c
+F: hw/net/xen_nic.c
+F: hw/xen/
+F: hw/xenpv/
+F: include/hw/xen/
Hosts:
------
@@ -286,6 +292,36 @@ F: hw/*/allwinner*
F: include/hw/*/allwinner*
F: hw/arm/cubieboard.c
+ARM PrimeCell
+M: Peter Maydell <peter.maydell@linaro.org>
+S: Maintained
+F: hw/char/pl011.c
+F: hw/display/pl110*
+F: hw/dma/pl080.c
+F: hw/dma/pl330.c
+F: hw/gpio/pl061.c
+F: hw/input/pl050.c
+F: hw/intc/pl190.c
+F: hw/sd/pl181.c
+F: hw/timer/pl031.c
+F: include/hw/arm/primecell.h
+
+ARM cores
+M: Peter Maydell <peter.maydell@linaro.org>
+S: Maintained
+F: hw/intc/arm*
+F: hw/intc/gic_internal.h
+F: hw/misc/a9scu.c
+F: hw/misc/arm11scu.c
+F: hw/timer/a9gtimer*
+F: hw/timer/arm_*
+F: include/hw/arm/arm.h
+F: include/hw/intc/arm*
+F: include/hw/misc/a9scu.h
+F: include/hw/misc/arm11scu.h
+F: include/hw/timer/a9gtimer.h
+F: include/hw/timer/arm_mptimer.h
+
Exynos
M: Evgeny Voevodin <e.voevodin@samsung.com>
M: Maksim Kozlov <m.kozlov@samsung.com>
@@ -322,11 +358,6 @@ M: Peter Maydell <peter.maydell@linaro.org>
S: Maintained
F: hw/arm/integratorcp.c
-Mainstone
-L: qemu-devel@nongnu.org
-S: Orphan
-F: hw/arm/mainstone.c
-
Musicpal
M: Jan Kiszka <jan.kiszka@web.de>
S: Maintained
@@ -346,11 +377,17 @@ Real View
M: Peter Maydell <peter.maydell@linaro.org>
S: Maintained
F: hw/arm/realview*
+F: hw/intc/realview_gic.c
+F: include/hw/intc/realview_gic.h
-Spitz
+PXA2XX
M: Andrzej Zaborowski <balrogg@gmail.com>
S: Maintained
+F: hw/arm/mainstone.c
F: hw/arm/spitz.c
+F: hw/arm/tosa.c
+F: hw/arm/z2.c
+F: hw/*/pxa2xx*
Stellaris
M: Peter Maydell <peter.maydell@linaro.org>
@@ -726,6 +763,8 @@ M: Scott Wood <scottwood@freescale.com>
L: qemu-ppc@nongnu.org
S: Supported
F: hw/ppc/e500*
+F: hw/pci-host/ppce500.c
+F: hw/net/fsl_etsec/
Character devices
M: Paolo Bonzini <pbonzini@redhat.com>
diff --git a/README b/README
index c7c990d895..f38193fc67 100644
--- a/README
+++ b/README
@@ -1,3 +1,107 @@
-Read the documentation in qemu-doc.html or on http://wiki.qemu-project.org
+ QEMU README
+ ===========
-- QEMU team
+QEMU is a generic and open source machine & userspace emulator and
+virtualizer.
+
+QEMU is capable of emulating a complete machine in software without any
+need for hardware virtualization support. By using dynamic translation,
+it achieves very good performance. QEMU can also integrate with the Xen
+and KVM hypervisors to provide emulated hardware while allowing the
+hypervisor to manage the CPU. With hypervisor support, QEMU can achieve
+near native performance for CPUs. When QEMU emulates CPUs directly it is
+capable of running operating systems made for one machine (e.g. an ARMv7
+board) on a different machine (e.g. an x86_64 PC board).
+
+QEMU is also capable of providing userspace API virtualization for Linux
+and BSD kernel interfaces. This allows binaries compiled against one
+architecture ABI (e.g. the Linux PPC64 ABI) to be run on a host using a
+different architecture ABI (e.g. the Linux x86_64 ABI). This does not
+involve any hardware emulation, simply CPU and syscall emulation.
+
+QEMU aims to fit into a variety of use cases. It can be invoked directly
+by users wishing to have full control over its behaviour and settings.
+It also aims to facilitate integration into higher level management
+layers, by providing a stable command line interface and monitor API.
+It is commonly invoked indirectly via the libvirt library when using
+open source applications such as oVirt, OpenStack and virt-manager.
+
+QEMU as a whole is released under the GNU General Public License,
+version 2. For full licensing details, consult the LICENSE file.
+
+
+Building
+========
+
+QEMU is multi-platform software intended to be buildable on all modern
+Linux platforms, OS-X, Win32 (via the Mingw64 toolchain) and a variety
+of other UNIX targets. The simple steps to build QEMU are:
+
+ mkdir build
+ cd build
+ ../configure
+ make
+
+Complete details of the process for building and configuring QEMU for
+all supported host platforms can be found in the qemu-tech.html file.
+Additional information can also be found online via the QEMU website:
+
+ http://qemu-project.org/Hosts/Linux
+ http://qemu-project.org/Hosts/W32
+
+
+Submitting patches
+==================
+
+The QEMU source code is maintained under the GIT version control system.
+
+ git clone git://git.qemu-project.org/qemu.git
+
+When submitting patches, the preferred approach is to use 'git
+format-patch' and/or 'git send-email' to format & send the mail to the
+qemu-devel@nongnu.org mailing list. All patches submitted must contain
+a 'Signed-off-by' line from the author. Patches should follow the
+guidelines set out in the HACKING and CODING_STYLE files.
+
+Additional information on submitting patches can be found online via
+the QEMU website
+
+ http://qemu-project.org/Contribute/SubmitAPatch
+ http://qemu-project.org/Contribute/TrivialPatches
+
+
+Bug reporting
+=============
+
+The QEMU project uses Launchpad as its primary upstream bug tracker. Bugs
+found when running code built from QEMU git or upstream released sources
+should be reported via:
+
+ https://bugs.launchpad.net/qemu/
+
+If using QEMU via an operating system vendor pre-built binary package, it
+is preferable to report bugs to the vendor's own bug tracker first. If
+the bug is also known to affect latest upstream code, it can also be
+reported via launchpad.
+
+For additional information on bug reporting consult:
+
+ http://qemu-project.org/Contribute/ReportABug
+
+
+Contact
+=======
+
+The QEMU community can be contacted in a number of ways, with the two
+main methods being email and IRC
+
+ - qemu-devel@nongnu.org
+ http://lists.nongnu.org/mailman/listinfo/qemu-devel
+ - #qemu on irc.oftc.net
+
+Information on additional methods of contacting the community can be
+found online via the QEMU website:
+
+ http://qemu-project.org/Contribute/StartHere
+
+-- End
diff --git a/backends/baum.c b/backends/baum.c
index a17f62541b..723c658ac0 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -561,7 +561,10 @@ static void baum_close(struct CharDriverState *chr)
g_free(baum);
}
-CharDriverState *chr_baum_init(void)
+static CharDriverState *chr_baum_init(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
BaumDriverState *baum;
CharDriverState *chr;
@@ -586,14 +589,16 @@ CharDriverState *chr_baum_init(void)
baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
if (baum->brlapi_fd == -1) {
- brlapi_perror("baum_init: brlapi_openConnection");
+ error_setg(errp, "brlapi__openConnection: %s",
+ brlapi_strerror(brlapi_error_location()));
goto fail_handle;
}
baum->cellCount_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, baum_cellCount_timer_cb, baum);
if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
- brlapi_perror("baum_init: brlapi_getDisplaySize");
+ error_setg(errp, "brlapi__getDisplaySize: %s",
+ brlapi_strerror(brlapi_error_location()));
goto fail;
}
@@ -609,7 +614,8 @@ CharDriverState *chr_baum_init(void)
tty = BRLAPI_TTY_DEFAULT;
if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
- brlapi_perror("baum_init: brlapi_enterTtyMode");
+ error_setg(errp, "brlapi__enterTtyMode: %s",
+ brlapi_strerror(brlapi_error_location()));
goto fail;
}
@@ -629,7 +635,8 @@ fail_handle:
static void register_types(void)
{
- register_char_driver("braille", CHARDEV_BACKEND_KIND_BRAILLE, NULL);
+ register_char_driver("braille", CHARDEV_BACKEND_KIND_BRAILLE, NULL,
+ chr_baum_init);
}
type_init(register_types);
diff --git a/backends/msmouse.c b/backends/msmouse.c
index 0119110a40..0126fa0b13 100644
--- a/backends/msmouse.c
+++ b/backends/msmouse.c
@@ -63,7 +63,10 @@ static void msmouse_chr_close (struct CharDriverState *chr)
g_free (chr);
}
-CharDriverState *qemu_chr_open_msmouse(void)
+static CharDriverState *qemu_chr_open_msmouse(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
CharDriverState *chr;
@@ -79,7 +82,8 @@ CharDriverState *qemu_chr_open_msmouse(void)
static void register_types(void)
{
- register_char_driver("msmouse", CHARDEV_BACKEND_KIND_MSMOUSE, NULL);
+ register_char_driver("msmouse", CHARDEV_BACKEND_KIND_MSMOUSE, NULL,
+ qemu_chr_open_msmouse);
}
type_init(register_types);
diff --git a/backends/testdev.c b/backends/testdev.c
index 1429152d05..26d5c7307a 100644
--- a/backends/testdev.c
+++ b/backends/testdev.c
@@ -108,7 +108,10 @@ static void testdev_close(struct CharDriverState *chr)
g_free(testdev);
}
-CharDriverState *chr_testdev_init(void)
+static CharDriverState *chr_testdev_init(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
TestdevCharState *testdev;
CharDriverState *chr;
@@ -125,7 +128,8 @@ CharDriverState *chr_testdev_init(void)
static void register_types(void)
{
- register_char_driver("testdev", CHARDEV_BACKEND_KIND_TESTDEV, NULL);
+ register_char_driver("testdev", CHARDEV_BACKEND_KIND_TESTDEV, NULL,
+ chr_testdev_init);
}
type_init(register_types);
diff --git a/configure b/configure
index f08327e10e..913ae4a0ec 100755
--- a/configure
+++ b/configure
@@ -1166,18 +1166,14 @@ fi
# Note that if the Python conditional here evaluates True we will exit
# with status 1 which is a shell 'false' value.
-if ! $python -c 'import sys; sys.exit(sys.version_info < (2,4) or sys.version_info >= (3,))'; then
- error_exit "Cannot use '$python', Python 2.4 or later is required." \
+if ! $python -c 'import sys; sys.exit(sys.version_info < (2,6) or sys.version_info >= (3,))'; then
+ error_exit "Cannot use '$python', Python 2.6 or later is required." \
"Note that Python 3 or later is not yet supported." \
"Use --python=/path/to/python to specify a supported Python."
fi
-# The -B switch was added in Python 2.6.
-# If it is supplied, compiled files are not written.
-# Use it for Python versions which support it.
-if $python -B -c 'import sys; sys.exit(0)' 2>/dev/null; then
- python="$python -B"
-fi
+# Suppress writing compiled files
+python="$python -B"
case "$cpu" in
ppc)
diff --git a/cpu-exec-common.c b/cpu-exec-common.c
index 16d305b911..43edf36777 100644
--- a/cpu-exec-common.c
+++ b/cpu-exec-common.c
@@ -37,31 +37,32 @@ void cpu_resume_from_signal(CPUState *cpu, void *puc)
siglongjmp(cpu->jmp_env, 1);
}
-void cpu_reload_memory_map(CPUState *cpu)
+void cpu_reloading_memory_map(void)
{
- AddressSpaceDispatch *d;
-
if (qemu_in_vcpu_thread()) {
- /* Do not let the guest prolong the critical section as much as it
- * as it desires.
+ /* The guest can in theory prolong the RCU critical section as long
+ * as it feels like. The major problem with this is that because it
+ * can do multiple reconfigurations of the memory map within the
+ * critical section, we could potentially accumulate an unbounded
+ * collection of memory data structures awaiting reclamation.
+ *
+ * Because the only thing we're currently protecting with RCU is the
+ * memory data structures, it's sufficient to break the critical section
+ * in this callback, which we know will get called every time the
+ * memory map is rearranged.
*
- * Currently, this is prevented by the I/O thread's periodinc kicking
- * of the VCPU thread (iothread_requesting_mutex, qemu_cpu_kick_thread)
- * but this will go away once TCG's execution moves out of the global
- * mutex.
+ * (If we add anything else in the system that uses RCU to protect
+ * its data structures, we will need to implement some other mechanism
+ * to force TCG CPUs to exit the critical section, at which point this
+ * part of this callback might become unnecessary.)
*
* This pair matches cpu_exec's rcu_read_lock()/rcu_read_unlock(), which
- * only protects cpu->as->dispatch. Since we reload it below, we can
- * split the critical section.
+ * only protects cpu->as->dispatch. Since we know our caller is about
+ * to reload it, it's safe to split the critical section.
*/
rcu_read_unlock();
rcu_read_lock();
}
-
- /* The CPU and TLB are protected by the iothread lock. */
- d = atomic_rcu_read(&cpu->as->dispatch);
- cpu->memory_dispatch = d;
- tlb_flush(cpu, 1);
}
#endif
diff --git a/docs/rcu.txt b/docs/rcu.txt
index 21ecb8106c..2f70954e82 100644
--- a/docs/rcu.txt
+++ b/docs/rcu.txt
@@ -128,7 +128,7 @@ The core RCU API is small:
the callback function is g_free, in particular, g_free_rcu can be
used. In the above case, one could have written simply:
- g_free_rcu(foo_reclaim, rcu);
+ g_free_rcu(&foo, rcu);
typeof(*p) atomic_rcu_read(p);
diff --git a/exec.c b/exec.c
index 7d90a52252..aad94a0ef7 100644
--- a/exec.c
+++ b/exec.c
@@ -161,6 +161,21 @@ static void memory_map_init(void);
static void tcg_commit(MemoryListener *listener);
static MemoryRegion io_mem_watch;
+
+/**
+ * CPUAddressSpace: all the information a CPU needs about an AddressSpace
+ * @cpu: the CPU whose AddressSpace this is
+ * @as: the AddressSpace itself
+ * @memory_dispatch: its dispatch pointer (cached, RCU protected)
+ * @tcg_as_listener: listener for tracking changes to the AddressSpace
+ */
+struct CPUAddressSpace {
+ CPUState *cpu;
+ AddressSpace *as;
+ struct AddressSpaceDispatch *memory_dispatch;
+ MemoryListener tcg_as_listener;
+};
+
#endif
#if !defined(CONFIG_USER_ONLY)
@@ -431,7 +446,7 @@ address_space_translate_for_iotlb(CPUState *cpu, hwaddr addr,
hwaddr *xlat, hwaddr *plen)
{
MemoryRegionSection *section;
- section = address_space_translate_internal(cpu->memory_dispatch,
+ section = address_space_translate_internal(cpu->cpu_ases[0].memory_dispatch,
addr, xlat, plen, false);
assert(!section->mr->iommu_ops);
@@ -537,13 +552,16 @@ void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as)
/* We only support one address space per cpu at the moment. */
assert(cpu->as == as);
- if (cpu->tcg_as_listener) {
- memory_listener_unregister(cpu->tcg_as_listener);
- } else {
- cpu->tcg_as_listener = g_new0(MemoryListener, 1);
+ if (cpu->cpu_ases) {
+ /* We've already registered the listener for our only AS */
+ return;
}
- cpu->tcg_as_listener->commit = tcg_commit;
- memory_listener_register(cpu->tcg_as_listener, as);
+
+ cpu->cpu_ases = g_new0(CPUAddressSpace, 1);
+ cpu->cpu_ases[0].cpu = cpu;
+ cpu->cpu_ases[0].as = as;
+ cpu->cpu_ases[0].tcg_as_listener.commit = tcg_commit;
+ memory_listener_register(&cpu->cpu_ases[0].tcg_as_listener, as);
}
#endif
@@ -601,7 +619,6 @@ void cpu_exec_init(CPUState *cpu, Error **errp)
#ifndef CONFIG_USER_ONLY
cpu->as = &address_space_memory;
cpu->thread_id = qemu_get_thread_id();
- cpu_reload_memory_map(cpu);
#endif
#if defined(CONFIG_USER_ONLY)
@@ -2219,7 +2236,8 @@ static uint16_t dummy_section(PhysPageMap *map, AddressSpace *as,
MemoryRegion *iotlb_to_region(CPUState *cpu, hwaddr index)
{
- AddressSpaceDispatch *d = atomic_rcu_read(&cpu->memory_dispatch);
+ CPUAddressSpace *cpuas = &cpu->cpu_ases[0];
+ AddressSpaceDispatch *d = atomic_rcu_read(&cpuas->memory_dispatch);
MemoryRegionSection *sections = d->map.sections;
return sections[index & ~TARGET_PAGE_MASK].mr;
@@ -2278,19 +2296,20 @@ static void mem_commit(MemoryListener *listener)
static void tcg_commit(MemoryListener *listener)
{
- CPUState *cpu;
+ CPUAddressSpace *cpuas;
+ AddressSpaceDispatch *d;
/* since each CPU stores ram addresses in its TLB cache, we must
reset the modified entries */
- /* XXX: slow ! */
- CPU_FOREACH(cpu) {
- /* FIXME: Disentangle the cpu.h circular files deps so we can
- directly get the right CPU from listener. */
- if (cpu->tcg_as_listener != listener) {
- continue;
- }
- cpu_reload_memory_map(cpu);
- }
+ cpuas = container_of(listener, CPUAddressSpace, tcg_as_listener);
+ cpu_reloading_memory_map();
+ /* The CPU and TLB are protected by the iothread lock.
+ * We reload the dispatch pointer now because cpu_reloading_memory_map()
+ * may have split the RCU critical section.
+ */
+ d = atomic_rcu_read(&cpuas->as->dispatch);
+ cpuas->memory_dispatch = d;
+ tlb_flush(cpuas->cpu, 1);
}
void address_space_init_dispatch(AddressSpace *as)
diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
index 44beee3a05..0fd69230ae 100644
--- a/hw/i386/kvm/pci-assign.c
+++ b/hw/i386/kvm/pci-assign.c
@@ -979,7 +979,7 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev)
MSIMessage msg = msi_get_message(pci_dev, 0);
int virq;
- virq = kvm_irqchip_add_msi_route(kvm_state, msg);
+ virq = kvm_irqchip_add_msi_route(kvm_state, msg, pci_dev);
if (virq < 0) {
perror("assigned_dev_update_msi: kvm_irqchip_add_msi_route");
return;
@@ -1017,7 +1017,7 @@ static void assigned_dev_update_msi_msg(PCIDevice *pci_dev)
}
kvm_irqchip_update_msi_route(kvm_state, assigned_dev->msi_virq[0],
- msi_get_message(pci_dev, 0));
+ msi_get_message(pci_dev, 0), pci_dev);
}
static bool assigned_dev_msix_masked(MSIXTableEntry *entry)
@@ -1083,7 +1083,7 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev)
msg.address = entry->addr_lo | ((uint64_t)entry->addr_hi << 32);
msg.data = entry->data;
- r = kvm_irqchip_add_msi_route(kvm_state, msg);
+ r = kvm_irqchip_add_msi_route(kvm_state, msg, pci_dev);
if (r < 0) {
return r;
}
@@ -1483,7 +1483,7 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
* error bits, leave the rest. */
status = pci_get_long(pci_dev->config + pos + PCI_X_STATUS);
status &= ~(PCI_X_STATUS_BUS | PCI_X_STATUS_DEVFN);
- status |= (pci_bus_num(pci_dev->bus) << 8) | pci_dev->devfn;
+ status |= pci_requester_id(pci_dev);
status &= ~(PCI_X_STATUS_SPL_DISC | PCI_X_STATUS_UNX_SPL |
PCI_X_STATUS_SPL_ERR);
pci_set_long(pci_dev->config + pos + PCI_X_STATUS, status);
@@ -1602,7 +1602,8 @@ static void assigned_dev_msix_mmio_write(void *opaque, hwaddr addr,
msg.data = entry->data;
ret = kvm_irqchip_update_msi_route(kvm_state,
- adev->msi_virq[i], msg);
+ adev->msi_virq[i], msg,
+ pdev);
if (ret) {
error_report("Error updating irq routing entry (%d)", ret);
}
diff --git a/hw/pci/msi.c b/hw/pci/msi.c
index f9c0484420..c1dd5318c8 100644
--- a/hw/pci/msi.c
+++ b/hw/pci/msi.c
@@ -294,7 +294,7 @@ void msi_send_message(PCIDevice *dev, MSIMessage msg)
{
MemTxAttrs attrs = {};
- attrs.stream_id = (pci_bus_num(dev->bus) << 8) | dev->devfn;
+ attrs.requester_id = pci_requester_id(dev);
address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
attrs, NULL);
}
diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
index 46e0ad8a93..98d2c183b0 100644
--- a/hw/pci/pcie_aer.c
+++ b/hw/pci/pcie_aer.c
@@ -979,7 +979,7 @@ static int do_pcie_aer_inject_error(Monitor *mon,
}
}
err.status = error_status;
- err.source_id = (pci_bus_num(dev->bus) << 8) | dev->devfn;
+ err.source_id = pci_requester_id(dev);
err.flags = 0;
if (correctable) {
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index a04369c5ad..dcd724e6a5 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -431,7 +431,7 @@ static uint64_t megasas_fw_time(void)
static uint64_t megasas_get_sata_addr(uint16_t id)
{
uint64_t addr = (0x1221ULL << 48);
- return addr & (id << 24);
+ return addr | ((uint64_t)id << 24);
}
/*
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index ffac8f4bb6..d373c1b676 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -558,7 +558,7 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
const int memset_off = offsetof(SCSIRequest, sense)
+ sizeof(req->sense);
- req = g_slice_alloc(reqops->size);
+ req = g_malloc(reqops->size);
memset((uint8_t *)req + memset_off, 0, reqops->size - memset_off);
req->refcount = 1;
req->bus = bus;
@@ -1622,7 +1622,7 @@ void scsi_req_unref(SCSIRequest *req)
}
object_unref(OBJECT(req->dev));
object_unref(OBJECT(qbus->parent));
- g_slice_free1(req->ops->size, req);
+ g_free(req);
}
}
diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
index 5575648a98..1248fd93ee 100644
--- a/hw/scsi/virtio-scsi-dataplane.c
+++ b/hw/scsi/virtio-scsi-dataplane.c
@@ -57,7 +57,7 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
return NULL;
}
- r = g_slice_new(VirtIOSCSIVring);
+ r = g_new(VirtIOSCSIVring, 1);
r->host_notifier = *virtio_queue_get_host_notifier(vq);
r->guest_notifier = *virtio_queue_get_guest_notifier(vq);
aio_set_event_notifier(s->ctx, &r->host_notifier, handler);
@@ -73,7 +73,7 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
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);
+ g_free(r);
return NULL;
}
@@ -182,18 +182,18 @@ static void virtio_scsi_vring_teardown(VirtIOSCSI *s)
if (s->ctrl_vring) {
vring_teardown(&s->ctrl_vring->vring, vdev, 0);
- g_slice_free(VirtIOSCSIVring, s->ctrl_vring);
+ g_free(s->ctrl_vring);
s->ctrl_vring = NULL;
}
if (s->event_vring) {
vring_teardown(&s->event_vring->vring, vdev, 1);
- g_slice_free(VirtIOSCSIVring, s->event_vring);
+ g_free(s->event_vring);
s->event_vring = NULL;
}
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);
- g_slice_free(VirtIOSCSIVring, s->cmd_vrings[i]);
+ g_free(s->cmd_vrings[i]);
s->cmd_vrings[i] = NULL;
}
free(s->cmd_vrings);
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 1c33f146a7..20885fb7f1 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -47,7 +47,7 @@ VirtIOSCSIReq *virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq)
const size_t zero_skip = offsetof(VirtIOSCSIReq, elem)
+ sizeof(VirtQueueElement);
- req = g_slice_alloc(sizeof(*req) + vs->cdb_size);
+ req = g_malloc(sizeof(*req) + vs->cdb_size);
req->vq = vq;
req->dev = s;
qemu_sglist_init(&req->qsgl, DEVICE(s), 8, &address_space_memory);
@@ -58,11 +58,9 @@ VirtIOSCSIReq *virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq)
void virtio_scsi_free_req(VirtIOSCSIReq *req)
{
- VirtIOSCSICommon *vs = (VirtIOSCSICommon *)req->dev;
-
qemu_iovec_destroy(&req->resp_iov);
qemu_sglist_destroy(&req->qsgl);
- g_slice_free1(sizeof(*req) + vs->cdb_size, req);
+ g_free(req);
}
static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
@@ -250,7 +248,7 @@ static void virtio_scsi_cancel_notify(Notifier *notifier, void *data)
if (--n->tmf_req->remaining == 0) {
virtio_scsi_complete_req(n->tmf_req);
}
- g_slice_free(VirtIOSCSICancelNotifier, n);
+ g_free(n);
}
/* Return 0 if the request is ready to be completed and return to guest;
@@ -301,7 +299,7 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
VirtIOSCSICancelNotifier *notifier;
req->remaining = 1;
- notifier = g_slice_new(VirtIOSCSICancelNotifier);
+ notifier = g_new(VirtIOSCSICancelNotifier, 1);
notifier->tmf_req = req;
notifier->notifier.notify = virtio_scsi_cancel_notify;
scsi_req_cancel_async(r, &notifier->notifier);
@@ -350,7 +348,7 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
VirtIOSCSICancelNotifier *notifier;
req->remaining++;
- notifier = g_slice_new(VirtIOSCSICancelNotifier);
+ notifier = g_new(VirtIOSCSICancelNotifier, 1);
notifier->notifier.notify = virtio_scsi_cancel_notify;
notifier->tmf_req = req;
scsi_req_cancel_async(r, &notifier->notifier);
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index dcabb6d3b3..8fadbcf682 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -424,7 +424,7 @@ static void vfio_add_kvm_msi_virq(VFIOPCIDevice *vdev, VFIOMSIVector *vector,
return;
}
- virq = kvm_irqchip_add_msi_route(kvm_state, *msg);
+ virq = kvm_irqchip_add_msi_route(kvm_state, *msg, &vdev->pdev);
if (virq < 0) {
event_notifier_cleanup(&vector->kvm_interrupt);
return;
@@ -449,9 +449,10 @@ static void vfio_remove_kvm_msi_virq(VFIOMSIVector *vector)
event_notifier_cleanup(&vector->kvm_interrupt);
}
-static void vfio_update_kvm_msi_virq(VFIOMSIVector *vector, MSIMessage msg)
+static void vfio_update_kvm_msi_virq(VFIOMSIVector *vector, MSIMessage msg,
+ PCIDevice *pdev)
{
- kvm_irqchip_update_msi_route(kvm_state, vector->virq, msg);
+ kvm_irqchip_update_msi_route(kvm_state, vector->virq, msg, pdev);
}
static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
@@ -486,7 +487,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
if (!msg) {
vfio_remove_kvm_msi_virq(vector);
} else {
- vfio_update_kvm_msi_virq(vector, *msg);
+ vfio_update_kvm_msi_virq(vector, *msg, pdev);
}
} else {
vfio_add_kvm_msi_virq(vdev, vector, msg, true);
@@ -760,7 +761,7 @@ static void vfio_update_msi(VFIOPCIDevice *vdev)
}
msg = msi_get_message(&vdev->pdev, i);
- vfio_update_kvm_msi_virq(vector, msg);
+ vfio_update_kvm_msi_virq(vector, msg, &vdev->pdev);
}
}
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index e5c406d1d2..f55dd2bf8e 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -590,7 +590,7 @@ static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
int ret;
if (irqfd->users == 0) {
- ret = kvm_irqchip_add_msi_route(kvm_state, msg);
+ ret = kvm_irqchip_add_msi_route(kvm_state, msg, &proxy->pci_dev);
if (ret < 0) {
return ret;
}
@@ -726,7 +726,8 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
if (proxy->vector_irqfd) {
irqfd = &proxy->vector_irqfd[vector];
if (irqfd->msg.data != msg.data || irqfd->msg.address != msg.address) {
- ret = kvm_irqchip_update_msi_route(kvm_state, irqfd->virq, msg);
+ ret = kvm_irqchip_update_msi_route(kvm_state, irqfd->virq, msg,
+ &proxy->pci_dev);
if (ret < 0) {
return ret;
}
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index a63fd6015e..9b93b9b47d 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -84,8 +84,7 @@ void QEMU_NORETURN cpu_loop_exit(CPUState *cpu);
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
#if !defined(CONFIG_USER_ONLY)
-bool qemu_in_vcpu_thread(void);
-void cpu_reload_memory_map(CPUState *cpu);
+void cpu_reloading_memory_map(void);
void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as);
/* cputlb.c */
/**
@@ -357,8 +356,6 @@ extern uintptr_t tci_tb_ptr;
#if !defined(CONFIG_USER_ONLY)
-void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align));
-
struct MemoryRegion *iotlb_to_region(CPUState *cpu,
hwaddr index);
@@ -408,7 +405,4 @@ extern int singlestep;
extern CPUState *tcg_current_cpu;
extern bool exit_request;
-#if !defined(CONFIG_USER_ONLY)
-void migration_bitmap_extend(ram_addr_t old, ram_addr_t new);
-#endif
#endif
diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
index f8537a8d91..e601061848 100644
--- a/include/exec/memattrs.h
+++ b/include/exec/memattrs.h
@@ -35,8 +35,8 @@ typedef struct MemTxAttrs {
unsigned int secure:1;
/* Memory access is usermode (unprivileged) */
unsigned int user:1;
- /* Stream ID (for MSI for example) */
- unsigned int stream_id:16;
+ /* Requester ID (for MSI for example) */
+ unsigned int requester_id:16;
} MemTxAttrs;
/* Bus masters which don't specify any attributes will get this,
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index c400a75a6a..3360ac5fde 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -289,5 +289,6 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest,
return num_dirty;
}
+void migration_bitmap_extend(ram_addr_t old, ram_addr_t new);
#endif
#endif
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 551cb3d608..f5e7fd818a 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -677,6 +677,11 @@ static inline uint32_t pci_config_size(const PCIDevice *d)
return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
}
+static inline uint16_t pci_requester_id(PCIDevice *dev)
+{
+ return (pci_bus_num(dev->bus) << 8) | dev->devfn;
+}
+
/* DMA access functions */
static inline AddressSpace *pci_get_address_space(PCIDevice *dev)
{
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index ee1ce1d44d..d4a8f7a6d5 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -16,6 +16,7 @@ typedef struct BusClass BusClass;
typedef struct BusState BusState;
typedef struct CharDriverState CharDriverState;
typedef struct CompatProperty CompatProperty;
+typedef struct CPUAddressSpace CPUAddressSpace;
typedef struct DeviceState DeviceState;
typedef struct DeviceListener DeviceListener;
typedef struct DisplayChangeListener DisplayChangeListener;
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index b613ff0329..51a1323ead 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -234,6 +234,10 @@ struct kvm_run;
* @can_do_io: Nonzero if memory-mapped IO is safe. Deterministic execution
* requires that IO only be performed on the last instruction of a TB
* so that interrupts take effect immediately.
+ * @cpu_ases: Pointer to array of CPUAddressSpaces (which define the
+ * AddressSpaces this CPU has)
+ * @as: Pointer to the first AddressSpace, for the convenience of targets which
+ * only have a single AddressSpace
* @env_ptr: Pointer to subclass-specific CPUArchState field.
* @current_tb: Currently executing TB.
* @gdb_regs: Additional GDB registers.
@@ -280,9 +284,8 @@ struct CPUState {
QemuMutex work_mutex;
struct qemu_work_item *queued_work_first, *queued_work_last;
+ CPUAddressSpace *cpu_ases;
AddressSpace *as;
- struct AddressSpaceDispatch *memory_dispatch;
- MemoryListener *tcg_as_listener;
void *env_ptr; /* CPUArchState */
struct TranslationBlock *current_tb;
diff --git a/include/standard-headers/asm-x86/hyperv.h b/include/standard-headers/asm-x86/hyperv.h
index 99d311e4ad..c37c14e018 100644
--- a/include/standard-headers/asm-x86/hyperv.h
+++ b/include/standard-headers/asm-x86/hyperv.h
@@ -153,6 +153,12 @@
/* MSR used to provide vcpu index */
#define HV_X64_MSR_VP_INDEX 0x40000002
+/* MSR used to reset the guest OS. */
+#define HV_X64_MSR_RESET 0x40000003
+
+/* MSR used to provide vcpu runtime in 100ns units */
+#define HV_X64_MSR_VP_RUNTIME 0x40000010
+
/* MSR used to read the per-partition time reference counter */
#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 832b7fead4..edf76693d9 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -345,7 +345,9 @@ bool chr_is_ringbuf(const CharDriverState *chr);
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
void register_char_driver(const char *name, ChardevBackendKind kind,
- void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp));
+ void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp),
+ CharDriverState *(*create)(const char *id, ChardevBackend *backend,
+ ChardevReturn *ret, Error **errp));
/* add an eventfd to the qemu devices that are polled */
CharDriverState *qemu_chr_open_eventfd(int eventfd);
@@ -354,18 +356,8 @@ extern int term_escape_char;
CharDriverState *qemu_char_get_next_serial(void);
-/* msmouse */
-CharDriverState *qemu_chr_open_msmouse(void);
-
-/* testdev.c */
-CharDriverState *chr_testdev_init(void);
-
-/* baum.c */
-CharDriverState *chr_baum_init(void);
-
/* console.c */
-typedef CharDriverState *(VcHandler)(ChardevVC *vc);
-
+typedef CharDriverState *(VcHandler)(ChardevVC *vc, Error **errp);
void register_vc_handler(VcHandler *handler);
-CharDriverState *vc_init(ChardevVC *vc);
+
#endif
diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h
index 3f162a9e08..30ddd1220e 100644
--- a/include/sysemu/cpus.h
+++ b/include/sysemu/cpus.h
@@ -2,6 +2,7 @@
#define QEMU_CPUS_H
/* cpus.c */
+bool qemu_in_vcpu_thread(void);
void qemu_init_cpu_loop(void);
void resume_all_vcpus(void);
void pause_all_vcpus(void);
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 2a58b4d19e..461ef65dea 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -52,6 +52,7 @@ extern bool kvm_msi_via_irqfd_allowed;
extern bool kvm_gsi_routing_allowed;
extern bool kvm_gsi_direct_mapping;
extern bool kvm_readonly_mem_allowed;
+extern bool kvm_direct_msi_allowed;
#if defined CONFIG_KVM || !defined NEED_CPU_H
#define kvm_enabled() (kvm_allowed)
@@ -145,6 +146,13 @@ extern bool kvm_readonly_mem_allowed;
*/
#define kvm_readonly_mem_enabled() (kvm_readonly_mem_allowed)
+/**
+ * kvm_direct_msi_enabled:
+ *
+ * Returns: true if KVM allows direct MSI injection.
+ */
+#define kvm_direct_msi_enabled() (kvm_direct_msi_allowed)
+
#else
#define kvm_enabled() (0)
#define kvm_irqchip_in_kernel() (false)
@@ -157,6 +165,7 @@ extern bool kvm_readonly_mem_allowed;
#define kvm_gsi_routing_allowed() (false)
#define kvm_gsi_direct_mapping() (false)
#define kvm_readonly_mem_enabled() (false)
+#define kvm_direct_msi_enabled() (false)
#endif
struct kvm_run;
@@ -182,8 +191,6 @@ int kvm_has_sync_mmu(void);
int kvm_has_vcpu_events(void);
int kvm_has_robust_singlestep(void);
int kvm_has_debugregs(void);
-int kvm_has_xsave(void);
-int kvm_has_xcrs(void);
int kvm_has_pit_state2(void);
int kvm_has_many_ioeventfds(void);
int kvm_has_gsi_routing(void);
@@ -210,6 +217,10 @@ int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset);
int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
int kvm_on_sigbus(int code, void *addr);
+/* interface with exec.c */
+
+void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align));
+
/* internal API */
int kvm_ioctl(KVMState *s, int type, ...);
@@ -313,7 +324,7 @@ int kvm_arch_on_sigbus(int code, void *addr);
void kvm_arch_init_irq_routing(KVMState *s);
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
- uint64_t address, uint32_t data);
+ uint64_t address, uint32_t data, PCIDevice *dev);
int kvm_arch_msi_data_to_gsi(uint32_t data);
@@ -438,8 +449,9 @@ static inline void cpu_clean_state(CPUState *cpu)
}
}
-int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg);
-int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg);
+int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg, PCIDevice *dev);
+int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg,
+ PCIDevice *dev);
void kvm_irqchip_release_virq(KVMState *s, int virq);
int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter);
diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h
index 0dff4229fc..f9ce357ff3 100644
--- a/include/ui/qemu-spice.h
+++ b/include/ui/qemu-spice.h
@@ -43,9 +43,7 @@ int qemu_spice_set_pw_expire(time_t expires);
int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
const char *subject);
-CharDriverState *qemu_chr_open_spice_vmc(const char *type);
#if SPICE_SERVER_VERSION >= 0x000c02
-CharDriverState *qemu_chr_open_spice_port(const char *name);
void qemu_spice_register_ports(void);
#else
static inline CharDriverState *qemu_chr_open_spice_port(const char *name)
diff --git a/kvm-all.c b/kvm-all.c
index 0be4615cdb..c442838668 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -77,8 +77,6 @@ struct KVMState
#ifdef KVM_CAP_SET_GUEST_DEBUG
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
#endif
- int pit_state2;
- int xsave, xcrs;
int many_ioeventfds;
int intx_set_mask;
/* The man page (and posix) say ioctl numbers are signed int, but
@@ -93,7 +91,6 @@ struct KVMState
uint32_t *used_gsi_bitmap;
unsigned int gsi_count;
QTAILQ_HEAD(msi_hashtab, KVMMSIRoute) msi_hashtab[KVM_MSI_HASHTAB_SIZE];
- bool direct_msi;
#endif
KVMMemoryListener memory_listener;
};
@@ -111,6 +108,7 @@ bool kvm_gsi_direct_mapping;
bool kvm_allowed;
bool kvm_readonly_mem_allowed;
bool kvm_vm_attributes_allowed;
+bool kvm_direct_msi_allowed;
static const KVMCapabilityInfo kvm_required_capabilites[] = {
KVM_CAP_INFO(USER_MEMORY),
@@ -642,15 +640,15 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
/* kvm works in page size chunks, but the function may be called
with sub-page size and unaligned start address. Pad the start
address to next and truncate size to previous page boundary. */
- delta = (TARGET_PAGE_SIZE - (start_addr & ~TARGET_PAGE_MASK));
- delta &= ~TARGET_PAGE_MASK;
+ delta = qemu_real_host_page_size - (start_addr & ~qemu_real_host_page_mask);
+ delta &= ~qemu_real_host_page_mask;
if (delta > size) {
return;
}
start_addr += delta;
size -= delta;
- size &= TARGET_PAGE_MASK;
- if (!size || (start_addr & ~TARGET_PAGE_MASK)) {
+ size &= qemu_real_host_page_mask;
+ if (!size || (start_addr & ~qemu_real_host_page_mask)) {
return;
}
@@ -979,7 +977,7 @@ void kvm_init_irq_routing(KVMState *s)
s->irq_routes = g_malloc0(sizeof(*s->irq_routes));
s->nr_allocated_irq_routes = 0;
- if (!s->direct_msi) {
+ if (!kvm_direct_msi_allowed) {
for (i = 0; i < KVM_MSI_HASHTAB_SIZE; i++) {
QTAILQ_INIT(&s->msi_hashtab[i]);
}
@@ -1113,7 +1111,7 @@ static int kvm_irqchip_get_virq(KVMState *s)
* number can succeed even though a new route entry cannot be added.
* When this happens, flush dynamic MSI entries to free IRQ route entries.
*/
- if (!s->direct_msi && s->irq_routes->nr == s->gsi_count) {
+ if (!kvm_direct_msi_allowed && s->irq_routes->nr == s->gsi_count) {
kvm_flush_dynamic_msi_routes(s);
}
@@ -1150,7 +1148,7 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
struct kvm_msi msi;
KVMMSIRoute *route;
- if (s->direct_msi) {
+ if (kvm_direct_msi_allowed) {
msi.address_lo = (uint32_t)msg.address;
msi.address_hi = msg.address >> 32;
msi.data = le32_to_cpu(msg.data);
@@ -1189,7 +1187,7 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
return kvm_set_irq(s, route->kroute.gsi, 1);
}
-int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
+int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg, PCIDevice *dev)
{
struct kvm_irq_routing_entry kroute = {};
int virq;
@@ -1213,7 +1211,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
kroute.u.msi.address_lo = (uint32_t)msg.address;
kroute.u.msi.address_hi = msg.address >> 32;
kroute.u.msi.data = le32_to_cpu(msg.data);
- if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data)) {
+ if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data, dev)) {
kvm_irqchip_release_virq(s, virq);
return -EINVAL;
}
@@ -1224,7 +1222,8 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
return virq;
}
-int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
+int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg,
+ PCIDevice *dev)
{
struct kvm_irq_routing_entry kroute = {};
@@ -1242,7 +1241,7 @@ int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
kroute.u.msi.address_lo = (uint32_t)msg.address;
kroute.u.msi.address_hi = msg.address >> 32;
kroute.u.msi.data = le32_to_cpu(msg.data);
- if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data)) {
+ if (kvm_arch_fixup_msi_route(&kroute, msg.address, msg.data, dev)) {
return -EINVAL;
}
@@ -1585,20 +1584,8 @@ static int kvm_init(MachineState *ms)
s->debugregs = kvm_check_extension(s, KVM_CAP_DEBUGREGS);
#endif
-#ifdef KVM_CAP_XSAVE
- s->xsave = kvm_check_extension(s, KVM_CAP_XSAVE);
-#endif
-
-#ifdef KVM_CAP_XCRS
- s->xcrs = kvm_check_extension(s, KVM_CAP_XCRS);
-#endif
-
-#ifdef KVM_CAP_PIT_STATE2
- s->pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2);
-#endif
-
#ifdef KVM_CAP_IRQ_ROUTING
- s->direct_msi = (kvm_check_extension(s, KVM_CAP_SIGNAL_MSI) > 0);
+ kvm_direct_msi_allowed = (kvm_check_extension(s, KVM_CAP_SIGNAL_MSI) > 0);
#endif
s->intx_set_mask = kvm_check_extension(s, KVM_CAP_PCI_2_3);
@@ -2062,21 +2049,6 @@ int kvm_has_debugregs(void)
return kvm_state->debugregs;
}
-int kvm_has_xsave(void)
-{
- return kvm_state->xsave;
-}
-
-int kvm_has_xcrs(void)
-{
- return kvm_state->xcrs;
-}
-
-int kvm_has_pit_state2(void)
-{
- return kvm_state->pit_state2;
-}
-
int kvm_has_many_ioeventfds(void)
{
if (!kvm_enabled()) {
diff --git a/kvm-stub.c b/kvm-stub.c
index d9ad624eee..a5051f7c6e 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -67,11 +67,6 @@ int kvm_has_many_ioeventfds(void)
return 0;
}
-int kvm_has_pit_state2(void)
-{
- return 0;
-}
-
void kvm_setup_guest_memory(void *start, size_t size)
{
}
@@ -115,7 +110,7 @@ int kvm_on_sigbus(int code, void *addr)
}
#ifndef CONFIG_USER_ONLY
-int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
+int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg, PCIDevice *dev)
{
return -ENOSYS;
}
@@ -128,7 +123,8 @@ void kvm_irqchip_release_virq(KVMState *s, int virq)
{
}
-int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg)
+int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg,
+ PCIDevice *dev)
{
return -ENOSYS;
}
diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h
index c8abf257c1..d3714c0aaf 100644
--- a/linux-headers/asm-arm64/kvm.h
+++ b/linux-headers/asm-arm64/kvm.h
@@ -53,14 +53,20 @@ struct kvm_regs {
struct user_fpsimd_state fp_regs;
};
-/* Supported Processor Types */
+/*
+ * Supported CPU Targets - Adding a new target type is not recommended,
+ * unless there are some special registers not supported by the
+ * genericv8 syreg table.
+ */
#define KVM_ARM_TARGET_AEM_V8 0
#define KVM_ARM_TARGET_FOUNDATION_V8 1
#define KVM_ARM_TARGET_CORTEX_A57 2
#define KVM_ARM_TARGET_XGENE_POTENZA 3
#define KVM_ARM_TARGET_CORTEX_A53 4
+/* Generic ARM v8 target */
+#define KVM_ARM_TARGET_GENERIC_V8 5
-#define KVM_ARM_NUM_TARGETS 5
+#define KVM_ARM_NUM_TARGETS 6
/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
#define KVM_ARM_DEVICE_TYPE_SHIFT 0
@@ -100,12 +106,39 @@ struct kvm_sregs {
struct kvm_fpu {
};
+/*
+ * See v8 ARM ARM D7.3: Debug Registers
+ *
+ * The architectural limit is 16 debug registers of each type although
+ * in practice there are usually less (see ID_AA64DFR0_EL1).
+ *
+ * Although the control registers are architecturally defined as 32
+ * bits wide we use a 64 bit structure here to keep parity with
+ * KVM_GET/SET_ONE_REG behaviour which treats all system registers as
+ * 64 bit values. It also allows for the possibility of the
+ * architecture expanding the control registers without having to
+ * change the userspace ABI.
+ */
+#define KVM_ARM_MAX_DBG_REGS 16
struct kvm_guest_debug_arch {
+ __u64 dbg_bcr[KVM_ARM_MAX_DBG_REGS];
+ __u64 dbg_bvr[KVM_ARM_MAX_DBG_REGS];
+ __u64 dbg_wcr[KVM_ARM_MAX_DBG_REGS];
+ __u64 dbg_wvr[KVM_ARM_MAX_DBG_REGS];
};
struct kvm_debug_exit_arch {
+ __u32 hsr;
+ __u64 far; /* used for watchpoints */
};
+/*
+ * Architecture specific defines for kvm_guest_debug->control
+ */
+
+#define KVM_GUESTDBG_USE_SW_BP (1 << 16)
+#define KVM_GUESTDBG_USE_HW (1 << 17)
+
struct kvm_sync_regs {
};
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 683f713e91..dcc410efe7 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -183,6 +183,7 @@ struct kvm_s390_skeys {
#define KVM_EXIT_EPR 23
#define KVM_EXIT_SYSTEM_EVENT 24
#define KVM_EXIT_S390_STSI 25
+#define KVM_EXIT_IOAPIC_EOI 26
/* For KVM_EXIT_INTERNAL_ERROR */
/* Emulate instruction failed. */
@@ -237,6 +238,7 @@ struct kvm_run {
__u32 count;
__u64 data_offset; /* relative to kvm_run start */
} io;
+ /* KVM_EXIT_DEBUG */
struct {
struct kvm_debug_exit_arch arch;
} debug;
@@ -285,6 +287,7 @@ struct kvm_run {
__u32 data;
__u8 is_write;
} dcr;
+ /* KVM_EXIT_INTERNAL_ERROR */
struct {
__u32 suberror;
/* Available with KVM_CAP_INTERNAL_ERROR_DATA: */
@@ -295,6 +298,7 @@ struct kvm_run {
struct {
__u64 gprs[32];
} osi;
+ /* KVM_EXIT_PAPR_HCALL */
struct {
__u64 nr;
__u64 ret;
@@ -330,6 +334,10 @@ struct kvm_run {
__u8 sel1;
__u16 sel2;
} s390_stsi;
+ /* KVM_EXIT_IOAPIC_EOI */
+ struct {
+ __u8 vector;
+ } eoi;
/* Fix the size of the union. */
char padding[256];
};
@@ -819,6 +827,10 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_DISABLE_QUIRKS 116
#define KVM_CAP_X86_SMM 117
#define KVM_CAP_MULTI_ADDRESS_SPACE 118
+#define KVM_CAP_GUEST_DEBUG_HW_BPS 119
+#define KVM_CAP_GUEST_DEBUG_HW_WPS 120
+#define KVM_CAP_SPLIT_IRQCHIP 121
+#define KVM_CAP_IOEVENTFD_ANY_LENGTH 122
#ifdef KVM_CAP_IRQ_ROUTING
diff --git a/nbd.c b/nbd.c
index 07240bd3e3..74859cbe09 100644
--- a/nbd.c
+++ b/nbd.c
@@ -1005,7 +1005,7 @@ static NBDRequest *nbd_request_get(NBDClient *client)
client->nb_requests++;
nbd_update_can_read(client);
- req = g_slice_new0(NBDRequest);
+ req = g_new0(NBDRequest, 1);
nbd_client_get(client);
req->client = client;
return req;
@@ -1018,7 +1018,7 @@ static void nbd_request_put(NBDRequest *req)
if (req->data) {
qemu_vfree(req->data);
}
- g_slice_free(NBDRequest, req);
+ g_free(req);
client->nb_requests--;
nbd_update_can_read(client);
diff --git a/qemu-char.c b/qemu-char.c
index 653ea10d6f..13371c4931 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -383,7 +383,10 @@ static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
return len;
}
-static CharDriverState *qemu_chr_open_null(void)
+static CharDriverState *qemu_chr_open_null(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
CharDriverState *chr;
@@ -679,11 +682,20 @@ static GSource *mux_chr_add_watch(CharDriverState *s, GIOCondition cond)
return d->drv->chr_add_watch(d->drv, cond);
}
-static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
+static CharDriverState *qemu_chr_open_mux(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret, Error **errp)
{
- CharDriverState *chr;
+ ChardevMux *mux = backend->mux;
+ CharDriverState *chr, *drv;
MuxDriver *d;
+ drv = qemu_chr_find(mux->chardev);
+ if (drv == NULL) {
+ error_setg(errp, "mux: base chardev %s not found", mux->chardev);
+ return NULL;
+ }
+
chr = qemu_chr_alloc();
d = g_new0(MuxDriver, 1);
@@ -1078,18 +1090,17 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
return chr;
}
-static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
+static CharDriverState *qemu_chr_open_pipe(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
+ ChardevHostdev *opts = backend->pipe;
int fd_in, fd_out;
char filename_in[CHR_MAX_FILENAME_SIZE];
char filename_out[CHR_MAX_FILENAME_SIZE];
const char *filename = opts->device;
- if (filename == NULL) {
- fprintf(stderr, "chardev: pipe: no filename given\n");
- return NULL;
- }
-
snprintf(filename_in, CHR_MAX_FILENAME_SIZE, "%s.in", filename);
snprintf(filename_out, CHR_MAX_FILENAME_SIZE, "%s.out", filename);
TFR(fd_in = qemu_open(filename_in, O_RDWR | O_BINARY));
@@ -1101,6 +1112,7 @@ static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
close(fd_out);
TFR(fd_in = fd_out = qemu_open(filename, O_RDWR | O_BINARY));
if (fd_in < 0) {
+ error_setg_file_open(errp, errno, filename);
return NULL;
}
}
@@ -1156,19 +1168,23 @@ static void qemu_chr_close_stdio(struct CharDriverState *chr)
fd_chr_close(chr);
}
-static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
+static CharDriverState *qemu_chr_open_stdio(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
+ ChardevStdio *opts = backend->stdio;
CharDriverState *chr;
struct sigaction act;
if (is_daemonized()) {
- error_report("cannot use stdio with -daemonize");
+ error_setg(errp, "cannot use stdio with -daemonize");
return NULL;
}
if (stdio_in_use) {
- error_report("cannot use stdio by multiple character devices");
- exit(1);
+ error_setg(errp, "cannot use stdio by multiple character devices");
+ return NULL;
}
stdio_in_use = true;
@@ -1196,7 +1212,8 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
|| defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
|| defined(__GLIBC__)
-#define HAVE_CHARDEV_TTY 1
+#define HAVE_CHARDEV_SERIAL 1
+#define HAVE_CHARDEV_PTY 1
typedef struct {
GIOChannel *fd;
@@ -1389,7 +1406,9 @@ static void pty_chr_close(struct CharDriverState *chr)
}
static CharDriverState *qemu_chr_open_pty(const char *id,
- ChardevReturn *ret)
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
CharDriverState *chr;
PtyCharDriver *s;
@@ -1398,6 +1417,7 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
master_fd = qemu_openpty_raw(&slave_fd, pty_name);
if (master_fd < 0) {
+ error_setg_errno(errp, errno, "Failed to create PTY");
return NULL;
}
@@ -1752,12 +1772,13 @@ static void pp_close(CharDriverState *chr)
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
-static CharDriverState *qemu_chr_open_pp_fd(int fd)
+static CharDriverState *qemu_chr_open_pp_fd(int fd, Error **errp)
{
CharDriverState *chr;
ParallelCharDriver *drv;
if (ioctl(fd, PPCLAIM) < 0) {
+ error_setg_errno(errp, errno, "not a parallel port");
close(fd);
return NULL;
}
@@ -1817,7 +1838,7 @@ static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
return 0;
}
-static CharDriverState *qemu_chr_open_pp_fd(int fd)
+static CharDriverState *qemu_chr_open_pp_fd(int fd, Error **errp)
{
CharDriverState *chr;
@@ -1832,6 +1853,8 @@ static CharDriverState *qemu_chr_open_pp_fd(int fd)
#else /* _WIN32 */
+#define HAVE_CHARDEV_SERIAL 1
+
typedef struct {
int max_size;
HANDLE hcom, hrecv, hsend;
@@ -1883,7 +1906,7 @@ static void win_chr_close(CharDriverState *chr)
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
-static int win_chr_init(CharDriverState *chr, const char *filename)
+static int win_chr_init(CharDriverState *chr, const char *filename, Error **errp)
{
WinCharState *s = chr->opaque;
COMMCONFIG comcfg;
@@ -1894,25 +1917,25 @@ static int win_chr_init(CharDriverState *chr, const char *filename)
s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!s->hsend) {
- fprintf(stderr, "Failed CreateEvent\n");
+ error_setg(errp, "Failed CreateEvent");
goto fail;
}
s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!s->hrecv) {
- fprintf(stderr, "Failed CreateEvent\n");
+ error_setg(errp, "Failed CreateEvent");
goto fail;
}
s->hcom = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (s->hcom == INVALID_HANDLE_VALUE) {
- fprintf(stderr, "Failed CreateFile (%lu)\n", GetLastError());
+ error_setg(errp, "Failed CreateFile (%lu)", GetLastError());
s->hcom = NULL;
goto fail;
}
if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) {
- fprintf(stderr, "Failed SetupComm\n");
+ error_setg(errp, "Failed SetupComm");
goto fail;
}
@@ -1923,23 +1946,23 @@ static int win_chr_init(CharDriverState *chr, const char *filename)
CommConfigDialog(filename, NULL, &comcfg);
if (!SetCommState(s->hcom, &comcfg.dcb)) {
- fprintf(stderr, "Failed SetCommState\n");
+ error_setg(errp, "Failed SetCommState");
goto fail;
}
if (!SetCommMask(s->hcom, EV_ERR)) {
- fprintf(stderr, "Failed SetCommMask\n");
+ error_setg(errp, "Failed SetCommMask");
goto fail;
}
cto.ReadIntervalTimeout = MAXDWORD;
if (!SetCommTimeouts(s->hcom, &cto)) {
- fprintf(stderr, "Failed SetCommTimeouts\n");
+ error_setg(errp, "Failed SetCommTimeouts");
goto fail;
}
if (!ClearCommError(s->hcom, &err, &comstat)) {
- fprintf(stderr, "Failed ClearCommError\n");
+ error_setg(errp, "Failed ClearCommError");
goto fail;
}
qemu_add_polling_cb(win_chr_poll, chr);
@@ -2044,7 +2067,8 @@ static int win_chr_poll(void *opaque)
return 0;
}
-static CharDriverState *qemu_chr_open_win_path(const char *filename)
+static CharDriverState *qemu_chr_open_win_path(const char *filename,
+ Error **errp)
{
CharDriverState *chr;
WinCharState *s;
@@ -2055,7 +2079,7 @@ static CharDriverState *qemu_chr_open_win_path(const char *filename)
chr->chr_write = win_chr_write;
chr->chr_close = win_chr_close;
- if (win_chr_init(chr, filename) < 0) {
+ if (win_chr_init(chr, filename, errp) < 0) {
g_free(s);
g_free(chr);
return NULL;
@@ -2079,7 +2103,8 @@ static int win_chr_pipe_poll(void *opaque)
return 0;
}
-static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
+static int win_chr_pipe_init(CharDriverState *chr, const char *filename,
+ Error **errp)
{
WinCharState *s = chr->opaque;
OVERLAPPED ov;
@@ -2091,12 +2116,12 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!s->hsend) {
- fprintf(stderr, "Failed CreateEvent\n");
+ error_setg(errp, "Failed CreateEvent");
goto fail;
}
s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!s->hrecv) {
- fprintf(stderr, "Failed CreateEvent\n");
+ error_setg(errp, "Failed CreateEvent");
goto fail;
}
@@ -2106,7 +2131,7 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
PIPE_WAIT,
MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL);
if (s->hcom == INVALID_HANDLE_VALUE) {
- fprintf(stderr, "Failed CreateNamedPipe (%lu)\n", GetLastError());
+ error_setg(errp, "Failed CreateNamedPipe (%lu)", GetLastError());
s->hcom = NULL;
goto fail;
}
@@ -2115,13 +2140,13 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ret = ConnectNamedPipe(s->hcom, &ov);
if (ret) {
- fprintf(stderr, "Failed ConnectNamedPipe\n");
+ error_setg(errp, "Failed ConnectNamedPipe");
goto fail;
}
ret = GetOverlappedResult(s->hcom, &ov, &size, TRUE);
if (!ret) {
- fprintf(stderr, "Failed GetOverlappedResult\n");
+ error_setg(errp, "Failed GetOverlappedResult");
if (ov.hEvent) {
CloseHandle(ov.hEvent);
ov.hEvent = NULL;
@@ -2142,8 +2167,12 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
}
-static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
+static CharDriverState *qemu_chr_open_pipe(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
+ ChardevHostdev *opts = backend->pipe;
const char *filename = opts->device;
CharDriverState *chr;
WinCharState *s;
@@ -2154,7 +2183,7 @@ static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
chr->chr_write = win_chr_write;
chr->chr_close = win_chr_close;
- if (win_chr_pipe_init(chr, filename) < 0) {
+ if (win_chr_pipe_init(chr, filename, errp) < 0) {
g_free(s);
g_free(chr);
return NULL;
@@ -2175,7 +2204,10 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
return chr;
}
-static CharDriverState *qemu_chr_open_win_con(void)
+static CharDriverState *qemu_chr_open_win_con(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE));
}
@@ -2316,7 +2348,10 @@ static void win_stdio_close(CharDriverState *chr)
g_free(chr);
}
-static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
+static CharDriverState *qemu_chr_open_stdio(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
CharDriverState *chr;
WinStdioCharState *stdio;
@@ -2328,8 +2363,8 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
if (stdio->hStdIn == INVALID_HANDLE_VALUE) {
- fprintf(stderr, "cannot open stdio: invalid handle\n");
- exit(1);
+ error_setg(errp, "cannot open stdio: invalid handle");
+ return NULL;
}
is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0;
@@ -2341,25 +2376,30 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
if (is_console) {
if (qemu_add_wait_object(stdio->hStdIn,
win_stdio_wait_func, chr)) {
- fprintf(stderr, "qemu_add_wait_object: failed\n");
+ error_setg(errp, "qemu_add_wait_object: failed");
+ goto err1;
}
} else {
DWORD dwId;
stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
stdio->hInputDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- stdio->hInputThread = CreateThread(NULL, 0, win_stdio_thread,
- chr, 0, &dwId);
-
- if (stdio->hInputThread == INVALID_HANDLE_VALUE
- || stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
+ if (stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
|| stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) {
- fprintf(stderr, "cannot create stdio thread or event\n");
- exit(1);
+ error_setg(errp, "cannot create event");
+ goto err2;
}
if (qemu_add_wait_object(stdio->hInputReadyEvent,
win_stdio_thread_wait_func, chr)) {
- fprintf(stderr, "qemu_add_wait_object: failed\n");
+ error_setg(errp, "qemu_add_wait_object: failed");
+ goto err2;
+ }
+ stdio->hInputThread = CreateThread(NULL, 0, win_stdio_thread,
+ chr, 0, &dwId);
+
+ if (stdio->hInputThread == INVALID_HANDLE_VALUE) {
+ error_setg(errp, "cannot create stdio thread");
+ goto err3;
}
}
@@ -2377,6 +2417,15 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
qemu_chr_fe_set_echo(chr, false);
return chr;
+
+err3:
+ qemu_del_wait_object(stdio->hInputReadyEvent, NULL, NULL);
+err2:
+ CloseHandle(stdio->hInputReadyEvent);
+ CloseHandle(stdio->hInputDoneEvent);
+err1:
+ qemu_del_wait_object(stdio->hStdIn, NULL, NULL);
+ return NULL;
}
#endif /* !_WIN32 */
@@ -3173,9 +3222,12 @@ static void ringbuf_chr_close(struct CharDriverState *chr)
chr->opaque = NULL;
}
-static CharDriverState *qemu_chr_open_ringbuf(ChardevRingbuf *opts,
+static CharDriverState *qemu_chr_open_ringbuf(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
Error **errp)
{
+ ChardevRingbuf *opts = backend->ringbuf;
CharDriverState *chr;
RingBufCharDriver *d;
@@ -3462,6 +3514,7 @@ static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
backend->stdio->signal = qemu_opt_get_bool(opts, "signal", true);
}
+#ifdef HAVE_CHARDEV_SERIAL
static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
@@ -3474,7 +3527,9 @@ static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
backend->serial = g_new0(ChardevHostdev, 1);
backend->serial->device = g_strdup(device);
}
+#endif
+#ifdef HAVE_CHARDEV_PARPORT
static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
@@ -3487,6 +3542,7 @@ static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
backend->parallel = g_new0(ChardevHostdev, 1);
backend->parallel->device = g_strdup(device);
}
+#endif
static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
@@ -3641,12 +3697,16 @@ typedef struct CharDriver {
const char *name;
ChardevBackendKind kind;
void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp);
+ CharDriverState *(*create)(const char *id, ChardevBackend *backend,
+ ChardevReturn *ret, Error **errp);
} CharDriver;
static GSList *backends;
void register_char_driver(const char *name, ChardevBackendKind kind,
- void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp))
+ void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp),
+ CharDriverState *(*create)(const char *id, ChardevBackend *backend,
+ ChardevReturn *ret, Error **errp))
{
CharDriver *s;
@@ -3654,6 +3714,7 @@ void register_char_driver(const char *name, ChardevBackendKind kind,
s->name = g_strdup(name);
s->kind = kind;
s->parse = parse;
+ s->create = create;
backends = g_slist_append(backends, s);
}
@@ -4002,8 +4063,12 @@ QemuOptsList qemu_chardev_opts = {
#ifdef _WIN32
-static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp)
+static CharDriverState *qmp_chardev_open_file(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
+ ChardevFile *file = backend->file;
HANDLE out;
if (file->has_in) {
@@ -4020,17 +4085,13 @@ static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp)
return qemu_chr_open_win_file(out);
}
-static CharDriverState *qmp_chardev_open_serial(ChardevHostdev *serial,
+static CharDriverState *qmp_chardev_open_serial(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
Error **errp)
{
- return qemu_chr_open_win_path(serial->device);
-}
-
-static CharDriverState *qmp_chardev_open_parallel(ChardevHostdev *parallel,
- Error **errp)
-{
- error_setg(errp, "character device backend type 'parallel' not supported");
- return NULL;
+ ChardevHostdev *serial = backend->serial;
+ return qemu_chr_open_win_path(serial->device, errp);
}
#else /* WIN32 */
@@ -4047,8 +4108,12 @@ static int qmp_chardev_open_file_source(char *src, int flags,
return fd;
}
-static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp)
+static CharDriverState *qmp_chardev_open_file(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
+ ChardevFile *file = backend->file;
int flags, in = -1, out;
flags = O_WRONLY | O_TRUNC | O_CREAT | O_BINARY;
@@ -4069,10 +4134,13 @@ static CharDriverState *qmp_chardev_open_file(ChardevFile *file, Error **errp)
return qemu_chr_open_fd(in, out);
}
-static CharDriverState *qmp_chardev_open_serial(ChardevHostdev *serial,
+#ifdef HAVE_CHARDEV_SERIAL
+static CharDriverState *qmp_chardev_open_serial(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
Error **errp)
{
-#ifdef HAVE_CHARDEV_TTY
+ ChardevHostdev *serial = backend->serial;
int fd;
fd = qmp_chardev_open_file_source(serial->device, O_RDWR, errp);
@@ -4081,28 +4149,25 @@ static CharDriverState *qmp_chardev_open_serial(ChardevHostdev *serial,
}
qemu_set_nonblock(fd);
return qemu_chr_open_tty_fd(fd);
-#else
- error_setg(errp, "character device backend type 'serial' not supported");
- return NULL;
-#endif
}
+#endif
-static CharDriverState *qmp_chardev_open_parallel(ChardevHostdev *parallel,
+#ifdef HAVE_CHARDEV_PARPORT
+static CharDriverState *qmp_chardev_open_parallel(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
Error **errp)
{
-#ifdef HAVE_CHARDEV_PARPORT
+ ChardevHostdev *parallel = backend->parallel;
int fd;
fd = qmp_chardev_open_file_source(parallel->device, O_RDWR, errp);
if (fd < 0) {
return NULL;
}
- return qemu_chr_open_pp_fd(fd);
-#else
- error_setg(errp, "character device backend type 'parallel' not supported");
- return NULL;
-#endif
+ return qemu_chr_open_pp_fd(fd, errp);
}
+#endif
#endif /* WIN32 */
@@ -4131,11 +4196,14 @@ static gboolean socket_reconnect_timeout(gpointer opaque)
return false;
}
-static CharDriverState *qmp_chardev_open_socket(ChardevSocket *sock,
+static CharDriverState *qmp_chardev_open_socket(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
Error **errp)
{
CharDriverState *chr;
TCPCharDriver *s;
+ ChardevSocket *sock = backend->socket;
SocketAddress *addr = sock->addr;
bool do_nodelay = sock->has_nodelay ? sock->nodelay : false;
bool is_listen = sock->has_server ? sock->server : true;
@@ -4197,9 +4265,12 @@ static CharDriverState *qmp_chardev_open_socket(ChardevSocket *sock,
return chr;
}
-static CharDriverState *qmp_chardev_open_udp(ChardevUdp *udp,
+static CharDriverState *qmp_chardev_open_udp(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
Error **errp)
{
+ ChardevUdp *udp = backend->udp;
int fd;
fd = socket_dgram(udp->remote, udp->local, errp);
@@ -4213,7 +4284,10 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
Error **errp)
{
ChardevReturn *ret = g_new0(ChardevReturn, 1);
- CharDriverState *base, *chr = NULL;
+ CharDriverState *chr = NULL;
+ Error *local_err = NULL;
+ GSList *i;
+ CharDriver *cd;
chr = qemu_chr_find(id);
if (chr) {
@@ -4222,106 +4296,40 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
return NULL;
}
- switch (backend->kind) {
- case CHARDEV_BACKEND_KIND_FILE:
- chr = qmp_chardev_open_file(backend->file, errp);
- break;
- case CHARDEV_BACKEND_KIND_SERIAL:
- chr = qmp_chardev_open_serial(backend->serial, errp);
- break;
- case CHARDEV_BACKEND_KIND_PARALLEL:
- chr = qmp_chardev_open_parallel(backend->parallel, errp);
- break;
- case CHARDEV_BACKEND_KIND_PIPE:
- chr = qemu_chr_open_pipe(backend->pipe);
- break;
- case CHARDEV_BACKEND_KIND_SOCKET:
- chr = qmp_chardev_open_socket(backend->socket, errp);
- break;
- case CHARDEV_BACKEND_KIND_UDP:
- chr = qmp_chardev_open_udp(backend->udp, errp);
- break;
-#ifdef HAVE_CHARDEV_TTY
- case CHARDEV_BACKEND_KIND_PTY:
- chr = qemu_chr_open_pty(id, ret);
- break;
-#endif
- case CHARDEV_BACKEND_KIND_NULL:
- chr = qemu_chr_open_null();
- break;
- case CHARDEV_BACKEND_KIND_MUX:
- base = qemu_chr_find(backend->mux->chardev);
- if (base == NULL) {
- error_setg(errp, "mux: base chardev %s not found",
- backend->mux->chardev);
+ for (i = backends; i; i = i->next) {
+ cd = i->data;
+
+ if (cd->kind == backend->kind) {
+ chr = cd->create(id, backend, ret, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ goto out_error;
+ }
break;
}
- chr = qemu_chr_open_mux(base);
- break;
- case CHARDEV_BACKEND_KIND_MSMOUSE:
- chr = qemu_chr_open_msmouse();
- break;
-#ifdef CONFIG_BRLAPI
- case CHARDEV_BACKEND_KIND_BRAILLE:
- chr = chr_baum_init();
- break;
-#endif
- case CHARDEV_BACKEND_KIND_TESTDEV:
- chr = chr_testdev_init();
- break;
- case CHARDEV_BACKEND_KIND_STDIO:
- chr = qemu_chr_open_stdio(backend->stdio);
- break;
-#ifdef _WIN32
- case CHARDEV_BACKEND_KIND_CONSOLE:
- chr = qemu_chr_open_win_con();
- break;
-#endif
-#ifdef CONFIG_SPICE
- case CHARDEV_BACKEND_KIND_SPICEVMC:
- chr = qemu_chr_open_spice_vmc(backend->spicevmc->type);
- break;
- case CHARDEV_BACKEND_KIND_SPICEPORT:
- chr = qemu_chr_open_spice_port(backend->spiceport->fqdn);
- break;
-#endif
- case CHARDEV_BACKEND_KIND_VC:
- chr = vc_init(backend->vc);
- break;
- case CHARDEV_BACKEND_KIND_RINGBUF:
- case CHARDEV_BACKEND_KIND_MEMORY:
- chr = qemu_chr_open_ringbuf(backend->ringbuf, errp);
- break;
- default:
- error_setg(errp, "unknown chardev backend (%d)", backend->kind);
- break;
}
- /*
- * Character backend open hasn't been fully converted to the Error
- * API. Some opens fail without setting an error. Set a generic
- * error then.
- * TODO full conversion to Error API
- */
- if (chr == NULL && errp && !*errp) {
- error_setg(errp, "Failed to create chardev");
+ if (chr == NULL) {
+ assert(!i);
+ error_setg(errp, "chardev backend not available");
+ goto out_error;
}
- if (chr) {
- chr->label = g_strdup(id);
- chr->avail_connections =
- (backend->kind == CHARDEV_BACKEND_KIND_MUX) ? MAX_MUX : 1;
- if (!chr->filename) {
- chr->filename = g_strdup(ChardevBackendKind_lookup[backend->kind]);
- }
- if (!chr->explicit_be_open) {
- qemu_chr_be_event(chr, CHR_EVENT_OPENED);
- }
- QTAILQ_INSERT_TAIL(&chardevs, chr, next);
- return ret;
- } else {
- g_free(ret);
- return NULL;
+
+ chr->label = g_strdup(id);
+ chr->avail_connections =
+ (backend->kind == CHARDEV_BACKEND_KIND_MUX) ? MAX_MUX : 1;
+ if (!chr->filename) {
+ chr->filename = g_strdup(ChardevBackendKind_lookup[backend->kind]);
+ }
+ if (!chr->explicit_be_open) {
+ qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}
+ QTAILQ_INSERT_TAIL(&chardevs, chr, next);
+ return ret;
+
+out_error:
+ g_free(ret);
+ return NULL;
}
void qmp_chardev_remove(const char *id, Error **errp)
@@ -4343,32 +4351,45 @@ void qmp_chardev_remove(const char *id, Error **errp)
static void register_types(void)
{
- register_char_driver("null", CHARDEV_BACKEND_KIND_NULL, NULL);
+ register_char_driver("null", CHARDEV_BACKEND_KIND_NULL, NULL,
+ qemu_chr_open_null);
register_char_driver("socket", CHARDEV_BACKEND_KIND_SOCKET,
- qemu_chr_parse_socket);
- register_char_driver("udp", CHARDEV_BACKEND_KIND_UDP, qemu_chr_parse_udp);
+ qemu_chr_parse_socket, qmp_chardev_open_socket);
+ register_char_driver("udp", CHARDEV_BACKEND_KIND_UDP, qemu_chr_parse_udp,
+ qmp_chardev_open_udp);
register_char_driver("ringbuf", CHARDEV_BACKEND_KIND_RINGBUF,
- qemu_chr_parse_ringbuf);
+ qemu_chr_parse_ringbuf, qemu_chr_open_ringbuf);
register_char_driver("file", CHARDEV_BACKEND_KIND_FILE,
- qemu_chr_parse_file_out);
+ qemu_chr_parse_file_out, qmp_chardev_open_file);
register_char_driver("stdio", CHARDEV_BACKEND_KIND_STDIO,
- qemu_chr_parse_stdio);
+ qemu_chr_parse_stdio, qemu_chr_open_stdio);
+#if defined HAVE_CHARDEV_SERIAL
register_char_driver("serial", CHARDEV_BACKEND_KIND_SERIAL,
- qemu_chr_parse_serial);
+ qemu_chr_parse_serial, qmp_chardev_open_serial);
register_char_driver("tty", CHARDEV_BACKEND_KIND_SERIAL,
- qemu_chr_parse_serial);
+ qemu_chr_parse_serial, qmp_chardev_open_serial);
+#endif
+#ifdef HAVE_CHARDEV_PARPORT
register_char_driver("parallel", CHARDEV_BACKEND_KIND_PARALLEL,
- qemu_chr_parse_parallel);
+ qemu_chr_parse_parallel, qmp_chardev_open_parallel);
register_char_driver("parport", CHARDEV_BACKEND_KIND_PARALLEL,
- qemu_chr_parse_parallel);
- register_char_driver("pty", CHARDEV_BACKEND_KIND_PTY, NULL);
- register_char_driver("console", CHARDEV_BACKEND_KIND_CONSOLE, NULL);
+ qemu_chr_parse_parallel, qmp_chardev_open_parallel);
+#endif
+#ifdef HAVE_CHARDEV_PTY
+ register_char_driver("pty", CHARDEV_BACKEND_KIND_PTY, NULL,
+ qemu_chr_open_pty);
+#endif
+#ifdef _WIN32
+ register_char_driver("console", CHARDEV_BACKEND_KIND_CONSOLE, NULL,
+ qemu_chr_open_win_con);
+#endif
register_char_driver("pipe", CHARDEV_BACKEND_KIND_PIPE,
- qemu_chr_parse_pipe);
- register_char_driver("mux", CHARDEV_BACKEND_KIND_MUX, qemu_chr_parse_mux);
+ qemu_chr_parse_pipe, qemu_chr_open_pipe);
+ register_char_driver("mux", CHARDEV_BACKEND_KIND_MUX, qemu_chr_parse_mux,
+ qemu_chr_open_mux);
/* Bug-compatibility: */
register_char_driver("memory", CHARDEV_BACKEND_KIND_MEMORY,
- qemu_chr_parse_ringbuf);
+ qemu_chr_parse_ringbuf, qemu_chr_open_ringbuf);
/* this must be done after machine init, since we register FEs with muxes
* as part of realize functions like serial_isa_realizefn when -nographic
* is specified
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index b6d71eae17..b0f6e113c5 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1010,7 +1010,9 @@ sub possible {
case|
else|
asm|__asm__|
- do
+ do|
+ \#|
+ \#\#
)(?:\s|$)|
^(?:typedef|struct|enum)\b
)}x;
@@ -1704,11 +1706,6 @@ sub process {
ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
}
-# ... however, open braces on typedef lines should be avoided.
- if ($line =~ /^.\s*typedef\s+(enum|union|struct)(?:\s+$Ident\b)?.*[^;]$/) {
- ERROR("typedefs should be separate from struct declaration\n" . $herecurr);
- }
-
# missing space after union, struct or enum definition
if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
ERROR("missing space after $1 definition\n" . $herecurr);
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index d41bb745a8..a20fb5c90c 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -296,15 +296,14 @@ static CharDriverState *chr_open(const char *subtype,
return chr;
}
-CharDriverState *qemu_chr_open_spice_vmc(const char *type)
+static CharDriverState *qemu_chr_open_spice_vmc(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
+ const char *type = backend->spicevmc->type;
const char **psubtype = spice_server_char_device_recognized_subtypes();
- if (type == NULL) {
- fprintf(stderr, "spice-qemu-char: missing name parameter\n");
- print_allowed_subtypes();
- return NULL;
- }
for (; *psubtype != NULL; ++psubtype) {
if (strcmp(type, *psubtype) == 0) {
break;
@@ -320,8 +319,12 @@ CharDriverState *qemu_chr_open_spice_vmc(const char *type)
}
#if SPICE_SERVER_VERSION >= 0x000c02
-CharDriverState *qemu_chr_open_spice_port(const char *name)
+static CharDriverState *qemu_chr_open_spice_port(const char *id,
+ ChardevBackend *backend,
+ ChardevReturn *ret,
+ Error **errp)
{
+ const char *name = backend->spiceport->fqdn;
CharDriverState *chr;
SpiceCharDriver *s;
@@ -379,9 +382,9 @@ static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend,
static void register_types(void)
{
register_char_driver("spicevmc", CHARDEV_BACKEND_KIND_SPICEVMC,
- qemu_chr_parse_spice_vmc);
+ qemu_chr_parse_spice_vmc, qemu_chr_open_spice_vmc);
register_char_driver("spiceport", CHARDEV_BACKEND_KIND_SPICEPORT,
- qemu_chr_parse_spice_port);
+ qemu_chr_parse_spice_port, qemu_chr_open_spice_port);
}
type_init(register_types);
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 85e4e81017..1862f8472b 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -1,8 +1,5 @@
stub-obj-y += arch-query-cpu-def.o
stub-obj-y += bdrv-commit-all.o
-stub-obj-y += chr-baum-init.o
-stub-obj-y += chr-msmouse.o
-stub-obj-y += chr-testdev.o
stub-obj-y += clock-warp.o
stub-obj-y += cpu-get-clock.o
stub-obj-y += cpu-get-icount.o
@@ -23,7 +20,6 @@ stub-obj-y += mon-is-qmp.o
stub-obj-y += mon-printf.o
stub-obj-y += monitor-init.o
stub-obj-y += notify-event.o
-stub-obj-$(CONFIG_SPICE) += qemu-chr-open-spice.o
stub-obj-y += qtest.o
stub-obj-y += reset.o
stub-obj-y += runstate-check.o
@@ -31,7 +27,6 @@ stub-obj-y += set-fd-handler.o
stub-obj-y += slirp.o
stub-obj-y += sysbus.o
stub-obj-y += uuid.o
-stub-obj-y += vc-init.o
stub-obj-y += vm-stop.o
stub-obj-y += vmstate.o
stub-obj-$(CONFIG_WIN32) += fd-register.o
diff --git a/stubs/chr-baum-init.c b/stubs/chr-baum-init.c
deleted file mode 100644
index f5cc6ce1f8..0000000000
--- a/stubs/chr-baum-init.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "qemu-common.h"
-#include "sysemu/char.h"
-
-CharDriverState *chr_baum_init(void)
-{
- return NULL;
-}
diff --git a/stubs/chr-msmouse.c b/stubs/chr-msmouse.c
deleted file mode 100644
index 812f8b0abe..0000000000
--- a/stubs/chr-msmouse.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "qemu-common.h"
-#include "sysemu/char.h"
-
-CharDriverState *qemu_chr_open_msmouse(void)
-{
- return 0;
-}
diff --git a/stubs/chr-testdev.c b/stubs/chr-testdev.c
deleted file mode 100644
index 23112a2c07..0000000000
--- a/stubs/chr-testdev.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "qemu-common.h"
-#include "sysemu/char.h"
-
-CharDriverState *chr_testdev_init(void)
-{
- return 0;
-}
diff --git a/stubs/qemu-chr-open-spice.c b/stubs/qemu-chr-open-spice.c
deleted file mode 100644
index f1c4849d9c..0000000000
--- a/stubs/qemu-chr-open-spice.c
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "qemu-common.h"
-#include "ui/qemu-spice.h"
-
-CharDriverState *qemu_chr_open_spice_vmc(const char *type)
-{
- return NULL;
-}
-
-#if SPICE_SERVER_VERSION >= 0x000c02
-CharDriverState *qemu_chr_open_spice_port(const char *name)
-{
- return NULL;
-}
-#endif
diff --git a/stubs/vc-init.c b/stubs/vc-init.c
deleted file mode 100644
index 308dfa0800..0000000000
--- a/stubs/vc-init.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "qemu-common.h"
-#include "sysemu/char.h"
-
-CharDriverState *vc_init(ChardevVC *vc)
-{
- return 0;
-}
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index 6aadcd88f7..79ef4c61de 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -605,7 +605,7 @@ int kvm_arm_vgic_probe(void)
}
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
- uint64_t address, uint32_t data)
+ uint64_t address, uint32_t data, PCIDevice *dev)
{
return 0;
}
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index c35b624c9d..e3bfe9d07e 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -88,8 +88,12 @@ typedef struct X86CPU {
bool hyperv_vapic;
bool hyperv_relaxed_timing;
int hyperv_spinlock_attempts;
+ char *hyperv_vendor_id;
bool hyperv_time;
bool hyperv_crash;
+ bool hyperv_reset;
+ bool hyperv_vpindex;
+ bool hyperv_runtime;
bool check_cpuid;
bool enforce_cpuid;
bool expose_kvm;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 05d7f26bf1..5f53af248f 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -3140,12 +3140,16 @@ static Property x86_cpu_properties[] = {
DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false),
DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false),
DEFINE_PROP_BOOL("hv-crash", X86CPU, hyperv_crash, false),
+ DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
+ DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
+ DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, false),
DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, 0),
DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, 0),
DEFINE_PROP_UINT32("xlevel2", X86CPU, env.cpuid_xlevel2, 0),
+ DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
DEFINE_PROP_END_OF_LIST()
};
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 54d9d50140..a395b4b07a 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -911,6 +911,7 @@ typedef struct CPUX86State {
uint64_t msr_hv_vapic;
uint64_t msr_hv_tsc;
uint64_t msr_hv_crash_params[HV_X64_MSR_CRASH_PARAMS];
+ uint64_t msr_hv_runtime;
/* exception/interrupt handling */
int error_code;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 80d1a7e01e..64046cb69d 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -28,6 +28,7 @@
#include "exec/gdbstub.h"
#include "qemu/host-utils.h"
#include "qemu/config-file.h"
+#include "qemu/error-report.h"
#include "hw/i386/pc.h"
#include "hw/i386/apic.h"
#include "hw/i386/apic_internal.h"
@@ -82,12 +83,24 @@ static bool has_msr_hv_hypercall;
static bool has_msr_hv_vapic;
static bool has_msr_hv_tsc;
static bool has_msr_hv_crash;
+static bool has_msr_hv_reset;
+static bool has_msr_hv_vpindex;
+static bool has_msr_hv_runtime;
static bool has_msr_mtrr;
static bool has_msr_xss;
static bool has_msr_architectural_pmu;
static uint32_t num_architectural_pmu_counters;
+static int has_xsave;
+static int has_xcrs;
+static int has_pit_state2;
+
+int kvm_has_pit_state2(void)
+{
+ return has_pit_state2;
+}
+
bool kvm_has_smm(void)
{
return kvm_check_extension(kvm_state, KVM_CAP_X86_SMM);
@@ -460,7 +473,10 @@ static bool hyperv_enabled(X86CPU *cpu)
(hyperv_hypercall_available(cpu) ||
cpu->hyperv_time ||
cpu->hyperv_relaxed_timing ||
- cpu->hyperv_crash);
+ cpu->hyperv_crash ||
+ cpu->hyperv_reset ||
+ cpu->hyperv_vpindex ||
+ cpu->hyperv_runtime);
}
static Error *invtsc_mig_blocker;
@@ -490,7 +506,18 @@ int kvm_arch_init_vcpu(CPUState *cs)
if (hyperv_enabled(cpu)) {
c = &cpuid_data.entries[cpuid_i++];
c->function = HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
- memcpy(signature, "Microsoft Hv", 12);
+ if (!cpu->hyperv_vendor_id) {
+ memcpy(signature, "Microsoft Hv", 12);
+ } else {
+ size_t len = strlen(cpu->hyperv_vendor_id);
+
+ if (len > 12) {
+ error_report("hv-vendor-id truncated to 12 characters");
+ len = 12;
+ }
+ memset(signature, 0, 12);
+ memcpy(signature, cpu->hyperv_vendor_id, len);
+ }
c->eax = HYPERV_CPUID_MIN;
c->ebx = signature[0];
c->ecx = signature[1];
@@ -529,7 +556,15 @@ int kvm_arch_init_vcpu(CPUState *cs)
if (cpu->hyperv_crash && has_msr_hv_crash) {
c->edx |= HV_X64_GUEST_CRASH_MSR_AVAILABLE;
}
-
+ if (cpu->hyperv_reset && has_msr_hv_reset) {
+ c->eax |= HV_X64_MSR_RESET_AVAILABLE;
+ }
+ if (cpu->hyperv_vpindex && has_msr_hv_vpindex) {
+ c->eax |= HV_X64_MSR_VP_INDEX_AVAILABLE;
+ }
+ if (cpu->hyperv_runtime && has_msr_hv_runtime) {
+ c->eax |= HV_X64_MSR_VP_RUNTIME_AVAILABLE;
+ }
c = &cpuid_data.entries[cpuid_i++];
c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
if (cpu->hyperv_relaxed_timing) {
@@ -752,7 +787,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
}
}
- if (kvm_has_xsave()) {
+ if (has_xsave) {
env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave));
}
@@ -858,6 +893,18 @@ static int kvm_get_supported_msrs(KVMState *s)
has_msr_hv_crash = true;
continue;
}
+ if (kvm_msr_list->indices[i] == HV_X64_MSR_RESET) {
+ has_msr_hv_reset = true;
+ continue;
+ }
+ if (kvm_msr_list->indices[i] == HV_X64_MSR_VP_INDEX) {
+ has_msr_hv_vpindex = true;
+ continue;
+ }
+ if (kvm_msr_list->indices[i] == HV_X64_MSR_VP_RUNTIME) {
+ has_msr_hv_runtime = true;
+ continue;
+ }
}
}
@@ -908,6 +955,18 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
int ret;
struct utsname utsname;
+#ifdef KVM_CAP_XSAVE
+ has_xsave = kvm_check_extension(s, KVM_CAP_XSAVE);
+#endif
+
+#ifdef KVM_CAP_XCRS
+ has_xcrs = kvm_check_extension(s, KVM_CAP_XCRS);
+#endif
+
+#ifdef KVM_CAP_PIT_STATE2
+ has_pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2);
+#endif
+
ret = kvm_get_supported_msrs(s);
if (ret < 0) {
return ret;
@@ -1116,7 +1175,7 @@ static int kvm_put_xsave(X86CPU *cpu)
uint8_t *xmm, *ymmh, *zmmh;
int i, r;
- if (!kvm_has_xsave()) {
+ if (!has_xsave) {
return kvm_put_fpu(cpu);
}
@@ -1170,7 +1229,7 @@ static int kvm_put_xcrs(X86CPU *cpu)
CPUX86State *env = &cpu->env;
struct kvm_xcrs xcrs = {};
- if (!kvm_has_xcrs()) {
+ if (!has_xcrs) {
return 0;
}
@@ -1403,6 +1462,10 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_CRASH_CTL,
HV_X64_MSR_CRASH_CTL_NOTIFY);
}
+ if (has_msr_hv_runtime) {
+ kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_VP_RUNTIME,
+ env->msr_hv_runtime);
+ }
if (has_msr_mtrr) {
kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype);
kvm_msr_entry_set(&msrs[n++],
@@ -1495,7 +1558,7 @@ static int kvm_get_xsave(X86CPU *cpu)
const uint8_t *xmm, *ymmh, *zmmh;
uint16_t cwd, swd, twd;
- if (!kvm_has_xsave()) {
+ if (!has_xsave) {
return kvm_get_fpu(cpu);
}
@@ -1554,7 +1617,7 @@ static int kvm_get_xcrs(X86CPU *cpu)
int i, ret;
struct kvm_xcrs xcrs;
- if (!kvm_has_xcrs()) {
+ if (!has_xcrs) {
return 0;
}
@@ -1768,6 +1831,9 @@ static int kvm_get_msrs(X86CPU *cpu)
msrs[n++].index = HV_X64_MSR_CRASH_P0 + j;
}
}
+ if (has_msr_hv_runtime) {
+ msrs[n++].index = HV_X64_MSR_VP_RUNTIME;
+ }
if (has_msr_mtrr) {
msrs[n++].index = MSR_MTRRdefType;
msrs[n++].index = MSR_MTRRfix64K_00000;
@@ -1921,6 +1987,9 @@ static int kvm_get_msrs(X86CPU *cpu)
case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
env->msr_hv_crash_params[index - HV_X64_MSR_CRASH_P0] = msrs[i].data;
break;
+ case HV_X64_MSR_VP_RUNTIME:
+ env->msr_hv_runtime = msrs[i].data;
+ break;
case MSR_MTRRdefType:
env->mtrr_deftype = msrs[i].data;
break;
@@ -2956,7 +3025,7 @@ int kvm_device_msix_deassign(KVMState *s, uint32_t dev_id)
}
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
- uint64_t address, uint32_t data)
+ uint64_t address, uint32_t data, PCIDevice *dev)
{
return 0;
}
diff --git a/target-i386/machine.c b/target-i386/machine.c
index 9fa056341a..67373663d0 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -687,6 +687,25 @@ static const VMStateDescription vmstate_msr_hyperv_crash = {
}
};
+static bool hyperv_runtime_enable_needed(void *opaque)
+{
+ X86CPU *cpu = opaque;
+ CPUX86State *env = &cpu->env;
+
+ return env->msr_hv_runtime != 0;
+}
+
+static const VMStateDescription vmstate_msr_hyperv_runtime = {
+ .name = "cpu/msr_hyperv_runtime",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = hyperv_runtime_enable_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(env.msr_hv_runtime, X86CPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static bool avx512_needed(void *opaque)
{
X86CPU *cpu = opaque;
@@ -869,6 +888,7 @@ VMStateDescription vmstate_x86_cpu = {
&vmstate_msr_hyperv_vapic,
&vmstate_msr_hyperv_time,
&vmstate_msr_hyperv_crash,
+ &vmstate_msr_hyperv_runtime,
&vmstate_avx512,
&vmstate_xss,
NULL
diff --git a/target-mips/kvm.c b/target-mips/kvm.c
index d287d42883..12d7db311e 100644
--- a/target-mips/kvm.c
+++ b/target-mips/kvm.c
@@ -678,7 +678,7 @@ int kvm_arch_get_registers(CPUState *cs)
}
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
- uint64_t address, uint32_t data)
+ uint64_t address, uint32_t data, PCIDevice *dev)
{
return 0;
}
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 72762991dc..38aa927eb0 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -2483,7 +2483,7 @@ error_out:
}
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
- uint64_t address, uint32_t data)
+ uint64_t address, uint32_t data, PCIDevice *dev)
{
return 0;
}
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 5fdee1b20b..0305ffa9d3 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -2208,7 +2208,7 @@ int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu)
}
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
- uint64_t address, uint32_t data)
+ uint64_t address, uint32_t data, PCIDevice *dev)
{
S390PCIBusDevice *pbdev;
uint32_t fid = data >> ZPCI_MSI_VEC_BITS;
diff --git a/ui/console.c b/ui/console.c
index 31f0d35987..cf649b2612 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1962,7 +1962,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
chr->init(chr);
}
-static CharDriverState *text_console_init(ChardevVC *vc)
+static CharDriverState *text_console_init(ChardevVC *vc, Error **errp)
{
CharDriverState *chr;
QemuConsole *s;
@@ -1993,6 +1993,7 @@ static CharDriverState *text_console_init(ChardevVC *vc)
if (!s) {
g_free(chr);
+ error_setg(errp, "cannot create text console");
return NULL;
}
@@ -2012,9 +2013,10 @@ static CharDriverState *text_console_init(ChardevVC *vc)
static VcHandler *vc_handler = text_console_init;
-CharDriverState *vc_init(ChardevVC *vc)
+static CharDriverState *vc_init(const char *id, ChardevBackend *backend,
+ ChardevReturn *ret, Error **errp)
{
- return vc_handler(vc);
+ return vc_handler(backend->vc, errp);
}
void register_vc_handler(VcHandler *handler)
@@ -2093,7 +2095,8 @@ static const TypeInfo qemu_console_info = {
static void register_types(void)
{
type_register_static(&qemu_console_info);
- register_char_driver("vc", CHARDEV_BACKEND_KIND_VC, qemu_chr_parse_vc);
+ register_char_driver("vc", CHARDEV_BACKEND_KIND_VC, qemu_chr_parse_vc,
+ vc_init);
}
type_init(register_types);
diff --git a/ui/gtk.c b/ui/gtk.c
index 294783885f..47b37e1f14 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1591,7 +1591,7 @@ static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
static int nb_vcs;
static CharDriverState *vcs[MAX_VCS];
-static CharDriverState *gd_vc_handler(ChardevVC *unused)
+static CharDriverState *gd_vc_handler(ChardevVC *unused, Error **errp)
{
CharDriverState *chr;
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 2add83a0fc..0a041a922e 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -586,12 +586,15 @@ fail:
static void inet_addr_to_opts(QemuOpts *opts, const InetSocketAddress *addr)
{
- bool ipv4 = addr->ipv4 || !addr->has_ipv4;
- bool ipv6 = addr->ipv6 || !addr->has_ipv6;
+ bool ipv4 = addr->has_ipv4 && addr->ipv4;
+ bool ipv6 = addr->has_ipv6 && addr->ipv6;
- if (!ipv4 || !ipv6) {
+ if (ipv4 || ipv6) {
qemu_opt_set_bool(opts, "ipv4", ipv4, &error_abort);
qemu_opt_set_bool(opts, "ipv6", ipv6, &error_abort);
+ } else if (addr->has_ipv4 || addr->has_ipv6) {
+ qemu_opt_set_bool(opts, "ipv4", !addr->has_ipv4, &error_abort);
+ qemu_opt_set_bool(opts, "ipv6", !addr->has_ipv6, &error_abort);
}
if (addr->has_to) {
qemu_opt_set_number(opts, "to", addr->to, &error_abort);