diff --git a/accel/mshv/mshv-all.c b/accel/mshv/mshv-all.c index 45174f7c4e..80428d130d 100644 --- a/accel/mshv/mshv-all.c +++ b/accel/mshv/mshv-all.c @@ -596,6 +596,9 @@ static void mshv_start_vcpu_thread(CPUState *cpu) { char thread_name[VCPU_THREAD_NAME_SIZE]; + snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/MSHV", + cpu->cpu_index); + cpu->thread = g_malloc0(sizeof(QemuThread)); cpu->halt_cond = g_malloc0(sizeof(QemuCond)); diff --git a/backends/cryptodev-vhost-user.c b/backends/cryptodev-vhost-user.c index cb04e68b02..cc478d9902 100644 --- a/backends/cryptodev-vhost-user.c +++ b/backends/cryptodev-vhost-user.c @@ -46,7 +46,7 @@ struct CryptoDevBackendVhostUser { CryptoDevBackend parent_obj; VhostUserState vhost_user; - CharBackend chr; + CharFrontend chr; char *chr_name; bool opened; CryptoDevBackendVhost *vhost_crypto[MAX_CRYPTO_QUEUE_NUM]; diff --git a/backends/rng-egd.c b/backends/rng-egd.c index 9fd3393ede..1d92bd71cf 100644 --- a/backends/rng-egd.c +++ b/backends/rng-egd.c @@ -24,7 +24,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(RngEgd, RNG_EGD) struct RngEgd { RngBackend parent; - CharBackend chr; + CharFrontend chr; char *chr_name; }; diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c index dacfca5ab7..f32b67dac7 100644 --- a/backends/tpm/tpm_emulator.c +++ b/backends/tpm/tpm_emulator.c @@ -69,7 +69,7 @@ struct TPMEmulator { TPMBackend parent; TPMEmulatorOptions *options; - CharBackend ctrl_chr; + CharFrontend ctrl_chr; QIOChannel *data_ioc; TPMVersion tpm_version; uint32_t caps; /* capabilities of the TPM */ @@ -126,7 +126,7 @@ static int tpm_emulator_ctrlcmd(TPMEmulator *tpm, unsigned long cmd, void *msg, size_t msg_len_in, size_t msg_len_out_err, size_t msg_len_out_total) { - CharBackend *dev = &tpm->ctrl_chr; + CharFrontend *dev = &tpm->ctrl_chr; uint32_t cmd_no = cpu_to_be32(cmd); ssize_t n = sizeof(uint32_t) + msg_len_in; ptm_res res; diff --git a/chardev/char-fe.c b/chardev/char-fe.c index 158a5f4f55..34b83fc1c4 100644 --- a/chardev/char-fe.c +++ b/chardev/char-fe.c @@ -30,9 +30,9 @@ #include "chardev/char-io.h" #include "chardev-internal.h" -int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len) +int qemu_chr_fe_write(CharFrontend *c, const uint8_t *buf, int len) { - Chardev *s = be->chr; + Chardev *s = c->chr; if (!s) { return 0; @@ -41,9 +41,9 @@ int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len) return qemu_chr_write(s, buf, len, false); } -int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len) +int qemu_chr_fe_write_all(CharFrontend *c, const uint8_t *buf, int len) { - Chardev *s = be->chr; + Chardev *s = c->chr; if (!s) { return 0; @@ -52,9 +52,9 @@ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len) return qemu_chr_write(s, buf, len, true); } -int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len) +int qemu_chr_fe_read_all(CharFrontend *c, uint8_t *buf, int len) { - Chardev *s = be->chr; + Chardev *s = c->chr; int offset = 0; int res; @@ -95,9 +95,9 @@ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len) return offset; } -int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg) +int qemu_chr_fe_ioctl(CharFrontend *c, int cmd, void *arg) { - Chardev *s = be->chr; + Chardev *s = c->chr; int res; if (!s || !CHARDEV_GET_CLASS(s)->chr_ioctl || qemu_chr_replay(s)) { @@ -109,11 +109,11 @@ int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg) return res; } -int qemu_chr_fe_get_msgfd(CharBackend *be) +int qemu_chr_fe_get_msgfd(CharFrontend *c) { - Chardev *s = be->chr; + Chardev *s = c->chr; int fd; - int res = (qemu_chr_fe_get_msgfds(be, &fd, 1) == 1) ? fd : -1; + int res = (qemu_chr_fe_get_msgfds(c, &fd, 1) == 1) ? fd : -1; if (s && qemu_chr_replay(s)) { error_report("Replay: get msgfd is not supported " "for serial devices yet"); @@ -122,9 +122,9 @@ int qemu_chr_fe_get_msgfd(CharBackend *be) return res; } -int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int len) +int qemu_chr_fe_get_msgfds(CharFrontend *c, int *fds, int len) { - Chardev *s = be->chr; + Chardev *s = c->chr; if (!s) { return -1; @@ -134,9 +134,9 @@ int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int len) CHARDEV_GET_CLASS(s)->get_msgfds(s, fds, len) : -1; } -int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num) +int qemu_chr_fe_set_msgfds(CharFrontend *c, int *fds, int num) { - Chardev *s = be->chr; + Chardev *s = c->chr; if (!s) { return -1; @@ -146,9 +146,9 @@ int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num) CHARDEV_GET_CLASS(s)->set_msgfds(s, fds, num) : -1; } -void qemu_chr_fe_accept_input(CharBackend *be) +void qemu_chr_fe_accept_input(CharFrontend *c) { - Chardev *s = be->chr; + Chardev *s = c->chr; if (!s) { return; @@ -160,7 +160,7 @@ void qemu_chr_fe_accept_input(CharBackend *be) qemu_notify_event(); } -void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...) +void qemu_chr_fe_printf(CharFrontend *c, const char *fmt, ...) { char buf[CHR_READ_BUF_LEN]; va_list ap; @@ -168,28 +168,28 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...) vsnprintf(buf, sizeof(buf), fmt, ap); /* XXX this blocks entire thread. Rewrite to use * qemu_chr_fe_write and background I/O callbacks */ - qemu_chr_fe_write_all(be, (uint8_t *)buf, strlen(buf)); + qemu_chr_fe_write_all(c, (uint8_t *)buf, strlen(buf)); va_end(ap); } -Chardev *qemu_chr_fe_get_driver(CharBackend *be) +Chardev *qemu_chr_fe_get_driver(CharFrontend *c) { /* this is unsafe for the users that support chardev hotswap */ - assert(be->chr_be_change == NULL); - return be->chr; + assert(c->chr_be_change == NULL); + return c->chr; } -bool qemu_chr_fe_backend_connected(CharBackend *be) +bool qemu_chr_fe_backend_connected(CharFrontend *c) { - return !!be->chr; + return !!c->chr; } -bool qemu_chr_fe_backend_open(CharBackend *be) +bool qemu_chr_fe_backend_open(CharFrontend *c) { - return be->chr && be->chr->be_open; + return c->chr && c->chr->be_open; } -bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp) +bool qemu_chr_fe_init(CharFrontend *c, Chardev *s, Error **errp) { unsigned int tag = 0; @@ -197,49 +197,49 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp) if (CHARDEV_IS_MUX(s)) { MuxChardev *d = MUX_CHARDEV(s); - if (!mux_chr_attach_frontend(d, b, &tag, errp)) { + if (!mux_chr_attach_frontend(d, c, &tag, errp)) { return false; } - } else if (s->be) { + } else if (s->fe) { error_setg(errp, "chardev '%s' is already in use", s->label); return false; } else { - s->be = b; + s->fe = c; } } - b->fe_is_open = false; - b->tag = tag; - b->chr = s; + c->fe_is_open = false; + c->tag = tag; + c->chr = s; return true; } -void qemu_chr_fe_deinit(CharBackend *b, bool del) +void qemu_chr_fe_deinit(CharFrontend *c, bool del) { - assert(b); + assert(c); - if (b->chr) { - qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, NULL, true); - if (b->chr->be == b) { - b->chr->be = NULL; + if (c->chr) { + qemu_chr_fe_set_handlers(c, NULL, NULL, NULL, NULL, NULL, NULL, true); + if (c->chr->fe == c) { + c->chr->fe = NULL; } - if (CHARDEV_IS_MUX(b->chr)) { - MuxChardev *d = MUX_CHARDEV(b->chr); - mux_chr_detach_frontend(d, b->tag); + if (CHARDEV_IS_MUX(c->chr)) { + MuxChardev *d = MUX_CHARDEV(c->chr); + mux_chr_detach_frontend(d, c->tag); } if (del) { - Object *obj = OBJECT(b->chr); + Object *obj = OBJECT(c->chr); if (obj->parent) { object_unparent(obj); } else { object_unref(obj); } } - b->chr = NULL; + c->chr = NULL; } } -void qemu_chr_fe_set_handlers_full(CharBackend *b, +void qemu_chr_fe_set_handlers_full(CharFrontend *c, IOCanReadHandler *fd_can_read, IOReadHandler *fd_read, IOEventHandler *fd_event, @@ -252,7 +252,7 @@ void qemu_chr_fe_set_handlers_full(CharBackend *b, Chardev *s; bool fe_open; - s = b->chr; + s = c->chr; if (!s) { return; } @@ -263,20 +263,20 @@ void qemu_chr_fe_set_handlers_full(CharBackend *b, } else { fe_open = true; } - b->chr_can_read = fd_can_read; - b->chr_read = fd_read; - b->chr_event = fd_event; - b->chr_be_change = be_change; - b->opaque = opaque; + c->chr_can_read = fd_can_read; + c->chr_read = fd_read; + c->chr_event = fd_event; + c->chr_be_change = be_change; + c->opaque = opaque; qemu_chr_be_update_read_handlers(s, context); if (set_open) { - qemu_chr_fe_set_open(b, fe_open); + qemu_chr_fe_set_open(c, fe_open); } if (fe_open) { - qemu_chr_fe_take_focus(b); + qemu_chr_fe_take_focus(c); /* We're connecting to an already opened device, so let's make sure we also get the open event */ if (sync_state && s->be_open) { @@ -285,7 +285,7 @@ void qemu_chr_fe_set_handlers_full(CharBackend *b, } } -void qemu_chr_fe_set_handlers(CharBackend *b, +void qemu_chr_fe_set_handlers(CharFrontend *c, IOCanReadHandler *fd_can_read, IOReadHandler *fd_read, IOEventHandler *fd_event, @@ -294,62 +294,62 @@ void qemu_chr_fe_set_handlers(CharBackend *b, GMainContext *context, bool set_open) { - qemu_chr_fe_set_handlers_full(b, fd_can_read, fd_read, fd_event, be_change, + qemu_chr_fe_set_handlers_full(c, fd_can_read, fd_read, fd_event, be_change, opaque, context, set_open, true); } -void qemu_chr_fe_take_focus(CharBackend *b) +void qemu_chr_fe_take_focus(CharFrontend *c) { - if (!b->chr) { + if (!c->chr) { return; } - if (CHARDEV_IS_MUX(b->chr)) { - mux_set_focus(b->chr, b->tag); + if (CHARDEV_IS_MUX(c->chr)) { + mux_set_focus(c->chr, c->tag); } } -int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp) +int qemu_chr_fe_wait_connected(CharFrontend *c, Error **errp) { - if (!be->chr) { + if (!c->chr) { error_setg(errp, "missing associated backend"); return -1; } - return qemu_chr_wait_connected(be->chr, errp); + return qemu_chr_wait_connected(c->chr, errp); } -void qemu_chr_fe_set_echo(CharBackend *be, bool echo) +void qemu_chr_fe_set_echo(CharFrontend *c, bool echo) { - Chardev *chr = be->chr; + Chardev *chr = c->chr; if (chr && CHARDEV_GET_CLASS(chr)->chr_set_echo) { CHARDEV_GET_CLASS(chr)->chr_set_echo(chr, echo); } } -void qemu_chr_fe_set_open(CharBackend *be, bool is_open) +void qemu_chr_fe_set_open(CharFrontend *c, bool is_open) { - Chardev *chr = be->chr; + Chardev *chr = c->chr; if (!chr) { return; } - if (be->fe_is_open == is_open) { + if (c->fe_is_open == is_open) { return; } - be->fe_is_open = is_open; + c->fe_is_open = is_open; if (CHARDEV_GET_CLASS(chr)->chr_set_fe_open) { CHARDEV_GET_CLASS(chr)->chr_set_fe_open(chr, is_open); } } -guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, +guint qemu_chr_fe_add_watch(CharFrontend *c, GIOCondition cond, FEWatchFunc func, void *user_data) { - Chardev *s = be->chr; + Chardev *s = c->chr; GSource *src; guint tag; @@ -369,9 +369,9 @@ guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, return tag; } -void qemu_chr_fe_disconnect(CharBackend *be) +void qemu_chr_fe_disconnect(CharFrontend *c) { - Chardev *chr = be->chr; + Chardev *chr = c->chr; if (chr && CHARDEV_GET_CLASS(chr)->chr_disconnect) { CHARDEV_GET_CLASS(chr)->chr_disconnect(chr); diff --git a/chardev/char-hub.c b/chardev/char-hub.c index 16ffee2017..d0967c2233 100644 --- a/chardev/char-hub.c +++ b/chardev/char-hub.c @@ -54,7 +54,7 @@ static int hub_chr_write(Chardev *chr, const uint8_t *buf, int len) d->be_eagain_ind = -1; for (i = 0; i < d->be_cnt; i++) { - if (!d->backends[i].be.chr->be_open) { + if (!d->backends[i].fe.chr->be_open) { /* Skip closed backend */ continue; } @@ -64,7 +64,7 @@ static int hub_chr_write(Chardev *chr, const uint8_t *buf, int len) ret = MIN(written, ret); continue; } - r = qemu_chr_fe_write(&d->backends[i].be, buf, len); + r = qemu_chr_fe_write(&d->backends[i].fe, buf, len); if (r < 0) { if (errno == EAGAIN) { /* Set index and expect to be called soon on watch wake up */ @@ -84,7 +84,7 @@ static int hub_chr_write(Chardev *chr, const uint8_t *buf, int len) static int hub_chr_can_read(void *opaque) { HubCharBackend *backend = opaque; - CharBackend *fe = backend->hub->parent.be; + CharFrontend *fe = backend->hub->parent.fe; if (fe && fe->chr_can_read) { return fe->chr_can_read(fe->opaque); @@ -96,7 +96,7 @@ static int hub_chr_can_read(void *opaque) static void hub_chr_read(void *opaque, const uint8_t *buf, int size) { HubCharBackend *backend = opaque; - CharBackend *fe = backend->hub->parent.be; + CharFrontend *fe = backend->hub->parent.fe; if (fe && fe->chr_read) { fe->chr_read(fe->opaque, buf, size); @@ -107,7 +107,7 @@ static void hub_chr_event(void *opaque, QEMUChrEvent event) { HubCharBackend *backend = opaque; HubChardev *d = backend->hub; - CharBackend *fe = d->parent.be; + CharFrontend *fe = d->parent.fe; if (event == CHR_EVENT_OPENED) { /* @@ -147,7 +147,7 @@ static GSource *hub_chr_add_watch(Chardev *s, GIOCondition cond) } assert(d->be_eagain_ind < d->be_cnt); - chr = qemu_chr_fe_get_driver(&d->backends[d->be_eagain_ind].be); + chr = qemu_chr_fe_get_driver(&d->backends[d->be_eagain_ind].fe); cc = CHARDEV_GET_CLASS(chr); if (!cc->chr_add_watch) { return NULL; @@ -167,7 +167,7 @@ static bool hub_chr_attach_chardev(HubChardev *d, Chardev *chr, d->parent.label); return false; } - ret = qemu_chr_fe_init(&d->backends[d->be_cnt].be, chr, errp); + ret = qemu_chr_fe_init(&d->backends[d->be_cnt].fe, chr, errp); if (ret) { d->backends[d->be_cnt].hub = d; d->backends[d->be_cnt].be_ind = d->be_cnt; @@ -183,7 +183,7 @@ static void char_hub_finalize(Object *obj) int i; for (i = 0; i < d->be_cnt; i++) { - qemu_chr_fe_deinit(&d->backends[i].be, false); + qemu_chr_fe_deinit(&d->backends[i].fe, false); } } @@ -193,7 +193,7 @@ static void hub_chr_update_read_handlers(Chardev *chr) int i; for (i = 0; i < d->be_cnt; i++) { - qemu_chr_fe_set_handlers_full(&d->backends[i].be, + qemu_chr_fe_set_handlers_full(&d->backends[i].fe, hub_chr_can_read, hub_chr_read, hub_chr_event, diff --git a/chardev/char-mux.c b/chardev/char-mux.c index 6b36290e2c..db9e89f441 100644 --- a/chardev/char-mux.c +++ b/chardev/char-mux.c @@ -128,10 +128,10 @@ static void mux_print_help(Chardev *chr) static void mux_chr_send_event(MuxChardev *d, unsigned int mux_nr, QEMUChrEvent event) { - CharBackend *be = d->backends[mux_nr]; + CharFrontend *fe = d->frontends[mux_nr]; - if (be && be->chr_event) { - be->chr_event(be->opaque, event); + if (fe && fe->chr_event) { + fe->chr_event(fe->opaque, event); } } @@ -200,11 +200,11 @@ static void mux_chr_accept_input(Chardev *chr) { MuxChardev *d = MUX_CHARDEV(chr); int m = d->focus; - CharBackend *be = d->backends[m]; + CharFrontend *fe = d->frontends[m]; - while (be && d->prod[m] != d->cons[m] && - be->chr_can_read && be->chr_can_read(be->opaque)) { - be->chr_read(be->opaque, + while (fe && d->prod[m] != d->cons[m] && + fe->chr_can_read && fe->chr_can_read(fe->opaque)) { + fe->chr_read(fe->opaque, &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1); } } @@ -213,14 +213,14 @@ static int mux_chr_can_read(void *opaque) { MuxChardev *d = MUX_CHARDEV(opaque); int m = d->focus; - CharBackend *be = d->backends[m]; + CharFrontend *fe = d->frontends[m]; if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE) { return 1; } - if (be && be->chr_can_read) { - return be->chr_can_read(be->opaque); + if (fe && fe->chr_can_read) { + return fe->chr_can_read(fe->opaque); } return 0; @@ -231,7 +231,7 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size) Chardev *chr = CHARDEV(opaque); MuxChardev *d = MUX_CHARDEV(opaque); int m = d->focus; - CharBackend *be = d->backends[m]; + CharFrontend *fe = d->frontends[m]; int i; mux_chr_accept_input(opaque); @@ -239,9 +239,9 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size) for (i = 0; i < size; i++) if (mux_proc_byte(chr, d, buf[i])) { if (d->prod[m] == d->cons[m] && - be && be->chr_can_read && - be->chr_can_read(be->opaque)) { - be->chr_read(be->opaque, &buf[i], 1); + fe && fe->chr_can_read && + fe->chr_can_read(fe->opaque)) { + fe->chr_read(fe->opaque, &buf[i], 1); } else { d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i]; } @@ -289,9 +289,9 @@ static void char_mux_finalize(Object *obj) bit = -1; while ((bit = find_next_bit(&d->mux_bitset, MAX_MUX, bit + 1)) < MAX_MUX) { - CharBackend *be = d->backends[bit]; + CharFrontend *be = d->frontends[bit]; be->chr = NULL; - d->backends[bit] = NULL; + d->frontends[bit] = NULL; } d->mux_bitset = 0; qemu_chr_fe_deinit(&d->chr, false); @@ -311,7 +311,7 @@ static void mux_chr_update_read_handlers(Chardev *chr) chr->gcontext, true, false); } -bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b, +bool mux_chr_attach_frontend(MuxChardev *d, CharFrontend *c, unsigned int *tag, Error **errp) { unsigned int bit; @@ -328,7 +328,7 @@ bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b, } d->mux_bitset |= (1ul << bit); - d->backends[bit] = b; + d->frontends[bit] = c; *tag = bit; return true; @@ -341,7 +341,7 @@ bool mux_chr_detach_frontend(MuxChardev *d, unsigned int tag) } d->mux_bitset &= ~(1ul << tag); - d->backends[tag] = NULL; + d->frontends[tag] = NULL; return true; } @@ -357,7 +357,7 @@ void mux_set_focus(Chardev *chr, unsigned int focus) } d->focus = focus; - chr->be = d->backends[focus]; + chr->fe = d->frontends[focus]; mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN); } diff --git a/chardev/char.c b/chardev/char.c index bbebd246c3..30b21fedce 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -53,13 +53,13 @@ Object *get_chardevs_root(void) static void chr_be_event(Chardev *s, QEMUChrEvent event) { - CharBackend *be = s->be; + CharFrontend *fe = s->fe; - if (!be || !be->chr_event) { + if (!fe || !fe->chr_event) { return; } - be->chr_event(be->opaque, event); + fe->chr_event(fe->opaque, event); } void qemu_chr_be_event(Chardev *s, QEMUChrEvent event) @@ -197,21 +197,21 @@ int qemu_chr_write(Chardev *s, const uint8_t *buf, int len, bool write_all) int qemu_chr_be_can_write(Chardev *s) { - CharBackend *be = s->be; + CharFrontend *fe = s->fe; - if (!be || !be->chr_can_read) { + if (!fe || !fe->chr_can_read) { return 0; } - return be->chr_can_read(be->opaque); + return fe->chr_can_read(fe->opaque); } void qemu_chr_be_write_impl(Chardev *s, const uint8_t *buf, int len) { - CharBackend *be = s->be; + CharFrontend *fe = s->fe; - if (be && be->chr_read) { - be->chr_read(be->opaque, buf, len); + if (fe && fe->chr_read) { + fe->chr_read(fe->opaque, buf, len); } } @@ -307,8 +307,8 @@ static void char_finalize(Object *obj) { Chardev *chr = CHARDEV(obj); - if (chr->be) { - chr->be->chr = NULL; + if (chr->fe) { + chr->fe->chr = NULL; } g_free(chr->filename); g_free(chr->label); @@ -335,7 +335,7 @@ static bool qemu_chr_is_busy(Chardev *s) MuxChardev *d = MUX_CHARDEV(s); return d->mux_bitset != 0; } else { - return s->be != NULL; + return s->fe != NULL; } } @@ -798,7 +798,7 @@ static int qmp_query_chardev_foreach(Object *obj, void *data) value->label = g_strdup(chr->label); value->filename = g_strdup(chr->filename); - value->frontend_open = chr->be && chr->be->fe_is_open; + value->frontend_open = chr->fe && chr->fe->fe_is_open; QAPI_LIST_PREPEND(*list, value); @@ -1112,7 +1112,7 @@ err: ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend, Error **errp) { - CharBackend *be; + CharFrontend *fe; const ChardevClass *cc, *cc_new; Chardev *chr, *chr_new; bool closed_sent = false; @@ -1136,14 +1136,14 @@ ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend, return NULL; } - be = chr->be; - if (!be) { + fe = chr->fe; + if (!fe) { /* easy case */ object_unparent(OBJECT(chr)); return qmp_chardev_add(id, backend, errp); } - if (!be->chr_be_change) { + if (!fe->chr_be_change) { error_setg(errp, "Chardev user does not support chardev hotswap"); return NULL; } @@ -1171,13 +1171,13 @@ ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend, closed_sent = true; } - chr->be = NULL; - qemu_chr_fe_init(be, chr_new, &error_abort); + chr->fe = NULL; + qemu_chr_fe_init(fe, chr_new, &error_abort); - if (be->chr_be_change(be->opaque) < 0) { + if (fe->chr_be_change(fe->opaque) < 0) { error_setg(errp, "Chardev '%s' change failed", chr_new->label); - chr_new->be = NULL; - qemu_chr_fe_init(be, chr, &error_abort); + chr_new->fe = NULL; + qemu_chr_fe_init(fe, chr, &error_abort); if (closed_sent) { qemu_chr_be_event(chr, CHR_EVENT_OPENED); } diff --git a/chardev/chardev-internal.h b/chardev/chardev-internal.h index 9752dd75f7..8ea10414ab 100644 --- a/chardev/chardev-internal.h +++ b/chardev/chardev-internal.h @@ -37,9 +37,9 @@ struct MuxChardev { Chardev parent; /* Linked frontends */ - CharBackend *backends[MAX_MUX]; - /* Linked backend */ - CharBackend chr; + CharFrontend *frontends[MAX_MUX]; + /* frontend of the underlying muxed chardev */ + CharFrontend chr; unsigned long mux_bitset; int focus; bool term_got_escape; @@ -64,8 +64,8 @@ typedef struct HubCharBackend HubCharBackend; * `hub->backends` array */ struct HubCharBackend { - HubChardev *hub; - CharBackend be; + HubChardev *hub; + CharFrontend fe; unsigned int be_ind; }; @@ -108,7 +108,7 @@ DECLARE_INSTANCE_CHECKER(HubChardev, HUB_CHARDEV, #define CHARDEV_IS_HUB(chr) \ object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_HUB) -bool mux_chr_attach_frontend(MuxChardev *d, CharBackend *b, +bool mux_chr_attach_frontend(MuxChardev *d, CharFrontend *c, unsigned int *tag, Error **errp); bool mux_chr_detach_frontend(MuxChardev *d, unsigned int tag); void mux_set_focus(Chardev *chr, unsigned int focus); diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index dacf2882e4..020610132f 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -544,6 +544,20 @@ available firmwares that are using the current (wrong) name. The property is kept as is in 9.1, together with "riscv,delegation", to give more time for firmware developers to change their code. +x86 "isapc" board use of modern x86 CPUs (since 10.2) +''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The "isapc" board represents a historical x86 ISA PC and is intended for +older 32-bit x86 CPU models, defaulting to a 486 CPU model. Previously it +was possible (but non-sensical) to specify a more modern x86 CPU, including +``-cpu host`` or ``-cpu max`` even if the features were incompatible with many +of the intended guest OSs. + +If the user requests a modern x86 CPU model (i.e. not one of ``486``, +``athlon``, ``kvm32``, ``pentium``, ``pentium2``, ``pentium3``or ``qemu32``) +a warning will be displayed until a future QEMU version when such CPUs will +be rejected. + Migration --------- diff --git a/gdbstub/system.c b/gdbstub/system.c index 5221c579d9..e2220c1ae4 100644 --- a/gdbstub/system.c +++ b/gdbstub/system.c @@ -34,7 +34,7 @@ /* System emulation specific state */ typedef struct { - CharBackend chr; + CharFrontend chr; Chardev *mon_chr; } GDBSystemState; diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index 229c98ddd9..059b07907d 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -927,7 +927,7 @@ struct StrongARMUARTState { SysBusDevice parent_obj; MemoryRegion iomem; - CharBackend chr; + CharFrontend chr; qemu_irq irq; uint8_t utcr0; diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c index bf44aaf9e4..bb323adda5 100644 --- a/hw/char/debugcon.c +++ b/hw/char/debugcon.c @@ -40,7 +40,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(ISADebugconState, ISA_DEBUGCON_DEVICE) typedef struct DebugconState { MemoryRegion io; - CharBackend chr; + CharFrontend chr; uint32_t readback; } DebugconState; diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c index 6521b4cedd..9e45d81990 100644 --- a/hw/char/exynos4210_uart.c +++ b/hw/char/exynos4210_uart.c @@ -154,7 +154,7 @@ struct Exynos4210UartState { QEMUTimer *fifo_timeout_timer; uint64_t wordtime; /* word time in ns */ - CharBackend chr; + CharFrontend chr; qemu_irq irq; qemu_irq dmairq; diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c index 81c26e3389..b2d5a40bb4 100644 --- a/hw/char/grlib_apbuart.c +++ b/hw/char/grlib_apbuart.c @@ -84,7 +84,7 @@ struct UART { MemoryRegion iomem; qemu_irq irq; - CharBackend chr; + CharFrontend chr; /* registers */ uint32_t status; diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c index 0a7ffcd0b7..25d7fc9574 100644 --- a/hw/char/ipoctal232.c +++ b/hw/char/ipoctal232.c @@ -102,7 +102,7 @@ typedef struct SCC2698Block SCC2698Block; struct SCC2698Channel { IPOctalState *ipoctal; - CharBackend dev; + CharFrontend dev; bool rx_enabled; uint8_t mr[2]; uint8_t mr_idx; diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c index 87bfcbebdc..f14de59530 100644 --- a/hw/char/mcf_uart.c +++ b/hw/char/mcf_uart.c @@ -36,7 +36,7 @@ struct mcf_uart_state { int tx_enabled; int rx_enabled; qemu_irq irq; - CharBackend chr; + CharFrontend chr; }; #define TYPE_MCF_UART "mcf-uart" diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c index 3e40d5e434..c51308f9c5 100644 --- a/hw/char/sclpconsole-lm.c +++ b/hw/char/sclpconsole-lm.c @@ -41,7 +41,7 @@ typedef struct OprtnsCommand { struct SCLPConsoleLM { SCLPEvent event; - CharBackend chr; + CharFrontend chr; bool echo; /* immediate echo of input if true */ uint32_t write_errors; /* errors writing to char layer */ uint32_t length; /* length of byte stream in buffer */ diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index 95e3045178..2abf861dbc 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -35,7 +35,7 @@ typedef struct ASCIIConsoleData { struct SCLPConsole { SCLPEvent event; - CharBackend chr; + CharFrontend chr; uint8_t iov[SIZE_BUFFER_VT220]; uint32_t iov_sclp; /* offset in buf for SCLP read operation */ uint32_t iov_bs; /* offset in buf for char layer read operation */ diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c index 30447fa018..83227a84a6 100644 --- a/hw/char/sh_serial.c +++ b/hw/char/sh_serial.c @@ -67,7 +67,7 @@ struct SHSerialState { int flags; int rtrg; - CharBackend chr; + CharFrontend chr; QEMUTimer fifo_timeout_timer; uint64_t etu; /* Elementary Time Unit (ns) */ diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c index fc8ea604f8..766b2bfcac 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -14,7 +14,7 @@ struct SpaprVioVty { SpaprVioDevice sdev; - CharBackend chardev; + CharFrontend chardev; uint32_t in, out; uint8_t buf[VTERM_BUFSIZE]; }; diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c index d950c17292..c993f67b42 100644 --- a/hw/char/terminal3270.c +++ b/hw/char/terminal3270.c @@ -30,7 +30,7 @@ struct Terminal3270 { EmulatedCcw3270Device cdev; - CharBackend chr; + CharFrontend chr; uint8_t inv[INPUT_BUFFER_SIZE]; uint8_t outv[OUTPUT_BUFFER_SIZE]; int in_len; diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c index 0932a3572b..1b669c9be8 100644 --- a/hw/char/virtio-console.c +++ b/hw/char/virtio-console.c @@ -30,7 +30,7 @@ DECLARE_INSTANCE_CHECKER(VirtConsole, VIRTIO_CONSOLE, struct VirtConsole { VirtIOSerialPort parent_obj; - CharBackend chr; + CharFrontend chr; guint watch; }; diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c index 0e73c2aee4..a639fb0b11 100644 --- a/hw/char/xen_console.c +++ b/hw/char/xen_console.c @@ -53,7 +53,7 @@ struct XenConsole { char *fe_path; unsigned int ring_ref; void *sring; - CharBackend chr; + CharFrontend chr; int backlog; }; diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c index 8008171eea..8feb58a898 100644 --- a/hw/char/xilinx_uartlite.c +++ b/hw/char/xilinx_uartlite.c @@ -60,7 +60,7 @@ struct XilinxUARTLite { EndianMode model_endianness; MemoryRegion mmio; - CharBackend chr; + CharFrontend chr; qemu_irq irq; uint8_t rx_fifo[8]; diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 1f810b7ddf..13cc91680b 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -258,10 +258,10 @@ const PropertyInfo qdev_prop_drive_iothread = { static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - CharBackend *be = object_field_prop_ptr(obj, opaque); + CharFrontend *fe = object_field_prop_ptr(obj, opaque); char *p; - p = g_strdup(be->chr && be->chr->label ? be->chr->label : ""); + p = g_strdup(fe->chr && fe->chr->label ? fe->chr->label : ""); visit_type_str(v, name, &p, errp); g_free(p); } @@ -271,7 +271,7 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, { ERRP_GUARD(); const Property *prop = opaque; - CharBackend *be = object_field_prop_ptr(obj, prop); + CharFrontend *fe = object_field_prop_ptr(obj, prop); Chardev *s; char *str; @@ -283,13 +283,13 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, * TODO Should this really be an error? If no, the old value * needs to be released before we store the new one. */ - if (!check_prop_still_unset(obj, name, be->chr, str, false, errp)) { + if (!check_prop_still_unset(obj, name, fe->chr, str, false, errp)) { return; } if (!*str) { g_free(str); - be->chr = NULL; + fe->chr = NULL; return; } @@ -297,7 +297,7 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, if (s == NULL) { error_setg(errp, "Property '%s.%s' can't find value '%s'", object_get_typename(obj), name, str); - } else if (!qemu_chr_fe_init(be, s, errp)) { + } else if (!qemu_chr_fe_init(fe, s, errp)) { error_prepend(errp, "Property '%s.%s' can't take value '%s': ", object_get_typename(obj), name, str); } @@ -307,9 +307,9 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, static void release_chr(Object *obj, const char *name, void *opaque) { const Property *prop = opaque; - CharBackend *be = object_field_prop_ptr(obj, prop); + CharFrontend *fe = object_field_prop_ptr(obj, prop); - qemu_chr_fe_deinit(be, false); + qemu_chr_fe_deinit(fe, false); } const PropertyInfo qdev_prop_chr = { @@ -865,15 +865,14 @@ out: visit_end_alternate(v, (void **) &alt); } -static int print_pci_devfn(Object *obj, const Property *prop, char *dest, - size_t len) +static char *print_pci_devfn(Object *obj, const Property *prop) { int32_t *ptr = object_field_prop_ptr(obj, prop); if (*ptr == -1) { - return snprintf(dest, len, ""); + return g_strdup(""); } else { - return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7); + return g_strdup_printf("%02x.%x", *ptr >> 3, *ptr & 7); } } diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index b7e8a89ba5..422a486969 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -1117,12 +1117,11 @@ static void qdev_get_legacy_property(Object *obj, Visitor *v, Error **errp) { const Property *prop = opaque; + char *s; - char buffer[1024]; - char *ptr = buffer; - - prop->info->print(obj, prop, buffer, sizeof(buffer)); - visit_type_str(v, name, &ptr, errp); + s = prop->info->print(obj, prop); + visit_type_str(v, name, &s, errp); + g_free(s); } /** diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index c3f267731b..cbca0026ab 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -151,7 +151,7 @@ static void io_cpu_write(void *opaque, hwaddr addr, ch = val; debugout = serial_hd(0); if (debugout) { - qemu_chr_fe_write_all(debugout->be, &ch, 1); + qemu_chr_fe_write_all(debugout->fe, &ch, 1); } else { fprintf(stderr, "%c", ch); } diff --git a/hw/i386/isapc.c b/hw/i386/isapc.c index 44f4a44672..1ba9ae22cc 100644 --- a/hw/i386/isapc.c +++ b/hw/i386/isapc.c @@ -41,29 +41,31 @@ static void pc_init_isa(MachineState *machine) DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; int i; - /* - * There is a small chance that someone unintentionally passes "-cpu max" - * for the isapc machine, which will provide a much more modern 32-bit - * CPU than would be expected for an ISA-era PC. If the "max" cpu type has - * been specified, choose the "best" 32-bit cpu possible which we consider - * be the pentium3 (deliberately choosing an Intel CPU given that the - * default 486 CPU for the isapc machine is also an Intel CPU). - */ - if (!strcmp(machine->cpu_type, X86_CPU_TYPE_NAME("max"))) { - machine->cpu_type = X86_CPU_TYPE_NAME("pentium3"); - warn_report("-cpu max is invalid for isapc machine, using pentium3"); - } + bool valid_cpu_type = false; + static const char * const valid_cpu_types[] = { + X86_CPU_TYPE_NAME("486"), + X86_CPU_TYPE_NAME("athlon"), + X86_CPU_TYPE_NAME("kvm32"), + X86_CPU_TYPE_NAME("pentium"), + X86_CPU_TYPE_NAME("pentium2"), + X86_CPU_TYPE_NAME("pentium3"), + X86_CPU_TYPE_NAME("qemu32"), + }; /* - * Similarly if someone unintentionally passes "-cpu host" for the isapc - * machine then display a warning and also switch to the "best" 32-bit - * cpu possible which we consider to be the pentium3. This is because any - * host CPU will already be modern than this, but it also ensures any - * newer CPU flags/features are filtered out for older guests. + * The isapc machine is supposed to represent a legacy ISA-only PC with a + * 32-bit processor. For historical reasons the machine can still accept + * almost any valid processor, but this is now deprecated in 10.2. Emit + * a warning if anyone tries to use a deprecated CPU. */ - if (!strcmp(machine->cpu_type, X86_CPU_TYPE_NAME("host"))) { - machine->cpu_type = X86_CPU_TYPE_NAME("pentium3"); - warn_report("-cpu host is invalid for isapc machine, using pentium3"); + for (i = 0; i < ARRAY_SIZE(valid_cpu_types); i++) { + if (!strcmp(machine->cpu_type, valid_cpu_types[i])) { + valid_cpu_type = true; + } + } + + if (!valid_cpu_type) { + warn_report("cpu type %s is deprecated for isapc machine", machine->cpu_type); } if (machine->ram_size > 3.5 * GiB) { @@ -154,18 +156,6 @@ static void pc_init_isa(MachineState *machine) static void isapc_machine_options(MachineClass *m) { - static const char * const valid_cpu_types[] = { - X86_CPU_TYPE_NAME("486"), - X86_CPU_TYPE_NAME("athlon"), - X86_CPU_TYPE_NAME("kvm32"), - X86_CPU_TYPE_NAME("pentium"), - X86_CPU_TYPE_NAME("pentium2"), - X86_CPU_TYPE_NAME("pentium3"), - X86_CPU_TYPE_NAME("qemu32"), - X86_CPU_TYPE_NAME("max"), - X86_CPU_TYPE_NAME("host"), - NULL - }; PCMachineClass *pcmc = PC_MACHINE_CLASS(m); m->desc = "ISA-only PC"; @@ -180,7 +170,6 @@ static void isapc_machine_options(MachineClass *m) pcmc->has_reserved_memory = false; m->default_nic = "ne2k_isa"; m->default_cpu_type = X86_CPU_TYPE_NAME("486"); - m->valid_cpu_types = valid_cpu_types; m->no_floppy = !module_object_class_by_name(TYPE_ISA_FDC); m->no_parallel = !module_object_class_by_name(TYPE_ISA_PARALLEL); } diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c index 6e78f3d07d..c844749900 100644 --- a/hw/i386/x86-common.c +++ b/hw/i386/x86-common.c @@ -183,6 +183,17 @@ void x86_cpu_plug(HotplugHandler *hotplug_dev, fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); } + /* + * Non-hotplugged CPUs get their SMM cpu address space initialized in + * machine init done notifier: register_smram_listener(). + * + * We need initialize the SMM cpu address space for the hotplugged CPU + * specifically. + */ + if (kvm_enabled() && dev->hotplugged && x86_machine_is_smm_enabled(x86ms)) { + kvm_smm_cpu_address_space_init(cpu); + } + found_cpu = x86_find_cpu_slot(MACHINE(x86ms), cpu->apic_id, NULL); found_cpu->cpu = CPU(dev); out: diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c index 9f1ba7b2f8..2c6c515579 100644 --- a/hw/ipmi/ipmi_bmc_extern.c +++ b/hw/ipmi/ipmi_bmc_extern.c @@ -67,7 +67,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(IPMIBmcExtern, IPMI_BMC_EXTERN) struct IPMIBmcExtern { IPMIBmc parent; - CharBackend chr; + CharFrontend chr; bool connected; diff --git a/hw/mips/boston.c b/hw/mips/boston.c index 0a3a827b5f..6a4fcdd9ca 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -68,7 +68,7 @@ struct BostonState { SerialMM *uart; Clock *cpuclk; - CharBackend lcd_display; + CharFrontend lcd_display; char lcd_content[8]; bool lcd_inited; diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 806e8d5078..a4e2ea98ad 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -89,7 +89,7 @@ typedef struct { uint32_t i2coe; uint32_t i2cout; uint32_t i2csel; - CharBackend display; + CharFrontend display; char display_text[9]; SerialMM *uart; bool display_inited; diff --git a/hw/misc/ivshmem-pci.c b/hw/misc/ivshmem-pci.c index 2748db9286..636d0b83de 100644 --- a/hw/misc/ivshmem-pci.c +++ b/hw/misc/ivshmem-pci.c @@ -94,7 +94,7 @@ struct IVShmemState { /* exactly one of these two may be set */ HostMemoryBackend *hostmem; /* with interrupts */ - CharBackend server_chr; /* without interrupts */ + CharFrontend server_chr; /* without interrupts */ /* registers */ uint32_t intrmask; diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 1f78fe406e..a6715b4026 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -623,7 +623,7 @@ static uint64_t qtest_rtas_call(char *cmd, uint32_t nargs, uint64_t args, return H_PARAMETER; } -static bool spapr_qtest_callback(CharBackend *chr, gchar **words) +static bool spapr_qtest_callback(CharFrontend *chr, gchar **words) { if (strcmp(words[0], "rtas") == 0) { uint64_t res, args, ret; diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c index 7f2676008c..4d51a93dd5 100644 --- a/hw/riscv/riscv_hart.c +++ b/hw/riscv/riscv_hart.c @@ -78,7 +78,7 @@ static void csr_call(char *cmd, uint64_t cpu_num, int csrno, uint64_t *val) g_assert(ret == RISCV_EXCP_NONE); } -static bool csr_qtest_callback(CharBackend *chr, gchar **words) +static bool csr_qtest_callback(CharFrontend *chr, gchar **words) { if (strcmp(words[0], "csr") == 0) { diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 1d264c40e5..2809fcdee0 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -447,7 +447,9 @@ static void write_response(ESPState *s) static bool esp_cdb_ready(ESPState *s) { - int len = fifo8_num_used(&s->cmdfifo) - s->cmdfifo_cdb_offset; + /* scsi_cdb_length() only reads the first byte */ + int limit = s->cmdfifo_cdb_offset + 1; + int len = fifo8_num_used(&s->cmdfifo); const uint8_t *pbuf; uint32_t n; int cdblen; @@ -457,7 +459,7 @@ static bool esp_cdb_ready(ESPState *s) } pbuf = fifo8_peek_bufptr(&s->cmdfifo, len, &n); - if (n < len) { + if (n < limit) { /* * In normal use the cmdfifo should never wrap, but include this check * to prevent a malicious guest from reading past the end of the diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 9b12ee7f1c..b9b115deed 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -823,7 +823,6 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d, { SCSIRequest *req; SCSIBus *bus = scsi_bus_from_device(d); - BusState *qbus = BUS(bus); const int memset_off = offsetof(SCSIRequest, sense) + sizeof(req->sense); @@ -838,8 +837,6 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d, req->status = -1; req->host_status = -1; req->ops = reqops; - object_ref(OBJECT(d)); - object_ref(OBJECT(qbus->parent)); notifier_list_init(&req->cancel_notifiers); if (reqops->init_req) { @@ -1496,15 +1493,15 @@ void scsi_device_report_change(SCSIDevice *dev, SCSISense sense) SCSIRequest *scsi_req_ref(SCSIRequest *req) { - assert(req->refcount > 0); - req->refcount++; + assert(qatomic_read(&req->refcount) > 0); + qatomic_inc(&req->refcount); return req; } void scsi_req_unref(SCSIRequest *req) { - assert(req->refcount > 0); - if (--req->refcount == 0) { + assert(qatomic_read(&req->refcount) > 0); + if (qatomic_fetch_dec(&req->refcount) == 1) { BusState *qbus = req->dev->qdev.parent_bus; SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, qbus); @@ -1514,8 +1511,6 @@ void scsi_req_unref(SCSIRequest *req) if (req->ops->free_req) { req->ops->free_req(req); } - object_unref(OBJECT(req->dev)); - object_unref(OBJECT(qbus->parent)); g_free(req); } } diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c index 1eea21a733..c8aada0988 100644 --- a/hw/usb/ccid-card-passthru.c +++ b/hw/usb/ccid-card-passthru.c @@ -56,7 +56,7 @@ typedef struct PassthruState PassthruState; struct PassthruState { CCIDCardState base; - CharBackend cs; + CharFrontend cs; uint8_t vscard_in_data[VSCARD_IN_SIZE]; uint32_t vscard_in_pos; uint32_t vscard_in_hdr; diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 1c116d8b0f..2eb52b2e01 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -105,7 +105,7 @@ struct USBSerialState { uint8_t xoff; QEMUSerialSetParams params; int latency; /* ms */ - CharBackend cs; + CharFrontend cs; }; #define TYPE_USB_SERIAL "usb-serial-dev" diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index f516ff42a1..d603a4a6f9 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -113,7 +113,7 @@ struct PacketIdQueue { struct USBRedirDevice { USBDevice dev; /* Properties */ - CharBackend cs; + CharFrontend cs; bool enable_streams; bool suppress_remote_wake; bool in_write; diff --git a/hw/virtio/vhost-stub.c b/hw/virtio/vhost-stub.c index 52d42adab2..7321dc9210 100644 --- a/hw/virtio/vhost-stub.c +++ b/hw/virtio/vhost-stub.c @@ -12,7 +12,7 @@ unsigned int vhost_get_free_memslots(void) return UINT_MAX; } -bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp) +bool vhost_user_init(VhostUserState *user, CharFrontend *chr, Error **errp) { return false; } diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 36c9c2e04d..aac98f898a 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -275,7 +275,7 @@ struct scrub_regions { static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg) { struct vhost_user *u = dev->opaque; - CharBackend *chr = u->user->chr; + CharFrontend *chr = u->user->chr; uint8_t *p = (uint8_t *) msg; int r, size = VHOST_USER_HDR_SIZE; @@ -303,7 +303,7 @@ static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg) static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg) { struct vhost_user *u = dev->opaque; - CharBackend *chr = u->user->chr; + CharFrontend *chr = u->user->chr; uint8_t *p = (uint8_t *) msg; int r, size; @@ -383,7 +383,7 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg, int *fds, int fd_num) { struct vhost_user *u = dev->opaque; - CharBackend *chr = u->user->chr; + CharFrontend *chr = u->user->chr; int ret, size = VHOST_USER_HDR_SIZE + msg->hdr.size; /* @@ -1680,7 +1680,7 @@ int vhost_user_get_shared_object(struct vhost_dev *dev, unsigned char *uuid, int *dmabuf_fd) { struct vhost_user *u = dev->opaque; - CharBackend *chr = u->user->chr; + CharFrontend *chr = u->user->chr; int ret; VhostUserMsg msg = { .hdr.request = VHOST_USER_GET_SHARED_OBJECT, @@ -1721,7 +1721,7 @@ vhost_user_backend_handle_shared_object_lookup(struct vhost_user *u, VhostUserPayload *payload) { QemuUUID uuid; - CharBackend *chr = u->user->chr; + CharFrontend *chr = u->user->chr; Error *local_err = NULL; int dmabuf_fd = -1; int fd_num = 0; @@ -2004,7 +2004,7 @@ static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp) { #ifdef CONFIG_LINUX struct vhost_user *u = dev->opaque; - CharBackend *chr = u->user->chr; + CharFrontend *chr = u->user->chr; int ufd; int ret; VhostUserMsg msg = { @@ -2670,7 +2670,7 @@ static int vhost_user_get_inflight_fd(struct vhost_dev *dev, int fd; int ret; struct vhost_user *u = dev->opaque; - CharBackend *chr = u->user->chr; + CharFrontend *chr = u->user->chr; VhostUserMsg msg = { .hdr.request = VHOST_USER_GET_INFLIGHT_FD, .hdr.flags = VHOST_USER_VERSION, @@ -2761,7 +2761,7 @@ static void vhost_user_state_destroy(gpointer data) vhost_user_host_notifier_remove(n, NULL, true); } -bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp) +bool vhost_user_init(VhostUserState *user, CharFrontend *chr, Error **errp) { if (user->chr) { error_setg(errp, "Cannot initialize vhost-user state"); @@ -2787,7 +2787,7 @@ void vhost_user_cleanup(VhostUserState *user) typedef struct { vu_async_close_fn cb; DeviceState *dev; - CharBackend *cd; + CharFrontend *cd; struct vhost_dev *vhost; } VhostAsyncCallback; @@ -2806,7 +2806,7 @@ static void vhost_user_async_close_bh(void *opaque) * purposes. */ void vhost_user_async_close(DeviceState *d, - CharBackend *chardev, struct vhost_dev *vhost, + CharFrontend *chardev, struct vhost_dev *vhost, vu_async_close_fn cb) { if (!runstate_check(RUN_STATE_SHUTDOWN)) { diff --git a/include/chardev/char-fe.h b/include/chardev/char-fe.h index 8ef05b3dd0..5f8a6df17d 100644 --- a/include/chardev/char-fe.h +++ b/include/chardev/char-fe.h @@ -8,12 +8,12 @@ typedef void IOEventHandler(void *opaque, QEMUChrEvent event); typedef int BackendChangeHandler(void *opaque); /** - * struct CharBackend - back end as seen by front end + * struct CharFrontend - Chardev as seen by front end * @fe_is_open: the front end is ready for IO * * The actual backend is Chardev */ -struct CharBackend { +struct CharFrontend { Chardev *chr; IOEventHandler *chr_event; IOCanReadHandler *chr_can_read; @@ -27,53 +27,52 @@ struct CharBackend { /** * qemu_chr_fe_init: * - * Initializes a front end for the given CharBackend and - * Chardev. Call qemu_chr_fe_deinit() to remove the association and - * release the driver. + * Initializes the frontend @c for the given Chardev backend @s. Call + * qemu_chr_fe_deinit() to remove the association and release the backend. * * Returns: false on error. */ -bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp); +bool qemu_chr_fe_init(CharFrontend *c, Chardev *be, Error **errp); /** * qemu_chr_fe_deinit: - * @b: a CharBackend + * @c: a CharFrontend * @del: if true, delete the chardev backend * - * Dissociate the CharBackend from the Chardev. + * Dissociate the CharFrontend from the Chardev. * * Safe to call without associated Chardev. */ -void qemu_chr_fe_deinit(CharBackend *b, bool del); +void qemu_chr_fe_deinit(CharFrontend *c, bool del); /** * qemu_chr_fe_get_driver: * - * Returns: the driver associated with a CharBackend or NULL if no + * Returns: the driver associated with a CharFrontend or NULL if no * associated Chardev. * Note: avoid this function as the driver should never be accessed directly, * especially by the frontends that support chardevice hotswap. * Consider qemu_chr_fe_backend_connected() to check for driver existence */ -Chardev *qemu_chr_fe_get_driver(CharBackend *be); +Chardev *qemu_chr_fe_get_driver(CharFrontend *c); /** * qemu_chr_fe_backend_connected: * - * Returns: true if there is a chardevice associated with @be. + * Returns: true if there is a backend associated with @c. */ -bool qemu_chr_fe_backend_connected(CharBackend *be); +bool qemu_chr_fe_backend_connected(CharFrontend *c); /** * qemu_chr_fe_backend_open: * - * Returns: true if chardevice associated with @be is open. + * Returns: true if the backend associated with @c is open. */ -bool qemu_chr_fe_backend_open(CharBackend *be); +bool qemu_chr_fe_backend_open(CharFrontend *c); /** * qemu_chr_fe_set_handlers_full: - * @b: a CharBackend + * @c: a CharFrontend * @fd_can_read: callback to get the amount of data the frontend may * receive * @fd_read: callback to receive data from char @@ -91,7 +90,7 @@ bool qemu_chr_fe_backend_open(CharBackend *be); * * Without associated Chardev, nothing is changed. */ -void qemu_chr_fe_set_handlers_full(CharBackend *b, +void qemu_chr_fe_set_handlers_full(CharFrontend *c, IOCanReadHandler *fd_can_read, IOReadHandler *fd_read, IOEventHandler *fd_event, @@ -106,7 +105,7 @@ void qemu_chr_fe_set_handlers_full(CharBackend *b, * * Version of qemu_chr_fe_set_handlers_full() with sync_state = true. */ -void qemu_chr_fe_set_handlers(CharBackend *b, +void qemu_chr_fe_set_handlers(CharFrontend *c, IOCanReadHandler *fd_can_read, IOReadHandler *fd_read, IOEventHandler *fd_event, @@ -122,14 +121,14 @@ void qemu_chr_fe_set_handlers(CharBackend *b, * * Without associated Chardev, nothing is changed. */ -void qemu_chr_fe_take_focus(CharBackend *b); +void qemu_chr_fe_take_focus(CharFrontend *c); /** * qemu_chr_fe_accept_input: * * Notify that the frontend is ready to receive data */ -void qemu_chr_fe_accept_input(CharBackend *be); +void qemu_chr_fe_accept_input(CharFrontend *c); /** * qemu_chr_fe_disconnect: @@ -137,7 +136,7 @@ void qemu_chr_fe_accept_input(CharBackend *be); * Close a fd accepted by character backend. * Without associated Chardev, do nothing. */ -void qemu_chr_fe_disconnect(CharBackend *be); +void qemu_chr_fe_disconnect(CharFrontend *c); /** * qemu_chr_fe_wait_connected: @@ -145,7 +144,7 @@ void qemu_chr_fe_disconnect(CharBackend *be); * Wait for character backend to be connected, return < 0 on error or * if no associated Chardev. */ -int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp); +int qemu_chr_fe_wait_connected(CharFrontend *c, Error **errp); /** * qemu_chr_fe_set_echo: @@ -156,17 +155,17 @@ int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp); * can see what you type if you try to type QMP commands. * Without associated Chardev, do nothing. */ -void qemu_chr_fe_set_echo(CharBackend *be, bool echo); +void qemu_chr_fe_set_echo(CharFrontend *c, bool echo); /** * qemu_chr_fe_set_open: - * @be: a CharBackend + * @c: a CharFrontend * @is_open: the front end open status * * This is an indication that the front end is ready (or not) to begin * doing I/O. Without associated Chardev, do nothing. */ -void qemu_chr_fe_set_open(CharBackend *be, bool is_open); +void qemu_chr_fe_set_open(CharFrontend *c, bool is_open); /** * qemu_chr_fe_printf: @@ -176,7 +175,7 @@ void qemu_chr_fe_set_open(CharBackend *be, bool is_open); * function is thread-safe. It does nothing without associated * Chardev. */ -void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...) +void qemu_chr_fe_printf(CharFrontend *c, const char *fmt, ...) G_GNUC_PRINTF(2, 3); @@ -215,7 +214,7 @@ typedef gboolean (*FEWatchFunc)(void *do_not_use, GIOCondition condition, void * * * Returns: the source tag */ -guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, +guint qemu_chr_fe_add_watch(CharFrontend *c, GIOCondition cond, FEWatchFunc func, void *user_data); /** @@ -230,7 +229,7 @@ guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond, * Returns: the number of bytes consumed (0 if no associated Chardev) * or -1 on error. */ -int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len); +int qemu_chr_fe_write(CharFrontend *c, const uint8_t *buf, int len); /** * qemu_chr_fe_write_all: @@ -245,7 +244,7 @@ int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len); * Returns: the number of bytes consumed (0 if no associated Chardev) * or -1 on error. */ -int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len); +int qemu_chr_fe_write_all(CharFrontend *c, const uint8_t *buf, int len); /** * qemu_chr_fe_read_all: @@ -257,7 +256,7 @@ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len); * Returns: the number of bytes read (0 if no associated Chardev) * or -1 on error. */ -int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len); +int qemu_chr_fe_read_all(CharFrontend *c, uint8_t *buf, int len); /** * qemu_chr_fe_ioctl: @@ -270,7 +269,7 @@ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len); * associated Chardev, -ENOTSUP, otherwise the return * value depends on the semantics of @cmd */ -int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg); +int qemu_chr_fe_ioctl(CharFrontend *c, int cmd, void *arg); /** * qemu_chr_fe_get_msgfd: @@ -283,7 +282,7 @@ int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg); * this function will return -1 until a client sends a new file * descriptor. */ -int qemu_chr_fe_get_msgfd(CharBackend *be); +int qemu_chr_fe_get_msgfd(CharFrontend *c); /** * qemu_chr_fe_get_msgfds: @@ -296,7 +295,7 @@ int qemu_chr_fe_get_msgfd(CharBackend *be); * this function will return -1 until a client sends a new set of file * descriptors. */ -int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num); +int qemu_chr_fe_get_msgfds(CharFrontend *c, int *fds, int num); /** * qemu_chr_fe_set_msgfds: @@ -309,6 +308,6 @@ int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num); * * Returns: -1 if fd passing isn't supported or no associated Chardev. */ -int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num); +int qemu_chr_fe_set_msgfds(CharFrontend *c, int *fds, int num); #endif /* QEMU_CHAR_FE_H */ diff --git a/include/chardev/char.h b/include/chardev/char.h index 429852f8d9..b65e9981c1 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -15,7 +15,7 @@ #define IAC 255 /* character device */ -typedef struct CharBackend CharBackend; +typedef struct CharFrontend CharFrontend; typedef enum { CHR_EVENT_BREAK, /* serial break char */ @@ -60,7 +60,7 @@ struct Chardev { Object parent_obj; QemuMutex chr_write_lock; - CharBackend *be; + CharFrontend *fe; char *label; char *filename; int logfd; diff --git a/include/hw/char/avr_usart.h b/include/hw/char/avr_usart.h index 0cc599e9b1..bd2d488f9a 100644 --- a/include/hw/char/avr_usart.h +++ b/include/hw/char/avr_usart.h @@ -66,7 +66,7 @@ struct AVRUsartState { /* */ MemoryRegion mmio; - CharBackend chr; + CharFrontend chr; bool enabled; diff --git a/include/hw/char/bcm2835_aux.h b/include/hw/char/bcm2835_aux.h index 9e081793a0..a11134f216 100644 --- a/include/hw/char/bcm2835_aux.h +++ b/include/hw/char/bcm2835_aux.h @@ -24,7 +24,7 @@ struct BCM2835AuxState { /*< public >*/ MemoryRegion iomem; - CharBackend chr; + CharFrontend chr; qemu_irq irq; uint8_t read_fifo[BCM2835_AUX_RX_FIFO_LEN]; diff --git a/include/hw/char/cadence_uart.h b/include/hw/char/cadence_uart.h index e7f7cd8468..c87c327357 100644 --- a/include/hw/char/cadence_uart.h +++ b/include/hw/char/cadence_uart.h @@ -47,7 +47,7 @@ struct CadenceUARTState { uint32_t rx_count; uint32_t tx_count; uint64_t char_tx_time; - CharBackend chr; + CharFrontend chr; qemu_irq irq; QEMUTimer *fifo_trigger_handle; Clock *refclk; diff --git a/include/hw/char/cmsdk-apb-uart.h b/include/hw/char/cmsdk-apb-uart.h index 7de8f8d1b9..3d0af26ceb 100644 --- a/include/hw/char/cmsdk-apb-uart.h +++ b/include/hw/char/cmsdk-apb-uart.h @@ -25,7 +25,7 @@ struct CMSDKAPBUART { /*< public >*/ MemoryRegion iomem; - CharBackend chr; + CharFrontend chr; qemu_irq txint; qemu_irq rxint; qemu_irq txovrint; diff --git a/include/hw/char/digic-uart.h b/include/hw/char/digic-uart.h index f710a1a099..3eebdab8a0 100644 --- a/include/hw/char/digic-uart.h +++ b/include/hw/char/digic-uart.h @@ -38,7 +38,7 @@ struct DigicUartState { /*< public >*/ MemoryRegion regs_region; - CharBackend chr; + CharFrontend chr; uint32_t reg_rx; uint32_t reg_st; diff --git a/include/hw/char/escc.h b/include/hw/char/escc.h index 8c4c6a7730..857f64699e 100644 --- a/include/hw/char/escc.h +++ b/include/hw/char/escc.h @@ -36,7 +36,7 @@ typedef struct ESCCChannelState { uint32_t reg; uint8_t wregs[ESCC_SERIAL_REGS], rregs[ESCC_SERIAL_REGS]; ESCCSERIOQueue queue; - CharBackend chr; + CharFrontend chr; int e0_mode, led_mode, caps_lock_mode, num_lock_mode; int disabled; int clock; diff --git a/include/hw/char/goldfish_tty.h b/include/hw/char/goldfish_tty.h index d59733e5ae..70fdedd1d0 100644 --- a/include/hw/char/goldfish_tty.h +++ b/include/hw/char/goldfish_tty.h @@ -24,7 +24,7 @@ struct GoldfishTTYState { MemoryRegion iomem; qemu_irq irq; - CharBackend chr; + CharFrontend chr; uint32_t data_len; uint64_t data_ptr; diff --git a/include/hw/char/ibex_uart.h b/include/hw/char/ibex_uart.h index 9deadf223b..1ccbb602e6 100644 --- a/include/hw/char/ibex_uart.h +++ b/include/hw/char/ibex_uart.h @@ -64,7 +64,7 @@ struct IbexUartState { Clock *f_clk; - CharBackend chr; + CharFrontend chr; qemu_irq tx_watermark; qemu_irq rx_watermark; qemu_irq tx_empty; diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h index 90ba3ff18c..2dcd2e6bcd 100644 --- a/include/hw/char/imx_serial.h +++ b/include/hw/char/imx_serial.h @@ -122,7 +122,7 @@ struct IMXSerialState { uint32_t ucr4; qemu_irq irq; - CharBackend chr; + CharFrontend chr; }; #endif diff --git a/include/hw/char/max78000_uart.h b/include/hw/char/max78000_uart.h index cf90d51dbf..ac93f83389 100644 --- a/include/hw/char/max78000_uart.h +++ b/include/hw/char/max78000_uart.h @@ -72,7 +72,7 @@ struct Max78000UartState { Fifo8 rx_fifo; - CharBackend chr; + CharFrontend chr; qemu_irq irq; }; #endif /* HW_STM32F2XX_USART_H */ diff --git a/include/hw/char/nrf51_uart.h b/include/hw/char/nrf51_uart.h index 561b6383c4..03d8c2a20d 100644 --- a/include/hw/char/nrf51_uart.h +++ b/include/hw/char/nrf51_uart.h @@ -59,7 +59,7 @@ struct NRF51UARTState { SysBusDevice parent_obj; MemoryRegion iomem; - CharBackend chr; + CharFrontend chr; qemu_irq irq; guint watch_tag; diff --git a/include/hw/char/parallel.h b/include/hw/char/parallel.h index 7b04478226..3f8d9b59a7 100644 --- a/include/hw/char/parallel.h +++ b/include/hw/char/parallel.h @@ -15,7 +15,7 @@ typedef struct ParallelState { uint8_t control; qemu_irq irq; int irq_pending; - CharBackend chr; + CharFrontend chr; int hw_driver; int epp_timeout; uint32_t last_read_offset; /* For debugging */ diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h index 299ca9b18b..2d4ff01c81 100644 --- a/include/hw/char/pl011.h +++ b/include/hw/char/pl011.h @@ -47,7 +47,7 @@ struct PL011State { int read_pos; int read_count; int read_trigger; - CharBackend chr; + CharFrontend chr; qemu_irq irq[6]; Clock *clk; bool migrate_clk; diff --git a/include/hw/char/renesas_sci.h b/include/hw/char/renesas_sci.h index a4764e3eee..90e784f36a 100644 --- a/include/hw/char/renesas_sci.h +++ b/include/hw/char/renesas_sci.h @@ -33,7 +33,7 @@ struct RSCIState { MemoryRegion memory; QEMUTimer timer; - CharBackend chr; + CharFrontend chr; qemu_irq irq[SCI_NR_IRQ]; uint8_t smr; diff --git a/include/hw/char/riscv_htif.h b/include/hw/char/riscv_htif.h index ee0ca29902..9d61e60d0a 100644 --- a/include/hw/char/riscv_htif.h +++ b/include/hw/char/riscv_htif.h @@ -36,7 +36,7 @@ typedef struct HTIFState { hwaddr fromhost_offset; MemoryRegion mmio; - CharBackend chr; + CharFrontend chr; uint64_t pending_read; } HTIFState; diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h index 2cfeaed7fb..b804e22588 100644 --- a/include/hw/char/serial.h +++ b/include/hw/char/serial.h @@ -54,7 +54,7 @@ struct SerialState { it can be reset while reading iir */ int thr_ipending; qemu_irq irq; - CharBackend chr; + CharFrontend chr; int last_break_enable; uint32_t baudbase; uint32_t tsr_retry; diff --git a/include/hw/char/shakti_uart.h b/include/hw/char/shakti_uart.h index 526c408233..e5e775d7c9 100644 --- a/include/hw/char/shakti_uart.h +++ b/include/hw/char/shakti_uart.h @@ -68,7 +68,7 @@ typedef struct { uint32_t uart_iq_cycles; uint32_t uart_rx_threshold; - CharBackend chr; + CharFrontend chr; } ShaktiUartState; #endif /* HW_SHAKTI_UART_H */ diff --git a/include/hw/char/sifive_uart.h b/include/hw/char/sifive_uart.h index 0846cf6218..6486c3f4a5 100644 --- a/include/hw/char/sifive_uart.h +++ b/include/hw/char/sifive_uart.h @@ -67,7 +67,7 @@ struct SiFiveUARTState { /*< public >*/ qemu_irq irq; MemoryRegion mmio; - CharBackend chr; + CharFrontend chr; uint32_t txfifo; uint32_t ie; diff --git a/include/hw/char/stm32f2xx_usart.h b/include/hw/char/stm32f2xx_usart.h index fdfa7424a7..f9018b8b8f 100644 --- a/include/hw/char/stm32f2xx_usart.h +++ b/include/hw/char/stm32f2xx_usart.h @@ -73,7 +73,7 @@ struct STM32F2XXUsartState { uint32_t usart_cr3; uint32_t usart_gtpr; - CharBackend chr; + CharFrontend chr; qemu_irq irq; }; #endif /* HW_STM32F2XX_USART_H */ diff --git a/include/hw/char/stm32l4x5_usart.h b/include/hw/char/stm32l4x5_usart.h index dd3866682a..cdf7419f53 100644 --- a/include/hw/char/stm32l4x5_usart.h +++ b/include/hw/char/stm32l4x5_usart.h @@ -53,7 +53,7 @@ struct Stm32l4x5UsartBaseState { uint32_t tdr; Clock *clk; - CharBackend chr; + CharFrontend chr; qemu_irq irq; guint watch_tag; }; diff --git a/include/hw/misc/ivshmem-flat.h b/include/hw/misc/ivshmem-flat.h index 3eca99004e..d656e57808 100644 --- a/include/hw/misc/ivshmem-flat.h +++ b/include/hw/misc/ivshmem-flat.h @@ -65,7 +65,7 @@ struct IvshmemFTState { QTAILQ_HEAD(, IvshmemPeer) peer; IvshmemPeer own; - CharBackend server_chr; + CharFrontend server_chr; /* IRQ */ qemu_irq irq; diff --git a/include/hw/qdev-properties-system.h b/include/hw/qdev-properties-system.h index 9601a11a09..5c6cc5eae8 100644 --- a/include/hw/qdev-properties-system.h +++ b/include/hw/qdev-properties-system.h @@ -38,7 +38,7 @@ extern const PropertyInfo qdev_prop_virtio_gpu_output_list; DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t) #define DEFINE_PROP_CHR(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharBackend) + DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharFrontend) #define DEFINE_PROP_NETDEV(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, NICPeers) #define DEFINE_PROP_DRIVE(_n, _s, _f) \ diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 0197aa4995..60b8133009 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -34,7 +34,7 @@ struct PropertyInfo { const char *description; const QEnumLookup *enum_table; bool realized_set_allowed; /* allow setting property on realized device */ - int (*print)(Object *obj, const Property *prop, char *dest, size_t len); + char *(*print)(Object *obj, const Property *prop); void (*set_default_value)(ObjectProperty *op, const Property *prop); ObjectProperty *(*create)(ObjectClass *oc, const char *name, const Property *prop); diff --git a/include/hw/virtio/vhost-user-base.h b/include/hw/virtio/vhost-user-base.h index 387e434b80..d5d2f081ae 100644 --- a/include/hw/virtio/vhost-user-base.h +++ b/include/hw/virtio/vhost-user-base.h @@ -20,7 +20,7 @@ struct VHostUserBase { VirtIODevice parent_obj; /* Properties */ - CharBackend chardev; + CharFrontend chardev; uint16_t virtio_id; uint32_t num_vqs; uint32_t vq_size; /* can't exceed VIRTIO_QUEUE_MAX */ diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h index a10f785672..8158d4673d 100644 --- a/include/hw/virtio/vhost-user-blk.h +++ b/include/hw/virtio/vhost-user-blk.h @@ -29,7 +29,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(VHostUserBlk, VHOST_USER_BLK) struct VHostUserBlk { VirtIODevice parent_obj; - CharBackend chardev; + CharFrontend chardev; int32_t bootindex; struct virtio_blk_config blkcfg; uint16_t num_queues; diff --git a/include/hw/virtio/vhost-user-fs.h b/include/hw/virtio/vhost-user-fs.h index 94c3aaa84e..5699ea03a1 100644 --- a/include/hw/virtio/vhost-user-fs.h +++ b/include/hw/virtio/vhost-user-fs.h @@ -24,7 +24,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(VHostUserFS, VHOST_USER_FS) typedef struct { - CharBackend chardev; + CharFrontend chardev; char *tag; uint16_t num_request_queues; uint16_t queue_size; diff --git a/include/hw/virtio/vhost-user-scmi.h b/include/hw/virtio/vhost-user-scmi.h index c90db77dd5..30ab0d7ab7 100644 --- a/include/hw/virtio/vhost-user-scmi.h +++ b/include/hw/virtio/vhost-user-scmi.h @@ -18,7 +18,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(VHostUserSCMI, VHOST_USER_SCMI); struct VHostUserSCMI { VirtIODevice parent; - CharBackend chardev; + CharFrontend chardev; struct vhost_virtqueue *vhost_vqs; struct vhost_dev vhost_dev; VhostUserState vhost_user; diff --git a/include/hw/virtio/vhost-user-vsock.h b/include/hw/virtio/vhost-user-vsock.h index 67aa46c952..5db6938b8b 100644 --- a/include/hw/virtio/vhost-user-vsock.h +++ b/include/hw/virtio/vhost-user-vsock.h @@ -20,7 +20,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(VHostUserVSock, VHOST_USER_VSOCK) typedef struct { - CharBackend chardev; + CharFrontend chardev; } VHostUserVSockConf; struct VHostUserVSock { diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h index 9a3f238b43..55d5725ef8 100644 --- a/include/hw/virtio/vhost-user.h +++ b/include/hw/virtio/vhost-user.h @@ -64,7 +64,7 @@ typedef struct VhostUserHostNotifier { * @memory_slots: */ typedef struct VhostUserState { - CharBackend *chr; + CharFrontend *chr; GPtrArray *notifiers; int memory_slots; bool supports_config; @@ -82,7 +82,7 @@ typedef struct VhostUserState { * * Return: true on success, false on error while setting errp. */ -bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp); +bool vhost_user_init(VhostUserState *user, CharFrontend *chr, Error **errp); /** * vhost_user_cleanup() - cleanup state @@ -96,7 +96,7 @@ void vhost_user_cleanup(VhostUserState *user); /** * vhost_user_async_close() - cleanup vhost-user post connection drop * @d: DeviceState for the associated device (passed to callback) - * @chardev: the CharBackend associated with the connection + * @chardev: the CharFrontend associated with the connection * @vhost: the common vhost device * @cb: the user callback function to complete the clean-up * @@ -108,7 +108,7 @@ void vhost_user_cleanup(VhostUserState *user); typedef void (*vu_async_close_fn)(DeviceState *cb); void vhost_user_async_close(DeviceState *d, - CharBackend *chardev, struct vhost_dev *vhost, + CharFrontend *chardev, struct vhost_dev *vhost, vu_async_close_fn cb); #endif diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 9f16f89a36..58e0f91fda 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -257,7 +257,7 @@ struct VhostUserGPU { VhostUserBackend *vhost; int vhost_gpu_fd; /* closed by the chardev */ - CharBackend vhost_chr; + CharFrontend vhost_chr; QemuDmaBuf *dmabuf[VIRTIO_GPU_MAX_SCANOUTS]; bool backend_blocked; }; diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h index 31e852ed6c..b6028bb5cd 100644 --- a/include/hw/virtio/virtio-scsi.h +++ b/include/hw/virtio/virtio-scsi.h @@ -58,7 +58,7 @@ struct VirtIOSCSIConf { uint32_t cmd_per_lun; char *vhostfd; char *wwpn; - CharBackend chardev; + CharFrontend chardev; uint32_t boot_tpgt; IOThread *iothread; IOThreadVirtQueueMappingList *iothread_vq_mapping_list; diff --git a/include/qobject/qobject.h b/include/qobject/qobject.h index a6244d0ce0..02f4c6a6eb 100644 --- a/include/qobject/qobject.h +++ b/include/qobject/qobject.h @@ -32,6 +32,7 @@ #ifndef QOBJECT_H #define QOBJECT_H +#include "qemu/atomic.h" #include "qapi/qapi-builtin-types.h" /* Not for use outside include/qobject/ */ @@ -73,7 +74,7 @@ QEMU_BUILD_BUG_MSG(QTYPE__MAX != 7, static inline void qobject_ref_impl(QObject *obj) { if (obj) { - obj->base.refcnt++; + qatomic_inc(&obj->base.refcnt); } } @@ -95,7 +96,7 @@ void qobject_destroy(QObject *obj); static inline void qobject_unref_impl(QObject *obj) { assert(!obj || obj->base.refcnt); - if (obj && --obj->base.refcnt == 0) { + if (obj && qatomic_fetch_dec(&obj->base.refcnt) == 1) { qobject_destroy(obj); } } diff --git a/include/system/qtest.h b/include/system/qtest.h index 84b1f8c6ee..7f6dc01d14 100644 --- a/include/system/qtest.h +++ b/include/system/qtest.h @@ -23,8 +23,8 @@ static inline bool qtest_enabled(void) return qtest_allowed; } -void G_GNUC_PRINTF(2, 3) qtest_sendf(CharBackend *chr, const char *fmt, ...); -void qtest_set_command_cb(bool (*pc_cb)(CharBackend *chr, gchar **words)); +void G_GNUC_PRINTF(2, 3) qtest_sendf(CharFrontend *chr, const char *fmt, ...); +void qtest_set_command_cb(bool (*pc_cb)(CharFrontend *chr, gchar **words)); bool qtest_driver(void); void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp); diff --git a/include/system/vhost-user-backend.h b/include/system/vhost-user-backend.h index 5634ebdb2e..3184c8e799 100644 --- a/include/system/vhost-user-backend.h +++ b/include/system/vhost-user-backend.h @@ -32,7 +32,7 @@ struct VhostUserBackend { Object parent; char *chr_name; - CharBackend chr; + CharFrontend chr; VhostUserState vhost_user; struct vhost_dev dev; VirtIODevice *vdev; diff --git a/meson.build b/meson.build index c5710a6a47..8ad37c992b 100644 --- a/meson.build +++ b/meson.build @@ -4251,6 +4251,7 @@ if have_rust '--allowlist-file', meson.project_source_root() + '/include/.*', '--allowlist-file', meson.project_build_root() + '/.*', '--blocklist-file', glib_pc.get_variable('includedir') + '/glib-2.0/.*', + '--blocklist-type', '.*_([a-z]*autoptr)$', ] if not rustfmt.found() if bindgen.version().version_compare('<0.65.0') diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index 5676eb334e..7735c73108 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -93,7 +93,7 @@ typedef struct HMPCommand { } HMPCommand; struct Monitor { - CharBackend chr; + CharFrontend chr; int suspend_cnt; /* Needs to be accessed atomically */ bool is_qmp; bool skip_flush; diff --git a/net/colo-compare.c b/net/colo-compare.c index 0e1844ee4c..95018b4704 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -88,7 +88,7 @@ static uint32_t max_queue_size; typedef struct SendCo { Coroutine *co; struct CompareState *s; - CharBackend *chr; + CharFrontend *chr; GQueue send_list; bool notify_remote_frame; bool done; @@ -108,10 +108,10 @@ struct CompareState { char *sec_indev; char *outdev; char *notify_dev; - CharBackend chr_pri_in; - CharBackend chr_sec_in; - CharBackend chr_out; - CharBackend chr_notify_dev; + CharFrontend chr_pri_in; + CharFrontend chr_sec_in; + CharFrontend chr_out; + CharFrontend chr_notify_dev; SocketReadState pri_rs; SocketReadState sec_rs; SocketReadState notify_rs; diff --git a/net/filter-mirror.c b/net/filter-mirror.c index 27734c91a7..8e01e98f40 100644 --- a/net/filter-mirror.c +++ b/net/filter-mirror.c @@ -37,8 +37,8 @@ struct MirrorState { NetFilterState parent_obj; char *indev; char *outdev; - CharBackend chr_in; - CharBackend chr_out; + CharFrontend chr_in; + CharFrontend chr_out; SocketReadState rs; bool vnet_hdr; }; diff --git a/net/passt.c b/net/passt.c index 32ecffb763..9ed811a514 100644 --- a/net/passt.c +++ b/net/passt.c @@ -71,7 +71,7 @@ typedef struct NetPasstState { /* vhost user */ VhostUserState *vhost_user; VHostNetState *vhost_net; - CharBackend vhost_chr; + CharFrontend vhost_chr; guint vhost_watch; uint64_t acked_features; bool started; diff --git a/net/slirp.c b/net/slirp.c index c627a9dd24..120eef6122 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -80,7 +80,7 @@ struct slirp_config_str { }; struct GuestFwd { - CharBackend hd; + CharFrontend hd; struct in_addr server; int port; Slirp *slirp; diff --git a/net/vhost-user.c b/net/vhost-user.c index 8b96157145..a4bb49bbcf 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -65,7 +65,7 @@ static const int user_feature_bits[] = { typedef struct NetVhostUserState { NetClientState nc; - CharBackend chr; /* only queue index 0 */ + CharFrontend chr; /* only queue index 0 */ VhostUserState *vhost_user; VHostNetState *vhost_net; guint watch; diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 783e626802..ace0baf9bd 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,18 +1,8 @@ [workspace] resolver = "2" members = [ - "bits", - "bql", - "common", - "migration", - "qemu-macros", - "qom", - "system", - "hw/core", "hw/char/pl011", "hw/timer/hpet", - "trace", - "util", "tests", ] diff --git a/rust/bindings/src/lib.rs b/rust/bindings/src/lib.rs index 5bf03b1370..4c9bb794f7 100644 --- a/rust/bindings/src/lib.rs +++ b/rust/bindings/src/lib.rs @@ -28,8 +28,8 @@ include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); // BQL is taken, either directly or via `BqlCell` and `BqlRefCell`. // When bindings for character devices are introduced, this can be // moved to the Opaque<> wrapper in src/chardev.rs. -unsafe impl Send for CharBackend {} -unsafe impl Sync for CharBackend {} +unsafe impl Send for CharFrontend {} +unsafe impl Sync for CharFrontend {} // SAFETY: this is a pure data struct unsafe impl Send for CoalescedMemoryRange {} diff --git a/rust/bql/src/bindings.rs b/rust/bql/src/bindings.rs index 8c70f3a87c..c656cf1884 100644 --- a/rust/bql/src/bindings.rs +++ b/rust/bql/src/bindings.rs @@ -18,9 +18,7 @@ clippy::too_many_arguments )] -use glib_sys::{ - guint, GArray, GHashTable, GHashTableIter, GList, GPollFD, GPtrArray, GQueue, GSList, GSource, -}; +use glib_sys::{guint, GArray, GHashTable, GHashTableIter, GPollFD, GPtrArray, GSList, GSource}; #[cfg(MESON)] include!("bindings.inc.rs"); diff --git a/rust/chardev/src/bindings.rs b/rust/chardev/src/bindings.rs index c95dc89c56..360b30d6a3 100644 --- a/rust/chardev/src/bindings.rs +++ b/rust/chardev/src/bindings.rs @@ -20,8 +20,8 @@ use common::Zeroable; use glib_sys::{ - gboolean, guint, GArray, GHashTable, GHashTableIter, GIOCondition, GList, GMainContext, - GPollFD, GPtrArray, GQueue, GSList, GSource, GSourceFunc, + gboolean, guint, GArray, GHashTable, GHashTableIter, GIOCondition, GMainContext, GPollFD, + GPtrArray, GSList, GSource, GSourceFunc, }; #[cfg(MESON)] @@ -34,7 +34,7 @@ include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); // BQL is taken, either directly or via `BqlCell` and `BqlRefCell`. // When bindings for character devices are introduced, this can be // moved to the Opaque<> wrapper in src/chardev.rs. -unsafe impl Send for CharBackend {} -unsafe impl Sync for CharBackend {} +unsafe impl Send for CharFrontend {} +unsafe impl Sync for CharFrontend {} -unsafe impl Zeroable for CharBackend {} +unsafe impl Zeroable for CharFrontend {} diff --git a/rust/chardev/src/chardev.rs b/rust/chardev/src/chardev.rs index 2014479674..f0b7975dbf 100644 --- a/rust/chardev/src/chardev.rs +++ b/rust/chardev/src/chardev.rs @@ -6,7 +6,7 @@ //! //! Character devices in QEMU can run under the big QEMU lock or in a separate //! `GMainContext`. Here we only support the former, because the bindings -//! enforce that the BQL is taken whenever the functions in [`CharBackend`] are +//! enforce that the BQL is taken whenever the functions in [`CharFrontend`] are //! called. use std::{ @@ -32,25 +32,25 @@ pub struct Chardev(Opaque); pub type ChardevClass = bindings::ChardevClass; pub type Event = bindings::QEMUChrEvent; -/// A safe wrapper around [`bindings::CharBackend`], denoting the character +/// A safe wrapper around [`bindings::CharFrontend`], denoting the character /// back-end that is used for example by a device. Compared to the /// underlying C struct it adds BQL protection, and is marked as pinned /// because the QOM object ([`bindings::Chardev`]) contains a pointer to -/// the `CharBackend`. -pub struct CharBackend { - inner: BqlRefCell, +/// the `CharFrontend`. +pub struct CharFrontend { + inner: BqlRefCell, _pin: PhantomPinned, } -pub struct CharBackendMut<'a>(BqlRefMut<'a, bindings::CharBackend>); +pub struct CharFrontendMut<'a>(BqlRefMut<'a, bindings::CharFrontend>); -impl Write for CharBackendMut<'_> { +impl Write for CharFrontendMut<'_> { fn flush(&mut self) -> io::Result<()> { Ok(()) } fn write(&mut self, buf: &[u8]) -> io::Result { - let chr: &mut bindings::CharBackend = &mut self.0; + let chr: &mut bindings::CharFrontend = &mut self.0; let len = buf.len().try_into().unwrap(); let r = unsafe { bindings::qemu_chr_fe_write(addr_of_mut!(*chr), buf.as_ptr(), len) }; @@ -58,7 +58,7 @@ impl Write for CharBackendMut<'_> { } fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - let chr: &mut bindings::CharBackend = &mut self.0; + let chr: &mut bindings::CharFrontend = &mut self.0; let len = buf.len().try_into().unwrap(); let r = unsafe { bindings::qemu_chr_fe_write_all(addr_of_mut!(*chr), buf.as_ptr(), len) }; @@ -72,7 +72,7 @@ impl Write for CharBackendMut<'_> { } } -impl Debug for CharBackend { +impl Debug for CharFrontend { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // SAFETY: accessed just to print the values let chr = self.inner.as_ptr(); @@ -81,13 +81,13 @@ impl Debug for CharBackend { } // FIXME: use something like PinnedDrop from the pinned_init crate -impl Drop for CharBackend { +impl Drop for CharFrontend { fn drop(&mut self) { self.disable_handlers(); } } -impl CharBackend { +impl CharFrontend { /// Enable the front-end's character device handlers, if there is an /// associated `Chardev`. pub fn enable_handlers< @@ -198,7 +198,7 @@ impl CharBackend { /// the big QEMU lock while the character device is borrowed, as /// that might cause C code to write to the character device. pub fn borrow_mut(&self) -> impl Write + '_ { - CharBackendMut(self.inner.borrow_mut()) + CharFrontendMut(self.inner.borrow_mut()) } /// Send a continuous stream of zero bits on the line if `enabled` is diff --git a/rust/hw/char/pl011/src/bindings.rs b/rust/hw/char/pl011/src/bindings.rs index 52a76d0de5..654be9185b 100644 --- a/rust/hw/char/pl011/src/bindings.rs +++ b/rust/hw/char/pl011/src/bindings.rs @@ -22,7 +22,7 @@ use glib_sys::{ gboolean, guint, GArray, GByteArray, GHashTable, GHashTableIter, GIOCondition, GList, - GMainContext, GPollFD, GPtrArray, GQueue, GSList, GSource, GSourceFunc, GString, + GMainContext, GPollFD, GPtrArray, GSList, GSource, GSourceFunc, GString, }; #[cfg(MESON)] diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/device.rs index 8889d6e54f..5e9b13fdf9 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -5,7 +5,7 @@ use std::{ffi::CStr, mem::size_of}; use bql::BqlRefCell; -use chardev::{CharBackend, Chardev, Event}; +use chardev::{CharFrontend, Chardev, Event}; use common::{static_assert, uninit_field_mut}; use hwcore::{ Clock, ClockEvent, DeviceImpl, DeviceMethods, DeviceState, IRQState, InterruptSource, @@ -106,7 +106,7 @@ pub struct PL011State { pub iomem: MemoryRegion, #[doc(alias = "chr")] #[property(rename = "chardev")] - pub char_backend: CharBackend, + pub char_frontend: CharFrontend, pub regs: BqlRefCell, /// QEMU interrupts /// @@ -240,7 +240,7 @@ impl PL011Registers { } let update = (self.line_control.send_break() != new_val.send_break()) && { let break_enable = new_val.send_break(); - let _ = device.char_backend.send_break(break_enable); + let _ = device.char_frontend.send_break(break_enable); self.loopback_break(break_enable) }; self.line_control = new_val; @@ -561,7 +561,7 @@ impl PL011State { trace::trace_pl011_read(offset, result, c""); if update_irq { self.update(); - self.char_backend.accept_input(); + self.char_frontend.accept_input(); } result.into() } @@ -579,7 +579,7 @@ impl PL011State { let ch: [u8; 1] = [value as u8]; // XXX this blocks entire thread. Rewrite to use // qemu_chr_fe_write and background I/O callbacks - let _ = self.char_backend.write_all(&ch); + let _ = self.char_frontend.write_all(&ch); } update_irq = self.regs.borrow_mut().write(field, value as u32, self); @@ -645,7 +645,7 @@ impl PL011State { } fn realize(&self) -> util::Result<()> { - self.char_backend + self.char_frontend .enable_handlers(self, Self::can_receive, Self::receive, Self::event); Ok(()) } diff --git a/rust/hw/core/src/bindings.rs b/rust/hw/core/src/bindings.rs index 65b9aae753..730d5b28a3 100644 --- a/rust/hw/core/src/bindings.rs +++ b/rust/hw/core/src/bindings.rs @@ -20,9 +20,7 @@ use chardev::bindings::Chardev; use common::Zeroable; -use glib_sys::{ - GArray, GByteArray, GHashTable, GHashTableIter, GList, GPtrArray, GQueue, GSList, GString, -}; +use glib_sys::{GArray, GByteArray, GHashTable, GHashTableIter, GList, GPtrArray, GSList, GString}; use migration::bindings::VMStateDescription; use qom::bindings::ObjectClass; use system::bindings::MemoryRegion; diff --git a/rust/hw/core/src/qdev.rs b/rust/hw/core/src/qdev.rs index c3097a284d..4e983da28b 100644 --- a/rust/hw/core/src/qdev.rs +++ b/rust/hw/core/src/qdev.rs @@ -156,7 +156,7 @@ impl_qdev_prop!(u64, qdev_prop_uint64, qdev_prop_bit64); impl_qdev_prop!(usize, qdev_prop_usize); impl_qdev_prop!(i32, qdev_prop_int32); impl_qdev_prop!(i64, qdev_prop_int64); -impl_qdev_prop!(chardev::CharBackend, qdev_prop_chr); +impl_qdev_prop!(chardev::CharFrontend, qdev_prop_chr); /// Trait to define device properties. /// diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/device.rs index 86638c0766..23f2eefd1c 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -539,7 +539,7 @@ pub struct HPETState { // Internal state /// Capabilities that QEMU HPET supports. /// bit 0: MSI (or FSB) support. - #[property(rename = "msi", bit = HPET_FLAG_MSI_SUPPORT_SHIFT as u8, default = false)] + #[property(rename = "msi", bit = HPET_FLAG_MSI_SUPPORT_SHIFT, default = false)] flags: u32, /// Offset of main counter relative to qemu clock. diff --git a/rust/migration/src/bindings.rs b/rust/migration/src/bindings.rs index 24503eb69b..e9c058386c 100644 --- a/rust/migration/src/bindings.rs +++ b/rust/migration/src/bindings.rs @@ -19,7 +19,7 @@ )] use common::Zeroable; -use glib_sys::{GHashTable, GHashTableIter, GList, GPtrArray, GQueue, GSList}; +use glib_sys::{GHashTable, GHashTableIter, GPtrArray, GSList}; #[cfg(MESON)] include!("bindings.inc.rs"); diff --git a/rust/migration/src/vmstate.rs b/rust/migration/src/vmstate.rs index 42e5df8d81..5a237c409a 100644 --- a/rust/migration/src/vmstate.rs +++ b/rust/migration/src/vmstate.rs @@ -268,7 +268,7 @@ macro_rules! impl_vmstate_transparent { ($type:ty where $base:tt: VMState $($where:tt)*) => { unsafe impl<$base> $crate::vmstate::VMState for $type where $base: $crate::vmstate::VMState $($where)* { const BASE: $crate::vmstate::VMStateField = $crate::vmstate::VMStateField { - size: mem::size_of::<$type>(), + size: ::core::mem::size_of::<$type>(), ..<$base as $crate::vmstate::VMState>::BASE }; const VARRAY_FLAG: $crate::bindings::VMStateFlags = <$base as $crate::vmstate::VMState>::VARRAY_FLAG; @@ -282,6 +282,7 @@ impl_vmstate_transparent!(std::cell::Cell where T: VMState); impl_vmstate_transparent!(std::cell::UnsafeCell where T: VMState); impl_vmstate_transparent!(std::pin::Pin where T: VMState); impl_vmstate_transparent!(common::Opaque where T: VMState); +impl_vmstate_transparent!(std::mem::ManuallyDrop where T: VMState); #[macro_export] macro_rules! impl_vmstate_bitsized { diff --git a/rust/qemu-macros/src/lib.rs b/rust/qemu-macros/src/lib.rs index 50239f228b..ee417bb4b4 100644 --- a/rust/qemu-macros/src/lib.rs +++ b/rust/qemu-macros/src/lib.rs @@ -262,12 +262,25 @@ fn derive_device_or_error(input: DeriveInput) -> Result::BASE_INFO } + let (qdev_prop, bitval) = if let Some(bitval) = bitnr { + ( + quote! { <#field_ty as ::hwcore::QDevProp>::BIT_INFO }, + quote! { + { + const { + assert!(#bitval >= 0 && #bitval < #field_ty::BITS as _, + "bit number exceeds type bits range"); + } + #bitval as u8 + } + }, + ) } else { - quote! { <#field_ty as ::hwcore::QDevProp>::BIT_INFO } + ( + quote! { <#field_ty as ::hwcore::QDevProp>::BASE_INFO }, + quote! { 0 }, + ) }; - let bitnr = bitnr.unwrap_or(syn::Expr::Verbatim(quote! { 0 })); let set_default = defval.is_some(); let defval = defval.unwrap_or(syn::Expr::Verbatim(quote! { 0 })); properties_expanded.push(quote! { @@ -275,7 +288,7 @@ fn derive_device_or_error(input: DeriveInput) -> Result::BIT_INFO, offset: ::core::mem::offset_of!(DummyState, flags) as isize, - bitnr: 3, + bitnr : { + const { assert!(3 >= 0 && 3 < u32::BITS as _ , "bit number exceeds type bits range"); } + 3 as u8 + }, set_default: false, defval: ::hwcore::bindings::Property__bindgen_ty_1 { u: 0 as u64 }, ..::common::Zeroable::ZERO @@ -207,7 +210,10 @@ fn test_derive_device() { name: ::std::ffi::CStr::as_ptr(c"flags"), info: ::BIT_INFO, offset: ::core::mem::offset_of!(DummyState, flags) as isize, - bitnr: 3, + bitnr : { + const { assert!(3 >= 0 && 3 < u32::BITS as _ , "bit number exceeds type bits range"); } + 3 as u8 + }, set_default: true, defval: ::hwcore::bindings::Property__bindgen_ty_1 { u: true as u64 }, ..::common::Zeroable::ZERO @@ -235,7 +241,10 @@ fn test_derive_device() { name: ::std::ffi::CStr::as_ptr(c"msi"), info: ::BIT_INFO, offset: ::core::mem::offset_of!(DummyState, flags) as isize, - bitnr: 3, + bitnr : { + const { assert!(3 >= 0 && 3 < u64::BITS as _ , "bit number exceeds type bits range"); } + 3 as u8 + }, set_default: true, defval: ::hwcore::bindings::Property__bindgen_ty_1 { u: false as u64 }, ..::common::Zeroable::ZERO diff --git a/rust/qom/src/bindings.rs b/rust/qom/src/bindings.rs index 91de42f242..e61259ec2e 100644 --- a/rust/qom/src/bindings.rs +++ b/rust/qom/src/bindings.rs @@ -18,7 +18,7 @@ clippy::too_many_arguments )] -use glib_sys::{GHashTable, GHashTableIter, GList, GPtrArray, GQueue, GSList}; +use glib_sys::{GHashTable, GHashTableIter, GPtrArray, GSList}; #[cfg(MESON)] include!("bindings.inc.rs"); diff --git a/rust/qom/src/qom.rs b/rust/qom/src/qom.rs index 5808051cd7..84455cea79 100644 --- a/rust/qom/src/qom.rs +++ b/rust/qom/src/qom.rs @@ -102,7 +102,7 @@ use std::{ }; use common::Opaque; -use migration::impl_vmstate_pointer; +use migration::{impl_vmstate_pointer, impl_vmstate_transparent}; use crate::bindings::{ self, object_class_dynamic_cast, object_dynamic_cast, object_get_class, object_get_typename, @@ -182,6 +182,7 @@ macro_rules! qom_isa { #[derive(Debug)] #[repr(transparent)] pub struct ParentField(std::mem::ManuallyDrop); +impl_vmstate_transparent!(ParentField where T: VMState + ObjectType); impl Deref for ParentField { type Target = T; diff --git a/rust/system/src/bindings.rs b/rust/system/src/bindings.rs index 6cbb588de3..ddccfe0436 100644 --- a/rust/system/src/bindings.rs +++ b/rust/system/src/bindings.rs @@ -20,8 +20,8 @@ use common::Zeroable; use glib_sys::{ - guint, GArray, GByteArray, GHashTable, GHashTableIter, GList, GPollFD, GPtrArray, GQueue, - GSList, GString, + guint, GArray, GByteArray, GHashTable, GHashTableIter, GList, GPollFD, GPtrArray, GSList, + GString, }; #[cfg(MESON)] diff --git a/rust/util/src/bindings.rs b/rust/util/src/bindings.rs index c277a295ad..3514a66f5f 100644 --- a/rust/util/src/bindings.rs +++ b/rust/util/src/bindings.rs @@ -18,7 +18,7 @@ clippy::too_many_arguments )] -use glib_sys::{guint, GList, GPollFD, GQueue, GSList, GString}; +use glib_sys::{guint, GPollFD, GString}; #[cfg(MESON)] include!("bindings.inc.rs"); diff --git a/scripts/meson-buildoptions.py b/scripts/meson-buildoptions.py index a3e22471b2..e636d258e8 100644 --- a/scripts/meson-buildoptions.py +++ b/scripts/meson-buildoptions.py @@ -111,13 +111,13 @@ def help_line(left, opt, indent, long): right = f'{opt["description"]}' if long: value = get_help(opt) - if value != "auto" and value != "": + if value not in {"", "auto"}: right += f" [{value}]" if "choices" in opt and long: choices = "/".join(sorted(opt["choices"])) right += f" (choices: {choices})" - for x in wrap(" " + left, right, indent): - sh_print(x) + for line in wrap(" " + left, right, indent): + sh_print(line) # Return whether the option (a dictionary) can be used with @@ -144,18 +144,18 @@ def require_arg(opt): return not ({"enabled", "disabled"}.intersection(opt["choices"])) -def filter_options(json): - if ":" in json["name"]: +def filter_options(opt): + if ":" in opt["name"]: return False - if json["section"] == "user": - return json["name"] not in SKIP_OPTIONS + if opt["section"] == "user": + return opt["name"] not in SKIP_OPTIONS else: - return json["name"] in BUILTIN_OPTIONS + return opt["name"] in BUILTIN_OPTIONS -def load_options(json): - json = [x for x in json if filter_options(x)] - return sorted(json, key=lambda x: x["name"]) +def load_options(opts): + opts = [opt for opt in opts if filter_options(opt)] + return sorted(opts, key=lambda opt: opt["name"]) def cli_option(opt): @@ -223,7 +223,7 @@ def print_parse(options): key = cli_option(opt) name = opt["name"] if require_arg(opt): - if opt["type"] == "array" and not "choices" in opt: + if opt["type"] == "array" and "choices" not in opt: print(f' --{key}=*) quote_sh "-D{name}=$(meson_option_build_array $2)" ;;') else: print(f' --{key}=*) quote_sh "-D{name}=$2" ;;') @@ -241,14 +241,19 @@ def print_parse(options): print(" esac") print("}") -json_data = sys.stdin.read() -try: - options = load_options(json.loads(json_data)) -except: - print("Failure in scripts/meson-buildoptions.py parsing stdin as json", - file=sys.stderr) - print(json_data, file=sys.stderr) - sys.exit(1) -print("# This file is generated by meson-buildoptions.py, do not edit!") -print_help(options) -print_parse(options) + +def main(): + json_data = sys.stdin.read() + try: + options = load_options(json.loads(json_data)) + except: + print("Failure in scripts/meson-buildoptions.py parsing stdin as json", + file=sys.stderr) + print(json_data, file=sys.stderr) + sys.exit(1) + print("# This file is generated by meson-buildoptions.py, do not edit!") + print_help(options) + print_parse(options) + + +sys.exit(main()) diff --git a/semihosting/console.c b/semihosting/console.c index c3683a1566..a4db8d8e76 100644 --- a/semihosting/console.c +++ b/semihosting/console.c @@ -30,7 +30,7 @@ /* Access to this structure is protected by the BQL */ typedef struct SemihostingConsole { - CharBackend backend; + CharFrontend frontend; Chardev *chr; GSList *sleeping_cpus; bool got; @@ -122,8 +122,8 @@ void qemu_semihosting_console_init(Chardev *chr) console.chr = chr; if (chr) { fifo8_create(&console.fifo, FIFO_SIZE); - qemu_chr_fe_init(&console.backend, chr, &error_abort); - qemu_chr_fe_set_handlers(&console.backend, + qemu_chr_fe_init(&console.frontend, chr, &error_abort); + qemu_chr_fe_set_handlers(&console.frontend, console_can_read, console_read, NULL, NULL, &console, diff --git a/system/qtest.c b/system/qtest.c index fa42c9f921..e4d1cd75da 100644 --- a/system/qtest.c +++ b/system/qtest.c @@ -44,7 +44,7 @@ struct QTest { bool has_machine_link; char *chr_name; Chardev *chr; - CharBackend qtest_chr; + CharFrontend qtest_chr; char *log; }; @@ -293,20 +293,20 @@ static void G_GNUC_PRINTF(1, 2) qtest_log_send(const char *fmt, ...) static void qtest_server_char_be_send(void *opaque, const char *str) { size_t len = strlen(str); - CharBackend* chr = (CharBackend *)opaque; + CharFrontend* chr = (CharFrontend *)opaque; qemu_chr_fe_write_all(chr, (uint8_t *)str, len); if (qtest_log_fp && qtest_opened) { fprintf(qtest_log_fp, "%s", str); } } -static void qtest_send(CharBackend *chr, const char *str) +static void qtest_send(CharFrontend *chr, const char *str) { qtest_log_timestamp(); qtest_server_send(qtest_server_send_opaque, str); } -void qtest_sendf(CharBackend *chr, const char *fmt, ...) +void qtest_sendf(CharFrontend *chr, const char *fmt, ...) { va_list ap; gchar *buffer; @@ -324,16 +324,16 @@ static void qtest_irq_handler(void *opaque, int n, int level) qemu_set_irq(old_irq, level); if (irq_levels[n] != level) { - CharBackend *chr = &qtest->qtest_chr; + CharFrontend *chr = &qtest->qtest_chr; irq_levels[n] = level; qtest_sendf(chr, "IRQ %s %d\n", level ? "raise" : "lower", n); } } -static bool (*process_command_cb)(CharBackend *chr, gchar **words); +static bool (*process_command_cb)(CharFrontend *chr, gchar **words); -void qtest_set_command_cb(bool (*pc_cb)(CharBackend *chr, gchar **words)) +void qtest_set_command_cb(bool (*pc_cb)(CharFrontend *chr, gchar **words)) { assert(!process_command_cb); /* Switch to a list if we need more than one */ @@ -349,7 +349,7 @@ static void qtest_install_gpio_out_intercept(DeviceState *dev, const char *name, *disconnected = qdev_intercept_gpio_out(dev, icpt, name, n); } -static void qtest_process_command(CharBackend *chr, gchar **words) +static void qtest_process_command(CharFrontend *chr, gchar **words) { const gchar *command; @@ -757,7 +757,7 @@ static void qtest_process_command(CharBackend *chr, gchar **words) * Process as much of @inbuf as we can in newline terminated chunks. * Remove the processed commands from @inbuf as we go. */ -static void qtest_process_inbuf(CharBackend *chr, GString *inbuf) +static void qtest_process_inbuf(CharFrontend *chr, GString *inbuf) { char *end; @@ -773,7 +773,7 @@ static void qtest_process_inbuf(CharBackend *chr, GString *inbuf) static void qtest_read(void *opaque, const uint8_t *buf, int size) { - CharBackend *chr = opaque; + CharFrontend *chr = opaque; g_string_append_len(inbuf, (const gchar *)buf, size); qtest_process_inbuf(chr, inbuf); diff --git a/target/hppa/sys_helper.c b/target/hppa/sys_helper.c index 6e65fadcc7..88109f0181 100644 --- a/target/hppa/sys_helper.c +++ b/target/hppa/sys_helper.c @@ -135,7 +135,7 @@ void HELPER(rfi_r)(CPUHPPAState *env) */ void HELPER(diag_console_output)(CPUHPPAState *env) { - CharBackend *serial_backend; + CharFrontend *fe; Chardev *serial_port; unsigned char c; @@ -145,14 +145,14 @@ void HELPER(diag_console_output)(CPUHPPAState *env) return; } - /* get serial_backend for the serial port */ - serial_backend = serial_port->be; - if (!serial_backend || - !qemu_chr_fe_backend_connected(serial_backend)) { + /* get the frontend for the serial port */ + fe = serial_port->fe; + if (!fe || + !qemu_chr_fe_backend_connected(fe)) { return; } c = (unsigned char)env->gr[26]; - qemu_chr_fe_write(serial_backend, &c, sizeof(c)); + qemu_chr_fe_write(fe, &c, sizeof(c)); } #endif diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c index a502437c30..3838c9f5a6 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -446,6 +446,7 @@ int hvf_process_events(CPUState *cs) cs->halted = 0; } if (cpu_test_interrupt(cs, CPU_INTERRUPT_SIPI)) { + cpu_reset_interrupt(cs, CPU_INTERRUPT_SIPI); cpu_synchronize_state(cs); do_cpu_sipi(cpu); } diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index f7a6ef650a..60c7981138 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -2748,6 +2748,12 @@ static void register_smram_listener(Notifier *n, void *unused) } } +/* It should only be called in cpu's hotplug callback */ +void kvm_smm_cpu_address_space_init(X86CPU *cpu) +{ + cpu_address_space_init(CPU(cpu), X86ASIdx_SMM, "cpu-smm", &smram_as_root); +} + static void *kvm_msr_energy_thread(void *data) { KVMState *s = data; @@ -5653,6 +5659,7 @@ int kvm_arch_process_async_events(CPUState *cs) cs->halted = 0; } if (cpu_test_interrupt(cs, CPU_INTERRUPT_SIPI)) { + cpu_reset_interrupt(cs, CPU_INTERRUPT_SIPI); kvm_cpu_synchronize_state(cs); do_cpu_sipi(cpu); } diff --git a/target/i386/kvm/kvm_i386.h b/target/i386/kvm/kvm_i386.h index 5c908fdd6a..2b653442f4 100644 --- a/target/i386/kvm/kvm_i386.h +++ b/target/i386/kvm/kvm_i386.h @@ -74,6 +74,7 @@ uint32_t kvm_x86_build_cpuid(CPUX86State *env, struct kvm_cpuid_entry2 *entries, uint32_t cpuid_i); #endif /* CONFIG_KVM */ +void kvm_smm_cpu_address_space_init(X86CPU *cpu); void kvm_pc_setup_irq_routing(bool pci_enabled); #endif diff --git a/target/i386/mshv/mshv-cpu.c b/target/i386/mshv/mshv-cpu.c index 1f7b9cb37e..1c3db02188 100644 --- a/target/i386/mshv/mshv-cpu.c +++ b/target/i386/mshv/mshv-cpu.c @@ -1489,6 +1489,10 @@ static int handle_pio_str(CPUState *cpu, hv_x64_io_port_intercept_message *info) reg_values[0] = info->rsi; } else { ret = handle_pio_str_read(cpu, info, repeat, port, direction_flag); + if (ret < 0) { + error_report("Failed to handle pio str read"); + return -1; + } reg_names[0] = HV_X64_REGISTER_RDI; reg_values[0] = info->rdi; } diff --git a/target/i386/nvmm/nvmm-all.c b/target/i386/nvmm/nvmm-all.c index 2e442baf4b..b9bd9ed985 100644 --- a/target/i386/nvmm/nvmm-all.c +++ b/target/i386/nvmm/nvmm-all.c @@ -709,6 +709,7 @@ nvmm_vcpu_loop(CPUState *cpu) cpu->halted = false; } if (cpu_test_interrupt(cpu, CPU_INTERRUPT_SIPI)) { + cpu_reset_interrupt(cpu, CPU_INTERRUPT_SIPI); nvmm_cpu_synchronize_state(cpu); do_cpu_sipi(x86_cpu); } diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c index 256761834c..6bf8d5f4bb 100644 --- a/target/i386/whpx/whpx-all.c +++ b/target/i386/whpx/whpx-all.c @@ -1621,6 +1621,7 @@ static void whpx_vcpu_process_async_events(CPUState *cpu) } if (cpu_test_interrupt(cpu, CPU_INTERRUPT_SIPI)) { + cpu_reset_interrupt(cpu, CPU_INTERRUPT_SIPI); whpx_cpu_synchronize_state(cpu); do_cpu_sipi(x86_cpu); } diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 000e44b2b7..47e672c7aa 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -1598,7 +1598,7 @@ static void kvm_riscv_handle_sbi_dbcn(CPUState *cs, struct kvm_run *run) buf = g_malloc0(num_bytes); if (run->riscv_sbi.function_id == SBI_EXT_DBCN_CONSOLE_READ) { - ret = qemu_chr_fe_read_all(serial_hd(0)->be, buf, num_bytes); + ret = qemu_chr_fe_read_all(serial_hd(0)->fe, buf, num_bytes); if (ret < 0) { error_report("SBI_EXT_DBCN_CONSOLE_READ: error when " "reading chardev"); @@ -1609,7 +1609,7 @@ static void kvm_riscv_handle_sbi_dbcn(CPUState *cs, struct kvm_run *run) } else { address_space_read(cs->as, addr, attrs, buf, num_bytes); - ret = qemu_chr_fe_write_all(serial_hd(0)->be, buf, num_bytes); + ret = qemu_chr_fe_write_all(serial_hd(0)->fe, buf, num_bytes); if (ret < 0) { error_report("SBI_EXT_DBCN_CONSOLE_WRITE: error when " "writing chardev"); @@ -1622,7 +1622,7 @@ static void kvm_riscv_handle_sbi_dbcn(CPUState *cs, struct kvm_run *run) break; case SBI_EXT_DBCN_CONSOLE_WRITE_BYTE: ch = run->riscv_sbi.args[0]; - ret = qemu_chr_fe_write_all(serial_hd(0)->be, &ch, sizeof(ch)); + ret = qemu_chr_fe_write_all(serial_hd(0)->fe, &ch, sizeof(ch)); if (ret < 0) { error_report("SBI_EXT_DBCN_CONSOLE_WRITE_BYTE: error when " @@ -1645,10 +1645,10 @@ static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run) switch (run->riscv_sbi.extension_id) { case SBI_EXT_0_1_CONSOLE_PUTCHAR: ch = run->riscv_sbi.args[0]; - qemu_chr_fe_write(serial_hd(0)->be, &ch, sizeof(ch)); + qemu_chr_fe_write(serial_hd(0)->fe, &ch, sizeof(ch)); break; case SBI_EXT_0_1_CONSOLE_GETCHAR: - ret = qemu_chr_fe_read_all(serial_hd(0)->be, &ch, sizeof(ch)); + ret = qemu_chr_fe_read_all(serial_hd(0)->fe, &ch, sizeof(ch)); if (ret == sizeof(ch)) { run->riscv_sbi.ret[0] = ch; } else { diff --git a/target/xtensa/xtensa-semi.c b/target/xtensa/xtensa-semi.c index 431c263dc5..552815ebfd 100644 --- a/target/xtensa/xtensa-semi.c +++ b/target/xtensa/xtensa-semi.c @@ -148,7 +148,7 @@ static uint32_t errno_h2g(int host_errno) } typedef struct XtensaSimConsole { - CharBackend be; + CharFrontend fe; struct { char buffer[16]; size_t offset; @@ -182,8 +182,8 @@ void xtensa_sim_open_console(Chardev *chr) { static XtensaSimConsole console; - qemu_chr_fe_init(&console.be, chr, &error_abort); - qemu_chr_fe_set_handlers(&console.be, + qemu_chr_fe_init(&console.fe, chr, &error_abort); + qemu_chr_fe_set_handlers(&console.fe, sim_console_can_read, sim_console_read, NULL, NULL, &console, @@ -227,7 +227,7 @@ void HELPER(simcall)(CPUXtensaState *env) len -= io_sz; if (fd < 3 && sim_console) { if (is_write && (fd == 1 || fd == 2)) { - io_done = qemu_chr_fe_write_all(&sim_console->be, + io_done = qemu_chr_fe_write_all(&sim_console->fe, buf, io_sz); regs[3] = errno_h2g(errno); } else if (!is_write && fd == 0) { @@ -241,7 +241,7 @@ void HELPER(simcall)(CPUXtensaState *env) sim_console->input.buffer + io_done, sim_console->input.offset - io_done); sim_console->input.offset -= io_done; - qemu_chr_fe_accept_input(&sim_console->be); + qemu_chr_fe_accept_input(&sim_console->fe); } else { io_done = -1; regs[3] = TARGET_EAGAIN; diff --git a/tests/qtest/am53c974-test.c b/tests/qtest/am53c974-test.c index ed3ac7db20..a3667275ac 100644 --- a/tests/qtest/am53c974-test.c +++ b/tests/qtest/am53c974-test.c @@ -109,6 +109,44 @@ static void test_cmdfifo_overflow2_ok(void) qtest_quit(s); } +/* Reported as https://issues.oss-fuzz.com/issues/439878564 */ +static void test_cmdfifo_overflow3_ok(void) +{ + QTestState *s = qtest_init( + "-device am53c974,id=scsi -device scsi-hd,drive=disk0 " + "-drive id=disk0,if=none,file=null-co://,format=raw -nodefaults"); + qtest_outl(s, 0xcf8, 0x80001010); + qtest_outl(s, 0xcfc, 0xc000); + qtest_outl(s, 0xcf8, 0x80001004); + qtest_outw(s, 0xcfc, 0x01); + qtest_outb(s, 0xc00c, 0x43); + qtest_outl(s, 0xc00b, 0x9100); + qtest_outl(s, 0xc009, 0x02000000); + qtest_outl(s, 0xc000, 0x0b); + qtest_outl(s, 0xc00b, 0x00); + qtest_outl(s, 0xc00b, 0x00); + qtest_outl(s, 0xc00b, 0xc200); + qtest_outl(s, 0xc00b, 0x1000); + qtest_outl(s, 0xc00b, 0x9000); + qtest_outb(s, 0xc008, 0x00); + qtest_outb(s, 0xc008, 0x00); + qtest_outl(s, 0xc03f, 0x0300); + qtest_outl(s, 0xc00b, 0x00); + qtest_outw(s, 0xc00b, 0x4200); + qtest_outl(s, 0xc00b, 0x00); + qtest_outw(s, 0xc00b, 0x1200); + qtest_outl(s, 0xc00b, 0x00); + qtest_outb(s, 0xc00c, 0x43); + qtest_outl(s, 0xc00b, 0x00); + qtest_outl(s, 0xc00b, 0x00); + qtest_outl(s, 0xc007, 0x00); + qtest_outl(s, 0xc007, 0x00); + qtest_outl(s, 0xc007, 0x00); + qtest_outl(s, 0xc00b, 0x1000); + qtest_outl(s, 0xc007, 0x00); + qtest_quit(s); +} + /* Reported as crash_0900379669 */ static void test_fifo_pop_buf(void) { @@ -266,6 +304,8 @@ int main(int argc, char **argv) test_cmdfifo_overflow_ok); qtest_add_func("am53c974/test_cmdfifo_overflow2_ok", test_cmdfifo_overflow2_ok); + qtest_add_func("am53c974/test_cmdfifo_overflow3_ok", + test_cmdfifo_overflow3_ok); qtest_add_func("am53c974/test_fifo_pop_buf", test_fifo_pop_buf); qtest_add_func("am53c974/test_target_selected_ok", diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 609ff24059..d2bb21d5b9 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -155,7 +155,7 @@ typedef struct TestServer { gchar *mig_path; gchar *chr_name; gchar *tmpfs; - CharBackend chr; + CharFrontend chr; int fds_num; int fds[VHOST_MEMORY_MAX_NREGIONS]; VhostUserMemory memory; @@ -180,10 +180,10 @@ struct vhost_user_ops { /* VHOST-USER commands. */ uint64_t (*get_features)(TestServer *s); - void (*set_features)(TestServer *s, CharBackend *chr, + void (*set_features)(TestServer *s, CharFrontend *chr, VhostUserMsg *msg); void (*get_protocol_features)(TestServer *s, - CharBackend *chr, VhostUserMsg *msg); + CharFrontend *chr, VhostUserMsg *msg); }; static const char *init_hugepagefs(void); @@ -331,7 +331,7 @@ static int chr_can_read(void *opaque) static void chr_read(void *opaque, const uint8_t *buf, int size) { TestServer *s = opaque; - CharBackend *chr = &s->chr; + CharFrontend *chr = &s->chr; VhostUserMsg msg; uint8_t *p = (uint8_t *) &msg; int fd = -1; @@ -1051,7 +1051,7 @@ static uint64_t vu_net_get_features(TestServer *s) return features; } -static void vu_net_set_features(TestServer *s, CharBackend *chr, +static void vu_net_set_features(TestServer *s, CharFrontend *chr, VhostUserMsg *msg) { g_assert(msg->payload.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES)); @@ -1061,7 +1061,7 @@ static void vu_net_set_features(TestServer *s, CharBackend *chr, } } -static void vu_net_get_protocol_features(TestServer *s, CharBackend *chr, +static void vu_net_get_protocol_features(TestServer *s, CharFrontend *chr, VhostUserMsg *msg) { /* send back features to qemu */ @@ -1148,7 +1148,7 @@ static uint64_t vu_gpio_get_features(TestServer *s) * that we support VHOST_USER_PROTOCOL_F_CONFIG as gpio would use it * talking to a read vhost-user daemon. */ -static void vu_gpio_get_protocol_features(TestServer *s, CharBackend *chr, +static void vu_gpio_get_protocol_features(TestServer *s, CharFrontend *chr, VhostUserMsg *msg) { /* send back features to qemu */ @@ -1191,7 +1191,7 @@ static uint64_t vu_scmi_get_features(TestServer *s) 0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES; } -static void vu_scmi_get_protocol_features(TestServer *s, CharBackend *chr, +static void vu_scmi_get_protocol_features(TestServer *s, CharFrontend *chr, VhostUserMsg *msg) { msg->flags |= VHOST_USER_REPLY_MASK; diff --git a/tests/unit/test-char.c b/tests/unit/test-char.c index e156b17329..8a98e42cad 100644 --- a/tests/unit/test-char.c +++ b/tests/unit/test-char.c @@ -107,18 +107,18 @@ static void char_console_test(void) static void char_stdio_test_subprocess(void) { Chardev *chr; - CharBackend be; + CharFrontend c; int ret; chr = qemu_chr_new("label", "stdio", NULL); g_assert_nonnull(chr); - qemu_chr_fe_init(&be, chr, &error_abort); - qemu_chr_fe_set_open(&be, true); - ret = qemu_chr_fe_write(&be, (void *)"buf", 4); + qemu_chr_fe_init(&c, chr, &error_abort); + qemu_chr_fe_set_open(&c, true); + ret = qemu_chr_fe_write(&c, (void *)"buf", 4); g_assert_cmpint(ret, ==, 4); - qemu_chr_fe_deinit(&be, true); + qemu_chr_fe_deinit(&c, true); } static void char_stdio_test(void) @@ -132,7 +132,7 @@ static void char_ringbuf_test(void) { QemuOpts *opts; Chardev *chr; - CharBackend be; + CharFrontend c; char *data; int ret; @@ -153,8 +153,8 @@ static void char_ringbuf_test(void) g_assert_nonnull(chr); qemu_opts_del(opts); - qemu_chr_fe_init(&be, chr, &error_abort); - ret = qemu_chr_fe_write(&be, (void *)"buff", 4); + qemu_chr_fe_init(&c, chr, &error_abort); + ret = qemu_chr_fe_write(&c, (void *)"buff", 4); g_assert_cmpint(ret, ==, 4); data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort); @@ -165,7 +165,7 @@ static void char_ringbuf_test(void) g_assert_cmpstr(data, ==, ""); g_free(data); - qemu_chr_fe_deinit(&be, true); + qemu_chr_fe_deinit(&c, true); /* check alias */ opts = qemu_opts_create(qemu_find_opts("chardev"), "memory-label", @@ -184,7 +184,7 @@ static void char_mux_test(void) Chardev *chr, *base; char *data; FeHandler h1 = { 0, false, 0, false, }, h2 = { 0, false, 0, false, }; - CharBackend chr_be1, chr_be2; + CharFrontend chr_fe1, chr_fe2; Error *error = NULL; /* Create mux and chardev to be immediately removed */ @@ -210,8 +210,8 @@ static void char_mux_test(void) g_assert_nonnull(chr); qemu_opts_del(opts); - qemu_chr_fe_init(&chr_be1, chr, &error_abort); - qemu_chr_fe_set_handlers(&chr_be1, + qemu_chr_fe_init(&chr_fe1, chr, &error_abort); + qemu_chr_fe_set_handlers(&chr_fe1, fe_can_read, fe_read, fe_event, @@ -219,15 +219,15 @@ static void char_mux_test(void) &h1, NULL, true); - qemu_chr_fe_init(&chr_be2, chr, &error_abort); - qemu_chr_fe_set_handlers(&chr_be2, + qemu_chr_fe_init(&chr_fe2, chr, &error_abort); + qemu_chr_fe_set_handlers(&chr_fe2, fe_can_read, fe_read, fe_event, NULL, &h2, NULL, true); - qemu_chr_fe_take_focus(&chr_be2); + qemu_chr_fe_take_focus(&chr_fe2); base = qemu_chr_find("mux-label-base"); g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0); @@ -271,8 +271,8 @@ static void char_mux_test(void) g_assert_cmpint(h2.last_event, ==, CHR_EVENT_MUX_OUT); /* open/close state and corresponding events */ - g_assert_true(qemu_chr_fe_backend_open(&chr_be1)); - g_assert_true(qemu_chr_fe_backend_open(&chr_be2)); + g_assert_true(qemu_chr_fe_backend_open(&chr_fe1)); + g_assert_true(qemu_chr_fe_backend_open(&chr_fe2)); g_assert_true(h1.is_open); g_assert_false(h1.openclose_mismatch); g_assert_true(h2.is_open); @@ -280,22 +280,22 @@ static void char_mux_test(void) h1.openclose_count = h2.openclose_count = 0; - qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL, + qemu_chr_fe_set_handlers(&chr_fe1, NULL, NULL, NULL, NULL, NULL, NULL, false); - qemu_chr_fe_set_handlers(&chr_be2, NULL, NULL, NULL, NULL, + qemu_chr_fe_set_handlers(&chr_fe2, NULL, NULL, NULL, NULL, NULL, NULL, false); g_assert_cmpint(h1.openclose_count, ==, 0); g_assert_cmpint(h2.openclose_count, ==, 0); h1.is_open = h2.is_open = false; - qemu_chr_fe_set_handlers(&chr_be1, + qemu_chr_fe_set_handlers(&chr_fe1, NULL, NULL, fe_event, NULL, &h1, NULL, false); - qemu_chr_fe_set_handlers(&chr_be2, + qemu_chr_fe_set_handlers(&chr_fe2, NULL, NULL, fe_event, @@ -314,14 +314,14 @@ static void char_mux_test(void) g_assert_cmpint(h2.openclose_count, ==, 3); g_assert_false(h2.openclose_mismatch); - qemu_chr_fe_set_handlers(&chr_be2, + qemu_chr_fe_set_handlers(&chr_fe2, fe_can_read, fe_read, fe_event, NULL, &h2, NULL, false); - qemu_chr_fe_set_handlers(&chr_be1, + qemu_chr_fe_set_handlers(&chr_fe1, fe_can_read, fe_read, fe_event, @@ -330,7 +330,7 @@ static void char_mux_test(void) NULL, false); /* remove first handler */ - qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL, + qemu_chr_fe_set_handlers(&chr_fe1, NULL, NULL, NULL, NULL, NULL, NULL, true); qemu_chr_be_write(base, (void *)"hello", 6); g_assert_cmpint(h1.read_count, ==, 0); @@ -349,13 +349,13 @@ static void char_mux_test(void) g_assert_cmpint(strlen(data), !=, 0); g_free(data); - qemu_chr_fe_deinit(&chr_be1, false); + qemu_chr_fe_deinit(&chr_fe1, false); qmp_chardev_remove("mux-label", &error); g_assert_cmpstr(error_get_pretty(error), ==, "Chardev 'mux-label' is busy"); error_free(error); - qemu_chr_fe_deinit(&chr_be2, false); + qemu_chr_fe_deinit(&chr_fe2, false); qmp_chardev_remove("mux-label", &error_abort); } @@ -366,7 +366,7 @@ static void char_hub_test(void) char *data; FeHandler h = { 0, false, 0, false, }; Error *error = NULL; - CharBackend chr_be; + CharFrontend chr_fe; int ret, i; #define RB_SIZE 128 @@ -497,8 +497,8 @@ static void char_hub_test(void) qemu_opts_del(opts); /* Attach hub to a frontend */ - qemu_chr_fe_init(&chr_be, hub, &error_abort); - qemu_chr_fe_set_handlers(&chr_be, + qemu_chr_fe_init(&chr_fe, hub, &error_abort); + qemu_chr_fe_set_handlers(&chr_fe, fe_can_read, fe_read, fe_event, @@ -507,7 +507,7 @@ static void char_hub_test(void) NULL, true); /* Fails second time */ - qemu_chr_fe_init(&chr_be, hub, &error); + qemu_chr_fe_init(&chr_fe, hub, &error); g_assert_cmpstr(error_get_pretty(error), ==, "chardev 'hub0' is already in use"); error_free(error); error = NULL; @@ -531,7 +531,7 @@ static void char_hub_test(void) h.read_count = 0; /* Write to frontend, chr_be */ - ret = qemu_chr_fe_write(&chr_be, (void *)"heyhey", 6); + ret = qemu_chr_fe_write(&chr_fe, (void *)"heyhey", 6); g_assert_cmpint(ret, ==, 6); data = qmp_ringbuf_read("chr1", RB_SIZE, false, 0, &error_abort); @@ -557,7 +557,7 @@ static void char_hub_test(void) error = NULL; /* Finalize frontend */ - qemu_chr_fe_deinit(&chr_be, false); + qemu_chr_fe_deinit(&chr_fe, false); /* Finalize hub0 */ qmp_chardev_remove("hub0", &error_abort); @@ -632,8 +632,8 @@ static void char_hub_test(void) qemu_opts_del(opts); /* Attach hub to a frontend */ - qemu_chr_fe_init(&chr_be, hub, &error_abort); - qemu_chr_fe_set_handlers(&chr_be, + qemu_chr_fe_init(&chr_fe, hub, &error_abort); + qemu_chr_fe_set_handlers(&chr_fe, fe_can_read, fe_read, fe_event, @@ -642,7 +642,7 @@ static void char_hub_test(void) NULL, true); /* Write to frontend, chr_be */ - ret = qemu_chr_fe_write(&chr_be, (void *)"thisis", 6); + ret = qemu_chr_fe_write(&chr_fe, (void *)"thisis", 6); g_assert_cmpint(ret, ==, 6); data = qmp_ringbuf_read("chr1", RB_SIZE, false, 0, &error_abort); @@ -663,7 +663,7 @@ static void char_hub_test(void) close(fd); /* Add watch. 0 indicates no watches if nothing to wait for */ - ret = qemu_chr_fe_add_watch(&chr_be, G_IO_OUT | G_IO_HUP, + ret = qemu_chr_fe_add_watch(&chr_fe, G_IO_OUT | G_IO_HUP, NULL, NULL); g_assert_cmpint(ret, ==, 0); @@ -672,14 +672,14 @@ static void char_hub_test(void) * power of two to fit nicely the whole pipe buffer. */ len = 0; - while ((ret = qemu_chr_fe_write(&chr_be, (void *)"thisisit", 8)) + while ((ret = qemu_chr_fe_write(&chr_fe, (void *)"thisisit", 8)) != -1) { len += ret; } g_assert_cmpint(errno, ==, EAGAIN); /* Further all writes should cause EAGAIN */ - ret = qemu_chr_fe_write(&chr_be, (void *)"b", 1); + ret = qemu_chr_fe_write(&chr_fe, (void *)"b", 1); g_assert_cmpint(ret, ==, -1); g_assert_cmpint(errno, ==, EAGAIN); @@ -687,7 +687,7 @@ static void char_hub_test(void) * Add watch. Non 0 indicates we have a blocked chardev, which * can wakes us up when write is possible. */ - ret = qemu_chr_fe_add_watch(&chr_be, G_IO_OUT | G_IO_HUP, + ret = qemu_chr_fe_add_watch(&chr_fe, G_IO_OUT | G_IO_HUP, NULL, NULL); g_assert_cmpint(ret, !=, 0); g_source_remove(ret); @@ -712,10 +712,10 @@ static void char_hub_test(void) * was already consumed and drained by the ring buffers, but * pipe have not recieved that yet. */ - ret = qemu_chr_fe_write(&chr_be, (void *)"thisisit", 8); + ret = qemu_chr_fe_write(&chr_fe, (void *)"thisisit", 8); g_assert_cmpint(ret, ==, 8); - ret = qemu_chr_fe_write(&chr_be, (void *)"streamisrestored", 16); + ret = qemu_chr_fe_write(&chr_fe, (void *)"streamisrestored", 16); g_assert_cmpint(ret, ==, 16); data = qmp_ringbuf_read("chr1", RB_SIZE, false, 0, &error_abort); @@ -744,7 +744,7 @@ static void char_hub_test(void) g_free(pipe); /* Finalize frontend */ - qemu_chr_fe_deinit(&chr_be, false); + qemu_chr_fe_deinit(&chr_fe, false); /* Finalize hub0 */ qmp_chardev_remove("hub0", &error_abort); @@ -803,10 +803,10 @@ static void websock_client_read(void *opaque, const uint8_t *buf, int size) Chardev *chr_client = opaque; if (websock_check_http_headers((char *) buf, size)) { - qemu_chr_fe_write(chr_client->be, ping, sizeof(ping)); + qemu_chr_fe_write(chr_client->fe, ping, sizeof(ping)); } else if (buf[0] == 0x8a && buf[1] == 0x05) { g_assert(strncmp((char *) buf + 2, "hello", 5) == 0); - qemu_chr_fe_write(chr_client->be, binary, sizeof(binary)); + qemu_chr_fe_write(chr_client->fe, binary, sizeof(binary)); } else { g_assert(buf[0] == 0x88 && buf[1] == 0x16); g_assert(strncmp((char *) buf + 4, "peer requested close", 10) == 0); @@ -828,8 +828,8 @@ static void char_websock_test(void) const char *port; char *tmp; char *handshake_port; - CharBackend be; - CharBackend client_be; + CharFrontend fe; + CharFrontend client_fe; Chardev *chr_client; Chardev *chr = qemu_chr_new("server", "websocket:127.0.0.1:0,server=on,wait=off", NULL); @@ -852,13 +852,13 @@ static void char_websock_test(void) handshake_port = g_strdup_printf(handshake, port, port); qobject_unref(qdict); - qemu_chr_fe_init(&be, chr, &error_abort); - qemu_chr_fe_set_handlers(&be, websock_server_can_read, websock_server_read, + qemu_chr_fe_init(&fe, chr, &error_abort); + qemu_chr_fe_set_handlers(&fe, websock_server_can_read, websock_server_read, NULL, NULL, chr, NULL, true); chr_client = qemu_chr_new("client", tmp, NULL); - qemu_chr_fe_init(&client_be, chr_client, &error_abort); - qemu_chr_fe_set_handlers(&client_be, websock_client_can_read, + qemu_chr_fe_init(&client_fe, chr_client, &error_abort); + qemu_chr_fe_set_handlers(&client_fe, websock_client_can_read, websock_client_read, NULL, NULL, chr_client, NULL, true); g_free(tmp); @@ -887,7 +887,7 @@ static void char_pipe_test(void) gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL); gchar *tmp, *in, *out, *pipe = g_build_filename(tmp_path, "pipe", NULL); Chardev *chr; - CharBackend be; + CharFrontend c; int ret, fd; char buf[10]; FeHandler fe = { 0, }; @@ -906,9 +906,9 @@ static void char_pipe_test(void) g_assert_nonnull(chr); g_free(tmp); - qemu_chr_fe_init(&be, chr, &error_abort); + qemu_chr_fe_init(&c, chr, &error_abort); - ret = qemu_chr_fe_write(&be, (void *)"pipe-out", 9); + ret = qemu_chr_fe_write(&c, (void *)"pipe-out", 9); g_assert_cmpint(ret, ==, 9); fd = open(out, O_RDWR); @@ -922,7 +922,7 @@ static void char_pipe_test(void) g_assert_cmpint(ret, ==, 8); close(fd); - qemu_chr_fe_set_handlers(&be, + qemu_chr_fe_set_handlers(&c, fe_can_read, fe_read, fe_event, @@ -935,7 +935,7 @@ static void char_pipe_test(void) g_assert_cmpint(fe.read_count, ==, 8); g_assert_cmpstr(fe.read_buf, ==, "pipe-in"); - qemu_chr_fe_deinit(&be, true); + qemu_chr_fe_deinit(&c, true); g_assert(g_unlink(in) == 0); g_assert(g_unlink(out) == 0); @@ -951,8 +951,8 @@ typedef struct SocketIdleData { GMainLoop *loop; Chardev *chr; bool conn_expected; - CharBackend *be; - CharBackend *client_be; + CharFrontend *fe; + CharFrontend *client_fe; } SocketIdleData; @@ -993,7 +993,7 @@ static void char_udp_test_internal(Chardev *reuse_chr, int sock) struct sockaddr_in other; SocketIdleData d = { 0, }; Chardev *chr; - CharBackend stack_be, *be = &stack_be; + CharFrontend stack_fe, *fe = &stack_fe; socklen_t alen = sizeof(other); int ret; char buf[10]; @@ -1001,7 +1001,7 @@ static void char_udp_test_internal(Chardev *reuse_chr, int sock) if (reuse_chr) { chr = reuse_chr; - be = chr->be; + fe = chr->fe; } else { int port; sock = make_udp_socket(&port); @@ -1009,11 +1009,11 @@ static void char_udp_test_internal(Chardev *reuse_chr, int sock) chr = qemu_chr_new("client", tmp, NULL); g_assert_nonnull(chr); - qemu_chr_fe_init(be, chr, &error_abort); + qemu_chr_fe_init(fe, chr, &error_abort); } d.chr = chr; - qemu_chr_fe_set_handlers(be, socket_can_read_hello, socket_read_hello, + qemu_chr_fe_set_handlers(fe, socket_can_read_hello, socket_read_hello, NULL, NULL, &d, NULL, true); ret = qemu_chr_write_all(chr, (uint8_t *)"hello", 5); g_assert_cmpint(ret, ==, 5); @@ -1028,7 +1028,7 @@ static void char_udp_test_internal(Chardev *reuse_chr, int sock) if (!reuse_chr) { close(sock); - qemu_chr_fe_deinit(be, true); + qemu_chr_fe_deinit(fe, true); } g_free(tmp); } @@ -1042,7 +1042,7 @@ static void char_udp_test(void) typedef struct { int event; bool got_pong; - CharBackend *be; + CharFrontend *fe; } CharSocketTestData; @@ -1063,13 +1063,13 @@ char_socket_event_with_error(void *opaque, QEMUChrEvent event) { static bool first_error; CharSocketTestData *data = opaque; - CharBackend *be = data->be; + CharFrontend *fe = data->fe; data->event = event; switch (event) { case CHR_EVENT_OPENED: if (!first_error) { first_error = true; - qemu_chr_fe_disconnect(be); + qemu_chr_fe_disconnect(fe); } return; case CHR_EVENT_CLOSED: @@ -1185,7 +1185,7 @@ static void char_socket_server_test(gconstpointer opaque) { const CharSocketServerTestConfig *config = opaque; Chardev *chr; - CharBackend be = {0}; + CharFrontend c = {0}; CharSocketTestData data = {0}; QObject *qaddr; SocketAddress *addr; @@ -1224,12 +1224,12 @@ static void char_socket_server_test(gconstpointer opaque) visit_free(v); qobject_unref(qaddr); - qemu_chr_fe_init(&be, chr, &error_abort); + qemu_chr_fe_init(&c, chr, &error_abort); reconnect: data.event = -1; - data.be = &be; - qemu_chr_fe_set_handlers(&be, NULL, NULL, + data.fe = &c; + qemu_chr_fe_set_handlers(&c, NULL, NULL, char_socket_event, NULL, &data, NULL, true); g_assert(data.event == -1); @@ -1260,13 +1260,13 @@ static void char_socket_server_test(gconstpointer opaque) data.event = -1; /* Send a greeting to the client */ - ret = qemu_chr_fe_write_all(&be, (const uint8_t *)SOCKET_PING, + ret = qemu_chr_fe_write_all(&c, (const uint8_t *)SOCKET_PING, sizeof(SOCKET_PING)); g_assert_cmpint(ret, ==, sizeof(SOCKET_PING)); g_assert(data.event == -1); /* Setup a callback to receive the reply to our greeting */ - qemu_chr_fe_set_handlers(&be, char_socket_can_read, + qemu_chr_fe_set_handlers(&c, char_socket_can_read, char_socket_read, char_socket_event, NULL, &data, NULL, true); @@ -1375,7 +1375,7 @@ static void char_socket_client_test(gconstpointer opaque) QIOChannelSocket *ioc; char *optstr; Chardev *chr; - CharBackend be = {0}; + CharFrontend c = {0}; CharSocketTestData data = {0}; SocketAddress *addr; QemuThread thread; @@ -1431,12 +1431,12 @@ static void char_socket_client_test(gconstpointer opaque) &error_abort)); } - qemu_chr_fe_init(&be, chr, &error_abort); + qemu_chr_fe_init(&c, chr, &error_abort); reconnect: data.event = -1; - data.be = &be; - qemu_chr_fe_set_handlers(&be, NULL, NULL, + data.fe = &c; + qemu_chr_fe_set_handlers(&c, NULL, NULL, event_cb, NULL, &data, NULL, true); if (config->reconnect) { @@ -1467,13 +1467,13 @@ static void char_socket_client_test(gconstpointer opaque) g_assert(object_property_get_bool(OBJECT(chr), "connected", &error_abort)); /* Send a greeting to the server */ - ret = qemu_chr_fe_write_all(&be, (const uint8_t *)SOCKET_PING, + ret = qemu_chr_fe_write_all(&c, (const uint8_t *)SOCKET_PING, sizeof(SOCKET_PING)); g_assert_cmpint(ret, ==, sizeof(SOCKET_PING)); g_assert(data.event == -1); /* Setup a callback to receive the reply to our greeting */ - qemu_chr_fe_set_handlers(&be, char_socket_can_read, + qemu_chr_fe_set_handlers(&c, char_socket_can_read, char_socket_read, event_cb, NULL, &data, NULL, true); @@ -1521,7 +1521,7 @@ static void char_socket_server_two_clients_test(gconstpointer opaque) { SocketAddress *incoming_addr = (gpointer) opaque; Chardev *chr; - CharBackend be = {0}; + CharFrontend c = {0}; QObject *qaddr; SocketAddress *addr; Visitor *v; @@ -1558,9 +1558,9 @@ static void char_socket_server_two_clients_test(gconstpointer opaque) visit_free(v); qobject_unref(qaddr); - qemu_chr_fe_init(&be, chr, &error_abort); + qemu_chr_fe_init(&c, chr, &error_abort); - qemu_chr_fe_set_handlers(&be, char_socket_can_read, char_socket_discard_read, + qemu_chr_fe_set_handlers(&c, char_socket_can_read, char_socket_discard_read, count_closed_event, NULL, &closed, NULL, true); @@ -1570,7 +1570,7 @@ static void char_socket_server_two_clients_test(gconstpointer opaque) /* switch the chardev to another context */ GMainContext *ctx = g_main_context_new(); - qemu_chr_fe_set_handlers(&be, char_socket_can_read, char_socket_discard_read, + qemu_chr_fe_set_handlers(&c, char_socket_can_read, char_socket_discard_read, count_closed_event, NULL, &closed, ctx, true); @@ -1649,7 +1649,7 @@ static void char_parallel_test(void) static void char_file_fifo_test(void) { Chardev *chr; - CharBackend be; + CharFrontend c; char *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL); char *fifo = g_build_filename(tmp_path, "fifo", NULL); char *out = g_build_filename(tmp_path, "out", NULL); @@ -1671,8 +1671,8 @@ static void char_file_fifo_test(void) chr = qemu_chardev_new("label-file", TYPE_CHARDEV_FILE, &backend, NULL, &error_abort); - qemu_chr_fe_init(&be, chr, &error_abort); - qemu_chr_fe_set_handlers(&be, + qemu_chr_fe_init(&c, chr, &error_abort); + qemu_chr_fe_set_handlers(&c, fe_can_read, fe_read, fe_event, @@ -1692,7 +1692,7 @@ static void char_file_fifo_test(void) g_assert_cmpint(fe.read_count, ==, 8); g_assert_cmpstr(fe.read_buf, ==, "fifo-in"); - qemu_chr_fe_deinit(&be, true); + qemu_chr_fe_deinit(&c, true); g_unlink(fifo); g_free(fifo); @@ -1752,7 +1752,7 @@ static void char_null_test(void) { Error *err = NULL; Chardev *chr; - CharBackend be; + CharFrontend c; int ret; chr = qemu_chr_find("label-null"); @@ -1768,27 +1768,27 @@ static void char_null_test(void) QEMU_CHAR_FEATURE_RECONNECTABLE) == false); /* check max avail */ - qemu_chr_fe_init(&be, chr, &error_abort); - qemu_chr_fe_init(&be, chr, &err); + qemu_chr_fe_init(&c, chr, &error_abort); + qemu_chr_fe_init(&c, chr, &err); error_free_or_abort(&err); /* deinit & reinit */ - qemu_chr_fe_deinit(&be, false); - qemu_chr_fe_init(&be, chr, &error_abort); + qemu_chr_fe_deinit(&c, false); + qemu_chr_fe_init(&c, chr, &error_abort); - qemu_chr_fe_set_open(&be, true); + qemu_chr_fe_set_open(&c, true); - qemu_chr_fe_set_handlers(&be, + qemu_chr_fe_set_handlers(&c, fe_can_read, fe_read, fe_event, NULL, NULL, NULL, true); - ret = qemu_chr_fe_write(&be, (void *)"buf", 4); + ret = qemu_chr_fe_write(&c, (void *)"buf", 4); g_assert_cmpint(ret, ==, 4); - qemu_chr_fe_deinit(&be, true); + qemu_chr_fe_deinit(&c, true); } static void char_invalid_test(void) @@ -1814,7 +1814,7 @@ static void char_hotswap_test(void) { char *chr_args; Chardev *chr; - CharBackend be; + CharFrontend c; gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL); char *filename = g_build_filename(tmp_path, "file", NULL); @@ -1830,32 +1830,32 @@ static void char_hotswap_test(void) chr_args = g_strdup_printf("udp:127.0.0.1:%d", port); chr = qemu_chr_new("chardev", chr_args, NULL); - qemu_chr_fe_init(&be, chr, &error_abort); + qemu_chr_fe_init(&c, chr, &error_abort); /* check that chardev operates correctly */ char_udp_test_internal(chr, sock); /* set the handler that denies the hotswap */ - qemu_chr_fe_set_handlers(&be, NULL, NULL, + qemu_chr_fe_set_handlers(&c, NULL, NULL, NULL, chardev_change_denied, NULL, NULL, true); /* now, change is denied and has to keep the old backend operating */ ret = qmp_chardev_change("chardev", &backend, NULL); g_assert(!ret); - g_assert(be.chr == chr); + g_assert(c.chr == chr); char_udp_test_internal(chr, sock); /* now allow the change */ - qemu_chr_fe_set_handlers(&be, NULL, NULL, + qemu_chr_fe_set_handlers(&c, NULL, NULL, NULL, chardev_change, NULL, NULL, true); /* has to succeed now */ ret = qmp_chardev_change("chardev", &backend, &error_abort); - g_assert(be.chr != chr); + g_assert(c.chr != chr); close(sock); - chr = be.chr; + chr = c.chr; /* run the file chardev test */ char_file_test_internal(chr, filename); diff --git a/tests/unit/test-yank.c b/tests/unit/test-yank.c index 4acfb2f3f6..9fc86a2128 100644 --- a/tests/unit/test-yank.c +++ b/tests/unit/test-yank.c @@ -65,7 +65,7 @@ static void char_change_test(gconstpointer opaque) CharChangeTestConfig *conf = (gpointer) opaque; SocketAddress *addr; Chardev *chr; - CharBackend be; + CharFrontend fe; ChardevReturn *ret; QIOChannelSocket *ioc; QemuThread thread; @@ -144,9 +144,9 @@ static void char_change_test(gconstpointer opaque) qemu_thread_join(&thread); } - qemu_chr_fe_init(&be, chr, &error_abort); + qemu_chr_fe_init(&fe, chr, &error_abort); /* allow chardev-change */ - qemu_chr_fe_set_handlers(&be, NULL, NULL, + qemu_chr_fe_set_handlers(&fe, NULL, NULL, NULL, chardev_change, NULL, NULL, true); if (conf->fail) { @@ -154,7 +154,7 @@ static void char_change_test(gconstpointer opaque) ret = qmp_chardev_change("chardev", &fail_backend[conf->new_yank], NULL); g_assert_null(ret); - g_assert(be.chr == chr); + g_assert(fe.chr == chr); g_assert(is_yank_instance_registered() == conf->old_yank); g_unsetenv("QTEST_SILENT_ERRORS"); } else { @@ -168,11 +168,11 @@ static void char_change_test(gconstpointer opaque) qemu_thread_join(&thread); } g_assert_nonnull(ret); - g_assert(be.chr != chr); + g_assert(fe.chr != chr); g_assert(is_yank_instance_registered() == conf->new_yank); } - object_unparent(OBJECT(be.chr)); + object_unparent(OBJECT(fe.chr)); object_unref(OBJECT(ioc)); qapi_free_ChardevReturn(ret); qapi_free_SocketAddress(addr); diff --git a/util/rcu.c b/util/rcu.c index b703c86f15..acac9446ea 100644 --- a/util/rcu.c +++ b/util/rcu.c @@ -43,10 +43,14 @@ #define RCU_GP_LOCKED (1UL << 0) #define RCU_GP_CTR (1UL << 1) + +#define RCU_CALL_MIN_SIZE 30 + unsigned long rcu_gp_ctr = RCU_GP_LOCKED; QemuEvent rcu_gp_event; static int in_drain_call_rcu; +static int rcu_call_count; static QemuMutex rcu_registry_lock; static QemuMutex rcu_sync_lock; @@ -76,15 +80,29 @@ static void wait_for_readers(void) { ThreadList qsreaders = QLIST_HEAD_INITIALIZER(qsreaders); struct rcu_reader_data *index, *tmp; + int sleeps = 0; + bool forced = false; for (;;) { - /* We want to be notified of changes made to rcu_gp_ongoing - * while we walk the list. + /* + * Force the grace period to end and wait for it if any of the + * following heuristical conditions are satisfied: + * - A decent number of callbacks piled up. + * - It timed out. + * - It is in a drain_call_rcu() call. + * + * Otherwise, periodically poll the grace period, hoping it ends + * promptly. */ - qemu_event_reset(&rcu_gp_event); + if (!forced && + (qatomic_read(&rcu_call_count) >= RCU_CALL_MIN_SIZE || + sleeps >= 5 || qatomic_read(&in_drain_call_rcu))) { + forced = true; - QLIST_FOREACH(index, ®istry, node) { - qatomic_set(&index->waiting, true); + QLIST_FOREACH(index, ®istry, node) { + notifier_list_notify(&index->force_rcu, NULL); + qatomic_set(&index->waiting, true); + } } /* Here, order the stores to index->waiting before the loads of @@ -106,8 +124,6 @@ static void wait_for_readers(void) * get some extra futex wakeups. */ qatomic_set(&index->waiting, false); - } else if (qatomic_read(&in_drain_call_rcu)) { - notifier_list_notify(&index->force_rcu, NULL); } } @@ -115,7 +131,8 @@ static void wait_for_readers(void) break; } - /* Wait for one thread to report a quiescent state and try again. + /* + * Sleep for a while and try again. * Release rcu_registry_lock, so rcu_(un)register_thread() doesn't * wait too much time. * @@ -133,7 +150,20 @@ static void wait_for_readers(void) * rcu_registry_lock is released. */ qemu_mutex_unlock(&rcu_registry_lock); - qemu_event_wait(&rcu_gp_event); + + if (forced) { + qemu_event_wait(&rcu_gp_event); + + /* + * We want to be notified of changes made to rcu_gp_ongoing + * while we walk the list. + */ + qemu_event_reset(&rcu_gp_event); + } else { + g_usleep(10000); + sleeps++; + } + qemu_mutex_lock(&rcu_registry_lock); } @@ -173,15 +203,11 @@ void synchronize_rcu(void) } } - -#define RCU_CALL_MIN_SIZE 30 - /* Multi-producer, single-consumer queue based on urcu/static/wfqueue.h * from liburcu. Note that head is only used by the consumer. */ static struct rcu_head dummy; static struct rcu_head *head = &dummy, **tail = &dummy.next; -static int rcu_call_count; static QemuEvent rcu_call_ready_event; static void enqueue(struct rcu_head *node) @@ -259,30 +285,27 @@ static void *call_rcu_thread(void *opaque) rcu_register_thread(); for (;;) { - int tries = 0; - int n = qatomic_read(&rcu_call_count); + int n; - /* Heuristically wait for a decent number of callbacks to pile up. + /* * Fetch rcu_call_count now, we only must process elements that were * added before synchronize_rcu() starts. */ - while (n == 0 || (n < RCU_CALL_MIN_SIZE && ++tries <= 5)) { - g_usleep(10000); - if (n == 0) { - qemu_event_reset(&rcu_call_ready_event); - n = qatomic_read(&rcu_call_count); - if (n == 0) { -#if defined(CONFIG_MALLOC_TRIM) - malloc_trim(4 * 1024 * 1024); -#endif - qemu_event_wait(&rcu_call_ready_event); - } - } + for (;;) { + qemu_event_reset(&rcu_call_ready_event); n = qatomic_read(&rcu_call_count); + if (n) { + break; + } + +#if defined(CONFIG_MALLOC_TRIM) + malloc_trim(4 * 1024 * 1024); +#endif + qemu_event_wait(&rcu_call_ready_event); } - qatomic_sub(&rcu_call_count, n); synchronize_rcu(); + qatomic_sub(&rcu_call_count, n); bql_lock(); while (n > 0) { node = try_dequeue();