mirror of https://github.com/proxmox/mirror_qemu
* 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.cmaster
commit
af3f37319c
|
@ -2356,6 +2356,7 @@ M: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: include/qemu/main-loop.h
|
F: include/qemu/main-loop.h
|
||||||
F: include/sysemu/runstate.h
|
F: include/sysemu/runstate.h
|
||||||
|
F: include/sysemu/runstate-action.h
|
||||||
F: util/main-loop.c
|
F: util/main-loop.c
|
||||||
F: util/qemu-timer.c
|
F: util/qemu-timer.c
|
||||||
F: softmmu/vl.c
|
F: softmmu/vl.c
|
||||||
|
@ -2364,6 +2365,7 @@ F: softmmu/cpus.c
|
||||||
F: softmmu/cpu-throttle.c
|
F: softmmu/cpu-throttle.c
|
||||||
F: softmmu/cpu-timers.c
|
F: softmmu/cpu-timers.c
|
||||||
F: softmmu/icount.c
|
F: softmmu/icount.c
|
||||||
|
F: softmmu/runstate-action.c
|
||||||
F: qapi/run-state.json
|
F: qapi/run-state.json
|
||||||
|
|
||||||
Read, Copy, Update (RCU)
|
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);
|
assert(bmap_start % BITS_PER_LONG == 0);
|
||||||
/* We should never do log_clear before log_sync */
|
/* We should never do log_clear before log_sync */
|
||||||
assert(mem->dirty_bmap);
|
assert(mem->dirty_bmap);
|
||||||
if (start_delta) {
|
if (start_delta || bmap_npages - size / psize) {
|
||||||
/* Slow path - we need to manipulate a temp bitmap */
|
/* Slow path - we need to manipulate a temp bitmap */
|
||||||
bmap_clear = bitmap_new(bmap_npages);
|
bmap_clear = bitmap_new(bmap_npages);
|
||||||
bitmap_copy_with_src_offset(bmap_clear, mem->dirty_bmap,
|
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);
|
bitmap_clear(bmap_clear, 0, start_delta);
|
||||||
d.dirty_bitmap = bmap_clear;
|
d.dirty_bitmap = bmap_clear;
|
||||||
} else {
|
} 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);
|
d.dirty_bitmap = mem->dirty_bmap + BIT_WORD(bmap_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2013,7 +2016,6 @@ static int kvm_init(MachineState *ms)
|
||||||
const KVMCapabilityInfo *missing_cap;
|
const KVMCapabilityInfo *missing_cap;
|
||||||
int ret;
|
int ret;
|
||||||
int type = 0;
|
int type = 0;
|
||||||
const char *kvm_type;
|
|
||||||
uint64_t dirty_log_manual_caps;
|
uint64_t dirty_log_manual_caps;
|
||||||
|
|
||||||
s = KVM_STATE(ms->accelerator);
|
s = KVM_STATE(ms->accelerator);
|
||||||
|
@ -2069,13 +2071,11 @@ static int kvm_init(MachineState *ms)
|
||||||
}
|
}
|
||||||
s->as = g_new0(struct KVMAs, s->nr_as);
|
s->as = g_new0(struct KVMAs, s->nr_as);
|
||||||
|
|
||||||
kvm_type = qemu_opt_get(qemu_get_machine_opts(), "kvm-type");
|
if (object_property_find(OBJECT(current_machine), "kvm-type")) {
|
||||||
if (mc->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);
|
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 {
|
do {
|
||||||
|
|
|
@ -685,7 +685,7 @@ static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb,
|
||||||
insns_left = MIN(0xffff, cpu->icount_budget);
|
insns_left = MIN(0xffff, cpu->icount_budget);
|
||||||
cpu_neg(cpu)->icount_decr.u16.low = insns_left;
|
cpu_neg(cpu)->icount_decr.u16.low = insns_left;
|
||||||
cpu->icount_extra = cpu->icount_budget - 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
|
/* Execute any remaining instructions, then let the main loop
|
||||||
* handle the next event.
|
* handle the next event.
|
||||||
*/
|
*/
|
||||||
|
@ -724,7 +724,7 @@ int cpu_exec(CPUState *cpu)
|
||||||
|
|
||||||
/* prepare setjmp context for exception handling */
|
/* prepare setjmp context for exception handling */
|
||||||
if (sigsetjmp(cpu->jmp_env, 0) != 0) {
|
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
|
/* Some compilers wrongly smash all local variables after
|
||||||
* siglongjmp. There were bug reports for gcc 4.5.0 and clang.
|
* siglongjmp. There were bug reports for gcc 4.5.0 and clang.
|
||||||
* Reload essential local variables here for those compilers.
|
* Reload essential local variables here for those compilers.
|
||||||
|
|
|
@ -2379,7 +2379,7 @@ void dump_exec_info(void)
|
||||||
qemu_printf("Translation buffer state:\n");
|
qemu_printf("Translation buffer state:\n");
|
||||||
/*
|
/*
|
||||||
* Report total code size including the padding and TB structs;
|
* 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.
|
* For avg host size we use the precise numbers from tb_tree_stats though.
|
||||||
*/
|
*/
|
||||||
qemu_printf("gen code size %zu/%zu\n",
|
qemu_printf("gen code size %zu/%zu\n",
|
||||||
|
|
|
@ -33,6 +33,13 @@
|
||||||
|
|
||||||
/* MUX driver for serial I/O splitting */
|
/* 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. */
|
/* Called with chr_write_lock held. */
|
||||||
static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len)
|
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);
|
MuxChardev *d = MUX_CHARDEV(chr);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!machine_init_done) {
|
if (!muxes_opened) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,7 +335,7 @@ static void qemu_chr_open_mux(Chardev *chr,
|
||||||
/* only default to opened state if we've realized the initial
|
/* only default to opened state if we've realized the initial
|
||||||
* set of muxes
|
* set of muxes
|
||||||
*/
|
*/
|
||||||
*be_opened = machine_init_done;
|
*be_opened = muxes_opened;
|
||||||
qemu_chr_fe_init(&d->chr, drv, errp);
|
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
|
* mux will receive CHR_EVENT_OPENED notifications for the BE
|
||||||
* immediately.
|
* immediately.
|
||||||
*/
|
*/
|
||||||
static int open_muxes(Chardev *chr)
|
static void open_muxes(Chardev *chr)
|
||||||
{
|
{
|
||||||
/* send OPENED to all already-attached FEs */
|
/* send OPENED to all already-attached FEs */
|
||||||
mux_chr_send_all_event(chr, CHR_EVENT_OPENED);
|
mux_chr_send_all_event(chr, CHR_EVENT_OPENED);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mark mux as OPENED so any new FEs will immediately receive
|
* mark mux as OPENED so any new FEs will immediately receive
|
||||||
* OPENED event
|
* OPENED event
|
||||||
*/
|
*/
|
||||||
chr->be_open = 1;
|
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;
|
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)
|
static void char_mux_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
ChardevClass *cc = CHARDEV_CLASS(oc);
|
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_accept_input = mux_chr_accept_input;
|
||||||
cc->chr_add_watch = mux_chr_add_watch;
|
cc->chr_add_watch = mux_chr_add_watch;
|
||||||
cc->chr_be_event = mux_chr_be_event;
|
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;
|
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)
|
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 = {}
|
chardev_modules = {}
|
||||||
|
|
||||||
|
|
|
@ -2137,7 +2137,6 @@ EOF
|
||||||
# Check we support --no-pie first; we will need this for building ROMs.
|
# Check we support --no-pie first; we will need this for building ROMs.
|
||||||
if compile_prog "-Werror -fno-pie" "-no-pie"; then
|
if compile_prog "-Werror -fno-pie" "-no-pie"; then
|
||||||
CFLAGS_NOPIE="-fno-pie"
|
CFLAGS_NOPIE="-fno-pie"
|
||||||
LDFLAGS_NOPIE="-no-pie"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$static" = "yes"; then
|
if test "$static" = "yes"; then
|
||||||
|
@ -2153,7 +2152,6 @@ if test "$static" = "yes"; then
|
||||||
fi
|
fi
|
||||||
elif test "$pie" = "no"; then
|
elif test "$pie" = "no"; then
|
||||||
CONFIGURE_CFLAGS="$CFLAGS_NOPIE $CONFIGURE_CFLAGS"
|
CONFIGURE_CFLAGS="$CFLAGS_NOPIE $CONFIGURE_CFLAGS"
|
||||||
CONFIGURE_LDFLAGS="$LDFLAGS_NOPIE $CONFIGURE_LDFLAGS"
|
|
||||||
elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then
|
elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then
|
||||||
CONFIGURE_CFLAGS="-fPIE -DPIE $CONFIGURE_CFLAGS"
|
CONFIGURE_CFLAGS="-fPIE -DPIE $CONFIGURE_CFLAGS"
|
||||||
CONFIGURE_LDFLAGS="-pie $CONFIGURE_LDFLAGS"
|
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_CFLAGS=$glib_cflags" >> $config_host_mak
|
||||||
echo "GLIB_LIBS=$glib_libs" >> $config_host_mak
|
echo "GLIB_LIBS=$glib_libs" >> $config_host_mak
|
||||||
echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $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 "LD_I386_EMULATION=$ld_i386_emulation" >> $config_host_mak
|
||||||
echo "EXESUF=$EXESUF" >> $config_host_mak
|
echo "EXESUF=$EXESUF" >> $config_host_mak
|
||||||
echo "HOST_DSOSUF=$HOST_DSOSUF" >> $config_host_mak
|
echo "HOST_DSOSUF=$HOST_DSOSUF" >> $config_host_mak
|
||||||
|
|
|
@ -9,7 +9,7 @@ endif
|
||||||
# Check if tools are available to build documentation.
|
# Check if tools are available to build documentation.
|
||||||
build_docs = false
|
build_docs = false
|
||||||
if sphinx_build.found()
|
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 we're making warnings fatal, apply this to Sphinx runs as well
|
||||||
if get_option('werror')
|
if get_option('werror')
|
||||||
SPHINX_ARGS += [ '-W' ]
|
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
|
silently ignored. Using the switch with HMP monitors will become an
|
||||||
error in the future.
|
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)
|
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.
|
to the user to load all the images they need.
|
||||||
3. ``-bios <file>`` - Tells QEMU to load the specified file as the firmwrae.
|
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``
|
``Configuring floppies with ``-global``
|
||||||
'''''''''''''''''''''''''''''''''''''''
|
'''''''''''''''''''''''''''''''''''''''
|
||||||
|
|
||||||
|
@ -493,230 +474,3 @@ nanoMIPS ISA
|
||||||
|
|
||||||
The ``nanoMIPS`` ISA has never been upstreamed to any compiler toolchain.
|
The ``nanoMIPS`` ISA has never been upstreamed to any compiler toolchain.
|
||||||
As it is hard to generate binaries for it, declare it deprecated.
|
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
|
targets
|
||||||
security
|
security
|
||||||
deprecated
|
deprecated
|
||||||
|
removed-features
|
||||||
build-platforms
|
build-platforms
|
||||||
license
|
license
|
||||||
|
|
|
@ -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 = "",
|
.params = "",
|
||||||
.help = "quit the emulator",
|
.help = "quit the emulator",
|
||||||
.cmd = hmp_quit,
|
.cmd = hmp_quit,
|
||||||
|
.flags = "p",
|
||||||
},
|
},
|
||||||
|
|
||||||
SRST
|
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_filename = ms->kernel_filename;
|
||||||
info->kernel_cmdline = ms->kernel_cmdline;
|
info->kernel_cmdline = ms->kernel_cmdline;
|
||||||
info->initrd_filename = ms->initrd_filename;
|
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;
|
info->dtb_limit = 0;
|
||||||
|
|
||||||
/* Load the kernel. */
|
/* Load the kernel. */
|
||||||
|
|
|
@ -286,10 +286,9 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
|
||||||
|
|
||||||
void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
|
void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
|
||||||
{
|
{
|
||||||
if (!runstate_check(RUN_STATE_PRECONFIG)) {
|
if (phase_check(PHASE_MACHINE_INITIALIZED)) {
|
||||||
error_setg(errp, "The command is permitted only in '%s' state",
|
error_setg(errp, "The command is permitted only before the machine has been created");
|
||||||
RunState_str(RUN_STATE_PRECONFIG));
|
return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_numa_options(MACHINE(qdev_get_machine()), cmd, errp);
|
set_numa_options(MACHINE(qdev_get_machine()), cmd, errp);
|
||||||
|
|
|
@ -16,16 +16,21 @@
|
||||||
#include "sysemu/replay.h"
|
#include "sysemu/replay.h"
|
||||||
#include "qemu/units.h"
|
#include "qemu/units.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
|
#include "hw/loader.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/qapi-visit-common.h"
|
#include "qapi/qapi-visit-common.h"
|
||||||
#include "qapi/visitor.h"
|
#include "qapi/visitor.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
|
#include "sysemu/cpus.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "sysemu/reset.h"
|
||||||
|
#include "sysemu/runstate.h"
|
||||||
#include "sysemu/numa.h"
|
#include "sysemu/numa.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "sysemu/qtest.h"
|
#include "sysemu/qtest.h"
|
||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
#include "hw/mem/nvdimm.h"
|
#include "hw/mem/nvdimm.h"
|
||||||
|
#include "migration/global_state.h"
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
|
|
||||||
GlobalProperty hw_compat_5_2[] = {};
|
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);
|
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)
|
static char *machine_get_kernel(Object *obj, Error **errp)
|
||||||
{
|
{
|
||||||
MachineState *ms = MACHINE(obj);
|
MachineState *ms = MACHINE(obj);
|
||||||
|
@ -1167,17 +1174,16 @@ void machine_run_board_init(MachineState *machine)
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_class->init(machine);
|
machine_class->init(machine);
|
||||||
|
phase_advance(PHASE_MACHINE_INITIALIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NotifierList machine_init_done_notifiers =
|
static NotifierList machine_init_done_notifiers =
|
||||||
NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
|
NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
|
||||||
|
|
||||||
bool machine_init_done;
|
|
||||||
|
|
||||||
void qemu_add_machine_init_done_notifier(Notifier *notify)
|
void qemu_add_machine_init_done_notifier(Notifier *notify)
|
||||||
{
|
{
|
||||||
notifier_list_add(&machine_init_done_notifiers, notify);
|
notifier_list_add(&machine_init_done_notifiers, notify);
|
||||||
if (machine_init_done) {
|
if (phase_check(PHASE_MACHINE_READY)) {
|
||||||
notify->notify(notify, NULL);
|
notify->notify(notify, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1187,10 +1193,48 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify)
|
||||||
notifier_remove(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);
|
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 = {
|
static const TypeInfo machine_info = {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
# core qdev-related obj files, also used by *-user and unit tests
|
# core qdev-related obj files, also used by *-user and unit tests
|
||||||
hwcore_files = files(
|
hwcore_files = files(
|
||||||
'bus.c',
|
'bus.c',
|
||||||
'fw-path-provider.c',
|
|
||||||
'hotplug.c',
|
'hotplug.c',
|
||||||
'qdev-properties.c',
|
'qdev-properties.c',
|
||||||
'qdev.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'))
|
common_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c'))
|
||||||
|
|
||||||
softmmu_ss.add(files(
|
softmmu_ss.add(files(
|
||||||
|
'fw-path-provider.c',
|
||||||
'loader.c',
|
'loader.c',
|
||||||
'machine-hmp-cmds.c',
|
'machine-hmp-cmds.c',
|
||||||
'machine.c',
|
'machine.c',
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
#include "migration/vmstate.h"
|
#include "migration/vmstate.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
bool qdev_hotplug = false;
|
|
||||||
static bool qdev_hot_added = false;
|
static bool qdev_hot_added = false;
|
||||||
bool qdev_hot_removed = 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);
|
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));
|
DeviceState *dev = DEVICE(object_dynamic_cast(obj, TYPE_DEVICE));
|
||||||
DeviceClass *dc;
|
DeviceClass *dc;
|
||||||
|
@ -417,16 +416,10 @@ static int qdev_assert_realized_properly(Object *obj, void *opaque)
|
||||||
return 0;
|
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(),
|
object_child_foreach_recursive(object_get_root(),
|
||||||
qdev_assert_realized_properly, NULL);
|
qdev_assert_realized_properly_cb, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool qdev_machine_modified(void)
|
bool qdev_machine_modified(void)
|
||||||
|
@ -911,7 +904,7 @@ static void device_initfn(Object *obj)
|
||||||
{
|
{
|
||||||
DeviceState *dev = DEVICE(obj);
|
DeviceState *dev = DEVICE(obj);
|
||||||
|
|
||||||
if (qdev_hotplug) {
|
if (phase_check(PHASE_MACHINE_READY)) {
|
||||||
dev->hotplugged = 1;
|
dev->hotplugged = 1;
|
||||||
qdev_hot_added = true;
|
qdev_hot_added = true;
|
||||||
}
|
}
|
||||||
|
@ -1144,6 +1137,19 @@ Object *qdev_get_machine(void)
|
||||||
return dev;
|
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 = {
|
static const TypeInfo device_type_info = {
|
||||||
.name = TYPE_DEVICE,
|
.name = TYPE_DEVICE,
|
||||||
.parent = TYPE_OBJECT,
|
.parent = TYPE_OBJECT,
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "sysemu/device_tree.h"
|
#include "sysemu/device_tree.h"
|
||||||
#include "sysemu/reset.h"
|
#include "sysemu/reset.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "hw/boards.h"
|
||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "qemu/cutils.h"
|
#include "qemu/cutils.h"
|
||||||
|
@ -116,16 +117,14 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
|
||||||
const char *dtb_filename,
|
const char *dtb_filename,
|
||||||
void (*machine_cpu_reset)(MicroBlazeCPU *))
|
void (*machine_cpu_reset)(MicroBlazeCPU *))
|
||||||
{
|
{
|
||||||
QemuOpts *machine_opts;
|
|
||||||
const char *kernel_filename;
|
const char *kernel_filename;
|
||||||
const char *kernel_cmdline;
|
const char *kernel_cmdline;
|
||||||
const char *dtb_arg;
|
const char *dtb_arg;
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
|
|
||||||
machine_opts = qemu_get_machine_opts();
|
kernel_filename = current_machine->kernel_filename;
|
||||||
kernel_filename = qemu_opt_get(machine_opts, "kernel");
|
kernel_cmdline = current_machine->kernel_cmdline;
|
||||||
kernel_cmdline = qemu_opt_get(machine_opts, "append");
|
dtb_arg = current_machine->dtb;
|
||||||
dtb_arg = qemu_opt_get(machine_opts, "dtb");
|
|
||||||
/* default to pcbios dtb as passed by machine_init */
|
/* default to pcbios dtb as passed by machine_init */
|
||||||
if (!dtb_arg && dtb_filename) {
|
if (!dtb_arg && dtb_filename) {
|
||||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
|
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "sysemu/device_tree.h"
|
#include "sysemu/device_tree.h"
|
||||||
#include "sysemu/reset.h"
|
#include "sysemu/reset.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "hw/boards.h"
|
||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
|
|
||||||
|
@ -120,16 +121,14 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
|
||||||
const char *dtb_filename,
|
const char *dtb_filename,
|
||||||
void (*machine_cpu_reset)(Nios2CPU *))
|
void (*machine_cpu_reset)(Nios2CPU *))
|
||||||
{
|
{
|
||||||
QemuOpts *machine_opts;
|
|
||||||
const char *kernel_filename;
|
const char *kernel_filename;
|
||||||
const char *kernel_cmdline;
|
const char *kernel_cmdline;
|
||||||
const char *dtb_arg;
|
const char *dtb_arg;
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
|
|
||||||
machine_opts = qemu_get_machine_opts();
|
kernel_filename = current_machine->kernel_filename;
|
||||||
kernel_filename = qemu_opt_get(machine_opts, "kernel");
|
kernel_cmdline = current_machine->kernel_cmdline;
|
||||||
kernel_cmdline = qemu_opt_get(machine_opts, "append");
|
dtb_arg = current_machine->dtb;
|
||||||
dtb_arg = qemu_opt_get(machine_opts, "dtb");
|
|
||||||
/* default to pcbios dtb as passed by machine_init */
|
/* default to pcbios dtb as passed by machine_init */
|
||||||
if (!dtb_arg) {
|
if (!dtb_arg) {
|
||||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
|
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;
|
PCIDevice *dev = opaque;
|
||||||
|
|
||||||
|
assert(addr + size <= dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE);
|
||||||
return pci_get_long(dev->msix_table + addr);
|
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;
|
int vector = addr / PCI_MSIX_ENTRY_SIZE;
|
||||||
bool was_masked;
|
bool was_masked;
|
||||||
|
|
||||||
|
assert(addr + size <= dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE);
|
||||||
|
|
||||||
was_masked = msix_is_masked(dev, vector);
|
was_masked = msix_is_masked(dev, vector);
|
||||||
pci_set_long(dev->msix_table + addr, val);
|
pci_set_long(dev->msix_table + addr, val);
|
||||||
msix_handle_mask_update(dev, vector, was_masked);
|
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,
|
address_space_init(&pci_dev->bus_master_as,
|
||||||
&pci_dev->bus_master_container_region, pci_dev->name);
|
&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_init_bus_master(pci_dev);
|
||||||
}
|
}
|
||||||
pci_dev->irq_state = 0;
|
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,
|
pmc->pci_pio_base >> 32, pmc->pci_pio_base,
|
||||||
0x0, 0x10000,
|
0x0, 0x10000,
|
||||||
};
|
};
|
||||||
QemuOpts *machine_opts = qemu_get_machine_opts();
|
const char *dtb_file = machine->dtb;
|
||||||
const char *dtb_file = qemu_opt_get(machine_opts, "dtb");
|
const char *toplevel_compat = machine->dt_compatible;
|
||||||
const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
|
|
||||||
|
|
||||||
if (dtb_file) {
|
if (dtb_file) {
|
||||||
char *filename;
|
char *filename;
|
||||||
|
|
|
@ -3275,6 +3275,19 @@ static void spapr_instance_init(Object *obj)
|
||||||
{
|
{
|
||||||
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
|
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
|
||||||
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
|
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->htab_fd = -1;
|
||||||
spapr->use_hotplug_event_source = true;
|
spapr->use_hotplug_event_source = true;
|
||||||
|
|
|
@ -27,10 +27,8 @@
|
||||||
#include "hw/ppc/spapr_nvdimm.h"
|
#include "hw/ppc/spapr_nvdimm.h"
|
||||||
#include "hw/mem/nvdimm.h"
|
#include "hw/mem/nvdimm.h"
|
||||||
#include "qemu/nvdimm-utils.h"
|
#include "qemu/nvdimm-utils.h"
|
||||||
#include "qemu/option.h"
|
|
||||||
#include "hw/ppc/fdt.h"
|
#include "hw/ppc/fdt.h"
|
||||||
#include "qemu/range.h"
|
#include "qemu/range.h"
|
||||||
#include "sysemu/sysemu.h"
|
|
||||||
#include "hw/ppc/spapr_numa.h"
|
#include "hw/ppc/spapr_numa.h"
|
||||||
|
|
||||||
bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
|
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 MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
|
||||||
const MachineState *ms = MACHINE(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;
|
g_autofree char *uuidstr = NULL;
|
||||||
QemuUUID uuid;
|
QemuUUID uuid;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -48,16 +45,7 @@ bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (!ms->nvdimms_state->is_enabled) {
|
||||||
* 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) {
|
|
||||||
error_setg(errp, "nvdimm device found but 'nvdimm=off' was set");
|
error_setg(errp, "nvdimm device found but 'nvdimm=off' was set");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,7 +152,7 @@ static int xilinx_load_device_tree(hwaddr addr,
|
||||||
int r;
|
int r;
|
||||||
const char *dtb_filename;
|
const char *dtb_filename;
|
||||||
|
|
||||||
dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
|
dtb_filename = current_machine->dtb;
|
||||||
if (dtb_filename) {
|
if (dtb_filename) {
|
||||||
fdt = load_device_tree(dtb_filename, &fdt_size);
|
fdt = load_device_tree(dtb_filename, &fdt_size);
|
||||||
if (!fdt) {
|
if (!fdt) {
|
||||||
|
|
|
@ -100,14 +100,12 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
|
||||||
int cpu;
|
int cpu;
|
||||||
uint32_t *cells;
|
uint32_t *cells;
|
||||||
char *nodename;
|
char *nodename;
|
||||||
const char *dtb_filename;
|
|
||||||
char ethclk_names[] = "pclk\0hclk";
|
char ethclk_names[] = "pclk\0hclk";
|
||||||
uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1;
|
uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1;
|
||||||
uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle;
|
uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle;
|
||||||
|
|
||||||
dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
|
if (ms->dtb) {
|
||||||
if (dtb_filename) {
|
fdt = s->fdt = load_device_tree(ms->dtb, &s->fdt_size);
|
||||||
fdt = s->fdt = load_device_tree(dtb_filename, &s->fdt_size);
|
|
||||||
if (!fdt) {
|
if (!fdt) {
|
||||||
error_report("load_device_tree() failed");
|
error_report("load_device_tree() failed");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -181,7 +181,6 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
|
||||||
{
|
{
|
||||||
void *fdt;
|
void *fdt;
|
||||||
int i, cpu, socket;
|
int i, cpu, socket;
|
||||||
const char *dtb_filename;
|
|
||||||
MachineState *mc = MACHINE(s);
|
MachineState *mc = MACHINE(s);
|
||||||
uint64_t addr, size;
|
uint64_t addr, size;
|
||||||
uint32_t *clint_cells, *plic_cells;
|
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 flashsize = virt_memmap[VIRT_FLASH].size / 2;
|
||||||
hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
|
hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
|
||||||
|
|
||||||
dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
|
if (mc->dtb) {
|
||||||
if (dtb_filename) {
|
fdt = s->fdt = load_device_tree(mc->dtb, &s->fdt_size);
|
||||||
fdt = s->fdt = load_device_tree(dtb_filename, &s->fdt_size);
|
|
||||||
if (!fdt) {
|
if (!fdt) {
|
||||||
error_report("load_device_tree() failed");
|
error_report("load_device_tree() failed");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -170,6 +170,8 @@ static void scsi_dma_restart_bh(void *opaque)
|
||||||
scsi_req_unref(req);
|
scsi_req_unref(req);
|
||||||
}
|
}
|
||||||
aio_context_release(blk_get_aio_context(s->conf.blk));
|
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)
|
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) {
|
if (!s->bh) {
|
||||||
AioContext *ctx = blk_get_aio_context(s->conf.blk);
|
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);
|
s->bh = aio_bh_new(ctx, scsi_dma_restart_bh, s);
|
||||||
qemu_bh_schedule(s->bh);
|
qemu_bh_schedule(s->bh);
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream)
|
||||||
USBDevice *dev = ep->dev;
|
USBDevice *dev = ep->dev;
|
||||||
USBBus *bus = usb_bus_from_device(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,
|
* This is machine init cold plug. No need to wakeup anyone,
|
||||||
* all devices will be reset anyway. And trying to wakeup can
|
* 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
|
* accept it. Having a different masks is possible but the guest will use
|
||||||
* sub-optimal block sizes, so warn about it.
|
* sub-optimal block sizes, so warn about it.
|
||||||
*/
|
*/
|
||||||
if (qdev_hotplug) {
|
if (phase_check(PHASE_MACHINE_READY)) {
|
||||||
int new_granule = ctz64(new_mask);
|
int new_granule = ctz64(new_mask);
|
||||||
int cur_granule = ctz64(cur_mask);
|
int cur_granule = ctz64(cur_mask);
|
||||||
|
|
||||||
|
|
|
@ -233,11 +233,10 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
|
||||||
qemu_irq *extints;
|
qemu_irq *extints;
|
||||||
DriveInfo *dinfo;
|
DriveInfo *dinfo;
|
||||||
PFlashCFI01 *flash = NULL;
|
PFlashCFI01 *flash = NULL;
|
||||||
QemuOpts *machine_opts = qemu_get_machine_opts();
|
const char *kernel_filename = machine->kernel_filename;
|
||||||
const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
|
const char *kernel_cmdline = machine->kernel_cmdline;
|
||||||
const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
|
const char *dtb_filename = machine->dtb;
|
||||||
const char *dtb_filename = qemu_opt_get(machine_opts, "dtb");
|
const char *initrd_filename = machine->initrd_filename;
|
||||||
const char *initrd_filename = qemu_opt_get(machine_opts, "initrd");
|
|
||||||
const unsigned system_io_size = 224 * MiB;
|
const unsigned system_io_size = 224 * MiB;
|
||||||
uint32_t freq = 10000000;
|
uint32_t freq = 10000000;
|
||||||
int n;
|
int n;
|
||||||
|
|
|
@ -270,8 +270,7 @@ struct ChardevClass {
|
||||||
void (*chr_set_echo)(Chardev *chr, bool echo);
|
void (*chr_set_echo)(Chardev *chr, bool echo);
|
||||||
void (*chr_set_fe_open)(Chardev *chr, int fe_open);
|
void (*chr_set_fe_open)(Chardev *chr, int fe_open);
|
||||||
void (*chr_be_event)(Chardev *s, QEMUChrEvent event);
|
void (*chr_be_event)(Chardev *s, QEMUChrEvent event);
|
||||||
/* Return 0 if succeeded, 1 if failed */
|
void (*chr_options_parsed)(Chardev *chr);
|
||||||
int (*chr_machine_done)(Chardev *chr);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Chardev *qemu_chardev_new(const char *id, const char *typename,
|
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,
|
GSource *qemu_chr_timeout_add_ms(Chardev *chr, guint ms,
|
||||||
GSourceFunc func, void *private);
|
GSourceFunc func, void *private);
|
||||||
|
|
||||||
|
void suspend_mux_open(void);
|
||||||
|
void resume_mux_open(void);
|
||||||
|
|
||||||
/* console.c */
|
/* console.c */
|
||||||
void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp);
|
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
|
#endif
|
||||||
|
|
||||||
|
/* vl.c */
|
||||||
|
extern int singlestep;
|
||||||
|
|
||||||
#endif /* CPU_COMMON_H */
|
#endif /* CPU_COMMON_H */
|
||||||
|
|
|
@ -676,7 +676,4 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu,
|
||||||
MemoryRegionSection *section);
|
MemoryRegionSection *section);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* vl.c */
|
|
||||||
extern int singlestep;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#ifndef HW_POISON_H
|
#ifndef HW_POISON_H
|
||||||
#define HW_POISON_H
|
#define HW_POISON_H
|
||||||
#ifdef __GNUC__
|
|
||||||
|
|
||||||
#pragma GCC poison TARGET_I386
|
#pragma GCC poison TARGET_I386
|
||||||
#pragma GCC poison TARGET_X86_64
|
#pragma GCC poison TARGET_X86_64
|
||||||
|
@ -93,4 +92,3 @@
|
||||||
#pragma GCC poison CONFIG_SOFTMMU
|
#pragma GCC poison CONFIG_SOFTMMU
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
|
@ -780,12 +780,12 @@ const VMStateDescription *qdev_get_vmsd(DeviceState *dev);
|
||||||
|
|
||||||
const char *qdev_fw_name(DeviceState *dev);
|
const char *qdev_fw_name(DeviceState *dev);
|
||||||
|
|
||||||
|
void qdev_assert_realized_properly(void);
|
||||||
Object *qdev_get_machine(void);
|
Object *qdev_get_machine(void);
|
||||||
|
|
||||||
/* FIXME: make this a link<> */
|
/* FIXME: make this a link<> */
|
||||||
bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp);
|
bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp);
|
||||||
|
|
||||||
extern bool qdev_hotplug;
|
|
||||||
extern bool qdev_hot_removed;
|
extern bool qdev_hot_removed;
|
||||||
|
|
||||||
char *qdev_get_dev_path(DeviceState *dev);
|
char *qdev_get_dev_path(DeviceState *dev);
|
||||||
|
@ -811,4 +811,35 @@ void device_listener_unregister(DeviceListener *listener);
|
||||||
*/
|
*/
|
||||||
bool qdev_should_hide_device(QemuOpts *opts);
|
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
|
#endif
|
||||||
|
|
|
@ -206,21 +206,12 @@ typedef struct __name##_back_ring __name##_back_ring_t
|
||||||
#define RING_HAS_UNCONSUMED_RESPONSES(_r) \
|
#define RING_HAS_UNCONSUMED_RESPONSES(_r) \
|
||||||
((_r)->sring->rsp_prod - (_r)->rsp_cons)
|
((_r)->sring->rsp_prod - (_r)->rsp_cons)
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({ \
|
#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({ \
|
||||||
unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \
|
unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \
|
||||||
unsigned int rsp = RING_SIZE(_r) - \
|
unsigned int rsp = RING_SIZE(_r) - \
|
||||||
((_r)->req_cons - (_r)->rsp_prod_pvt); \
|
((_r)->req_cons - (_r)->rsp_prod_pvt); \
|
||||||
req < rsp ? req : rsp; \
|
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. */
|
/* Direct access to individual ring elements, by index. */
|
||||||
#define RING_GET_REQUEST(_r, _idx) \
|
#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);
|
void qmp_enable_command(QmpCommandList *cmds, const char *name);
|
||||||
|
|
||||||
bool qmp_command_is_enabled(const QmpCommand *cmd);
|
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);
|
const char *qmp_command_name(const QmpCommand *cmd);
|
||||||
bool qmp_has_success_response(const QmpCommand *cmd);
|
bool qmp_has_success_response(const QmpCommand *cmd);
|
||||||
QDict *qmp_error_response(Error *err);
|
QDict *qmp_error_response(Error *err);
|
||||||
|
|
|
@ -241,23 +241,6 @@
|
||||||
|
|
||||||
#else /* __ATOMIC_RELAXED */
|
#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__
|
#ifdef __alpha__
|
||||||
#define smp_read_barrier_depends() asm volatile("mb":::"memory")
|
#define smp_read_barrier_depends() asm volatile("mb":::"memory")
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,17 +11,6 @@
|
||||||
#define QEMU_STATIC_ANALYSIS 1
|
#define QEMU_STATIC_ANALYSIS 1
|
||||||
#endif
|
#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_NORETURN __attribute__ ((__noreturn__))
|
||||||
|
|
||||||
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||||
|
@ -44,10 +33,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef likely
|
#ifndef likely
|
||||||
#if __GNUC__ < 3
|
|
||||||
#define __builtin_expect(x, n) (x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define likely(x) __builtin_expect(!!(x), 1)
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
#endif
|
#endif
|
||||||
|
@ -68,14 +53,10 @@
|
||||||
(offsetof(container, field) + sizeof_field(container, field))
|
(offsetof(container, field) + sizeof_field(container, field))
|
||||||
|
|
||||||
/* Convert from a base type to a parent type, with compile time checking. */
|
/* Convert from a base type to a parent type, with compile time checking. */
|
||||||
#ifdef __GNUC__
|
|
||||||
#define DO_UPCAST(type, field, dev) ( __extension__ ( { \
|
#define DO_UPCAST(type, field, dev) ( __extension__ ( { \
|
||||||
char __attribute__((unused)) offset_must_be_zero[ \
|
char __attribute__((unused)) offset_must_be_zero[ \
|
||||||
-offsetof(type, field)]; \
|
-offsetof(type, field)]; \
|
||||||
container_of(dev, 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 typeof_field(type, field) typeof(((type *)0)->field)
|
||||||
#define type_check(t1,t2) ((t1*)0 - (t2*)0)
|
#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)) - \
|
#define QEMU_BUILD_BUG_ON_ZERO(x) (sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)) - \
|
||||||
sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)))
|
sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)))
|
||||||
|
|
||||||
#if defined __GNUC__
|
#if defined(__clang__)
|
||||||
# if !QEMU_GNUC_PREREQ(4, 4)
|
/* clang doesn't support gnu_printf, so use printf. */
|
||||||
/* 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)))
|
||||||
# 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
|
|
||||||
#else
|
#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
|
#endif
|
||||||
|
|
||||||
#ifndef __has_warning
|
#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);
|
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 {
|
union qemu_plugin_cb_sig {
|
||||||
qemu_plugin_simple_cb_t simple;
|
qemu_plugin_simple_cb_t simple;
|
||||||
|
@ -199,7 +199,7 @@ static inline void qemu_plugin_opt_parse(const char *optarg,
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int qemu_plugin_load_list(QemuPluginList *head)
|
static inline int qemu_plugin_load_list(QemuPluginList *head, Error **errp)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,13 +28,8 @@
|
||||||
#endif
|
#endif
|
||||||
#define QEMU_PLUGIN_LOCAL
|
#define QEMU_PLUGIN_LOCAL
|
||||||
#else
|
#else
|
||||||
#if __GNUC__ >= 4
|
#define QEMU_PLUGIN_EXPORT __attribute__((visibility("default")))
|
||||||
#define QEMU_PLUGIN_EXPORT __attribute__((visibility("default")))
|
#define QEMU_PLUGIN_LOCAL __attribute__((visibility("hidden")))
|
||||||
#define QEMU_PLUGIN_LOCAL __attribute__((visibility("hidden")))
|
|
||||||
#else
|
|
||||||
#define QEMU_PLUGIN_EXPORT
|
|
||||||
#define QEMU_PLUGIN_LOCAL
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef uint64_t qemu_plugin_id_t;
|
typedef uint64_t qemu_plugin_id_t;
|
||||||
|
|
|
@ -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,
|
QEMU_WAKEUP_REASON_OTHER,
|
||||||
} WakeupReason;
|
} WakeupReason;
|
||||||
|
|
||||||
void qemu_exit_preconfig_request(void);
|
|
||||||
void qemu_system_reset_request(ShutdownCause reason);
|
void qemu_system_reset_request(ShutdownCause reason);
|
||||||
void qemu_system_suspend_request(void);
|
void qemu_system_suspend_request(void);
|
||||||
void qemu_register_suspend_notifier(Notifier *notifier);
|
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_add_exit_notifier(Notifier *notify);
|
||||||
void qemu_remove_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_run_machine_init_done_notifiers(void);
|
||||||
void qemu_add_machine_init_done_notifier(Notifier *notify);
|
void qemu_add_machine_init_done_notifier(Notifier *notify);
|
||||||
void qemu_remove_machine_init_done_notifier(Notifier *notify);
|
void qemu_remove_machine_init_done_notifier(Notifier *notify);
|
||||||
|
|
||||||
void configure_rtc(QemuOpts *opts);
|
void configure_rtc(QemuOpts *opts);
|
||||||
|
|
||||||
|
void qemu_init_subsystems(void);
|
||||||
|
|
||||||
extern int autostart;
|
extern int autostart;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -43,7 +43,6 @@ extern int win2k_install_hack;
|
||||||
extern int alt_grab;
|
extern int alt_grab;
|
||||||
extern int ctrl_grab;
|
extern int ctrl_grab;
|
||||||
extern int graphic_rotate;
|
extern int graphic_rotate;
|
||||||
extern int no_shutdown;
|
|
||||||
extern int old_param;
|
extern int old_param;
|
||||||
extern int boot_menu;
|
extern int boot_menu;
|
||||||
extern bool boot_strict;
|
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_register_boot_set(QEMUBootSetHandler *func, void *opaque);
|
||||||
void qemu_boot_set(const char *boot_order, Error **errp);
|
void qemu_boot_set(const char *boot_order, Error **errp);
|
||||||
|
|
||||||
QemuOpts *qemu_get_machine_opts(void);
|
|
||||||
|
|
||||||
bool defaults_enabled(void);
|
bool defaults_enabled(void);
|
||||||
|
|
||||||
void qemu_init(int argc, char **argv, char **envp);
|
void qemu_init(int argc, char **argv, char **envp);
|
||||||
|
|
|
@ -671,9 +671,7 @@ int main(int argc, char **argv, char **envp)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
trace_init_file();
|
trace_init_file();
|
||||||
if (qemu_plugin_load_list(&plugins)) {
|
qemu_plugin_load_list(&plugins, &error_fatal);
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Zero out regs */
|
/* Zero out regs */
|
||||||
memset(regs, 0, sizeof(struct target_pt_regs));
|
memset(regs, 0, sizeof(struct target_pt_regs));
|
||||||
|
|
|
@ -24,7 +24,6 @@ struct syscallname {
|
||||||
abi_long, abi_long, abi_long);
|
abi_long, abi_long, abi_long);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
/*
|
/*
|
||||||
* It is possible that target doesn't have syscall that uses
|
* It is possible that target doesn't have syscall that uses
|
||||||
* following flags but we don't want the compiler to warn
|
* 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.
|
* functions. It is ok to keep them while not used.
|
||||||
*/
|
*/
|
||||||
#define UNUSED __attribute__ ((unused))
|
#define UNUSED __attribute__ ((unused))
|
||||||
#else
|
|
||||||
#define UNUSED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure used to translate flag values into strings. This is
|
* Structure used to translate flag values into strings. This is
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include "hw/qdev-core.h"
|
||||||
#include "monitor-internal.h"
|
#include "monitor-internal.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/qmp/qdict.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)
|
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,
|
static void help_cmd_dump_one(Monitor *mon,
|
||||||
|
@ -658,8 +659,8 @@ static const HMPCommand *monitor_parse_command(MonitorHMP *hmp_mon,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!cmd_available(cmd)) {
|
if (!cmd_available(cmd)) {
|
||||||
monitor_printf(mon, "Command '%.*s' not available with -preconfig "
|
monitor_printf(mon, "Command '%.*s' not available "
|
||||||
"until after exit_preconfig.\n",
|
"until machine initialization has completed.\n",
|
||||||
(int)(p - cmdp_start), cmdp_start);
|
(int)(p - cmdp_start), cmdp_start);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "ui/vnc.h"
|
#include "ui/vnc.h"
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
#include "sysemu/runstate.h"
|
#include "sysemu/runstate.h"
|
||||||
|
#include "sysemu/runstate-action.h"
|
||||||
#include "sysemu/arch_init.h"
|
#include "sysemu/arch_init.h"
|
||||||
#include "sysemu/blockdev.h"
|
#include "sysemu/blockdev.h"
|
||||||
#include "sysemu/block-backend.h"
|
#include "sysemu/block-backend.h"
|
||||||
|
@ -72,7 +73,7 @@ UuidInfo *qmp_query_uuid(Error **errp)
|
||||||
|
|
||||||
void qmp_quit(Error **errp)
|
void qmp_quit(Error **errp)
|
||||||
{
|
{
|
||||||
no_shutdown = 0;
|
shutdown_action = SHUTDOWN_ACTION_POWEROFF;
|
||||||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
|
qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,16 +103,6 @@ void qmp_system_powerdown(Error **errp)
|
||||||
qemu_system_powerdown_request();
|
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)
|
void qmp_cont(Error **errp)
|
||||||
{
|
{
|
||||||
BlockBackend *blk;
|
BlockBackend *blk;
|
||||||
|
|
|
@ -41,7 +41,6 @@ override CFLAGS += $(call cc-option, $(Wa)-32)
|
||||||
|
|
||||||
LD_I386_EMULATION ?= elf_i386
|
LD_I386_EMULATION ?= elf_i386
|
||||||
override LDFLAGS = -m $(LD_I386_EMULATION) -T $(SRC_DIR)/flat.lds
|
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
|
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);
|
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;
|
qemu_plugin_install_func_t install;
|
||||||
struct qemu_plugin_ctx *ctx;
|
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);
|
ctx->handle = g_module_open(desc->path, G_MODULE_BIND_LOCAL);
|
||||||
if (ctx->handle == NULL) {
|
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;
|
goto err_dlopen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_module_symbol(ctx->handle, "qemu_plugin_install", &sym)) {
|
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;
|
goto err_symbol;
|
||||||
}
|
}
|
||||||
install = (qemu_plugin_install_func_t) sym;
|
install = (qemu_plugin_install_func_t) sym;
|
||||||
/* symbol was found; it could be NULL though */
|
/* symbol was found; it could be NULL though */
|
||||||
if (install == NULL) {
|
if (install == NULL) {
|
||||||
error_report("%s: %s: qemu_plugin_install is NULL",
|
error_setg(errp, "Could not load plugin %s: qemu_plugin_install is NULL",
|
||||||
__func__, desc->path);
|
desc->path);
|
||||||
goto err_symbol;
|
goto err_symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!g_module_symbol(ctx->handle, "qemu_plugin_version", &sym)) {
|
if (!g_module_symbol(ctx->handle, "qemu_plugin_version", &sym)) {
|
||||||
error_report("TCG plugin %s does not declare API version %s",
|
error_setg(errp, "Could not load plugin %s: plugin does not declare API version %s",
|
||||||
desc->path, g_module_error());
|
desc->path, g_module_error());
|
||||||
goto err_symbol;
|
goto err_symbol;
|
||||||
} else {
|
} else {
|
||||||
int version = *(int *)sym;
|
int version = *(int *)sym;
|
||||||
if (version < QEMU_PLUGIN_MIN_VERSION) {
|
if (version < QEMU_PLUGIN_MIN_VERSION) {
|
||||||
error_report("TCG plugin %s requires API version %d, but "
|
error_setg(errp, "Could not load plugin %s: plugin requires API version %d, but "
|
||||||
"this QEMU supports only a minimum version of %d",
|
"this QEMU supports only a minimum version of %d",
|
||||||
desc->path, version, QEMU_PLUGIN_MIN_VERSION);
|
desc->path, version, QEMU_PLUGIN_MIN_VERSION);
|
||||||
goto err_symbol;
|
goto err_symbol;
|
||||||
} else if (version > QEMU_PLUGIN_VERSION) {
|
} else if (version > QEMU_PLUGIN_VERSION) {
|
||||||
error_report("TCG plugin %s requires API version %d, but "
|
error_setg(errp, "Could not load plugin %s: plugin requires API version %d, but "
|
||||||
"this QEMU supports only up to version %d",
|
"this QEMU supports only up to version %d",
|
||||||
desc->path, version, QEMU_PLUGIN_VERSION);
|
desc->path, version, QEMU_PLUGIN_VERSION);
|
||||||
goto err_symbol;
|
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);
|
rc = install(ctx->id, info, desc->argc, desc->argv);
|
||||||
ctx->installing = false;
|
ctx->installing = false;
|
||||||
if (rc) {
|
if (rc) {
|
||||||
error_report("%s: qemu_plugin_install returned error code %d",
|
error_setg(errp, "Could not load plugin %s: qemu_plugin_install returned error code %d",
|
||||||
__func__, rc);
|
desc->path, rc);
|
||||||
/*
|
/*
|
||||||
* we cannot rely on the plugin doing its own cleanup, so
|
* we cannot rely on the plugin doing its own cleanup, so
|
||||||
* call a full uninstall if the plugin did not yet call it.
|
* 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
|
* Note: the descriptor of each successfully installed plugin is removed
|
||||||
* from the list given by @head.
|
* 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;
|
struct qemu_plugin_desc *desc, *next;
|
||||||
g_autofree qemu_info_t *info = g_new0(qemu_info_t, 1);
|
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) {
|
QTAILQ_FOREACH_SAFE(desc, head, entry, next) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = plugin_load(desc, info);
|
err = plugin_load(desc, info, errp);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,7 +219,8 @@
|
||||||
# -> { "execute": "quit" }
|
# -> { "execute": "quit" }
|
||||||
# <- { "return": {} }
|
# <- { "return": {} }
|
||||||
##
|
##
|
||||||
{ 'command': 'quit' }
|
{ 'command': 'quit',
|
||||||
|
'allow-preconfig': true }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @MonitorMode:
|
# @MonitorMode:
|
||||||
|
|
|
@ -167,10 +167,7 @@ QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runstate_check(RUN_STATE_PRECONFIG) &&
|
if (!qmp_command_available(cmd, &err)) {
|
||||||
!(cmd->options & QCO_ALLOW_PRECONFIG)) {
|
|
||||||
error_setg(&err, "The command '%s' isn't permitted in '%s' state",
|
|
||||||
cmd->name, RunState_str(RUN_STATE_PRECONFIG));
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,15 +50,12 @@
|
||||||
# @colo: guest is paused to save/restore VM state under colo checkpoint,
|
# @colo: guest is paused to save/restore VM state under colo checkpoint,
|
||||||
# VM can not get into this state unless colo capability is enabled
|
# VM can not get into this state unless colo capability is enabled
|
||||||
# for migration. (since 2.8)
|
# 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',
|
{ 'enum': 'RunState',
|
||||||
'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',
|
'data': [ 'debug', 'inmigrate', 'internal-error', 'io-error', 'paused',
|
||||||
'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
|
'postmigrate', 'prelaunch', 'finish-migrate', 'restore-vm',
|
||||||
'running', 'save-vm', 'shutdown', 'suspended', 'watchdog',
|
'running', 'save-vm', 'shutdown', 'suspended', 'watchdog',
|
||||||
'guest-panicked', 'colo', 'preconfig' ] }
|
'guest-panicked', 'colo' ] }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @ShutdownCause:
|
# @ShutdownCause:
|
||||||
|
@ -328,6 +325,46 @@
|
||||||
'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none',
|
'data': [ 'reset', 'shutdown', 'poweroff', 'pause', 'debug', 'none',
|
||||||
'inject-nmi' ] }
|
'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:
|
# @watchdog-set-action:
|
||||||
#
|
#
|
||||||
|
@ -337,6 +374,40 @@
|
||||||
##
|
##
|
||||||
{ 'command': 'watchdog-set-action', 'data' : {'action': 'WatchdogAction'} }
|
{ '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:
|
# @GUEST_PANICKED:
|
||||||
#
|
#
|
||||||
|
|
|
@ -3713,17 +3713,6 @@ SRST
|
||||||
Do not start CPU at startup (you must type 'c' in the monitor).
|
Do not start CPU at startup (you must type 'c' in the monitor).
|
||||||
ERST
|
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,
|
DEF("overcommit", HAS_ARG, QEMU_OPTION_overcommit,
|
||||||
"-overcommit [mem-lock=on|off][cpu-pm=on|off]\n"
|
"-overcommit [mem-lock=on|off][cpu-pm=on|off]\n"
|
||||||
" run qemu with overcommit hints\n"
|
" run qemu with overcommit hints\n"
|
||||||
|
@ -3739,8 +3728,7 @@ SRST
|
||||||
|
|
||||||
Locking qemu and guest memory can be enabled via ``mem-lock=on``
|
Locking qemu and guest memory can be enabled via ``mem-lock=on``
|
||||||
(disabled by default). This works when host memory is not
|
(disabled by default). This works when host memory is not
|
||||||
overcommitted and reduces the worst-case latency for guest. This is
|
overcommitted and reduces the worst-case latency for guest.
|
||||||
equivalent to ``realtime``.
|
|
||||||
|
|
||||||
Guest ability to manage power state of host cpus (increasing latency
|
Guest ability to manage power state of host cpus (increasing latency
|
||||||
for other processes on the same host cpu, but decreasing latency for
|
for other processes on the same host cpu, but decreasing latency for
|
||||||
|
@ -3894,6 +3882,31 @@ SRST
|
||||||
changes to the disk image.
|
changes to the disk image.
|
||||||
ERST
|
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, \
|
DEF("loadvm", HAS_ARG, QEMU_OPTION_loadvm, \
|
||||||
"-loadvm [tag|id]\n" \
|
"-loadvm [tag|id]\n" \
|
||||||
" start right away with a saved state (loadvm in monitor)\n",
|
" start right away with a saved state (loadvm in monitor)\n",
|
||||||
|
@ -4079,21 +4092,6 @@ SRST
|
||||||
|
|
||||||
ERST
|
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, \
|
DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \
|
||||||
"-incoming tcp:[host]:port[,to=maxport][,ipv4][,ipv6]\n" \
|
"-incoming tcp:[host]:port[,to=maxport][,ipv4][,ipv6]\n" \
|
||||||
"-incoming rdma:host:port[,ipv4][,ipv6]\n" \
|
"-incoming rdma:host:port[,ipv4][,ipv6]\n" \
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* From qemu/compiler.h */
|
/* From qemu/compiler.h */
|
||||||
#define QEMU_GNUC_PREREQ(maj, min) 1
|
|
||||||
#define QEMU_NORETURN __attribute__ ((__noreturn__))
|
#define QEMU_NORETURN __attribute__ ((__noreturn__))
|
||||||
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||||
#define QEMU_SENTINEL __attribute__((sentinel))
|
#define QEMU_SENTINEL __attribute__((sentinel))
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
# Documentation
|
# Documentation
|
||||||
docs/*
|
docs/*
|
||||||
*.rst
|
*.rst
|
||||||
|
*.rst.inc
|
||||||
|
|
||||||
# build system
|
# build system
|
||||||
configure
|
configure
|
||||||
|
@ -28,9 +29,11 @@ qga/*.json
|
||||||
|
|
||||||
# headers
|
# headers
|
||||||
*.h
|
*.h
|
||||||
|
*.h.inc
|
||||||
|
|
||||||
# decoding tree specification
|
# decoding tree specification
|
||||||
*.decode
|
*.decode
|
||||||
|
|
||||||
# code
|
# code
|
||||||
*.c
|
*.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)
|
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) {
|
if (dumpdtb) {
|
||||||
/* Dump the dtb to a file and quit */
|
/* Dump the dtb to a file and quit */
|
||||||
|
|
|
@ -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->terminates = true;
|
||||||
mr->destructor = memory_region_destructor_ram;
|
mr->destructor = memory_region_destructor_ram;
|
||||||
mr->ram_block = qemu_ram_alloc(size, share, mr, &err);
|
mr->ram_block = qemu_ram_alloc(size, share, mr, &err);
|
||||||
mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
|
|
||||||
if (err) {
|
if (err) {
|
||||||
mr->size = int128_zero();
|
mr->size = int128_zero();
|
||||||
object_unparent(OBJECT(mr));
|
object_unparent(OBJECT(mr));
|
||||||
|
@ -1573,7 +1572,6 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
|
||||||
mr->destructor = memory_region_destructor_ram;
|
mr->destructor = memory_region_destructor_ram;
|
||||||
mr->ram_block = qemu_ram_alloc_resizeable(size, max_size, resized,
|
mr->ram_block = qemu_ram_alloc_resizeable(size, max_size, resized,
|
||||||
mr, &err);
|
mr, &err);
|
||||||
mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
|
|
||||||
if (err) {
|
if (err) {
|
||||||
mr->size = int128_zero();
|
mr->size = int128_zero();
|
||||||
object_unparent(OBJECT(mr));
|
object_unparent(OBJECT(mr));
|
||||||
|
@ -1598,7 +1596,6 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
|
||||||
mr->destructor = memory_region_destructor_ram;
|
mr->destructor = memory_region_destructor_ram;
|
||||||
mr->align = align;
|
mr->align = align;
|
||||||
mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path, &err);
|
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) {
|
if (err) {
|
||||||
mr->size = int128_zero();
|
mr->size = int128_zero();
|
||||||
object_unparent(OBJECT(mr));
|
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,
|
mr->ram_block = qemu_ram_alloc_from_fd(size, mr,
|
||||||
share ? RAM_SHARED : 0,
|
share ? RAM_SHARED : 0,
|
||||||
fd, &err);
|
fd, &err);
|
||||||
mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0;
|
|
||||||
if (err) {
|
if (err) {
|
||||||
mr->size = int128_zero();
|
mr->size = int128_zero();
|
||||||
object_unparent(OBJECT(mr));
|
object_unparent(OBJECT(mr));
|
||||||
|
@ -1641,7 +1637,6 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
|
||||||
mr->ram = true;
|
mr->ram = true;
|
||||||
mr->terminates = true;
|
mr->terminates = true;
|
||||||
mr->destructor = memory_region_destructor_ram;
|
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. */
|
/* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */
|
||||||
assert(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->ops = &ram_device_mem_ops;
|
||||||
mr->opaque = mr;
|
mr->opaque = mr;
|
||||||
mr->destructor = memory_region_destructor_ram;
|
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. */
|
/* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */
|
||||||
assert(ptr != NULL);
|
assert(ptr != NULL);
|
||||||
mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal);
|
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))) {
|
memory_region_is_iommu(mr))) {
|
||||||
mask |= (1 << DIRTY_MEMORY_MIGRATION);
|
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;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,17 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
|
||||||
'cpus.c',
|
'cpus.c',
|
||||||
'cpu-throttle.c',
|
'cpu-throttle.c',
|
||||||
'datadir.c',
|
'datadir.c',
|
||||||
|
'globals.c',
|
||||||
'physmem.c',
|
'physmem.c',
|
||||||
'ioport.c',
|
'ioport.c',
|
||||||
'rtc.c',
|
'rtc.c',
|
||||||
|
'runstate.c',
|
||||||
'memory.c',
|
'memory.c',
|
||||||
'memory_mapping.c',
|
'memory_mapping.c',
|
||||||
'qtest.c',
|
'qtest.c',
|
||||||
'vl.c',
|
'vl.c',
|
||||||
'cpu-timers.c',
|
'cpu-timers.c',
|
||||||
|
'runstate-action.c',
|
||||||
)])
|
)])
|
||||||
|
|
||||||
specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: [files(
|
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;
|
AddressSpaceDispatch *d;
|
||||||
hwaddr l;
|
hwaddr l;
|
||||||
MemoryRegion *mr;
|
MemoryRegion *mr;
|
||||||
|
Int128 diff;
|
||||||
|
|
||||||
assert(len > 0);
|
assert(len > 0);
|
||||||
|
|
||||||
|
@ -3263,6 +3264,15 @@ int64_t address_space_cache_init(MemoryRegionCache *cache,
|
||||||
d = flatview_to_dispatch(cache->fv);
|
d = flatview_to_dispatch(cache->fv);
|
||||||
cache->mrs = *address_space_translate_internal(d, addr, &cache->xlat, &l, true);
|
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;
|
mr = cache->mrs.mr;
|
||||||
memory_region_ref(mr);
|
memory_region_ref(mr);
|
||||||
if (memory_access_is_direct(mr, is_write)) {
|
if (memory_access_is_direct(mr, is_write)) {
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "sysemu/arch_init.h"
|
#include "sysemu/arch_init.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/qapi-commands-qdev.h"
|
#include "qapi/qapi-commands-qdev.h"
|
||||||
|
#include "qapi/qmp/dispatch.h"
|
||||||
#include "qapi/qmp/qdict.h"
|
#include "qapi/qmp/qdict.h"
|
||||||
#include "qapi/qmp/qerror.h"
|
#include "qapi/qmp/qerror.h"
|
||||||
#include "qemu/config-file.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);
|
dc = DEVICE_CLASS(oc);
|
||||||
if (!dc->user_creatable ||
|
if (!dc->user_creatable ||
|
||||||
(qdev_hotplug && !dc->hotpluggable)) {
|
(phase_check(PHASE_MACHINE_READY) && !dc->hotpluggable)) {
|
||||||
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
|
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
|
||||||
"a pluggable device type");
|
"a pluggable device type");
|
||||||
return NULL;
|
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);
|
error_setg(errp, QERR_BUS_NO_HOTPLUG, bus->name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -640,15 +641,17 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
|
||||||
dev = qdev_new(driver);
|
dev = qdev_new(driver);
|
||||||
|
|
||||||
/* Check whether the hotplug is allowed by the machine */
|
/* Check whether the hotplug is allowed by the machine */
|
||||||
if (qdev_hotplug && !qdev_hotplug_allowed(dev, errp)) {
|
if (phase_check(PHASE_MACHINE_READY)) {
|
||||||
goto err_del_dev;
|
if (!qdev_hotplug_allowed(dev, errp)) {
|
||||||
}
|
goto err_del_dev;
|
||||||
|
}
|
||||||
|
|
||||||
if (!bus && qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) {
|
if (!bus && !qdev_get_machine_hotplug_handler(dev)) {
|
||||||
/* No bus, no machine hotplug handler --> device is not hotpluggable */
|
/* No bus, no machine hotplug handler --> device is not hotpluggable */
|
||||||
error_setg(errp, "Device '%s' can not be hotplugged on this machine",
|
error_setg(errp, "Device '%s' can not be hotplugged on this machine",
|
||||||
driver);
|
driver);
|
||||||
goto err_del_dev;
|
goto err_del_dev;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qdev_set_id(dev, qemu_opts_id(opts));
|
qdev_set_id(dev, qemu_opts_id(opts));
|
||||||
|
@ -983,3 +986,14 @@ int qemu_global_option(const char *str)
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* This work is licensed under the terms of the GNU GPL, version 2.
|
||||||
|
* See the COPYING file in the top-level directory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "sysemu/runstate-action.h"
|
||||||
|
#include "sysemu/watchdog.h"
|
||||||
|
#include "qemu/config-file.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "qemu/option_int.h"
|
||||||
|
|
||||||
|
RebootAction reboot_action = REBOOT_ACTION_NONE;
|
||||||
|
ShutdownAction shutdown_action = SHUTDOWN_ACTION_POWEROFF;
|
||||||
|
PanicAction panic_action = PANIC_ACTION_POWEROFF;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Receives actions to be applied for specific guest events
|
||||||
|
* and sets the internal state as requested.
|
||||||
|
*/
|
||||||
|
void qmp_set_action(bool has_reboot, RebootAction reboot,
|
||||||
|
bool has_shutdown, ShutdownAction shutdown,
|
||||||
|
bool has_panic, PanicAction panic,
|
||||||
|
bool has_watchdog, WatchdogAction watchdog,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
if (has_reboot) {
|
||||||
|
reboot_action = reboot;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_panic) {
|
||||||
|
panic_action = panic;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_watchdog) {
|
||||||
|
qmp_watchdog_set_action(watchdog, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process shutdown last, in case the panic action needs to be altered */
|
||||||
|
if (has_shutdown) {
|
||||||
|
shutdown_action = shutdown;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,812 @@
|
||||||
|
/*
|
||||||
|
* QEMU main system emulation loop
|
||||||
|
*
|
||||||
|
* Copyright (c) 2003-2020 QEMU contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "audio/audio.h"
|
||||||
|
#include "block/block.h"
|
||||||
|
#include "chardev/char.h"
|
||||||
|
#include "crypto/cipher.h"
|
||||||
|
#include "crypto/init.h"
|
||||||
|
#include "exec/cpu-common.h"
|
||||||
|
#include "exec/exec-all.h"
|
||||||
|
#include "exec/gdbstub.h"
|
||||||
|
#include "hw/boards.h"
|
||||||
|
#include "migration/misc.h"
|
||||||
|
#include "migration/postcopy-ram.h"
|
||||||
|
#include "monitor/monitor.h"
|
||||||
|
#include "net/net.h"
|
||||||
|
#include "net/vhost_net.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "qapi/qapi-commands-run-state.h"
|
||||||
|
#include "qapi/qapi-events-run-state.h"
|
||||||
|
#include "qemu-common.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
#include "qemu/job.h"
|
||||||
|
#include "qemu/module.h"
|
||||||
|
#include "qemu/plugin.h"
|
||||||
|
#include "qemu/sockets.h"
|
||||||
|
#include "qemu/thread.h"
|
||||||
|
#include "qom/object.h"
|
||||||
|
#include "qom/object_interfaces.h"
|
||||||
|
#include "sysemu/cpus.h"
|
||||||
|
#include "sysemu/qtest.h"
|
||||||
|
#include "sysemu/replay.h"
|
||||||
|
#include "sysemu/reset.h"
|
||||||
|
#include "sysemu/runstate.h"
|
||||||
|
#include "sysemu/runstate-action.h"
|
||||||
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "sysemu/tpm.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
static NotifierList exit_notifiers =
|
||||||
|
NOTIFIER_LIST_INITIALIZER(exit_notifiers);
|
||||||
|
|
||||||
|
static RunState current_run_state = RUN_STATE_PRELAUNCH;
|
||||||
|
|
||||||
|
/* We use RUN_STATE__MAX but any invalid value will do */
|
||||||
|
static RunState vmstop_requested = RUN_STATE__MAX;
|
||||||
|
static QemuMutex vmstop_lock;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
RunState from;
|
||||||
|
RunState to;
|
||||||
|
} RunStateTransition;
|
||||||
|
|
||||||
|
static const RunStateTransition runstate_transitions_def[] = {
|
||||||
|
{ RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
|
||||||
|
|
||||||
|
{ RUN_STATE_DEBUG, RUN_STATE_RUNNING },
|
||||||
|
{ RUN_STATE_DEBUG, RUN_STATE_FINISH_MIGRATE },
|
||||||
|
{ RUN_STATE_DEBUG, RUN_STATE_PRELAUNCH },
|
||||||
|
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_INTERNAL_ERROR },
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_IO_ERROR },
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_PAUSED },
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_SHUTDOWN },
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_SUSPENDED },
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_WATCHDOG },
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_GUEST_PANICKED },
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_FINISH_MIGRATE },
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_PRELAUNCH },
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_POSTMIGRATE },
|
||||||
|
{ RUN_STATE_INMIGRATE, RUN_STATE_COLO },
|
||||||
|
|
||||||
|
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
|
||||||
|
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE },
|
||||||
|
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_PRELAUNCH },
|
||||||
|
|
||||||
|
{ RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
|
||||||
|
{ RUN_STATE_IO_ERROR, RUN_STATE_FINISH_MIGRATE },
|
||||||
|
{ RUN_STATE_IO_ERROR, RUN_STATE_PRELAUNCH },
|
||||||
|
|
||||||
|
{ RUN_STATE_PAUSED, RUN_STATE_RUNNING },
|
||||||
|
{ RUN_STATE_PAUSED, RUN_STATE_FINISH_MIGRATE },
|
||||||
|
{ RUN_STATE_PAUSED, RUN_STATE_POSTMIGRATE },
|
||||||
|
{ RUN_STATE_PAUSED, RUN_STATE_PRELAUNCH },
|
||||||
|
{ RUN_STATE_PAUSED, RUN_STATE_COLO},
|
||||||
|
|
||||||
|
{ RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
|
||||||
|
{ RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE },
|
||||||
|
{ RUN_STATE_POSTMIGRATE, RUN_STATE_PRELAUNCH },
|
||||||
|
|
||||||
|
{ RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
|
||||||
|
{ RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE },
|
||||||
|
{ RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
|
||||||
|
|
||||||
|
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
|
||||||
|
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_PAUSED },
|
||||||
|
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
|
||||||
|
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_PRELAUNCH },
|
||||||
|
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_COLO},
|
||||||
|
|
||||||
|
{ RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
|
||||||
|
{ RUN_STATE_RESTORE_VM, RUN_STATE_PRELAUNCH },
|
||||||
|
|
||||||
|
{ RUN_STATE_COLO, RUN_STATE_RUNNING },
|
||||||
|
|
||||||
|
{ RUN_STATE_RUNNING, RUN_STATE_DEBUG },
|
||||||
|
{ RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR },
|
||||||
|
{ RUN_STATE_RUNNING, RUN_STATE_IO_ERROR },
|
||||||
|
{ RUN_STATE_RUNNING, RUN_STATE_PAUSED },
|
||||||
|
{ RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE },
|
||||||
|
{ RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM },
|
||||||
|
{ RUN_STATE_RUNNING, RUN_STATE_SAVE_VM },
|
||||||
|
{ RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN },
|
||||||
|
{ RUN_STATE_RUNNING, RUN_STATE_WATCHDOG },
|
||||||
|
{ RUN_STATE_RUNNING, RUN_STATE_GUEST_PANICKED },
|
||||||
|
{ RUN_STATE_RUNNING, RUN_STATE_COLO},
|
||||||
|
|
||||||
|
{ RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
|
||||||
|
|
||||||
|
{ RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
|
||||||
|
{ RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE },
|
||||||
|
{ RUN_STATE_SHUTDOWN, RUN_STATE_PRELAUNCH },
|
||||||
|
{ RUN_STATE_SHUTDOWN, RUN_STATE_COLO },
|
||||||
|
|
||||||
|
{ RUN_STATE_DEBUG, RUN_STATE_SUSPENDED },
|
||||||
|
{ RUN_STATE_RUNNING, RUN_STATE_SUSPENDED },
|
||||||
|
{ RUN_STATE_SUSPENDED, RUN_STATE_RUNNING },
|
||||||
|
{ RUN_STATE_SUSPENDED, RUN_STATE_FINISH_MIGRATE },
|
||||||
|
{ RUN_STATE_SUSPENDED, RUN_STATE_PRELAUNCH },
|
||||||
|
{ RUN_STATE_SUSPENDED, RUN_STATE_COLO},
|
||||||
|
|
||||||
|
{ RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
|
||||||
|
{ RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
|
||||||
|
{ RUN_STATE_WATCHDOG, RUN_STATE_PRELAUNCH },
|
||||||
|
{ RUN_STATE_WATCHDOG, RUN_STATE_COLO},
|
||||||
|
|
||||||
|
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_RUNNING },
|
||||||
|
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
|
||||||
|
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_PRELAUNCH },
|
||||||
|
|
||||||
|
{ RUN_STATE__MAX, RUN_STATE__MAX },
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool runstate_valid_transitions[RUN_STATE__MAX][RUN_STATE__MAX];
|
||||||
|
|
||||||
|
bool runstate_check(RunState state)
|
||||||
|
{
|
||||||
|
return current_run_state == state;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool runstate_store(char *str, size_t size)
|
||||||
|
{
|
||||||
|
const char *state = RunState_str(current_run_state);
|
||||||
|
size_t len = strlen(state) + 1;
|
||||||
|
|
||||||
|
if (len > size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(str, state, len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void runstate_init(void)
|
||||||
|
{
|
||||||
|
const RunStateTransition *p;
|
||||||
|
|
||||||
|
memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
|
||||||
|
for (p = &runstate_transitions_def[0]; p->from != RUN_STATE__MAX; p++) {
|
||||||
|
runstate_valid_transitions[p->from][p->to] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_mutex_init(&vmstop_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function will abort() on invalid state transitions */
|
||||||
|
void runstate_set(RunState new_state)
|
||||||
|
{
|
||||||
|
assert(new_state < RUN_STATE__MAX);
|
||||||
|
|
||||||
|
trace_runstate_set(current_run_state, RunState_str(current_run_state),
|
||||||
|
new_state, RunState_str(new_state));
|
||||||
|
|
||||||
|
if (current_run_state == new_state) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!runstate_valid_transitions[current_run_state][new_state]) {
|
||||||
|
error_report("invalid runstate transition: '%s' -> '%s'",
|
||||||
|
RunState_str(current_run_state),
|
||||||
|
RunState_str(new_state));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
current_run_state = new_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
int runstate_is_running(void)
|
||||||
|
{
|
||||||
|
return runstate_check(RUN_STATE_RUNNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool runstate_needs_reset(void)
|
||||||
|
{
|
||||||
|
return runstate_check(RUN_STATE_INTERNAL_ERROR) ||
|
||||||
|
runstate_check(RUN_STATE_SHUTDOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusInfo *qmp_query_status(Error **errp)
|
||||||
|
{
|
||||||
|
StatusInfo *info = g_malloc0(sizeof(*info));
|
||||||
|
|
||||||
|
info->running = runstate_is_running();
|
||||||
|
info->singlestep = singlestep;
|
||||||
|
info->status = current_run_state;
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qemu_vmstop_requested(RunState *r)
|
||||||
|
{
|
||||||
|
qemu_mutex_lock(&vmstop_lock);
|
||||||
|
*r = vmstop_requested;
|
||||||
|
vmstop_requested = RUN_STATE__MAX;
|
||||||
|
qemu_mutex_unlock(&vmstop_lock);
|
||||||
|
return *r < RUN_STATE__MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_system_vmstop_request_prepare(void)
|
||||||
|
{
|
||||||
|
qemu_mutex_lock(&vmstop_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_system_vmstop_request(RunState state)
|
||||||
|
{
|
||||||
|
vmstop_requested = state;
|
||||||
|
qemu_mutex_unlock(&vmstop_lock);
|
||||||
|
qemu_notify_event();
|
||||||
|
}
|
||||||
|
struct VMChangeStateEntry {
|
||||||
|
VMChangeStateHandler *cb;
|
||||||
|
void *opaque;
|
||||||
|
QTAILQ_ENTRY(VMChangeStateEntry) entries;
|
||||||
|
int priority;
|
||||||
|
};
|
||||||
|
|
||||||
|
static QTAILQ_HEAD(, VMChangeStateEntry) vm_change_state_head =
|
||||||
|
QTAILQ_HEAD_INITIALIZER(vm_change_state_head);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qemu_add_vm_change_state_handler_prio:
|
||||||
|
* @cb: the callback to invoke
|
||||||
|
* @opaque: user data passed to the callback
|
||||||
|
* @priority: low priorities execute first when the vm runs and the reverse is
|
||||||
|
* true when the vm stops
|
||||||
|
*
|
||||||
|
* Register a callback function that is invoked when the vm starts or stops
|
||||||
|
* running.
|
||||||
|
*
|
||||||
|
* Returns: an entry to be freed using qemu_del_vm_change_state_handler()
|
||||||
|
*/
|
||||||
|
VMChangeStateEntry *qemu_add_vm_change_state_handler_prio(
|
||||||
|
VMChangeStateHandler *cb, void *opaque, int priority)
|
||||||
|
{
|
||||||
|
VMChangeStateEntry *e;
|
||||||
|
VMChangeStateEntry *other;
|
||||||
|
|
||||||
|
e = g_malloc0(sizeof(*e));
|
||||||
|
e->cb = cb;
|
||||||
|
e->opaque = opaque;
|
||||||
|
e->priority = priority;
|
||||||
|
|
||||||
|
/* Keep list sorted in ascending priority order */
|
||||||
|
QTAILQ_FOREACH(other, &vm_change_state_head, entries) {
|
||||||
|
if (priority < other->priority) {
|
||||||
|
QTAILQ_INSERT_BEFORE(other, e, entries);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QTAILQ_INSERT_TAIL(&vm_change_state_head, e, entries);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
return qemu_add_vm_change_state_handler_prio(cb, opaque, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
|
||||||
|
{
|
||||||
|
QTAILQ_REMOVE(&vm_change_state_head, e, entries);
|
||||||
|
g_free(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_state_notify(int running, RunState state)
|
||||||
|
{
|
||||||
|
VMChangeStateEntry *e, *next;
|
||||||
|
|
||||||
|
trace_vm_state_notify(running, state, RunState_str(state));
|
||||||
|
|
||||||
|
if (running) {
|
||||||
|
QTAILQ_FOREACH_SAFE(e, &vm_change_state_head, entries, next) {
|
||||||
|
e->cb(e->opaque, running, state);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QTAILQ_FOREACH_REVERSE_SAFE(e, &vm_change_state_head, entries, next) {
|
||||||
|
e->cb(e->opaque, running, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ShutdownCause reset_requested;
|
||||||
|
static ShutdownCause shutdown_requested;
|
||||||
|
static int shutdown_signal;
|
||||||
|
static pid_t shutdown_pid;
|
||||||
|
static int powerdown_requested;
|
||||||
|
static int debug_requested;
|
||||||
|
static int suspend_requested;
|
||||||
|
static WakeupReason wakeup_reason;
|
||||||
|
static NotifierList powerdown_notifiers =
|
||||||
|
NOTIFIER_LIST_INITIALIZER(powerdown_notifiers);
|
||||||
|
static NotifierList suspend_notifiers =
|
||||||
|
NOTIFIER_LIST_INITIALIZER(suspend_notifiers);
|
||||||
|
static NotifierList wakeup_notifiers =
|
||||||
|
NOTIFIER_LIST_INITIALIZER(wakeup_notifiers);
|
||||||
|
static NotifierList shutdown_notifiers =
|
||||||
|
NOTIFIER_LIST_INITIALIZER(shutdown_notifiers);
|
||||||
|
static uint32_t wakeup_reason_mask = ~(1 << QEMU_WAKEUP_REASON_NONE);
|
||||||
|
|
||||||
|
ShutdownCause qemu_shutdown_requested_get(void)
|
||||||
|
{
|
||||||
|
return shutdown_requested;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShutdownCause qemu_reset_requested_get(void)
|
||||||
|
{
|
||||||
|
return reset_requested;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qemu_shutdown_requested(void)
|
||||||
|
{
|
||||||
|
return qatomic_xchg(&shutdown_requested, SHUTDOWN_CAUSE_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qemu_kill_report(void)
|
||||||
|
{
|
||||||
|
if (!qtest_driver() && shutdown_signal) {
|
||||||
|
if (shutdown_pid == 0) {
|
||||||
|
/* This happens for eg ^C at the terminal, so it's worth
|
||||||
|
* avoiding printing an odd message in that case.
|
||||||
|
*/
|
||||||
|
error_report("terminating on signal %d", shutdown_signal);
|
||||||
|
} else {
|
||||||
|
char *shutdown_cmd = qemu_get_pid_name(shutdown_pid);
|
||||||
|
|
||||||
|
error_report("terminating on signal %d from pid " FMT_pid " (%s)",
|
||||||
|
shutdown_signal, shutdown_pid,
|
||||||
|
shutdown_cmd ? shutdown_cmd : "<unknown process>");
|
||||||
|
g_free(shutdown_cmd);
|
||||||
|
}
|
||||||
|
shutdown_signal = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ShutdownCause qemu_reset_requested(void)
|
||||||
|
{
|
||||||
|
ShutdownCause r = reset_requested;
|
||||||
|
|
||||||
|
if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
|
||||||
|
reset_requested = SHUTDOWN_CAUSE_NONE;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return SHUTDOWN_CAUSE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qemu_suspend_requested(void)
|
||||||
|
{
|
||||||
|
int r = suspend_requested;
|
||||||
|
if (r && replay_checkpoint(CHECKPOINT_SUSPEND_REQUESTED)) {
|
||||||
|
suspend_requested = 0;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WakeupReason qemu_wakeup_requested(void)
|
||||||
|
{
|
||||||
|
return wakeup_reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qemu_powerdown_requested(void)
|
||||||
|
{
|
||||||
|
int r = powerdown_requested;
|
||||||
|
powerdown_requested = 0;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int qemu_debug_requested(void)
|
||||||
|
{
|
||||||
|
int r = debug_requested;
|
||||||
|
debug_requested = 0;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the VM. Issue an event unless @reason is SHUTDOWN_CAUSE_NONE.
|
||||||
|
*/
|
||||||
|
void qemu_system_reset(ShutdownCause reason)
|
||||||
|
{
|
||||||
|
MachineClass *mc;
|
||||||
|
|
||||||
|
mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
|
||||||
|
|
||||||
|
cpu_synchronize_all_states();
|
||||||
|
|
||||||
|
if (mc && mc->reset) {
|
||||||
|
mc->reset(current_machine);
|
||||||
|
} else {
|
||||||
|
qemu_devices_reset();
|
||||||
|
}
|
||||||
|
if (reason && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
|
||||||
|
qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
|
||||||
|
}
|
||||||
|
cpu_synchronize_all_post_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wake the VM after suspend.
|
||||||
|
*/
|
||||||
|
static void qemu_system_wakeup(void)
|
||||||
|
{
|
||||||
|
MachineClass *mc;
|
||||||
|
|
||||||
|
mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
|
||||||
|
|
||||||
|
if (mc && mc->wakeup) {
|
||||||
|
mc->wakeup(current_machine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_system_guest_panicked(GuestPanicInformation *info)
|
||||||
|
{
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "Guest crashed");
|
||||||
|
|
||||||
|
if (current_cpu) {
|
||||||
|
current_cpu->crash_occurred = true;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* TODO: Currently the available panic actions are: none, pause, and
|
||||||
|
* poweroff, but in principle debug and reset could be supported as well.
|
||||||
|
* Investigate any potential use cases for the unimplemented actions.
|
||||||
|
*/
|
||||||
|
if (panic_action == PANIC_ACTION_PAUSE) {
|
||||||
|
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE,
|
||||||
|
!!info, info);
|
||||||
|
vm_stop(RUN_STATE_GUEST_PANICKED);
|
||||||
|
} else if (panic_action == PANIC_ACTION_POWEROFF) {
|
||||||
|
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF,
|
||||||
|
!!info, info);
|
||||||
|
vm_stop(RUN_STATE_GUEST_PANICKED);
|
||||||
|
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
|
||||||
|
} else {
|
||||||
|
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_RUN,
|
||||||
|
!!info, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info) {
|
||||||
|
if (info->type == GUEST_PANIC_INFORMATION_TYPE_HYPER_V) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "\nHV crash parameters: (%#"PRIx64
|
||||||
|
" %#"PRIx64" %#"PRIx64" %#"PRIx64" %#"PRIx64")\n",
|
||||||
|
info->u.hyper_v.arg1,
|
||||||
|
info->u.hyper_v.arg2,
|
||||||
|
info->u.hyper_v.arg3,
|
||||||
|
info->u.hyper_v.arg4,
|
||||||
|
info->u.hyper_v.arg5);
|
||||||
|
} else if (info->type == GUEST_PANIC_INFORMATION_TYPE_S390) {
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, " on cpu %d: %s\n"
|
||||||
|
"PSW: 0x%016" PRIx64 " 0x%016" PRIx64"\n",
|
||||||
|
info->u.s390.core,
|
||||||
|
S390CrashReason_str(info->u.s390.reason),
|
||||||
|
info->u.s390.psw_mask,
|
||||||
|
info->u.s390.psw_addr);
|
||||||
|
}
|
||||||
|
qapi_free_GuestPanicInformation(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_system_guest_crashloaded(GuestPanicInformation *info)
|
||||||
|
{
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "Guest crash loaded");
|
||||||
|
|
||||||
|
qapi_event_send_guest_crashloaded(GUEST_PANIC_ACTION_RUN,
|
||||||
|
!!info, info);
|
||||||
|
|
||||||
|
if (info) {
|
||||||
|
qapi_free_GuestPanicInformation(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_system_reset_request(ShutdownCause reason)
|
||||||
|
{
|
||||||
|
if (reboot_action == REBOOT_ACTION_SHUTDOWN &&
|
||||||
|
reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) {
|
||||||
|
shutdown_requested = reason;
|
||||||
|
} else {
|
||||||
|
reset_requested = reason;
|
||||||
|
}
|
||||||
|
cpu_stop_current();
|
||||||
|
qemu_notify_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qemu_system_suspend(void)
|
||||||
|
{
|
||||||
|
pause_all_vcpus();
|
||||||
|
notifier_list_notify(&suspend_notifiers, NULL);
|
||||||
|
runstate_set(RUN_STATE_SUSPENDED);
|
||||||
|
qapi_event_send_suspend();
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_system_suspend_request(void)
|
||||||
|
{
|
||||||
|
if (runstate_check(RUN_STATE_SUSPENDED)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
suspend_requested = 1;
|
||||||
|
cpu_stop_current();
|
||||||
|
qemu_notify_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_register_suspend_notifier(Notifier *notifier)
|
||||||
|
{
|
||||||
|
notifier_list_add(&suspend_notifiers, notifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_system_wakeup_request(WakeupReason reason, Error **errp)
|
||||||
|
{
|
||||||
|
trace_system_wakeup_request(reason);
|
||||||
|
|
||||||
|
if (!runstate_check(RUN_STATE_SUSPENDED)) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Unable to wake up: guest is not in suspended state");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(wakeup_reason_mask & (1 << reason))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
runstate_set(RUN_STATE_RUNNING);
|
||||||
|
wakeup_reason = reason;
|
||||||
|
qemu_notify_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_system_wakeup_enable(WakeupReason reason, bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled) {
|
||||||
|
wakeup_reason_mask |= (1 << reason);
|
||||||
|
} else {
|
||||||
|
wakeup_reason_mask &= ~(1 << reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_register_wakeup_notifier(Notifier *notifier)
|
||||||
|
{
|
||||||
|
notifier_list_add(&wakeup_notifiers, notifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool wakeup_suspend_enabled;
|
||||||
|
|
||||||
|
void qemu_register_wakeup_support(void)
|
||||||
|
{
|
||||||
|
wakeup_suspend_enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool qemu_wakeup_suspend_enabled(void)
|
||||||
|
{
|
||||||
|
return wakeup_suspend_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_system_killed(int signal, pid_t pid)
|
||||||
|
{
|
||||||
|
shutdown_signal = signal;
|
||||||
|
shutdown_pid = pid;
|
||||||
|
shutdown_action = SHUTDOWN_ACTION_POWEROFF;
|
||||||
|
|
||||||
|
/* Cannot call qemu_system_shutdown_request directly because
|
||||||
|
* we are in a signal handler.
|
||||||
|
*/
|
||||||
|
shutdown_requested = SHUTDOWN_CAUSE_HOST_SIGNAL;
|
||||||
|
qemu_notify_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_system_shutdown_request(ShutdownCause reason)
|
||||||
|
{
|
||||||
|
trace_qemu_system_shutdown_request(reason);
|
||||||
|
replay_shutdown_request(reason);
|
||||||
|
shutdown_requested = reason;
|
||||||
|
qemu_notify_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qemu_system_powerdown(void)
|
||||||
|
{
|
||||||
|
qapi_event_send_powerdown();
|
||||||
|
notifier_list_notify(&powerdown_notifiers, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qemu_system_shutdown(ShutdownCause cause)
|
||||||
|
{
|
||||||
|
qapi_event_send_shutdown(shutdown_caused_by_guest(cause), cause);
|
||||||
|
notifier_list_notify(&shutdown_notifiers, &cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_system_powerdown_request(void)
|
||||||
|
{
|
||||||
|
trace_qemu_system_powerdown_request();
|
||||||
|
powerdown_requested = 1;
|
||||||
|
qemu_notify_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_register_powerdown_notifier(Notifier *notifier)
|
||||||
|
{
|
||||||
|
notifier_list_add(&powerdown_notifiers, notifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_register_shutdown_notifier(Notifier *notifier)
|
||||||
|
{
|
||||||
|
notifier_list_add(&shutdown_notifiers, notifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_system_debug_request(void)
|
||||||
|
{
|
||||||
|
debug_requested = 1;
|
||||||
|
qemu_notify_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool main_loop_should_exit(void)
|
||||||
|
{
|
||||||
|
RunState r;
|
||||||
|
ShutdownCause request;
|
||||||
|
|
||||||
|
if (qemu_debug_requested()) {
|
||||||
|
vm_stop(RUN_STATE_DEBUG);
|
||||||
|
}
|
||||||
|
if (qemu_suspend_requested()) {
|
||||||
|
qemu_system_suspend();
|
||||||
|
}
|
||||||
|
request = qemu_shutdown_requested();
|
||||||
|
if (request) {
|
||||||
|
qemu_kill_report();
|
||||||
|
qemu_system_shutdown(request);
|
||||||
|
if (shutdown_action == SHUTDOWN_ACTION_PAUSE) {
|
||||||
|
vm_stop(RUN_STATE_SHUTDOWN);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request = qemu_reset_requested();
|
||||||
|
if (request) {
|
||||||
|
pause_all_vcpus();
|
||||||
|
qemu_system_reset(request);
|
||||||
|
resume_all_vcpus();
|
||||||
|
/*
|
||||||
|
* runstate can change in pause_all_vcpus()
|
||||||
|
* as iothread mutex is unlocked
|
||||||
|
*/
|
||||||
|
if (!runstate_check(RUN_STATE_RUNNING) &&
|
||||||
|
!runstate_check(RUN_STATE_INMIGRATE) &&
|
||||||
|
!runstate_check(RUN_STATE_FINISH_MIGRATE)) {
|
||||||
|
runstate_set(RUN_STATE_PRELAUNCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (qemu_wakeup_requested()) {
|
||||||
|
pause_all_vcpus();
|
||||||
|
qemu_system_wakeup();
|
||||||
|
notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
|
||||||
|
wakeup_reason = QEMU_WAKEUP_REASON_NONE;
|
||||||
|
resume_all_vcpus();
|
||||||
|
qapi_event_send_wakeup();
|
||||||
|
}
|
||||||
|
if (qemu_powerdown_requested()) {
|
||||||
|
qemu_system_powerdown();
|
||||||
|
}
|
||||||
|
if (qemu_vmstop_requested(&r)) {
|
||||||
|
vm_stop(r);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_main_loop(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_PROFILER
|
||||||
|
int64_t ti;
|
||||||
|
#endif
|
||||||
|
while (!main_loop_should_exit()) {
|
||||||
|
#ifdef CONFIG_PROFILER
|
||||||
|
ti = profile_getclock();
|
||||||
|
#endif
|
||||||
|
main_loop_wait(false);
|
||||||
|
#ifdef CONFIG_PROFILER
|
||||||
|
dev_time += profile_getclock() - ti;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_add_exit_notifier(Notifier *notify)
|
||||||
|
{
|
||||||
|
notifier_list_add(&exit_notifiers, notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_remove_exit_notifier(Notifier *notify)
|
||||||
|
{
|
||||||
|
notifier_remove(notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qemu_run_exit_notifiers(void)
|
||||||
|
{
|
||||||
|
notifier_list_notify(&exit_notifiers, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qemu_init_subsystems(void)
|
||||||
|
{
|
||||||
|
Error *err;
|
||||||
|
|
||||||
|
os_set_line_buffering();
|
||||||
|
|
||||||
|
module_call_init(MODULE_INIT_TRACE);
|
||||||
|
|
||||||
|
qemu_init_cpu_list();
|
||||||
|
qemu_init_cpu_loop();
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
|
|
||||||
|
atexit(qemu_run_exit_notifiers);
|
||||||
|
|
||||||
|
module_call_init(MODULE_INIT_QOM);
|
||||||
|
module_call_init(MODULE_INIT_MIGRATION);
|
||||||
|
|
||||||
|
runstate_init();
|
||||||
|
precopy_infrastructure_init();
|
||||||
|
postcopy_infrastructure_init();
|
||||||
|
monitor_init_globals();
|
||||||
|
|
||||||
|
if (qcrypto_init(&err) < 0) {
|
||||||
|
error_reportf_err(err, "cannot initialize crypto: ");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
os_setup_early_signal_handling();
|
||||||
|
|
||||||
|
bdrv_init_with_whitelist();
|
||||||
|
socket_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void qemu_cleanup(void)
|
||||||
|
{
|
||||||
|
gdbserver_cleanup();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cleaning up the migration object cancels any existing migration
|
||||||
|
* try to do this early so that it also stops using devices.
|
||||||
|
*/
|
||||||
|
migration_shutdown();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We must cancel all block jobs while the block layer is drained,
|
||||||
|
* or cancelling will be affected by throttling and thus may block
|
||||||
|
* for an extended period of time.
|
||||||
|
* vm_shutdown() will bdrv_drain_all(), so we may as well include
|
||||||
|
* it in the drained section.
|
||||||
|
* We do not need to end this section, because we do not want any
|
||||||
|
* requests happening from here on anyway.
|
||||||
|
*/
|
||||||
|
bdrv_drain_all_begin();
|
||||||
|
|
||||||
|
/* No more vcpu or device emulation activity beyond this point */
|
||||||
|
vm_shutdown();
|
||||||
|
replay_finish();
|
||||||
|
|
||||||
|
job_cancel_sync_all();
|
||||||
|
bdrv_close_all();
|
||||||
|
|
||||||
|
/* vhost-user must be cleaned up before chardevs. */
|
||||||
|
tpm_cleanup();
|
||||||
|
net_cleanup();
|
||||||
|
audio_cleanup();
|
||||||
|
monitor_cleanup();
|
||||||
|
qemu_chr_cleanup();
|
||||||
|
user_creatable_cleanup();
|
||||||
|
/* TODO: unref root container, check all devices are ok */
|
||||||
|
}
|
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('isa-bus.c'))
|
||||||
stub_ss.add(files('is-daemonized.c'))
|
stub_ss.add(files('is-daemonized.c'))
|
||||||
stub_ss.add(when: 'CONFIG_LINUX_AIO', if_true: files('linux-aio.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('migr-blocker.c'))
|
||||||
stub_ss.add(files('monitor.c'))
|
stub_ss.add(files('monitor.c'))
|
||||||
stub_ss.add(files('monitor-core.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('pci-host-piix.c'))
|
||||||
stub_ss.add(files('qemu-timer-notify-cb.c'))
|
stub_ss.add(files('qemu-timer-notify-cb.c'))
|
||||||
stub_ss.add(files('qmp_memory_device.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('qtest.c'))
|
||||||
stub_ss.add(files('ram-block.c'))
|
stub_ss.add(files('ram-block.c'))
|
||||||
stub_ss.add(files('ramfb.c'))
|
stub_ss.add(files('ramfb.c'))
|
||||||
|
|
|
@ -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",
|
argv_source += ["-mem-path", "/dev/shm",
|
||||||
"-mem-prealloc"]
|
"-mem-prealloc"]
|
||||||
if hardware._locked_pages:
|
if hardware._locked_pages:
|
||||||
argv_source += ["-realtime", "mlock=on"]
|
argv_source += ["-overcommit", "mem-lock=on"]
|
||||||
if hardware._huge_pages:
|
if hardware._huge_pages:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,55 @@ static void test_lp1878642_pci_bus_get_irq_level_assert(void)
|
||||||
qtest_quit(s);
|
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)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
const char *arch = qtest_get_arch();
|
const char *arch = qtest_get_arch();
|
||||||
|
@ -59,6 +108,8 @@ int main(int argc, char **argv)
|
||||||
test_lp1878263_megasas_zero_iov_cnt);
|
test_lp1878263_megasas_zero_iov_cnt);
|
||||||
qtest_add_func("fuzz/test_lp1878642_pci_bus_get_irq_level_assert",
|
qtest_add_func("fuzz/test_lp1878642_pci_bus_get_irq_level_assert",
|
||||||
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();
|
return g_test_run();
|
||||||
|
|
|
@ -11,13 +11,36 @@
|
||||||
#include "libqos/libqtest.h"
|
#include "libqos/libqtest.h"
|
||||||
#include "qapi/qmp/qdict.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)
|
static void test_panic(void)
|
||||||
{
|
{
|
||||||
uint8_t val;
|
uint8_t val;
|
||||||
QDict *response, *data;
|
QDict *response, *data;
|
||||||
QTestState *qts;
|
QTestState *qts;
|
||||||
|
|
||||||
qts = qtest_init("-device pvpanic");
|
qts = qtest_init("-device pvpanic -action panic=pause");
|
||||||
|
|
||||||
val = qtest_inb(qts, 0x505);
|
val = qtest_inb(qts, 0x505);
|
||||||
g_assert_cmpuint(val, ==, 3);
|
g_assert_cmpuint(val, ==, 3);
|
||||||
|
@ -40,6 +63,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
g_test_init(&argc, &argv, NULL);
|
g_test_init(&argc, &argv, NULL);
|
||||||
qtest_add_func("/pvpanic/panic", test_panic);
|
qtest_add_func("/pvpanic/panic", test_panic);
|
||||||
|
qtest_add_func("/pvpanic/panic-nopause", test_panic_nopause);
|
||||||
|
|
||||||
ret = g_test_run();
|
ret = g_test_run();
|
||||||
|
|
||||||
|
|
|
@ -295,7 +295,7 @@ static void test_qmp_preconfig(void)
|
||||||
rsp = qtest_qmp(qs, "{ 'execute': 'query-status' }");
|
rsp = qtest_qmp(qs, "{ 'execute': 'query-status' }");
|
||||||
ret = qdict_get_qdict(rsp, "return");
|
ret = qdict_get_qdict(rsp, "return");
|
||||||
g_assert(ret);
|
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);
|
qobject_unref(rsp);
|
||||||
|
|
||||||
/* exit preconfig state */
|
/* exit preconfig state */
|
||||||
|
|
|
@ -73,11 +73,9 @@ static void print_int64(int i, int64_t num)
|
||||||
|
|
||||||
#ifndef SNANF
|
#ifndef SNANF
|
||||||
/* Signaling NaN macros, if supported. */
|
/* Signaling NaN macros, if supported. */
|
||||||
# if __GNUC_PREREQ(3, 3)
|
# define SNANF (__builtin_nansf (""))
|
||||||
# define SNANF (__builtin_nansf (""))
|
# define SNAN (__builtin_nans (""))
|
||||||
# define SNAN (__builtin_nans (""))
|
# define SNANL (__builtin_nansl (""))
|
||||||
# define SNANL (__builtin_nansl (""))
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float single_numbers[] = { -SNANF,
|
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!
|
* On 32bit systems please add -D_FILE_OFFSET_BITS=64 to your compile flags!
|
||||||
*/
|
*/
|
||||||
|
QEMU_BUILD_BUG_ON(sizeof(off_t) != 8);
|
||||||
#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
|
|
||||||
|
|
||||||
#endif /* FUSE_COMMON_H_ */
|
#endif /* FUSE_COMMON_H_ */
|
||||||
|
|
|
@ -1345,7 +1345,7 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
|
||||||
if (QTAILQ_EMPTY(&consoles)) {
|
if (QTAILQ_EMPTY(&consoles)) {
|
||||||
s->index = 0;
|
s->index = 0;
|
||||||
QTAILQ_INSERT_TAIL(&consoles, s, next);
|
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);
|
QemuConsole *last = QTAILQ_LAST(&consoles);
|
||||||
s->index = last->index + 1;
|
s->index = last->index + 1;
|
||||||
QTAILQ_INSERT_TAIL(&consoles, s, next);
|
QTAILQ_INSERT_TAIL(&consoles, s, next);
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "ui/input.h"
|
#include "ui/input.h"
|
||||||
#include "ui/sdl2.h"
|
#include "ui/sdl2.h"
|
||||||
#include "sysemu/runstate.h"
|
#include "sysemu/runstate.h"
|
||||||
|
#include "sysemu/runstate-action.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "ui/win32-kbd-hook.h"
|
#include "ui/win32-kbd-hook.h"
|
||||||
|
|
||||||
|
@ -606,7 +607,7 @@ static void handle_windowevent(SDL_Event *ev)
|
||||||
allow_close = false;
|
allow_close = false;
|
||||||
}
|
}
|
||||||
if (allow_close) {
|
if (allow_close) {
|
||||||
no_shutdown = 0;
|
shutdown_action = SHUTDOWN_ACTION_POWEROFF;
|
||||||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
|
qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -653,7 +654,7 @@ void sdl2_poll_events(struct sdl2_console *scon)
|
||||||
allow_close = false;
|
allow_close = false;
|
||||||
}
|
}
|
||||||
if (allow_close) {
|
if (allow_close) {
|
||||||
no_shutdown = 0;
|
shutdown_action = SHUTDOWN_ACTION_POWEROFF;
|
||||||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
|
qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -38,27 +38,19 @@
|
||||||
#include "qemu/help_option.h"
|
#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)
|
* first byte of the option name)
|
||||||
*
|
*
|
||||||
* The option name is delimited by delim (usually , or =) or the string end
|
* The option name is @len characters long and is copied into @option. The
|
||||||
* and is copied into option. The caller is responsible for free'ing option
|
* caller is responsible for free'ing @option when no longer required.
|
||||||
* when no longer required.
|
|
||||||
*
|
*
|
||||||
* The return value is the position of the delimiter/zero byte after the option
|
* 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);
|
*option = g_strndup(p, len);
|
||||||
|
return p + len;
|
||||||
if (offset) {
|
|
||||||
*option = g_strndup(p, offset - p);
|
|
||||||
return offset;
|
|
||||||
} else {
|
|
||||||
*option = g_strdup(p);
|
|
||||||
return p + strlen(p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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)
|
int qemu_opt_unset(QemuOpts *opts, const char *name)
|
||||||
{
|
{
|
||||||
QemuOpt *opt = qemu_opt_find(opts, name);
|
QemuOpt *opt = qemu_opt_find(opts, name);
|
||||||
|
|
||||||
assert(opts_accepts_any(opts));
|
assert(opts_accepts_any(opts->list));
|
||||||
|
|
||||||
if (opt == NULL) {
|
if (opt == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -508,9 +500,10 @@ static bool opt_validate(QemuOpt *opt, bool *help_wanted,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
const QemuOptDesc *desc;
|
const QemuOptDesc *desc;
|
||||||
|
const QemuOptsList *list = opt->opts->list;
|
||||||
|
|
||||||
desc = find_desc_by_name(opt->opts->list->desc, opt->name);
|
desc = find_desc_by_name(list->desc, opt->name);
|
||||||
if (!desc && !opts_accepts_any(opt->opts)) {
|
if (!desc && !opts_accepts_any(list)) {
|
||||||
error_setg(errp, QERR_INVALID_PARAMETER, opt->name);
|
error_setg(errp, QERR_INVALID_PARAMETER, opt->name);
|
||||||
if (help_wanted && is_help_option(opt->name)) {
|
if (help_wanted && is_help_option(opt->name)) {
|
||||||
*help_wanted = true;
|
*help_wanted = true;
|
||||||
|
@ -543,9 +536,10 @@ bool qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val,
|
||||||
{
|
{
|
||||||
QemuOpt *opt;
|
QemuOpt *opt;
|
||||||
const QemuOptDesc *desc;
|
const QemuOptDesc *desc;
|
||||||
|
const QemuOptsList *list = opts->list;
|
||||||
|
|
||||||
desc = find_desc_by_name(opts->list->desc, name);
|
desc = find_desc_by_name(list->desc, name);
|
||||||
if (!desc && !opts_accepts_any(opts)) {
|
if (!desc && !opts_accepts_any(list)) {
|
||||||
error_setg(errp, QERR_INVALID_PARAMETER, name);
|
error_setg(errp, QERR_INVALID_PARAMETER, name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -565,9 +559,10 @@ bool qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val,
|
||||||
{
|
{
|
||||||
QemuOpt *opt;
|
QemuOpt *opt;
|
||||||
const QemuOptDesc *desc;
|
const QemuOptDesc *desc;
|
||||||
|
const QemuOptsList *list = opts->list;
|
||||||
|
|
||||||
desc = find_desc_by_name(opts->list->desc, name);
|
desc = find_desc_by_name(list->desc, name);
|
||||||
if (!desc && !opts_accepts_any(opts)) {
|
if (!desc && !opts_accepts_any(list)) {
|
||||||
error_setg(errp, QERR_INVALID_PARAMETER, name);
|
error_setg(errp, QERR_INVALID_PARAMETER, name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -766,12 +761,11 @@ static const char *get_opt_name_value(const char *params,
|
||||||
const char *firstname,
|
const char *firstname,
|
||||||
char **name, char **value)
|
char **name, char **value)
|
||||||
{
|
{
|
||||||
const char *p, *pe, *pc;
|
const char *p;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
pe = strchr(params, '=');
|
len = strcspn(params, "=,");
|
||||||
pc = strchr(params, ',');
|
if (params[len] != '=') {
|
||||||
|
|
||||||
if (!pe || (pc && pc < pe)) {
|
|
||||||
/* found "foo,more" */
|
/* found "foo,more" */
|
||||||
if (firstname) {
|
if (firstname) {
|
||||||
/* implicitly named first option */
|
/* implicitly named first option */
|
||||||
|
@ -779,7 +773,7 @@ static const char *get_opt_name_value(const char *params,
|
||||||
p = get_opt_value(params, value);
|
p = get_opt_value(params, value);
|
||||||
} else {
|
} else {
|
||||||
/* option without value, must be a flag */
|
/* 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) {
|
if (strncmp(*name, "no", 2) == 0) {
|
||||||
memmove(*name, *name + 2, strlen(*name + 2) + 1);
|
memmove(*name, *name + 2, strlen(*name + 2) + 1);
|
||||||
*value = g_strdup("off");
|
*value = g_strdup("off");
|
||||||
|
@ -789,7 +783,7 @@ static const char *get_opt_name_value(const char *params,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* found "foo=bar,more" */
|
/* found "foo=bar,more" */
|
||||||
p = get_opt_name(params, name, '=');
|
p = get_opt_name(params, name, len);
|
||||||
assert(*p == '=');
|
assert(*p == '=');
|
||||||
p++;
|
p++;
|
||||||
p = get_opt_value(p, value);
|
p = get_opt_value(p, value);
|
||||||
|
@ -1116,7 +1110,7 @@ bool qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
|
||||||
{
|
{
|
||||||
QemuOpt *opt;
|
QemuOpt *opt;
|
||||||
|
|
||||||
assert(opts_accepts_any(opts));
|
assert(opts_accepts_any(opts->list));
|
||||||
|
|
||||||
QTAILQ_FOREACH(opt, &opts->head, next) {
|
QTAILQ_FOREACH(opt, &opts->head, next) {
|
||||||
opt->desc = find_desc_by_name(desc, opt->name);
|
opt->desc = find_desc_by_name(desc, opt->name);
|
||||||
|
|
Loading…
Reference in New Issue