Browse Source
* More vl.c cleanup (myself with help from Daniel and Igor) * Remove deprecated options (Philippe, Thomas) * Dirty bitmap fix (Zenghui) * icount caching speedup (Pavel) * SCSI race fix (Maxim) * Remove pre-GCC 4.8 code (Marc-André) -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAl/Y+BQUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroOhPwf9GnBgYnsJcMpvsmKPZ0aU7qhCtGxY HrlxRXxGSK1kBlbRnIA2XEJe07isQRyT4q3dpLH+cJkA6gBAmBICvO0tHY8eW0OB 6qbTPdYvrIhjBkeeEy+WGmgU+kw/YXCOCx6TdZFjYm6BqalAMXuTGw82jLlKyOGI 2Ehc0PNnOTPZuRSmIgs7Kox5lDViJIX1ydMUeWw1lMksosCgeyZzecVdp9Ehmv9O SuSgq5ilmsUvzrV9DbYaT3/KinwLI+ZHPCiOd75WWB+cX546iji1nH9aaUHPnwy0 EsAGza06A93uyiQNOxIPkF7Wd27e+u1VkfsCdOBNS8hy3sOeKhh/yZxkgA== =sFe1 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging * New -action option and set-action QMP command (Alejandro) * More vl.c cleanup (myself with help from Daniel and Igor) * Remove deprecated options (Philippe, Thomas) * Dirty bitmap fix (Zenghui) * icount caching speedup (Pavel) * SCSI race fix (Maxim) * Remove pre-GCC 4.8 code (Marc-André) # gpg: Signature made Tue 15 Dec 2020 17:53:24 GMT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini-gitlab/tags/for-upstream: (45 commits) build: -no-pie is no functional linker flag scripts/git.orderfile: Keep files with .inc extension sorted compiler.h: remove QEMU_GNUC_PREREQ linux-user: remove GNUC check compiler: remove GNUC check xen: remove GNUC check poison: remove GNUC check compiler.h: explicit case for Clang printf attribute virtiofsd: replace _Static_assert with QEMU_BUILD_BUG_ON tests: remove GCC < 4 fallbacks qemu-plugin.h: remove GCC < 4 compiler.h: remove GCC < 3 __builtin_expect fallback accel/tcg: Remove special case for GCC < 4.6 qemu/atomic: Drop special case for unsupported compiler hw/core: Restrict 'fw-path-provider.c' to system mode emulation docs: set CONFDIR when running sphinx vl: rename local variable in configure_accelerators qemu-option: pass QemuOptsList to opts_accepts_any qemu-option: simplify search for end of key kvm: Take into account the unaligned section size when preparing bitmap ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org> # Conflicts: # softmmu/vl.cpull/104/head
79 changed files with 1832 additions and 1595 deletions
@ -1,69 +0,0 @@ |
|||
/*
|
|||
* QEMU System Emulator |
|||
* |
|||
* Copyright (c) 2003-2008 Fabrice Bellard |
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
* THE SOFTWARE. |
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
#include "sysemu/sysemu.h" |
|||
#include "chardev/char.h" |
|||
#include "qemu/error-report.h" |
|||
#include "chardev-internal.h" |
|||
|
|||
static int chardev_machine_done_notify_one(Object *child, void *opaque) |
|||
{ |
|||
Chardev *chr = (Chardev *)child; |
|||
ChardevClass *class = CHARDEV_GET_CLASS(chr); |
|||
|
|||
if (class->chr_machine_done) { |
|||
return class->chr_machine_done(chr); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
static void chardev_machine_done_hook(Notifier *notifier, void *unused) |
|||
{ |
|||
int ret = object_child_foreach(get_chardevs_root(), |
|||
chardev_machine_done_notify_one, NULL); |
|||
|
|||
if (ret) { |
|||
error_report("Failed to call chardev machine_done hooks"); |
|||
exit(1); |
|||
} |
|||
} |
|||
|
|||
|
|||
static Notifier chardev_machine_done_notify = { |
|||
.notify = chardev_machine_done_hook, |
|||
}; |
|||
|
|||
static void register_types(void) |
|||
{ |
|||
/*
|
|||
* This must be done after machine init, since we register FEs with muxes |
|||
* as part of realize functions like serial_isa_realizefn when -nographic |
|||
* is specified. |
|||
*/ |
|||
qemu_add_machine_init_done_notifier(&chardev_machine_done_notify); |
|||
} |
|||
|
|||
type_init(register_types); |
|||
@ -0,0 +1,243 @@ |
|||
|
|||
Removed features |
|||
================ |
|||
|
|||
What follows is a record of recently removed, formerly deprecated |
|||
features that serves as a record for users who have encountered |
|||
trouble after a recent upgrade. |
|||
|
|||
System emulator command line arguments |
|||
-------------------------------------- |
|||
|
|||
``-net ...,name=``\ *name* (removed in 5.1) |
|||
''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
The ``name`` parameter of the ``-net`` option was a synonym |
|||
for the ``id`` parameter, which should now be used instead. |
|||
|
|||
``-no-kvm`` (removed in 5.2) |
|||
'''''''''''''''''''''''''''' |
|||
|
|||
The ``-no-kvm`` argument was a synonym for setting ``-machine accel=tcg``. |
|||
|
|||
``-realtime`` (removed in 6.0) |
|||
'''''''''''''''''''''''''''''' |
|||
|
|||
The ``-realtime mlock=on|off`` argument has been replaced by the |
|||
``-overcommit mem-lock=on|off`` argument. |
|||
|
|||
``-show-cursor`` option (since 5.0) |
|||
''''''''''''''''''''''''''''''''''' |
|||
|
|||
Use ``-display sdl,show-cursor=on``, ``-display gtk,show-cursor=on`` |
|||
or ``-display default,show-cursor=on`` instead. |
|||
|
|||
``-tb-size`` option (removed in 6.0) |
|||
'''''''''''''''''''''''''''''''''''' |
|||
|
|||
QEMU 5.0 introduced an alternative syntax to specify the size of the translation |
|||
block cache, ``-accel tcg,tb-size=``. |
|||
|
|||
QEMU Machine Protocol (QMP) commands |
|||
------------------------------------ |
|||
|
|||
``block-dirty-bitmap-add`` "autoload" parameter (removed in 4.2.0) |
|||
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
The "autoload" parameter has been ignored since 2.12.0. All bitmaps |
|||
are automatically loaded from qcow2 images. |
|||
|
|||
``cpu-add`` (removed in 5.2) |
|||
'''''''''''''''''''''''''''' |
|||
|
|||
Use ``device_add`` for hotplugging vCPUs instead of ``cpu-add``. See |
|||
documentation of ``query-hotpluggable-cpus`` for additional details. |
|||
|
|||
Human Monitor Protocol (HMP) commands |
|||
------------------------------------- |
|||
|
|||
The ``hub_id`` parameter of ``hostfwd_add`` / ``hostfwd_remove`` (removed in 5.0) |
|||
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
The ``[hub_id name]`` parameter tuple of the 'hostfwd_add' and |
|||
'hostfwd_remove' HMP commands has been replaced by ``netdev_id``. |
|||
|
|||
``cpu-add`` (removed in 5.2) |
|||
'''''''''''''''''''''''''''' |
|||
|
|||
Use ``device_add`` for hotplugging vCPUs instead of ``cpu-add``. See |
|||
documentation of ``query-hotpluggable-cpus`` for additional details. |
|||
|
|||
Guest Emulator ISAs |
|||
------------------- |
|||
|
|||
RISC-V ISA privilege specification version 1.09.1 (removed in 5.1) |
|||
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
The RISC-V ISA privilege specification version 1.09.1 has been removed. |
|||
QEMU supports both the newer version 1.10.0 and the ratified version 1.11.0, these |
|||
should be used instead of the 1.09.1 version. |
|||
|
|||
System emulator CPUS |
|||
-------------------- |
|||
|
|||
KVM guest support on 32-bit Arm hosts (removed in 5.2) |
|||
'''''''''''''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
The Linux kernel has dropped support for allowing 32-bit Arm systems |
|||
to host KVM guests as of the 5.7 kernel. Accordingly, QEMU is deprecating |
|||
its support for this configuration and will remove it in a future version. |
|||
Running 32-bit guests on a 64-bit Arm host remains supported. |
|||
|
|||
RISC-V ISA Specific CPUs (removed in 5.1) |
|||
''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
The RISC-V cpus with the ISA version in the CPU name have been removed. The |
|||
four CPUs are: ``rv32gcsu-v1.9.1``, ``rv32gcsu-v1.10.0``, ``rv64gcsu-v1.9.1`` and |
|||
``rv64gcsu-v1.10.0``. Instead the version can be specified via the CPU ``priv_spec`` |
|||
option when using the ``rv32`` or ``rv64`` CPUs. |
|||
|
|||
RISC-V no MMU CPUs (removed in 5.1) |
|||
''''''''''''''''''''''''''''''''''' |
|||
|
|||
The RISC-V no MMU cpus have been removed. The two CPUs: ``rv32imacu-nommu`` and |
|||
``rv64imacu-nommu`` can no longer be used. Instead the MMU status can be specified |
|||
via the CPU ``mmu`` option when using the ``rv32`` or ``rv64`` CPUs. |
|||
|
|||
System emulator machines |
|||
------------------------ |
|||
|
|||
``spike_v1.9.1`` and ``spike_v1.10`` (removed in 5.1) |
|||
''''''''''''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
The version specific Spike machines have been removed in favour of the |
|||
generic ``spike`` machine. If you need to specify an older version of the RISC-V |
|||
spec you can use the ``-cpu rv64gcsu,priv_spec=v1.10.0`` command line argument. |
|||
|
|||
mips ``r4k`` platform (removed in 5.2) |
|||
'''''''''''''''''''''''''''''''''''''' |
|||
|
|||
This machine type was very old and unmaintained. Users should use the ``malta`` |
|||
machine type instead. |
|||
|
|||
Related binaries |
|||
---------------- |
|||
|
|||
``qemu-nbd --partition`` (removed in 5.0) |
|||
''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
The ``qemu-nbd --partition $digit`` code (also spelled ``-P``) |
|||
could only handle MBR partitions, and never correctly handled logical |
|||
partitions beyond partition 5. Exporting a partition can still be |
|||
done by utilizing the ``--image-opts`` option with a raw blockdev |
|||
using the ``offset`` and ``size`` parameters layered on top of |
|||
any other existing blockdev. For example, if partition 1 is 100MiB |
|||
long starting at 1MiB, the old command:: |
|||
|
|||
qemu-nbd -t -P 1 -f qcow2 file.qcow2 |
|||
|
|||
can be rewritten as:: |
|||
|
|||
qemu-nbd -t --image-opts driver=raw,offset=1M,size=100M,file.driver=qcow2,file.file.driver=file,file.file.filename=file.qcow2 |
|||
|
|||
``qemu-img convert -n -o`` (removed in 5.1) |
|||
''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
All options specified in ``-o`` are image creation options, so |
|||
they are now rejected when used with ``-n`` to skip image creation. |
|||
|
|||
|
|||
``qemu-img create -b bad file $size`` (removed in 5.1) |
|||
'''''''''''''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
When creating an image with a backing file that could not be opened, |
|||
``qemu-img create`` used to issue a warning about the failure but |
|||
proceed with the image creation if an explicit size was provided. |
|||
However, as the ``-u`` option exists for this purpose, it is safer to |
|||
enforce that any failure to open the backing image (including if the |
|||
backing file is missing or an incorrect format was specified) is an |
|||
error when ``-u`` is not used. |
|||
|
|||
Command line options |
|||
-------------------- |
|||
|
|||
``-smp`` (invalid topologies) (removed 5.2) |
|||
''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
CPU topology properties should describe whole machine topology including |
|||
possible CPUs. |
|||
|
|||
However, historically it was possible to start QEMU with an incorrect topology |
|||
where *n* <= *sockets* * *cores* * *threads* < *maxcpus*, |
|||
which could lead to an incorrect topology enumeration by the guest. |
|||
Support for invalid topologies is removed, the user must ensure |
|||
topologies described with -smp include all possible cpus, i.e. |
|||
*sockets* * *cores* * *threads* = *maxcpus*. |
|||
|
|||
``-numa`` node (without memory specified) (removed 5.2) |
|||
''''''''''''''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
Splitting RAM by default between NUMA nodes had the same issues as ``mem`` |
|||
parameter with the difference that the role of the user plays QEMU using |
|||
implicit generic or board specific splitting rule. |
|||
Use ``memdev`` with *memory-backend-ram* backend or ``mem`` (if |
|||
it's supported by used machine type) to define mapping explicitly instead. |
|||
Users of existing VMs, wishing to preserve the same RAM distribution, should |
|||
configure it explicitly using ``-numa node,memdev`` options. Current RAM |
|||
distribution can be retrieved using HMP command ``info numa`` and if separate |
|||
memory devices (pc|nv-dimm) are present use ``info memory-device`` and subtract |
|||
device memory from output of ``info numa``. |
|||
|
|||
``-numa node,mem=``\ *size* (removed in 5.1) |
|||
'''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
The parameter ``mem`` of ``-numa node`` was used to assign a part of |
|||
guest RAM to a NUMA node. But when using it, it's impossible to manage a specified |
|||
RAM chunk on the host side (like bind it to a host node, setting bind policy, ...), |
|||
so the guest ends up with the fake NUMA configuration with suboptiomal performance. |
|||
However since 2014 there is an alternative way to assign RAM to a NUMA node |
|||
using parameter ``memdev``, which does the same as ``mem`` and adds |
|||
means to actually manage node RAM on the host side. Use parameter ``memdev`` |
|||
with *memory-backend-ram* backend as replacement for parameter ``mem`` |
|||
to achieve the same fake NUMA effect or a properly configured |
|||
*memory-backend-file* backend to actually benefit from NUMA configuration. |
|||
New machine versions (since 5.1) will not accept the option but it will still |
|||
work with old machine types. User can check the QAPI schema to see if the legacy |
|||
option is supported by looking at MachineInfo::numa-mem-supported property. |
|||
|
|||
``-mem-path`` fallback to RAM (removed in 5.0) |
|||
'''''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
If guest RAM allocation from file pointed by ``mem-path`` failed, |
|||
QEMU was falling back to allocating from RAM, which might have resulted |
|||
in unpredictable behavior since the backing file specified by the user |
|||
as ignored. Currently, users are responsible for making sure the backing storage |
|||
specified with ``-mem-path`` can actually provide the guest RAM configured with |
|||
``-m`` and QEMU fails to start up if RAM allocation is unsuccessful. |
|||
|
|||
``-smp`` (invalid topologies) (removed 5.2) |
|||
''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
CPU topology properties should describe whole machine topology including |
|||
possible CPUs. |
|||
|
|||
However, historically it was possible to start QEMU with an incorrect topology |
|||
where *n* <= *sockets* * *cores* * *threads* < *maxcpus*, |
|||
which could lead to an incorrect topology enumeration by the guest. |
|||
Support for invalid topologies is removed, the user must ensure |
|||
topologies described with -smp include all possible cpus, i.e. |
|||
*sockets* * *cores* * *threads* = *maxcpus*. |
|||
|
|||
``-machine enforce-config-section=on|off`` (removed 5.2) |
|||
'''''''''''''''''''''''''''''''''''''''''''''''''''''''' |
|||
|
|||
The ``enforce-config-section`` property was replaced by the |
|||
``-global migration.send-configuration={on|off}`` option. |
|||
|
|||
Block devices |
|||
------------- |
|||
|
|||
VXHS backend (removed in 5.1) |
|||
''''''''''''''''''''''''''''' |
|||
|
|||
The VXHS code did not compile since v2.12.0. It was removed in 5.1. |
|||
@ -0,0 +1,19 @@ |
|||
/*
|
|||
* Copyright (c) 2020 Oracle and/or its affiliates. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2. |
|||
* See the COPYING file in the top-level directory. |
|||
* |
|||
*/ |
|||
|
|||
#ifndef RUNSTATE_ACTION_H |
|||
#define RUNSTATE_ACTION_H |
|||
|
|||
#include "qapi/qapi-commands-run-state.h" |
|||
|
|||
/* in softmmu/runstate-action.c */ |
|||
extern RebootAction reboot_action; |
|||
extern ShutdownAction shutdown_action; |
|||
extern PanicAction panic_action; |
|||
|
|||
#endif /* RUNSTATE_ACTION_H */ |
|||
@ -0,0 +1,72 @@ |
|||
/*
|
|||
* Global variables that (mostly) should not exist |
|||
* |
|||
* Copyright (c) 2003-2020 QEMU contributors |
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
* THE SOFTWARE. |
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
#include "exec/cpu-common.h" |
|||
#include "hw/display/vga.h" |
|||
#include "hw/i386/pc.h" |
|||
#include "hw/i386/x86.h" |
|||
#include "hw/loader.h" |
|||
#include "hw/xen/xen.h" |
|||
#include "net/net.h" |
|||
#include "sysemu/cpus.h" |
|||
#include "sysemu/sysemu.h" |
|||
|
|||
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; |
|||
int display_opengl; |
|||
const char* keyboard_layout; |
|||
bool enable_mlock; |
|||
bool enable_cpu_pm; |
|||
int nb_nics; |
|||
NICInfo nd_table[MAX_NICS]; |
|||
int autostart = 1; |
|||
int vga_interface_type = VGA_NONE; |
|||
Chardev *parallel_hds[MAX_PARALLEL_PORTS]; |
|||
int win2k_install_hack; |
|||
int singlestep; |
|||
int fd_bootchk = 1; |
|||
int graphic_rotate; |
|||
QEMUOptionRom option_rom[MAX_OPTION_ROMS]; |
|||
int nb_option_roms; |
|||
int old_param; |
|||
const char *qemu_name; |
|||
int alt_grab; |
|||
int ctrl_grab; |
|||
unsigned int nb_prom_envs; |
|||
const char *prom_envs[MAX_PROM_ENVS]; |
|||
int boot_menu; |
|||
bool boot_strict; |
|||
uint8_t *boot_splash_filedata; |
|||
int only_migratable; /* turn it off unless user states otherwise */ |
|||
int icount_align_option; |
|||
|
|||
/* The bytes in qemu_uuid are in the order specified by RFC4122, _not_ in the
|
|||
* little-endian "wire format" described in the SMBIOS 2.6 specification. |
|||
*/ |
|||
QemuUUID qemu_uuid; |
|||
bool qemu_uuid_set; |
|||
|
|||
uint32_t xen_domid; |
|||
enum xen_mode xen_mode = XEN_EMULATE; |
|||
bool xen_domid_restrict; |
|||
@ -0,0 +1,46 @@ |
|||
/*
|
|||
* Copyright (c) 2020 Oracle and/or its affiliates. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2. |
|||
* See the COPYING file in the top-level directory. |
|||
* |
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
#include "sysemu/runstate-action.h" |
|||
#include "sysemu/watchdog.h" |
|||
#include "qemu/config-file.h" |
|||
#include "qapi/error.h" |
|||
#include "qemu/option_int.h" |
|||
|
|||
RebootAction reboot_action = REBOOT_ACTION_NONE; |
|||
ShutdownAction shutdown_action = SHUTDOWN_ACTION_POWEROFF; |
|||
PanicAction panic_action = PANIC_ACTION_POWEROFF; |
|||
|
|||
/*
|
|||
* Receives actions to be applied for specific guest events |
|||
* and sets the internal state as requested. |
|||
*/ |
|||
void qmp_set_action(bool has_reboot, RebootAction reboot, |
|||
bool has_shutdown, ShutdownAction shutdown, |
|||
bool has_panic, PanicAction panic, |
|||
bool has_watchdog, WatchdogAction watchdog, |
|||
Error **errp) |
|||
{ |
|||
if (has_reboot) { |
|||
reboot_action = reboot; |
|||
} |
|||
|
|||
if (has_panic) { |
|||
panic_action = panic; |
|||
} |
|||
|
|||
if (has_watchdog) { |
|||
qmp_watchdog_set_action(watchdog, errp); |
|||
} |
|||
|
|||
/* Process shutdown last, in case the panic action needs to be altered */ |
|||
if (has_shutdown) { |
|||
shutdown_action = shutdown; |
|||
} |
|||
} |
|||
@ -0,0 +1,812 @@ |
|||
/*
|
|||
* QEMU main system emulation loop |
|||
* |
|||
* Copyright (c) 2003-2020 QEMU contributors |
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
* THE SOFTWARE. |
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
#include "audio/audio.h" |
|||
#include "block/block.h" |
|||
#include "chardev/char.h" |
|||
#include "crypto/cipher.h" |
|||
#include "crypto/init.h" |
|||
#include "exec/cpu-common.h" |
|||
#include "exec/exec-all.h" |
|||
#include "exec/gdbstub.h" |
|||
#include "hw/boards.h" |
|||
#include "migration/misc.h" |
|||
#include "migration/postcopy-ram.h" |
|||
#include "monitor/monitor.h" |
|||
#include "net/net.h" |
|||
#include "net/vhost_net.h" |
|||
#include "qapi/error.h" |
|||
#include "qapi/qapi-commands-run-state.h" |
|||
#include "qapi/qapi-events-run-state.h" |
|||
#include "qemu-common.h" |
|||
#include "qemu/error-report.h" |
|||
#include "qemu/job.h" |
|||
#include "qemu/module.h" |
|||
#include "qemu/plugin.h" |
|||
#include "qemu/sockets.h" |
|||
#include "qemu/thread.h" |
|||
#include "qom/object.h" |
|||
#include "qom/object_interfaces.h" |
|||
#include "sysemu/cpus.h" |
|||
#include "sysemu/qtest.h" |
|||
#include "sysemu/replay.h" |
|||
#include "sysemu/reset.h" |
|||
#include "sysemu/runstate.h" |
|||
#include "sysemu/runstate-action.h" |
|||
#include "sysemu/sysemu.h" |
|||
#include "sysemu/tpm.h" |
|||
#include "trace.h" |
|||
|
|||
static NotifierList exit_notifiers = |
|||
NOTIFIER_LIST_INITIALIZER(exit_notifiers); |
|||
|
|||
static RunState current_run_state = RUN_STATE_PRELAUNCH; |
|||
|
|||
/* We use RUN_STATE__MAX but any invalid value will do */ |
|||
static RunState vmstop_requested = RUN_STATE__MAX; |
|||
static QemuMutex vmstop_lock; |
|||
|
|||
typedef struct { |
|||
RunState from; |
|||
RunState to; |
|||
} RunStateTransition; |
|||
|
|||
static const RunStateTransition runstate_transitions_def[] = { |
|||
{ RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE }, |
|||
|
|||
{ RUN_STATE_DEBUG, RUN_STATE_RUNNING }, |
|||
{ RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE }, |
|||
{ RUN_STATE_DEBUG, RUN_STATE_PRELAUNCH }, |
|||
|
|||
{ RUN_STATE_INMIGRATE, RUN_STATE_INTERNAL_ERROR }, |
|||
{ RUN_STATE_INMIGRATE, RUN_STATE_IO_ERROR }, |
|||
{ RUN_STATE_INMIGRATE, RUN_STATE_PAUSED }, |
|||
{ RUN_STATE_INMIGRATE, RUN_STATE_RUNNING }, |
|||
{ RUN_STATE_INMIGRATE, RUN_STATE_SHUTDOWN }, |
|||
{ RUN_STATE_INMIGRATE, RUN_STATE_SUSPENDED }, |
|||
{ RUN_STATE_INMIGRATE, RUN_STATE_WATCHDOG }, |
|||
{ RUN_STATE_INMIGRATE, RUN_STATE_GUEST_PANICKED }, |
|||
{ RUN_STATE_INMIGRATE, RUN_STATE_FINISH_MIGRATE }, |
|||
{ RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH }, |
|||
{ RUN_STATE_INMIGRATE, RUN_STATE_POSTMIGRATE }, |
|||
{ RUN_STATE_INMIGRATE, RUN_STATE_COLO }, |
|||
|
|||
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED }, |
|||
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE }, |
|||
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_PRELAUNCH }, |
|||
|
|||
{ RUN_STATE_IO_ERROR, RUN_STATE_RUNNING }, |
|||
{ RUN_STATE_IO_ERROR, RUN_STATE_FINISH_MIGRATE }, |
|||
{ RUN_STATE_IO_ERROR, RUN_STATE_PRELAUNCH }, |
|||
|
|||
{ RUN_STATE_PAUSED, RUN_STATE_RUNNING }, |
|||
{ RUN_STATE_PAUSED, RUN_STATE_FINISH_MIGRATE }, |
|||
{ RUN_STATE_PAUSED, RUN_STATE_POSTMIGRATE }, |
|||
{ RUN_STATE_PAUSED, RUN_STATE_PRELAUNCH }, |
|||
{ RUN_STATE_PAUSED, RUN_STATE_COLO}, |
|||
|
|||
{ RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING }, |
|||
{ RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE }, |
|||
{ RUN_STATE_POSTMIGRATE, RUN_STATE_PRELAUNCH }, |
|||
|
|||
{ RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING }, |
|||
{ RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE }, |
|||
{ RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE }, |
|||
|
|||
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING }, |
|||
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_PAUSED }, |
|||
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE }, |
|||
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_PRELAUNCH }, |
|||
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_COLO}, |
|||
|
|||
{ RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING }, |
|||
{ RUN_STATE_RESTORE_VM, RUN_STATE_PRELAUNCH }, |
|||
|
|||
{ RUN_STATE_COLO, RUN_STATE_RUNNING }, |
|||
|
|||
{ RUN_STATE_RUNNING, RUN_STATE_DEBUG }, |
|||
{ RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR }, |
|||
{ RUN_STATE_RUNNING, RUN_STATE_IO_ERROR }, |
|||
{ RUN_STATE_RUNNING, RUN_STATE_PAUSED }, |
|||
{ RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE }, |
|||
{ RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM }, |
|||
{ RUN_STATE_RUNNING, RUN_STATE_SAVE_VM }, |
|||
{ RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN }, |
|||
{ RUN_STATE_RUNNING, RUN_STATE_WATCHDOG }, |
|||
{ RUN_STATE_RUNNING, RUN_STATE_GUEST_PANICKED }, |
|||
{ RUN_STATE_RUNNING, RUN_STATE_COLO}, |
|||
|
|||
{ RUN_STATE_SAVE_VM, RUN_STATE_RUNNING }, |
|||
|
|||
{ RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED }, |
|||
{ RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE }, |
|||
{ RUN_STATE_SHUTDOWN, RUN_STATE_PRELAUNCH }, |
|||
{ RUN_STATE_SHUTDOWN, RUN_STATE_COLO }, |
|||
|
|||
{ RUN_STATE_DEBUG, RUN_STATE_SUSPENDED }, |
|||
{ RUN_STATE_RUNNING, RUN_STATE_SUSPENDED }, |
|||
{ RUN_STATE_SUSPENDED, RUN_STATE_RUNNING }, |
|||
{ RUN_STATE_SUSPENDED, RUN_STATE_FINISH_MIGRATE }, |
|||
{ RUN_STATE_SUSPENDED, RUN_STATE_PRELAUNCH }, |
|||
{ RUN_STATE_SUSPENDED, RUN_STATE_COLO}, |
|||
|
|||
{ RUN_STATE_WATCHDOG, RUN_STATE_RUNNING }, |
|||
{ RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE }, |
|||
{ RUN_STATE_WATCHDOG, RUN_STATE_PRELAUNCH }, |
|||
{ RUN_STATE_WATCHDOG, RUN_STATE_COLO}, |
|||
|
|||
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_RUNNING }, |
|||
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE }, |
|||
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_PRELAUNCH }, |
|||
|
|||
{ RUN_STATE__MAX, RUN_STATE__MAX }, |
|||
}; |
|||
|
|||
static bool runstate_valid_transitions[RUN_STATE__MAX][RUN_STATE__MAX]; |
|||
|
|||
bool runstate_check(RunState state) |
|||
{ |
|||
return current_run_state == state; |
|||
} |
|||
|
|||
bool runstate_store(char *str, size_t size) |
|||
{ |
|||
const char *state = RunState_str(current_run_state); |
|||
size_t len = strlen(state) + 1; |
|||
|
|||
if (len > size) { |
|||
return false; |
|||
} |
|||
memcpy(str, state, len); |
|||
return true; |
|||
} |
|||
|
|||
static void runstate_init(void) |
|||
{ |
|||
const RunStateTransition *p; |
|||
|
|||
memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions)); |
|||
for (p = &runstate_transitions_def[0]; p->from != RUN_STATE__MAX; p++) { |
|||
runstate_valid_transitions[p->from][p->to] = true; |
|||
} |
|||
|
|||
qemu_mutex_init(&vmstop_lock); |
|||
} |
|||
|
|||
/* This function will abort() on invalid state transitions */ |
|||
void runstate_set(RunState new_state) |
|||
{ |
|||
assert(new_state < RUN_STATE__MAX); |
|||
|
|||
trace_runstate_set(current_run_state, RunState_str(current_run_state), |
|||
new_state, RunState_str(new_state)); |
|||
|
|||
if (current_run_state == new_state) { |
|||
return; |
|||
} |
|||
|
|||
if (!runstate_valid_transitions[current_run_state][new_state]) { |
|||
error_report("invalid runstate transition: '%s' -> '%s'", |
|||
RunState_str(current_run_state), |
|||
RunState_str(new_state)); |
|||
abort(); |
|||
} |
|||
|
|||
current_run_state = new_state; |
|||
} |
|||
|
|||
int runstate_is_running(void) |
|||
{ |
|||
return runstate_check(RUN_STATE_RUNNING); |
|||
} |
|||
|
|||
bool runstate_needs_reset(void) |
|||
{ |
|||
return runstate_check(RUN_STATE_INTERNAL_ERROR) || |
|||
runstate_check(RUN_STATE_SHUTDOWN); |
|||
} |
|||
|
|||
StatusInfo *qmp_query_status(Error **errp) |
|||
{ |
|||
StatusInfo *info = g_malloc0(sizeof(*info)); |
|||
|
|||
info->running = runstate_is_running(); |
|||
info->singlestep = singlestep; |
|||
info->status = current_run_state; |
|||
|
|||
return info; |
|||
} |
|||
|
|||
bool qemu_vmstop_requested(RunState *r) |
|||
{ |
|||
qemu_mutex_lock(&vmstop_lock); |
|||
*r = vmstop_requested; |
|||
vmstop_requested = RUN_STATE__MAX; |
|||
qemu_mutex_unlock(&vmstop_lock); |
|||
return *r < RUN_STATE__MAX; |
|||
} |
|||
|
|||
void qemu_system_vmstop_request_prepare(void) |
|||
{ |
|||
qemu_mutex_lock(&vmstop_lock); |
|||
} |
|||
|
|||
void qemu_system_vmstop_request(RunState state) |
|||
{ |
|||
vmstop_requested = state; |
|||
qemu_mutex_unlock(&vmstop_lock); |
|||
qemu_notify_event(); |
|||
} |
|||
struct VMChangeStateEntry { |
|||
VMChangeStateHandler *cb; |
|||
void *opaque; |
|||
QTAILQ_ENTRY(VMChangeStateEntry) entries; |
|||
int priority; |
|||
}; |
|||
|
|||
static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head = |
|||
QTAILQ_HEAD_INITIALIZER(vm_change_state_head); |
|||
|
|||
/**
|
|||
* qemu_add_vm_change_state_handler_prio: |
|||
* @cb: the callback to invoke |
|||
* @opaque: user data passed to the callback |
|||
* @priority: low priorities execute first when the vm runs and the reverse is |
|||
* true when the vm stops |
|||
* |
|||
* Register a callback function that is invoked when the vm starts or stops |
|||
* running. |
|||
* |
|||
* Returns: an entry to be freed using qemu_del_vm_change_state_handler() |
|||
*/ |
|||
VMChangeStateEntry *qemu_add_vm_change_state_handler_prio( |
|||
VMChangeStateHandler *cb, void *opaque, int priority) |
|||
{ |
|||
VMChangeStateEntry *e; |
|||
VMChangeStateEntry *other; |
|||
|
|||
e = g_malloc0(sizeof(*e)); |
|||
e->cb = cb; |
|||
e->opaque = opaque; |
|||
e->priority = priority; |
|||
|
|||
/* Keep list sorted in ascending priority order */ |
|||
QTAILQ_FOREACH(other, &vm_change_state_head, entries) { |
|||
if (priority < other->priority) { |
|||
QTAILQ_INSERT_BEFORE(other, e, entries); |
|||
return e; |
|||
} |
|||
} |
|||
|
|||
QTAILQ_INSERT_TAIL(&vm_change_state_head, e, entries); |
|||
return e; |
|||
} |
|||
|
|||
VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb, |
|||
void *opaque) |
|||
{ |
|||
return qemu_add_vm_change_state_handler_prio(cb, opaque, 0); |
|||
} |
|||
|
|||
void qemu_del_vm_change_state_handler(VMChangeStateEntry *e) |
|||
{ |
|||
QTAILQ_REMOVE(&vm_change_state_head, e, entries); |
|||
g_free(e); |
|||
} |
|||
|
|||
void vm_state_notify(int running, RunState state) |
|||
{ |
|||
VMChangeStateEntry *e, *next; |
|||
|
|||
trace_vm_state_notify(running, state, RunState_str(state)); |
|||
|
|||
if (running) { |
|||
QTAILQ_FOREACH_SAFE(e, &vm_change_state_head, entries, next) { |
|||
e->cb(e->opaque, running, state); |
|||
} |
|||
} else { |
|||
QTAILQ_FOREACH_REVERSE_SAFE(e, &vm_change_state_head, entries, next) { |
|||
e->cb(e->opaque, running, state); |
|||
} |
|||
} |
|||
} |
|||
|
|||
static ShutdownCause reset_requested; |
|||
static ShutdownCause shutdown_requested; |
|||
static int shutdown_signal; |
|||
static pid_t shutdown_pid; |
|||
static int powerdown_requested; |
|||
static int debug_requested; |
|||
static int suspend_requested; |
|||
static WakeupReason wakeup_reason; |
|||
static NotifierList powerdown_notifiers = |
|||
NOTIFIER_LIST_INITIALIZER(powerdown_notifiers); |
|||
static NotifierList suspend_notifiers = |
|||
NOTIFIER_LIST_INITIALIZER(suspend_notifiers); |
|||
static NotifierList wakeup_notifiers = |
|||
NOTIFIER_LIST_INITIALIZER(wakeup_notifiers); |
|||
static NotifierList shutdown_notifiers = |
|||
NOTIFIER_LIST_INITIALIZER(shutdown_notifiers); |
|||
static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE); |
|||
|
|||
ShutdownCause qemu_shutdown_requested_get(void) |
|||
{ |
|||
return shutdown_requested; |
|||
} |
|||
|
|||
ShutdownCause qemu_reset_requested_get(void) |
|||
{ |
|||
return reset_requested; |
|||
} |
|||
|
|||
static int qemu_shutdown_requested(void) |
|||
{ |
|||
return qatomic_xchg(&shutdown_requested, SHUTDOWN_CAUSE_NONE); |
|||
} |
|||
|
|||
static void qemu_kill_report(void) |
|||
{ |
|||
if (!qtest_driver() && shutdown_signal) { |
|||
if (shutdown_pid == 0) { |
|||
/* This happens for eg ^C at the terminal, so it's worth
|
|||
* avoiding printing an odd message in that case. |
|||
*/ |
|||
error_report("terminating on signal %d", shutdown_signal); |
|||
} else { |
|||
char *shutdown_cmd = qemu_get_pid_name(shutdown_pid); |
|||
|
|||
error_report("terminating on signal %d from pid " FMT_pid " (%s)", |
|||
shutdown_signal, shutdown_pid, |
|||
shutdown_cmd ? shutdown_cmd : "<unknown process>"); |
|||
g_free(shutdown_cmd); |
|||
} |
|||
shutdown_signal = 0; |
|||
} |
|||
} |
|||
|
|||
static ShutdownCause qemu_reset_requested(void) |
|||
{ |
|||
ShutdownCause r = reset_requested; |
|||
|
|||
if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) { |
|||
reset_requested = SHUTDOWN_CAUSE_NONE; |
|||
return r; |
|||
} |
|||
return SHUTDOWN_CAUSE_NONE; |
|||
} |
|||
|
|||
static int qemu_suspend_requested(void) |
|||
{ |
|||
int r = suspend_requested; |
|||
if (r && replay_checkpoint(CHECKPOINT_SUSPEND_REQUESTED)) { |
|||
suspend_requested = 0; |
|||
return r; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
static WakeupReason qemu_wakeup_requested(void) |
|||
{ |
|||
return wakeup_reason; |
|||
} |
|||
|
|||
static int qemu_powerdown_requested(void) |
|||
{ |
|||
int r = powerdown_requested; |
|||
powerdown_requested = 0; |
|||
return r; |
|||
} |
|||
|
|||
static int qemu_debug_requested(void) |
|||
{ |
|||
int r = debug_requested; |
|||
debug_requested = 0; |
|||
return r; |
|||
} |
|||
|
|||
/*
|
|||
* Reset the VM. Issue an event unless @reason is SHUTDOWN_CAUSE_NONE. |
|||
*/ |
|||
void qemu_system_reset(ShutdownCause reason) |
|||
{ |
|||
MachineClass *mc; |
|||
|
|||
mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL; |
|||
|
|||
cpu_synchronize_all_states(); |
|||
|
|||
if (mc && mc->reset) { |
|||
mc->reset(current_machine); |
|||
} else { |
|||
qemu_devices_reset(); |
|||
} |
|||
if (reason && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) { |
|||
qapi_event_send_reset(shutdown_caused_by_guest(reason), reason); |
|||
} |
|||
cpu_synchronize_all_post_reset(); |
|||
} |
|||
|
|||
/*
|
|||
* Wake the VM after suspend. |
|||
*/ |
|||
static void qemu_system_wakeup(void) |
|||
{ |
|||
MachineClass *mc; |
|||
|
|||
mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL; |
|||
|
|||
if (mc && mc->wakeup) { |
|||
mc->wakeup(current_machine); |
|||
} |
|||
} |
|||
|
|||
void qemu_system_guest_panicked(GuestPanicInformation *info) |
|||
{ |
|||
qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed"); |
|||
|
|||
if (current_cpu) { |
|||
current_cpu->crash_occurred = true; |
|||
} |
|||
/*
|
|||
* TODO: Currently the available panic actions are: none, pause, and |
|||
* poweroff, but in principle debug and reset could be supported as well. |
|||
* Investigate any potential use cases for the unimplemented actions. |
|||
*/ |
|||
if (panic_action == PANIC_ACTION_PAUSE) { |
|||
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, |
|||
!!info, info); |
|||
vm_stop(RUN_STATE_GUEST_PANICKED); |
|||
} else if (panic_action == PANIC_ACTION_POWEROFF) { |
|||
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF, |
|||
!!info, info); |
|||
vm_stop(RUN_STATE_GUEST_PANICKED); |
|||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC); |
|||
} else { |
|||
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_RUN, |
|||
!!info, info); |
|||
} |
|||
|
|||
if (info) { |
|||
if (info->type == GUEST_PANIC_INFORMATION_TYPE_HYPER_V) { |
|||
qemu_log_mask(LOG_GUEST_ERROR, "\nHV crash parameters: (%#"PRIx64 |
|||
" %#"PRIx64" %#"PRIx64" %#"PRIx64" %#"PRIx64")\n", |
|||
info->u.hyper_v.arg1, |
|||
info->u.hyper_v.arg2, |
|||
info->u.hyper_v.arg3, |
|||
info->u.hyper_v.arg4, |
|||
info->u.hyper_v.arg5); |
|||
} else if (info->type == GUEST_PANIC_INFORMATION_TYPE_S390) { |
|||
qemu_log_mask(LOG_GUEST_ERROR, " on cpu %d: %s\n" |
|||
"PSW: 0x%016" PRIx64 " 0x%016" PRIx64"\n", |
|||
info->u.s390.core, |
|||
S390CrashReason_str(info->u.s390.reason), |
|||
info->u.s390.psw_mask, |
|||
info->u.s390.psw_addr); |
|||
} |
|||
qapi_free_GuestPanicInformation(info); |
|||
} |
|||
} |
|||
|
|||
void qemu_system_guest_crashloaded(GuestPanicInformation *info) |
|||
{ |
|||
qemu_log_mask(LOG_GUEST_ERROR, "Guest crash loaded"); |
|||
|
|||
qapi_event_send_guest_crashloaded(GUEST_PANIC_ACTION_RUN, |
|||
!!info, info); |
|||
|
|||
if (info) { |
|||
qapi_free_GuestPanicInformation(info); |
|||
} |
|||
} |
|||
|
|||
void qemu_system_reset_request(ShutdownCause reason) |
|||
{ |
|||
if (reboot_action == REBOOT_ACTION_SHUTDOWN && |
|||
reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) { |
|||
shutdown_requested = reason; |
|||
} else { |
|||
reset_requested = reason; |
|||
} |
|||
cpu_stop_current(); |
|||
qemu_notify_event(); |
|||
} |
|||
|
|||
static void qemu_system_suspend(void) |
|||
{ |
|||
pause_all_vcpus(); |
|||
notifier_list_notify(&suspend_notifiers, NULL); |
|||
runstate_set(RUN_STATE_SUSPENDED); |
|||
qapi_event_send_suspend(); |
|||
} |
|||
|
|||
void qemu_system_suspend_request(void) |
|||
{ |
|||
if (runstate_check(RUN_STATE_SUSPENDED)) { |
|||
return; |
|||
} |
|||
suspend_requested = 1; |
|||
cpu_stop_current(); |
|||
qemu_notify_event(); |
|||
} |
|||
|
|||
void qemu_register_suspend_notifier(Notifier *notifier) |
|||
{ |
|||
notifier_list_add(&suspend_notifiers, notifier); |
|||
} |
|||
|
|||
void qemu_system_wakeup_request(WakeupReason reason, Error **errp) |
|||
{ |
|||
trace_system_wakeup_request(reason); |
|||
|
|||
if (!runstate_check(RUN_STATE_SUSPENDED)) { |
|||
error_setg(errp, |
|||
"Unable to wake up: guest is not in suspended state"); |
|||
return; |
|||
} |
|||
if (!(wakeup_reason_mask & (1 << reason))) { |
|||
return; |
|||
} |
|||
runstate_set(RUN_STATE_RUNNING); |
|||
wakeup_reason = reason; |
|||
qemu_notify_event(); |
|||
} |
|||
|
|||
void qemu_system_wakeup_enable(WakeupReason reason, bool enabled) |
|||
{ |
|||
if (enabled) { |
|||
wakeup_reason_mask |= (1 << reason); |
|||
} else { |
|||
wakeup_reason_mask &= ~(1 << reason); |
|||
} |
|||
} |
|||
|
|||
void qemu_register_wakeup_notifier(Notifier *notifier) |
|||
{ |
|||
notifier_list_add(&wakeup_notifiers, notifier); |
|||
} |
|||
|
|||
static bool wakeup_suspend_enabled; |
|||
|
|||
void qemu_register_wakeup_support(void) |
|||
{ |
|||
wakeup_suspend_enabled = true; |
|||
} |
|||
|
|||
bool qemu_wakeup_suspend_enabled(void) |
|||
{ |
|||
return wakeup_suspend_enabled; |
|||
} |
|||
|
|||
void qemu_system_killed(int signal, pid_t pid) |
|||
{ |
|||
shutdown_signal = signal; |
|||
shutdown_pid = pid; |
|||
shutdown_action = SHUTDOWN_ACTION_POWEROFF; |
|||
|
|||
/* Cannot call qemu_system_shutdown_request directly because
|
|||
* we are in a signal handler. |
|||
*/ |
|||
shutdown_requested = SHUTDOWN_CAUSE_HOST_SIGNAL; |
|||
qemu_notify_event(); |
|||
} |
|||
|
|||
void qemu_system_shutdown_request(ShutdownCause reason) |
|||
{ |
|||
trace_qemu_system_shutdown_request(reason); |
|||
replay_shutdown_request(reason); |
|||
shutdown_requested = reason; |
|||
qemu_notify_event(); |
|||
} |
|||
|
|||
static void qemu_system_powerdown(void) |
|||
{ |
|||
qapi_event_send_powerdown(); |
|||
notifier_list_notify(&powerdown_notifiers, NULL); |
|||
} |
|||
|
|||
static void qemu_system_shutdown(ShutdownCause cause) |
|||
{ |
|||
qapi_event_send_shutdown(shutdown_caused_by_guest(cause), cause); |
|||
notifier_list_notify(&shutdown_notifiers, &cause); |
|||
} |
|||
|
|||
void qemu_system_powerdown_request(void) |
|||
{ |
|||
trace_qemu_system_powerdown_request(); |
|||
powerdown_requested = 1; |
|||
qemu_notify_event(); |
|||
} |
|||
|
|||
void qemu_register_powerdown_notifier(Notifier *notifier) |
|||
{ |
|||
notifier_list_add(&powerdown_notifiers, notifier); |
|||
} |
|||
|
|||
void qemu_register_shutdown_notifier(Notifier *notifier) |
|||
{ |
|||
notifier_list_add(&shutdown_notifiers, notifier); |
|||
} |
|||
|
|||
void qemu_system_debug_request(void) |
|||
{ |
|||
debug_requested = 1; |
|||
qemu_notify_event(); |
|||
} |
|||
|
|||
static bool main_loop_should_exit(void) |
|||
{ |
|||
RunState r; |
|||
ShutdownCause request; |
|||
|
|||
if (qemu_debug_requested()) { |
|||
vm_stop(RUN_STATE_DEBUG); |
|||
} |
|||
if (qemu_suspend_requested()) { |
|||
qemu_system_suspend(); |
|||
} |
|||
request = qemu_shutdown_requested(); |
|||
if (request) { |
|||
qemu_kill_report(); |
|||
qemu_system_shutdown(request); |
|||
if (shutdown_action == SHUTDOWN_ACTION_PAUSE) { |
|||
vm_stop(RUN_STATE_SHUTDOWN); |
|||
} else { |
|||
return true; |
|||
} |
|||
} |
|||
request = qemu_reset_requested(); |
|||
if (request) { |
|||
pause_all_vcpus(); |
|||
qemu_system_reset(request); |
|||
resume_all_vcpus(); |
|||
/*
|
|||
* runstate can change in pause_all_vcpus() |
|||
* as iothread mutex is unlocked |
|||
*/ |
|||
if (!runstate_check(RUN_STATE_RUNNING) && |
|||
!runstate_check(RUN_STATE_INMIGRATE) && |
|||
!runstate_check(RUN_STATE_FINISH_MIGRATE)) { |
|||
runstate_set(RUN_STATE_PRELAUNCH); |
|||
} |
|||
} |
|||
if (qemu_wakeup_requested()) { |
|||
pause_all_vcpus(); |
|||
qemu_system_wakeup(); |
|||
notifier_list_notify(&wakeup_notifiers, &wakeup_reason); |
|||
wakeup_reason = QEMU_WAKEUP_REASON_NONE; |
|||
resume_all_vcpus(); |
|||
qapi_event_send_wakeup(); |
|||
} |
|||
if (qemu_powerdown_requested()) { |
|||
qemu_system_powerdown(); |
|||
} |
|||
if (qemu_vmstop_requested(&r)) { |
|||
vm_stop(r); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
void qemu_main_loop(void) |
|||
{ |
|||
#ifdef CONFIG_PROFILER |
|||
int64_t ti; |
|||
#endif |
|||
while (!main_loop_should_exit()) { |
|||
#ifdef CONFIG_PROFILER |
|||
ti = profile_getclock(); |
|||
#endif |
|||
main_loop_wait(false); |
|||
#ifdef CONFIG_PROFILER |
|||
dev_time += profile_getclock() - ti; |
|||
#endif |
|||
} |
|||
} |
|||
|
|||
void qemu_add_exit_notifier(Notifier *notify) |
|||
{ |
|||
notifier_list_add(&exit_notifiers, notify); |
|||
} |
|||
|
|||
void qemu_remove_exit_notifier(Notifier *notify) |
|||
{ |
|||
notifier_remove(notify); |
|||
} |
|||
|
|||
static void qemu_run_exit_notifiers(void) |
|||
{ |
|||
notifier_list_notify(&exit_notifiers, NULL); |
|||
} |
|||
|
|||
void qemu_init_subsystems(void) |
|||
{ |
|||
Error *err; |
|||
|
|||
os_set_line_buffering(); |
|||
|
|||
module_call_init(MODULE_INIT_TRACE); |
|||
|
|||
qemu_init_cpu_list(); |
|||
qemu_init_cpu_loop(); |
|||
qemu_mutex_lock_iothread(); |
|||
|
|||
atexit(qemu_run_exit_notifiers); |
|||
|
|||
module_call_init(MODULE_INIT_QOM); |
|||
module_call_init(MODULE_INIT_MIGRATION); |
|||
|
|||
runstate_init(); |
|||
precopy_infrastructure_init(); |
|||
postcopy_infrastructure_init(); |
|||
monitor_init_globals(); |
|||
|
|||
if (qcrypto_init(&err) < 0) { |
|||
error_reportf_err(err, "cannot initialize crypto: "); |
|||
exit(1); |
|||
} |
|||
|
|||
os_setup_early_signal_handling(); |
|||
|
|||
bdrv_init_with_whitelist(); |
|||
socket_init(); |
|||
} |
|||
|
|||
|
|||
void qemu_cleanup(void) |
|||
{ |
|||
gdbserver_cleanup(); |
|||
|
|||
/*
|
|||
* cleaning up the migration object cancels any existing migration |
|||
* try to do this early so that it also stops using devices. |
|||
*/ |
|||
migration_shutdown(); |
|||
|
|||
/*
|
|||
* We must cancel all block jobs while the block layer is drained, |
|||
* or cancelling will be affected by throttling and thus may block |
|||
* for an extended period of time. |
|||
* vm_shutdown() will bdrv_drain_all(), so we may as well include |
|||
* it in the drained section. |
|||
* We do not need to end this section, because we do not want any |
|||
* requests happening from here on anyway. |
|||
*/ |
|||
bdrv_drain_all_begin(); |
|||
|
|||
/* No more vcpu or device emulation activity beyond this point */ |
|||
vm_shutdown(); |
|||
replay_finish(); |
|||
|
|||
job_cancel_sync_all(); |
|||
bdrv_close_all(); |
|||
|
|||
/* vhost-user must be cleaned up before chardevs. */ |
|||
tpm_cleanup(); |
|||
net_cleanup(); |
|||
audio_cleanup(); |
|||
monitor_cleanup(); |
|||
qemu_chr_cleanup(); |
|||
user_creatable_cleanup(); |
|||
/* TODO: unref root container, check all devices are ok */ |
|||
} |
|||
File diff suppressed because it is too large
@ -1,8 +0,0 @@ |
|||
#include "qemu/osdep.h" |
|||
#include "sysemu/sysemu.h" |
|||
|
|||
bool machine_init_done = true; |
|||
|
|||
void qemu_add_machine_init_done_notifier(Notifier *notify) |
|||
{ |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
#include "qemu/osdep.h" |
|||
#include "qapi/qmp/dispatch.h" |
|||
|
|||
bool qmp_command_available(const QmpCommand *cmd, Error **errp) |
|||
{ |
|||
return true; |
|||
} |
|||
Loading…
Reference in new issue