* 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:
Richard Henderson 2023-05-25 08:36:10 -07:00
commit 6ad2c71c23
12 changed files with 218 additions and 131 deletions

View File

@ -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) {

View File

@ -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);

View File

@ -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],

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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)

View File

@ -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'],

View File

@ -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)

View File

@ -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 */ }
}
},

View File

@ -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 ===

View File

@ -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