* 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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAABCAAGBQJWJKYWAAoJEL/70l94x66D2yYH/Rw06gj9FFVEhfNODmJozCsK zRqRREo+VMo/lIGUSwzI+OCX+yUoivxnsJXchqunK0udPuQ5vZ+mVGyKedg8/SU+ uqXzXMK7QgJK/w7qNA1n0OacNYSosZz9MpOwPgzSLPRda8FbtVKqPBOugSEs+Ymg APtiumz3DGWXUmt+vqRdgdiAvoGkefPODjjPjfSQFukg205KR88tf/b9oN8Z+kDW LtGqG9dUNS/60ulLNQdFInn3x5WpuGky5kk57f47QHpInNcN4/CH0BiguvYNkA9A aFFEWj5RsK7xkhcwSw6JIaSoWoTdrQVd4mB6+WTZN4tfGIIaoDeI6fp2MFmVpZU= =9Tf9 -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
526d5809a0
51
MAINTAINERS
51
MAINTAINERS
@ -255,6 +255,12 @@ L: xen-devel@lists.xensource.com
|
|||||||
S: Supported
|
S: Supported
|
||||||
F: xen-*
|
F: xen-*
|
||||||
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:
|
Hosts:
|
||||||
------
|
------
|
||||||
@ -286,6 +292,36 @@ F: hw/*/allwinner*
|
|||||||
F: include/hw/*/allwinner*
|
F: include/hw/*/allwinner*
|
||||||
F: hw/arm/cubieboard.c
|
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
|
Exynos
|
||||||
M: Evgeny Voevodin <e.voevodin@samsung.com>
|
M: Evgeny Voevodin <e.voevodin@samsung.com>
|
||||||
M: Maksim Kozlov <m.kozlov@samsung.com>
|
M: Maksim Kozlov <m.kozlov@samsung.com>
|
||||||
@ -322,11 +358,6 @@ M: Peter Maydell <peter.maydell@linaro.org>
|
|||||||
S: Maintained
|
S: Maintained
|
||||||
F: hw/arm/integratorcp.c
|
F: hw/arm/integratorcp.c
|
||||||
|
|
||||||
Mainstone
|
|
||||||
L: qemu-devel@nongnu.org
|
|
||||||
S: Orphan
|
|
||||||
F: hw/arm/mainstone.c
|
|
||||||
|
|
||||||
Musicpal
|
Musicpal
|
||||||
M: Jan Kiszka <jan.kiszka@web.de>
|
M: Jan Kiszka <jan.kiszka@web.de>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
@ -346,11 +377,17 @@ Real View
|
|||||||
M: Peter Maydell <peter.maydell@linaro.org>
|
M: Peter Maydell <peter.maydell@linaro.org>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: hw/arm/realview*
|
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>
|
M: Andrzej Zaborowski <balrogg@gmail.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
F: hw/arm/mainstone.c
|
||||||
F: hw/arm/spitz.c
|
F: hw/arm/spitz.c
|
||||||
|
F: hw/arm/tosa.c
|
||||||
|
F: hw/arm/z2.c
|
||||||
|
F: hw/*/pxa2xx*
|
||||||
|
|
||||||
Stellaris
|
Stellaris
|
||||||
M: Peter Maydell <peter.maydell@linaro.org>
|
M: Peter Maydell <peter.maydell@linaro.org>
|
||||||
@ -726,6 +763,8 @@ M: Scott Wood <scottwood@freescale.com>
|
|||||||
L: qemu-ppc@nongnu.org
|
L: qemu-ppc@nongnu.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: hw/ppc/e500*
|
F: hw/ppc/e500*
|
||||||
|
F: hw/pci-host/ppce500.c
|
||||||
|
F: hw/net/fsl_etsec/
|
||||||
|
|
||||||
Character devices
|
Character devices
|
||||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
108
README
108
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
|
||||||
|
@ -561,7 +561,10 @@ static void baum_close(struct CharDriverState *chr)
|
|||||||
g_free(baum);
|
g_free(baum);
|
||||||
}
|
}
|
||||||
|
|
||||||
CharDriverState *chr_baum_init(void)
|
static CharDriverState *chr_baum_init(const char *id,
|
||||||
|
ChardevBackend *backend,
|
||||||
|
ChardevReturn *ret,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
BaumDriverState *baum;
|
BaumDriverState *baum;
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
@ -586,14 +589,16 @@ CharDriverState *chr_baum_init(void)
|
|||||||
|
|
||||||
baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
|
baum->brlapi_fd = brlapi__openConnection(handle, NULL, NULL);
|
||||||
if (baum->brlapi_fd == -1) {
|
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;
|
goto fail_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
baum->cellCount_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, baum_cellCount_timer_cb, baum);
|
baum->cellCount_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, baum_cellCount_timer_cb, baum);
|
||||||
|
|
||||||
if (brlapi__getDisplaySize(handle, &baum->x, &baum->y) == -1) {
|
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;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +614,8 @@ CharDriverState *chr_baum_init(void)
|
|||||||
tty = BRLAPI_TTY_DEFAULT;
|
tty = BRLAPI_TTY_DEFAULT;
|
||||||
|
|
||||||
if (brlapi__enterTtyMode(handle, tty, NULL) == -1) {
|
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;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -629,7 +635,8 @@ fail_handle:
|
|||||||
|
|
||||||
static void register_types(void)
|
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);
|
type_init(register_types);
|
||||||
|
@ -63,7 +63,10 @@ static void msmouse_chr_close (struct CharDriverState *chr)
|
|||||||
g_free (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;
|
CharDriverState *chr;
|
||||||
|
|
||||||
@ -79,7 +82,8 @@ CharDriverState *qemu_chr_open_msmouse(void)
|
|||||||
|
|
||||||
static void register_types(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);
|
type_init(register_types);
|
||||||
|
@ -108,7 +108,10 @@ static void testdev_close(struct CharDriverState *chr)
|
|||||||
g_free(testdev);
|
g_free(testdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
CharDriverState *chr_testdev_init(void)
|
static CharDriverState *chr_testdev_init(const char *id,
|
||||||
|
ChardevBackend *backend,
|
||||||
|
ChardevReturn *ret,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
TestdevCharState *testdev;
|
TestdevCharState *testdev;
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
@ -125,7 +128,8 @@ CharDriverState *chr_testdev_init(void)
|
|||||||
|
|
||||||
static void register_types(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);
|
type_init(register_types);
|
||||||
|
12
configure
vendored
12
configure
vendored
@ -1166,18 +1166,14 @@ fi
|
|||||||
|
|
||||||
# Note that if the Python conditional here evaluates True we will exit
|
# Note that if the Python conditional here evaluates True we will exit
|
||||||
# with status 1 which is a shell 'false' value.
|
# 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
|
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.4 or later is required." \
|
error_exit "Cannot use '$python', Python 2.6 or later is required." \
|
||||||
"Note that Python 3 or later is not yet supported." \
|
"Note that Python 3 or later is not yet supported." \
|
||||||
"Use --python=/path/to/python to specify a supported Python."
|
"Use --python=/path/to/python to specify a supported Python."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# The -B switch was added in Python 2.6.
|
# Suppress writing compiled files
|
||||||
# If it is supplied, compiled files are not written.
|
python="$python -B"
|
||||||
# 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
|
|
||||||
|
|
||||||
case "$cpu" in
|
case "$cpu" in
|
||||||
ppc)
|
ppc)
|
||||||
|
@ -37,31 +37,32 @@ void cpu_resume_from_signal(CPUState *cpu, void *puc)
|
|||||||
siglongjmp(cpu->jmp_env, 1);
|
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()) {
|
if (qemu_in_vcpu_thread()) {
|
||||||
/* Do not let the guest prolong the critical section as much as it
|
/* The guest can in theory prolong the RCU critical section as long
|
||||||
* as it desires.
|
* 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.
|
||||||
*
|
*
|
||||||
* Currently, this is prevented by the I/O thread's periodinc kicking
|
* Because the only thing we're currently protecting with RCU is the
|
||||||
* of the VCPU thread (iothread_requesting_mutex, qemu_cpu_kick_thread)
|
* memory data structures, it's sufficient to break the critical section
|
||||||
* but this will go away once TCG's execution moves out of the global
|
* in this callback, which we know will get called every time the
|
||||||
* mutex.
|
* memory map is rearranged.
|
||||||
|
*
|
||||||
|
* (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
|
* 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
|
* only protects cpu->as->dispatch. Since we know our caller is about
|
||||||
* split the critical section.
|
* to reload it, it's safe to split the critical section.
|
||||||
*/
|
*/
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
rcu_read_lock();
|
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
|
#endif
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ The core RCU API is small:
|
|||||||
the callback function is g_free, in particular, g_free_rcu can be
|
the callback function is g_free, in particular, g_free_rcu can be
|
||||||
used. In the above case, one could have written simply:
|
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);
|
typeof(*p) atomic_rcu_read(p);
|
||||||
|
|
||||||
|
57
exec.c
57
exec.c
@ -161,6 +161,21 @@ static void memory_map_init(void);
|
|||||||
static void tcg_commit(MemoryListener *listener);
|
static void tcg_commit(MemoryListener *listener);
|
||||||
|
|
||||||
static MemoryRegion io_mem_watch;
|
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
|
#endif
|
||||||
|
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
@ -431,7 +446,7 @@ address_space_translate_for_iotlb(CPUState *cpu, hwaddr addr,
|
|||||||
hwaddr *xlat, hwaddr *plen)
|
hwaddr *xlat, hwaddr *plen)
|
||||||
{
|
{
|
||||||
MemoryRegionSection *section;
|
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);
|
addr, xlat, plen, false);
|
||||||
|
|
||||||
assert(!section->mr->iommu_ops);
|
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. */
|
/* We only support one address space per cpu at the moment. */
|
||||||
assert(cpu->as == as);
|
assert(cpu->as == as);
|
||||||
|
|
||||||
if (cpu->tcg_as_listener) {
|
if (cpu->cpu_ases) {
|
||||||
memory_listener_unregister(cpu->tcg_as_listener);
|
/* We've already registered the listener for our only AS */
|
||||||
} else {
|
return;
|
||||||
cpu->tcg_as_listener = g_new0(MemoryListener, 1);
|
|
||||||
}
|
}
|
||||||
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
|
#endif
|
||||||
|
|
||||||
@ -601,7 +619,6 @@ void cpu_exec_init(CPUState *cpu, Error **errp)
|
|||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
cpu->as = &address_space_memory;
|
cpu->as = &address_space_memory;
|
||||||
cpu->thread_id = qemu_get_thread_id();
|
cpu->thread_id = qemu_get_thread_id();
|
||||||
cpu_reload_memory_map(cpu);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
#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)
|
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;
|
MemoryRegionSection *sections = d->map.sections;
|
||||||
|
|
||||||
return sections[index & ~TARGET_PAGE_MASK].mr;
|
return sections[index & ~TARGET_PAGE_MASK].mr;
|
||||||
@ -2278,19 +2296,20 @@ static void mem_commit(MemoryListener *listener)
|
|||||||
|
|
||||||
static void tcg_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
|
/* since each CPU stores ram addresses in its TLB cache, we must
|
||||||
reset the modified entries */
|
reset the modified entries */
|
||||||
/* XXX: slow ! */
|
cpuas = container_of(listener, CPUAddressSpace, tcg_as_listener);
|
||||||
CPU_FOREACH(cpu) {
|
cpu_reloading_memory_map();
|
||||||
/* FIXME: Disentangle the cpu.h circular files deps so we can
|
/* The CPU and TLB are protected by the iothread lock.
|
||||||
directly get the right CPU from listener. */
|
* We reload the dispatch pointer now because cpu_reloading_memory_map()
|
||||||
if (cpu->tcg_as_listener != listener) {
|
* may have split the RCU critical section.
|
||||||
continue;
|
*/
|
||||||
}
|
d = atomic_rcu_read(&cpuas->as->dispatch);
|
||||||
cpu_reload_memory_map(cpu);
|
cpuas->memory_dispatch = d;
|
||||||
}
|
tlb_flush(cpuas->cpu, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void address_space_init_dispatch(AddressSpace *as)
|
void address_space_init_dispatch(AddressSpace *as)
|
||||||
|
@ -979,7 +979,7 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev)
|
|||||||
MSIMessage msg = msi_get_message(pci_dev, 0);
|
MSIMessage msg = msi_get_message(pci_dev, 0);
|
||||||
int virq;
|
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) {
|
if (virq < 0) {
|
||||||
perror("assigned_dev_update_msi: kvm_irqchip_add_msi_route");
|
perror("assigned_dev_update_msi: kvm_irqchip_add_msi_route");
|
||||||
return;
|
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],
|
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)
|
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.address = entry->addr_lo | ((uint64_t)entry->addr_hi << 32);
|
||||||
msg.data = entry->data;
|
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) {
|
if (r < 0) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -1483,7 +1483,7 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev, Error **errp)
|
|||||||
* error bits, leave the rest. */
|
* error bits, leave the rest. */
|
||||||
status = pci_get_long(pci_dev->config + pos + PCI_X_STATUS);
|
status = pci_get_long(pci_dev->config + pos + PCI_X_STATUS);
|
||||||
status &= ~(PCI_X_STATUS_BUS | PCI_X_STATUS_DEVFN);
|
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 |
|
status &= ~(PCI_X_STATUS_SPL_DISC | PCI_X_STATUS_UNX_SPL |
|
||||||
PCI_X_STATUS_SPL_ERR);
|
PCI_X_STATUS_SPL_ERR);
|
||||||
pci_set_long(pci_dev->config + pos + PCI_X_STATUS, status);
|
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;
|
msg.data = entry->data;
|
||||||
|
|
||||||
ret = kvm_irqchip_update_msi_route(kvm_state,
|
ret = kvm_irqchip_update_msi_route(kvm_state,
|
||||||
adev->msi_virq[i], msg);
|
adev->msi_virq[i], msg,
|
||||||
|
pdev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
error_report("Error updating irq routing entry (%d)", ret);
|
error_report("Error updating irq routing entry (%d)", ret);
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,7 @@ void msi_send_message(PCIDevice *dev, MSIMessage msg)
|
|||||||
{
|
{
|
||||||
MemTxAttrs attrs = {};
|
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,
|
address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
|
||||||
attrs, NULL);
|
attrs, NULL);
|
||||||
}
|
}
|
||||||
|
@ -979,7 +979,7 @@ static int do_pcie_aer_inject_error(Monitor *mon,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
err.status = error_status;
|
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;
|
err.flags = 0;
|
||||||
if (correctable) {
|
if (correctable) {
|
||||||
|
@ -431,7 +431,7 @@ static uint64_t megasas_fw_time(void)
|
|||||||
static uint64_t megasas_get_sata_addr(uint16_t id)
|
static uint64_t megasas_get_sata_addr(uint16_t id)
|
||||||
{
|
{
|
||||||
uint64_t addr = (0x1221ULL << 48);
|
uint64_t addr = (0x1221ULL << 48);
|
||||||
return addr & (id << 24);
|
return addr | ((uint64_t)id << 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -558,7 +558,7 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
|
|||||||
const int memset_off = offsetof(SCSIRequest, sense)
|
const int memset_off = offsetof(SCSIRequest, sense)
|
||||||
+ sizeof(req->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);
|
memset((uint8_t *)req + memset_off, 0, reqops->size - memset_off);
|
||||||
req->refcount = 1;
|
req->refcount = 1;
|
||||||
req->bus = bus;
|
req->bus = bus;
|
||||||
@ -1622,7 +1622,7 @@ void scsi_req_unref(SCSIRequest *req)
|
|||||||
}
|
}
|
||||||
object_unref(OBJECT(req->dev));
|
object_unref(OBJECT(req->dev));
|
||||||
object_unref(OBJECT(qbus->parent));
|
object_unref(OBJECT(qbus->parent));
|
||||||
g_slice_free1(req->ops->size, req);
|
g_free(req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = g_slice_new(VirtIOSCSIVring);
|
r = g_new(VirtIOSCSIVring, 1);
|
||||||
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);
|
||||||
aio_set_event_notifier(s->ctx, &r->host_notifier, handler);
|
aio_set_event_notifier(s->ctx, &r->host_notifier, handler);
|
||||||
@ -73,7 +73,7 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s,
|
|||||||
fail_vring:
|
fail_vring:
|
||||||
aio_set_event_notifier(s->ctx, &r->host_notifier, NULL);
|
aio_set_event_notifier(s->ctx, &r->host_notifier, NULL);
|
||||||
k->set_host_notifier(qbus->parent, n, false);
|
k->set_host_notifier(qbus->parent, n, false);
|
||||||
g_slice_free(VirtIOSCSIVring, r);
|
g_free(r);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,18 +182,18 @@ static void virtio_scsi_vring_teardown(VirtIOSCSI *s)
|
|||||||
|
|
||||||
if (s->ctrl_vring) {
|
if (s->ctrl_vring) {
|
||||||
vring_teardown(&s->ctrl_vring->vring, vdev, 0);
|
vring_teardown(&s->ctrl_vring->vring, vdev, 0);
|
||||||
g_slice_free(VirtIOSCSIVring, s->ctrl_vring);
|
g_free(s->ctrl_vring);
|
||||||
s->ctrl_vring = NULL;
|
s->ctrl_vring = NULL;
|
||||||
}
|
}
|
||||||
if (s->event_vring) {
|
if (s->event_vring) {
|
||||||
vring_teardown(&s->event_vring->vring, vdev, 1);
|
vring_teardown(&s->event_vring->vring, vdev, 1);
|
||||||
g_slice_free(VirtIOSCSIVring, s->event_vring);
|
g_free(s->event_vring);
|
||||||
s->event_vring = NULL;
|
s->event_vring = NULL;
|
||||||
}
|
}
|
||||||
if (s->cmd_vrings) {
|
if (s->cmd_vrings) {
|
||||||
for (i = 0; i < vs->conf.num_queues && s->cmd_vrings[i]; i++) {
|
for (i = 0; i < vs->conf.num_queues && s->cmd_vrings[i]; i++) {
|
||||||
vring_teardown(&s->cmd_vrings[i]->vring, vdev, 2 + 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;
|
s->cmd_vrings[i] = NULL;
|
||||||
}
|
}
|
||||||
free(s->cmd_vrings);
|
free(s->cmd_vrings);
|
||||||
|
@ -47,7 +47,7 @@ VirtIOSCSIReq *virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq)
|
|||||||
const size_t zero_skip = offsetof(VirtIOSCSIReq, elem)
|
const size_t zero_skip = offsetof(VirtIOSCSIReq, elem)
|
||||||
+ sizeof(VirtQueueElement);
|
+ sizeof(VirtQueueElement);
|
||||||
|
|
||||||
req = g_slice_alloc(sizeof(*req) + vs->cdb_size);
|
req = g_malloc(sizeof(*req) + vs->cdb_size);
|
||||||
req->vq = vq;
|
req->vq = vq;
|
||||||
req->dev = s;
|
req->dev = s;
|
||||||
qemu_sglist_init(&req->qsgl, DEVICE(s), 8, &address_space_memory);
|
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)
|
void virtio_scsi_free_req(VirtIOSCSIReq *req)
|
||||||
{
|
{
|
||||||
VirtIOSCSICommon *vs = (VirtIOSCSICommon *)req->dev;
|
|
||||||
|
|
||||||
qemu_iovec_destroy(&req->resp_iov);
|
qemu_iovec_destroy(&req->resp_iov);
|
||||||
qemu_sglist_destroy(&req->qsgl);
|
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)
|
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) {
|
if (--n->tmf_req->remaining == 0) {
|
||||||
virtio_scsi_complete_req(n->tmf_req);
|
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;
|
/* 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;
|
VirtIOSCSICancelNotifier *notifier;
|
||||||
|
|
||||||
req->remaining = 1;
|
req->remaining = 1;
|
||||||
notifier = g_slice_new(VirtIOSCSICancelNotifier);
|
notifier = g_new(VirtIOSCSICancelNotifier, 1);
|
||||||
notifier->tmf_req = req;
|
notifier->tmf_req = req;
|
||||||
notifier->notifier.notify = virtio_scsi_cancel_notify;
|
notifier->notifier.notify = virtio_scsi_cancel_notify;
|
||||||
scsi_req_cancel_async(r, ¬ifier->notifier);
|
scsi_req_cancel_async(r, ¬ifier->notifier);
|
||||||
@ -350,7 +348,7 @@ static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
|
|||||||
VirtIOSCSICancelNotifier *notifier;
|
VirtIOSCSICancelNotifier *notifier;
|
||||||
|
|
||||||
req->remaining++;
|
req->remaining++;
|
||||||
notifier = g_slice_new(VirtIOSCSICancelNotifier);
|
notifier = g_new(VirtIOSCSICancelNotifier, 1);
|
||||||
notifier->notifier.notify = virtio_scsi_cancel_notify;
|
notifier->notifier.notify = virtio_scsi_cancel_notify;
|
||||||
notifier->tmf_req = req;
|
notifier->tmf_req = req;
|
||||||
scsi_req_cancel_async(r, ¬ifier->notifier);
|
scsi_req_cancel_async(r, ¬ifier->notifier);
|
||||||
|
@ -424,7 +424,7 @@ static void vfio_add_kvm_msi_virq(VFIOPCIDevice *vdev, VFIOMSIVector *vector,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
virq = kvm_irqchip_add_msi_route(kvm_state, *msg);
|
virq = kvm_irqchip_add_msi_route(kvm_state, *msg, &vdev->pdev);
|
||||||
if (virq < 0) {
|
if (virq < 0) {
|
||||||
event_notifier_cleanup(&vector->kvm_interrupt);
|
event_notifier_cleanup(&vector->kvm_interrupt);
|
||||||
return;
|
return;
|
||||||
@ -449,9 +449,10 @@ static void vfio_remove_kvm_msi_virq(VFIOMSIVector *vector)
|
|||||||
event_notifier_cleanup(&vector->kvm_interrupt);
|
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,
|
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) {
|
if (!msg) {
|
||||||
vfio_remove_kvm_msi_virq(vector);
|
vfio_remove_kvm_msi_virq(vector);
|
||||||
} else {
|
} else {
|
||||||
vfio_update_kvm_msi_virq(vector, *msg);
|
vfio_update_kvm_msi_virq(vector, *msg, pdev);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vfio_add_kvm_msi_virq(vdev, vector, msg, true);
|
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);
|
msg = msi_get_message(&vdev->pdev, i);
|
||||||
vfio_update_kvm_msi_virq(vector, msg);
|
vfio_update_kvm_msi_virq(vector, msg, &vdev->pdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,7 +590,7 @@ static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (irqfd->users == 0) {
|
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) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -726,7 +726,8 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy,
|
|||||||
if (proxy->vector_irqfd) {
|
if (proxy->vector_irqfd) {
|
||||||
irqfd = &proxy->vector_irqfd[vector];
|
irqfd = &proxy->vector_irqfd[vector];
|
||||||
if (irqfd->msg.data != msg.data || irqfd->msg.address != msg.address) {
|
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) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -84,8 +84,7 @@ void QEMU_NORETURN cpu_loop_exit(CPUState *cpu);
|
|||||||
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
|
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
|
||||||
|
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
bool qemu_in_vcpu_thread(void);
|
void cpu_reloading_memory_map(void);
|
||||||
void cpu_reload_memory_map(CPUState *cpu);
|
|
||||||
void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as);
|
void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as);
|
||||||
/* cputlb.c */
|
/* cputlb.c */
|
||||||
/**
|
/**
|
||||||
@ -357,8 +356,6 @@ extern uintptr_t tci_tb_ptr;
|
|||||||
|
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
|
|
||||||
void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align));
|
|
||||||
|
|
||||||
struct MemoryRegion *iotlb_to_region(CPUState *cpu,
|
struct MemoryRegion *iotlb_to_region(CPUState *cpu,
|
||||||
hwaddr index);
|
hwaddr index);
|
||||||
|
|
||||||
@ -408,7 +405,4 @@ extern int singlestep;
|
|||||||
extern CPUState *tcg_current_cpu;
|
extern CPUState *tcg_current_cpu;
|
||||||
extern bool exit_request;
|
extern bool exit_request;
|
||||||
|
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
|
||||||
void migration_bitmap_extend(ram_addr_t old, ram_addr_t new);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,8 +35,8 @@ typedef struct MemTxAttrs {
|
|||||||
unsigned int secure:1;
|
unsigned int secure:1;
|
||||||
/* Memory access is usermode (unprivileged) */
|
/* Memory access is usermode (unprivileged) */
|
||||||
unsigned int user:1;
|
unsigned int user:1;
|
||||||
/* Stream ID (for MSI for example) */
|
/* Requester ID (for MSI for example) */
|
||||||
unsigned int stream_id:16;
|
unsigned int requester_id:16;
|
||||||
} MemTxAttrs;
|
} MemTxAttrs;
|
||||||
|
|
||||||
/* Bus masters which don't specify any attributes will get this,
|
/* Bus masters which don't specify any attributes will get this,
|
||||||
|
@ -289,5 +289,6 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest,
|
|||||||
return num_dirty;
|
return num_dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void migration_bitmap_extend(ram_addr_t old, ram_addr_t new);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -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;
|
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 */
|
/* DMA access functions */
|
||||||
static inline AddressSpace *pci_get_address_space(PCIDevice *dev)
|
static inline AddressSpace *pci_get_address_space(PCIDevice *dev)
|
||||||
{
|
{
|
||||||
|
@ -16,6 +16,7 @@ typedef struct BusClass BusClass;
|
|||||||
typedef struct BusState BusState;
|
typedef struct BusState BusState;
|
||||||
typedef struct CharDriverState CharDriverState;
|
typedef struct CharDriverState CharDriverState;
|
||||||
typedef struct CompatProperty CompatProperty;
|
typedef struct CompatProperty CompatProperty;
|
||||||
|
typedef struct CPUAddressSpace CPUAddressSpace;
|
||||||
typedef struct DeviceState DeviceState;
|
typedef struct DeviceState DeviceState;
|
||||||
typedef struct DeviceListener DeviceListener;
|
typedef struct DeviceListener DeviceListener;
|
||||||
typedef struct DisplayChangeListener DisplayChangeListener;
|
typedef struct DisplayChangeListener DisplayChangeListener;
|
||||||
|
@ -234,6 +234,10 @@ struct kvm_run;
|
|||||||
* @can_do_io: Nonzero if memory-mapped IO is safe. Deterministic execution
|
* @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
|
* requires that IO only be performed on the last instruction of a TB
|
||||||
* so that interrupts take effect immediately.
|
* 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.
|
* @env_ptr: Pointer to subclass-specific CPUArchState field.
|
||||||
* @current_tb: Currently executing TB.
|
* @current_tb: Currently executing TB.
|
||||||
* @gdb_regs: Additional GDB registers.
|
* @gdb_regs: Additional GDB registers.
|
||||||
@ -280,9 +284,8 @@ struct CPUState {
|
|||||||
QemuMutex work_mutex;
|
QemuMutex work_mutex;
|
||||||
struct qemu_work_item *queued_work_first, *queued_work_last;
|
struct qemu_work_item *queued_work_first, *queued_work_last;
|
||||||
|
|
||||||
|
CPUAddressSpace *cpu_ases;
|
||||||
AddressSpace *as;
|
AddressSpace *as;
|
||||||
struct AddressSpaceDispatch *memory_dispatch;
|
|
||||||
MemoryListener *tcg_as_listener;
|
|
||||||
|
|
||||||
void *env_ptr; /* CPUArchState */
|
void *env_ptr; /* CPUArchState */
|
||||||
struct TranslationBlock *current_tb;
|
struct TranslationBlock *current_tb;
|
||||||
|
@ -153,6 +153,12 @@
|
|||||||
/* MSR used to provide vcpu index */
|
/* MSR used to provide vcpu index */
|
||||||
#define HV_X64_MSR_VP_INDEX 0x40000002
|
#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 */
|
/* MSR used to read the per-partition time reference counter */
|
||||||
#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
|
#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
|
||||||
|
|
||||||
|
@ -345,7 +345,9 @@ bool chr_is_ringbuf(const CharDriverState *chr);
|
|||||||
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
|
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
|
||||||
|
|
||||||
void register_char_driver(const char *name, ChardevBackendKind kind,
|
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 */
|
/* add an eventfd to the qemu devices that are polled */
|
||||||
CharDriverState *qemu_chr_open_eventfd(int eventfd);
|
CharDriverState *qemu_chr_open_eventfd(int eventfd);
|
||||||
@ -354,18 +356,8 @@ extern int term_escape_char;
|
|||||||
|
|
||||||
CharDriverState *qemu_char_get_next_serial(void);
|
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 */
|
/* console.c */
|
||||||
typedef CharDriverState *(VcHandler)(ChardevVC *vc);
|
typedef CharDriverState *(VcHandler)(ChardevVC *vc, Error **errp);
|
||||||
|
|
||||||
void register_vc_handler(VcHandler *handler);
|
void register_vc_handler(VcHandler *handler);
|
||||||
CharDriverState *vc_init(ChardevVC *vc);
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define QEMU_CPUS_H
|
#define QEMU_CPUS_H
|
||||||
|
|
||||||
/* cpus.c */
|
/* cpus.c */
|
||||||
|
bool qemu_in_vcpu_thread(void);
|
||||||
void qemu_init_cpu_loop(void);
|
void qemu_init_cpu_loop(void);
|
||||||
void resume_all_vcpus(void);
|
void resume_all_vcpus(void);
|
||||||
void pause_all_vcpus(void);
|
void pause_all_vcpus(void);
|
||||||
|
@ -52,6 +52,7 @@ extern bool kvm_msi_via_irqfd_allowed;
|
|||||||
extern bool kvm_gsi_routing_allowed;
|
extern bool kvm_gsi_routing_allowed;
|
||||||
extern bool kvm_gsi_direct_mapping;
|
extern bool kvm_gsi_direct_mapping;
|
||||||
extern bool kvm_readonly_mem_allowed;
|
extern bool kvm_readonly_mem_allowed;
|
||||||
|
extern bool kvm_direct_msi_allowed;
|
||||||
|
|
||||||
#if defined CONFIG_KVM || !defined NEED_CPU_H
|
#if defined CONFIG_KVM || !defined NEED_CPU_H
|
||||||
#define kvm_enabled() (kvm_allowed)
|
#define kvm_enabled() (kvm_allowed)
|
||||||
@ -145,6 +146,13 @@ extern bool kvm_readonly_mem_allowed;
|
|||||||
*/
|
*/
|
||||||
#define kvm_readonly_mem_enabled() (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
|
#else
|
||||||
#define kvm_enabled() (0)
|
#define kvm_enabled() (0)
|
||||||
#define kvm_irqchip_in_kernel() (false)
|
#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_routing_allowed() (false)
|
||||||
#define kvm_gsi_direct_mapping() (false)
|
#define kvm_gsi_direct_mapping() (false)
|
||||||
#define kvm_readonly_mem_enabled() (false)
|
#define kvm_readonly_mem_enabled() (false)
|
||||||
|
#define kvm_direct_msi_enabled() (false)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct kvm_run;
|
struct kvm_run;
|
||||||
@ -182,8 +191,6 @@ int kvm_has_sync_mmu(void);
|
|||||||
int kvm_has_vcpu_events(void);
|
int kvm_has_vcpu_events(void);
|
||||||
int kvm_has_robust_singlestep(void);
|
int kvm_has_robust_singlestep(void);
|
||||||
int kvm_has_debugregs(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_pit_state2(void);
|
||||||
int kvm_has_many_ioeventfds(void);
|
int kvm_has_many_ioeventfds(void);
|
||||||
int kvm_has_gsi_routing(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_vcpu(CPUState *cpu, int code, void *addr);
|
||||||
int kvm_on_sigbus(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 */
|
/* internal API */
|
||||||
|
|
||||||
int kvm_ioctl(KVMState *s, int type, ...);
|
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);
|
void kvm_arch_init_irq_routing(KVMState *s);
|
||||||
|
|
||||||
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
|
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);
|
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_add_msi_route(KVMState *s, MSIMessage msg, PCIDevice *dev);
|
||||||
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);
|
||||||
void kvm_irqchip_release_virq(KVMState *s, int virq);
|
void kvm_irqchip_release_virq(KVMState *s, int virq);
|
||||||
|
|
||||||
int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter);
|
int kvm_irqchip_add_adapter_route(KVMState *s, AdapterInfo *adapter);
|
||||||
|
@ -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,
|
int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
|
||||||
const char *subject);
|
const char *subject);
|
||||||
|
|
||||||
CharDriverState *qemu_chr_open_spice_vmc(const char *type);
|
|
||||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||||
CharDriverState *qemu_chr_open_spice_port(const char *name);
|
|
||||||
void qemu_spice_register_ports(void);
|
void qemu_spice_register_ports(void);
|
||||||
#else
|
#else
|
||||||
static inline CharDriverState *qemu_chr_open_spice_port(const char *name)
|
static inline CharDriverState *qemu_chr_open_spice_port(const char *name)
|
||||||
|
56
kvm-all.c
56
kvm-all.c
@ -77,8 +77,6 @@ struct KVMState
|
|||||||
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||||
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
|
struct kvm_sw_breakpoint_head kvm_sw_breakpoints;
|
||||||
#endif
|
#endif
|
||||||
int pit_state2;
|
|
||||||
int xsave, xcrs;
|
|
||||||
int many_ioeventfds;
|
int many_ioeventfds;
|
||||||
int intx_set_mask;
|
int intx_set_mask;
|
||||||
/* The man page (and posix) say ioctl numbers are signed int, but
|
/* The man page (and posix) say ioctl numbers are signed int, but
|
||||||
@ -93,7 +91,6 @@ struct KVMState
|
|||||||
uint32_t *used_gsi_bitmap;
|
uint32_t *used_gsi_bitmap;
|
||||||
unsigned int gsi_count;
|
unsigned int gsi_count;
|
||||||
QTAILQ_HEAD(msi_hashtab, KVMMSIRoute) msi_hashtab[KVM_MSI_HASHTAB_SIZE];
|
QTAILQ_HEAD(msi_hashtab, KVMMSIRoute) msi_hashtab[KVM_MSI_HASHTAB_SIZE];
|
||||||
bool direct_msi;
|
|
||||||
#endif
|
#endif
|
||||||
KVMMemoryListener memory_listener;
|
KVMMemoryListener memory_listener;
|
||||||
};
|
};
|
||||||
@ -111,6 +108,7 @@ bool kvm_gsi_direct_mapping;
|
|||||||
bool kvm_allowed;
|
bool kvm_allowed;
|
||||||
bool kvm_readonly_mem_allowed;
|
bool kvm_readonly_mem_allowed;
|
||||||
bool kvm_vm_attributes_allowed;
|
bool kvm_vm_attributes_allowed;
|
||||||
|
bool kvm_direct_msi_allowed;
|
||||||
|
|
||||||
static const KVMCapabilityInfo kvm_required_capabilites[] = {
|
static const KVMCapabilityInfo kvm_required_capabilites[] = {
|
||||||
KVM_CAP_INFO(USER_MEMORY),
|
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
|
/* kvm works in page size chunks, but the function may be called
|
||||||
with sub-page size and unaligned start address. Pad the start
|
with sub-page size and unaligned start address. Pad the start
|
||||||
address to next and truncate size to previous page boundary. */
|
address to next and truncate size to previous page boundary. */
|
||||||
delta = (TARGET_PAGE_SIZE - (start_addr & ~TARGET_PAGE_MASK));
|
delta = qemu_real_host_page_size - (start_addr & ~qemu_real_host_page_mask);
|
||||||
delta &= ~TARGET_PAGE_MASK;
|
delta &= ~qemu_real_host_page_mask;
|
||||||
if (delta > size) {
|
if (delta > size) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
start_addr += delta;
|
start_addr += delta;
|
||||||
size -= delta;
|
size -= delta;
|
||||||
size &= TARGET_PAGE_MASK;
|
size &= qemu_real_host_page_mask;
|
||||||
if (!size || (start_addr & ~TARGET_PAGE_MASK)) {
|
if (!size || (start_addr & ~qemu_real_host_page_mask)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -979,7 +977,7 @@ void kvm_init_irq_routing(KVMState *s)
|
|||||||
s->irq_routes = g_malloc0(sizeof(*s->irq_routes));
|
s->irq_routes = g_malloc0(sizeof(*s->irq_routes));
|
||||||
s->nr_allocated_irq_routes = 0;
|
s->nr_allocated_irq_routes = 0;
|
||||||
|
|
||||||
if (!s->direct_msi) {
|
if (!kvm_direct_msi_allowed) {
|
||||||
for (i = 0; i < KVM_MSI_HASHTAB_SIZE; i++) {
|
for (i = 0; i < KVM_MSI_HASHTAB_SIZE; i++) {
|
||||||
QTAILQ_INIT(&s->msi_hashtab[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.
|
* number can succeed even though a new route entry cannot be added.
|
||||||
* When this happens, flush dynamic MSI entries to free IRQ route entries.
|
* 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);
|
kvm_flush_dynamic_msi_routes(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1150,7 +1148,7 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg)
|
|||||||
struct kvm_msi msi;
|
struct kvm_msi msi;
|
||||||
KVMMSIRoute *route;
|
KVMMSIRoute *route;
|
||||||
|
|
||||||
if (s->direct_msi) {
|
if (kvm_direct_msi_allowed) {
|
||||||
msi.address_lo = (uint32_t)msg.address;
|
msi.address_lo = (uint32_t)msg.address;
|
||||||
msi.address_hi = msg.address >> 32;
|
msi.address_hi = msg.address >> 32;
|
||||||
msi.data = le32_to_cpu(msg.data);
|
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);
|
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 = {};
|
struct kvm_irq_routing_entry kroute = {};
|
||||||
int virq;
|
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_lo = (uint32_t)msg.address;
|
||||||
kroute.u.msi.address_hi = msg.address >> 32;
|
kroute.u.msi.address_hi = msg.address >> 32;
|
||||||
kroute.u.msi.data = le32_to_cpu(msg.data);
|
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);
|
kvm_irqchip_release_virq(s, virq);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1224,7 +1222,8 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg)
|
|||||||
return virq;
|
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 = {};
|
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_lo = (uint32_t)msg.address;
|
||||||
kroute.u.msi.address_hi = msg.address >> 32;
|
kroute.u.msi.address_hi = msg.address >> 32;
|
||||||
kroute.u.msi.data = le32_to_cpu(msg.data);
|
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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1585,20 +1584,8 @@ static int kvm_init(MachineState *ms)
|
|||||||
s->debugregs = kvm_check_extension(s, KVM_CAP_DEBUGREGS);
|
s->debugregs = kvm_check_extension(s, KVM_CAP_DEBUGREGS);
|
||||||
#endif
|
#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
|
#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
|
#endif
|
||||||
|
|
||||||
s->intx_set_mask = kvm_check_extension(s, KVM_CAP_PCI_2_3);
|
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;
|
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)
|
int kvm_has_many_ioeventfds(void)
|
||||||
{
|
{
|
||||||
if (!kvm_enabled()) {
|
if (!kvm_enabled()) {
|
||||||
|
10
kvm-stub.c
10
kvm-stub.c
@ -67,11 +67,6 @@ int kvm_has_many_ioeventfds(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int kvm_has_pit_state2(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kvm_setup_guest_memory(void *start, size_t size)
|
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
|
#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;
|
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;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
@ -53,14 +53,20 @@ struct kvm_regs {
|
|||||||
struct user_fpsimd_state fp_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_AEM_V8 0
|
||||||
#define KVM_ARM_TARGET_FOUNDATION_V8 1
|
#define KVM_ARM_TARGET_FOUNDATION_V8 1
|
||||||
#define KVM_ARM_TARGET_CORTEX_A57 2
|
#define KVM_ARM_TARGET_CORTEX_A57 2
|
||||||
#define KVM_ARM_TARGET_XGENE_POTENZA 3
|
#define KVM_ARM_TARGET_XGENE_POTENZA 3
|
||||||
#define KVM_ARM_TARGET_CORTEX_A53 4
|
#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 */
|
/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
|
||||||
#define KVM_ARM_DEVICE_TYPE_SHIFT 0
|
#define KVM_ARM_DEVICE_TYPE_SHIFT 0
|
||||||
@ -100,12 +106,39 @@ struct kvm_sregs {
|
|||||||
struct kvm_fpu {
|
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 {
|
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 {
|
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 {
|
struct kvm_sync_regs {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -183,6 +183,7 @@ struct kvm_s390_skeys {
|
|||||||
#define KVM_EXIT_EPR 23
|
#define KVM_EXIT_EPR 23
|
||||||
#define KVM_EXIT_SYSTEM_EVENT 24
|
#define KVM_EXIT_SYSTEM_EVENT 24
|
||||||
#define KVM_EXIT_S390_STSI 25
|
#define KVM_EXIT_S390_STSI 25
|
||||||
|
#define KVM_EXIT_IOAPIC_EOI 26
|
||||||
|
|
||||||
/* For KVM_EXIT_INTERNAL_ERROR */
|
/* For KVM_EXIT_INTERNAL_ERROR */
|
||||||
/* Emulate instruction failed. */
|
/* Emulate instruction failed. */
|
||||||
@ -237,6 +238,7 @@ struct kvm_run {
|
|||||||
__u32 count;
|
__u32 count;
|
||||||
__u64 data_offset; /* relative to kvm_run start */
|
__u64 data_offset; /* relative to kvm_run start */
|
||||||
} io;
|
} io;
|
||||||
|
/* KVM_EXIT_DEBUG */
|
||||||
struct {
|
struct {
|
||||||
struct kvm_debug_exit_arch arch;
|
struct kvm_debug_exit_arch arch;
|
||||||
} debug;
|
} debug;
|
||||||
@ -285,6 +287,7 @@ struct kvm_run {
|
|||||||
__u32 data;
|
__u32 data;
|
||||||
__u8 is_write;
|
__u8 is_write;
|
||||||
} dcr;
|
} dcr;
|
||||||
|
/* KVM_EXIT_INTERNAL_ERROR */
|
||||||
struct {
|
struct {
|
||||||
__u32 suberror;
|
__u32 suberror;
|
||||||
/* Available with KVM_CAP_INTERNAL_ERROR_DATA: */
|
/* Available with KVM_CAP_INTERNAL_ERROR_DATA: */
|
||||||
@ -295,6 +298,7 @@ struct kvm_run {
|
|||||||
struct {
|
struct {
|
||||||
__u64 gprs[32];
|
__u64 gprs[32];
|
||||||
} osi;
|
} osi;
|
||||||
|
/* KVM_EXIT_PAPR_HCALL */
|
||||||
struct {
|
struct {
|
||||||
__u64 nr;
|
__u64 nr;
|
||||||
__u64 ret;
|
__u64 ret;
|
||||||
@ -330,6 +334,10 @@ struct kvm_run {
|
|||||||
__u8 sel1;
|
__u8 sel1;
|
||||||
__u16 sel2;
|
__u16 sel2;
|
||||||
} s390_stsi;
|
} s390_stsi;
|
||||||
|
/* KVM_EXIT_IOAPIC_EOI */
|
||||||
|
struct {
|
||||||
|
__u8 vector;
|
||||||
|
} eoi;
|
||||||
/* Fix the size of the union. */
|
/* Fix the size of the union. */
|
||||||
char padding[256];
|
char padding[256];
|
||||||
};
|
};
|
||||||
@ -819,6 +827,10 @@ struct kvm_ppc_smmu_info {
|
|||||||
#define KVM_CAP_DISABLE_QUIRKS 116
|
#define KVM_CAP_DISABLE_QUIRKS 116
|
||||||
#define KVM_CAP_X86_SMM 117
|
#define KVM_CAP_X86_SMM 117
|
||||||
#define KVM_CAP_MULTI_ADDRESS_SPACE 118
|
#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
|
#ifdef KVM_CAP_IRQ_ROUTING
|
||||||
|
|
||||||
|
4
nbd.c
4
nbd.c
@ -1005,7 +1005,7 @@ static NBDRequest *nbd_request_get(NBDClient *client)
|
|||||||
client->nb_requests++;
|
client->nb_requests++;
|
||||||
nbd_update_can_read(client);
|
nbd_update_can_read(client);
|
||||||
|
|
||||||
req = g_slice_new0(NBDRequest);
|
req = g_new0(NBDRequest, 1);
|
||||||
nbd_client_get(client);
|
nbd_client_get(client);
|
||||||
req->client = client;
|
req->client = client;
|
||||||
return req;
|
return req;
|
||||||
@ -1018,7 +1018,7 @@ static void nbd_request_put(NBDRequest *req)
|
|||||||
if (req->data) {
|
if (req->data) {
|
||||||
qemu_vfree(req->data);
|
qemu_vfree(req->data);
|
||||||
}
|
}
|
||||||
g_slice_free(NBDRequest, req);
|
g_free(req);
|
||||||
|
|
||||||
client->nb_requests--;
|
client->nb_requests--;
|
||||||
nbd_update_can_read(client);
|
nbd_update_can_read(client);
|
||||||
|
395
qemu-char.c
395
qemu-char.c
@ -383,7 +383,10 @@ static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
|||||||
return 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;
|
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);
|
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;
|
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();
|
chr = qemu_chr_alloc();
|
||||||
d = g_new0(MuxDriver, 1);
|
d = g_new0(MuxDriver, 1);
|
||||||
|
|
||||||
@ -1078,18 +1090,17 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
|
|||||||
return chr;
|
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;
|
int fd_in, fd_out;
|
||||||
char filename_in[CHR_MAX_FILENAME_SIZE];
|
char filename_in[CHR_MAX_FILENAME_SIZE];
|
||||||
char filename_out[CHR_MAX_FILENAME_SIZE];
|
char filename_out[CHR_MAX_FILENAME_SIZE];
|
||||||
const char *filename = opts->device;
|
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_in, CHR_MAX_FILENAME_SIZE, "%s.in", filename);
|
||||||
snprintf(filename_out, CHR_MAX_FILENAME_SIZE, "%s.out", filename);
|
snprintf(filename_out, CHR_MAX_FILENAME_SIZE, "%s.out", filename);
|
||||||
TFR(fd_in = qemu_open(filename_in, O_RDWR | O_BINARY));
|
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);
|
close(fd_out);
|
||||||
TFR(fd_in = fd_out = qemu_open(filename, O_RDWR | O_BINARY));
|
TFR(fd_in = fd_out = qemu_open(filename, O_RDWR | O_BINARY));
|
||||||
if (fd_in < 0) {
|
if (fd_in < 0) {
|
||||||
|
error_setg_file_open(errp, errno, filename);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1156,19 +1168,23 @@ static void qemu_chr_close_stdio(struct CharDriverState *chr)
|
|||||||
fd_chr_close(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;
|
CharDriverState *chr;
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
|
|
||||||
if (is_daemonized()) {
|
if (is_daemonized()) {
|
||||||
error_report("cannot use stdio with -daemonize");
|
error_setg(errp, "cannot use stdio with -daemonize");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stdio_in_use) {
|
if (stdio_in_use) {
|
||||||
error_report("cannot use stdio by multiple character devices");
|
error_setg(errp, "cannot use stdio by multiple character devices");
|
||||||
exit(1);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
stdio_in_use = true;
|
stdio_in_use = true;
|
||||||
@ -1196,7 +1212,8 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
|
|||||||
|| defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
|
|| defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
|
||||||
|| defined(__GLIBC__)
|
|| defined(__GLIBC__)
|
||||||
|
|
||||||
#define HAVE_CHARDEV_TTY 1
|
#define HAVE_CHARDEV_SERIAL 1
|
||||||
|
#define HAVE_CHARDEV_PTY 1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GIOChannel *fd;
|
GIOChannel *fd;
|
||||||
@ -1389,7 +1406,9 @@ static void pty_chr_close(struct CharDriverState *chr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CharDriverState *qemu_chr_open_pty(const char *id,
|
static CharDriverState *qemu_chr_open_pty(const char *id,
|
||||||
ChardevReturn *ret)
|
ChardevBackend *backend,
|
||||||
|
ChardevReturn *ret,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
PtyCharDriver *s;
|
PtyCharDriver *s;
|
||||||
@ -1398,6 +1417,7 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
|
|||||||
|
|
||||||
master_fd = qemu_openpty_raw(&slave_fd, pty_name);
|
master_fd = qemu_openpty_raw(&slave_fd, pty_name);
|
||||||
if (master_fd < 0) {
|
if (master_fd < 0) {
|
||||||
|
error_setg_errno(errp, errno, "Failed to create PTY");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1752,12 +1772,13 @@ static void pp_close(CharDriverState *chr)
|
|||||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
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;
|
CharDriverState *chr;
|
||||||
ParallelCharDriver *drv;
|
ParallelCharDriver *drv;
|
||||||
|
|
||||||
if (ioctl(fd, PPCLAIM) < 0) {
|
if (ioctl(fd, PPCLAIM) < 0) {
|
||||||
|
error_setg_errno(errp, errno, "not a parallel port");
|
||||||
close(fd);
|
close(fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1817,7 +1838,7 @@ static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CharDriverState *qemu_chr_open_pp_fd(int fd)
|
static CharDriverState *qemu_chr_open_pp_fd(int fd, Error **errp)
|
||||||
{
|
{
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
|
|
||||||
@ -1832,6 +1853,8 @@ static CharDriverState *qemu_chr_open_pp_fd(int fd)
|
|||||||
|
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
|
|
||||||
|
#define HAVE_CHARDEV_SERIAL 1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int max_size;
|
int max_size;
|
||||||
HANDLE hcom, hrecv, hsend;
|
HANDLE hcom, hrecv, hsend;
|
||||||
@ -1883,7 +1906,7 @@ static void win_chr_close(CharDriverState *chr)
|
|||||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
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;
|
WinCharState *s = chr->opaque;
|
||||||
COMMCONFIG comcfg;
|
COMMCONFIG comcfg;
|
||||||
@ -1894,25 +1917,25 @@ static int win_chr_init(CharDriverState *chr, const char *filename)
|
|||||||
|
|
||||||
s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
|
s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
if (!s->hsend) {
|
if (!s->hsend) {
|
||||||
fprintf(stderr, "Failed CreateEvent\n");
|
error_setg(errp, "Failed CreateEvent");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
|
s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
if (!s->hrecv) {
|
if (!s->hrecv) {
|
||||||
fprintf(stderr, "Failed CreateEvent\n");
|
error_setg(errp, "Failed CreateEvent");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->hcom = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
|
s->hcom = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
|
||||||
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
|
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
|
||||||
if (s->hcom == INVALID_HANDLE_VALUE) {
|
if (s->hcom == INVALID_HANDLE_VALUE) {
|
||||||
fprintf(stderr, "Failed CreateFile (%lu)\n", GetLastError());
|
error_setg(errp, "Failed CreateFile (%lu)", GetLastError());
|
||||||
s->hcom = NULL;
|
s->hcom = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) {
|
if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) {
|
||||||
fprintf(stderr, "Failed SetupComm\n");
|
error_setg(errp, "Failed SetupComm");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1923,23 +1946,23 @@ static int win_chr_init(CharDriverState *chr, const char *filename)
|
|||||||
CommConfigDialog(filename, NULL, &comcfg);
|
CommConfigDialog(filename, NULL, &comcfg);
|
||||||
|
|
||||||
if (!SetCommState(s->hcom, &comcfg.dcb)) {
|
if (!SetCommState(s->hcom, &comcfg.dcb)) {
|
||||||
fprintf(stderr, "Failed SetCommState\n");
|
error_setg(errp, "Failed SetCommState");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetCommMask(s->hcom, EV_ERR)) {
|
if (!SetCommMask(s->hcom, EV_ERR)) {
|
||||||
fprintf(stderr, "Failed SetCommMask\n");
|
error_setg(errp, "Failed SetCommMask");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
cto.ReadIntervalTimeout = MAXDWORD;
|
cto.ReadIntervalTimeout = MAXDWORD;
|
||||||
if (!SetCommTimeouts(s->hcom, &cto)) {
|
if (!SetCommTimeouts(s->hcom, &cto)) {
|
||||||
fprintf(stderr, "Failed SetCommTimeouts\n");
|
error_setg(errp, "Failed SetCommTimeouts");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ClearCommError(s->hcom, &err, &comstat)) {
|
if (!ClearCommError(s->hcom, &err, &comstat)) {
|
||||||
fprintf(stderr, "Failed ClearCommError\n");
|
error_setg(errp, "Failed ClearCommError");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
qemu_add_polling_cb(win_chr_poll, chr);
|
qemu_add_polling_cb(win_chr_poll, chr);
|
||||||
@ -2044,7 +2067,8 @@ static int win_chr_poll(void *opaque)
|
|||||||
return 0;
|
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;
|
CharDriverState *chr;
|
||||||
WinCharState *s;
|
WinCharState *s;
|
||||||
@ -2055,7 +2079,7 @@ static CharDriverState *qemu_chr_open_win_path(const char *filename)
|
|||||||
chr->chr_write = win_chr_write;
|
chr->chr_write = win_chr_write;
|
||||||
chr->chr_close = win_chr_close;
|
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(s);
|
||||||
g_free(chr);
|
g_free(chr);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2079,7 +2103,8 @@ static int win_chr_pipe_poll(void *opaque)
|
|||||||
return 0;
|
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;
|
WinCharState *s = chr->opaque;
|
||||||
OVERLAPPED ov;
|
OVERLAPPED ov;
|
||||||
@ -2091,12 +2116,12 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
|
|||||||
|
|
||||||
s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
|
s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
if (!s->hsend) {
|
if (!s->hsend) {
|
||||||
fprintf(stderr, "Failed CreateEvent\n");
|
error_setg(errp, "Failed CreateEvent");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
|
s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
if (!s->hrecv) {
|
if (!s->hrecv) {
|
||||||
fprintf(stderr, "Failed CreateEvent\n");
|
error_setg(errp, "Failed CreateEvent");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2106,7 +2131,7 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
|
|||||||
PIPE_WAIT,
|
PIPE_WAIT,
|
||||||
MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL);
|
MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL);
|
||||||
if (s->hcom == INVALID_HANDLE_VALUE) {
|
if (s->hcom == INVALID_HANDLE_VALUE) {
|
||||||
fprintf(stderr, "Failed CreateNamedPipe (%lu)\n", GetLastError());
|
error_setg(errp, "Failed CreateNamedPipe (%lu)", GetLastError());
|
||||||
s->hcom = NULL;
|
s->hcom = NULL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -2115,13 +2140,13 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
|
|||||||
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
ret = ConnectNamedPipe(s->hcom, &ov);
|
ret = ConnectNamedPipe(s->hcom, &ov);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
fprintf(stderr, "Failed ConnectNamedPipe\n");
|
error_setg(errp, "Failed ConnectNamedPipe");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = GetOverlappedResult(s->hcom, &ov, &size, TRUE);
|
ret = GetOverlappedResult(s->hcom, &ov, &size, TRUE);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
fprintf(stderr, "Failed GetOverlappedResult\n");
|
error_setg(errp, "Failed GetOverlappedResult");
|
||||||
if (ov.hEvent) {
|
if (ov.hEvent) {
|
||||||
CloseHandle(ov.hEvent);
|
CloseHandle(ov.hEvent);
|
||||||
ov.hEvent = NULL;
|
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;
|
const char *filename = opts->device;
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
WinCharState *s;
|
WinCharState *s;
|
||||||
@ -2154,7 +2183,7 @@ static CharDriverState *qemu_chr_open_pipe(ChardevHostdev *opts)
|
|||||||
chr->chr_write = win_chr_write;
|
chr->chr_write = win_chr_write;
|
||||||
chr->chr_close = win_chr_close;
|
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(s);
|
||||||
g_free(chr);
|
g_free(chr);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2175,7 +2204,10 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
|
|||||||
return chr;
|
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));
|
return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE));
|
||||||
}
|
}
|
||||||
@ -2316,7 +2348,10 @@ static void win_stdio_close(CharDriverState *chr)
|
|||||||
g_free(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;
|
CharDriverState *chr;
|
||||||
WinStdioCharState *stdio;
|
WinStdioCharState *stdio;
|
||||||
@ -2328,8 +2363,8 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
|
|||||||
|
|
||||||
stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
if (stdio->hStdIn == INVALID_HANDLE_VALUE) {
|
if (stdio->hStdIn == INVALID_HANDLE_VALUE) {
|
||||||
fprintf(stderr, "cannot open stdio: invalid handle\n");
|
error_setg(errp, "cannot open stdio: invalid handle");
|
||||||
exit(1);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0;
|
is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0;
|
||||||
@ -2341,25 +2376,30 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
|
|||||||
if (is_console) {
|
if (is_console) {
|
||||||
if (qemu_add_wait_object(stdio->hStdIn,
|
if (qemu_add_wait_object(stdio->hStdIn,
|
||||||
win_stdio_wait_func, chr)) {
|
win_stdio_wait_func, chr)) {
|
||||||
fprintf(stderr, "qemu_add_wait_object: failed\n");
|
error_setg(errp, "qemu_add_wait_object: failed");
|
||||||
|
goto err1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DWORD dwId;
|
DWORD dwId;
|
||||||
|
|
||||||
stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
stdio->hInputDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
stdio->hInputDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
stdio->hInputThread = CreateThread(NULL, 0, win_stdio_thread,
|
if (stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
|
||||||
chr, 0, &dwId);
|
|
||||||
|
|
||||||
if (stdio->hInputThread == INVALID_HANDLE_VALUE
|
|
||||||
|| stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
|
|
||||||
|| stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) {
|
|| stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) {
|
||||||
fprintf(stderr, "cannot create stdio thread or event\n");
|
error_setg(errp, "cannot create event");
|
||||||
exit(1);
|
goto err2;
|
||||||
}
|
}
|
||||||
if (qemu_add_wait_object(stdio->hInputReadyEvent,
|
if (qemu_add_wait_object(stdio->hInputReadyEvent,
|
||||||
win_stdio_thread_wait_func, chr)) {
|
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);
|
qemu_chr_fe_set_echo(chr, false);
|
||||||
|
|
||||||
return chr;
|
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 */
|
#endif /* !_WIN32 */
|
||||||
|
|
||||||
@ -3173,9 +3222,12 @@ static void ringbuf_chr_close(struct CharDriverState *chr)
|
|||||||
chr->opaque = NULL;
|
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)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
ChardevRingbuf *opts = backend->ringbuf;
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
RingBufCharDriver *d;
|
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);
|
backend->stdio->signal = qemu_opt_get_bool(opts, "signal", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_CHARDEV_SERIAL
|
||||||
static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
|
static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
@ -3474,7 +3527,9 @@ static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
|
|||||||
backend->serial = g_new0(ChardevHostdev, 1);
|
backend->serial = g_new0(ChardevHostdev, 1);
|
||||||
backend->serial->device = g_strdup(device);
|
backend->serial->device = g_strdup(device);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_CHARDEV_PARPORT
|
||||||
static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
|
static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
@ -3487,6 +3542,7 @@ static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
|
|||||||
backend->parallel = g_new0(ChardevHostdev, 1);
|
backend->parallel = g_new0(ChardevHostdev, 1);
|
||||||
backend->parallel->device = g_strdup(device);
|
backend->parallel->device = g_strdup(device);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
|
static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
@ -3641,12 +3697,16 @@ typedef struct CharDriver {
|
|||||||
const char *name;
|
const char *name;
|
||||||
ChardevBackendKind kind;
|
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;
|
} CharDriver;
|
||||||
|
|
||||||
static GSList *backends;
|
static GSList *backends;
|
||||||
|
|
||||||
void register_char_driver(const char *name, ChardevBackendKind kind,
|
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;
|
CharDriver *s;
|
||||||
|
|
||||||
@ -3654,6 +3714,7 @@ void register_char_driver(const char *name, ChardevBackendKind kind,
|
|||||||
s->name = g_strdup(name);
|
s->name = g_strdup(name);
|
||||||
s->kind = kind;
|
s->kind = kind;
|
||||||
s->parse = parse;
|
s->parse = parse;
|
||||||
|
s->create = create;
|
||||||
|
|
||||||
backends = g_slist_append(backends, s);
|
backends = g_slist_append(backends, s);
|
||||||
}
|
}
|
||||||
@ -4002,8 +4063,12 @@ QemuOptsList qemu_chardev_opts = {
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#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;
|
HANDLE out;
|
||||||
|
|
||||||
if (file->has_in) {
|
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);
|
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)
|
Error **errp)
|
||||||
{
|
{
|
||||||
return qemu_chr_open_win_path(serial->device);
|
ChardevHostdev *serial = backend->serial;
|
||||||
}
|
return qemu_chr_open_win_path(serial->device, errp);
|
||||||
|
|
||||||
static CharDriverState *qmp_chardev_open_parallel(ChardevHostdev *parallel,
|
|
||||||
Error **errp)
|
|
||||||
{
|
|
||||||
error_setg(errp, "character device backend type 'parallel' not supported");
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* WIN32 */
|
#else /* WIN32 */
|
||||||
@ -4047,8 +4108,12 @@ static int qmp_chardev_open_file_source(char *src, int flags,
|
|||||||
return fd;
|
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;
|
int flags, in = -1, out;
|
||||||
|
|
||||||
flags = O_WRONLY | O_TRUNC | O_CREAT | O_BINARY;
|
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);
|
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)
|
Error **errp)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_CHARDEV_TTY
|
ChardevHostdev *serial = backend->serial;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = qmp_chardev_open_file_source(serial->device, O_RDWR, errp);
|
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);
|
qemu_set_nonblock(fd);
|
||||||
return qemu_chr_open_tty_fd(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)
|
Error **errp)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_CHARDEV_PARPORT
|
ChardevHostdev *parallel = backend->parallel;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = qmp_chardev_open_file_source(parallel->device, O_RDWR, errp);
|
fd = qmp_chardev_open_file_source(parallel->device, O_RDWR, errp);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return qemu_chr_open_pp_fd(fd);
|
return qemu_chr_open_pp_fd(fd, errp);
|
||||||
#else
|
|
||||||
error_setg(errp, "character device backend type 'parallel' not supported");
|
|
||||||
return NULL;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
|
|
||||||
@ -4131,11 +4196,14 @@ static gboolean socket_reconnect_timeout(gpointer opaque)
|
|||||||
return false;
|
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)
|
Error **errp)
|
||||||
{
|
{
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
TCPCharDriver *s;
|
TCPCharDriver *s;
|
||||||
|
ChardevSocket *sock = backend->socket;
|
||||||
SocketAddress *addr = sock->addr;
|
SocketAddress *addr = sock->addr;
|
||||||
bool do_nodelay = sock->has_nodelay ? sock->nodelay : false;
|
bool do_nodelay = sock->has_nodelay ? sock->nodelay : false;
|
||||||
bool is_listen = sock->has_server ? sock->server : true;
|
bool is_listen = sock->has_server ? sock->server : true;
|
||||||
@ -4197,9 +4265,12 @@ static CharDriverState *qmp_chardev_open_socket(ChardevSocket *sock,
|
|||||||
return chr;
|
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)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
ChardevUdp *udp = backend->udp;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = socket_dgram(udp->remote, udp->local, errp);
|
fd = socket_dgram(udp->remote, udp->local, errp);
|
||||||
@ -4213,7 +4284,10 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
|
|||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
ChardevReturn *ret = g_new0(ChardevReturn, 1);
|
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);
|
chr = qemu_chr_find(id);
|
||||||
if (chr) {
|
if (chr) {
|
||||||
@ -4222,106 +4296,40 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (backend->kind) {
|
for (i = backends; i; i = i->next) {
|
||||||
case CHARDEV_BACKEND_KIND_FILE:
|
cd = i->data;
|
||||||
chr = qmp_chardev_open_file(backend->file, errp);
|
|
||||||
break;
|
if (cd->kind == backend->kind) {
|
||||||
case CHARDEV_BACKEND_KIND_SERIAL:
|
chr = cd->create(id, backend, ret, &local_err);
|
||||||
chr = qmp_chardev_open_serial(backend->serial, errp);
|
if (local_err) {
|
||||||
break;
|
error_propagate(errp, local_err);
|
||||||
case CHARDEV_BACKEND_KIND_PARALLEL:
|
goto out_error;
|
||||||
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);
|
|
||||||
break;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (chr == NULL) {
|
||||||
* Character backend open hasn't been fully converted to the Error
|
assert(!i);
|
||||||
* API. Some opens fail without setting an error. Set a generic
|
error_setg(errp, "chardev backend not available");
|
||||||
* error then.
|
goto out_error;
|
||||||
* TODO full conversion to Error API
|
|
||||||
*/
|
|
||||||
if (chr == NULL && errp && !*errp) {
|
|
||||||
error_setg(errp, "Failed to create chardev");
|
|
||||||
}
|
}
|
||||||
if (chr) {
|
|
||||||
chr->label = g_strdup(id);
|
chr->label = g_strdup(id);
|
||||||
chr->avail_connections =
|
chr->avail_connections =
|
||||||
(backend->kind == CHARDEV_BACKEND_KIND_MUX) ? MAX_MUX : 1;
|
(backend->kind == CHARDEV_BACKEND_KIND_MUX) ? MAX_MUX : 1;
|
||||||
if (!chr->filename) {
|
if (!chr->filename) {
|
||||||
chr->filename = g_strdup(ChardevBackendKind_lookup[backend->kind]);
|
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;
|
|
||||||
}
|
}
|
||||||
|
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)
|
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)
|
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,
|
register_char_driver("socket", CHARDEV_BACKEND_KIND_SOCKET,
|
||||||
qemu_chr_parse_socket);
|
qemu_chr_parse_socket, qmp_chardev_open_socket);
|
||||||
register_char_driver("udp", CHARDEV_BACKEND_KIND_UDP, qemu_chr_parse_udp);
|
register_char_driver("udp", CHARDEV_BACKEND_KIND_UDP, qemu_chr_parse_udp,
|
||||||
|
qmp_chardev_open_udp);
|
||||||
register_char_driver("ringbuf", CHARDEV_BACKEND_KIND_RINGBUF,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
register_char_driver("parport", CHARDEV_BACKEND_KIND_PARALLEL,
|
||||||
qemu_chr_parse_parallel);
|
qemu_chr_parse_parallel, qmp_chardev_open_parallel);
|
||||||
register_char_driver("pty", CHARDEV_BACKEND_KIND_PTY, NULL);
|
#endif
|
||||||
register_char_driver("console", CHARDEV_BACKEND_KIND_CONSOLE, NULL);
|
#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,
|
register_char_driver("pipe", CHARDEV_BACKEND_KIND_PIPE,
|
||||||
qemu_chr_parse_pipe);
|
qemu_chr_parse_pipe, qemu_chr_open_pipe);
|
||||||
register_char_driver("mux", CHARDEV_BACKEND_KIND_MUX, qemu_chr_parse_mux);
|
register_char_driver("mux", CHARDEV_BACKEND_KIND_MUX, qemu_chr_parse_mux,
|
||||||
|
qemu_chr_open_mux);
|
||||||
/* Bug-compatibility: */
|
/* Bug-compatibility: */
|
||||||
register_char_driver("memory", CHARDEV_BACKEND_KIND_MEMORY,
|
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
|
/* this must be done after machine init, since we register FEs with muxes
|
||||||
* as part of realize functions like serial_isa_realizefn when -nographic
|
* as part of realize functions like serial_isa_realizefn when -nographic
|
||||||
* is specified
|
* is specified
|
||||||
|
@ -1010,7 +1010,9 @@ sub possible {
|
|||||||
case|
|
case|
|
||||||
else|
|
else|
|
||||||
asm|__asm__|
|
asm|__asm__|
|
||||||
do
|
do|
|
||||||
|
\#|
|
||||||
|
\#\#
|
||||||
)(?:\s|$)|
|
)(?:\s|$)|
|
||||||
^(?:typedef|struct|enum)\b
|
^(?:typedef|struct|enum)\b
|
||||||
)}x;
|
)}x;
|
||||||
@ -1704,11 +1706,6 @@ sub process {
|
|||||||
ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
|
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
|
# missing space after union, struct or enum definition
|
||||||
if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
|
if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
|
||||||
ERROR("missing space after $1 definition\n" . $herecurr);
|
ERROR("missing space after $1 definition\n" . $herecurr);
|
||||||
|
@ -296,15 +296,14 @@ static CharDriverState *chr_open(const char *subtype,
|
|||||||
return chr;
|
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();
|
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) {
|
for (; *psubtype != NULL; ++psubtype) {
|
||||||
if (strcmp(type, *psubtype) == 0) {
|
if (strcmp(type, *psubtype) == 0) {
|
||||||
break;
|
break;
|
||||||
@ -320,8 +319,12 @@ CharDriverState *qemu_chr_open_spice_vmc(const char *type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
#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;
|
CharDriverState *chr;
|
||||||
SpiceCharDriver *s;
|
SpiceCharDriver *s;
|
||||||
|
|
||||||
@ -379,9 +382,9 @@ static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend,
|
|||||||
static void register_types(void)
|
static void register_types(void)
|
||||||
{
|
{
|
||||||
register_char_driver("spicevmc", CHARDEV_BACKEND_KIND_SPICEVMC,
|
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,
|
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);
|
type_init(register_types);
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
stub-obj-y += arch-query-cpu-def.o
|
stub-obj-y += arch-query-cpu-def.o
|
||||||
stub-obj-y += bdrv-commit-all.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 += clock-warp.o
|
||||||
stub-obj-y += cpu-get-clock.o
|
stub-obj-y += cpu-get-clock.o
|
||||||
stub-obj-y += cpu-get-icount.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 += mon-printf.o
|
||||||
stub-obj-y += monitor-init.o
|
stub-obj-y += monitor-init.o
|
||||||
stub-obj-y += notify-event.o
|
stub-obj-y += notify-event.o
|
||||||
stub-obj-$(CONFIG_SPICE) += qemu-chr-open-spice.o
|
|
||||||
stub-obj-y += qtest.o
|
stub-obj-y += qtest.o
|
||||||
stub-obj-y += reset.o
|
stub-obj-y += reset.o
|
||||||
stub-obj-y += runstate-check.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 += slirp.o
|
||||||
stub-obj-y += sysbus.o
|
stub-obj-y += sysbus.o
|
||||||
stub-obj-y += uuid.o
|
stub-obj-y += uuid.o
|
||||||
stub-obj-y += vc-init.o
|
|
||||||
stub-obj-y += vm-stop.o
|
stub-obj-y += vm-stop.o
|
||||||
stub-obj-y += vmstate.o
|
stub-obj-y += vmstate.o
|
||||||
stub-obj-$(CONFIG_WIN32) += fd-register.o
|
stub-obj-$(CONFIG_WIN32) += fd-register.o
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
#include "qemu-common.h"
|
|
||||||
#include "sysemu/char.h"
|
|
||||||
|
|
||||||
CharDriverState *chr_baum_init(void)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
#include "qemu-common.h"
|
|
||||||
#include "sysemu/char.h"
|
|
||||||
|
|
||||||
CharDriverState *qemu_chr_open_msmouse(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
#include "qemu-common.h"
|
|
||||||
#include "sysemu/char.h"
|
|
||||||
|
|
||||||
CharDriverState *chr_testdev_init(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -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
|
|
@ -1,7 +0,0 @@
|
|||||||
#include "qemu-common.h"
|
|
||||||
#include "sysemu/char.h"
|
|
||||||
|
|
||||||
CharDriverState *vc_init(ChardevVC *vc)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -605,7 +605,7 @@ int kvm_arm_vgic_probe(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -88,8 +88,12 @@ typedef struct X86CPU {
|
|||||||
bool hyperv_vapic;
|
bool hyperv_vapic;
|
||||||
bool hyperv_relaxed_timing;
|
bool hyperv_relaxed_timing;
|
||||||
int hyperv_spinlock_attempts;
|
int hyperv_spinlock_attempts;
|
||||||
|
char *hyperv_vendor_id;
|
||||||
bool hyperv_time;
|
bool hyperv_time;
|
||||||
bool hyperv_crash;
|
bool hyperv_crash;
|
||||||
|
bool hyperv_reset;
|
||||||
|
bool hyperv_vpindex;
|
||||||
|
bool hyperv_runtime;
|
||||||
bool check_cpuid;
|
bool check_cpuid;
|
||||||
bool enforce_cpuid;
|
bool enforce_cpuid;
|
||||||
bool expose_kvm;
|
bool expose_kvm;
|
||||||
|
@ -3140,12 +3140,16 @@ static Property x86_cpu_properties[] = {
|
|||||||
DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false),
|
DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false),
|
||||||
DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false),
|
DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false),
|
||||||
DEFINE_PROP_BOOL("hv-crash", X86CPU, hyperv_crash, 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("check", X86CPU, check_cpuid, false),
|
||||||
DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
|
DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
|
||||||
DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
|
DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
|
||||||
DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, 0),
|
DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, 0),
|
||||||
DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, 0),
|
DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, 0),
|
||||||
DEFINE_PROP_UINT32("xlevel2", X86CPU, env.cpuid_xlevel2, 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()
|
DEFINE_PROP_END_OF_LIST()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -911,6 +911,7 @@ typedef struct CPUX86State {
|
|||||||
uint64_t msr_hv_vapic;
|
uint64_t msr_hv_vapic;
|
||||||
uint64_t msr_hv_tsc;
|
uint64_t msr_hv_tsc;
|
||||||
uint64_t msr_hv_crash_params[HV_X64_MSR_CRASH_PARAMS];
|
uint64_t msr_hv_crash_params[HV_X64_MSR_CRASH_PARAMS];
|
||||||
|
uint64_t msr_hv_runtime;
|
||||||
|
|
||||||
/* exception/interrupt handling */
|
/* exception/interrupt handling */
|
||||||
int error_code;
|
int error_code;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "exec/gdbstub.h"
|
#include "exec/gdbstub.h"
|
||||||
#include "qemu/host-utils.h"
|
#include "qemu/host-utils.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
#include "hw/i386/pc.h"
|
#include "hw/i386/pc.h"
|
||||||
#include "hw/i386/apic.h"
|
#include "hw/i386/apic.h"
|
||||||
#include "hw/i386/apic_internal.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_vapic;
|
||||||
static bool has_msr_hv_tsc;
|
static bool has_msr_hv_tsc;
|
||||||
static bool has_msr_hv_crash;
|
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_mtrr;
|
||||||
static bool has_msr_xss;
|
static bool has_msr_xss;
|
||||||
|
|
||||||
static bool has_msr_architectural_pmu;
|
static bool has_msr_architectural_pmu;
|
||||||
static uint32_t num_architectural_pmu_counters;
|
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)
|
bool kvm_has_smm(void)
|
||||||
{
|
{
|
||||||
return kvm_check_extension(kvm_state, KVM_CAP_X86_SMM);
|
return kvm_check_extension(kvm_state, KVM_CAP_X86_SMM);
|
||||||
@ -460,7 +473,10 @@ static bool hyperv_enabled(X86CPU *cpu)
|
|||||||
(hyperv_hypercall_available(cpu) ||
|
(hyperv_hypercall_available(cpu) ||
|
||||||
cpu->hyperv_time ||
|
cpu->hyperv_time ||
|
||||||
cpu->hyperv_relaxed_timing ||
|
cpu->hyperv_relaxed_timing ||
|
||||||
cpu->hyperv_crash);
|
cpu->hyperv_crash ||
|
||||||
|
cpu->hyperv_reset ||
|
||||||
|
cpu->hyperv_vpindex ||
|
||||||
|
cpu->hyperv_runtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Error *invtsc_mig_blocker;
|
static Error *invtsc_mig_blocker;
|
||||||
@ -490,7 +506,18 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
|||||||
if (hyperv_enabled(cpu)) {
|
if (hyperv_enabled(cpu)) {
|
||||||
c = &cpuid_data.entries[cpuid_i++];
|
c = &cpuid_data.entries[cpuid_i++];
|
||||||
c->function = HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
|
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->eax = HYPERV_CPUID_MIN;
|
||||||
c->ebx = signature[0];
|
c->ebx = signature[0];
|
||||||
c->ecx = signature[1];
|
c->ecx = signature[1];
|
||||||
@ -529,7 +556,15 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
|||||||
if (cpu->hyperv_crash && has_msr_hv_crash) {
|
if (cpu->hyperv_crash && has_msr_hv_crash) {
|
||||||
c->edx |= HV_X64_GUEST_CRASH_MSR_AVAILABLE;
|
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 = &cpuid_data.entries[cpuid_i++];
|
||||||
c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
|
c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
|
||||||
if (cpu->hyperv_relaxed_timing) {
|
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));
|
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;
|
has_msr_hv_crash = true;
|
||||||
continue;
|
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;
|
int ret;
|
||||||
struct utsname utsname;
|
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);
|
ret = kvm_get_supported_msrs(s);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
@ -1116,7 +1175,7 @@ static int kvm_put_xsave(X86CPU *cpu)
|
|||||||
uint8_t *xmm, *ymmh, *zmmh;
|
uint8_t *xmm, *ymmh, *zmmh;
|
||||||
int i, r;
|
int i, r;
|
||||||
|
|
||||||
if (!kvm_has_xsave()) {
|
if (!has_xsave) {
|
||||||
return kvm_put_fpu(cpu);
|
return kvm_put_fpu(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1170,7 +1229,7 @@ static int kvm_put_xcrs(X86CPU *cpu)
|
|||||||
CPUX86State *env = &cpu->env;
|
CPUX86State *env = &cpu->env;
|
||||||
struct kvm_xcrs xcrs = {};
|
struct kvm_xcrs xcrs = {};
|
||||||
|
|
||||||
if (!kvm_has_xcrs()) {
|
if (!has_xcrs) {
|
||||||
return 0;
|
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,
|
kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_CRASH_CTL,
|
||||||
HV_X64_MSR_CRASH_CTL_NOTIFY);
|
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) {
|
if (has_msr_mtrr) {
|
||||||
kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype);
|
kvm_msr_entry_set(&msrs[n++], MSR_MTRRdefType, env->mtrr_deftype);
|
||||||
kvm_msr_entry_set(&msrs[n++],
|
kvm_msr_entry_set(&msrs[n++],
|
||||||
@ -1495,7 +1558,7 @@ static int kvm_get_xsave(X86CPU *cpu)
|
|||||||
const uint8_t *xmm, *ymmh, *zmmh;
|
const uint8_t *xmm, *ymmh, *zmmh;
|
||||||
uint16_t cwd, swd, twd;
|
uint16_t cwd, swd, twd;
|
||||||
|
|
||||||
if (!kvm_has_xsave()) {
|
if (!has_xsave) {
|
||||||
return kvm_get_fpu(cpu);
|
return kvm_get_fpu(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1554,7 +1617,7 @@ static int kvm_get_xcrs(X86CPU *cpu)
|
|||||||
int i, ret;
|
int i, ret;
|
||||||
struct kvm_xcrs xcrs;
|
struct kvm_xcrs xcrs;
|
||||||
|
|
||||||
if (!kvm_has_xcrs()) {
|
if (!has_xcrs) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1768,6 +1831,9 @@ static int kvm_get_msrs(X86CPU *cpu)
|
|||||||
msrs[n++].index = HV_X64_MSR_CRASH_P0 + j;
|
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) {
|
if (has_msr_mtrr) {
|
||||||
msrs[n++].index = MSR_MTRRdefType;
|
msrs[n++].index = MSR_MTRRdefType;
|
||||||
msrs[n++].index = MSR_MTRRfix64K_00000;
|
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:
|
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;
|
env->msr_hv_crash_params[index - HV_X64_MSR_CRASH_P0] = msrs[i].data;
|
||||||
break;
|
break;
|
||||||
|
case HV_X64_MSR_VP_RUNTIME:
|
||||||
|
env->msr_hv_runtime = msrs[i].data;
|
||||||
|
break;
|
||||||
case MSR_MTRRdefType:
|
case MSR_MTRRdefType:
|
||||||
env->mtrr_deftype = msrs[i].data;
|
env->mtrr_deftype = msrs[i].data;
|
||||||
break;
|
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,
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
static bool avx512_needed(void *opaque)
|
||||||
{
|
{
|
||||||
X86CPU *cpu = opaque;
|
X86CPU *cpu = opaque;
|
||||||
@ -869,6 +888,7 @@ VMStateDescription vmstate_x86_cpu = {
|
|||||||
&vmstate_msr_hyperv_vapic,
|
&vmstate_msr_hyperv_vapic,
|
||||||
&vmstate_msr_hyperv_time,
|
&vmstate_msr_hyperv_time,
|
||||||
&vmstate_msr_hyperv_crash,
|
&vmstate_msr_hyperv_crash,
|
||||||
|
&vmstate_msr_hyperv_runtime,
|
||||||
&vmstate_avx512,
|
&vmstate_avx512,
|
||||||
&vmstate_xss,
|
&vmstate_xss,
|
||||||
NULL
|
NULL
|
||||||
|
@ -678,7 +678,7 @@ int kvm_arch_get_registers(CPUState *cs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2483,7 +2483,7 @@ error_out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
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;
|
S390PCIBusDevice *pbdev;
|
||||||
uint32_t fid = data >> ZPCI_MSI_VEC_BITS;
|
uint32_t fid = data >> ZPCI_MSI_VEC_BITS;
|
||||||
|
11
ui/console.c
11
ui/console.c
@ -1962,7 +1962,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
|
|||||||
chr->init(chr);
|
chr->init(chr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CharDriverState *text_console_init(ChardevVC *vc)
|
static CharDriverState *text_console_init(ChardevVC *vc, Error **errp)
|
||||||
{
|
{
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
QemuConsole *s;
|
QemuConsole *s;
|
||||||
@ -1993,6 +1993,7 @@ static CharDriverState *text_console_init(ChardevVC *vc)
|
|||||||
|
|
||||||
if (!s) {
|
if (!s) {
|
||||||
g_free(chr);
|
g_free(chr);
|
||||||
|
error_setg(errp, "cannot create text console");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2012,9 +2013,10 @@ static CharDriverState *text_console_init(ChardevVC *vc)
|
|||||||
|
|
||||||
static VcHandler *vc_handler = text_console_init;
|
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)
|
void register_vc_handler(VcHandler *handler)
|
||||||
@ -2093,7 +2095,8 @@ static const TypeInfo qemu_console_info = {
|
|||||||
static void register_types(void)
|
static void register_types(void)
|
||||||
{
|
{
|
||||||
type_register_static(&qemu_console_info);
|
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);
|
type_init(register_types);
|
||||||
|
2
ui/gtk.c
2
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 int nb_vcs;
|
||||||
static CharDriverState *vcs[MAX_VCS];
|
static CharDriverState *vcs[MAX_VCS];
|
||||||
|
|
||||||
static CharDriverState *gd_vc_handler(ChardevVC *unused)
|
static CharDriverState *gd_vc_handler(ChardevVC *unused, Error **errp)
|
||||||
{
|
{
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
|
|
||||||
|
@ -586,12 +586,15 @@ fail:
|
|||||||
|
|
||||||
static void inet_addr_to_opts(QemuOpts *opts, const InetSocketAddress *addr)
|
static void inet_addr_to_opts(QemuOpts *opts, const InetSocketAddress *addr)
|
||||||
{
|
{
|
||||||
bool ipv4 = addr->ipv4 || !addr->has_ipv4;
|
bool ipv4 = addr->has_ipv4 && addr->ipv4;
|
||||||
bool ipv6 = addr->ipv6 || !addr->has_ipv6;
|
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, "ipv4", ipv4, &error_abort);
|
||||||
qemu_opt_set_bool(opts, "ipv6", ipv6, &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) {
|
if (addr->has_to) {
|
||||||
qemu_opt_set_number(opts, "to", addr->to, &error_abort);
|
qemu_opt_set_number(opts, "to", addr->to, &error_abort);
|
||||||
|
Loading…
Reference in New Issue
Block a user