* 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é) -----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.c
This commit is contained in:
commit
af3f37319c
@ -2356,6 +2356,7 @@ M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
S: Maintained
|
||||
F: include/qemu/main-loop.h
|
||||
F: include/sysemu/runstate.h
|
||||
F: include/sysemu/runstate-action.h
|
||||
F: util/main-loop.c
|
||||
F: util/qemu-timer.c
|
||||
F: softmmu/vl.c
|
||||
@ -2364,6 +2365,7 @@ F: softmmu/cpus.c
|
||||
F: softmmu/cpu-throttle.c
|
||||
F: softmmu/cpu-timers.c
|
||||
F: softmmu/icount.c
|
||||
F: softmmu/runstate-action.c
|
||||
F: qapi/run-state.json
|
||||
|
||||
Read, Copy, Update (RCU)
|
||||
|
@ -745,7 +745,7 @@ static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start,
|
||||
assert(bmap_start % BITS_PER_LONG == 0);
|
||||
/* We should never do log_clear before log_sync */
|
||||
assert(mem->dirty_bmap);
|
||||
if (start_delta) {
|
||||
if (start_delta || bmap_npages - size / psize) {
|
||||
/* Slow path - we need to manipulate a temp bitmap */
|
||||
bmap_clear = bitmap_new(bmap_npages);
|
||||
bitmap_copy_with_src_offset(bmap_clear, mem->dirty_bmap,
|
||||
@ -758,7 +758,10 @@ static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start,
|
||||
bitmap_clear(bmap_clear, 0, start_delta);
|
||||
d.dirty_bitmap = bmap_clear;
|
||||
} else {
|
||||
/* Fast path - start address aligns well with BITS_PER_LONG */
|
||||
/*
|
||||
* Fast path - both start and size align well with BITS_PER_LONG
|
||||
* (or the end of memory slot)
|
||||
*/
|
||||
d.dirty_bitmap = mem->dirty_bmap + BIT_WORD(bmap_start);
|
||||
}
|
||||
|
||||
@ -2013,7 +2016,6 @@ static int kvm_init(MachineState *ms)
|
||||
const KVMCapabilityInfo *missing_cap;
|
||||
int ret;
|
||||
int type = 0;
|
||||
const char *kvm_type;
|
||||
uint64_t dirty_log_manual_caps;
|
||||
|
||||
s = KVM_STATE(ms->accelerator);
|
||||
@ -2069,13 +2071,11 @@ static int kvm_init(MachineState *ms)
|
||||
}
|
||||
s->as = g_new0(struct KVMAs, s->nr_as);
|
||||
|
||||
kvm_type = qemu_opt_get(qemu_get_machine_opts(), "kvm-type");
|
||||
if (mc->kvm_type) {
|
||||
if (object_property_find(OBJECT(current_machine), "kvm-type")) {
|
||||
g_autofree char *kvm_type = object_property_get_str(OBJECT(current_machine),
|
||||
"kvm-type",
|
||||
&error_abort);
|
||||
type = mc->kvm_type(ms, kvm_type);
|
||||
} else if (kvm_type) {
|
||||
ret = -EINVAL;
|
||||
fprintf(stderr, "Invalid argument kvm-type=%s\n", kvm_type);
|
||||
goto err;
|
||||
}
|
||||
|
||||
do {
|
||||
|
@ -685,7 +685,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
insns_left = MIN(0xffff, cpu->icount_budget);
|
||||
cpu_neg(cpu)->icount_decr.u16.low = insns_left;
|
||||
cpu->icount_extra = cpu->icount_budget - insns_left;
|
||||
if (!cpu->icount_extra) {
|
||||
if (!cpu->icount_extra && insns_left < tb->icount) {
|
||||
/* Execute any remaining instructions, then let the main loop
|
||||
* handle the next event.
|
||||
*/
|
||||
@ -724,7 +724,7 @@ int cpu_exec(CPUState *cpu)
|
||||
|
||||
/* prepare setjmp context for exception handling */
|
||||
if (sigsetjmp(cpu->jmp_env, 0) != 0) {
|
||||
#if defined(__clang__) || !QEMU_GNUC_PREREQ(4, 6)
|
||||
#if defined(__clang__)
|
||||
/* Some compilers wrongly smash all local variables after
|
||||
* siglongjmp. There were bug reports for gcc 4.5.0 and clang.
|
||||
* Reload essential local variables here for those compilers.
|
||||
|
@ -2379,7 +2379,7 @@ void dump_exec_info(void)
|
||||
qemu_printf("Translation buffer state:\n");
|
||||
/*
|
||||
* Report total code size including the padding and TB structs;
|
||||
* otherwise users might think "-tb-size" is not honoured.
|
||||
* otherwise users might think "-accel tcg,tb-size" is not honoured.
|
||||
* For avg host size we use the precise numbers from tb_tree_stats though.
|
||||
*/
|
||||
qemu_printf("gen code size %zu/%zu\n",
|
||||
|
@ -33,6 +33,13 @@
|
||||
|
||||
/* MUX driver for serial I/O splitting */
|
||||
|
||||
/*
|
||||
* Set to false by suspend_mux_open. Open events are delayed until
|
||||
* resume_mux_open. Usually suspend_mux_open is called before
|
||||
* command line processing and resume_mux_open afterwards.
|
||||
*/
|
||||
static bool muxes_opened = true;
|
||||
|
||||
/* Called with chr_write_lock held. */
|
||||
static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len)
|
||||
{
|
||||
@ -237,7 +244,7 @@ void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event)
|
||||
MuxChardev *d = MUX_CHARDEV(chr);
|
||||
int i;
|
||||
|
||||
if (!machine_init_done) {
|
||||
if (!muxes_opened) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -328,7 +335,7 @@ static void qemu_chr_open_mux(Chardev *chr,
|
||||
/* only default to opened state if we've realized the initial
|
||||
* set of muxes
|
||||
*/
|
||||
*be_opened = machine_init_done;
|
||||
*be_opened = muxes_opened;
|
||||
qemu_chr_fe_init(&d->chr, drv, errp);
|
||||
}
|
||||
|
||||
@ -360,19 +367,42 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
|
||||
* mux will receive CHR_EVENT_OPENED notifications for the BE
|
||||
* immediately.
|
||||
*/
|
||||
static int open_muxes(Chardev *chr)
|
||||
static void open_muxes(Chardev *chr)
|
||||
{
|
||||
/* send OPENED to all already-attached FEs */
|
||||
mux_chr_send_all_event(chr, CHR_EVENT_OPENED);
|
||||
|
||||
/*
|
||||
* mark mux as OPENED so any new FEs will immediately receive
|
||||
* OPENED event
|
||||
*/
|
||||
chr->be_open = 1;
|
||||
}
|
||||
|
||||
void suspend_mux_open(void)
|
||||
{
|
||||
muxes_opened = false;
|
||||
}
|
||||
|
||||
static int chardev_options_parsed_cb(Object *child, void *opaque)
|
||||
{
|
||||
Chardev *chr = (Chardev *)child;
|
||||
ChardevClass *class = CHARDEV_GET_CLASS(chr);
|
||||
|
||||
if (!chr->be_open && class->chr_options_parsed) {
|
||||
class->chr_options_parsed(chr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void resume_mux_open(void)
|
||||
{
|
||||
muxes_opened = true;
|
||||
object_child_foreach(get_chardevs_root(),
|
||||
chardev_options_parsed_cb, NULL);
|
||||
}
|
||||
|
||||
static void char_mux_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
ChardevClass *cc = CHARDEV_CLASS(oc);
|
||||
@ -383,7 +413,7 @@ static void char_mux_class_init(ObjectClass *oc, void *data)
|
||||
cc->chr_accept_input = mux_chr_accept_input;
|
||||
cc->chr_add_watch = mux_chr_add_watch;
|
||||
cc->chr_be_event = mux_chr_be_event;
|
||||
cc->chr_machine_done = open_muxes;
|
||||
cc->chr_options_parsed = open_muxes;
|
||||
cc->chr_update_read_handler = mux_chr_update_read_handlers;
|
||||
}
|
||||
|
||||
|
@ -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);
|
@ -25,7 +25,7 @@ chardev_ss.add(when: 'CONFIG_WIN32', if_true: files(
|
||||
|
||||
chardev_ss = chardev_ss.apply(config_host, strict: false)
|
||||
|
||||
softmmu_ss.add(files('chardev-sysemu.c', 'msmouse.c', 'wctablet.c', 'testdev.c'))
|
||||
softmmu_ss.add(files('msmouse.c', 'wctablet.c', 'testdev.c'))
|
||||
|
||||
chardev_modules = {}
|
||||
|
||||
|
3
configure
vendored
3
configure
vendored
@ -2137,7 +2137,6 @@ EOF
|
||||
# Check we support --no-pie first; we will need this for building ROMs.
|
||||
if compile_prog "-Werror -fno-pie" "-no-pie"; then
|
||||
CFLAGS_NOPIE="-fno-pie"
|
||||
LDFLAGS_NOPIE="-no-pie"
|
||||
fi
|
||||
|
||||
if test "$static" = "yes"; then
|
||||
@ -2153,7 +2152,6 @@ if test "$static" = "yes"; then
|
||||
fi
|
||||
elif test "$pie" = "no"; then
|
||||
CONFIGURE_CFLAGS="$CFLAGS_NOPIE $CONFIGURE_CFLAGS"
|
||||
CONFIGURE_LDFLAGS="$LDFLAGS_NOPIE $CONFIGURE_LDFLAGS"
|
||||
elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then
|
||||
CONFIGURE_CFLAGS="-fPIE -DPIE $CONFIGURE_CFLAGS"
|
||||
CONFIGURE_LDFLAGS="-pie $CONFIGURE_LDFLAGS"
|
||||
@ -6714,7 +6712,6 @@ echo "QEMU_CXXFLAGS=$QEMU_CXXFLAGS" >> $config_host_mak
|
||||
echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
|
||||
echo "GLIB_LIBS=$glib_libs" >> $config_host_mak
|
||||
echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak
|
||||
echo "LDFLAGS_NOPIE=$LDFLAGS_NOPIE" >> $config_host_mak
|
||||
echo "LD_I386_EMULATION=$ld_i386_emulation" >> $config_host_mak
|
||||
echo "EXESUF=$EXESUF" >> $config_host_mak
|
||||
echo "HOST_DSOSUF=$HOST_DSOSUF" >> $config_host_mak
|
||||
|
@ -9,7 +9,7 @@ endif
|
||||
# Check if tools are available to build documentation.
|
||||
build_docs = false
|
||||
if sphinx_build.found()
|
||||
SPHINX_ARGS = [sphinx_build]
|
||||
SPHINX_ARGS = ['env', 'CONFDIR=' + qemu_confdir, sphinx_build]
|
||||
# If we're making warnings fatal, apply this to Sphinx runs as well
|
||||
if get_option('werror')
|
||||
SPHINX_ARGS += [ '-W' ]
|
||||
|
@ -75,12 +75,6 @@ The ``pretty=on|off`` switch has no effect for HMP monitors, but is
|
||||
silently ignored. Using the switch with HMP monitors will become an
|
||||
error in the future.
|
||||
|
||||
``-realtime`` (since 4.1)
|
||||
'''''''''''''''''''''''''
|
||||
|
||||
The ``-realtime mlock=on|off`` argument has been replaced by the
|
||||
``-overcommit mem-lock=on|off`` argument.
|
||||
|
||||
RISC-V ``-bios`` (since 5.1)
|
||||
''''''''''''''''''''''''''''
|
||||
|
||||
@ -100,19 +94,6 @@ QEMU 5.1 has three options:
|
||||
to the user to load all the images they need.
|
||||
3. ``-bios <file>`` - Tells QEMU to load the specified file as the firmwrae.
|
||||
|
||||
``-tb-size`` option (since 5.0)
|
||||
'''''''''''''''''''''''''''''''
|
||||
|
||||
QEMU 5.0 introduced an alternative syntax to specify the size of the translation
|
||||
block cache, ``-accel tcg,tb-size=``. The new syntax deprecates the
|
||||
previously available ``-tb-size`` option.
|
||||
|
||||
``-show-cursor`` option (since 5.0)
|
||||
'''''''''''''''''''''''''''''''''''
|
||||
|
||||
Use ``-display sdl,show-cursor=on`` or
|
||||
``-display gtk,show-cursor=on`` instead.
|
||||
|
||||
``Configuring floppies with ``-global``
|
||||
'''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
@ -493,230 +474,3 @@ nanoMIPS ISA
|
||||
|
||||
The ``nanoMIPS`` ISA has never been upstreamed to any compiler toolchain.
|
||||
As it is hard to generate binaries for it, declare it deprecated.
|
||||
|
||||
|
||||
Recently 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``.
|
||||
|
||||
|
||||
QEMU Machine Protocol (QMP) commands
|
||||
------------------------------------
|
||||
|
||||
``block-dirty-bitmap-add`` "autoload" parameter (since 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 does not compile since v2.12.0. It was removed in 5.1.
|
||||
|
@ -35,5 +35,6 @@ Contents:
|
||||
targets
|
||||
security
|
||||
deprecated
|
||||
removed-features
|
||||
build-platforms
|
||||
license
|
||||
|
243
docs/system/removed-features.rst
Normal file
243
docs/system/removed-features.rst
Normal file
@ -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.
|
@ -45,6 +45,7 @@ ERST
|
||||
.params = "",
|
||||
.help = "quit the emulator",
|
||||
.cmd = hmp_quit,
|
||||
.flags = "p",
|
||||
},
|
||||
|
||||
SRST
|
||||
|
@ -1299,7 +1299,7 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
|
||||
info->kernel_filename = ms->kernel_filename;
|
||||
info->kernel_cmdline = ms->kernel_cmdline;
|
||||
info->initrd_filename = ms->initrd_filename;
|
||||
info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
|
||||
info->dtb_filename = ms->dtb;
|
||||
info->dtb_limit = 0;
|
||||
|
||||
/* Load the kernel. */
|
||||
|
@ -286,10 +286,9 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
|
||||
|
||||
void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
|
||||
{
|
||||
if (!runstate_check(RUN_STATE_PRECONFIG)) {
|
||||
error_setg(errp, "The command is permitted only in '%s' state",
|
||||
RunState_str(RUN_STATE_PRECONFIG));
|
||||
return;
|
||||
if (phase_check(PHASE_MACHINE_INITIALIZED)) {
|
||||
error_setg(errp, "The command is permitted only before the machine has been created");
|
||||
return;
|
||||
}
|
||||
|
||||
set_numa_options(MACHINE(qdev_get_machine()), cmd, errp);
|
||||
|
@ -16,16 +16,21 @@
|
||||
#include "sysemu/replay.h"
|
||||
#include "qemu/units.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-visit-common.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/numa.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/mem/nvdimm.h"
|
||||
#include "migration/global_state.h"
|
||||
#include "migration/vmstate.h"
|
||||
|
||||
GlobalProperty hw_compat_5_2[] = {};
|
||||
@ -216,6 +221,8 @@ GlobalProperty hw_compat_2_1[] = {
|
||||
};
|
||||
const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1);
|
||||
|
||||
MachineState *current_machine;
|
||||
|
||||
static char *machine_get_kernel(Object *obj, Error **errp)
|
||||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
@ -1167,17 +1174,16 @@ void machine_run_board_init(MachineState *machine)
|
||||
}
|
||||
|
||||
machine_class->init(machine);
|
||||
phase_advance(PHASE_MACHINE_INITIALIZED);
|
||||
}
|
||||
|
||||
static NotifierList machine_init_done_notifiers =
|
||||
NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
|
||||
|
||||
bool machine_init_done;
|
||||
|
||||
void qemu_add_machine_init_done_notifier(Notifier *notify)
|
||||
{
|
||||
notifier_list_add(&machine_init_done_notifiers, notify);
|
||||
if (machine_init_done) {
|
||||
if (phase_check(PHASE_MACHINE_READY)) {
|
||||
notify->notify(notify, NULL);
|
||||
}
|
||||
}
|
||||
@ -1187,10 +1193,48 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify)
|
||||
notifier_remove(notify);
|
||||
}
|
||||
|
||||
void qemu_run_machine_init_done_notifiers(void)
|
||||
void qdev_machine_creation_done(void)
|
||||
{
|
||||
machine_init_done = true;
|
||||
cpu_synchronize_all_post_init();
|
||||
|
||||
if (current_machine->boot_once) {
|
||||
qemu_boot_set(current_machine->boot_once, &error_fatal);
|
||||
qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order));
|
||||
}
|
||||
|
||||
/*
|
||||
* ok, initial machine setup is done, starting from now we can
|
||||
* only create hotpluggable devices
|
||||
*/
|
||||
phase_advance(PHASE_MACHINE_READY);
|
||||
qdev_assert_realized_properly();
|
||||
|
||||
/* TODO: once all bus devices are qdevified, this should be done
|
||||
* when bus is created by qdev.c */
|
||||
/*
|
||||
* TODO: If we had a main 'reset container' that the whole system
|
||||
* lived in, we could reset that using the multi-phase reset
|
||||
* APIs. For the moment, we just reset the sysbus, which will cause
|
||||
* all devices hanging off it (and all their child buses, recursively)
|
||||
* to be reset. Note that this will *not* reset any Device objects
|
||||
* which are not attached to some part of the qbus tree!
|
||||
*/
|
||||
qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default());
|
||||
|
||||
notifier_list_notify(&machine_init_done_notifiers, NULL);
|
||||
|
||||
if (rom_check_and_register_reset() != 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
replay_start();
|
||||
|
||||
/* This checkpoint is required by replay to separate prior clock
|
||||
reading from the other reads, because timer polling functions query
|
||||
clock values from the log. */
|
||||
replay_checkpoint(CHECKPOINT_RESET);
|
||||
qemu_system_reset(SHUTDOWN_CAUSE_NONE);
|
||||
register_global_state();
|
||||
}
|
||||
|
||||
static const TypeInfo machine_info = {
|
||||
|
@ -1,7 +1,6 @@
|
||||
# core qdev-related obj files, also used by *-user and unit tests
|
||||
hwcore_files = files(
|
||||
'bus.c',
|
||||
'fw-path-provider.c',
|
||||
'hotplug.c',
|
||||
'qdev-properties.c',
|
||||
'qdev.c',
|
||||
@ -25,6 +24,7 @@ common_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c'))
|
||||
common_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c'))
|
||||
|
||||
softmmu_ss.add(files(
|
||||
'fw-path-provider.c',
|
||||
'loader.c',
|
||||
'machine-hmp-cmds.c',
|
||||
'machine.c',
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include "migration/vmstate.h"
|
||||
#include "trace.h"
|
||||
|
||||
bool qdev_hotplug = false;
|
||||
static bool qdev_hot_added = false;
|
||||
bool qdev_hot_removed = false;
|
||||
|
||||
@ -404,7 +403,7 @@ void qdev_unrealize(DeviceState *dev)
|
||||
object_property_set_bool(OBJECT(dev), "realized", false, &error_abort);
|
||||
}
|
||||
|
||||
static int qdev_assert_realized_properly(Object *obj, void *opaque)
|
||||
static int qdev_assert_realized_properly_cb(Object *obj, void *opaque)
|
||||
{
|
||||
DeviceState *dev = DEVICE(object_dynamic_cast(obj, TYPE_DEVICE));
|
||||
DeviceClass *dc;
|
||||
@ -417,16 +416,10 @@ static int qdev_assert_realized_properly(Object *obj, void *opaque)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qdev_machine_creation_done(void)
|
||||
void qdev_assert_realized_properly(void)
|
||||
{
|
||||
/*
|
||||
* ok, initial machine setup is done, starting from now we can
|
||||
* only create hotpluggable devices
|
||||
*/
|
||||
qdev_hotplug = true;
|
||||
|
||||
object_child_foreach_recursive(object_get_root(),
|
||||
qdev_assert_realized_properly, NULL);
|
||||
qdev_assert_realized_properly_cb, NULL);
|
||||
}
|
||||
|
||||
bool qdev_machine_modified(void)
|
||||
@ -911,7 +904,7 @@ static void device_initfn(Object *obj)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
|
||||
if (qdev_hotplug) {
|
||||
if (phase_check(PHASE_MACHINE_READY)) {
|
||||
dev->hotplugged = 1;
|
||||
qdev_hot_added = true;
|
||||
}
|
||||
@ -1144,6 +1137,19 @@ Object *qdev_get_machine(void)
|
||||
return dev;
|
||||
}
|
||||
|
||||
static MachineInitPhase machine_phase;
|
||||
|
||||
bool phase_check(MachineInitPhase phase)
|
||||
{
|
||||
return machine_phase >= phase;
|
||||
}
|
||||
|
||||
void phase_advance(MachineInitPhase phase)
|
||||
{
|
||||
assert(machine_phase == phase - 1);
|
||||
machine_phase = phase;
|
||||
}
|
||||
|
||||
static const TypeInfo device_type_info = {
|
||||
.name = TYPE_DEVICE,
|
||||
.parent = TYPE_OBJECT,
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
#include "elf.h"
|
||||
#include "qemu/cutils.h"
|
||||
@ -116,16 +117,14 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
|
||||
const char *dtb_filename,
|
||||
void (*machine_cpu_reset)(MicroBlazeCPU *))
|
||||
{
|
||||
QemuOpts *machine_opts;
|
||||
const char *kernel_filename;
|
||||
const char *kernel_cmdline;
|
||||
const char *dtb_arg;
|
||||
char *filename = NULL;
|
||||
|
||||
machine_opts = qemu_get_machine_opts();
|
||||
kernel_filename = qemu_opt_get(machine_opts, "kernel");
|
||||
kernel_cmdline = qemu_opt_get(machine_opts, "append");
|
||||
dtb_arg = qemu_opt_get(machine_opts, "dtb");
|
||||
kernel_filename = current_machine->kernel_filename;
|
||||
kernel_cmdline = current_machine->kernel_cmdline;
|
||||
dtb_arg = current_machine->dtb;
|
||||
/* default to pcbios dtb as passed by machine_init */
|
||||
if (!dtb_arg && dtb_filename) {
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/loader.h"
|
||||
#include "elf.h"
|
||||
|
||||
@ -120,16 +121,14 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
|
||||
const char *dtb_filename,
|
||||
void (*machine_cpu_reset)(Nios2CPU *))
|
||||
{
|
||||
QemuOpts *machine_opts;
|
||||
const char *kernel_filename;
|
||||
const char *kernel_cmdline;
|
||||
const char *dtb_arg;
|
||||
char *filename = NULL;
|
||||
|
||||
machine_opts = qemu_get_machine_opts();
|
||||
kernel_filename = qemu_opt_get(machine_opts, "kernel");
|
||||
kernel_cmdline = qemu_opt_get(machine_opts, "append");
|
||||
dtb_arg = qemu_opt_get(machine_opts, "dtb");
|
||||
kernel_filename = current_machine->kernel_filename;
|
||||
kernel_cmdline = current_machine->kernel_cmdline;
|
||||
dtb_arg = current_machine->dtb;
|
||||
/* default to pcbios dtb as passed by machine_init */
|
||||
if (!dtb_arg) {
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
|
||||
|
@ -179,6 +179,7 @@ static uint64_t msix_table_mmio_read(void *opaque, hwaddr addr,
|
||||
{
|
||||
PCIDevice *dev = opaque;
|
||||
|
||||
assert(addr + size <= dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE);
|
||||
return pci_get_long(dev->msix_table + addr);
|
||||
}
|
||||
|
||||
@ -189,6 +190,8 @@ static void msix_table_mmio_write(void *opaque, hwaddr addr,
|
||||
int vector = addr / PCI_MSIX_ENTRY_SIZE;
|
||||
bool was_masked;
|
||||
|
||||
assert(addr + size <= dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE);
|
||||
|
||||
was_masked = msix_is_masked(dev, vector);
|
||||
pci_set_long(dev->msix_table + addr, val);
|
||||
msix_handle_mask_update(dev, vector, was_masked);
|
||||
|
@ -1062,7 +1062,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev,
|
||||
address_space_init(&pci_dev->bus_master_as,
|
||||
&pci_dev->bus_master_container_region, pci_dev->name);
|
||||
|
||||
if (qdev_hotplug) {
|
||||
if (phase_check(PHASE_MACHINE_READY)) {
|
||||
pci_init_bus_master(pci_dev);
|
||||
}
|
||||
pci_dev->irq_state = 0;
|
||||
|
@ -343,9 +343,8 @@ static int ppce500_load_device_tree(PPCE500MachineState *pms,
|
||||
pmc->pci_pio_base >> 32, pmc->pci_pio_base,
|
||||
0x0, 0x10000,
|
||||
};
|
||||
QemuOpts *machine_opts = qemu_get_machine_opts();
|
||||
const char *dtb_file = qemu_opt_get(machine_opts, "dtb");
|
||||
const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
|
||||
const char *dtb_file = machine->dtb;
|
||||
const char *toplevel_compat = machine->dt_compatible;
|
||||
|
||||
if (dtb_file) {
|
||||
char *filename;
|
||||
|
@ -3275,6 +3275,19 @@ static void spapr_instance_init(Object *obj)
|
||||
{
|
||||
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
|
||||
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
|
||||
MachineState *ms = MACHINE(spapr);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
|
||||
/*
|
||||
* NVDIMM support went live in 5.1 without considering that, in
|
||||
* other archs, the user needs to enable NVDIMM support with the
|
||||
* 'nvdimm' machine option and the default behavior is NVDIMM
|
||||
* support disabled. It is too late to roll back to the standard
|
||||
* behavior without breaking 5.1 guests.
|
||||
*/
|
||||
if (mc->nvdimm_supported) {
|
||||
ms->nvdimms_state->is_enabled = true;
|
||||
}
|
||||
|
||||
spapr->htab_fd = -1;
|
||||
spapr->use_hotplug_event_source = true;
|
||||
|
@ -27,10 +27,8 @@
|
||||
#include "hw/ppc/spapr_nvdimm.h"
|
||||
#include "hw/mem/nvdimm.h"
|
||||
#include "qemu/nvdimm-utils.h"
|
||||
#include "qemu/option.h"
|
||||
#include "hw/ppc/fdt.h"
|
||||
#include "qemu/range.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/ppc/spapr_numa.h"
|
||||
|
||||
bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
|
||||
@ -38,7 +36,6 @@ bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
|
||||
{
|
||||
const MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
|
||||
const MachineState *ms = MACHINE(hotplug_dev);
|
||||
const char *nvdimm_opt = qemu_opt_get(qemu_get_machine_opts(), "nvdimm");
|
||||
g_autofree char *uuidstr = NULL;
|
||||
QemuUUID uuid;
|
||||
int ret;
|
||||
@ -48,16 +45,7 @@ bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* NVDIMM support went live in 5.1 without considering that, in
|
||||
* other archs, the user needs to enable NVDIMM support with the
|
||||
* 'nvdimm' machine option and the default behavior is NVDIMM
|
||||
* support disabled. It is too late to roll back to the standard
|
||||
* behavior without breaking 5.1 guests. What we can do is to
|
||||
* ensure that, if the user sets nvdimm=off, we error out
|
||||
* regardless of being 5.1 or newer.
|
||||
*/
|
||||
if (!ms->nvdimms_state->is_enabled && nvdimm_opt) {
|
||||
if (!ms->nvdimms_state->is_enabled) {
|
||||
error_setg(errp, "nvdimm device found but 'nvdimm=off' was set");
|
||||
return false;
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ static int xilinx_load_device_tree(hwaddr addr,
|
||||
int r;
|
||||
const char *dtb_filename;
|
||||
|
||||
dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
|
||||
dtb_filename = current_machine->dtb;
|
||||
if (dtb_filename) {
|
||||
fdt = load_device_tree(dtb_filename, &fdt_size);
|
||||
if (!fdt) {
|
||||
|
@ -100,14 +100,12 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
|
||||
int cpu;
|
||||
uint32_t *cells;
|
||||
char *nodename;
|
||||
const char *dtb_filename;
|
||||
char ethclk_names[] = "pclk\0hclk";
|
||||
uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1;
|
||||
uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle;
|
||||
|
||||
dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
|
||||
if (dtb_filename) {
|
||||
fdt = s->fdt = load_device_tree(dtb_filename, &s->fdt_size);
|
||||
if (ms->dtb) {
|
||||
fdt = s->fdt = load_device_tree(ms->dtb, &s->fdt_size);
|
||||
if (!fdt) {
|
||||
error_report("load_device_tree() failed");
|
||||
exit(1);
|
||||
|
@ -181,7 +181,6 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
|
||||
{
|
||||
void *fdt;
|
||||
int i, cpu, socket;
|
||||
const char *dtb_filename;
|
||||
MachineState *mc = MACHINE(s);
|
||||
uint64_t addr, size;
|
||||
uint32_t *clint_cells, *plic_cells;
|
||||
@ -195,9 +194,8 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
|
||||
hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
|
||||
hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
|
||||
|
||||
dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
|
||||
if (dtb_filename) {
|
||||
fdt = s->fdt = load_device_tree(dtb_filename, &s->fdt_size);
|
||||
if (mc->dtb) {
|
||||
fdt = s->fdt = load_device_tree(mc->dtb, &s->fdt_size);
|
||||
if (!fdt) {
|
||||
error_report("load_device_tree() failed");
|
||||
exit(1);
|
||||
|
@ -170,6 +170,8 @@ static void scsi_dma_restart_bh(void *opaque)
|
||||
scsi_req_unref(req);
|
||||
}
|
||||
aio_context_release(blk_get_aio_context(s->conf.blk));
|
||||
/* Drop the reference that was acquired in scsi_dma_restart_cb */
|
||||
object_unref(OBJECT(s));
|
||||
}
|
||||
|
||||
void scsi_req_retry(SCSIRequest *req)
|
||||
@ -188,6 +190,8 @@ static void scsi_dma_restart_cb(void *opaque, int running, RunState state)
|
||||
}
|
||||
if (!s->bh) {
|
||||
AioContext *ctx = blk_get_aio_context(s->conf.blk);
|
||||
/* The reference is dropped in scsi_dma_restart_bh.*/
|
||||
object_ref(OBJECT(s));
|
||||
s->bh = aio_bh_new(ctx, scsi_dma_restart_bh, s);
|
||||
qemu_bh_schedule(s->bh);
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream)
|
||||
USBDevice *dev = ep->dev;
|
||||
USBBus *bus = usb_bus_from_device(dev);
|
||||
|
||||
if (!qdev_hotplug) {
|
||||
if (!phase_check(PHASE_MACHINE_READY)) {
|
||||
/*
|
||||
* This is machine init cold plug. No need to wakeup anyone,
|
||||
* all devices will be reset anyway. And trying to wakeup can
|
||||
|
@ -930,7 +930,7 @@ static int virtio_iommu_set_page_size_mask(IOMMUMemoryRegion *mr,
|
||||
* accept it. Having a different masks is possible but the guest will use
|
||||
* sub-optimal block sizes, so warn about it.
|
||||
*/
|
||||
if (qdev_hotplug) {
|
||||
if (phase_check(PHASE_MACHINE_READY)) {
|
||||
int new_granule = ctz64(new_mask);
|
||||
int cur_granule = ctz64(cur_mask);
|
||||
|
||||
|
@ -233,11 +233,10 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
|
||||
qemu_irq *extints;
|
||||
DriveInfo *dinfo;
|
||||
PFlashCFI01 *flash = NULL;
|
||||
QemuOpts *machine_opts = qemu_get_machine_opts();
|
||||
const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
|
||||
const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
|
||||
const char *dtb_filename = qemu_opt_get(machine_opts, "dtb");
|
||||
const char *initrd_filename = qemu_opt_get(machine_opts, "initrd");
|
||||
const char *kernel_filename = machine->kernel_filename;
|
||||
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||
const char *dtb_filename = machine->dtb;
|
||||
const char *initrd_filename = machine->initrd_filename;
|
||||
const unsigned system_io_size = 224 * MiB;
|
||||
uint32_t freq = 10000000;
|
||||
int n;
|
||||
|
@ -270,8 +270,7 @@ struct ChardevClass {
|
||||
void (*chr_set_echo)(Chardev *chr, bool echo);
|
||||
void (*chr_set_fe_open)(Chardev *chr, int fe_open);
|
||||
void (*chr_be_event)(Chardev *s, QEMUChrEvent event);
|
||||
/* Return 0 if succeeded, 1 if failed */
|
||||
int (*chr_machine_done)(Chardev *chr);
|
||||
void (*chr_options_parsed)(Chardev *chr);
|
||||
};
|
||||
|
||||
Chardev *qemu_chardev_new(const char *id, const char *typename,
|
||||
@ -283,6 +282,9 @@ extern int term_escape_char;
|
||||
GSource *qemu_chr_timeout_add_ms(Chardev *chr, guint ms,
|
||||
GSourceFunc func, void *private);
|
||||
|
||||
void suspend_mux_open(void);
|
||||
void resume_mux_open(void);
|
||||
|
||||
/* console.c */
|
||||
void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp);
|
||||
|
||||
|
@ -105,4 +105,7 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length);
|
||||
|
||||
#endif
|
||||
|
||||
/* vl.c */
|
||||
extern int singlestep;
|
||||
|
||||
#endif /* CPU_COMMON_H */
|
||||
|
@ -676,7 +676,4 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
|
||||
MemoryRegionSection *section);
|
||||
#endif
|
||||
|
||||
/* vl.c */
|
||||
extern int singlestep;
|
||||
|
||||
#endif
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#ifndef HW_POISON_H
|
||||
#define HW_POISON_H
|
||||
#ifdef __GNUC__
|
||||
|
||||
#pragma GCC poison TARGET_I386
|
||||
#pragma GCC poison TARGET_X86_64
|
||||
@ -93,4 +92,3 @@
|
||||
#pragma GCC poison CONFIG_SOFTMMU
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -780,12 +780,12 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev);
|
||||
|
||||
const char *qdev_fw_name(DeviceState *dev);
|
||||
|
||||
void qdev_assert_realized_properly(void);
|
||||
Object *qdev_get_machine(void);
|
||||
|
||||
/* FIXME: make this a link<> */
|
||||
bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp);
|
||||
|
||||
extern bool qdev_hotplug;
|
||||
extern bool qdev_hot_removed;
|
||||
|
||||
char *qdev_get_dev_path(DeviceState *dev);
|
||||
@ -811,4 +811,35 @@ void device_listener_unregister(DeviceListener *listener);
|
||||
*/
|
||||
bool qdev_should_hide_device(QemuOpts *opts);
|
||||
|
||||
typedef enum MachineInitPhase {
|
||||
/* current_machine is NULL. */
|
||||
PHASE_NO_MACHINE,
|
||||
|
||||
/* current_machine is not NULL, but current_machine->accel is NULL. */
|
||||
PHASE_MACHINE_CREATED,
|
||||
|
||||
/*
|
||||
* current_machine->accel is not NULL, but the machine properties have
|
||||
* not been validated and machine_class->init has not yet been called.
|
||||
*/
|
||||
PHASE_ACCEL_CREATED,
|
||||
|
||||
/*
|
||||
* machine_class->init has been called, thus creating any embedded
|
||||
* devices and validating machine properties. Devices created at
|
||||
* this time are considered to be cold-plugged.
|
||||
*/
|
||||
PHASE_MACHINE_INITIALIZED,
|
||||
|
||||
/*
|
||||
* QEMU is ready to start CPUs and devices created at this time
|
||||
* are considered to be hot-plugged. The monitor is not restricted
|
||||
* to "preconfig" commands.
|
||||
*/
|
||||
PHASE_MACHINE_READY,
|
||||
} MachineInitPhase;
|
||||
|
||||
extern bool phase_check(MachineInitPhase phase);
|
||||
extern void phase_advance(MachineInitPhase phase);
|
||||
|
||||
#endif
|
||||
|
@ -206,21 +206,12 @@ typedef struct __name##_back_ring __name##_back_ring_t
|
||||
#define RING_HAS_UNCONSUMED_RESPONSES(_r) \
|
||||
((_r)->sring->rsp_prod - (_r)->rsp_cons)
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({ \
|
||||
unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \
|
||||
unsigned int rsp = RING_SIZE(_r) - \
|
||||
((_r)->req_cons - (_r)->rsp_prod_pvt); \
|
||||
req < rsp ? req : rsp; \
|
||||
})
|
||||
#else
|
||||
/* Same as above, but without the nice GCC ({ ... }) syntax. */
|
||||
#define RING_HAS_UNCONSUMED_REQUESTS(_r) \
|
||||
((((_r)->sring->req_prod - (_r)->req_cons) < \
|
||||
(RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ? \
|
||||
((_r)->sring->req_prod - (_r)->req_cons) : \
|
||||
(RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt)))
|
||||
#endif
|
||||
|
||||
/* Direct access to individual ring elements, by index. */
|
||||
#define RING_GET_REQUEST(_r, _idx) \
|
||||
|
@ -48,6 +48,7 @@ void qmp_disable_command(QmpCommandList *cmds, const char *name);
|
||||
void qmp_enable_command(QmpCommandList *cmds, const char *name);
|
||||
|
||||
bool qmp_command_is_enabled(const QmpCommand *cmd);
|
||||
bool qmp_command_available(const QmpCommand *cmd, Error **errp);
|
||||
const char *qmp_command_name(const QmpCommand *cmd);
|
||||
bool qmp_has_success_response(const QmpCommand *cmd);
|
||||
QDict *qmp_error_response(Error *err);
|
||||
|
@ -241,23 +241,6 @@
|
||||
|
||||
#else /* __ATOMIC_RELAXED */
|
||||
|
||||
/*
|
||||
* We use GCC builtin if it's available, as that can use mfence on
|
||||
* 32-bit as well, e.g. if built with -march=pentium-m. However, on
|
||||
* i386 the spec is buggy, and the implementation followed it until
|
||||
* 4.3 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36793).
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#if !QEMU_GNUC_PREREQ(4, 4)
|
||||
#if defined __x86_64__
|
||||
#define smp_mb() ({ asm volatile("mfence" ::: "memory"); (void)0; })
|
||||
#else
|
||||
#define smp_mb() ({ asm volatile("lock; addl $0,0(%%esp) " ::: "memory"); (void)0; })
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __alpha__
|
||||
#define smp_read_barrier_depends() asm volatile("mb":::"memory")
|
||||
#endif
|
||||
|
@ -11,17 +11,6 @@
|
||||
#define QEMU_STATIC_ANALYSIS 1
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The macro QEMU_GNUC_PREREQ tests for minimum version of the GNU C compiler.
|
||||
| The code is a copy of SOFTFLOAT_GNUC_PREREQ, see softfloat-macros.h.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define QEMU_GNUC_PREREQ(maj, min) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
# define QEMU_GNUC_PREREQ(maj, min) 0
|
||||
#endif
|
||||
|
||||
#define QEMU_NORETURN __attribute__ ((__noreturn__))
|
||||
|
||||
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
@ -44,10 +33,6 @@
|
||||
#endif
|
||||
|
||||
#ifndef likely
|
||||
#if __GNUC__ < 3
|
||||
#define __builtin_expect(x, n) (x)
|
||||
#endif
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
@ -68,14 +53,10 @@
|
||||
(offsetof(container, field) + sizeof_field(container, field))
|
||||
|
||||
/* Convert from a base type to a parent type, with compile time checking. */
|
||||
#ifdef __GNUC__
|
||||
#define DO_UPCAST(type, field, dev) ( __extension__ ( { \
|
||||
char __attribute__((unused)) offset_must_be_zero[ \
|
||||
-offsetof(type, field)]; \
|
||||
container_of(dev, type, field);}))
|
||||
#else
|
||||
#define DO_UPCAST(type, field, dev) container_of(dev, type, field)
|
||||
#endif
|
||||
|
||||
#define typeof_field(type, field) typeof(((type *)0)->field)
|
||||
#define type_check(t1,t2) ((t1*)0 - (t2*)0)
|
||||
@ -103,21 +84,19 @@
|
||||
#define QEMU_BUILD_BUG_ON_ZERO(x) (sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)) - \
|
||||
sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)))
|
||||
|
||||
#if defined __GNUC__
|
||||
# if !QEMU_GNUC_PREREQ(4, 4)
|
||||
/* gcc versions before 4.4.x don't support gnu_printf, so use printf. */
|
||||
# define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m)))
|
||||
# else
|
||||
/* Use gnu_printf when supported (qemu uses standard format strings). */
|
||||
# define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
|
||||
# if defined(_WIN32)
|
||||
/* Map __printf__ to __gnu_printf__ because we want standard format strings
|
||||
* even when MinGW or GLib include files use __printf__. */
|
||||
# define __printf__ __gnu_printf__
|
||||
# endif
|
||||
# endif
|
||||
#if defined(__clang__)
|
||||
/* clang doesn't support gnu_printf, so use printf. */
|
||||
# define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m)))
|
||||
#else
|
||||
#define GCC_FMT_ATTR(n, m)
|
||||
/* Use gnu_printf (qemu uses standard format strings). */
|
||||
# define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
|
||||
# if defined(_WIN32)
|
||||
/*
|
||||
* Map __printf__ to __gnu_printf__ because we want standard format strings even
|
||||
* when MinGW or GLib include files use __printf__.
|
||||
*/
|
||||
# define __printf__ __gnu_printf__
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef __has_warning
|
||||
|
@ -45,7 +45,7 @@ static inline void qemu_plugin_add_opts(void)
|
||||
}
|
||||
|
||||
void qemu_plugin_opt_parse(const char *optarg, QemuPluginList *head);
|
||||
int qemu_plugin_load_list(QemuPluginList *head);
|
||||
int qemu_plugin_load_list(QemuPluginList *head, Error **errp);
|
||||
|
||||
union qemu_plugin_cb_sig {
|
||||
qemu_plugin_simple_cb_t simple;
|
||||
@ -199,7 +199,7 @@ static inline void qemu_plugin_opt_parse(const char *optarg,
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static inline int qemu_plugin_load_list(QemuPluginList *head)
|
||||
static inline int qemu_plugin_load_list(QemuPluginList *head, Error **errp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -28,13 +28,8 @@
|
||||
#endif
|
||||
#define QEMU_PLUGIN_LOCAL
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define QEMU_PLUGIN_EXPORT __attribute__((visibility("default")))
|
||||
#define QEMU_PLUGIN_LOCAL __attribute__((visibility("hidden")))
|
||||
#else
|
||||
#define QEMU_PLUGIN_EXPORT
|
||||
#define QEMU_PLUGIN_LOCAL
|
||||
#endif
|
||||
#define QEMU_PLUGIN_EXPORT __attribute__((visibility("default")))
|
||||
#define QEMU_PLUGIN_LOCAL __attribute__((visibility("hidden")))
|
||||
#endif
|
||||
|
||||
typedef uint64_t qemu_plugin_id_t;
|
||||
|
19
include/sysemu/runstate-action.h
Normal file
19
include/sysemu/runstate-action.h
Normal file
@ -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 */
|
@ -41,7 +41,6 @@ typedef enum WakeupReason {
|
||||
QEMU_WAKEUP_REASON_OTHER,
|
||||
} WakeupReason;
|
||||
|
||||
void qemu_exit_preconfig_request(void);
|
||||
void qemu_system_reset_request(ShutdownCause reason);
|
||||
void qemu_system_suspend_request(void);
|
||||
void qemu_register_suspend_notifier(Notifier *notifier);
|
||||
|
@ -16,14 +16,14 @@ extern bool qemu_uuid_set;
|
||||
void qemu_add_exit_notifier(Notifier *notify);
|
||||
void qemu_remove_exit_notifier(Notifier *notify);
|
||||
|
||||
extern bool machine_init_done;
|
||||
|
||||
void qemu_run_machine_init_done_notifiers(void);
|
||||
void qemu_add_machine_init_done_notifier(Notifier *notify);
|
||||
void qemu_remove_machine_init_done_notifier(Notifier *notify);
|
||||
|
||||
void configure_rtc(QemuOpts *opts);
|
||||
|
||||
void qemu_init_subsystems(void);
|
||||
|
||||
extern int autostart;
|
||||
|
||||
typedef enum {
|
||||
@ -43,7 +43,6 @@ extern int win2k_install_hack;
|
||||
extern int alt_grab;
|
||||
extern int ctrl_grab;
|
||||
extern int graphic_rotate;
|
||||
extern int no_shutdown;
|
||||
extern int old_param;
|
||||
extern int boot_menu;
|
||||
extern bool boot_strict;
|
||||
@ -103,8 +102,6 @@ typedef void QEMUBootSetHandler(void *opaque, const char *boot_order,
|
||||
void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque);
|
||||
void qemu_boot_set(const char *boot_order, Error **errp);
|
||||
|
||||
QemuOpts *qemu_get_machine_opts(void);
|
||||
|
||||
bool defaults_enabled(void);
|
||||
|
||||
void qemu_init(int argc, char **argv, char **envp);
|
||||
|
@ -671,9 +671,7 @@ int main(int argc, char **argv, char **envp)
|
||||
exit(1);
|
||||
}
|
||||
trace_init_file();
|
||||
if (qemu_plugin_load_list(&plugins)) {
|
||||
exit(1);
|
||||
}
|
||||
qemu_plugin_load_list(&plugins, &error_fatal);
|
||||
|
||||
/* Zero out regs */
|
||||
memset(regs, 0, sizeof(struct target_pt_regs));
|
||||
|
@ -24,7 +24,6 @@ struct syscallname {
|
||||
abi_long, abi_long, abi_long);
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
/*
|
||||
* It is possible that target doesn't have syscall that uses
|
||||
* following flags but we don't want the compiler to warn
|
||||
@ -32,9 +31,6 @@ struct syscallname {
|
||||
* functions. It is ok to keep them while not used.
|
||||
*/
|
||||
#define UNUSED __attribute__ ((unused))
|
||||
#else
|
||||
#define UNUSED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Structure used to translate flag values into strings. This is
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <dirent.h>
|
||||
#include "hw/qdev-core.h"
|
||||
#include "monitor-internal.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
@ -215,7 +216,7 @@ static bool cmd_can_preconfig(const HMPCommand *cmd)
|
||||
|
||||
static bool cmd_available(const HMPCommand *cmd)
|
||||
{
|
||||
return !runstate_check(RUN_STATE_PRECONFIG) || cmd_can_preconfig(cmd);
|
||||
return phase_check(PHASE_MACHINE_READY) || cmd_can_preconfig(cmd);
|
||||
}
|
||||
|
||||
static void help_cmd_dump_one(Monitor *mon,
|
||||
@ -658,8 +659,8 @@ static const HMPCommand *monitor_parse_command(MonitorHMP *hmp_mon,
|
||||
return NULL;
|
||||
}
|
||||
if (!cmd_available(cmd)) {
|
||||
monitor_printf(mon, "Command '%.*s' not available with -preconfig "
|
||||
"until after exit_preconfig.\n",
|
||||
monitor_printf(mon, "Command '%.*s' not available "
|
||||
"until machine initialization has completed.\n",
|
||||
(int)(p - cmdp_start), cmdp_start);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "ui/vnc.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/runstate-action.h"
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
@ -72,7 +73,7 @@ UuidInfo *qmp_query_uuid(Error **errp)
|
||||
|
||||
void qmp_quit(Error **errp)
|
||||
{
|
||||
no_shutdown = 0;
|
||||
shutdown_action = SHUTDOWN_ACTION_POWEROFF;
|
||||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
|
||||
}
|
||||
|
||||
@ -102,16 +103,6 @@ void qmp_system_powerdown(Error **errp)
|
||||
qemu_system_powerdown_request();
|
||||
}
|
||||
|
||||
void qmp_x_exit_preconfig(Error **errp)
|
||||
{
|
||||
if (!runstate_check(RUN_STATE_PRECONFIG)) {
|
||||
error_setg(errp, "The command is permitted only in '%s' state",
|
||||
RunState_str(RUN_STATE_PRECONFIG));
|
||||
return;
|
||||
}
|
||||
qemu_exit_preconfig_request();
|
||||
}
|
||||
|
||||
void qmp_cont(Error **errp)
|
||||
{
|
||||
BlockBackend *blk;
|
||||
|
@ -41,7 +41,6 @@ override CFLAGS += $(call cc-option, $(Wa)-32)
|
||||
|
||||
LD_I386_EMULATION ?= elf_i386
|
||||
override LDFLAGS = -m $(LD_I386_EMULATION) -T $(SRC_DIR)/flat.lds
|
||||
override LDFLAGS += $(LDFLAGS_NOPIE)
|
||||
|
||||
all: multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin pvh.bin
|
||||
|
||||
|
@ -150,7 +150,7 @@ static uint64_t xorshift64star(uint64_t x)
|
||||
return x * UINT64_C(2685821657736338717);
|
||||
}
|
||||
|
||||
static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info)
|
||||
static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info, Error **errp)
|
||||
{
|
||||
qemu_plugin_install_func_t install;
|
||||
struct qemu_plugin_ctx *ctx;
|
||||
@ -163,37 +163,37 @@ static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info)
|
||||
|
||||
ctx->handle = g_module_open(desc->path, G_MODULE_BIND_LOCAL);
|
||||
if (ctx->handle == NULL) {
|
||||
error_report("%s: %s", __func__, g_module_error());
|
||||
error_setg(errp, "Could not load plugin %s: %s", desc->path, g_module_error());
|
||||
goto err_dlopen;
|
||||
}
|
||||
|
||||
if (!g_module_symbol(ctx->handle, "qemu_plugin_install", &sym)) {
|
||||
error_report("%s: %s", __func__, g_module_error());
|
||||
error_setg(errp, "Could not load plugin %s: %s", desc->path, g_module_error());
|
||||
goto err_symbol;
|
||||
}
|
||||
install = (qemu_plugin_install_func_t) sym;
|
||||
/* symbol was found; it could be NULL though */
|
||||
if (install == NULL) {
|
||||
error_report("%s: %s: qemu_plugin_install is NULL",
|
||||
__func__, desc->path);
|
||||
error_setg(errp, "Could not load plugin %s: qemu_plugin_install is NULL",
|
||||
desc->path);
|
||||
goto err_symbol;
|
||||
}
|
||||
|
||||
if (!g_module_symbol(ctx->handle, "qemu_plugin_version", &sym)) {
|
||||
error_report("TCG plugin %s does not declare API version %s",
|
||||
desc->path, g_module_error());
|
||||
error_setg(errp, "Could not load plugin %s: plugin does not declare API version %s",
|
||||
desc->path, g_module_error());
|
||||
goto err_symbol;
|
||||
} else {
|
||||
int version = *(int *)sym;
|
||||
if (version < QEMU_PLUGIN_MIN_VERSION) {
|
||||
error_report("TCG plugin %s requires API version %d, but "
|
||||
"this QEMU supports only a minimum version of %d",
|
||||
desc->path, version, QEMU_PLUGIN_MIN_VERSION);
|
||||
error_setg(errp, "Could not load plugin %s: plugin requires API version %d, but "
|
||||
"this QEMU supports only a minimum version of %d",
|
||||
desc->path, version, QEMU_PLUGIN_MIN_VERSION);
|
||||
goto err_symbol;
|
||||
} else if (version > QEMU_PLUGIN_VERSION) {
|
||||
error_report("TCG plugin %s requires API version %d, but "
|
||||
"this QEMU supports only up to version %d",
|
||||
desc->path, version, QEMU_PLUGIN_VERSION);
|
||||
error_setg(errp, "Could not load plugin %s: plugin requires API version %d, but "
|
||||
"this QEMU supports only up to version %d",
|
||||
desc->path, version, QEMU_PLUGIN_VERSION);
|
||||
goto err_symbol;
|
||||
}
|
||||
}
|
||||
@ -220,8 +220,8 @@ static int plugin_load(struct qemu_plugin_desc *desc, const qemu_info_t *info)
|
||||
rc = install(ctx->id, info, desc->argc, desc->argv);
|
||||
ctx->installing = false;
|
||||
if (rc) {
|
||||
error_report("%s: qemu_plugin_install returned error code %d",
|
||||
__func__, rc);
|
||||
error_setg(errp, "Could not load plugin %s: qemu_plugin_install returned error code %d",
|
||||
desc->path, rc);
|
||||
/*
|
||||
* we cannot rely on the plugin doing its own cleanup, so
|
||||
* call a full uninstall if the plugin did not yet call it.
|
||||
@ -263,7 +263,7 @@ static void plugin_desc_free(struct qemu_plugin_desc *desc)
|
||||
* Note: the descriptor of each successfully installed plugin is removed
|
||||
* from the list given by @head.
|
||||
*/
|
||||
int qemu_plugin_load_list(QemuPluginList *head)
|
||||
int qemu_plugin_load_list(QemuPluginList *head, Error **errp)
|
||||
{
|
||||
struct qemu_plugin_desc *desc, *next;
|
||||
g_autofree qemu_info_t *info = g_new0(qemu_info_t, 1);
|
||||
@ -283,7 +283,7 @@ int qemu_plugin_load_list(QemuPluginList *head)
|
||||
QTAILQ_FOREACH_SAFE(desc, head, entry, next) {
|
||||
int err;
|
||||
|
||||
err = plugin_load(desc, info);
|
||||
err = plugin_load(desc, info, errp);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
@ -219,7 +219,8 @@
|
||||
# -> { "execute": "quit" }
|
||||
# <- { "return": {} }
|
||||
##
|
||||
{ 'command': 'quit' }
|
||||
{ 'command': 'quit',
|
||||
'allow-preconfig': true }
|
||||
|
||||
##
|
||||
# @MonitorMode:
|
||||
|
@ -167,10 +167,7 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (runstate_check(RUN_STATE_PRECONFIG) &&
|
||||
!(cmd->options & QCO_ALLOW_PRECONFIG)) {
|
||||
error_setg(&err, "The command '%s' isn't permitted in '%s' state",
|
||||
cmd->name, RunState_str(RUN_STATE_PRECONFIG));
|
||||
if (!qmp_command_available(cmd, &err)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -50,15 +50,12 @@
|
||||
# @colo: guest is paused to save/restore VM state under colo checkpoint,
|
||||
# VM can not get into this state unless colo capability is enabled
|
||||
# for migration. (since 2.8)
|
||||
# @preconfig: QEMU is paused before board specific init callback is executed.
|
||||
# The state is reachable only if the --preconfig CLI option is used.
|
||||
# (Since 3.0)
|
||||
##
|
||||
{ 'enum': 'RunState',
|
||||
'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',
|
||||
'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
|
||||
'running', 'save-vm', 'shutdown', 'suspended', 'watchdog',
|
||||
'guest-panicked', 'colo', 'preconfig' ] }
|
||||
'guest-panicked', 'colo' ] }
|
||||
|
||||
##
|
||||
# @ShutdownCause:
|
||||
@ -328,6 +325,46 @@
|
||||
'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none',
|
||||
'inject-nmi' ] }
|
||||
|
||||
##
|
||||
# @RebootAction:
|
||||
#
|
||||
# Possible QEMU actions upon guest reboot
|
||||
#
|
||||
# @none: Reset the VM
|
||||
#
|
||||
# @shutdown: Shutdown the VM and exit
|
||||
#
|
||||
# Since: 6.0
|
||||
##
|
||||
{ 'enum': 'RebootAction',
|
||||
'data': [ 'none', 'shutdown' ] }
|
||||
|
||||
##
|
||||
# @ShutdownAction:
|
||||
#
|
||||
# Possible QEMU actions upon guest shutdown
|
||||
#
|
||||
# @poweroff: Shutdown the VM and exit
|
||||
#
|
||||
# @pause: pause the VM#
|
||||
#
|
||||
# Since: 6.0
|
||||
##
|
||||
{ 'enum': 'ShutdownAction',
|
||||
'data': [ 'poweroff', 'pause' ] }
|
||||
|
||||
##
|
||||
# @PanicAction:
|
||||
#
|
||||
# @none: Continue VM execution
|
||||
#
|
||||
# @pause: Pause the VM
|
||||
#
|
||||
# Since: 6.0
|
||||
##
|
||||
{ 'enum': 'PanicAction',
|
||||
'data': [ 'poweroff', 'pause', 'none' ] }
|
||||
|
||||
##
|
||||
# @watchdog-set-action:
|
||||
#
|
||||
@ -337,6 +374,40 @@
|
||||
##
|
||||
{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
|
||||
|
||||
##
|
||||
# @set-action:
|
||||
#
|
||||
# Set the actions that will be taken by the emulator in response to guest
|
||||
# events.
|
||||
#
|
||||
# @reboot: @RebootAction action taken on guest reboot.
|
||||
#
|
||||
# @shutdown: @ShutdownAction action taken on guest shutdown.
|
||||
#
|
||||
# @panic: @PanicAction action taken on guest panic.
|
||||
#
|
||||
# @watchdog: @WatchdogAction action taken when watchdog timer expires .
|
||||
#
|
||||
# Returns: Nothing on success.
|
||||
#
|
||||
# Since: 6.0
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# -> { "execute": "set-action",
|
||||
# "arguments": { "reboot": "shutdown",
|
||||
# "shutdown" : "pause",
|
||||
# "panic": "pause",
|
||||
# "watchdog": "inject-nmi" } }
|
||||
# <- { "return": {} }
|
||||
##
|
||||
{ 'command': 'set-action',
|
||||
'data': { '*reboot': 'RebootAction',
|
||||
'*shutdown': 'ShutdownAction',
|
||||
'*panic': 'PanicAction',
|
||||
'*watchdog': 'WatchdogAction' },
|
||||
'allow-preconfig': true }
|
||||
|
||||
##
|
||||
# @GUEST_PANICKED:
|
||||
#
|
||||
|
@ -3713,17 +3713,6 @@ SRST
|
||||
Do not start CPU at startup (you must type 'c' in the monitor).
|
||||
ERST
|
||||
|
||||
DEF("realtime", HAS_ARG, QEMU_OPTION_realtime,
|
||||
"-realtime [mlock=on|off]\n"
|
||||
" run qemu with realtime features\n"
|
||||
" mlock=on|off controls mlock support (default: on)\n",
|
||||
QEMU_ARCH_ALL)
|
||||
SRST
|
||||
``-realtime mlock=on|off``
|
||||
Run qemu with realtime features. mlocking qemu and guest memory can
|
||||
be enabled via ``mlock=on`` (enabled by default).
|
||||
ERST
|
||||
|
||||
DEF("overcommit", HAS_ARG, QEMU_OPTION_overcommit,
|
||||
"-overcommit [mem-lock=on|off][cpu-pm=on|off]\n"
|
||||
" run qemu with overcommit hints\n"
|
||||
@ -3739,8 +3728,7 @@ SRST
|
||||
|
||||
Locking qemu and guest memory can be enabled via ``mem-lock=on``
|
||||
(disabled by default). This works when host memory is not
|
||||
overcommitted and reduces the worst-case latency for guest. This is
|
||||
equivalent to ``realtime``.
|
||||
overcommitted and reduces the worst-case latency for guest.
|
||||
|
||||
Guest ability to manage power state of host cpus (increasing latency
|
||||
for other processes on the same host cpu, but decreasing latency for
|
||||
@ -3894,6 +3882,31 @@ SRST
|
||||
changes to the disk image.
|
||||
ERST
|
||||
|
||||
DEF("action", HAS_ARG, QEMU_OPTION_action,
|
||||
"-action reboot=none|shutdown\n"
|
||||
" action when guest reboots [default=none]\n"
|
||||
"-action shutdown=poweroff|pause\n"
|
||||
" action when guest shuts down [default=poweroff]\n"
|
||||
"-action panic=poweroff|pause|none\n"
|
||||
" action when guest panics [default=poweroff]\n"
|
||||
"-action watchdog=reset|shutdown|poweroff|inject-nmi|pause|debug|none\n"
|
||||
" action when watchdog fires [default=reset]\n",
|
||||
QEMU_ARCH_ALL)
|
||||
SRST
|
||||
``-action event=action``
|
||||
The action parameter serves to modify QEMU's default behavior when
|
||||
certain guest events occur. It provides a generic method for specifying the
|
||||
same behaviors that are modified by the ``-no-reboot`` and ``-no-shutdown``
|
||||
parameters.
|
||||
|
||||
Examples:
|
||||
|
||||
``-action panic=none``
|
||||
``-action reboot=shutdown,shutdown=pause``
|
||||
``-watchdog i6300esb -action watchdog=pause``
|
||||
|
||||
ERST
|
||||
|
||||
DEF("loadvm", HAS_ARG, QEMU_OPTION_loadvm, \
|
||||
"-loadvm [tag|id]\n" \
|
||||
" start right away with a saved state (loadvm in monitor)\n",
|
||||
@ -4079,21 +4092,6 @@ SRST
|
||||
|
||||
ERST
|
||||
|
||||
DEF("show-cursor", 0, QEMU_OPTION_show_cursor, \
|
||||
"-show-cursor show cursor\n", QEMU_ARCH_ALL)
|
||||
SRST
|
||||
``-show-cursor``
|
||||
Show cursor.
|
||||
ERST
|
||||
|
||||
DEF("tb-size", HAS_ARG, QEMU_OPTION_tb_size, \
|
||||
"-tb-size n set TB size\n", QEMU_ARCH_ALL)
|
||||
SRST
|
||||
``-tb-size n``
|
||||
Set TCG translation block cache size. Deprecated, use
|
||||
'\ ``-accel tcg,tb-size=n``\ ' instead.
|
||||
ERST
|
||||
|
||||
DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \
|
||||
"-incoming tcp:[host]:port[,to=maxport][,ipv4][,ipv6]\n" \
|
||||
"-incoming rdma:host:port[,ipv4][,ipv6]\n" \
|
||||
|
@ -19,7 +19,6 @@
|
||||
*/
|
||||
|
||||
/* From qemu/compiler.h */
|
||||
#define QEMU_GNUC_PREREQ(maj, min) 1
|
||||
#define QEMU_NORETURN __attribute__ ((__noreturn__))
|
||||
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#define QEMU_SENTINEL __attribute__((sentinel))
|
||||
|
@ -12,6 +12,7 @@
|
||||
# Documentation
|
||||
docs/*
|
||||
*.rst
|
||||
*.rst.inc
|
||||
|
||||
# build system
|
||||
configure
|
||||
@ -28,9 +29,11 @@ qga/*.json
|
||||
|
||||
# headers
|
||||
*.h
|
||||
*.h.inc
|
||||
|
||||
# decoding tree specification
|
||||
*.decode
|
||||
|
||||
# code
|
||||
*.c
|
||||
*.c.inc
|
||||
|
@ -526,7 +526,7 @@ int qemu_fdt_add_subnode(void *fdt, const char *name)
|
||||
|
||||
void qemu_fdt_dumpdtb(void *fdt, int size)
|
||||
{
|
||||
const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb");
|
||||
const char *dumpdtb = current_machine->dumpdtb;
|
||||
|
||||
if (dumpdtb) {
|
||||
/* Dump the dtb to a file and quit */
|
||||
|
72
softmmu/globals.c
Normal file
72
softmmu/globals.c
Normal file
@ -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;
|
@ -1548,7 +1548,6 @@ void memory_region_init_ram_shared_nomigrate(MemoryRegion *mr,
|
||||
mr->terminates = true;
|
||||
mr->destructor = memory_region_destructor_ram;
|
||||
mr->ram_block = qemu_ram_alloc(size, share, mr, &err);
|
||||
mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
|
||||
if (err) {
|
||||
mr->size = int128_zero();
|
||||
object_unparent(OBJECT(mr));
|
||||
@ -1573,7 +1572,6 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
|
||||
mr->destructor = memory_region_destructor_ram;
|
||||
mr->ram_block = qemu_ram_alloc_resizeable(size, max_size, resized,
|
||||
mr, &err);
|
||||
mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
|
||||
if (err) {
|
||||
mr->size = int128_zero();
|
||||
object_unparent(OBJECT(mr));
|
||||
@ -1598,7 +1596,6 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
|
||||
mr->destructor = memory_region_destructor_ram;
|
||||
mr->align = align;
|
||||
mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path, &err);
|
||||
mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
|
||||
if (err) {
|
||||
mr->size = int128_zero();
|
||||
object_unparent(OBJECT(mr));
|
||||
@ -1622,7 +1619,6 @@ void memory_region_init_ram_from_fd(MemoryRegion *mr,
|
||||
mr->ram_block = qemu_ram_alloc_from_fd(size, mr,
|
||||
share ? RAM_SHARED : 0,
|
||||
fd, &err);
|
||||
mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
|
||||
if (err) {
|
||||
mr->size = int128_zero();
|
||||
object_unparent(OBJECT(mr));
|
||||
@ -1641,7 +1637,6 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
|
||||
mr->ram = true;
|
||||
mr->terminates = true;
|
||||
mr->destructor = memory_region_destructor_ram;
|
||||
mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
|
||||
|
||||
/* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */
|
||||
assert(ptr != NULL);
|
||||
@ -1661,7 +1656,7 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr,
|
||||
mr->ops = &ram_device_mem_ops;
|
||||
mr->opaque = mr;
|
||||
mr->destructor = memory_region_destructor_ram;
|
||||
mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
|
||||
|
||||
/* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */
|
||||
assert(ptr != NULL);
|
||||
mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal);
|
||||
@ -1819,6 +1814,11 @@ uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr)
|
||||
memory_region_is_iommu(mr))) {
|
||||
mask |= (1 << DIRTY_MEMORY_MIGRATION);
|
||||
}
|
||||
|
||||
if (tcg_enabled() && rb) {
|
||||
/* TCG only cares about dirty memory logging for RAM, not IOMMU. */
|
||||
mask |= (1 << DIRTY_MEMORY_CODE);
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,17 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
|
||||
'cpus.c',
|
||||
'cpu-throttle.c',
|
||||
'datadir.c',
|
||||
'globals.c',
|
||||
'physmem.c',
|
||||
'ioport.c',
|
||||
'rtc.c',
|
||||
'runstate.c',
|
||||
'memory.c',
|
||||
'memory_mapping.c',
|
||||
'qtest.c',
|
||||
'vl.c',
|
||||
'cpu-timers.c',
|
||||
'runstate-action.c',
|
||||
)])
|
||||
|
||||
specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: [files(
|
||||
|
@ -3255,6 +3255,7 @@ int64_t address_space_cache_init(MemoryRegionCache *cache,
|
||||
AddressSpaceDispatch *d;
|
||||
hwaddr l;
|
||||
MemoryRegion *mr;
|
||||
Int128 diff;
|
||||
|
||||
assert(len > 0);
|
||||
|
||||
@ -3263,6 +3264,15 @@ int64_t address_space_cache_init(MemoryRegionCache *cache,
|
||||
d = flatview_to_dispatch(cache->fv);
|
||||
cache->mrs = *address_space_translate_internal(d, addr, &cache->xlat, &l, true);
|
||||
|
||||
/*
|
||||
* cache->xlat is now relative to cache->mrs.mr, not to the section itself.
|
||||
* Take that into account to compute how many bytes are there between
|
||||
* cache->xlat and the end of the section.
|
||||
*/
|
||||
diff = int128_sub(cache->mrs.size,
|
||||
int128_make64(cache->xlat - cache->mrs.offset_within_region));
|
||||
l = int128_get64(int128_min(diff, int128_make64(l)));
|
||||
|
||||
mr = cache->mrs.mr;
|
||||
memory_region_ref(mr);
|
||||
if (memory_access_is_direct(mr, is_write)) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-commands-qdev.h"
|
||||
#include "qapi/qmp/dispatch.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/config-file.h"
|
||||
@ -244,7 +245,7 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp)
|
||||
|
||||
dc = DEVICE_CLASS(oc);
|
||||
if (!dc->user_creatable ||
|
||||
(qdev_hotplug && !dc->hotpluggable)) {
|
||||
(phase_check(PHASE_MACHINE_READY) && !dc->hotpluggable)) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
|
||||
"a pluggable device type");
|
||||
return NULL;
|
||||
@ -626,7 +627,7 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
if (qdev_hotplug && bus && !qbus_is_hotpluggable(bus)) {
|
||||
if (phase_check(PHASE_MACHINE_READY) && bus && !qbus_is_hotpluggable(bus)) {
|
||||
error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name);
|
||||
return NULL;
|
||||
}
|
||||
@ -640,15 +641,17 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
|
||||
dev = qdev_new(driver);
|
||||
|
||||
/* Check whether the hotplug is allowed by the machine */
|
||||
if (qdev_hotplug && !qdev_hotplug_allowed(dev, errp)) {
|
||||
goto err_del_dev;
|
||||
}
|
||||
if (phase_check(PHASE_MACHINE_READY)) {
|
||||
if (!qdev_hotplug_allowed(dev, errp)) {
|
||||
goto err_del_dev;
|
||||
}
|
||||
|
||||
if (!bus && qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) {
|
||||
/* No bus, no machine hotplug handler --> device is not hotpluggable */
|
||||
error_setg(errp, "Device '%s' can not be hotplugged on this machine",
|
||||
driver);
|
||||
goto err_del_dev;
|
||||
if (!bus && !qdev_get_machine_hotplug_handler(dev)) {
|
||||
/* No bus, no machine hotplug handler --> device is not hotpluggable */
|
||||
error_setg(errp, "Device '%s' can not be hotplugged on this machine",
|
||||
driver);
|
||||
goto err_del_dev;
|
||||
}
|
||||
}
|
||||
|
||||
qdev_set_id(dev, qemu_opts_id(opts));
|
||||
@ -983,3 +986,14 @@ int qemu_global_option(const char *str)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool qmp_command_available(const QmpCommand *cmd, Error **errp)
|
||||
{
|
||||
if (!phase_check(PHASE_MACHINE_READY) &&
|
||||
!(cmd->options & QCO_ALLOW_PRECONFIG)) {
|
||||
error_setg(errp, "The command '%s' is permitted only after machine initialization has completed",
|
||||
cmd->name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
46
softmmu/runstate-action.c
Normal file
46
softmmu/runstate-action.c
Normal file
@ -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;
|
||||
}
|
||||
}
|
812
softmmu/runstate.c
Normal file
812
softmmu/runstate.c
Normal file
@ -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 */
|
||||
}
|
1079
softmmu/vl.c
1079
softmmu/vl.c
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
{
|
||||
}
|
@ -21,7 +21,6 @@ stub_ss.add(files('iothread-lock.c'))
|
||||
stub_ss.add(files('isa-bus.c'))
|
||||
stub_ss.add(files('is-daemonized.c'))
|
||||
stub_ss.add(when: 'CONFIG_LINUX_AIO', if_true: files('linux-aio.c'))
|
||||
stub_ss.add(files('machine-init-done.c'))
|
||||
stub_ss.add(files('migr-blocker.c'))
|
||||
stub_ss.add(files('monitor.c'))
|
||||
stub_ss.add(files('monitor-core.c'))
|
||||
@ -29,6 +28,7 @@ stub_ss.add(files('pci-bus.c'))
|
||||
stub_ss.add(files('pci-host-piix.c'))
|
||||
stub_ss.add(files('qemu-timer-notify-cb.c'))
|
||||
stub_ss.add(files('qmp_memory_device.c'))
|
||||
stub_ss.add(files('qmp-command-available.c'))
|
||||
stub_ss.add(files('qtest.c'))
|
||||
stub_ss.add(files('ram-block.c'))
|
||||
stub_ss.add(files('ramfb.c'))
|
||||
|
7
stubs/qmp-command-available.c
Normal file
7
stubs/qmp-command-available.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qmp/dispatch.h"
|
||||
|
||||
bool qmp_command_available(const QmpCommand *cmd, Error **errp)
|
||||
{
|
||||
return true;
|
||||
}
|
@ -304,7 +304,7 @@ class Engine(object):
|
||||
argv_source += ["-mem-path", "/dev/shm",
|
||||
"-mem-prealloc"]
|
||||
if hardware._locked_pages:
|
||||
argv_source += ["-realtime", "mlock=on"]
|
||||
argv_source += ["-overcommit", "mem-lock=on"]
|
||||
if hardware._huge_pages:
|
||||
pass
|
||||
|
||||
|
@ -48,6 +48,55 @@ static void test_lp1878642_pci_bus_get_irq_level_assert(void)
|
||||
qtest_quit(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here a MemoryRegionCache pointed to an MMIO region but had a
|
||||
* larger size than the underlying region.
|
||||
*/
|
||||
static void test_mmio_oob_from_memory_region_cache(void)
|
||||
{
|
||||
QTestState *s;
|
||||
|
||||
s = qtest_init("-M pc-q35-5.2 -display none -m 512M "
|
||||
"-device virtio-scsi,num_queues=8,addr=03.0 ");
|
||||
|
||||
qtest_outl(s, 0xcf8, 0x80001811);
|
||||
qtest_outb(s, 0xcfc, 0x6e);
|
||||
qtest_outl(s, 0xcf8, 0x80001824);
|
||||
qtest_outl(s, 0xcf8, 0x80001813);
|
||||
qtest_outl(s, 0xcfc, 0xa080000);
|
||||
qtest_outl(s, 0xcf8, 0x80001802);
|
||||
qtest_outl(s, 0xcfc, 0x5a175a63);
|
||||
qtest_outb(s, 0x6e08, 0x9e);
|
||||
qtest_writeb(s, 0x9f003, 0xff);
|
||||
qtest_writeb(s, 0x9f004, 0x01);
|
||||
qtest_writeb(s, 0x9e012, 0x0e);
|
||||
qtest_writeb(s, 0x9e01b, 0x0e);
|
||||
qtest_writeb(s, 0x9f006, 0x01);
|
||||
qtest_writeb(s, 0x9f008, 0x01);
|
||||
qtest_writeb(s, 0x9f00a, 0x01);
|
||||
qtest_writeb(s, 0x9f00c, 0x01);
|
||||
qtest_writeb(s, 0x9f00e, 0x01);
|
||||
qtest_writeb(s, 0x9f010, 0x01);
|
||||
qtest_writeb(s, 0x9f012, 0x01);
|
||||
qtest_writeb(s, 0x9f014, 0x01);
|
||||
qtest_writeb(s, 0x9f016, 0x01);
|
||||
qtest_writeb(s, 0x9f018, 0x01);
|
||||
qtest_writeb(s, 0x9f01a, 0x01);
|
||||
qtest_writeb(s, 0x9f01c, 0x01);
|
||||
qtest_writeb(s, 0x9f01e, 0x01);
|
||||
qtest_writeb(s, 0x9f020, 0x01);
|
||||
qtest_writeb(s, 0x9f022, 0x01);
|
||||
qtest_writeb(s, 0x9f024, 0x01);
|
||||
qtest_writeb(s, 0x9f026, 0x01);
|
||||
qtest_writeb(s, 0x9f028, 0x01);
|
||||
qtest_writeb(s, 0x9f02a, 0x01);
|
||||
qtest_writeb(s, 0x9f02c, 0x01);
|
||||
qtest_writeb(s, 0x9f02e, 0x01);
|
||||
qtest_writeb(s, 0x9f030, 0x01);
|
||||
qtest_outb(s, 0x6e10, 0x00);
|
||||
qtest_quit(s);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *arch = qtest_get_arch();
|
||||
@ -59,6 +108,8 @@ int main(int argc, char **argv)
|
||||
test_lp1878263_megasas_zero_iov_cnt);
|
||||
qtest_add_func("fuzz/test_lp1878642_pci_bus_get_irq_level_assert",
|
||||
test_lp1878642_pci_bus_get_irq_level_assert);
|
||||
qtest_add_func("fuzz/test_mmio_oob_from_memory_region_cache",
|
||||
test_mmio_oob_from_memory_region_cache);
|
||||
}
|
||||
|
||||
return g_test_run();
|
||||
|
@ -11,13 +11,36 @@
|
||||
#include "libqos/libqtest.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
|
||||
static void test_panic_nopause(void)
|
||||
{
|
||||
uint8_t val;
|
||||
QDict *response, *data;
|
||||
QTestState *qts;
|
||||
|
||||
qts = qtest_init("-device pvpanic -action panic=none");
|
||||
|
||||
val = qtest_inb(qts, 0x505);
|
||||
g_assert_cmpuint(val, ==, 3);
|
||||
|
||||
qtest_outb(qts, 0x505, 0x1);
|
||||
|
||||
response = qtest_qmp_eventwait_ref(qts, "GUEST_PANICKED");
|
||||
g_assert(qdict_haskey(response, "data"));
|
||||
data = qdict_get_qdict(response, "data");
|
||||
g_assert(qdict_haskey(data, "action"));
|
||||
g_assert_cmpstr(qdict_get_str(data, "action"), ==, "run");
|
||||
qobject_unref(response);
|
||||
|
||||
qtest_quit(qts);
|
||||
}
|
||||
|
||||
static void test_panic(void)
|
||||
{
|
||||
uint8_t val;
|
||||
QDict *response, *data;
|
||||
QTestState *qts;
|
||||
|
||||
qts = qtest_init("-device pvpanic");
|
||||
qts = qtest_init("-device pvpanic -action panic=pause");
|
||||
|
||||
val = qtest_inb(qts, 0x505);
|
||||
g_assert_cmpuint(val, ==, 3);
|
||||
@ -40,6 +63,7 @@ int main(int argc, char **argv)
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
qtest_add_func("/pvpanic/panic", test_panic);
|
||||
qtest_add_func("/pvpanic/panic-nopause", test_panic_nopause);
|
||||
|
||||
ret = g_test_run();
|
||||
|
||||
|
@ -295,7 +295,7 @@ static void test_qmp_preconfig(void)
|
||||
rsp = qtest_qmp(qs, "{ 'execute': 'query-status' }");
|
||||
ret = qdict_get_qdict(rsp, "return");
|
||||
g_assert(ret);
|
||||
g_assert_cmpstr(qdict_get_try_str(ret, "status"), ==, "preconfig");
|
||||
g_assert_cmpstr(qdict_get_try_str(ret, "status"), ==, "prelaunch");
|
||||
qobject_unref(rsp);
|
||||
|
||||
/* exit preconfig state */
|
||||
|
@ -73,11 +73,9 @@ static void print_int64(int i, int64_t num)
|
||||
|
||||
#ifndef SNANF
|
||||
/* Signaling NaN macros, if supported. */
|
||||
# if __GNUC_PREREQ(3, 3)
|
||||
# define SNANF (__builtin_nansf (""))
|
||||
# define SNAN (__builtin_nans (""))
|
||||
# define SNANL (__builtin_nansl (""))
|
||||
# endif
|
||||
# define SNANF (__builtin_nansf (""))
|
||||
# define SNAN (__builtin_nans (""))
|
||||
# define SNANL (__builtin_nansl (""))
|
||||
#endif
|
||||
|
||||
float single_numbers[] = { -SNANF,
|
||||
|
@ -807,15 +807,6 @@ void fuse_remove_signal_handlers(struct fuse_session *se);
|
||||
*
|
||||
* On 32bit systems please add -D_FILE_OFFSET_BITS=64 to your compile flags!
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__) && \
|
||||
(__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && \
|
||||
!defined __cplusplus
|
||||
_Static_assert(sizeof(off_t) == 8, "fuse: off_t must be 64bit");
|
||||
#else
|
||||
struct _fuse_off_t_must_be_64bit_dummy_struct {
|
||||
unsigned _fuse_off_t_must_be_64bit:((sizeof(off_t) == 8) ? 1 : -1);
|
||||
};
|
||||
#endif
|
||||
QEMU_BUILD_BUG_ON(sizeof(off_t) != 8);
|
||||
|
||||
#endif /* FUSE_COMMON_H_ */
|
||||
|
@ -1345,7 +1345,7 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
|
||||
if (QTAILQ_EMPTY(&consoles)) {
|
||||
s->index = 0;
|
||||
QTAILQ_INSERT_TAIL(&consoles, s, next);
|
||||
} else if (console_type != GRAPHIC_CONSOLE || qdev_hotplug) {
|
||||
} else if (console_type != GRAPHIC_CONSOLE || phase_check(PHASE_MACHINE_READY)) {
|
||||
QemuConsole *last = QTAILQ_LAST(&consoles);
|
||||
s->index = last->index + 1;
|
||||
QTAILQ_INSERT_TAIL(&consoles, s, next);
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "ui/input.h"
|
||||
#include "ui/sdl2.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/runstate-action.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "ui/win32-kbd-hook.h"
|
||||
|
||||
@ -606,7 +607,7 @@ static void handle_windowevent(SDL_Event *ev)
|
||||
allow_close = false;
|
||||
}
|
||||
if (allow_close) {
|
||||
no_shutdown = 0;
|
||||
shutdown_action = SHUTDOWN_ACTION_POWEROFF;
|
||||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
|
||||
}
|
||||
} else {
|
||||
@ -653,7 +654,7 @@ void sdl2_poll_events(struct sdl2_console *scon)
|
||||
allow_close = false;
|
||||
}
|
||||
if (allow_close) {
|
||||
no_shutdown = 0;
|
||||
shutdown_action = SHUTDOWN_ACTION_POWEROFF;
|
||||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
|
||||
}
|
||||
break;
|
||||
|
@ -38,27 +38,19 @@
|
||||
#include "qemu/help_option.h"
|
||||
|
||||
/*
|
||||
* Extracts the name of an option from the parameter string (p points at the
|
||||
* Extracts the name of an option from the parameter string (@p points at the
|
||||
* first byte of the option name)
|
||||
*
|
||||
* The option name is delimited by delim (usually , or =) or the string end
|
||||
* and is copied into option. The caller is responsible for free'ing option
|
||||
* when no longer required.
|
||||
* The option name is @len characters long and is copied into @option. The
|
||||
* caller is responsible for free'ing @option when no longer required.
|
||||
*
|
||||
* The return value is the position of the delimiter/zero byte after the option
|
||||
* name in p.
|
||||
* name in @p.
|
||||
*/
|
||||
static const char *get_opt_name(const char *p, char **option, char delim)
|
||||
static const char *get_opt_name(const char *p, char **option, size_t len)
|
||||
{
|
||||
char *offset = strchr(p, delim);
|
||||
|
||||
if (offset) {
|
||||
*option = g_strndup(p, offset - p);
|
||||
return offset;
|
||||
} else {
|
||||
*option = g_strdup(p);
|
||||
return p + strlen(p);
|
||||
}
|
||||
*option = g_strndup(p, len);
|
||||
return p + len;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -468,16 +460,16 @@ static bool qemu_opt_parse(QemuOpt *opt, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static bool opts_accepts_any(const QemuOpts *opts)
|
||||
static bool opts_accepts_any(const QemuOptsList *list)
|
||||
{
|
||||
return opts->list->desc[0].name == NULL;
|
||||
return list->desc[0].name == NULL;
|
||||
}
|
||||
|
||||
int qemu_opt_unset(QemuOpts *opts, const char *name)
|
||||
{
|
||||
QemuOpt *opt = qemu_opt_find(opts, name);
|
||||
|
||||
assert(opts_accepts_any(opts));
|
||||
assert(opts_accepts_any(opts->list));
|
||||
|
||||
if (opt == NULL) {
|
||||
return -1;
|
||||
@ -508,9 +500,10 @@ static bool opt_validate(QemuOpt *opt, bool *help_wanted,
|
||||
Error **errp)
|
||||
{
|
||||
const QemuOptDesc *desc;
|
||||
const QemuOptsList *list = opt->opts->list;
|
||||
|
||||
desc = find_desc_by_name(opt->opts->list->desc, opt->name);
|
||||
if (!desc && !opts_accepts_any(opt->opts)) {
|
||||
desc = find_desc_by_name(list->desc, opt->name);
|
||||
if (!desc && !opts_accepts_any(list)) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, opt->name);
|
||||
if (help_wanted && is_help_option(opt->name)) {
|
||||
*help_wanted = true;
|
||||
@ -543,9 +536,10 @@ bool qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
|
||||
{
|
||||
QemuOpt *opt;
|
||||
const QemuOptDesc *desc;
|
||||
const QemuOptsList *list = opts->list;
|
||||
|
||||
desc = find_desc_by_name(opts->list->desc, name);
|
||||
if (!desc && !opts_accepts_any(opts)) {
|
||||
desc = find_desc_by_name(list->desc, name);
|
||||
if (!desc && !opts_accepts_any(list)) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, name);
|
||||
return false;
|
||||
}
|
||||
@ -565,9 +559,10 @@ bool qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val,
|
||||
{
|
||||
QemuOpt *opt;
|
||||
const QemuOptDesc *desc;
|
||||
const QemuOptsList *list = opts->list;
|
||||
|
||||
desc = find_desc_by_name(opts->list->desc, name);
|
||||
if (!desc && !opts_accepts_any(opts)) {
|
||||
desc = find_desc_by_name(list->desc, name);
|
||||
if (!desc && !opts_accepts_any(list)) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, name);
|
||||
return false;
|
||||
}
|
||||
@ -766,12 +761,11 @@ static const char *get_opt_name_value(const char *params,
|
||||
const char *firstname,
|
||||
char **name, char **value)
|
||||
{
|
||||
const char *p, *pe, *pc;
|
||||
const char *p;
|
||||
size_t len;
|
||||
|
||||
pe = strchr(params, '=');
|
||||
pc = strchr(params, ',');
|
||||
|
||||
if (!pe || (pc && pc < pe)) {
|
||||
len = strcspn(params, "=,");
|
||||
if (params[len] != '=') {
|
||||
/* found "foo,more" */
|
||||
if (firstname) {
|
||||
/* implicitly named first option */
|
||||
@ -779,7 +773,7 @@ static const char *get_opt_name_value(const char *params,
|
||||
p = get_opt_value(params, value);
|
||||
} else {
|
||||
/* option without value, must be a flag */
|
||||
p = get_opt_name(params, name, ',');
|
||||
p = get_opt_name(params, name, len);
|
||||
if (strncmp(*name, "no", 2) == 0) {
|
||||
memmove(*name, *name + 2, strlen(*name + 2) + 1);
|
||||
*value = g_strdup("off");
|
||||
@ -789,7 +783,7 @@ static const char *get_opt_name_value(const char *params,
|
||||
}
|
||||
} else {
|
||||
/* found "foo=bar,more" */
|
||||
p = get_opt_name(params, name, '=');
|
||||
p = get_opt_name(params, name, len);
|
||||
assert(*p == '=');
|
||||
p++;
|
||||
p = get_opt_value(p, value);
|
||||
@ -1116,7 +1110,7 @@ bool qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
|
||||
{
|
||||
QemuOpt *opt;
|
||||
|
||||
assert(opts_accepts_any(opts));
|
||||
assert(opts_accepts_any(opts->list));
|
||||
|
||||
QTAILQ_FOREACH(opt, &opts->head, next) {
|
||||
opt->desc = find_desc_by_name(desc, opt->name);
|
||||
|
Loading…
Reference in New Issue
Block a user