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