mirror of https://github.com/xemu-project/xemu.git
* 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. */
|
||||
ohci->frame_number = (ohci->frame_number + 1) & 0xffff;
|
||||
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) {
|
||||
|
|
|
@ -40,6 +40,9 @@ void monitor_flush(Monitor *mon);
|
|||
int monitor_set_cpu(Monitor *mon, int cpu_index);
|
||||
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 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
|
||||
# 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')
|
||||
qemu_common_flags += cc.get_supported_arguments('-fno-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
|
||||
qemu_common_flags += cc.get_supported_arguments('-fno-pie', '-no-pie')
|
||||
endif
|
||||
|
||||
if not get_option('stack_protector').disabled()
|
||||
|
@ -780,7 +789,7 @@ if not cc.compiles('''
|
|||
g_free(f);
|
||||
}
|
||||
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')
|
||||
endif
|
||||
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)
|
||||
{
|
||||
Monitor *mon = opaque;
|
||||
MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
|
||||
|
||||
switch (event) {
|
||||
case CHR_EVENT_MUX_IN:
|
||||
qemu_mutex_lock(&mon->mon_lock);
|
||||
mon->mux_out = 0;
|
||||
qemu_mutex_unlock(&mon->mon_lock);
|
||||
if (mon->reset_seen) {
|
||||
readline_restart(hmp_mon->rs);
|
||||
if (mon->mux_out) {
|
||||
mon->mux_out = 0;
|
||||
monitor_resume(mon);
|
||||
monitor_flush(mon);
|
||||
} else {
|
||||
qatomic_mb_set(&mon->suspend_cnt, 0);
|
||||
}
|
||||
qemu_mutex_unlock(&mon->mon_lock);
|
||||
break;
|
||||
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
|
||||
case CHR_EVENT_OPENED:
|
||||
monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
|
||||
"information\n", QEMU_VERSION);
|
||||
if (!mon->mux_out) {
|
||||
readline_restart(hmp_mon->rs);
|
||||
readline_show_prompt(hmp_mon->rs);
|
||||
}
|
||||
qemu_mutex_lock(&mon->mon_lock);
|
||||
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++;
|
||||
break;
|
||||
|
||||
|
|
|
@ -94,7 +94,6 @@ typedef struct HMPCommand {
|
|||
|
||||
struct Monitor {
|
||||
CharBackend chr;
|
||||
int reset_seen;
|
||||
int suspend_cnt; /* Needs to be accessed atomically */
|
||||
bool is_qmp;
|
||||
bool skip_flush;
|
||||
|
@ -115,8 +114,8 @@ struct Monitor {
|
|||
QLIST_HEAD(, mon_fd_t) fds;
|
||||
GString *outbuf;
|
||||
guint out_watch;
|
||||
/* Read under either BQL or mon_lock, written with BQL+mon_lock. */
|
||||
int mux_out;
|
||||
int reset_seen;
|
||||
};
|
||||
|
||||
struct MonitorHMP {
|
||||
|
@ -166,7 +165,6 @@ typedef QTAILQ_HEAD(MonitorList, Monitor) MonitorList;
|
|||
extern IOThread *mon_iothread;
|
||||
extern Coroutine *qmp_dispatcher_co;
|
||||
extern bool qmp_dispatcher_co_shutdown;
|
||||
extern bool qmp_dispatcher_co_busy;
|
||||
extern QmpCommandList qmp_commands, qmp_cap_negotiation_commands;
|
||||
extern QemuMutex monitor_lock;
|
||||
extern MonitorList mon_list;
|
||||
|
@ -184,6 +182,7 @@ void monitor_fdsets_cleanup(void);
|
|||
void qmp_send_response(MonitorQMP *mon, const QDict *rsp);
|
||||
void monitor_data_destroy_qmp(MonitorQMP *mon);
|
||||
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);
|
||||
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 *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
|
||||
* 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 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.
|
||||
* Set to true when the dispatcher coroutine should terminate. Protected
|
||||
* by monitor_lock.
|
||||
*/
|
||||
bool qmp_dispatcher_co_busy;
|
||||
bool qmp_dispatcher_co_shutdown;
|
||||
|
||||
/*
|
||||
* 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));
|
||||
}
|
||||
|
||||
static void monitor_flush_locked(Monitor *mon);
|
||||
|
||||
static gboolean monitor_unblocked(void *do_not_use, GIOCondition cond,
|
||||
void *opaque)
|
||||
{
|
||||
Monitor *mon = opaque;
|
||||
|
||||
qemu_mutex_lock(&mon->mon_lock);
|
||||
QEMU_LOCK_GUARD(&mon->mon_lock);
|
||||
mon->out_watch = 0;
|
||||
monitor_flush_locked(mon);
|
||||
qemu_mutex_unlock(&mon->mon_lock);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Caller must hold mon->mon_lock */
|
||||
static void monitor_flush_locked(Monitor *mon)
|
||||
void monitor_flush_locked(Monitor *mon)
|
||||
{
|
||||
int rc;
|
||||
size_t len;
|
||||
|
@ -203,18 +182,16 @@ static void monitor_flush_locked(Monitor *mon)
|
|||
|
||||
void monitor_flush(Monitor *mon)
|
||||
{
|
||||
qemu_mutex_lock(&mon->mon_lock);
|
||||
QEMU_LOCK_GUARD(&mon->mon_lock);
|
||||
monitor_flush_locked(mon);
|
||||
qemu_mutex_unlock(&mon->mon_lock);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
char c;
|
||||
|
||||
qemu_mutex_lock(&mon->mon_lock);
|
||||
for (i = 0; str[i]; i++) {
|
||||
c = str[i];
|
||||
if (c == '\n') {
|
||||
|
@ -225,11 +202,16 @@ int monitor_puts(Monitor *mon, const char *str)
|
|||
monitor_flush_locked(mon);
|
||||
}
|
||||
}
|
||||
qemu_mutex_unlock(&mon->mon_lock);
|
||||
|
||||
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)
|
||||
{
|
||||
char *buf;
|
||||
|
@ -569,6 +551,17 @@ static void monitor_accept_input(void *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);
|
||||
}
|
||||
|
||||
|
@ -587,12 +580,6 @@ void monitor_resume(Monitor *mon)
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -603,7 +590,7 @@ int monitor_can_read(void *opaque)
|
|||
{
|
||||
Monitor *mon = opaque;
|
||||
|
||||
return !qatomic_mb_read(&mon->suspend_cnt);
|
||||
return !qatomic_read(&mon->suspend_cnt);
|
||||
}
|
||||
|
||||
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
|
||||
* and monitor_data_destroy() will free them.
|
||||
*/
|
||||
qmp_dispatcher_co_shutdown = true;
|
||||
if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) {
|
||||
aio_co_wake(qmp_dispatcher_co);
|
||||
WITH_QEMU_LOCK_GUARD(&monitor_lock) {
|
||||
qmp_dispatcher_co_shutdown = true;
|
||||
}
|
||||
qmp_dispatcher_co_wake();
|
||||
|
||||
AIO_WAIT_WHILE_UNLOCKED(NULL,
|
||||
(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),
|
||||
|
@ -732,7 +719,6 @@ void monitor_init_globals(void)
|
|||
* rid of those assumptions.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
108
monitor/qmp.c
108
monitor/qmp.c
|
@ -33,6 +33,30 @@
|
|||
#include "qapi/qmp/qlist.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 {
|
||||
/* Owner of the request */
|
||||
MonitorQMP *mon;
|
||||
|
@ -178,8 +202,6 @@ static QMPRequest *monitor_qmp_requests_pop_any_with_lock(void)
|
|||
Monitor *mon;
|
||||
MonitorQMP *qmp_mon;
|
||||
|
||||
QEMU_LOCK_GUARD(&monitor_lock);
|
||||
|
||||
QTAILQ_FOREACH(mon, &mon_list, entry) {
|
||||
if (!monitor_is_qmp(mon)) {
|
||||
continue;
|
||||
|
@ -207,53 +229,56 @@ static QMPRequest *monitor_qmp_requests_pop_any_with_lock(void)
|
|||
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) {
|
||||
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
|
||||
* don't miss any new requests coming in the middle of our
|
||||
* processing.
|
||||
*
|
||||
* Clear qmp_dispatcher_co_busy before reading request.
|
||||
*/
|
||||
qatomic_mb_set(&qmp_dispatcher_co_busy, false);
|
||||
|
||||
/* On shutdown, don't take any more requests from the queue */
|
||||
if (qmp_dispatcher_co_shutdown) {
|
||||
return;
|
||||
}
|
||||
WITH_QEMU_LOCK_GUARD(&monitor_lock) {
|
||||
QMPRequest *req_obj;
|
||||
|
||||
while (!(req_obj = monitor_qmp_requests_pop_any_with_lock())) {
|
||||
/*
|
||||
* 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()
|
||||
*/
|
||||
/* On shutdown, don't take any more requests from the queue */
|
||||
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,
|
||||
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);
|
||||
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)
|
||||
|
@ -403,9 +439,7 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err)
|
|||
}
|
||||
|
||||
/* Kick the dispatcher routine */
|
||||
if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) {
|
||||
aio_co_wake(qmp_dispatcher_co);
|
||||
}
|
||||
qmp_dispatcher_co_wake();
|
||||
}
|
||||
|
||||
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_vss,
|
||||
'-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_MANUFACTURER=' + config_host['QEMU_GA_MANUFACTURER'],
|
||||
'-D', 'QEMU_GA_DISTRO=' + config_host['QEMU_GA_DISTRO'],
|
||||
|
|
|
@ -32,11 +32,16 @@
|
|||
#include "exec/address-spaces.h"
|
||||
#include "trace.h"
|
||||
|
||||
typedef struct MemoryRegionPortioList {
|
||||
struct MemoryRegionPortioList {
|
||||
Object obj;
|
||||
|
||||
MemoryRegion mr;
|
||||
void *portio_opaque;
|
||||
MemoryRegionPortio ports[];
|
||||
} MemoryRegionPortioList;
|
||||
MemoryRegionPortio *ports;
|
||||
};
|
||||
|
||||
#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)
|
||||
{
|
||||
|
@ -147,7 +152,7 @@ void portio_list_destroy(PortioList *piolist)
|
|||
for (i = 0; i < piolist->nr; ++i) {
|
||||
mrpio = container_of(piolist->regions[i], MemoryRegionPortioList, mr);
|
||||
object_unparent(OBJECT(&mrpio->mr));
|
||||
g_free(mrpio);
|
||||
object_unref(mrpio);
|
||||
}
|
||||
g_free(piolist->regions);
|
||||
}
|
||||
|
@ -224,12 +229,15 @@ static void portio_list_add_1(PortioList *piolist,
|
|||
unsigned off_low, unsigned off_high)
|
||||
{
|
||||
MemoryRegionPortioList *mrpio;
|
||||
Object *owner;
|
||||
char *name;
|
||||
unsigned i;
|
||||
|
||||
/* Copy the sub-list and null-terminate it. */
|
||||
mrpio = g_malloc0(sizeof(MemoryRegionPortioList) +
|
||||
sizeof(MemoryRegionPortio) * (count + 1));
|
||||
mrpio = MEMORY_REGION_PORTIO_LIST(
|
||||
object_new(TYPE_MEMORY_REGION_PORTIO_LIST));
|
||||
mrpio->portio_opaque = piolist->opaque;
|
||||
mrpio->ports = g_malloc0(sizeof(MemoryRegionPortio) * (count + 1));
|
||||
memcpy(mrpio->ports, pio_init, sizeof(MemoryRegionPortio) * count);
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
},
|
||||
{
|
||||
.version = 4,
|
||||
.props = (PropValue[]) {
|
||||
/* Erratum 1386 */
|
||||
{ "model-id",
|
||||
"AMD EPYC-Rome-v4 Processor (no XSAVES)" },
|
||||
{ "xsaves", "off" },
|
||||
{ /* 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
|
||||
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 ===
|
||||
|
@ -134,7 +134,7 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||
|
||||
Testing: -drive if=virtio
|
||||
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 ===
|
||||
|
|
|
@ -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
|
||||
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 ===
|
||||
|
@ -142,11 +142,11 @@ QEMU X.Y.Z monitor - type 'help' for more information
|
|||
|
||||
Testing: -drive if=ide
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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 ===
|
||||
|
||||
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) 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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
QEMU X.Y.Z monitor - type 'help' for more information
|
||||
|
|
Loading…
Reference in New Issue