* hot-unplug fixes for ioport
* purge qatomic_mb_read/set from monitor * build system fixes * OHCI fix from gitlab * provide EPYC-Rome CPU model not susceptible to XSAVES erratum -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmRvGpEUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroOa/Af/WS5/tmIlEYgH7UOPERQXNqf7+Jwj bA2wgqv3ZoQwcgp5f4EVjfA8ABfpGxLZy6xIdUSbWANb8lDJNuh/nPd/em3rWUAU LnJGGdo1vF31gfsVQnlzb7hJi3ur+e2f8JqkRVskDCk3a7YY44OCN42JdKWLrN9u CFf2zYqxMqXHjrYrY0Kx2oTkfGDZrfwUlx0vM4dHb8IEoxaplfDd8lJXQzjO4htr 3nPBPjQ+h08EeC7mObH4XoJE0omzovR10GkBo8K4q952xGOQ041Y/2YY7JwLfx0D na7IanVo+ZAmvTJZoJFSBwNnXkTMHvDH5+Hc45NSTsDBtz0YJhRxPw/z/A== =A5Lp -----END PGP SIGNATURE----- Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging * hot-unplug fixes for ioport * purge qatomic_mb_read/set from monitor * build system fixes * OHCI fix from gitlab * provide EPYC-Rome CPU model not susceptible to XSAVES erratum # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmRvGpEUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroOa/Af/WS5/tmIlEYgH7UOPERQXNqf7+Jwj # bA2wgqv3ZoQwcgp5f4EVjfA8ABfpGxLZy6xIdUSbWANb8lDJNuh/nPd/em3rWUAU # LnJGGdo1vF31gfsVQnlzb7hJi3ur+e2f8JqkRVskDCk3a7YY44OCN42JdKWLrN9u # CFf2zYqxMqXHjrYrY0Kx2oTkfGDZrfwUlx0vM4dHb8IEoxaplfDd8lJXQzjO4htr # 3nPBPjQ+h08EeC7mObH4XoJE0omzovR10GkBo8K4q952xGOQ041Y/2YY7JwLfx0D # na7IanVo+ZAmvTJZoJFSBwNnXkTMHvDH5+Hc45NSTsDBtz0YJhRxPw/z/A== # =A5Lp # -----END PGP SIGNATURE----- # gpg: Signature made Thu 25 May 2023 01:21:37 AM PDT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [undefined] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # 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 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: monitor: do not use mb_read/mb_set monitor: extract request dequeuing to a new function monitor: introduce qmp_dispatcher_co_wake monitor: cleanup fetching of QMP requests monitor: cleanup detection of qmp_dispatcher_co shutting down monitor: do not use mb_read/mb_set for suspend_cnt monitor: add more *_locked() functions monitor: allow calling monitor_resume under mon_lock monitor: use QEMU_LOCK_GUARD a bit more softmmu/ioport.c: make MemoryRegionPortioList owner of portio_list MemoryRegions softmmu/ioport.c: QOMify MemoryRegionPortioList softmmu/ioport.c: allocate MemoryRegionPortioList ports on the heap usb/ohci: Set pad to 0 after frame update meson: move -no-pie from linker to compiler meson: fix rule for qemu-ga installer meson.build: Fix glib -Wno-unused-function workaround target/i386: EPYC-Rome model without XSAVES Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
6ad2c71c23
@ -1239,6 +1239,8 @@ static void ohci_frame_boundary(void *opaque)
|
|||||||
/* Increment frame number and take care of endianness. */
|
/* Increment frame number and take care of endianness. */
|
||||||
ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
|
ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
|
||||||
hcca.frame = cpu_to_le16(ohci->frame_number);
|
hcca.frame = cpu_to_le16(ohci->frame_number);
|
||||||
|
/* When the HC updates frame number, set pad to 0. Ref OHCI Spec 4.4.1*/
|
||||||
|
hcca.pad = 0;
|
||||||
|
|
||||||
if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
|
if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) {
|
||||||
if (!ohci->done) {
|
if (!ohci->done) {
|
||||||
|
@ -40,6 +40,9 @@ void monitor_flush(Monitor *mon);
|
|||||||
int monitor_set_cpu(Monitor *mon, int cpu_index);
|
int monitor_set_cpu(Monitor *mon, int cpu_index);
|
||||||
int monitor_get_cpu_index(Monitor *mon);
|
int monitor_get_cpu_index(Monitor *mon);
|
||||||
|
|
||||||
|
int monitor_puts_locked(Monitor *mon, const char *str);
|
||||||
|
void monitor_flush_locked(Monitor *mon);
|
||||||
|
|
||||||
void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp);
|
void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp);
|
||||||
|
|
||||||
void monitor_read_command(MonitorHMP *mon, int show_prompt);
|
void monitor_read_command(MonitorHMP *mon, int show_prompt);
|
||||||
|
21
meson.build
21
meson.build
@ -265,12 +265,21 @@ endif
|
|||||||
|
|
||||||
# Meson currently only handles pie as a boolean for now, so if the user
|
# Meson currently only handles pie as a boolean for now, so if the user
|
||||||
# has explicitly disabled PIE we need to extend our cflags.
|
# has explicitly disabled PIE we need to extend our cflags.
|
||||||
|
#
|
||||||
|
# -no-pie is supposedly a linker flag that has no effect on the compiler
|
||||||
|
# command line, but some distros, that didn't quite know what they were
|
||||||
|
# doing, made local changes to gcc's specs file that turned it into
|
||||||
|
# a compiler command-line flag.
|
||||||
|
#
|
||||||
|
# What about linker flags? For a static build, no PIE is implied by -static
|
||||||
|
# which we added above (and if it's not because of the same specs patching,
|
||||||
|
# there's nothing we can do: compilation will fail, report a bug to your
|
||||||
|
# distro and do not use --disable-pie in the meanwhile). For dynamic linking,
|
||||||
|
# instead, we can't add -no-pie because it overrides -shared: the linker then
|
||||||
|
# tries to build an executable instead of a shared library and fails. So
|
||||||
|
# don't add -no-pie anywhere and cross fingers. :(
|
||||||
if not get_option('b_pie')
|
if not get_option('b_pie')
|
||||||
qemu_common_flags += cc.get_supported_arguments('-fno-pie')
|
qemu_common_flags += cc.get_supported_arguments('-fno-pie', '-no-pie')
|
||||||
if not get_option('prefer_static')
|
|
||||||
# No PIE is implied by -static which we added above.
|
|
||||||
qemu_ldflags += cc.get_supported_link_arguments('-no-pie')
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if not get_option('stack_protector').disabled()
|
if not get_option('stack_protector').disabled()
|
||||||
@ -780,7 +789,7 @@ if not cc.compiles('''
|
|||||||
g_free(f);
|
g_free(f);
|
||||||
}
|
}
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(Foo, foo_free)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(Foo, foo_free)
|
||||||
int main(void) { return 0; }''', dependencies: glib_pc, args: ['-Werror'])
|
int main(void) { return 0; }''', dependencies: glib_pc, args: ['-Wunused-function', '-Werror'])
|
||||||
glib_cflags += cc.get_supported_arguments('-Wno-unused-function')
|
glib_cflags += cc.get_supported_arguments('-Wno-unused-function')
|
||||||
endif
|
endif
|
||||||
glib = declare_dependency(dependencies: [glib_pc, gmodule],
|
glib = declare_dependency(dependencies: [glib_pc, gmodule],
|
||||||
|
@ -1401,45 +1401,42 @@ static void monitor_read(void *opaque, const uint8_t *buf, int size)
|
|||||||
static void monitor_event(void *opaque, QEMUChrEvent event)
|
static void monitor_event(void *opaque, QEMUChrEvent event)
|
||||||
{
|
{
|
||||||
Monitor *mon = opaque;
|
Monitor *mon = opaque;
|
||||||
MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
|
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case CHR_EVENT_MUX_IN:
|
case CHR_EVENT_MUX_IN:
|
||||||
qemu_mutex_lock(&mon->mon_lock);
|
qemu_mutex_lock(&mon->mon_lock);
|
||||||
mon->mux_out = 0;
|
if (mon->mux_out) {
|
||||||
qemu_mutex_unlock(&mon->mon_lock);
|
mon->mux_out = 0;
|
||||||
if (mon->reset_seen) {
|
|
||||||
readline_restart(hmp_mon->rs);
|
|
||||||
monitor_resume(mon);
|
monitor_resume(mon);
|
||||||
monitor_flush(mon);
|
|
||||||
} else {
|
|
||||||
qatomic_mb_set(&mon->suspend_cnt, 0);
|
|
||||||
}
|
}
|
||||||
|
qemu_mutex_unlock(&mon->mon_lock);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHR_EVENT_MUX_OUT:
|
case CHR_EVENT_MUX_OUT:
|
||||||
if (mon->reset_seen) {
|
|
||||||
if (qatomic_mb_read(&mon->suspend_cnt) == 0) {
|
|
||||||
monitor_printf(mon, "\n");
|
|
||||||
}
|
|
||||||
monitor_flush(mon);
|
|
||||||
monitor_suspend(mon);
|
|
||||||
} else {
|
|
||||||
qatomic_inc(&mon->suspend_cnt);
|
|
||||||
}
|
|
||||||
qemu_mutex_lock(&mon->mon_lock);
|
qemu_mutex_lock(&mon->mon_lock);
|
||||||
mon->mux_out = 1;
|
if (!mon->mux_out) {
|
||||||
|
if (mon->reset_seen && !mon->suspend_cnt) {
|
||||||
|
monitor_puts_locked(mon, "\n");
|
||||||
|
} else {
|
||||||
|
monitor_flush_locked(mon);
|
||||||
|
}
|
||||||
|
monitor_suspend(mon);
|
||||||
|
mon->mux_out = 1;
|
||||||
|
}
|
||||||
qemu_mutex_unlock(&mon->mon_lock);
|
qemu_mutex_unlock(&mon->mon_lock);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CHR_EVENT_OPENED:
|
case CHR_EVENT_OPENED:
|
||||||
monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
|
monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
|
||||||
"information\n", QEMU_VERSION);
|
"information\n", QEMU_VERSION);
|
||||||
if (!mon->mux_out) {
|
qemu_mutex_lock(&mon->mon_lock);
|
||||||
readline_restart(hmp_mon->rs);
|
|
||||||
readline_show_prompt(hmp_mon->rs);
|
|
||||||
}
|
|
||||||
mon->reset_seen = 1;
|
mon->reset_seen = 1;
|
||||||
|
if (!mon->mux_out) {
|
||||||
|
/* Suspend-resume forces the prompt to be printed. */
|
||||||
|
monitor_suspend(mon);
|
||||||
|
monitor_resume(mon);
|
||||||
|
}
|
||||||
|
qemu_mutex_unlock(&mon->mon_lock);
|
||||||
mon_refcount++;
|
mon_refcount++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -94,7 +94,6 @@ typedef struct HMPCommand {
|
|||||||
|
|
||||||
struct Monitor {
|
struct Monitor {
|
||||||
CharBackend chr;
|
CharBackend chr;
|
||||||
int reset_seen;
|
|
||||||
int suspend_cnt; /* Needs to be accessed atomically */
|
int suspend_cnt; /* Needs to be accessed atomically */
|
||||||
bool is_qmp;
|
bool is_qmp;
|
||||||
bool skip_flush;
|
bool skip_flush;
|
||||||
@ -115,8 +114,8 @@ struct Monitor {
|
|||||||
QLIST_HEAD(, mon_fd_t) fds;
|
QLIST_HEAD(, mon_fd_t) fds;
|
||||||
GString *outbuf;
|
GString *outbuf;
|
||||||
guint out_watch;
|
guint out_watch;
|
||||||
/* Read under either BQL or mon_lock, written with BQL+mon_lock. */
|
|
||||||
int mux_out;
|
int mux_out;
|
||||||
|
int reset_seen;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MonitorHMP {
|
struct MonitorHMP {
|
||||||
@ -166,7 +165,6 @@ typedef QTAILQ_HEAD(MonitorList, Monitor) MonitorList;
|
|||||||
extern IOThread *mon_iothread;
|
extern IOThread *mon_iothread;
|
||||||
extern Coroutine *qmp_dispatcher_co;
|
extern Coroutine *qmp_dispatcher_co;
|
||||||
extern bool qmp_dispatcher_co_shutdown;
|
extern bool qmp_dispatcher_co_shutdown;
|
||||||
extern bool qmp_dispatcher_co_busy;
|
|
||||||
extern QmpCommandList qmp_commands, qmp_cap_negotiation_commands;
|
extern QmpCommandList qmp_commands, qmp_cap_negotiation_commands;
|
||||||
extern QemuMutex monitor_lock;
|
extern QemuMutex monitor_lock;
|
||||||
extern MonitorList mon_list;
|
extern MonitorList mon_list;
|
||||||
@ -184,6 +182,7 @@ void monitor_fdsets_cleanup(void);
|
|||||||
void qmp_send_response(MonitorQMP *mon, const QDict *rsp);
|
void qmp_send_response(MonitorQMP *mon, const QDict *rsp);
|
||||||
void monitor_data_destroy_qmp(MonitorQMP *mon);
|
void monitor_data_destroy_qmp(MonitorQMP *mon);
|
||||||
void coroutine_fn monitor_qmp_dispatcher_co(void *data);
|
void coroutine_fn monitor_qmp_dispatcher_co(void *data);
|
||||||
|
void qmp_dispatcher_co_wake(void);
|
||||||
|
|
||||||
int get_monitor_def(Monitor *mon, int64_t *pval, const char *name);
|
int get_monitor_def(Monitor *mon, int64_t *pval, const char *name);
|
||||||
void handle_hmp_command(MonitorHMP *mon, const char *cmdline);
|
void handle_hmp_command(MonitorHMP *mon, const char *cmdline);
|
||||||
|
@ -56,29 +56,11 @@ IOThread *mon_iothread;
|
|||||||
/* Coroutine to dispatch the requests received from I/O thread */
|
/* Coroutine to dispatch the requests received from I/O thread */
|
||||||
Coroutine *qmp_dispatcher_co;
|
Coroutine *qmp_dispatcher_co;
|
||||||
|
|
||||||
/* Set to true when the dispatcher coroutine should terminate */
|
|
||||||
bool qmp_dispatcher_co_shutdown;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* qmp_dispatcher_co_busy is used for synchronisation between the
|
* Set to true when the dispatcher coroutine should terminate. Protected
|
||||||
* monitor thread and the main thread to ensure that the dispatcher
|
* by monitor_lock.
|
||||||
* coroutine never gets scheduled a second time when it's already
|
|
||||||
* scheduled (scheduling the same coroutine twice is forbidden).
|
|
||||||
*
|
|
||||||
* It is true if the coroutine is active and processing requests.
|
|
||||||
* Additional requests may then be pushed onto mon->qmp_requests,
|
|
||||||
* and @qmp_dispatcher_co_shutdown may be set without further ado.
|
|
||||||
* @qmp_dispatcher_co_busy must not be woken up in this case.
|
|
||||||
*
|
|
||||||
* If false, you also have to set @qmp_dispatcher_co_busy to true and
|
|
||||||
* wake up @qmp_dispatcher_co after pushing the new requests.
|
|
||||||
*
|
|
||||||
* The coroutine will automatically change this variable back to false
|
|
||||||
* before it yields. Nobody else may set the variable to false.
|
|
||||||
*
|
|
||||||
* Access must be atomic for thread safety.
|
|
||||||
*/
|
*/
|
||||||
bool qmp_dispatcher_co_busy;
|
bool qmp_dispatcher_co_shutdown;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Protects mon_list, monitor_qapi_event_state, coroutine_mon,
|
* Protects mon_list, monitor_qapi_event_state, coroutine_mon,
|
||||||
@ -154,22 +136,19 @@ static inline bool monitor_is_hmp_non_interactive(const Monitor *mon)
|
|||||||
return !monitor_uses_readline(container_of(mon, MonitorHMP, common));
|
return !monitor_uses_readline(container_of(mon, MonitorHMP, common));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void monitor_flush_locked(Monitor *mon);
|
|
||||||
|
|
||||||
static gboolean monitor_unblocked(void *do_not_use, GIOCondition cond,
|
static gboolean monitor_unblocked(void *do_not_use, GIOCondition cond,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
{
|
{
|
||||||
Monitor *mon = opaque;
|
Monitor *mon = opaque;
|
||||||
|
|
||||||
qemu_mutex_lock(&mon->mon_lock);
|
QEMU_LOCK_GUARD(&mon->mon_lock);
|
||||||
mon->out_watch = 0;
|
mon->out_watch = 0;
|
||||||
monitor_flush_locked(mon);
|
monitor_flush_locked(mon);
|
||||||
qemu_mutex_unlock(&mon->mon_lock);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Caller must hold mon->mon_lock */
|
/* Caller must hold mon->mon_lock */
|
||||||
static void monitor_flush_locked(Monitor *mon)
|
void monitor_flush_locked(Monitor *mon)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
size_t len;
|
size_t len;
|
||||||
@ -203,18 +182,16 @@ static void monitor_flush_locked(Monitor *mon)
|
|||||||
|
|
||||||
void monitor_flush(Monitor *mon)
|
void monitor_flush(Monitor *mon)
|
||||||
{
|
{
|
||||||
qemu_mutex_lock(&mon->mon_lock);
|
QEMU_LOCK_GUARD(&mon->mon_lock);
|
||||||
monitor_flush_locked(mon);
|
monitor_flush_locked(mon);
|
||||||
qemu_mutex_unlock(&mon->mon_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* flush at every end of line */
|
/* flush at every end of line */
|
||||||
int monitor_puts(Monitor *mon, const char *str)
|
int monitor_puts_locked(Monitor *mon, const char *str)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
qemu_mutex_lock(&mon->mon_lock);
|
|
||||||
for (i = 0; str[i]; i++) {
|
for (i = 0; str[i]; i++) {
|
||||||
c = str[i];
|
c = str[i];
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
@ -225,11 +202,16 @@ int monitor_puts(Monitor *mon, const char *str)
|
|||||||
monitor_flush_locked(mon);
|
monitor_flush_locked(mon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qemu_mutex_unlock(&mon->mon_lock);
|
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int monitor_puts(Monitor *mon, const char *str)
|
||||||
|
{
|
||||||
|
QEMU_LOCK_GUARD(&mon->mon_lock);
|
||||||
|
return monitor_puts_locked(mon, str);
|
||||||
|
}
|
||||||
|
|
||||||
int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
|
int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
@ -569,6 +551,17 @@ static void monitor_accept_input(void *opaque)
|
|||||||
{
|
{
|
||||||
Monitor *mon = opaque;
|
Monitor *mon = opaque;
|
||||||
|
|
||||||
|
qemu_mutex_lock(&mon->mon_lock);
|
||||||
|
if (!monitor_is_qmp(mon) && mon->reset_seen) {
|
||||||
|
MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
|
||||||
|
assert(hmp_mon->rs);
|
||||||
|
readline_restart(hmp_mon->rs);
|
||||||
|
qemu_mutex_unlock(&mon->mon_lock);
|
||||||
|
readline_show_prompt(hmp_mon->rs);
|
||||||
|
} else {
|
||||||
|
qemu_mutex_unlock(&mon->mon_lock);
|
||||||
|
}
|
||||||
|
|
||||||
qemu_chr_fe_accept_input(&mon->chr);
|
qemu_chr_fe_accept_input(&mon->chr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,12 +580,6 @@ void monitor_resume(Monitor *mon)
|
|||||||
ctx = qemu_get_aio_context();
|
ctx = qemu_get_aio_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!monitor_is_qmp(mon)) {
|
|
||||||
MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
|
|
||||||
assert(hmp_mon->rs);
|
|
||||||
readline_show_prompt(hmp_mon->rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
aio_bh_schedule_oneshot(ctx, monitor_accept_input, mon);
|
aio_bh_schedule_oneshot(ctx, monitor_accept_input, mon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,7 +590,7 @@ int monitor_can_read(void *opaque)
|
|||||||
{
|
{
|
||||||
Monitor *mon = opaque;
|
Monitor *mon = opaque;
|
||||||
|
|
||||||
return !qatomic_mb_read(&mon->suspend_cnt);
|
return !qatomic_read(&mon->suspend_cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void monitor_list_append(Monitor *mon)
|
void monitor_list_append(Monitor *mon)
|
||||||
@ -674,14 +661,14 @@ void monitor_cleanup(void)
|
|||||||
* we'll just leave them in the queue without sending a response
|
* we'll just leave them in the queue without sending a response
|
||||||
* and monitor_data_destroy() will free them.
|
* and monitor_data_destroy() will free them.
|
||||||
*/
|
*/
|
||||||
qmp_dispatcher_co_shutdown = true;
|
WITH_QEMU_LOCK_GUARD(&monitor_lock) {
|
||||||
if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) {
|
qmp_dispatcher_co_shutdown = true;
|
||||||
aio_co_wake(qmp_dispatcher_co);
|
|
||||||
}
|
}
|
||||||
|
qmp_dispatcher_co_wake();
|
||||||
|
|
||||||
AIO_WAIT_WHILE_UNLOCKED(NULL,
|
AIO_WAIT_WHILE_UNLOCKED(NULL,
|
||||||
(aio_poll(iohandler_get_aio_context(), false),
|
(aio_poll(iohandler_get_aio_context(), false),
|
||||||
qatomic_mb_read(&qmp_dispatcher_co_busy)));
|
qatomic_read(&qmp_dispatcher_co)));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to explicitly stop the I/O thread (but not destroy it),
|
* We need to explicitly stop the I/O thread (but not destroy it),
|
||||||
@ -732,7 +719,6 @@ void monitor_init_globals(void)
|
|||||||
* rid of those assumptions.
|
* rid of those assumptions.
|
||||||
*/
|
*/
|
||||||
qmp_dispatcher_co = qemu_coroutine_create(monitor_qmp_dispatcher_co, NULL);
|
qmp_dispatcher_co = qemu_coroutine_create(monitor_qmp_dispatcher_co, NULL);
|
||||||
qatomic_mb_set(&qmp_dispatcher_co_busy, true);
|
|
||||||
aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co);
|
aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
108
monitor/qmp.c
108
monitor/qmp.c
@ -33,6 +33,30 @@
|
|||||||
#include "qapi/qmp/qlist.h"
|
#include "qapi/qmp/qlist.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* qmp_dispatcher_co_busy is used for synchronisation between the
|
||||||
|
* monitor thread and the main thread to ensure that the dispatcher
|
||||||
|
* coroutine never gets scheduled a second time when it's already
|
||||||
|
* scheduled (scheduling the same coroutine twice is forbidden).
|
||||||
|
*
|
||||||
|
* It is true if the coroutine will process at least one more request
|
||||||
|
* before going to sleep. Either it has been kicked already, or it
|
||||||
|
* is active and processing requests. Additional requests may therefore
|
||||||
|
* be pushed onto mon->qmp_requests, and @qmp_dispatcher_co_shutdown may
|
||||||
|
* be set without further ado. @qmp_dispatcher_co must not be woken up
|
||||||
|
* in this case.
|
||||||
|
*
|
||||||
|
* If false, you have to wake up @qmp_dispatcher_co after pushing new
|
||||||
|
* requests. You also have to set @qmp_dispatcher_co_busy to true
|
||||||
|
* before waking up the coroutine.
|
||||||
|
*
|
||||||
|
* The coroutine will automatically change this variable back to false
|
||||||
|
* before it yields. Nobody else may set the variable to false.
|
||||||
|
*
|
||||||
|
* Access must be atomic for thread safety.
|
||||||
|
*/
|
||||||
|
static bool qmp_dispatcher_co_busy = true;
|
||||||
|
|
||||||
struct QMPRequest {
|
struct QMPRequest {
|
||||||
/* Owner of the request */
|
/* Owner of the request */
|
||||||
MonitorQMP *mon;
|
MonitorQMP *mon;
|
||||||
@ -178,8 +202,6 @@ static QMPRequest *monitor_qmp_requests_pop_any_with_lock(void)
|
|||||||
Monitor *mon;
|
Monitor *mon;
|
||||||
MonitorQMP *qmp_mon;
|
MonitorQMP *qmp_mon;
|
||||||
|
|
||||||
QEMU_LOCK_GUARD(&monitor_lock);
|
|
||||||
|
|
||||||
QTAILQ_FOREACH(mon, &mon_list, entry) {
|
QTAILQ_FOREACH(mon, &mon_list, entry) {
|
||||||
if (!monitor_is_qmp(mon)) {
|
if (!monitor_is_qmp(mon)) {
|
||||||
continue;
|
continue;
|
||||||
@ -207,53 +229,56 @@ static QMPRequest *monitor_qmp_requests_pop_any_with_lock(void)
|
|||||||
return req_obj;
|
return req_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void coroutine_fn monitor_qmp_dispatcher_co(void *data)
|
static QMPRequest *monitor_qmp_dispatcher_pop_any(void)
|
||||||
{
|
{
|
||||||
QMPRequest *req_obj = NULL;
|
|
||||||
QDict *rsp;
|
|
||||||
bool oob_enabled;
|
|
||||||
MonitorQMP *mon;
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
assert(qatomic_mb_read(&qmp_dispatcher_co_busy) == true);
|
/*
|
||||||
|
* To avoid double scheduling, busy is true on entry to
|
||||||
|
* monitor_qmp_dispatcher_co(), and must be set again before
|
||||||
|
* aio_co_wake()-ing it.
|
||||||
|
*/
|
||||||
|
assert(qatomic_read(&qmp_dispatcher_co_busy) == true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark the dispatcher as not busy already here so that we
|
* Mark the dispatcher as not busy already here so that we
|
||||||
* don't miss any new requests coming in the middle of our
|
* don't miss any new requests coming in the middle of our
|
||||||
* processing.
|
* processing.
|
||||||
|
*
|
||||||
|
* Clear qmp_dispatcher_co_busy before reading request.
|
||||||
*/
|
*/
|
||||||
qatomic_mb_set(&qmp_dispatcher_co_busy, false);
|
qatomic_mb_set(&qmp_dispatcher_co_busy, false);
|
||||||
|
|
||||||
/* On shutdown, don't take any more requests from the queue */
|
WITH_QEMU_LOCK_GUARD(&monitor_lock) {
|
||||||
if (qmp_dispatcher_co_shutdown) {
|
QMPRequest *req_obj;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!(req_obj = monitor_qmp_requests_pop_any_with_lock())) {
|
/* On shutdown, don't take any more requests from the queue */
|
||||||
/*
|
|
||||||
* No more requests to process. Wait to be reentered from
|
|
||||||
* handle_qmp_command() when it pushes more requests, or
|
|
||||||
* from monitor_cleanup() when it requests shutdown.
|
|
||||||
*/
|
|
||||||
if (!qmp_dispatcher_co_shutdown) {
|
|
||||||
qemu_coroutine_yield();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* busy must be set to true again by whoever
|
|
||||||
* rescheduled us to avoid double scheduling
|
|
||||||
*/
|
|
||||||
assert(qatomic_xchg(&qmp_dispatcher_co_busy, false) == true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* qmp_dispatcher_co_shutdown may have changed if we
|
|
||||||
* yielded and were reentered from monitor_cleanup()
|
|
||||||
*/
|
|
||||||
if (qmp_dispatcher_co_shutdown) {
|
if (qmp_dispatcher_co_shutdown) {
|
||||||
return;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
req_obj = monitor_qmp_requests_pop_any_with_lock();
|
||||||
|
if (req_obj) {
|
||||||
|
return req_obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No more requests to process. Wait to be reentered from
|
||||||
|
* handle_qmp_command() when it pushes more requests, or
|
||||||
|
* from monitor_cleanup() when it requests shutdown.
|
||||||
|
*/
|
||||||
|
qemu_coroutine_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void coroutine_fn monitor_qmp_dispatcher_co(void *data)
|
||||||
|
{
|
||||||
|
QMPRequest *req_obj;
|
||||||
|
QDict *rsp;
|
||||||
|
bool oob_enabled;
|
||||||
|
MonitorQMP *mon;
|
||||||
|
|
||||||
|
while ((req_obj = monitor_qmp_dispatcher_pop_any()) != NULL) {
|
||||||
trace_monitor_qmp_in_band_dequeue(req_obj,
|
trace_monitor_qmp_in_band_dequeue(req_obj,
|
||||||
req_obj->mon->qmp_requests->length);
|
req_obj->mon->qmp_requests->length);
|
||||||
|
|
||||||
@ -340,6 +365,17 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data)
|
|||||||
aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co);
|
aio_co_schedule(iohandler_get_aio_context(), qmp_dispatcher_co);
|
||||||
qemu_coroutine_yield();
|
qemu_coroutine_yield();
|
||||||
}
|
}
|
||||||
|
qatomic_set(&qmp_dispatcher_co, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qmp_dispatcher_co_wake(void)
|
||||||
|
{
|
||||||
|
/* Write request before reading qmp_dispatcher_co_busy. */
|
||||||
|
smp_mb__before_rmw();
|
||||||
|
|
||||||
|
if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) {
|
||||||
|
aio_co_wake(qmp_dispatcher_co);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_qmp_command(void *opaque, QObject *req, Error *err)
|
static void handle_qmp_command(void *opaque, QObject *req, Error *err)
|
||||||
@ -403,9 +439,7 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Kick the dispatcher routine */
|
/* Kick the dispatcher routine */
|
||||||
if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) {
|
qmp_dispatcher_co_wake();
|
||||||
aio_co_wake(qmp_dispatcher_co);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size)
|
static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size)
|
||||||
|
@ -154,7 +154,7 @@ if targetos == 'windows'
|
|||||||
qemu_ga_msi_arch[cpu],
|
qemu_ga_msi_arch[cpu],
|
||||||
qemu_ga_msi_vss,
|
qemu_ga_msi_vss,
|
||||||
'-D', 'BUILD_DIR=' + meson.project_build_root(),
|
'-D', 'BUILD_DIR=' + meson.project_build_root(),
|
||||||
'-D', 'BIN_DIR=' + glib.get_variable('bindir'),
|
'-D', 'BIN_DIR=' + glib_pc.get_variable('bindir'),
|
||||||
'-D', 'QEMU_GA_VERSION=' + config_host['QEMU_GA_VERSION'],
|
'-D', 'QEMU_GA_VERSION=' + config_host['QEMU_GA_VERSION'],
|
||||||
'-D', 'QEMU_GA_MANUFACTURER=' + config_host['QEMU_GA_MANUFACTURER'],
|
'-D', 'QEMU_GA_MANUFACTURER=' + config_host['QEMU_GA_MANUFACTURER'],
|
||||||
'-D', 'QEMU_GA_DISTRO=' + config_host['QEMU_GA_DISTRO'],
|
'-D', 'QEMU_GA_DISTRO=' + config_host['QEMU_GA_DISTRO'],
|
||||||
|
@ -32,11 +32,16 @@
|
|||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
typedef struct MemoryRegionPortioList {
|
struct MemoryRegionPortioList {
|
||||||
|
Object obj;
|
||||||
|
|
||||||
MemoryRegion mr;
|
MemoryRegion mr;
|
||||||
void *portio_opaque;
|
void *portio_opaque;
|
||||||
MemoryRegionPortio ports[];
|
MemoryRegionPortio *ports;
|
||||||
} MemoryRegionPortioList;
|
};
|
||||||
|
|
||||||
|
#define TYPE_MEMORY_REGION_PORTIO_LIST "memory-region-portio-list"
|
||||||
|
OBJECT_DECLARE_SIMPLE_TYPE(MemoryRegionPortioList, MEMORY_REGION_PORTIO_LIST)
|
||||||
|
|
||||||
static uint64_t unassigned_io_read(void *opaque, hwaddr addr, unsigned size)
|
static uint64_t unassigned_io_read(void *opaque, hwaddr addr, unsigned size)
|
||||||
{
|
{
|
||||||
@ -147,7 +152,7 @@ void portio_list_destroy(PortioList *piolist)
|
|||||||
for (i = 0; i < piolist->nr; ++i) {
|
for (i = 0; i < piolist->nr; ++i) {
|
||||||
mrpio = container_of(piolist->regions[i], MemoryRegionPortioList, mr);
|
mrpio = container_of(piolist->regions[i], MemoryRegionPortioList, mr);
|
||||||
object_unparent(OBJECT(&mrpio->mr));
|
object_unparent(OBJECT(&mrpio->mr));
|
||||||
g_free(mrpio);
|
object_unref(mrpio);
|
||||||
}
|
}
|
||||||
g_free(piolist->regions);
|
g_free(piolist->regions);
|
||||||
}
|
}
|
||||||
@ -224,12 +229,15 @@ static void portio_list_add_1(PortioList *piolist,
|
|||||||
unsigned off_low, unsigned off_high)
|
unsigned off_low, unsigned off_high)
|
||||||
{
|
{
|
||||||
MemoryRegionPortioList *mrpio;
|
MemoryRegionPortioList *mrpio;
|
||||||
|
Object *owner;
|
||||||
|
char *name;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
/* Copy the sub-list and null-terminate it. */
|
/* Copy the sub-list and null-terminate it. */
|
||||||
mrpio = g_malloc0(sizeof(MemoryRegionPortioList) +
|
mrpio = MEMORY_REGION_PORTIO_LIST(
|
||||||
sizeof(MemoryRegionPortio) * (count + 1));
|
object_new(TYPE_MEMORY_REGION_PORTIO_LIST));
|
||||||
mrpio->portio_opaque = piolist->opaque;
|
mrpio->portio_opaque = piolist->opaque;
|
||||||
|
mrpio->ports = g_malloc0(sizeof(MemoryRegionPortio) * (count + 1));
|
||||||
memcpy(mrpio->ports, pio_init, sizeof(MemoryRegionPortio) * count);
|
memcpy(mrpio->ports, pio_init, sizeof(MemoryRegionPortio) * count);
|
||||||
memset(mrpio->ports + count, 0, sizeof(MemoryRegionPortio));
|
memset(mrpio->ports + count, 0, sizeof(MemoryRegionPortio));
|
||||||
|
|
||||||
@ -239,8 +247,25 @@ static void portio_list_add_1(PortioList *piolist,
|
|||||||
mrpio->ports[i].base = start + off_low;
|
mrpio->ports[i].base = start + off_low;
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_region_init_io(&mrpio->mr, piolist->owner, &portio_ops, mrpio,
|
/*
|
||||||
|
* The MemoryRegion owner is the MemoryRegionPortioList since that manages
|
||||||
|
* the lifecycle via the refcount
|
||||||
|
*/
|
||||||
|
memory_region_init_io(&mrpio->mr, OBJECT(mrpio), &portio_ops, mrpio,
|
||||||
piolist->name, off_high - off_low);
|
piolist->name, off_high - off_low);
|
||||||
|
|
||||||
|
/* Reparent the MemoryRegion to the piolist owner */
|
||||||
|
object_ref(&mrpio->mr);
|
||||||
|
object_unparent(OBJECT(&mrpio->mr));
|
||||||
|
if (!piolist->owner) {
|
||||||
|
owner = container_get(qdev_get_machine(), "/unattached");
|
||||||
|
} else {
|
||||||
|
owner = piolist->owner;
|
||||||
|
}
|
||||||
|
name = g_strdup_printf("%s[*]", piolist->name);
|
||||||
|
object_property_add_child(owner, name, OBJECT(&mrpio->mr));
|
||||||
|
g_free(name);
|
||||||
|
|
||||||
if (piolist->flush_coalesced_mmio) {
|
if (piolist->flush_coalesced_mmio) {
|
||||||
memory_region_set_flush_coalesced(&mrpio->mr);
|
memory_region_set_flush_coalesced(&mrpio->mr);
|
||||||
}
|
}
|
||||||
@ -297,3 +322,25 @@ void portio_list_del(PortioList *piolist)
|
|||||||
memory_region_del_subregion(piolist->address_space, &mrpio->mr);
|
memory_region_del_subregion(piolist->address_space, &mrpio->mr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void memory_region_portio_list_finalize(Object *obj)
|
||||||
|
{
|
||||||
|
MemoryRegionPortioList *mrpio = MEMORY_REGION_PORTIO_LIST(obj);
|
||||||
|
|
||||||
|
object_unref(&mrpio->mr);
|
||||||
|
g_free(mrpio->ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo memory_region_portio_list_info = {
|
||||||
|
.parent = TYPE_OBJECT,
|
||||||
|
.name = TYPE_MEMORY_REGION_PORTIO_LIST,
|
||||||
|
.instance_size = sizeof(MemoryRegionPortioList),
|
||||||
|
.instance_finalize = memory_region_portio_list_finalize,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ioport_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&memory_region_portio_list_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(ioport_register_types)
|
||||||
|
@ -4466,6 +4466,16 @@ static const X86CPUDefinition builtin_x86_defs[] = {
|
|||||||
},
|
},
|
||||||
.cache_info = &epyc_rome_v3_cache_info
|
.cache_info = &epyc_rome_v3_cache_info
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.version = 4,
|
||||||
|
.props = (PropValue[]) {
|
||||||
|
/* Erratum 1386 */
|
||||||
|
{ "model-id",
|
||||||
|
"AMD EPYC-Rome-v4 Processor (no XSAVES)" },
|
||||||
|
{ "xsaves", "off" },
|
||||||
|
{ /* end of list */ }
|
||||||
|
},
|
||||||
|
},
|
||||||
{ /* end of list */ }
|
{ /* end of list */ }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -74,7 +74,7 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,node-name=foo#12: Invalid node-name: 'fo
|
|||||||
|
|
||||||
Testing: -device virtio-scsi -device scsi-hd
|
Testing: -device virtio-scsi -device scsi-hd
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: -device scsi-hd: drive property not set
|
QEMU_PROG: -device scsi-hd: drive property not set
|
||||||
|
|
||||||
|
|
||||||
=== Overriding backing file ===
|
=== Overriding backing file ===
|
||||||
@ -134,7 +134,7 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||||||
|
|
||||||
Testing: -drive if=virtio
|
Testing: -drive if=virtio
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
|
QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
|
||||||
|
|
||||||
|
|
||||||
=== Attach to node in non-default iothread ===
|
=== Attach to node in non-default iothread ===
|
||||||
|
@ -74,7 +74,7 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,node-name=foo#12: Invalid node-name: 'fo
|
|||||||
|
|
||||||
Testing: -device virtio-scsi -device scsi-hd
|
Testing: -device virtio-scsi -device scsi-hd
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: -device scsi-hd: drive property not set
|
QEMU_PROG: -device scsi-hd: drive property not set
|
||||||
|
|
||||||
|
|
||||||
=== Overriding backing file ===
|
=== Overriding backing file ===
|
||||||
@ -142,11 +142,11 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||||||
|
|
||||||
Testing: -drive if=ide
|
Testing: -drive if=ide
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: Device needs media, but drive is empty
|
QEMU_PROG: Device needs media, but drive is empty
|
||||||
|
|
||||||
Testing: -drive if=virtio
|
Testing: -drive if=virtio
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
|
QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
|
||||||
|
|
||||||
Testing: -drive if=none,id=disk -device ide-cd,drive=disk
|
Testing: -drive if=none,id=disk -device ide-cd,drive=disk
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
@ -158,22 +158,22 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||||||
|
|
||||||
Testing: -drive if=none,id=disk -device ide-hd,drive=disk
|
Testing: -drive if=none,id=disk -device ide-hd,drive=disk
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty
|
QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty
|
||||||
|
|
||||||
Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk
|
Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty
|
QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty
|
||||||
|
|
||||||
|
|
||||||
=== Attach to node in non-default iothread ===
|
=== Attach to node in non-default iothread ===
|
||||||
|
|
||||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device ide-hd,drive=disk,share-rw=on
|
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device ide-hd,drive=disk,share-rw=on
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: -device ide-hd,drive=disk,share-rw=on: Cannot change iothread of active block backend
|
QEMU_PROG: -device ide-hd,drive=disk,share-rw=on: Cannot change iothread of active block backend
|
||||||
|
|
||||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-blk-pci,drive=disk,share-rw=on
|
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-blk-pci,drive=disk,share-rw=on
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: -device virtio-blk-pci,drive=disk,share-rw=on: Cannot change iothread of active block backend
|
QEMU_PROG: -device virtio-blk-pci,drive=disk,share-rw=on: Cannot change iothread of active block backend
|
||||||
|
|
||||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device lsi53c895a,id=lsi0 -device scsi-hd,bus=lsi0.0,drive=disk,share-rw=on
|
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device lsi53c895a,id=lsi0 -device scsi-hd,bus=lsi0.0,drive=disk,share-rw=on
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
@ -185,7 +185,7 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||||||
|
|
||||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-blk-pci,drive=disk,iothread=thread0,share-rw=on
|
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-blk-pci,drive=disk,iothread=thread0,share-rw=on
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: -device virtio-blk-pci,drive=disk,iothread=thread0,share-rw=on: Cannot change iothread of active block backend
|
QEMU_PROG: -device virtio-blk-pci,drive=disk,iothread=thread0,share-rw=on: Cannot change iothread of active block backend
|
||||||
|
|
||||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-scsi,id=virtio-scsi1,iothread=thread0 -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on
|
Testing: -drive file=TEST_DIR/t.qcow2,if=none,node-name=disk -object iothread,id=thread0 -device virtio-scsi,iothread=thread0,id=virtio-scsi0 -device scsi-hd,bus=virtio-scsi0.0,drive=disk,share-rw=on -device virtio-scsi,id=virtio-scsi1,iothread=thread0 -device scsi-hd,bus=virtio-scsi1.0,drive=disk,share-rw=on
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
@ -204,7 +204,7 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||||||
|
|
||||||
Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on
|
Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: Block node is read-only
|
QEMU_PROG: Block node is read-only
|
||||||
|
|
||||||
Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
|
Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
@ -220,7 +220,7 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||||||
|
|
||||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk
|
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
(qemu) QEMU_PROG: -device ide-hd,drive=disk: Block node is read-only
|
QEMU_PROG: -device ide-hd,drive=disk: Block node is read-only
|
||||||
|
|
||||||
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
|
Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
|
||||||
QEMU X.Y.Z monitor - type 'help' for more information
|
QEMU X.Y.Z monitor - type 'help' for more information
|
||||||
|
Loading…
x
Reference in New Issue
Block a user