From ddece4657627026a4c853faa8f37029097144e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 6 Oct 2021 14:18:09 +0400 Subject: [PATCH 001/730] ui/vdagent: add CHECK_SPICE_PROTOCOL_VERSION MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- meson.build | 5 +++++ ui/vdagent.c | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/meson.build b/meson.build index f45ecf31bd..1c70839bbf 100644 --- a/meson.build +++ b/meson.build @@ -1497,6 +1497,11 @@ config_host_data.set('CONFIG_ZSTD', zstd.found()) config_host_data.set('CONFIG_FUSE', fuse.found()) config_host_data.set('CONFIG_FUSE_LSEEK', fuse_lseek.found()) config_host_data.set('CONFIG_SPICE_PROTOCOL', spice_protocol.found()) +if spice_protocol.found() +config_host_data.set('CONFIG_SPICE_PROTOCOL_MAJOR', spice_protocol.version().split('.')[0]) +config_host_data.set('CONFIG_SPICE_PROTOCOL_MINOR', spice_protocol.version().split('.')[1]) +config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().split('.')[2]) +endif config_host_data.set('CONFIG_SPICE', spice.found()) config_host_data.set('CONFIG_X11', x11.found()) config_host_data.set('CONFIG_CFI', get_option('cfi')) diff --git a/ui/vdagent.c b/ui/vdagent.c index 19e8fbfc96..1f8fc77ee8 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -17,6 +17,14 @@ #include "spice/vd_agent.h" +#define CHECK_SPICE_PROTOCOL_VERSION(major, minor, micro) \ + (CONFIG_SPICE_PROTOCOL_MAJOR > (major) || \ + (CONFIG_SPICE_PROTOCOL_MAJOR == (major) && \ + CONFIG_SPICE_PROTOCOL_MINOR > (minor)) || \ + (CONFIG_SPICE_PROTOCOL_MAJOR == (major) && \ + CONFIG_SPICE_PROTOCOL_MINOR == (minor) && \ + CONFIG_SPICE_PROTOCOL_MICRO >= (micro))) + #define VDAGENT_BUFFER_LIMIT (1 * MiB) #define VDAGENT_MOUSE_DEFAULT true #define VDAGENT_CLIPBOARD_DEFAULT false From 59127452883afe3d603e90824bb33ac57b4dbee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 6 Oct 2021 14:25:44 +0400 Subject: [PATCH 002/730] ui/vdagent: replace #if 0 with protocol version check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- ui/vdagent.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ui/vdagent.c b/ui/vdagent.c index 1f8fc77ee8..64e0017001 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -87,8 +87,10 @@ static const char *cap_name[] = { [VD_AGENT_CAP_MONITORS_CONFIG_POSITION] = "monitors-config-position", [VD_AGENT_CAP_FILE_XFER_DISABLED] = "file-xfer-disabled", [VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS] = "file-xfer-detailed-errors", -#if 0 +#if CHECK_SPICE_PROTOCOL_VERSION(0, 14, 0) [VD_AGENT_CAP_GRAPHICS_DEVICE_INFO] = "graphics-device-info", +#endif +#if CHECK_SPICE_PROTOCOL_VERSION(0, 14, 1) [VD_AGENT_CAP_CLIPBOARD_NO_RELEASE_ON_REGRAB] = "clipboard-no-release-on-regrab", [VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL] = "clipboard-grab-serial", #endif @@ -110,7 +112,7 @@ static const char *msg_name[] = { [VD_AGENT_CLIENT_DISCONNECTED] = "client-disconnected", [VD_AGENT_MAX_CLIPBOARD] = "max-clipboard", [VD_AGENT_AUDIO_VOLUME_SYNC] = "audio-volume-sync", -#if 0 +#if CHECK_SPICE_PROTOCOL_VERSION(0, 14, 0) [VD_AGENT_GRAPHICS_DEVICE_INFO] = "graphics-device-info", #endif }; @@ -128,7 +130,7 @@ static const char *type_name[] = { [VD_AGENT_CLIPBOARD_IMAGE_BMP] = "bmp", [VD_AGENT_CLIPBOARD_IMAGE_TIFF] = "tiff", [VD_AGENT_CLIPBOARD_IMAGE_JPG] = "jpg", -#if 0 +#if CHECK_SPICE_PROTOCOL_VERSION(0, 14, 3) [VD_AGENT_CLIPBOARD_FILE_LIST] = "files", #endif }; From 1b17f1e9f962f5ae9cd559d7f23718ceed71b813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 19 Jul 2021 19:42:15 +0400 Subject: [PATCH 003/730] ui: generalize clipboard notifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a QemuClipboardNotify union type for extendable clipboard events. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- include/ui/clipboard.h | 32 ++++++++++++++++++++++++++++++-- ui/clipboard.c | 12 ++++++++---- ui/cocoa.m | 17 +++++++++++++---- ui/gtk-clipboard.c | 20 ++++++++++++++++---- ui/vdagent.c | 27 ++++++++++++++++++--------- ui/vnc-clipboard.c | 20 +++++++++++++++----- ui/vnc.c | 2 +- 7 files changed, 101 insertions(+), 29 deletions(-) diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h index 6298986b15..d82cf31481 100644 --- a/include/ui/clipboard.h +++ b/include/ui/clipboard.h @@ -20,8 +20,10 @@ */ typedef enum QemuClipboardType QemuClipboardType; +typedef enum QemuClipboardNotifyType QemuClipboardNotifyType; typedef enum QemuClipboardSelection QemuClipboardSelection; typedef struct QemuClipboardPeer QemuClipboardPeer; +typedef struct QemuClipboardNotify QemuClipboardNotify; typedef struct QemuClipboardInfo QemuClipboardInfo; /** @@ -55,18 +57,44 @@ enum QemuClipboardSelection { * struct QemuClipboardPeer * * @name: peer name. - * @update: notifier for clipboard updates. + * @notifier: notifier for clipboard updates. * @request: callback for clipboard data requests. * * Clipboard peer description. */ struct QemuClipboardPeer { const char *name; - Notifier update; + Notifier notifier; void (*request)(QemuClipboardInfo *info, QemuClipboardType type); }; +/** + * enum QemuClipboardNotifyType + * + * @QEMU_CLIPBOARD_UPDATE_INFO: clipboard info update + * + * Clipboard notify type. + */ +enum QemuClipboardNotifyType { + QEMU_CLIPBOARD_UPDATE_INFO, +}; + +/** + * struct QemuClipboardNotify + * + * @type: the type of event. + * @info: a QemuClipboardInfo event. + * + * Clipboard notify data. + */ +struct QemuClipboardNotify { + QemuClipboardNotifyType type; + union { + QemuClipboardInfo *info; + }; +}; + /** * struct QemuClipboardInfo * diff --git a/ui/clipboard.c b/ui/clipboard.c index d7b008d62a..743b39edf4 100644 --- a/ui/clipboard.c +++ b/ui/clipboard.c @@ -8,7 +8,7 @@ static QemuClipboardInfo *cbinfo[QEMU_CLIPBOARD_SELECTION__COUNT]; void qemu_clipboard_peer_register(QemuClipboardPeer *peer) { - notifier_list_add(&clipboard_notifiers, &peer->update); + notifier_list_add(&clipboard_notifiers, &peer->notifier); } void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer) @@ -18,8 +18,7 @@ void qemu_clipboard_peer_unregister(QemuClipboardPeer *peer) for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) { qemu_clipboard_peer_release(peer, i); } - - notifier_remove(&peer->update); + notifier_remove(&peer->notifier); } bool qemu_clipboard_peer_owns(QemuClipboardPeer *peer, @@ -44,10 +43,15 @@ void qemu_clipboard_peer_release(QemuClipboardPeer *peer, void qemu_clipboard_update(QemuClipboardInfo *info) { + QemuClipboardNotify notify = { + .type = QEMU_CLIPBOARD_UPDATE_INFO, + .info = info, + }; g_autoptr(QemuClipboardInfo) old = NULL; + assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT); - notifier_list_notify(&clipboard_notifiers, info); + notifier_list_notify(&clipboard_notifiers, ¬ify); old = cbinfo[info->selection]; cbinfo[info->selection] = qemu_clipboard_info_ref(info); diff --git a/ui/cocoa.m b/ui/cocoa.m index 68a6302184..6640a2e80e 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -1808,14 +1808,12 @@ static void cocoa_clipboard_request(QemuClipboardInfo *info, static QemuClipboardPeer cbpeer = { .name = "cocoa", - .update = { .notify = cocoa_clipboard_notify }, + .notifier = { .notify = cocoa_clipboard_notify }, .request = cocoa_clipboard_request }; -static void cocoa_clipboard_notify(Notifier *notifier, void *data) +static void cocoa_clipboard_update_info(QemuClipboardInfo *info) { - QemuClipboardInfo *info = data; - if (info->owner == &cbpeer || info->selection != QEMU_CLIPBOARD_SELECTION_CLIPBOARD) { return; } @@ -1831,6 +1829,17 @@ static void cocoa_clipboard_notify(Notifier *notifier, void *data) qemu_event_set(&cbevent); } +static void cocoa_clipboard_notify(Notifier *notifier, void *data) +{ + QemuClipboardNotify *notify = data; + + switch (notify->type) { + case QEMU_CLIPBOARD_UPDATE_INFO: + cocoa_clipboard_update_info(notify->info); + return; + } +} + static void cocoa_clipboard_request(QemuClipboardInfo *info, QemuClipboardType type) { diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c index 35b7a2c228..44ff810234 100644 --- a/ui/gtk-clipboard.c +++ b/ui/gtk-clipboard.c @@ -74,10 +74,9 @@ static void gd_clipboard_clear(GtkClipboard *clipboard, gd->cbowner[s] = false; } -static void gd_clipboard_notify(Notifier *notifier, void *data) +static void gd_clipboard_update_info(GtkDisplayState *gd, + QemuClipboardInfo *info) { - GtkDisplayState *gd = container_of(notifier, GtkDisplayState, cbpeer.update); - QemuClipboardInfo *info = data; QemuClipboardSelection s = info->selection; bool self_update = info->owner == &gd->cbpeer; @@ -118,6 +117,19 @@ static void gd_clipboard_notify(Notifier *notifier, void *data) */ } +static void gd_clipboard_notify(Notifier *notifier, void *data) +{ + GtkDisplayState *gd = + container_of(notifier, GtkDisplayState, cbpeer.notifier); + QemuClipboardNotify *notify = data; + + switch (notify->type) { + case QEMU_CLIPBOARD_UPDATE_INFO: + gd_clipboard_update_info(gd, notify->info); + return; + } +} + static void gd_clipboard_request(QemuClipboardInfo *info, QemuClipboardType type) { @@ -172,7 +184,7 @@ static void gd_owner_change(GtkClipboard *clipboard, void gd_clipboard_init(GtkDisplayState *gd) { gd->cbpeer.name = "gtk"; - gd->cbpeer.update.notify = gd_clipboard_notify; + gd->cbpeer.notifier.notify = gd_clipboard_notify; gd->cbpeer.request = gd_clipboard_request; qemu_clipboard_peer_register(&gd->cbpeer); diff --git a/ui/vdagent.c b/ui/vdagent.c index 64e0017001..de827aad27 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -417,10 +417,9 @@ static void vdagent_send_empty_clipboard_data(VDAgentChardev *vd, vdagent_send_clipboard_data(vd, info, type); } -static void vdagent_clipboard_notify(Notifier *notifier, void *data) +static void vdagent_clipboard_update_info(VDAgentChardev *vd, + QemuClipboardInfo *info) { - VDAgentChardev *vd = container_of(notifier, VDAgentChardev, cbpeer.update); - QemuClipboardInfo *info = data; QemuClipboardSelection s = info->selection; QemuClipboardType type; bool self_update = info->owner == &vd->cbpeer; @@ -449,6 +448,19 @@ static void vdagent_clipboard_notify(Notifier *notifier, void *data) } } +static void vdagent_clipboard_notify(Notifier *notifier, void *data) +{ + VDAgentChardev *vd = + container_of(notifier, VDAgentChardev, cbpeer.notifier); + QemuClipboardNotify *notify = data; + + switch (notify->type) { + case QEMU_CLIPBOARD_UPDATE_INFO: + vdagent_clipboard_update_info(vd, notify->info); + return; + } +} + static void vdagent_clipboard_request(QemuClipboardInfo *info, QemuClipboardType qtype) { @@ -658,9 +670,9 @@ static void vdagent_chr_recv_caps(VDAgentChardev *vd, VDAgentMessage *msg) if (have_mouse(vd) && vd->mouse_hs) { qemu_input_handler_activate(vd->mouse_hs); } - if (have_clipboard(vd) && vd->cbpeer.update.notify == NULL) { + if (have_clipboard(vd) && vd->cbpeer.notifier.notify == NULL) { vd->cbpeer.name = "vdagent"; - vd->cbpeer.update.notify = vdagent_clipboard_notify; + vd->cbpeer.notifier.notify = vdagent_clipboard_notify; vd->cbpeer.request = vdagent_clipboard_request; qemu_clipboard_peer_register(&vd->cbpeer); } @@ -799,7 +811,7 @@ static void vdagent_disconnect(VDAgentChardev *vd) if (vd->mouse_hs) { qemu_input_handler_deactivate(vd->mouse_hs); } - if (vd->cbpeer.update.notify) { + if (vd->cbpeer.notifier.notify) { qemu_clipboard_peer_unregister(&vd->cbpeer); memset(&vd->cbpeer, 0, sizeof(vd->cbpeer)); } @@ -807,11 +819,8 @@ static void vdagent_disconnect(VDAgentChardev *vd) static void vdagent_chr_set_fe_open(struct Chardev *chr, int fe_open) { - VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(chr); - if (!fe_open) { trace_vdagent_close(); - vdagent_disconnect(vd); return; } diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c index 67284b556c..6a0b105884 100644 --- a/ui/vnc-clipboard.c +++ b/ui/vnc-clipboard.c @@ -189,10 +189,8 @@ static void vnc_clipboard_provide(VncState *vs, vnc_flush(vs); } -static void vnc_clipboard_notify(Notifier *notifier, void *data) +static void vnc_clipboard_update_info(VncState *vs, QemuClipboardInfo *info) { - VncState *vs = container_of(notifier, VncState, cbpeer.update); - QemuClipboardInfo *info = data; QemuClipboardType type; bool self_update = info->owner == &vs->cbpeer; uint32_t flags = 0; @@ -223,6 +221,18 @@ static void vnc_clipboard_notify(Notifier *notifier, void *data) } } +static void vnc_clipboard_notify(Notifier *notifier, void *data) +{ + VncState *vs = container_of(notifier, VncState, cbpeer.notifier); + QemuClipboardNotify *notify = data; + + switch (notify->type) { + case QEMU_CLIPBOARD_UPDATE_INFO: + vnc_clipboard_update_info(vs, notify->info); + return; + } +} + static void vnc_clipboard_request(QemuClipboardInfo *info, QemuClipboardType type) { @@ -316,9 +326,9 @@ void vnc_server_cut_text_caps(VncState *vs) caps[1] = 0; vnc_clipboard_send(vs, 2, caps); - if (!vs->cbpeer.update.notify) { + if (!vs->cbpeer.notifier.notify) { vs->cbpeer.name = "vnc"; - vs->cbpeer.update.notify = vnc_clipboard_notify; + vs->cbpeer.notifier.notify = vnc_clipboard_notify; vs->cbpeer.request = vnc_clipboard_request; qemu_clipboard_peer_register(&vs->cbpeer); } diff --git a/ui/vnc.c b/ui/vnc.c index af02522e84..9b603382e7 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1354,7 +1354,7 @@ void vnc_disconnect_finish(VncState *vs) /* last client gone */ vnc_update_server_surface(vs->vd); } - if (vs->cbpeer.update.notify) { + if (vs->cbpeer.notifier.notify) { qemu_clipboard_peer_unregister(&vs->cbpeer); } From 835f69f4e64e2285253bae57f618a75a2756f27c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 19 Jul 2021 00:33:31 +0400 Subject: [PATCH 004/730] ui/vdagent: add serial capability support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Spice agent implements a simple serial mechanism to avoid clipboard races between client & guest. See: https://gitlab.freedesktop.org/spice/spice-protocol/-/commit/045a6978d6dbbf7046affc5c321fa8177c8cce56 Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- include/ui/clipboard.h | 4 ++++ ui/trace-events | 1 + ui/vdagent.c | 39 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h index d82cf31481..e590b453c8 100644 --- a/include/ui/clipboard.h +++ b/include/ui/clipboard.h @@ -102,6 +102,8 @@ struct QemuClipboardNotify { * @owner: clipboard owner. * @selection: clipboard selection. * @types: clipboard data array (one entry per type). + * @has_serial: whether @serial is available. + * @serial: the grab serial counter. * * Clipboard content data and metadata. */ @@ -109,6 +111,8 @@ struct QemuClipboardInfo { uint32_t refcount; QemuClipboardPeer *owner; QemuClipboardSelection selection; + bool has_serial; + uint32_t serial; struct { bool available; bool requested; diff --git a/ui/trace-events b/ui/trace-events index b9c0dd0fa1..e832c3e365 100644 --- a/ui/trace-events +++ b/ui/trace-events @@ -135,3 +135,4 @@ vdagent_recv_msg(const char *name, uint32_t size) "msg %s, size %d" vdagent_peer_cap(const char *name) "cap %s" vdagent_cb_grab_selection(const char *name) "selection %s" vdagent_cb_grab_type(const char *name) "type %s" +vdagent_cb_serial_discard(uint32_t current, uint32_t received) "current=%u, received=%u" diff --git a/ui/vdagent.c b/ui/vdagent.c index de827aad27..b4fdae6917 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -59,6 +59,7 @@ struct VDAgentChardev { /* clipboard */ QemuClipboardPeer cbpeer; + uint32_t last_serial[QEMU_CLIPBOARD_SELECTION__COUNT]; uint32_t cbpending[QEMU_CLIPBOARD_SELECTION__COUNT]; }; typedef struct VDAgentChardev VDAgentChardev; @@ -203,6 +204,9 @@ static void vdagent_send_caps(VDAgentChardev *vd) if (vd->clipboard) { caps->caps[0] |= (1 << VD_AGENT_CAP_CLIPBOARD_BY_DEMAND); caps->caps[0] |= (1 << VD_AGENT_CAP_CLIPBOARD_SELECTION); +#if CHECK_SPICE_PROTOCOL_VERSION(0, 14, 1) + caps->caps[0] |= (1 << VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL); +#endif } vdagent_send_msg(vd, msg); @@ -333,7 +337,8 @@ static void vdagent_send_clipboard_grab(VDAgentChardev *vd, { g_autofree VDAgentMessage *msg = g_malloc0(sizeof(VDAgentMessage) + - sizeof(uint32_t) * (QEMU_CLIPBOARD_TYPE__COUNT + 1)); + sizeof(uint32_t) * (QEMU_CLIPBOARD_TYPE__COUNT + 1) + + sizeof(uint32_t)); uint8_t *s = msg->data; uint32_t *data = (uint32_t *)msg->data; uint32_t q, type; @@ -346,6 +351,19 @@ static void vdagent_send_clipboard_grab(VDAgentChardev *vd, return; } +#if CHECK_SPICE_PROTOCOL_VERSION(0, 14, 1) + if (vd->caps & (1 << VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL)) { + if (!info->has_serial) { + /* client should win */ + info->serial = vd->last_serial[info->selection]++; + info->has_serial = true; + } + *data = info->serial; + data++; + msg->size += sizeof(uint32_t); + } +#endif + for (q = 0; q < QEMU_CLIPBOARD_TYPE__COUNT; q++) { type = type_qemu_to_vdagent(q); if (type != VD_AGENT_CLIPBOARD_NONE && info->types[q].available) { @@ -494,6 +512,24 @@ static void vdagent_clipboard_recv_grab(VDAgentChardev *vd, uint8_t s, uint32_t trace_vdagent_cb_grab_selection(GET_NAME(sel_name, s)); info = qemu_clipboard_info_new(&vd->cbpeer, s); +#if CHECK_SPICE_PROTOCOL_VERSION(0, 14, 1) + if (vd->caps & (1 << VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL)) { + if (size < sizeof(uint32_t)) { + /* this shouldn't happen! */ + return; + } + + info->has_serial = true; + info->serial = *(uint32_t *)data; + if (info->serial < vd->last_serial[s]) { + /* discard lower-ordering guest grab */ + return; + } + vd->last_serial[s] = info->serial; + data += sizeof(uint32_t); + size -= sizeof(uint32_t); + } +#endif if (size > sizeof(uint32_t) * 10) { /* * spice has 6 types as of 2021. Limiting to 10 entries @@ -671,6 +707,7 @@ static void vdagent_chr_recv_caps(VDAgentChardev *vd, VDAgentMessage *msg) qemu_input_handler_activate(vd->mouse_hs); } if (have_clipboard(vd) && vd->cbpeer.notifier.notify == NULL) { + memset(vd->last_serial, 0, sizeof(vd->last_serial)); vd->cbpeer.name = "vdagent"; vd->cbpeer.notifier.notify = vdagent_clipboard_notify; vd->cbpeer.request = vdagent_clipboard_request; From 349504e5a1533c795cd5f72e629766b996982050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 21 Jul 2021 15:19:13 +0400 Subject: [PATCH 005/730] ui/clipboard: add qemu_clipboard_check_serial() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- include/ui/clipboard.h | 10 ++++++++++ ui/clipboard.c | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h index e590b453c8..2c6488c1ee 100644 --- a/include/ui/clipboard.h +++ b/include/ui/clipboard.h @@ -172,6 +172,16 @@ void qemu_clipboard_peer_release(QemuClipboardPeer *peer, */ QemuClipboardInfo *qemu_clipboard_info(QemuClipboardSelection selection); +/** + * qemu_clipboard_check_serial + * + * @info: clipboard info. + * @client: whether to check from the client context and priority. + * + * Return TRUE if the @info has a higher serial than the current clipboard. + */ +bool qemu_clipboard_check_serial(QemuClipboardInfo *info, bool client); + /** * qemu_clipboard_info_new * diff --git a/ui/clipboard.c b/ui/clipboard.c index 743b39edf4..ffbd80e5c6 100644 --- a/ui/clipboard.c +++ b/ui/clipboard.c @@ -41,6 +41,21 @@ void qemu_clipboard_peer_release(QemuClipboardPeer *peer, } } +bool qemu_clipboard_check_serial(QemuClipboardInfo *info, bool client) +{ + if (!info->has_serial || + !cbinfo[info->selection] || + !cbinfo[info->selection]->has_serial) { + return true; + } + + if (client) { + return cbinfo[info->selection]->serial >= info->serial; + } else { + return cbinfo[info->selection]->serial > info->serial; + } +} + void qemu_clipboard_update(QemuClipboardInfo *info) { QemuClipboardNotify notify = { From 505dbf9b99e937853c02d7995f9eebe95508e8d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 19 Jul 2021 19:49:56 +0400 Subject: [PATCH 006/730] ui/clipboard: add a clipboard reset serial event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- include/ui/clipboard.h | 9 +++++++++ ui/clipboard.c | 7 +++++++ ui/cocoa.m | 3 +++ ui/gtk-clipboard.c | 3 +++ ui/vdagent.c | 12 ++++++++++++ ui/vnc-clipboard.c | 3 +++ 6 files changed, 37 insertions(+) diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h index 2c6488c1ee..ce76aa451f 100644 --- a/include/ui/clipboard.h +++ b/include/ui/clipboard.h @@ -73,11 +73,13 @@ struct QemuClipboardPeer { * enum QemuClipboardNotifyType * * @QEMU_CLIPBOARD_UPDATE_INFO: clipboard info update + * @QEMU_CLIPBOARD_RESET_SERIAL: reset clipboard serial * * Clipboard notify type. */ enum QemuClipboardNotifyType { QEMU_CLIPBOARD_UPDATE_INFO, + QEMU_CLIPBOARD_RESET_SERIAL, }; /** @@ -230,6 +232,13 @@ void qemu_clipboard_info_unref(QemuClipboardInfo *info); */ void qemu_clipboard_update(QemuClipboardInfo *info); +/** + * qemu_clipboard_reset_serial + * + * Reset the clipboard serial. + */ +void qemu_clipboard_reset_serial(void); + /** * qemu_clipboard_request * diff --git a/ui/clipboard.c b/ui/clipboard.c index ffbd80e5c6..82572ea116 100644 --- a/ui/clipboard.c +++ b/ui/clipboard.c @@ -129,6 +129,13 @@ void qemu_clipboard_request(QemuClipboardInfo *info, info->owner->request(info, type); } +void qemu_clipboard_reset_serial(void) +{ + QemuClipboardNotify notify = { .type = QEMU_CLIPBOARD_RESET_SERIAL }; + + notifier_list_notify(&clipboard_notifiers, ¬ify); +} + void qemu_clipboard_set_data(QemuClipboardPeer *peer, QemuClipboardInfo *info, QemuClipboardType type, diff --git a/ui/cocoa.m b/ui/cocoa.m index 6640a2e80e..7ca429fa80 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -1837,6 +1837,9 @@ static void cocoa_clipboard_notify(Notifier *notifier, void *data) case QEMU_CLIPBOARD_UPDATE_INFO: cocoa_clipboard_update_info(notify->info); return; + case QEMU_CLIPBOARD_RESET_SERIAL: + /* ignore */ + return; } } diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c index 44ff810234..e0b8b283fe 100644 --- a/ui/gtk-clipboard.c +++ b/ui/gtk-clipboard.c @@ -127,6 +127,9 @@ static void gd_clipboard_notify(Notifier *notifier, void *data) case QEMU_CLIPBOARD_UPDATE_INFO: gd_clipboard_update_info(gd, notify->info); return; + case QEMU_CLIPBOARD_RESET_SERIAL: + /* ignore */ + return; } } diff --git a/ui/vdagent.c b/ui/vdagent.c index b4fdae6917..7ea4bc5d9a 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -466,6 +466,15 @@ static void vdagent_clipboard_update_info(VDAgentChardev *vd, } } +static void vdagent_clipboard_reset_serial(VDAgentChardev *vd) +{ + Chardev *chr = CHARDEV(vd); + + /* reopen the agent connection to reset the serial state */ + qemu_chr_be_event(chr, CHR_EVENT_CLOSED); + qemu_chr_be_event(chr, CHR_EVENT_OPENED); +} + static void vdagent_clipboard_notify(Notifier *notifier, void *data) { VDAgentChardev *vd = @@ -476,6 +485,9 @@ static void vdagent_clipboard_notify(Notifier *notifier, void *data) case QEMU_CLIPBOARD_UPDATE_INFO: vdagent_clipboard_update_info(vd, notify->info); return; + case QEMU_CLIPBOARD_RESET_SERIAL: + vdagent_clipboard_reset_serial(vd); + return; } } diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c index 6a0b105884..d48f75eb1a 100644 --- a/ui/vnc-clipboard.c +++ b/ui/vnc-clipboard.c @@ -230,6 +230,9 @@ static void vnc_clipboard_notify(Notifier *notifier, void *data) case QEMU_CLIPBOARD_UPDATE_INFO: vnc_clipboard_update_info(vs, notify->info); return; + case QEMU_CLIPBOARD_RESET_SERIAL: + /* ignore */ + return; } } From 8f5f1ea0c04e730f24112f7bc4e343439f7c4420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 1 Jul 2021 11:08:54 +0400 Subject: [PATCH 007/730] hw/display: report an error if virgl initialization failed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, virgl initialization error is silent. Make it verbose instead. (this is likely going to bug later on, as the device isn't fully initialized) Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann Reviewed-by: Philippe Mathieu-Daudé --- hw/display/virtio-gpu-virgl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c index 18d054922f..0d87de65d7 100644 --- a/hw/display/virtio-gpu-virgl.c +++ b/hw/display/virtio-gpu-virgl.c @@ -609,6 +609,7 @@ int virtio_gpu_virgl_init(VirtIOGPU *g) ret = virgl_renderer_init(g, 0, &virtio_gpu_3d_cbs); if (ret != 0) { + error_report("virgl could not be initialized: %d", ret); return ret; } From 46e4609e339f424a0e19c1fb657ccad6a43f7364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 4 May 2021 12:07:46 +0400 Subject: [PATCH 008/730] virtio-gpu: use VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's part of Linux headers for a while now. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann Reviewed-by: Philippe Mathieu-Daudé --- hw/display/virtio-gpu-virgl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c index 0d87de65d7..73cb92c8d5 100644 --- a/hw/display/virtio-gpu-virgl.c +++ b/hw/display/virtio-gpu-virgl.c @@ -175,7 +175,7 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g, virgl_renderer_force_ctx_0(); dpy_gl_scanout_texture( g->parent_obj.scanout[ss.scanout_id].con, info.tex_id, - info.flags & 1 /* FIXME: Y_0_TOP */, + info.flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP, info.width, info.height, ss.r.x, ss.r.y, ss.r.width, ss.r.height); } else { From ca19ef52999251443b511b53e7b0498dd247261e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 13 Apr 2021 20:39:11 +0400 Subject: [PATCH 009/730] ui: do not delay further remote resize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A remote client, such as Spice, will already avoid flooding the stream by delaying the resize requests. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- include/ui/console.h | 2 +- ui/cocoa.m | 2 +- ui/console.c | 5 +++-- ui/gtk.c | 2 +- ui/sdl2.c | 2 +- ui/spice-display.c | 2 +- ui/vnc.c | 2 +- 7 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 6d678924f6..65e6bbcab8 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -292,7 +292,7 @@ void unregister_displaychangelistener(DisplayChangeListener *dcl); bool dpy_ui_info_supported(QemuConsole *con); const QemuUIInfo *dpy_get_ui_info(const QemuConsole *con); -int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info); +int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info, bool delay); void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h); void dpy_gfx_update_full(QemuConsole *con); diff --git a/ui/cocoa.m b/ui/cocoa.m index 7ca429fa80..69745c483b 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -552,7 +552,7 @@ QemuCocoaView *cocoaView; info.width = frameSize.width; info.height = frameSize.height; - dpy_set_ui_info(dcl.con, &info); + dpy_set_ui_info(dcl.con, &info, TRUE); } - (void)viewDidMoveToWindow diff --git a/ui/console.c b/ui/console.c index 29a3e3f0f5..dcc21eb5b2 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1538,7 +1538,7 @@ const QemuUIInfo *dpy_get_ui_info(const QemuConsole *con) return &con->ui_info; } -int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info) +int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info, bool delay) { if (con == NULL) { con = active_console; @@ -1558,7 +1558,8 @@ int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info) * go notify the guest. */ con->ui_info = *info; - timer_mod(con->ui_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000); + timer_mod(con->ui_timer, + qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + (delay ? 1000 : 0)); return 0; } diff --git a/ui/gtk.c b/ui/gtk.c index 428f02f2df..c0d8a9f061 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -698,7 +698,7 @@ static void gd_set_ui_info(VirtualConsole *vc, gint width, gint height) memset(&info, 0, sizeof(info)); info.width = width; info.height = height; - dpy_set_ui_info(vc->gfx.dcl.con, &info); + dpy_set_ui_info(vc->gfx.dcl.con, &info, true); } #if defined(CONFIG_OPENGL) diff --git a/ui/sdl2.c b/ui/sdl2.c index 17c0ec30eb..9ba3bc49e7 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -561,7 +561,7 @@ static void handle_windowevent(SDL_Event *ev) memset(&info, 0, sizeof(info)); info.width = ev->window.data1; info.height = ev->window.data2; - dpy_set_ui_info(scon->dcl.con, &info); + dpy_set_ui_info(scon->dcl.con, &info, true); } sdl2_redraw(scon); break; diff --git a/ui/spice-display.c b/ui/spice-display.c index f59c69882d..52d9f3260a 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -692,7 +692,7 @@ static int interface_client_monitors_config(QXLInstance *sin, } trace_qemu_spice_ui_info(ssd->qxl.id, info.width, info.height); - dpy_set_ui_info(ssd->dcl.con, &info); + dpy_set_ui_info(ssd->dcl.con, &info, false); return 1; } diff --git a/ui/vnc.c b/ui/vnc.c index 9b603382e7..1ed1c7efc6 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -2596,7 +2596,7 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) memset(&info, 0, sizeof(info)); info.width = w; info.height = h; - dpy_set_ui_info(vs->vd->dcl.con, &info); + dpy_set_ui_info(vs->vd->dcl.con, &info, false); vnc_desktop_resize_ext(vs, 4 /* Request forwarded */); } else { vnc_desktop_resize_ext(vs, 3 /* Invalid screen layout */); From 4f4181499170dcf80182745b319607802ea32896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 25 Jan 2021 14:53:18 +0400 Subject: [PATCH 010/730] ui: factor out qemu_console_set_display_gl_ctx() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The next patch will make use of this function to dissociate DisplayChangeListener from GL context. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann Reviewed-by: Philippe Mathieu-Daudé --- include/ui/console.h | 3 +++ ui/console.c | 22 ++++++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 65e6bbcab8..fb10e6d60c 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -411,6 +411,9 @@ void graphic_hw_gl_flushed(QemuConsole *con); void qemu_console_early_init(void); +void qemu_console_set_display_gl_ctx(QemuConsole *con, + DisplayChangeListener *dcl); + QemuConsole *qemu_console_lookup_by_index(unsigned int index); QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head); QemuConsole *qemu_console_lookup_by_device_name(const char *device_id, diff --git a/ui/console.c b/ui/console.c index dcc21eb5b2..7b83e6cdea 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1443,6 +1443,19 @@ static bool dpy_compatible_with(QemuConsole *con, return true; } +void qemu_console_set_display_gl_ctx(QemuConsole *con, + DisplayChangeListener *dcl) +{ + /* display has opengl support */ + assert(dcl->con); + if (dcl->con->gl) { + fprintf(stderr, "can't register two opengl displays (%s, %s)\n", + dcl->ops->dpy_name, dcl->con->gl->ops->dpy_name); + exit(1); + } + dcl->con->gl = dcl; +} + void register_displaychangelistener(DisplayChangeListener *dcl) { static const char nodev[] = @@ -1453,14 +1466,7 @@ void register_displaychangelistener(DisplayChangeListener *dcl) assert(!dcl->ds); if (dcl->ops->dpy_gl_ctx_create) { - /* display has opengl support */ - assert(dcl->con); - if (dcl->con->gl) { - fprintf(stderr, "can't register two opengl displays (%s, %s)\n", - dcl->ops->dpy_name, dcl->con->gl->ops->dpy_name); - exit(1); - } - dcl->con->gl = dcl; + qemu_console_set_display_gl_ctx(dcl->con, dcl); } if (dcl->con) { From ac32b2fff127843355b4f7e7ac9f93dd4a395adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 25 Jan 2021 15:10:36 +0400 Subject: [PATCH 011/730] ui: associate GL context outside of display listener registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consoles can have an associated GL context, without listeners (they may be added or removed later on). Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- ui/console.c | 7 +++++-- ui/egl-headless.c | 1 + ui/gtk.c | 3 +++ ui/sdl2.c | 3 +++ ui/spice-display.c | 3 +++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/ui/console.c b/ui/console.c index 7b83e6cdea..87f897e46d 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1465,8 +1465,11 @@ void register_displaychangelistener(DisplayChangeListener *dcl) assert(!dcl->ds); - if (dcl->ops->dpy_gl_ctx_create) { - qemu_console_set_display_gl_ctx(dcl->con, dcl); + if (dcl->con && dcl->con->gl && + dcl->con->gl != dcl) { + error_report("Display %s is incompatible with the GL context", + dcl->ops->dpy_name); + exit(1); } if (dcl->con) { diff --git a/ui/egl-headless.c b/ui/egl-headless.c index a26a2520c4..08327c40c6 100644 --- a/ui/egl-headless.c +++ b/ui/egl-headless.c @@ -197,6 +197,7 @@ static void egl_headless_init(DisplayState *ds, DisplayOptions *opts) edpy->dcl.con = con; edpy->dcl.ops = &egl_ops; edpy->gls = qemu_gl_init_shader(); + qemu_console_set_display_gl_ctx(con, &edpy->dcl); register_displaychangelistener(&edpy->dcl); } } diff --git a/ui/gtk.c b/ui/gtk.c index c0d8a9f061..25896023ff 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -2083,6 +2083,9 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc, vc->gfx.kbd = qkbd_state_init(con); vc->gfx.dcl.con = con; + if (display_opengl) { + qemu_console_set_display_gl_ctx(con, &vc->gfx.dcl); + } register_displaychangelistener(&vc->gfx.dcl); gd_connect_vc_gfx_signals(vc); diff --git a/ui/sdl2.c b/ui/sdl2.c index 9ba3bc49e7..bb186a381a 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -866,6 +866,9 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) #endif sdl2_console[i].dcl.con = con; sdl2_console[i].kbd = qkbd_state_init(con); + if (display_opengl) { + qemu_console_set_display_gl_ctx(con, &sdl2_console[i].dcl); + } register_displaychangelistener(&sdl2_console[i].dcl); #if defined(SDL_VIDEO_DRIVER_WINDOWS) || defined(SDL_VIDEO_DRIVER_X11) diff --git a/ui/spice-display.c b/ui/spice-display.c index 52d9f3260a..2c204bceee 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -1156,6 +1156,9 @@ static void qemu_spice_display_init_one(QemuConsole *con) qemu_spice_create_host_memslot(ssd); + if (spice_opengl) { + qemu_console_set_display_gl_ctx(con, &ssd->dcl); + } register_displaychangelistener(&ssd->dcl); } From a4ddc31417199eab96211b254097a0a0869d5bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 11 Mar 2021 11:45:33 +0400 Subject: [PATCH 012/730] ui: make gl_block use a counter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Track multiple callers blocking requests. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- ui/console.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ui/console.c b/ui/console.c index 87f897e46d..39f7b66baf 100644 --- a/ui/console.c +++ b/ui/console.c @@ -79,7 +79,7 @@ struct QemuConsole { DisplaySurface *surface; int dcls; DisplayChangeListener *gl; - bool gl_block; + int gl_block; int window_id; /* Graphic console state. */ @@ -237,10 +237,19 @@ void graphic_hw_gl_block(QemuConsole *con, bool block) { assert(con != NULL); - con->gl_block = block; - if (con->hw_ops->gl_block) { - con->hw_ops->gl_block(con->hw, block); + if (block) { + con->gl_block++; + } else { + con->gl_block--; } + assert(con->gl_block >= 0); + if (!con->hw_ops->gl_block) { + return; + } + if ((block && con->gl_block != 1) || (!block && con->gl_block != 0)) { + return; + } + con->hw_ops->gl_block(con->hw, block); } void graphic_hw_gl_flushed(QemuConsole *con) From a9b1e471e1783a1d7ae9215f9b8adc7cdb053367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 11 Mar 2021 11:56:58 +0400 Subject: [PATCH 013/730] ui: add a gl-unblock warning timer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to the one that exists for Spice, so we can investigate if something is locked. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- ui/console.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ui/console.c b/ui/console.c index 39f7b66baf..fcc4fe6a0a 100644 --- a/ui/console.c +++ b/ui/console.c @@ -80,6 +80,7 @@ struct QemuConsole { int dcls; DisplayChangeListener *gl; int gl_block; + QEMUTimer *gl_unblock_timer; int window_id; /* Graphic console state. */ @@ -233,8 +234,14 @@ void graphic_hw_update(QemuConsole *con) } } +static void graphic_hw_gl_unblock_timer(void *opaque) +{ + warn_report("console: no gl-unblock within one second"); +} + void graphic_hw_gl_block(QemuConsole *con, bool block) { + uint64_t timeout; assert(con != NULL); if (block) { @@ -250,6 +257,14 @@ void graphic_hw_gl_block(QemuConsole *con, bool block) return; } con->hw_ops->gl_block(con->hw, block); + + if (block) { + timeout = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); + timeout += 1000; /* one sec */ + timer_mod(con->gl_unblock_timer, timeout); + } else { + timer_del(con->gl_unblock_timer); + } } void graphic_hw_gl_flushed(QemuConsole *con) @@ -1966,6 +1981,8 @@ QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head, surface = qemu_create_placeholder_surface(width, height, noinit); dpy_gfx_replace_surface(s, surface); + s->gl_unblock_timer = timer_new_ms(QEMU_CLOCK_REALTIME, + graphic_hw_gl_unblock_timer, s); return s; } From f6413cbfd0b3a3f85ebaf9fe13494af1dad916bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 11 Mar 2021 12:11:37 +0400 Subject: [PATCH 014/730] ui: simplify gl unblock & flush MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GraphicHw.gl_flushed was introduced to notify the device (vhost-user-gpu) that the GL resources (the display scanout) are no longer needed. It was decoupled from QEMU own gl-blocking mechanism, but that difference isn't helping. Instead, we can reuse QEMU gl-blocking and notify virtio_gpu_gl_flushed() when unblocking (to unlock vhost-user-gpu). An extra block/unblock is added arount dpy_gl_update() so existing backends that don't block will have the flush event handled. It will also help when there are no backends associated. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- hw/display/vhost-user-gpu.c | 2 +- hw/display/virtio-gpu-base.c | 5 ++++- hw/display/virtio-vga.c | 11 ----------- include/ui/console.h | 2 -- ui/console.c | 12 +++--------- ui/gtk-egl.c | 2 -- ui/gtk-gl-area.c | 2 -- ui/gtk.c | 1 - ui/sdl2-gl.c | 2 -- ui/spice-display.c | 1 - 10 files changed, 8 insertions(+), 32 deletions(-) diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 49df56cd14..09818231bd 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -254,8 +254,8 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) vhost_user_gpu_unblock(g); break; } - dpy_gl_update(con, m->x, m->y, m->width, m->height); g->backend_blocked = true; + dpy_gl_update(con, m->x, m->y, m->width, m->height); break; } case VHOST_USER_GPU_UPDATE: { diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c index c8da4806e0..fff0fb4a82 100644 --- a/hw/display/virtio-gpu-base.c +++ b/hw/display/virtio-gpu-base.c @@ -117,6 +117,10 @@ virtio_gpu_gl_block(void *opaque, bool block) g->renderer_blocked--; } assert(g->renderer_blocked >= 0); + + if (!block && g->renderer_blocked == 0) { + virtio_gpu_gl_flushed(g); + } } static int @@ -143,7 +147,6 @@ static const GraphicHwOps virtio_gpu_ops = { .text_update = virtio_gpu_text_update, .ui_info = virtio_gpu_ui_info, .gl_block = virtio_gpu_gl_block, - .gl_flushed = virtio_gpu_gl_flushed, }; bool diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c index 9e57f61e9e..b23a75a04b 100644 --- a/hw/display/virtio-vga.c +++ b/hw/display/virtio-vga.c @@ -68,16 +68,6 @@ static void virtio_vga_base_gl_block(void *opaque, bool block) } } -static void virtio_vga_base_gl_flushed(void *opaque) -{ - VirtIOVGABase *vvga = opaque; - VirtIOGPUBase *g = vvga->vgpu; - - if (g->hw_ops->gl_flushed) { - g->hw_ops->gl_flushed(g); - } -} - static int virtio_vga_base_get_flags(void *opaque) { VirtIOVGABase *vvga = opaque; @@ -93,7 +83,6 @@ static const GraphicHwOps virtio_vga_base_ops = { .text_update = virtio_vga_base_text_update, .ui_info = virtio_vga_base_ui_info, .gl_block = virtio_vga_base_gl_block, - .gl_flushed = virtio_vga_base_gl_flushed, }; static const VMStateDescription vmstate_virtio_vga_base = { diff --git a/include/ui/console.h b/include/ui/console.h index fb10e6d60c..3ff51b492e 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -391,7 +391,6 @@ typedef struct GraphicHwOps { void (*update_interval)(void *opaque, uint64_t interval); int (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info); void (*gl_block)(void *opaque, bool block); - void (*gl_flushed)(void *opaque); } GraphicHwOps; QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head, @@ -407,7 +406,6 @@ void graphic_hw_update_done(QemuConsole *con); void graphic_hw_invalidate(QemuConsole *con); void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata); void graphic_hw_gl_block(QemuConsole *con, bool block); -void graphic_hw_gl_flushed(QemuConsole *con); void qemu_console_early_init(void); diff --git a/ui/console.c b/ui/console.c index fcc4fe6a0a..6f21007737 100644 --- a/ui/console.c +++ b/ui/console.c @@ -267,15 +267,6 @@ void graphic_hw_gl_block(QemuConsole *con, bool block) } } -void graphic_hw_gl_flushed(QemuConsole *con) -{ - assert(con != NULL); - - if (con->hw_ops->gl_flushed) { - con->hw_ops->gl_flushed(con->hw); - } -} - int qemu_console_get_window_id(QemuConsole *con) { return con->window_id; @@ -1894,7 +1885,10 @@ void dpy_gl_update(QemuConsole *con, uint32_t x, uint32_t y, uint32_t w, uint32_t h) { assert(con->gl); + + graphic_hw_gl_block(con, true); con->gl->ops->dpy_gl_update(con->gl, x, y, w, h); + graphic_hw_gl_block(con, false); } /***********************************************************/ diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 45cb67712d..e891b61048 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -119,8 +119,6 @@ void gd_egl_draw(VirtualConsole *vc) glFlush(); } - - graphic_hw_gl_flushed(vc->gfx.dcl.con); } void gd_egl_update(DisplayChangeListener *dcl, diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 01e4e74ee3..f1c7636cba 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -101,8 +101,6 @@ void gd_gl_area_draw(VirtualConsole *vc) surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, ww, wh); surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds); } - - graphic_hw_gl_flushed(vc->gfx.dcl.con); } void gd_gl_area_update(DisplayChangeListener *dcl, diff --git a/ui/gtk.c b/ui/gtk.c index 25896023ff..077d38145d 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -593,7 +593,6 @@ void gd_hw_gl_flushed(void *vcon) close(dmabuf->fence_fd); dmabuf->fence_fd = -1; graphic_hw_gl_block(vc->gfx.dcl.con, false); - graphic_hw_gl_flushed(vc->gfx.dcl.con); } /** DisplayState Callbacks (opengl version) **/ diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c index a21d2deed9..5b950fbbea 100644 --- a/ui/sdl2-gl.c +++ b/ui/sdl2-gl.c @@ -58,7 +58,6 @@ static void sdl2_gl_render_surface(struct sdl2_console *scon) surface_gl_render_texture(scon->gls, scon->surface); SDL_GL_SwapWindow(scon->real_window); - graphic_hw_gl_flushed(scon->dcl.con); } void sdl2_gl_update(DisplayChangeListener *dcl, @@ -241,5 +240,4 @@ void sdl2_gl_scanout_flush(DisplayChangeListener *dcl, egl_fb_blit(&scon->win_fb, &scon->guest_fb, !scon->y0_top); SDL_GL_SwapWindow(scon->real_window); - graphic_hw_gl_flushed(dcl->con); } diff --git a/ui/spice-display.c b/ui/spice-display.c index 2c204bceee..ec501f129f 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -830,7 +830,6 @@ static void qemu_spice_gl_unblock_bh(void *opaque) SimpleSpiceDisplay *ssd = opaque; qemu_spice_gl_block(ssd, false); - graphic_hw_gl_flushed(ssd->dcl.con); } static void qemu_spice_gl_block_timer(void *opaque) From 7cc712e9862ffdbe4161dbdf3bbf41bcbe547472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 26 Jan 2021 00:00:30 +0400 Subject: [PATCH 015/730] ui: dispatch GL events to all listeners MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For now, only one listener can receive GL events. Let's dispatch to all listeners. (preliminary check ensure there is a single listener now during regitration, and in next patches, compatible listeners only) Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- ui/console.c | 58 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/ui/console.c b/ui/console.c index 6f21007737..13c0d001c0 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1824,8 +1824,12 @@ int dpy_gl_ctx_make_current(QemuConsole *con, QEMUGLContext ctx) void dpy_gl_scanout_disable(QemuConsole *con) { - assert(con->gl); - con->gl->ops->dpy_gl_scanout_disable(con->gl); + DisplayState *s = con->ds; + DisplayChangeListener *dcl; + + QLIST_FOREACH(dcl, &s->listeners, next) { + dcl->ops->dpy_gl_scanout_disable(dcl); + } } void dpy_gl_scanout_texture(QemuConsole *con, @@ -1836,58 +1840,80 @@ void dpy_gl_scanout_texture(QemuConsole *con, uint32_t x, uint32_t y, uint32_t width, uint32_t height) { - assert(con->gl); - con->gl->ops->dpy_gl_scanout_texture(con->gl, backing_id, + DisplayState *s = con->ds; + DisplayChangeListener *dcl; + + QLIST_FOREACH(dcl, &s->listeners, next) { + dcl->ops->dpy_gl_scanout_texture(dcl, backing_id, backing_y_0_top, backing_width, backing_height, x, y, width, height); + } } void dpy_gl_scanout_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf) { - assert(con->gl); - con->gl->ops->dpy_gl_scanout_dmabuf(con->gl, dmabuf); + DisplayState *s = con->ds; + DisplayChangeListener *dcl; + + QLIST_FOREACH(dcl, &s->listeners, next) { + dcl->ops->dpy_gl_scanout_dmabuf(dcl, dmabuf); + } } void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf, bool have_hot, uint32_t hot_x, uint32_t hot_y) { - assert(con->gl); + DisplayState *s = con->ds; + DisplayChangeListener *dcl; - if (con->gl->ops->dpy_gl_cursor_dmabuf) { - con->gl->ops->dpy_gl_cursor_dmabuf(con->gl, dmabuf, + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_gl_cursor_dmabuf) { + dcl->ops->dpy_gl_cursor_dmabuf(dcl, dmabuf, have_hot, hot_x, hot_y); + } } } void dpy_gl_cursor_position(QemuConsole *con, uint32_t pos_x, uint32_t pos_y) { - assert(con->gl); + DisplayState *s = con->ds; + DisplayChangeListener *dcl; - if (con->gl->ops->dpy_gl_cursor_position) { - con->gl->ops->dpy_gl_cursor_position(con->gl, pos_x, pos_y); + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_gl_cursor_position) { + dcl->ops->dpy_gl_cursor_position(dcl, pos_x, pos_y); + } } } void dpy_gl_release_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf) { - assert(con->gl); + DisplayState *s = con->ds; + DisplayChangeListener *dcl; - if (con->gl->ops->dpy_gl_release_dmabuf) { - con->gl->ops->dpy_gl_release_dmabuf(con->gl, dmabuf); + QLIST_FOREACH(dcl, &s->listeners, next) { + if (dcl->ops->dpy_gl_release_dmabuf) { + dcl->ops->dpy_gl_release_dmabuf(dcl, dmabuf); + } } } void dpy_gl_update(QemuConsole *con, uint32_t x, uint32_t y, uint32_t w, uint32_t h) { + DisplayState *s = con->ds; + DisplayChangeListener *dcl; + assert(con->gl); graphic_hw_gl_block(con, true); - con->gl->ops->dpy_gl_update(con->gl, x, y, w, h); + QLIST_FOREACH(dcl, &s->listeners, next) { + dcl->ops->dpy_gl_update(dcl, x, y, w, h); + } graphic_hw_gl_block(con, false); } From 5e79d516e8ac818d2a90aae9f787775055434ee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sat, 9 Oct 2021 23:48:46 +0400 Subject: [PATCH 016/730] ui: split the GL context in a different object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will allow to have one GL context but a variable number of listeners. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- include/ui/console.h | 34 ++++++++++++++++++++++------------ include/ui/egl-context.h | 6 +++--- include/ui/gtk.h | 11 ++++++----- include/ui/sdl2.h | 7 ++++--- include/ui/spice-display.h | 1 + ui/console.c | 26 ++++++++++++++++---------- ui/egl-context.c | 6 +++--- ui/egl-headless.c | 21 ++++++++++++++------- ui/gtk-egl.c | 10 +++++----- ui/gtk-gl-area.c | 8 ++++---- ui/gtk.c | 24 ++++++++++++++++-------- ui/sdl2-gl.c | 10 +++++----- ui/sdl2.c | 13 +++++++++---- ui/spice-display.c | 18 +++++++++++------- 14 files changed, 119 insertions(+), 76 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 3ff51b492e..fe08b4dd04 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -179,6 +179,7 @@ typedef struct QemuDmaBuf { } QemuDmaBuf; typedef struct DisplayState DisplayState; +typedef struct DisplayGLCtx DisplayGLCtx; typedef struct DisplayChangeListenerOps { const char *dpy_name; @@ -213,16 +214,6 @@ typedef struct DisplayChangeListenerOps { void (*dpy_cursor_define)(DisplayChangeListener *dcl, QEMUCursor *cursor); - /* required if GL */ - QEMUGLContext (*dpy_gl_ctx_create)(DisplayChangeListener *dcl, - QEMUGLParams *params); - /* required if GL */ - void (*dpy_gl_ctx_destroy)(DisplayChangeListener *dcl, - QEMUGLContext ctx); - /* required if GL */ - int (*dpy_gl_ctx_make_current)(DisplayChangeListener *dcl, - QEMUGLContext ctx); - /* required if GL */ void (*dpy_gl_scanout_disable)(DisplayChangeListener *dcl); /* required if GL */ @@ -263,6 +254,26 @@ struct DisplayChangeListener { QLIST_ENTRY(DisplayChangeListener) next; }; +typedef struct DisplayGLCtxOps { + /* + * We only check if the GLCtx is compatible with a DCL via ops. A natural + * evolution of this would be a callback to check some runtime requirements + * and allow various DCL kinds. + */ + const DisplayChangeListenerOps *compatible_dcl; + + QEMUGLContext (*dpy_gl_ctx_create)(DisplayGLCtx *dgc, + QEMUGLParams *params); + void (*dpy_gl_ctx_destroy)(DisplayGLCtx *dgc, + QEMUGLContext ctx); + int (*dpy_gl_ctx_make_current)(DisplayGLCtx *dgc, + QEMUGLContext ctx); +} DisplayGLCtxOps; + +struct DisplayGLCtx { + const DisplayGLCtxOps *ops; +}; + DisplayState *init_displaystate(void); DisplaySurface *qemu_create_displaysurface_from(int width, int height, pixman_format_code_t format, @@ -409,8 +420,7 @@ void graphic_hw_gl_block(QemuConsole *con, bool block); void qemu_console_early_init(void); -void qemu_console_set_display_gl_ctx(QemuConsole *con, - DisplayChangeListener *dcl); +void qemu_console_set_display_gl_ctx(QemuConsole *con, DisplayGLCtx *ctx); QemuConsole *qemu_console_lookup_by_index(unsigned int index); QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head); diff --git a/include/ui/egl-context.h b/include/ui/egl-context.h index 9374fe41e3..c2761d747a 100644 --- a/include/ui/egl-context.h +++ b/include/ui/egl-context.h @@ -4,10 +4,10 @@ #include "ui/console.h" #include "ui/egl-helpers.h" -QEMUGLContext qemu_egl_create_context(DisplayChangeListener *dcl, +QEMUGLContext qemu_egl_create_context(DisplayGLCtx *dgc, QEMUGLParams *params); -void qemu_egl_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx); -int qemu_egl_make_context_current(DisplayChangeListener *dcl, +void qemu_egl_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx); +int qemu_egl_make_context_current(DisplayGLCtx *dgc, QEMUGLContext ctx); #endif /* EGL_CONTEXT_H */ diff --git a/include/ui/gtk.h b/include/ui/gtk.h index 7d22affd38..101b147d1b 100644 --- a/include/ui/gtk.h +++ b/include/ui/gtk.h @@ -35,6 +35,7 @@ typedef struct GtkDisplayState GtkDisplayState; typedef struct VirtualGfxConsole { GtkWidget *drawing_area; + DisplayGLCtx dgc; DisplayChangeListener dcl; QKbdState *kbd; DisplaySurface *ds; @@ -165,7 +166,7 @@ void gd_egl_update(DisplayChangeListener *dcl, void gd_egl_refresh(DisplayChangeListener *dcl); void gd_egl_switch(DisplayChangeListener *dcl, DisplaySurface *surface); -QEMUGLContext gd_egl_create_context(DisplayChangeListener *dcl, +QEMUGLContext gd_egl_create_context(DisplayGLCtx *dgc, QEMUGLParams *params); void gd_egl_scanout_disable(DisplayChangeListener *dcl); void gd_egl_scanout_texture(DisplayChangeListener *dcl, @@ -187,7 +188,7 @@ void gd_egl_flush(DisplayChangeListener *dcl, void gd_egl_scanout_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h); void gtk_egl_init(DisplayGLMode mode); -int gd_egl_make_current(DisplayChangeListener *dcl, +int gd_egl_make_current(DisplayGLCtx *dgc, QEMUGLContext ctx); /* ui/gtk-gl-area.c */ @@ -198,9 +199,9 @@ void gd_gl_area_update(DisplayChangeListener *dcl, void gd_gl_area_refresh(DisplayChangeListener *dcl); void gd_gl_area_switch(DisplayChangeListener *dcl, DisplaySurface *surface); -QEMUGLContext gd_gl_area_create_context(DisplayChangeListener *dcl, +QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc, QEMUGLParams *params); -void gd_gl_area_destroy_context(DisplayChangeListener *dcl, +void gd_gl_area_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx); void gd_gl_area_scanout_dmabuf(DisplayChangeListener *dcl, QemuDmaBuf *dmabuf); @@ -215,7 +216,7 @@ void gd_gl_area_scanout_disable(DisplayChangeListener *dcl); void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h); void gtk_gl_area_init(void); -int gd_gl_area_make_current(DisplayChangeListener *dcl, +int gd_gl_area_make_current(DisplayGLCtx *dgc, QEMUGLContext ctx); /* gtk-clipboard.c */ diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h index f85c117a78..71bcf7ebda 100644 --- a/include/ui/sdl2.h +++ b/include/ui/sdl2.h @@ -16,6 +16,7 @@ #endif struct sdl2_console { + DisplayGLCtx dgc; DisplayChangeListener dcl; DisplaySurface *surface; DisplayOptions *opts; @@ -65,10 +66,10 @@ void sdl2_gl_switch(DisplayChangeListener *dcl, void sdl2_gl_refresh(DisplayChangeListener *dcl); void sdl2_gl_redraw(struct sdl2_console *scon); -QEMUGLContext sdl2_gl_create_context(DisplayChangeListener *dcl, +QEMUGLContext sdl2_gl_create_context(DisplayGLCtx *dgc, QEMUGLParams *params); -void sdl2_gl_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx); -int sdl2_gl_make_context_current(DisplayChangeListener *dcl, +void sdl2_gl_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx); +int sdl2_gl_make_context_current(DisplayGLCtx *dgc, QEMUGLContext ctx); void sdl2_gl_scanout_disable(DisplayChangeListener *dcl); diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index ed298d58f0..a2fbf62c52 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -86,6 +86,7 @@ typedef struct SimpleSpiceCursor SimpleSpiceCursor; struct SimpleSpiceDisplay { DisplaySurface *ds; + DisplayGLCtx dgc; DisplayChangeListener dcl; void *buf; int bufsize; diff --git a/ui/console.c b/ui/console.c index 13c0d001c0..78583df920 100644 --- a/ui/console.c +++ b/ui/console.c @@ -78,7 +78,7 @@ struct QemuConsole { DisplayState *ds; DisplaySurface *surface; int dcls; - DisplayChangeListener *gl; + DisplayGLCtx *gl; int gl_block; QEMUTimer *gl_unblock_timer; int window_id; @@ -1458,17 +1458,24 @@ static bool dpy_compatible_with(QemuConsole *con, return true; } -void qemu_console_set_display_gl_ctx(QemuConsole *con, - DisplayChangeListener *dcl) +void qemu_console_set_display_gl_ctx(QemuConsole *con, DisplayGLCtx *gl) { /* display has opengl support */ - assert(dcl->con); - if (dcl->con->gl) { - fprintf(stderr, "can't register two opengl displays (%s, %s)\n", - dcl->ops->dpy_name, dcl->con->gl->ops->dpy_name); + assert(con); + if (con->gl) { + error_report("The console already has an OpenGL context."); exit(1); } - dcl->con->gl = dcl; + con->gl = gl; +} + +static bool dpy_gl_compatible_with(QemuConsole *con, DisplayChangeListener *dcl) +{ + if (!con->gl) { + return true; + } + + return con->gl->ops->compatible_dcl == dcl->ops; } void register_displaychangelistener(DisplayChangeListener *dcl) @@ -1480,8 +1487,7 @@ void register_displaychangelistener(DisplayChangeListener *dcl) assert(!dcl->ds); - if (dcl->con && dcl->con->gl && - dcl->con->gl != dcl) { + if (dcl->con && !dpy_gl_compatible_with(dcl->con, dcl)) { error_report("Display %s is incompatible with the GL context", dcl->ops->dpy_name); exit(1); diff --git a/ui/egl-context.c b/ui/egl-context.c index 368ffa49d8..eb5f520fc4 100644 --- a/ui/egl-context.c +++ b/ui/egl-context.c @@ -1,7 +1,7 @@ #include "qemu/osdep.h" #include "ui/egl-context.h" -QEMUGLContext qemu_egl_create_context(DisplayChangeListener *dcl, +QEMUGLContext qemu_egl_create_context(DisplayGLCtx *dgc, QEMUGLParams *params) { EGLContext ctx; @@ -24,12 +24,12 @@ QEMUGLContext qemu_egl_create_context(DisplayChangeListener *dcl, return ctx; } -void qemu_egl_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx) +void qemu_egl_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx) { eglDestroyContext(qemu_egl_display, ctx); } -int qemu_egl_make_context_current(DisplayChangeListener *dcl, +int qemu_egl_make_context_current(DisplayGLCtx *dgc, QEMUGLContext ctx) { return eglMakeCurrent(qemu_egl_display, diff --git a/ui/egl-headless.c b/ui/egl-headless.c index 08327c40c6..94082a9da9 100644 --- a/ui/egl-headless.c +++ b/ui/egl-headless.c @@ -38,12 +38,12 @@ static void egl_gfx_switch(DisplayChangeListener *dcl, edpy->ds = new_surface; } -static QEMUGLContext egl_create_context(DisplayChangeListener *dcl, +static QEMUGLContext egl_create_context(DisplayGLCtx *dgc, QEMUGLParams *params) { eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, qemu_egl_rn_ctx); - return qemu_egl_create_context(dcl, params); + return qemu_egl_create_context(dgc, params); } static void egl_scanout_disable(DisplayChangeListener *dcl) @@ -157,10 +157,6 @@ static const DisplayChangeListenerOps egl_ops = { .dpy_gfx_update = egl_gfx_update, .dpy_gfx_switch = egl_gfx_switch, - .dpy_gl_ctx_create = egl_create_context, - .dpy_gl_ctx_destroy = qemu_egl_destroy_context, - .dpy_gl_ctx_make_current = qemu_egl_make_context_current, - .dpy_gl_scanout_disable = egl_scanout_disable, .dpy_gl_scanout_texture = egl_scanout_texture, .dpy_gl_scanout_dmabuf = egl_scanout_dmabuf, @@ -170,6 +166,13 @@ static const DisplayChangeListenerOps egl_ops = { .dpy_gl_update = egl_scanout_flush, }; +static const DisplayGLCtxOps eglctx_ops = { + .compatible_dcl = &egl_ops, + .dpy_gl_ctx_create = egl_create_context, + .dpy_gl_ctx_destroy = qemu_egl_destroy_context, + .dpy_gl_ctx_make_current = qemu_egl_make_context_current, +}; + static void early_egl_headless_init(DisplayOptions *opts) { display_opengl = 1; @@ -188,6 +191,8 @@ static void egl_headless_init(DisplayState *ds, DisplayOptions *opts) } for (idx = 0;; idx++) { + DisplayGLCtx *ctx; + con = qemu_console_lookup_by_index(idx); if (!con || !qemu_console_is_graphic(con)) { break; @@ -197,7 +202,9 @@ static void egl_headless_init(DisplayState *ds, DisplayOptions *opts) edpy->dcl.con = con; edpy->dcl.ops = &egl_ops; edpy->gls = qemu_gl_init_shader(); - qemu_console_set_display_gl_ctx(con, &edpy->dcl); + ctx = g_new0(DisplayGLCtx, 1); + ctx->ops = &eglctx_ops; + qemu_console_set_display_gl_ctx(con, ctx); register_displaychangelistener(&edpy->dcl); } } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index e891b61048..e3bd4bc274 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -197,14 +197,14 @@ void gd_egl_switch(DisplayChangeListener *dcl, } } -QEMUGLContext gd_egl_create_context(DisplayChangeListener *dcl, +QEMUGLContext gd_egl_create_context(DisplayGLCtx *dgc, QEMUGLParams *params) { - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); + VirtualConsole *vc = container_of(dgc, VirtualConsole, gfx.dgc); eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, vc->gfx.esurface, vc->gfx.ectx); - return qemu_egl_create_context(dcl, params); + return qemu_egl_create_context(dgc, params); } void gd_egl_scanout_disable(DisplayChangeListener *dcl) @@ -360,10 +360,10 @@ void gtk_egl_init(DisplayGLMode mode) display_opengl = 1; } -int gd_egl_make_current(DisplayChangeListener *dcl, +int gd_egl_make_current(DisplayGLCtx *dgc, QEMUGLContext ctx) { - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); + VirtualConsole *vc = container_of(dgc, VirtualConsole, gfx.dgc); return eglMakeCurrent(qemu_egl_display, vc->gfx.esurface, vc->gfx.esurface, ctx); diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index f1c7636cba..fc5a082eb8 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -170,10 +170,10 @@ void gd_gl_area_switch(DisplayChangeListener *dcl, } } -QEMUGLContext gd_gl_area_create_context(DisplayChangeListener *dcl, +QEMUGLContext gd_gl_area_create_context(DisplayGLCtx *dgc, QEMUGLParams *params) { - VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); + VirtualConsole *vc = container_of(dgc, VirtualConsole, gfx.dgc); GdkWindow *window; GdkGLContext *ctx; GError *err = NULL; @@ -199,7 +199,7 @@ QEMUGLContext gd_gl_area_create_context(DisplayChangeListener *dcl, return ctx; } -void gd_gl_area_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx) +void gd_gl_area_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx) { /* FIXME */ } @@ -278,7 +278,7 @@ void gtk_gl_area_init(void) display_opengl = 1; } -int gd_gl_area_make_current(DisplayChangeListener *dcl, +int gd_gl_area_make_current(DisplayGLCtx *dgc, QEMUGLContext ctx) { gdk_gl_context_make_current(ctx); diff --git a/ui/gtk.c b/ui/gtk.c index 077d38145d..6a1f65d518 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -606,9 +606,6 @@ static const DisplayChangeListenerOps dcl_gl_area_ops = { .dpy_mouse_set = gd_mouse_set, .dpy_cursor_define = gd_cursor_define, - .dpy_gl_ctx_create = gd_gl_area_create_context, - .dpy_gl_ctx_destroy = gd_gl_area_destroy_context, - .dpy_gl_ctx_make_current = gd_gl_area_make_current, .dpy_gl_scanout_texture = gd_gl_area_scanout_texture, .dpy_gl_scanout_disable = gd_gl_area_scanout_disable, .dpy_gl_update = gd_gl_area_scanout_flush, @@ -617,8 +614,14 @@ static const DisplayChangeListenerOps dcl_gl_area_ops = { .dpy_has_dmabuf = gd_has_dmabuf, }; -#ifdef CONFIG_X11 +static const DisplayGLCtxOps gl_area_ctx_ops = { + .compatible_dcl = &dcl_gl_area_ops, + .dpy_gl_ctx_create = gd_gl_area_create_context, + .dpy_gl_ctx_destroy = gd_gl_area_destroy_context, + .dpy_gl_ctx_make_current = gd_gl_area_make_current, +}; +#ifdef CONFIG_X11 static const DisplayChangeListenerOps dcl_egl_ops = { .dpy_name = "gtk-egl", .dpy_gfx_update = gd_egl_update, @@ -628,9 +631,6 @@ static const DisplayChangeListenerOps dcl_egl_ops = { .dpy_mouse_set = gd_mouse_set, .dpy_cursor_define = gd_cursor_define, - .dpy_gl_ctx_create = gd_egl_create_context, - .dpy_gl_ctx_destroy = qemu_egl_destroy_context, - .dpy_gl_ctx_make_current = gd_egl_make_current, .dpy_gl_scanout_disable = gd_egl_scanout_disable, .dpy_gl_scanout_texture = gd_egl_scanout_texture, .dpy_gl_scanout_dmabuf = gd_egl_scanout_dmabuf, @@ -641,6 +641,12 @@ static const DisplayChangeListenerOps dcl_egl_ops = { .dpy_has_dmabuf = gd_has_dmabuf, }; +static const DisplayGLCtxOps egl_ctx_ops = { + .compatible_dcl = &dcl_egl_ops, + .dpy_gl_ctx_create = gd_egl_create_context, + .dpy_gl_ctx_destroy = qemu_egl_destroy_context, + .dpy_gl_ctx_make_current = gd_egl_make_current, +}; #endif #endif /* CONFIG_OPENGL */ @@ -2034,6 +2040,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc, g_signal_connect(vc->gfx.drawing_area, "realize", G_CALLBACK(gl_area_realize), vc); vc->gfx.dcl.ops = &dcl_gl_area_ops; + vc->gfx.dgc.ops = &gl_area_ctx_ops; } else { #ifdef CONFIG_X11 vc->gfx.drawing_area = gtk_drawing_area_new(); @@ -2048,6 +2055,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc, gtk_widget_set_double_buffered(vc->gfx.drawing_area, FALSE); #pragma GCC diagnostic pop vc->gfx.dcl.ops = &dcl_egl_ops; + vc->gfx.dgc.ops = &egl_ctx_ops; vc->gfx.has_dmabuf = qemu_egl_has_dmabuf(); #else abort(); @@ -2083,7 +2091,7 @@ static GSList *gd_vc_gfx_init(GtkDisplayState *s, VirtualConsole *vc, vc->gfx.dcl.con = con; if (display_opengl) { - qemu_console_set_display_gl_ctx(con, &vc->gfx.dcl); + qemu_console_set_display_gl_ctx(con, &vc->gfx.dgc); } register_displaychangelistener(&vc->gfx.dcl); diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c index 5b950fbbea..39cab8cde7 100644 --- a/ui/sdl2-gl.c +++ b/ui/sdl2-gl.c @@ -132,10 +132,10 @@ void sdl2_gl_redraw(struct sdl2_console *scon) } } -QEMUGLContext sdl2_gl_create_context(DisplayChangeListener *dcl, +QEMUGLContext sdl2_gl_create_context(DisplayGLCtx *dgc, QEMUGLParams *params) { - struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + struct sdl2_console *scon = container_of(dgc, struct sdl2_console, dgc); SDL_GLContext ctx; assert(scon->opengl); @@ -167,17 +167,17 @@ QEMUGLContext sdl2_gl_create_context(DisplayChangeListener *dcl, return (QEMUGLContext)ctx; } -void sdl2_gl_destroy_context(DisplayChangeListener *dcl, QEMUGLContext ctx) +void sdl2_gl_destroy_context(DisplayGLCtx *dgc, QEMUGLContext ctx) { SDL_GLContext sdlctx = (SDL_GLContext)ctx; SDL_GL_DeleteContext(sdlctx); } -int sdl2_gl_make_context_current(DisplayChangeListener *dcl, +int sdl2_gl_make_context_current(DisplayGLCtx *dgc, QEMUGLContext ctx) { - struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + struct sdl2_console *scon = container_of(dgc, struct sdl2_console, dgc); SDL_GLContext sdlctx = (SDL_GLContext)ctx; assert(scon->opengl); diff --git a/ui/sdl2.c b/ui/sdl2.c index bb186a381a..0bd30504cf 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -778,13 +778,17 @@ static const DisplayChangeListenerOps dcl_gl_ops = { .dpy_mouse_set = sdl_mouse_warp, .dpy_cursor_define = sdl_mouse_define, - .dpy_gl_ctx_create = sdl2_gl_create_context, - .dpy_gl_ctx_destroy = sdl2_gl_destroy_context, - .dpy_gl_ctx_make_current = sdl2_gl_make_context_current, .dpy_gl_scanout_disable = sdl2_gl_scanout_disable, .dpy_gl_scanout_texture = sdl2_gl_scanout_texture, .dpy_gl_update = sdl2_gl_scanout_flush, }; + +static const DisplayGLCtxOps gl_ctx_ops = { + .compatible_dcl = &dcl_gl_ops, + .dpy_gl_ctx_create = sdl2_gl_create_context, + .dpy_gl_ctx_destroy = sdl2_gl_destroy_context, + .dpy_gl_ctx_make_current = sdl2_gl_make_context_current, +}; #endif static void sdl2_display_early_init(DisplayOptions *o) @@ -860,6 +864,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) #ifdef CONFIG_OPENGL sdl2_console[i].opengl = display_opengl; sdl2_console[i].dcl.ops = display_opengl ? &dcl_gl_ops : &dcl_2d_ops; + sdl2_console[i].dgc.ops = display_opengl ? &gl_ctx_ops : NULL; #else sdl2_console[i].opengl = 0; sdl2_console[i].dcl.ops = &dcl_2d_ops; @@ -867,7 +872,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) sdl2_console[i].dcl.con = con; sdl2_console[i].kbd = qkbd_state_init(con); if (display_opengl) { - qemu_console_set_display_gl_ctx(con, &sdl2_console[i].dcl); + qemu_console_set_display_gl_ctx(con, &sdl2_console[i].dgc); } register_displaychangelistener(&sdl2_console[i].dcl); diff --git a/ui/spice-display.c b/ui/spice-display.c index ec501f129f..798e0f6167 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -908,12 +908,12 @@ static void spice_gl_switch(DisplayChangeListener *dcl, } } -static QEMUGLContext qemu_spice_gl_create_context(DisplayChangeListener *dcl, +static QEMUGLContext qemu_spice_gl_create_context(DisplayGLCtx *dgc, QEMUGLParams *params) { eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, qemu_egl_rn_ctx); - return qemu_egl_create_context(dcl, params); + return qemu_egl_create_context(dgc, params); } static void qemu_spice_gl_scanout_disable(DisplayChangeListener *dcl) @@ -1105,10 +1105,6 @@ static const DisplayChangeListenerOps display_listener_gl_ops = { .dpy_mouse_set = display_mouse_set, .dpy_cursor_define = display_mouse_define, - .dpy_gl_ctx_create = qemu_spice_gl_create_context, - .dpy_gl_ctx_destroy = qemu_egl_destroy_context, - .dpy_gl_ctx_make_current = qemu_egl_make_context_current, - .dpy_gl_scanout_disable = qemu_spice_gl_scanout_disable, .dpy_gl_scanout_texture = qemu_spice_gl_scanout_texture, .dpy_gl_scanout_dmabuf = qemu_spice_gl_scanout_dmabuf, @@ -1118,6 +1114,13 @@ static const DisplayChangeListenerOps display_listener_gl_ops = { .dpy_gl_update = qemu_spice_gl_update, }; +static const DisplayGLCtxOps gl_ctx_ops = { + .compatible_dcl = &display_listener_gl_ops, + .dpy_gl_ctx_create = qemu_spice_gl_create_context, + .dpy_gl_ctx_destroy = qemu_egl_destroy_context, + .dpy_gl_ctx_make_current = qemu_egl_make_context_current, +}; + #endif /* HAVE_SPICE_GL */ static void qemu_spice_display_init_one(QemuConsole *con) @@ -1130,6 +1133,7 @@ static void qemu_spice_display_init_one(QemuConsole *con) #ifdef HAVE_SPICE_GL if (spice_opengl) { ssd->dcl.ops = &display_listener_gl_ops; + ssd->dgc.ops = &gl_ctx_ops; ssd->gl_unblock_bh = qemu_bh_new(qemu_spice_gl_unblock_bh, ssd); ssd->gl_unblock_timer = timer_new_ms(QEMU_CLOCK_REALTIME, qemu_spice_gl_block_timer, ssd); @@ -1156,7 +1160,7 @@ static void qemu_spice_display_init_one(QemuConsole *con) qemu_spice_create_host_memslot(ssd); if (spice_opengl) { - qemu_console_set_display_gl_ctx(con, &ssd->dcl); + qemu_console_set_display_gl_ctx(con, &ssd->dgc); } register_displaychangelistener(&ssd->dcl); } From f6ef71bded95d99106d4541cf1f420376818732e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 15 Feb 2021 15:10:36 +0400 Subject: [PATCH 017/730] ui: move qemu_spice_fill_device_address to ui/util.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Other backends can use it. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- hw/display/qxl.c | 7 +++- include/ui/console.h | 6 +++ include/ui/spice-display.h | 4 -- ui/meson.build | 1 + ui/spice-core.c | 50 ------------------------- ui/spice-display.c | 5 ++- ui/util.c | 75 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 92 insertions(+), 56 deletions(-) create mode 100644 ui/util.c diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 29c80b4289..e2d6e317da 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -2171,12 +2171,17 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp) } #if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */ + Error *err = NULL; char device_address[256] = ""; - if (qemu_spice_fill_device_address(qxl->vga.con, device_address, 256)) { + if (qemu_console_fill_device_address(qxl->vga.con, + device_address, sizeof(device_address), + &err)) { spice_qxl_set_device_info(&qxl->ssd.qxl, device_address, 0, qxl->max_outputs); + } else { + error_report_err(err); } #endif diff --git a/include/ui/console.h b/include/ui/console.h index fe08b4dd04..eefd7e4dc1 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -495,4 +495,10 @@ int index_from_key(const char *key, size_t key_length); int udmabuf_fd(void); #endif +/* util.c */ +bool qemu_console_fill_device_address(QemuConsole *con, + char *device_address, + size_t size, + Error **errp); + #endif diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index a2fbf62c52..e271e011da 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -184,8 +184,4 @@ void qemu_spice_display_start(void); void qemu_spice_display_stop(void); int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd); -bool qemu_spice_fill_device_address(QemuConsole *con, - char *device_address, - size_t size); - #endif diff --git a/ui/meson.build b/ui/meson.build index ee8ef27714..a9df5b911e 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -12,6 +12,7 @@ softmmu_ss.add(files( 'kbd-state.c', 'keymaps.c', 'qemu-pixman.c', + 'util.c', )) softmmu_ss.add([spice_headers, files('spice-module.c')]) softmmu_ss.add(when: spice_protocol, if_true: files('vdagent.c')) diff --git a/ui/spice-core.c b/ui/spice-core.c index 31974b8d6c..c3ac20ad43 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -884,56 +884,6 @@ bool qemu_spice_have_display_interface(QemuConsole *con) return false; } -/* - * Recursively (in reverse order) appends addresses of PCI devices as it moves - * up in the PCI hierarchy. - * - * @returns true on success, false when the buffer wasn't large enough - */ -static bool append_pci_address(char *buf, size_t buf_size, const PCIDevice *pci) -{ - PCIBus *bus = pci_get_bus(pci); - /* - * equivalent to if (!pci_bus_is_root(bus)), but the function is not built - * with PCI_CONFIG=n, avoid using an #ifdef by checking directly - */ - if (bus->parent_dev != NULL) { - append_pci_address(buf, buf_size, bus->parent_dev); - } - - size_t len = strlen(buf); - ssize_t written = snprintf(buf + len, buf_size - len, "/%02x.%x", - PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn)); - - return written > 0 && written < buf_size - len; -} - -bool qemu_spice_fill_device_address(QemuConsole *con, - char *device_address, - size_t size) -{ - DeviceState *dev = DEVICE(object_property_get_link(OBJECT(con), - "device", - &error_abort)); - PCIDevice *pci = (PCIDevice *) object_dynamic_cast(OBJECT(dev), - TYPE_PCI_DEVICE); - - if (pci == NULL) { - warn_report("Setting device address of a display device to SPICE: " - "Not a PCI device."); - return false; - } - - strncpy(device_address, "pci/0000", size); - if (!append_pci_address(device_address, size, pci)) { - warn_report("Setting device address of a display device to SPICE: " - "Too many PCI devices in the chain."); - return false; - } - - return true; -} - int qemu_spice_add_display_interface(QXLInstance *qxlin, QemuConsole *con) { if (g_slist_find(spice_consoles, con)) { diff --git a/ui/spice-display.c b/ui/spice-display.c index 798e0f6167..1043f47f94 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -1148,12 +1148,15 @@ static void qemu_spice_display_init_one(QemuConsole *con) qemu_spice_add_display_interface(&ssd->qxl, con); #if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */ + Error *err = NULL; char device_address[256] = ""; - if (qemu_spice_fill_device_address(con, device_address, 256)) { + if (qemu_console_fill_device_address(con, device_address, 256, &err)) { spice_qxl_set_device_info(&ssd->qxl, device_address, qemu_console_get_head(con), 1); + } else { + error_report_err(err); } #endif diff --git a/ui/util.c b/ui/util.c new file mode 100644 index 0000000000..7e8fc1ea53 --- /dev/null +++ b/ui/util.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2021 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "qemu/osdep.h" + +#include "hw/pci/pci.h" +#include "hw/pci/pci_bus.h" +#include "qapi/error.h" +#include "ui/console.h" + +/* + * Recursively (in reverse order) appends addresses of PCI devices as it moves + * up in the PCI hierarchy. + * + * @returns true on success, false when the buffer wasn't large enough + */ +static bool append_pci_address(char *buf, size_t buf_size, const PCIDevice *pci) +{ + PCIBus *bus = pci_get_bus(pci); + /* + * equivalent to if (!pci_bus_is_root(bus)), but the function is not built + * with PCI_CONFIG=n, avoid using an #ifdef by checking directly + */ + if (bus->parent_dev != NULL) { + append_pci_address(buf, buf_size, bus->parent_dev); + } + + size_t len = strlen(buf); + ssize_t written = snprintf(buf + len, buf_size - len, "/%02x.%x", + PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn)); + + return written > 0 && written < buf_size - len; +} + +bool qemu_console_fill_device_address(QemuConsole *con, + char *device_address, + size_t size, + Error **errp) +{ + ERRP_GUARD(); + DeviceState *dev = DEVICE(object_property_get_link(OBJECT(con), + "device", + &error_abort)); + PCIDevice *pci = (PCIDevice *) object_dynamic_cast(OBJECT(dev), + TYPE_PCI_DEVICE); + + if (pci == NULL) { + error_setg(errp, "Setting device address of a display device: " + "Not a PCI device."); + return false; + } + + strncpy(device_address, "pci/0000", size); + if (!append_pci_address(device_address, size, pci)) { + error_setg(errp, "Setting device address of a display device: " + "Too many PCI devices in the chain."); + return false; + } + + return true; +} From ebced091854517f063c46ce8e522ebc45e9bccdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sat, 20 Feb 2021 16:23:03 +0400 Subject: [PATCH 018/730] console: save current scanout details MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new DisplayScanout structure to save the current scanout details. This allows to attach later UI backends and set the scanout. Introduce displaychangelistener_display_console() helper function to handle the dpy_gfx_switch/gl_scanout() & dpy_gfx_update() calls. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- include/ui/console.h | 27 +++++++ ui/console.c | 165 +++++++++++++++++++++++++++++-------------- 2 files changed, 138 insertions(+), 54 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index eefd7e4dc1..f590819880 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -108,6 +108,17 @@ struct QemuConsoleClass { #define QEMU_ALLOCATED_FLAG 0x01 #define QEMU_PLACEHOLDER_FLAG 0x02 +typedef struct ScanoutTexture { + uint32_t backing_id; + bool backing_y_0_top; + uint32_t backing_width; + uint32_t backing_height; + uint32_t x; + uint32_t y; + uint32_t width; + uint32_t height; +} ScanoutTexture; + typedef struct DisplaySurface { pixman_format_code_t format; pixman_image_t *image; @@ -178,6 +189,22 @@ typedef struct QemuDmaBuf { bool draw_submitted; } QemuDmaBuf; +enum display_scanout { + SCANOUT_NONE, + SCANOUT_SURFACE, + SCANOUT_TEXTURE, + SCANOUT_DMABUF, +}; + +typedef struct DisplayScanout { + enum display_scanout kind; + union { + /* DisplaySurface *surface; is kept in QemuConsole */ + ScanoutTexture texture; + QemuDmaBuf *dmabuf; + }; +} DisplayScanout; + typedef struct DisplayState DisplayState; typedef struct DisplayGLCtx DisplayGLCtx; diff --git a/ui/console.c b/ui/console.c index 78583df920..40eebb6d2c 100644 --- a/ui/console.c +++ b/ui/console.c @@ -77,6 +77,7 @@ struct QemuConsole { console_type_t console_type; DisplayState *ds; DisplaySurface *surface; + DisplayScanout scanout; int dcls; DisplayGLCtx *gl; int gl_block; @@ -146,6 +147,7 @@ static void dpy_refresh(DisplayState *s); static DisplayState *get_alloc_displaystate(void); static void text_console_update_cursor_timer(void); static void text_console_update_cursor(void *opaque); +static bool displaychangelistener_has_dmabuf(DisplayChangeListener *dcl); static void gui_update(void *opaque) { @@ -481,6 +483,8 @@ static void text_console_resize(QemuConsole *s) TextCell *cells, *c, *c1; int w1, x, y, last_width; + assert(s->scanout.kind == SCANOUT_SURFACE); + last_width = s->width; s->width = surface_width(s->surface) / FONT_WIDTH; s->height = surface_height(s->surface) / FONT_HEIGHT; @@ -1052,6 +1056,48 @@ static void console_putchar(QemuConsole *s, int ch) } } +static void displaychangelistener_display_console(DisplayChangeListener *dcl, + QemuConsole *con) +{ + static const char nodev[] = + "This VM has no graphic display device."; + static DisplaySurface *dummy; + + if (!con) { + if (!dcl->ops->dpy_gfx_switch) { + return; + } + if (!dummy) { + dummy = qemu_create_placeholder_surface(640, 480, nodev); + } + dcl->ops->dpy_gfx_switch(dcl, dummy); + return; + } + + if (con->scanout.kind == SCANOUT_DMABUF && + displaychangelistener_has_dmabuf(dcl)) { + dcl->ops->dpy_gl_scanout_dmabuf(dcl, con->scanout.dmabuf); + } else if (con->scanout.kind == SCANOUT_TEXTURE && + dcl->ops->dpy_gl_scanout_texture) { + dcl->ops->dpy_gl_scanout_texture(dcl, + con->scanout.texture.backing_id, + con->scanout.texture.backing_y_0_top, + con->scanout.texture.backing_width, + con->scanout.texture.backing_height, + con->scanout.texture.x, + con->scanout.texture.y, + con->scanout.texture.width, + con->scanout.texture.height); + } else if (con->scanout.kind == SCANOUT_SURFACE && + dcl->ops->dpy_gfx_switch) { + dcl->ops->dpy_gfx_switch(dcl, con->surface); + } + + dcl->ops->dpy_gfx_update(dcl, 0, 0, + qemu_console_get_width(con, 0), + qemu_console_get_height(con, 0)); +} + void console_select(unsigned int index) { DisplayChangeListener *dcl; @@ -1068,13 +1114,7 @@ void console_select(unsigned int index) if (dcl->con != NULL) { continue; } - if (dcl->ops->dpy_gfx_switch) { - dcl->ops->dpy_gfx_switch(dcl, s->surface); - } - } - if (s->surface) { - dpy_gfx_update(s, 0, 0, surface_width(s->surface), - surface_height(s->surface)); + displaychangelistener_display_console(dcl, s); } } if (ds->have_text) { @@ -1480,9 +1520,6 @@ static bool dpy_gl_compatible_with(QemuConsole *con, DisplayChangeListener *dcl) void register_displaychangelistener(DisplayChangeListener *dcl) { - static const char nodev[] = - "This VM has no graphic display device."; - static DisplaySurface *dummy; QemuConsole *con; assert(!dcl->ds); @@ -1507,16 +1544,7 @@ void register_displaychangelistener(DisplayChangeListener *dcl) } else { con = active_console; } - if (dcl->ops->dpy_gfx_switch) { - if (con) { - dcl->ops->dpy_gfx_switch(dcl, con->surface); - } else { - if (!dummy) { - dummy = qemu_create_placeholder_surface(640, 480, nodev); - } - dcl->ops->dpy_gfx_switch(dcl, dummy); - } - } + displaychangelistener_display_console(dcl, con); text_console_update_cursor(NULL); } @@ -1597,13 +1625,9 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h) { DisplayState *s = con->ds; DisplayChangeListener *dcl; - int width = w; - int height = h; + int width = qemu_console_get_width(con, x + w); + int height = qemu_console_get_height(con, y + h); - if (con->surface) { - width = surface_width(con->surface); - height = surface_height(con->surface); - } x = MAX(x, 0); y = MAX(y, 0); x = MIN(x, width); @@ -1626,12 +1650,10 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h) void dpy_gfx_update_full(QemuConsole *con) { - if (!con->surface) { - return; - } - dpy_gfx_update(con, 0, 0, - surface_width(con->surface), - surface_height(con->surface)); + int w = qemu_console_get_width(con, 0); + int h = qemu_console_get_height(con, 0); + + dpy_gfx_update(con, 0, 0, w, h); } void dpy_gfx_replace_surface(QemuConsole *con, @@ -1658,6 +1680,7 @@ void dpy_gfx_replace_surface(QemuConsole *con, assert(old_surface != surface); + con->scanout.kind = SCANOUT_SURFACE; con->surface = surface; QLIST_FOREACH(dcl, &s->listeners, next) { if (con != (dcl->con ? dcl->con : active_console)) { @@ -1833,6 +1856,9 @@ void dpy_gl_scanout_disable(QemuConsole *con) DisplayState *s = con->ds; DisplayChangeListener *dcl; + if (con->scanout.kind != SCANOUT_SURFACE) { + con->scanout.kind = SCANOUT_NONE; + } QLIST_FOREACH(dcl, &s->listeners, next) { dcl->ops->dpy_gl_scanout_disable(dcl); } @@ -1849,6 +1875,11 @@ void dpy_gl_scanout_texture(QemuConsole *con, DisplayState *s = con->ds; DisplayChangeListener *dcl; + con->scanout.kind = SCANOUT_TEXTURE; + con->scanout.texture = (ScanoutTexture) { + backing_id, backing_y_0_top, backing_width, backing_height, + x, y, width, height + }; QLIST_FOREACH(dcl, &s->listeners, next) { dcl->ops->dpy_gl_scanout_texture(dcl, backing_id, backing_y_0_top, @@ -1863,6 +1894,8 @@ void dpy_gl_scanout_dmabuf(QemuConsole *con, DisplayState *s = con->ds; DisplayChangeListener *dcl; + con->scanout.kind = SCANOUT_DMABUF; + con->scanout.dmabuf = dmabuf; QLIST_FOREACH(dcl, &s->listeners, next) { dcl->ops->dpy_gl_scanout_dmabuf(dcl, dmabuf); } @@ -1989,10 +2022,8 @@ QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head, s = qemu_console_lookup_unused(); if (s) { trace_console_gfx_reuse(s->index); - if (s->surface) { - width = surface_width(s->surface); - height = surface_height(s->surface); - } + width = qemu_console_get_width(s, 0); + height = qemu_console_get_height(s, 0); } else { trace_console_gfx_new(); s = new_console(ds, GRAPHIC_CONSOLE, head); @@ -2021,13 +2052,8 @@ void graphic_console_close(QemuConsole *con) static const char unplugged[] = "Guest display has been unplugged"; DisplaySurface *surface; - int width = 640; - int height = 480; - - if (con->surface) { - width = surface_width(con->surface); - height = surface_height(con->surface); - } + int width = qemu_console_get_width(con, 640); + int height = qemu_console_get_height(con, 480); trace_console_gfx_close(con->index); object_property_set_link(OBJECT(con), "device", NULL, &error_abort); @@ -2179,7 +2205,19 @@ int qemu_console_get_width(QemuConsole *con, int fallback) if (con == NULL) { con = active_console; } - return con ? surface_width(con->surface) : fallback; + if (con == NULL) { + return fallback; + } + switch (con->scanout.kind) { + case SCANOUT_DMABUF: + return con->scanout.dmabuf->width; + case SCANOUT_TEXTURE: + return con->scanout.texture.width; + case SCANOUT_SURFACE: + return surface_width(con->surface); + default: + return fallback; + } } int qemu_console_get_height(QemuConsole *con, int fallback) @@ -2187,7 +2225,19 @@ int qemu_console_get_height(QemuConsole *con, int fallback) if (con == NULL) { con = active_console; } - return con ? surface_height(con->surface) : fallback; + if (con == NULL) { + return fallback; + } + switch (con->scanout.kind) { + case SCANOUT_DMABUF: + return con->scanout.dmabuf->height; + case SCANOUT_TEXTURE: + return con->scanout.texture.height; + case SCANOUT_SURFACE: + return surface_height(con->surface); + default: + return fallback; + } } static void vc_chr_accept_input(Chardev *chr) @@ -2253,12 +2303,13 @@ static void text_console_do_init(Chardev *chr, DisplayState *ds) s->total_height = DEFAULT_BACKSCROLL; s->x = 0; s->y = 0; - if (!s->surface) { - if (active_console && active_console->surface) { - g_width = surface_width(active_console->surface); - g_height = surface_height(active_console->surface); + if (s->scanout.kind != SCANOUT_SURFACE) { + if (active_console && active_console->scanout.kind == SCANOUT_SURFACE) { + g_width = qemu_console_get_width(active_console, g_width); + g_height = qemu_console_get_height(active_console, g_height); } s->surface = qemu_create_displaysurface(g_width, g_height); + s->scanout.kind = SCANOUT_SURFACE; } s->hw_ops = &text_console_ops; @@ -2317,6 +2368,7 @@ static void vc_chr_open(Chardev *chr, s = new_console(NULL, TEXT_CONSOLE, 0); } else { s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE, 0); + s->scanout.kind = SCANOUT_SURFACE; s->surface = qemu_create_displaysurface(width, height); } @@ -2340,13 +2392,13 @@ static void vc_chr_open(Chardev *chr, void qemu_console_resize(QemuConsole *s, int width, int height) { - DisplaySurface *surface; + DisplaySurface *surface = qemu_console_surface(s); assert(s->console_type == GRAPHIC_CONSOLE); - if (s->surface && (s->surface->flags & QEMU_ALLOCATED_FLAG) && - pixman_image_get_width(s->surface->image) == width && - pixman_image_get_height(s->surface->image) == height) { + if (surface && (surface->flags & QEMU_ALLOCATED_FLAG) && + pixman_image_get_width(surface->image) == width && + pixman_image_get_height(surface->image) == height) { return; } @@ -2356,7 +2408,12 @@ void qemu_console_resize(QemuConsole *s, int width, int height) DisplaySurface *qemu_console_surface(QemuConsole *console) { - return console->surface; + switch (console->scanout.kind) { + case SCANOUT_SURFACE: + return console->surface; + default: + return NULL; + } } PixelFormat qemu_default_pixelformat(int bpp) From 20f19713ef5a33bd9074bb87aea004c08a27be7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 15 Jul 2021 11:54:13 +0400 Subject: [PATCH 019/730] scripts: teach modinfo to skip non-C sources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- scripts/modinfo-collect.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/modinfo-collect.py b/scripts/modinfo-collect.py index 4acb188c3e..61b90688c6 100755 --- a/scripts/modinfo-collect.py +++ b/scripts/modinfo-collect.py @@ -51,6 +51,9 @@ def main(args): with open('compile_commands.json') as f: compile_commands = json.load(f) for src in args: + if not src.endswith('.c'): + print("MODINFO_DEBUG skip %s" % src) + continue print("MODINFO_DEBUG src %s" % src) command = find_command(src, target, compile_commands) cmdline = process_command(src, command) From 2668dc7b5d9f56d8c3e6d2876c526fddc7068eca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 6 Oct 2021 01:00:35 +0400 Subject: [PATCH 020/730] docs/sphinx: add sphinx modules to include D-Bus documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new dbus-doc directive to import D-Bus interfaces documentation from the introspection XML. The comments annotations follow the gtkdoc/kerneldoc style, and should be formatted with reST. Note: I realize after the fact that I was implementing those modules with sphinx 4, and that we have much lower requirements. Instead of lowering the features and code (removing type annotations etc), let's have a warning in the documentation when the D-Bus modules can't be used, and point to the source XML file in that case. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- docs/conf.py | 8 + docs/sphinx/dbusdoc.py | 166 +++++++++++++++ docs/sphinx/dbusdomain.py | 406 +++++++++++++++++++++++++++++++++++++ docs/sphinx/dbusparser.py | 373 ++++++++++++++++++++++++++++++++++ docs/sphinx/fakedbusdoc.py | 25 +++ 5 files changed, 978 insertions(+) create mode 100644 docs/sphinx/dbusdoc.py create mode 100644 docs/sphinx/dbusdomain.py create mode 100644 docs/sphinx/dbusparser.py create mode 100644 docs/sphinx/fakedbusdoc.py diff --git a/docs/conf.py b/docs/conf.py index 763e7d2434..e79015975e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -73,6 +73,12 @@ needs_sphinx = '1.6' # ones. extensions = ['kerneldoc', 'qmp_lexer', 'hxtool', 'depfile', 'qapidoc'] +if sphinx.version_info[:3] > (4, 0, 0): + tags.add('sphinx4') + extensions += ['dbusdoc'] +else: + extensions += ['fakedbusdoc'] + # Add any paths that contain templates here, relative to this directory. templates_path = [os.path.join(qemu_docdir, '_templates')] @@ -311,3 +317,5 @@ kerneldoc_bin = ['perl', os.path.join(qemu_docdir, '../scripts/kernel-doc')] kerneldoc_srctree = os.path.join(qemu_docdir, '..') hxtool_srctree = os.path.join(qemu_docdir, '..') qapidoc_srctree = os.path.join(qemu_docdir, '..') +dbusdoc_srctree = os.path.join(qemu_docdir, '..') +dbus_index_common_prefix = ["org.qemu."] diff --git a/docs/sphinx/dbusdoc.py b/docs/sphinx/dbusdoc.py new file mode 100644 index 0000000000..be284ed08f --- /dev/null +++ b/docs/sphinx/dbusdoc.py @@ -0,0 +1,166 @@ +# D-Bus XML documentation extension +# +# Copyright (C) 2021, Red Hat Inc. +# +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Author: Marc-André Lureau +"""dbus-doc is a Sphinx extension that provides documentation from D-Bus XML.""" + +import os +import re +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Dict, + Iterator, + List, + Optional, + Sequence, + Set, + Tuple, + Type, + TypeVar, + Union, +) + +import sphinx +from docutils import nodes +from docutils.nodes import Element, Node +from docutils.parsers.rst import Directive, directives +from docutils.parsers.rst.states import RSTState +from docutils.statemachine import StringList, ViewList +from sphinx.application import Sphinx +from sphinx.errors import ExtensionError +from sphinx.util import logging +from sphinx.util.docstrings import prepare_docstring +from sphinx.util.docutils import SphinxDirective, switch_source_input +from sphinx.util.nodes import nested_parse_with_titles + +import dbusdomain +from dbusparser import parse_dbus_xml + +logger = logging.getLogger(__name__) + +__version__ = "1.0" + + +class DBusDoc: + def __init__(self, sphinx_directive, dbusfile): + self._cur_doc = None + self._sphinx_directive = sphinx_directive + self._dbusfile = dbusfile + self._top_node = nodes.section() + self.result = StringList() + self.indent = "" + + def add_line(self, line: str, *lineno: int) -> None: + """Append one line of generated reST to the output.""" + if line.strip(): # not a blank line + self.result.append(self.indent + line, self._dbusfile, *lineno) + else: + self.result.append("", self._dbusfile, *lineno) + + def add_method(self, method): + self.add_line(f".. dbus:method:: {method.name}") + self.add_line("") + self.indent += " " + for arg in method.in_args: + self.add_line(f":arg {arg.signature} {arg.name}: {arg.doc_string}") + for arg in method.out_args: + self.add_line(f":ret {arg.signature} {arg.name}: {arg.doc_string}") + self.add_line("") + for line in prepare_docstring("\n" + method.doc_string): + self.add_line(line) + self.indent = self.indent[:-3] + + def add_signal(self, signal): + self.add_line(f".. dbus:signal:: {signal.name}") + self.add_line("") + self.indent += " " + for arg in signal.args: + self.add_line(f":arg {arg.signature} {arg.name}: {arg.doc_string}") + self.add_line("") + for line in prepare_docstring("\n" + signal.doc_string): + self.add_line(line) + self.indent = self.indent[:-3] + + def add_property(self, prop): + self.add_line(f".. dbus:property:: {prop.name}") + self.indent += " " + self.add_line(f":type: {prop.signature}") + access = {"read": "readonly", "write": "writeonly", "readwrite": "readwrite"}[ + prop.access + ] + self.add_line(f":{access}:") + if prop.emits_changed_signal: + self.add_line(f":emits-changed: yes") + self.add_line("") + for line in prepare_docstring("\n" + prop.doc_string): + self.add_line(line) + self.indent = self.indent[:-3] + + def add_interface(self, iface): + self.add_line(f".. dbus:interface:: {iface.name}") + self.add_line("") + self.indent += " " + for line in prepare_docstring("\n" + iface.doc_string): + self.add_line(line) + for method in iface.methods: + self.add_method(method) + for sig in iface.signals: + self.add_signal(sig) + for prop in iface.properties: + self.add_property(prop) + self.indent = self.indent[:-3] + + +def parse_generated_content(state: RSTState, content: StringList) -> List[Node]: + """Parse a generated content by Documenter.""" + with switch_source_input(state, content): + node = nodes.paragraph() + node.document = state.document + state.nested_parse(content, 0, node) + + return node.children + + +class DBusDocDirective(SphinxDirective): + """Extract documentation from the specified D-Bus XML file""" + + has_content = True + required_arguments = 1 + optional_arguments = 0 + final_argument_whitespace = True + + def run(self): + reporter = self.state.document.reporter + + try: + source, lineno = reporter.get_source_and_line(self.lineno) # type: ignore + except AttributeError: + source, lineno = (None, None) + + logger.debug("[dbusdoc] %s:%s: input:\n%s", source, lineno, self.block_text) + + env = self.state.document.settings.env + dbusfile = env.config.qapidoc_srctree + "/" + self.arguments[0] + with open(dbusfile, "rb") as f: + xml_data = f.read() + xml = parse_dbus_xml(xml_data) + doc = DBusDoc(self, dbusfile) + for iface in xml: + doc.add_interface(iface) + + result = parse_generated_content(self.state, doc.result) + return result + + +def setup(app: Sphinx) -> Dict[str, Any]: + """Register dbus-doc directive with Sphinx""" + app.add_config_value("dbusdoc_srctree", None, "env") + app.add_directive("dbus-doc", DBusDocDirective) + dbusdomain.setup(app) + + return dict(version=__version__, parallel_read_safe=True, parallel_write_safe=True) diff --git a/docs/sphinx/dbusdomain.py b/docs/sphinx/dbusdomain.py new file mode 100644 index 0000000000..2ea95af623 --- /dev/null +++ b/docs/sphinx/dbusdomain.py @@ -0,0 +1,406 @@ +# D-Bus sphinx domain extension +# +# Copyright (C) 2021, Red Hat Inc. +# +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Author: Marc-André Lureau + +from typing import ( + Any, + Dict, + Iterable, + Iterator, + List, + NamedTuple, + Optional, + Tuple, + cast, +) + +from docutils import nodes +from docutils.nodes import Element, Node +from docutils.parsers.rst import directives +from sphinx import addnodes +from sphinx.addnodes import desc_signature, pending_xref +from sphinx.directives import ObjectDescription +from sphinx.domains import Domain, Index, IndexEntry, ObjType +from sphinx.locale import _ +from sphinx.roles import XRefRole +from sphinx.util import nodes as node_utils +from sphinx.util.docfields import Field, TypedField +from sphinx.util.typing import OptionSpec + + +class DBusDescription(ObjectDescription[str]): + """Base class for DBus objects""" + + option_spec: OptionSpec = ObjectDescription.option_spec.copy() + option_spec.update( + { + "deprecated": directives.flag, + } + ) + + def get_index_text(self, modname: str, name: str) -> str: + """Return the text for the index entry of the object.""" + raise NotImplementedError("must be implemented in subclasses") + + def add_target_and_index( + self, name: str, sig: str, signode: desc_signature + ) -> None: + ifacename = self.env.ref_context.get("dbus:interface") + node_id = name + if ifacename: + node_id = f"{ifacename}.{node_id}" + + signode["names"].append(name) + signode["ids"].append(node_id) + + if "noindexentry" not in self.options: + indextext = self.get_index_text(ifacename, name) + if indextext: + self.indexnode["entries"].append( + ("single", indextext, node_id, "", None) + ) + + domain = cast(DBusDomain, self.env.get_domain("dbus")) + domain.note_object(name, self.objtype, node_id, location=signode) + + +class DBusInterface(DBusDescription): + """ + Implementation of ``dbus:interface``. + """ + + def get_index_text(self, ifacename: str, name: str) -> str: + return ifacename + + def before_content(self) -> None: + self.env.ref_context["dbus:interface"] = self.arguments[0] + + def after_content(self) -> None: + self.env.ref_context.pop("dbus:interface") + + def handle_signature(self, sig: str, signode: desc_signature) -> str: + signode += addnodes.desc_annotation("interface ", "interface ") + signode += addnodes.desc_name(sig, sig) + return sig + + def run(self) -> List[Node]: + _, node = super().run() + name = self.arguments[0] + section = nodes.section(ids=[name + "-section"]) + section += nodes.title(name, "%s interface" % name) + section += node + return [self.indexnode, section] + + +class DBusMember(DBusDescription): + + signal = False + + +class DBusMethod(DBusMember): + """ + Implementation of ``dbus:method``. + """ + + option_spec: OptionSpec = DBusMember.option_spec.copy() + option_spec.update( + { + "noreply": directives.flag, + } + ) + + doc_field_types: List[Field] = [ + TypedField( + "arg", + label=_("Arguments"), + names=("arg",), + rolename="arg", + typerolename=None, + typenames=("argtype", "type"), + ), + TypedField( + "ret", + label=_("Returns"), + names=("ret",), + rolename="ret", + typerolename=None, + typenames=("rettype", "type"), + ), + ] + + def get_index_text(self, ifacename: str, name: str) -> str: + return _("%s() (%s method)") % (name, ifacename) + + def handle_signature(self, sig: str, signode: desc_signature) -> str: + params = addnodes.desc_parameterlist() + returns = addnodes.desc_parameterlist() + + contentnode = addnodes.desc_content() + self.state.nested_parse(self.content, self.content_offset, contentnode) + for child in contentnode: + if isinstance(child, nodes.field_list): + for field in child: + ty, sg, name = field[0].astext().split(None, 2) + param = addnodes.desc_parameter() + param += addnodes.desc_sig_keyword_type(sg, sg) + param += addnodes.desc_sig_space() + param += addnodes.desc_sig_name(name, name) + if ty == "arg": + params += param + elif ty == "ret": + returns += param + + anno = "signal " if self.signal else "method " + signode += addnodes.desc_annotation(anno, anno) + signode += addnodes.desc_name(sig, sig) + signode += params + if not self.signal and "noreply" not in self.options: + ret = addnodes.desc_returns() + ret += returns + signode += ret + + return sig + + +class DBusSignal(DBusMethod): + """ + Implementation of ``dbus:signal``. + """ + + doc_field_types: List[Field] = [ + TypedField( + "arg", + label=_("Arguments"), + names=("arg",), + rolename="arg", + typerolename=None, + typenames=("argtype", "type"), + ), + ] + signal = True + + def get_index_text(self, ifacename: str, name: str) -> str: + return _("%s() (%s signal)") % (name, ifacename) + + +class DBusProperty(DBusMember): + """ + Implementation of ``dbus:property``. + """ + + option_spec: OptionSpec = DBusMember.option_spec.copy() + option_spec.update( + { + "type": directives.unchanged, + "readonly": directives.flag, + "writeonly": directives.flag, + "readwrite": directives.flag, + "emits-changed": directives.unchanged, + } + ) + + doc_field_types: List[Field] = [] + + def get_index_text(self, ifacename: str, name: str) -> str: + return _("%s (%s property)") % (name, ifacename) + + def transform_content(self, contentnode: addnodes.desc_content) -> None: + fieldlist = nodes.field_list() + access = None + if "readonly" in self.options: + access = _("read-only") + if "writeonly" in self.options: + access = _("write-only") + if "readwrite" in self.options: + access = _("read & write") + if access: + content = nodes.Text(access) + fieldname = nodes.field_name("", _("Access")) + fieldbody = nodes.field_body("", nodes.paragraph("", "", content)) + field = nodes.field("", fieldname, fieldbody) + fieldlist += field + emits = self.options.get("emits-changed", None) + if emits: + content = nodes.Text(emits) + fieldname = nodes.field_name("", _("Emits Changed")) + fieldbody = nodes.field_body("", nodes.paragraph("", "", content)) + field = nodes.field("", fieldname, fieldbody) + fieldlist += field + if len(fieldlist) > 0: + contentnode.insert(0, fieldlist) + + def handle_signature(self, sig: str, signode: desc_signature) -> str: + contentnode = addnodes.desc_content() + self.state.nested_parse(self.content, self.content_offset, contentnode) + ty = self.options.get("type") + + signode += addnodes.desc_annotation("property ", "property ") + signode += addnodes.desc_name(sig, sig) + signode += addnodes.desc_sig_punctuation("", ":") + signode += addnodes.desc_sig_keyword_type(ty, ty) + return sig + + def run(self) -> List[Node]: + self.name = "dbus:member" + return super().run() + + +class DBusXRef(XRefRole): + def process_link(self, env, refnode, has_explicit_title, title, target): + refnode["dbus:interface"] = env.ref_context.get("dbus:interface") + if not has_explicit_title: + title = title.lstrip(".") # only has a meaning for the target + target = target.lstrip("~") # only has a meaning for the title + # if the first character is a tilde, don't display the module/class + # parts of the contents + if title[0:1] == "~": + title = title[1:] + dot = title.rfind(".") + if dot != -1: + title = title[dot + 1 :] + # if the first character is a dot, search more specific namespaces first + # else search builtins first + if target[0:1] == ".": + target = target[1:] + refnode["refspecific"] = True + return title, target + + +class DBusIndex(Index): + """ + Index subclass to provide a D-Bus interfaces index. + """ + + name = "dbusindex" + localname = _("D-Bus Interfaces Index") + shortname = _("dbus") + + def generate( + self, docnames: Iterable[str] = None + ) -> Tuple[List[Tuple[str, List[IndexEntry]]], bool]: + content: Dict[str, List[IndexEntry]] = {} + # list of prefixes to ignore + ignores: List[str] = self.domain.env.config["dbus_index_common_prefix"] + ignores = sorted(ignores, key=len, reverse=True) + + ifaces = sorted( + [ + x + for x in self.domain.data["objects"].items() + if x[1].objtype == "interface" + ], + key=lambda x: x[0].lower(), + ) + for name, (docname, node_id, _) in ifaces: + if docnames and docname not in docnames: + continue + + for ignore in ignores: + if name.startswith(ignore): + name = name[len(ignore) :] + stripped = ignore + break + else: + stripped = "" + + entries = content.setdefault(name[0].lower(), []) + entries.append(IndexEntry(stripped + name, 0, docname, node_id, "", "", "")) + + # sort by first letter + sorted_content = sorted(content.items()) + + return sorted_content, False + + +class ObjectEntry(NamedTuple): + docname: str + node_id: str + objtype: str + + +class DBusDomain(Domain): + """ + Implementation of the D-Bus domain. + """ + + name = "dbus" + label = "D-Bus" + object_types: Dict[str, ObjType] = { + "interface": ObjType(_("interface"), "iface", "obj"), + "method": ObjType(_("method"), "meth", "obj"), + "signal": ObjType(_("signal"), "sig", "obj"), + "property": ObjType(_("property"), "attr", "_prop", "obj"), + } + directives = { + "interface": DBusInterface, + "method": DBusMethod, + "signal": DBusSignal, + "property": DBusProperty, + } + roles = { + "iface": DBusXRef(), + "meth": DBusXRef(), + "sig": DBusXRef(), + "prop": DBusXRef(), + } + initial_data: Dict[str, Dict[str, Tuple[Any]]] = { + "objects": {}, # fullname -> ObjectEntry + } + indices = [ + DBusIndex, + ] + + @property + def objects(self) -> Dict[str, ObjectEntry]: + return self.data.setdefault("objects", {}) # fullname -> ObjectEntry + + def note_object( + self, name: str, objtype: str, node_id: str, location: Any = None + ) -> None: + self.objects[name] = ObjectEntry(self.env.docname, node_id, objtype) + + def clear_doc(self, docname: str) -> None: + for fullname, obj in list(self.objects.items()): + if obj.docname == docname: + del self.objects[fullname] + + def find_obj(self, typ: str, name: str) -> Optional[Tuple[str, ObjectEntry]]: + # skip parens + if name[-2:] == "()": + name = name[:-2] + if typ in ("meth", "sig", "prop"): + try: + ifacename, name = name.rsplit(".", 1) + except ValueError: + pass + return self.objects.get(name) + + def resolve_xref( + self, + env: "BuildEnvironment", + fromdocname: str, + builder: "Builder", + typ: str, + target: str, + node: pending_xref, + contnode: Element, + ) -> Optional[Element]: + """Resolve the pending_xref *node* with the given *typ* and *target*.""" + objdef = self.find_obj(typ, target) + if objdef: + return node_utils.make_refnode( + builder, fromdocname, objdef.docname, objdef.node_id, contnode + ) + + def get_objects(self) -> Iterator[Tuple[str, str, str, str, str, int]]: + for refname, obj in self.objects.items(): + yield (refname, refname, obj.objtype, obj.docname, obj.node_id, 1) + + +def setup(app): + app.add_domain(DBusDomain) + app.add_config_value("dbus_index_common_prefix", [], "env") diff --git a/docs/sphinx/dbusparser.py b/docs/sphinx/dbusparser.py new file mode 100644 index 0000000000..024553eae7 --- /dev/null +++ b/docs/sphinx/dbusparser.py @@ -0,0 +1,373 @@ +# Based from "GDBus - GLib D-Bus Library": +# +# Copyright (C) 2008-2011 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General +# Public License along with this library; if not, see . +# +# Author: David Zeuthen + +import xml.parsers.expat + + +class Annotation: + def __init__(self, key, value): + self.key = key + self.value = value + self.annotations = [] + self.since = "" + + +class Arg: + def __init__(self, name, signature): + self.name = name + self.signature = signature + self.annotations = [] + self.doc_string = "" + self.since = "" + + +class Method: + def __init__(self, name, h_type_implies_unix_fd=True): + self.name = name + self.h_type_implies_unix_fd = h_type_implies_unix_fd + self.in_args = [] + self.out_args = [] + self.annotations = [] + self.doc_string = "" + self.since = "" + self.deprecated = False + self.unix_fd = False + + +class Signal: + def __init__(self, name): + self.name = name + self.args = [] + self.annotations = [] + self.doc_string = "" + self.since = "" + self.deprecated = False + + +class Property: + def __init__(self, name, signature, access): + self.name = name + self.signature = signature + self.access = access + self.annotations = [] + self.arg = Arg("value", self.signature) + self.arg.annotations = self.annotations + self.readable = False + self.writable = False + if self.access == "readwrite": + self.readable = True + self.writable = True + elif self.access == "read": + self.readable = True + elif self.access == "write": + self.writable = True + else: + raise ValueError('Invalid access type "{}"'.format(self.access)) + self.doc_string = "" + self.since = "" + self.deprecated = False + self.emits_changed_signal = True + + +class Interface: + def __init__(self, name): + self.name = name + self.methods = [] + self.signals = [] + self.properties = [] + self.annotations = [] + self.doc_string = "" + self.doc_string_brief = "" + self.since = "" + self.deprecated = False + + +class DBusXMLParser: + STATE_TOP = "top" + STATE_NODE = "node" + STATE_INTERFACE = "interface" + STATE_METHOD = "method" + STATE_SIGNAL = "signal" + STATE_PROPERTY = "property" + STATE_ARG = "arg" + STATE_ANNOTATION = "annotation" + STATE_IGNORED = "ignored" + + def __init__(self, xml_data, h_type_implies_unix_fd=True): + self._parser = xml.parsers.expat.ParserCreate() + self._parser.CommentHandler = self.handle_comment + self._parser.CharacterDataHandler = self.handle_char_data + self._parser.StartElementHandler = self.handle_start_element + self._parser.EndElementHandler = self.handle_end_element + + self.parsed_interfaces = [] + self._cur_object = None + + self.state = DBusXMLParser.STATE_TOP + self.state_stack = [] + self._cur_object = None + self._cur_object_stack = [] + + self.doc_comment_last_symbol = "" + + self._h_type_implies_unix_fd = h_type_implies_unix_fd + + self._parser.Parse(xml_data) + + COMMENT_STATE_BEGIN = "begin" + COMMENT_STATE_PARAMS = "params" + COMMENT_STATE_BODY = "body" + COMMENT_STATE_SKIP = "skip" + + def handle_comment(self, data): + comment_state = DBusXMLParser.COMMENT_STATE_BEGIN + lines = data.split("\n") + symbol = "" + body = "" + in_para = False + params = {} + for line in lines: + orig_line = line + line = line.lstrip() + if comment_state == DBusXMLParser.COMMENT_STATE_BEGIN: + if len(line) > 0: + colon_index = line.find(": ") + if colon_index == -1: + if line.endswith(":"): + symbol = line[0 : len(line) - 1] + comment_state = DBusXMLParser.COMMENT_STATE_PARAMS + else: + comment_state = DBusXMLParser.COMMENT_STATE_SKIP + else: + symbol = line[0:colon_index] + rest_of_line = line[colon_index + 2 :].strip() + if len(rest_of_line) > 0: + body += rest_of_line + "\n" + comment_state = DBusXMLParser.COMMENT_STATE_PARAMS + elif comment_state == DBusXMLParser.COMMENT_STATE_PARAMS: + if line.startswith("@"): + colon_index = line.find(": ") + if colon_index == -1: + comment_state = DBusXMLParser.COMMENT_STATE_BODY + if not in_para: + in_para = True + body += orig_line + "\n" + else: + param = line[1:colon_index] + docs = line[colon_index + 2 :] + params[param] = docs + else: + comment_state = DBusXMLParser.COMMENT_STATE_BODY + if len(line) > 0: + if not in_para: + in_para = True + body += orig_line + "\n" + elif comment_state == DBusXMLParser.COMMENT_STATE_BODY: + if len(line) > 0: + if not in_para: + in_para = True + body += orig_line + "\n" + else: + if in_para: + body += "\n" + in_para = False + if in_para: + body += "\n" + + if symbol != "": + self.doc_comment_last_symbol = symbol + self.doc_comment_params = params + self.doc_comment_body = body + + def handle_char_data(self, data): + # print 'char_data=%s'%data + pass + + def handle_start_element(self, name, attrs): + old_state = self.state + old_cur_object = self._cur_object + if self.state == DBusXMLParser.STATE_IGNORED: + self.state = DBusXMLParser.STATE_IGNORED + elif self.state == DBusXMLParser.STATE_TOP: + if name == DBusXMLParser.STATE_NODE: + self.state = DBusXMLParser.STATE_NODE + else: + self.state = DBusXMLParser.STATE_IGNORED + elif self.state == DBusXMLParser.STATE_NODE: + if name == DBusXMLParser.STATE_INTERFACE: + self.state = DBusXMLParser.STATE_INTERFACE + iface = Interface(attrs["name"]) + self._cur_object = iface + self.parsed_interfaces.append(iface) + elif name == DBusXMLParser.STATE_ANNOTATION: + self.state = DBusXMLParser.STATE_ANNOTATION + anno = Annotation(attrs["name"], attrs["value"]) + self._cur_object.annotations.append(anno) + self._cur_object = anno + else: + self.state = DBusXMLParser.STATE_IGNORED + + # assign docs, if any + if "name" in attrs and self.doc_comment_last_symbol == attrs["name"]: + self._cur_object.doc_string = self.doc_comment_body + if "short_description" in self.doc_comment_params: + short_description = self.doc_comment_params["short_description"] + self._cur_object.doc_string_brief = short_description + if "since" in self.doc_comment_params: + self._cur_object.since = self.doc_comment_params["since"].strip() + + elif self.state == DBusXMLParser.STATE_INTERFACE: + if name == DBusXMLParser.STATE_METHOD: + self.state = DBusXMLParser.STATE_METHOD + method = Method( + attrs["name"], h_type_implies_unix_fd=self._h_type_implies_unix_fd + ) + self._cur_object.methods.append(method) + self._cur_object = method + elif name == DBusXMLParser.STATE_SIGNAL: + self.state = DBusXMLParser.STATE_SIGNAL + signal = Signal(attrs["name"]) + self._cur_object.signals.append(signal) + self._cur_object = signal + elif name == DBusXMLParser.STATE_PROPERTY: + self.state = DBusXMLParser.STATE_PROPERTY + prop = Property(attrs["name"], attrs["type"], attrs["access"]) + self._cur_object.properties.append(prop) + self._cur_object = prop + elif name == DBusXMLParser.STATE_ANNOTATION: + self.state = DBusXMLParser.STATE_ANNOTATION + anno = Annotation(attrs["name"], attrs["value"]) + self._cur_object.annotations.append(anno) + self._cur_object = anno + else: + self.state = DBusXMLParser.STATE_IGNORED + + # assign docs, if any + if "name" in attrs and self.doc_comment_last_symbol == attrs["name"]: + self._cur_object.doc_string = self.doc_comment_body + if "since" in self.doc_comment_params: + self._cur_object.since = self.doc_comment_params["since"].strip() + + elif self.state == DBusXMLParser.STATE_METHOD: + if name == DBusXMLParser.STATE_ARG: + self.state = DBusXMLParser.STATE_ARG + arg_name = None + if "name" in attrs: + arg_name = attrs["name"] + arg = Arg(arg_name, attrs["type"]) + direction = attrs.get("direction", "in") + if direction == "in": + self._cur_object.in_args.append(arg) + elif direction == "out": + self._cur_object.out_args.append(arg) + else: + raise ValueError('Invalid direction "{}"'.format(direction)) + self._cur_object = arg + elif name == DBusXMLParser.STATE_ANNOTATION: + self.state = DBusXMLParser.STATE_ANNOTATION + anno = Annotation(attrs["name"], attrs["value"]) + self._cur_object.annotations.append(anno) + self._cur_object = anno + else: + self.state = DBusXMLParser.STATE_IGNORED + + # assign docs, if any + if self.doc_comment_last_symbol == old_cur_object.name: + if "name" in attrs and attrs["name"] in self.doc_comment_params: + doc_string = self.doc_comment_params[attrs["name"]] + if doc_string is not None: + self._cur_object.doc_string = doc_string + if "since" in self.doc_comment_params: + self._cur_object.since = self.doc_comment_params[ + "since" + ].strip() + + elif self.state == DBusXMLParser.STATE_SIGNAL: + if name == DBusXMLParser.STATE_ARG: + self.state = DBusXMLParser.STATE_ARG + arg_name = None + if "name" in attrs: + arg_name = attrs["name"] + arg = Arg(arg_name, attrs["type"]) + self._cur_object.args.append(arg) + self._cur_object = arg + elif name == DBusXMLParser.STATE_ANNOTATION: + self.state = DBusXMLParser.STATE_ANNOTATION + anno = Annotation(attrs["name"], attrs["value"]) + self._cur_object.annotations.append(anno) + self._cur_object = anno + else: + self.state = DBusXMLParser.STATE_IGNORED + + # assign docs, if any + if self.doc_comment_last_symbol == old_cur_object.name: + if "name" in attrs and attrs["name"] in self.doc_comment_params: + doc_string = self.doc_comment_params[attrs["name"]] + if doc_string is not None: + self._cur_object.doc_string = doc_string + if "since" in self.doc_comment_params: + self._cur_object.since = self.doc_comment_params[ + "since" + ].strip() + + elif self.state == DBusXMLParser.STATE_PROPERTY: + if name == DBusXMLParser.STATE_ANNOTATION: + self.state = DBusXMLParser.STATE_ANNOTATION + anno = Annotation(attrs["name"], attrs["value"]) + self._cur_object.annotations.append(anno) + self._cur_object = anno + else: + self.state = DBusXMLParser.STATE_IGNORED + + elif self.state == DBusXMLParser.STATE_ARG: + if name == DBusXMLParser.STATE_ANNOTATION: + self.state = DBusXMLParser.STATE_ANNOTATION + anno = Annotation(attrs["name"], attrs["value"]) + self._cur_object.annotations.append(anno) + self._cur_object = anno + else: + self.state = DBusXMLParser.STATE_IGNORED + + elif self.state == DBusXMLParser.STATE_ANNOTATION: + if name == DBusXMLParser.STATE_ANNOTATION: + self.state = DBusXMLParser.STATE_ANNOTATION + anno = Annotation(attrs["name"], attrs["value"]) + self._cur_object.annotations.append(anno) + self._cur_object = anno + else: + self.state = DBusXMLParser.STATE_IGNORED + + else: + raise ValueError( + 'Unhandled state "{}" while entering element with name "{}"'.format( + self.state, name + ) + ) + + self.state_stack.append(old_state) + self._cur_object_stack.append(old_cur_object) + + def handle_end_element(self, name): + self.state = self.state_stack.pop() + self._cur_object = self._cur_object_stack.pop() + + +def parse_dbus_xml(xml_data): + parser = DBusXMLParser(xml_data, True) + return parser.parsed_interfaces diff --git a/docs/sphinx/fakedbusdoc.py b/docs/sphinx/fakedbusdoc.py new file mode 100644 index 0000000000..a680b25754 --- /dev/null +++ b/docs/sphinx/fakedbusdoc.py @@ -0,0 +1,25 @@ +# D-Bus XML documentation extension, compatibility gunk for +"""dbus-doc is a Sphinx extension that provides documentation from D-Bus XML.""" + +from sphinx.application import Sphinx +from sphinx.util.docutils import SphinxDirective +from typing import Any, Dict + + +class FakeDBusDocDirective(SphinxDirective): + has_content = True + required_arguments = 1 + + def run(self): + return [] + + +def setup(app: Sphinx) -> Dict[str, Any]: + """Register a fake dbus-doc directive with Sphinx""" + app.add_directive("dbus-doc", FakeDBusDocDirective) From 61534882e796961b0723f2bb220bdc01388eb1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 6 Oct 2021 01:18:42 +0400 Subject: [PATCH 021/730] backends: move dbus-vmstate1.xml to backends/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although not used by the backend itself, use a common location for documentation and sharing purposes. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- {tests/qtest => backends}/dbus-vmstate1.xml | 0 tests/qtest/meson.build | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename {tests/qtest => backends}/dbus-vmstate1.xml (100%) diff --git a/tests/qtest/dbus-vmstate1.xml b/backends/dbus-vmstate1.xml similarity index 100% rename from tests/qtest/dbus-vmstate1.xml rename to backends/dbus-vmstate1.xml diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index ebeac59b3f..913e987409 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -98,7 +98,7 @@ if dbus_daemon.found() and config_host.has_key('GDBUS_CODEGEN') #qtests_i386 += ['dbus-vmstate-test'] dbus_vmstate1 = custom_target('dbus-vmstate description', output: ['dbus-vmstate1.h', 'dbus-vmstate1.c'], - input: files('dbus-vmstate1.xml'), + input: meson.source_root() / 'backends/dbus-vmstate1.xml', command: [config_host['GDBUS_CODEGEN'], '@INPUT@', '--interface-prefix', 'org.qemu', From d2f25776ca4044ce4f19a4065cc0e4d2566f32ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 6 Oct 2021 01:35:29 +0400 Subject: [PATCH 022/730] docs: move D-Bus VMState documentation to source XML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the source XML document as single reference, importing its documentation via the dbus-doc directive. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- backends/dbus-vmstate1.xml | 42 +++++++++++++++++++++++++++- docs/interop/dbus-vmstate.rst | 52 ++++++----------------------------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/backends/dbus-vmstate1.xml b/backends/dbus-vmstate1.xml index cc8563be4c..601ee8dc7e 100644 --- a/backends/dbus-vmstate1.xml +++ b/backends/dbus-vmstate1.xml @@ -1,10 +1,50 @@ - + + + + + + + + diff --git a/docs/interop/dbus-vmstate.rst b/docs/interop/dbus-vmstate.rst index 1d719c1c60..5fb3f279e2 100644 --- a/docs/interop/dbus-vmstate.rst +++ b/docs/interop/dbus-vmstate.rst @@ -2,9 +2,6 @@ D-Bus VMState ============= -Introduction -============ - The QEMU dbus-vmstate object's aim is to migrate helpers' data running on a QEMU D-Bus bus. (refer to the :doc:`dbus` document for some recommendations on D-Bus usage) @@ -26,49 +23,16 @@ dbus-vmstate object can be configured with the expected list of helpers by setting its ``id-list`` property, with a comma-separated ``Id`` list. -Interface -========= +.. only:: sphinx4 -On object path ``/org/qemu/VMState1``, the following -``org.qemu.VMState1`` interface should be implemented: + .. dbus-doc:: backends/dbus-vmstate1.xml -.. code:: xml +.. only:: not sphinx4 - - - - - - - - - + .. warning:: + Sphinx 4 is required to build D-Bus documentation. -"Id" property -------------- + This is the content of ``backends/dbus-vmstate1.xml``: -A string that identifies the helper uniquely. (maximum 256 bytes -including terminating NUL byte) - -.. note:: - - The helper ID namespace is a separate namespace. In particular, it is not - related to QEMU "id" used in -object/-device objects. - -Load(in u8[] bytes) method --------------------------- - -The method called on destination with the state to restore. - -The helper may be initially started in a waiting state (with -an --incoming argument for example), and it may resume on success. - -An error may be returned to the caller. - -Save(out u8[] bytes) method ---------------------------- - -The method called on the source to get the current state to be -migrated. The helper should continue to run normally. - -An error may be returned to the caller. + .. literalinclude:: ../../backends/dbus-vmstate1.xml + :language: xml From ef20c5ba0805a8f16fa86c62fb07d01cac6a2216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 6 Oct 2021 01:41:01 +0400 Subject: [PATCH 023/730] docs: add dbus-display documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wire up the dbus-display documentation. The interface and feature is implemented next. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- docs/interop/dbus-display.rst | 31 +++++++++++++++++++++++++++++++ docs/interop/dbus.rst | 2 ++ docs/interop/index.rst | 1 + ui/dbus-display1.xml | 0 4 files changed, 34 insertions(+) create mode 100644 docs/interop/dbus-display.rst create mode 100644 ui/dbus-display1.xml diff --git a/docs/interop/dbus-display.rst b/docs/interop/dbus-display.rst new file mode 100644 index 0000000000..8c6e8e0f5a --- /dev/null +++ b/docs/interop/dbus-display.rst @@ -0,0 +1,31 @@ +D-Bus display +============= + +QEMU can export the VM display through D-Bus (when started with ``-display +dbus``), to allow out-of-process UIs, remote protocol servers or other +interactive display usages. + +Various specialized D-Bus interfaces are available on different object paths +under ``/org/qemu/Display1/``, depending on the VM configuration. + +QEMU also implements the standard interfaces, such as +`org.freedesktop.DBus.Introspectable +`_. + +.. contents:: + :local: + :depth: 1 + +.. only:: sphinx4 + + .. dbus-doc:: ui/dbus-display1.xml + +.. only:: not sphinx4 + + .. warning:: + Sphinx 4 is required to build D-Bus documentation. + + This is the content of ``ui/dbus-display1.xml``: + + .. literalinclude:: ../../ui/dbus-display1.xml + :language: xml diff --git a/docs/interop/dbus.rst b/docs/interop/dbus.rst index be596d3f41..427debc9c5 100644 --- a/docs/interop/dbus.rst +++ b/docs/interop/dbus.rst @@ -108,3 +108,5 @@ QEMU Interfaces =============== :doc:`dbus-vmstate` + +:doc:`dbus-display` diff --git a/docs/interop/index.rst b/docs/interop/index.rst index 47b9ed82bb..c59bac9834 100644 --- a/docs/interop/index.rst +++ b/docs/interop/index.rst @@ -12,6 +12,7 @@ are useful for making QEMU interoperate with other software. bitmaps dbus dbus-vmstate + dbus-display live-block-operations pr-helper qemu-ga diff --git a/ui/dbus-display1.xml b/ui/dbus-display1.xml new file mode 100644 index 0000000000..e69de29bb2 From d83acfd013ada96f3c5fe216f8b3648f0d311a4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sat, 9 Oct 2021 17:37:40 +0400 Subject: [PATCH 024/730] build-sys: set glib dependency version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Further meson configuration tests are to be added based on the glib version. Also correct the version reporting in the config log. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann Reviewed-by: Philippe Mathieu-Daudé --- configure | 1 + meson.build | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 8ccfe51673..51eae49daf 100755 --- a/configure +++ b/configure @@ -3694,6 +3694,7 @@ echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak echo "QEMU_CXXFLAGS=$QEMU_CXXFLAGS" >> $config_host_mak echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak echo "GLIB_LIBS=$glib_libs" >> $config_host_mak +echo "GLIB_VERSION=$(pkg-config --modversion glib-2.0)" >> $config_host_mak echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak echo "LD_I386_EMULATION=$ld_i386_emulation" >> $config_host_mak echo "EXESUF=$EXESUF" >> $config_host_mak diff --git a/meson.build b/meson.build index 1c70839bbf..c37eb92ebe 100644 --- a/meson.build +++ b/meson.build @@ -404,14 +404,16 @@ endif add_project_arguments(config_host['GLIB_CFLAGS'].split(), native: false, language: ['c', 'cpp', 'objc']) glib = declare_dependency(compile_args: config_host['GLIB_CFLAGS'].split(), - link_args: config_host['GLIB_LIBS'].split()) + link_args: config_host['GLIB_LIBS'].split(), + version: config_host['GLIB_VERSION']) # override glib dep with the configure results (for subprojects) meson.override_dependency('glib-2.0', glib) gio = not_found if 'CONFIG_GIO' in config_host gio = declare_dependency(compile_args: config_host['GIO_CFLAGS'].split(), - link_args: config_host['GIO_LIBS'].split()) + link_args: config_host['GIO_LIBS'].split(), + version: config_host['GLIB_VERSION']) endif lttng = not_found if 'ust' in get_option('trace_backends') From 142ca628a733d0f523ad2b6713a22945e505f061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 15 Jul 2021 11:53:53 +0400 Subject: [PATCH 025/730] ui: add a D-Bus display backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "dbus" display backend exports the QEMU consoles and other UI-related interfaces over D-Bus. By default, the connection is established on the session bus, but you can specify a different bus with the "addr" option. The backend takes the "org.qemu" service name, while still allowing further instances to queue on the same name (so you can lookup all the available instances too). It accepts any number of clients at this point, although this is expected to evolve with options to restrict clients, or only accept p2p via fd passing. The interface is intentionally very close to the internal QEMU API, and can be introspected or interacted with busctl/dfeet etc: $ ./qemu-system-x86_64 -name MyVM -display dbus $ busctl --user introspect org.qemu /org/qemu/Display1/Console_0 org.qemu.Display1.Console interface - - - .RegisterListener method h - - .SetUIInfo method qqiiuu - - .DeviceAddress property s "pci/0000/01.0" emits-change .Head property u 0 emits-change .Height property u 480 emits-change .Label property s "VGA" emits-change .Type property s "Graphic" emits-change .Width property u 640 emits-change [...] See the interfaces XML source file and Sphinx docs for the generated API documentations. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- include/qemu/dbus.h | 19 ++ meson.build | 11 + meson_options.txt | 2 + qapi/ui.json | 27 +- qemu-options.hx | 15 + scripts/meson-buildoptions.sh | 3 + ui/dbus-console.c | 497 ++++++++++++++++++++++++++++++++++ ui/dbus-display1.xml | 378 ++++++++++++++++++++++++++ ui/dbus-error.c | 48 ++++ ui/dbus-listener.c | 486 +++++++++++++++++++++++++++++++++ ui/dbus.c | 262 ++++++++++++++++++ ui/dbus.h | 83 ++++++ ui/meson.build | 22 ++ ui/trace-events | 11 + 14 files changed, 1862 insertions(+), 2 deletions(-) create mode 100644 ui/dbus-console.c create mode 100644 ui/dbus-error.c create mode 100644 ui/dbus-listener.c create mode 100644 ui/dbus.c create mode 100644 ui/dbus.h diff --git a/include/qemu/dbus.h b/include/qemu/dbus.h index 9d591f9ee4..c0cbb1ca44 100644 --- a/include/qemu/dbus.h +++ b/include/qemu/dbus.h @@ -12,6 +12,25 @@ #include +/* glib/gio 2.68 */ +#define DBUS_METHOD_INVOCATION_HANDLED TRUE +#define DBUS_METHOD_INVOCATION_UNHANDLED FALSE + +/* in msec */ +#define DBUS_DEFAULT_TIMEOUT 1000 + +#define DBUS_DISPLAY1_ROOT "/org/qemu/Display1" + +#define DBUS_DISPLAY_ERROR (dbus_display_error_quark()) +GQuark dbus_display_error_quark(void); + +typedef enum { + DBUS_DISPLAY_ERROR_FAILED, + DBUS_DISPLAY_ERROR_INVALID, + DBUS_DISPLAY_ERROR_UNSUPPORTED, + DBUS_DISPLAY_N_ERRORS, +} DBusDisplayError; + GStrv qemu_dbus_get_queued_owners(GDBusConnection *connection, const char *name, Error **errp); diff --git a/meson.build b/meson.build index c37eb92ebe..73d4b241df 100644 --- a/meson.build +++ b/meson.build @@ -1397,6 +1397,15 @@ endif have_host_block_device = (targetos != 'darwin' or cc.has_header('IOKit/storage/IOMedia.h')) +dbus_display = false +if not get_option('dbus_display').disabled() + # FIXME enable_modules shouldn't be necessary, but: https://github.com/mesonbuild/meson/issues/8333 + dbus_display = gio.version().version_compare('>=2.64') and config_host.has_key('GDBUS_CODEGEN') and enable_modules + if get_option('dbus_display').enabled() and not dbus_display + error('Requirements missing to enable -display dbus (glib>=2.64 && --enable-modules)') + endif +endif + have_virtfs = (targetos == 'linux' and have_system and libattr.found() and @@ -1506,6 +1515,7 @@ config_host_data.set('CONFIG_SPICE_PROTOCOL_MICRO', spice_protocol.version().spl endif config_host_data.set('CONFIG_SPICE', spice.found()) config_host_data.set('CONFIG_X11', x11.found()) +config_host_data.set('CONFIG_DBUS_DISPLAY', dbus_display) config_host_data.set('CONFIG_CFI', get_option('cfi')) config_host_data.set('CONFIG_SELINUX', selinux.found()) config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version())) @@ -3229,6 +3239,7 @@ summary_info += {'Trace backends': ','.join(get_option('trace_backends'))} if 'simple' in get_option('trace_backends') summary_info += {'Trace output file': get_option('trace_file') + '-'} endif +summary_info += {'D-Bus display': dbus_display} summary_info += {'QOM debugging': config_host.has_key('CONFIG_QOM_CAST_DEBUG')} summary_info += {'vhost-kernel support': config_host.has_key('CONFIG_VHOST_KERNEL')} summary_info += {'vhost-net support': config_host.has_key('CONFIG_VHOST_NET')} diff --git a/meson_options.txt b/meson_options.txt index 4114bfcaa4..921967eddb 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -66,6 +66,8 @@ option('cfi_debug', type: 'boolean', value: 'false', description: 'Verbose errors in case of CFI violation') option('multiprocess', type: 'feature', value: 'auto', description: 'Out of process device emulation support') +option('dbus_display', type: 'feature', value: 'auto', + description: '-display dbus support') option('attr', type : 'feature', value : 'auto', description: 'attr/xattr support') diff --git a/qapi/ui.json b/qapi/ui.json index d7567ac866..80855328b1 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1121,6 +1121,23 @@ { 'struct' : 'DisplayEGLHeadless', 'data' : { '*rendernode' : 'str' } } +## +# @DisplayDBus: +# +# DBus display options. +# +# @addr: The D-Bus bus address (default to the session bus). +# +# @rendernode: Which DRM render node should be used. Default is the first +# available node on the host. +# +# Since: 7.0 +# +## +{ 'struct' : 'DisplayDBus', + 'data' : { '*rendernode' : 'str', + '*addr': 'str' } } + ## # @DisplayGLMode: # @@ -1186,6 +1203,8 @@ # application to connect to it. The server will redirect # the serial console and QEMU monitors. (Since 4.0) # +# @dbus: Start a D-Bus service for the display. (Since 7.0) +# # Since: 2.12 # ## @@ -1199,7 +1218,10 @@ 'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } }, { 'name': 'curses', 'if': 'CONFIG_CURSES' }, { 'name': 'cocoa', 'if': 'CONFIG_COCOA' }, - { 'name': 'spice-app', 'if': 'CONFIG_SPICE'} ] } + { 'name': 'spice-app', 'if': 'CONFIG_SPICE' }, + { 'name': 'dbus', 'if': 'CONFIG_DBUS_DISPLAY' } + ] +} ## # @DisplayOptions: @@ -1227,7 +1249,8 @@ 'gtk': { 'type': 'DisplayGTK', 'if': 'CONFIG_GTK' }, 'curses': { 'type': 'DisplayCurses', 'if': 'CONFIG_CURSES' }, 'egl-headless': { 'type': 'DisplayEGLHeadless', - 'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } } + 'if': { 'all': ['CONFIG_OPENGL', 'CONFIG_GBM'] } }, + 'dbus': { 'type': 'DisplayDBus', 'if': 'CONFIG_DBUS_DISPLAY' } } } diff --git a/qemu-options.hx b/qemu-options.hx index 489b58e151..38983a919b 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1862,6 +1862,10 @@ DEF("display", HAS_ARG, QEMU_OPTION_display, #endif #if defined(CONFIG_OPENGL) "-display egl-headless[,rendernode=]\n" +#endif +#if defined(CONFIG_DBUS_DISPLAY) + "-display dbus[,addr=]\n" + " [,gl=on|core|es|off][,rendernode=]\n" #endif "-display none\n" " select display backend type\n" @@ -1889,6 +1893,17 @@ SRST application. The Spice server will redirect the serial consoles and QEMU monitors. (Since 4.0) + ``dbus`` + Export the display over D-Bus interfaces. (Since 7.0) + + The connection is registered with the "org.qemu" name (and queued when + already owned). + + ``addr=`` : D-Bus bus address to connect to. + + ``gl=on|off|core|es`` : Use OpenGL for rendering (the D-interface will + share framebuffers with DMABUF file descriptors). + ``sdl`` Display video output via SDL (usually in a separate graphics window; see the SDL documentation for other possibilities). diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index ae8f18edc2..50bd7bed4d 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -33,6 +33,7 @@ meson_options_help() { printf "%s\n" ' coreaudio CoreAudio sound support' printf "%s\n" ' curl CURL block device driver' printf "%s\n" ' curses curses UI' + printf "%s\n" ' dbus-display -display dbus support' printf "%s\n" ' docs Documentations build support' printf "%s\n" ' dsound DirectSound sound support' printf "%s\n" ' fuse FUSE block device export' @@ -131,6 +132,8 @@ _meson_option_parse() { --disable-curl) printf "%s" -Dcurl=disabled ;; --enable-curses) printf "%s" -Dcurses=enabled ;; --disable-curses) printf "%s" -Dcurses=disabled ;; + --enable-dbus-display) printf "%s" -Ddbus_display=enabled ;; + --disable-dbus-display) printf "%s" -Ddbus_display=disabled ;; --enable-docs) printf "%s" -Ddocs=enabled ;; --disable-docs) printf "%s" -Ddocs=disabled ;; --enable-dsound) printf "%s" -Ddsound=enabled ;; diff --git a/ui/dbus-console.c b/ui/dbus-console.c new file mode 100644 index 0000000000..1ccf638c10 --- /dev/null +++ b/ui/dbus-console.c @@ -0,0 +1,497 @@ +/* + * QEMU DBus display console + * + * Copyright (c) 2021 Marc-André Lureau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "ui/input.h" +#include "ui/kbd-state.h" +#include "trace.h" + +#include + +#include "dbus.h" + +struct _DBusDisplayConsole { + GDBusObjectSkeleton parent_instance; + DisplayChangeListener dcl; + + DBusDisplay *display; + QemuConsole *con; + GHashTable *listeners; + QemuDBusDisplay1Console *iface; + + QemuDBusDisplay1Keyboard *iface_kbd; + QKbdState *kbd; + + QemuDBusDisplay1Mouse *iface_mouse; + gboolean last_set; + guint last_x; + guint last_y; + Notifier mouse_mode_notifier; +}; + +G_DEFINE_TYPE(DBusDisplayConsole, + dbus_display_console, + G_TYPE_DBUS_OBJECT_SKELETON) + +static void +dbus_display_console_set_size(DBusDisplayConsole *ddc, + uint32_t width, uint32_t height) +{ + g_object_set(ddc->iface, + "width", width, + "height", height, + NULL); +} + +static void +dbus_gfx_switch(DisplayChangeListener *dcl, + struct DisplaySurface *new_surface) +{ + DBusDisplayConsole *ddc = container_of(dcl, DBusDisplayConsole, dcl); + + dbus_display_console_set_size(ddc, + surface_width(new_surface), + surface_height(new_surface)); +} + +static void +dbus_gfx_update(DisplayChangeListener *dcl, + int x, int y, int w, int h) +{ +} + +static void +dbus_gl_scanout_disable(DisplayChangeListener *dcl) +{ +} + +static void +dbus_gl_scanout_texture(DisplayChangeListener *dcl, + uint32_t tex_id, + bool backing_y_0_top, + uint32_t backing_width, + uint32_t backing_height, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h) +{ + DBusDisplayConsole *ddc = container_of(dcl, DBusDisplayConsole, dcl); + + dbus_display_console_set_size(ddc, w, h); +} + +static void +dbus_gl_scanout_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf) +{ + DBusDisplayConsole *ddc = container_of(dcl, DBusDisplayConsole, dcl); + + dbus_display_console_set_size(ddc, + dmabuf->width, + dmabuf->height); +} + +static void +dbus_gl_scanout_update(DisplayChangeListener *dcl, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h) +{ +} + +static const DisplayChangeListenerOps dbus_console_dcl_ops = { + .dpy_name = "dbus-console", + .dpy_gfx_switch = dbus_gfx_switch, + .dpy_gfx_update = dbus_gfx_update, + .dpy_gl_scanout_disable = dbus_gl_scanout_disable, + .dpy_gl_scanout_texture = dbus_gl_scanout_texture, + .dpy_gl_scanout_dmabuf = dbus_gl_scanout_dmabuf, + .dpy_gl_update = dbus_gl_scanout_update, +}; + +static void +dbus_display_console_init(DBusDisplayConsole *object) +{ + DBusDisplayConsole *ddc = DBUS_DISPLAY_CONSOLE(object); + + ddc->listeners = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, g_object_unref); + ddc->dcl.ops = &dbus_console_dcl_ops; +} + +static void +dbus_display_console_dispose(GObject *object) +{ + DBusDisplayConsole *ddc = DBUS_DISPLAY_CONSOLE(object); + + unregister_displaychangelistener(&ddc->dcl); + g_clear_object(&ddc->iface_kbd); + g_clear_object(&ddc->iface); + g_clear_pointer(&ddc->listeners, g_hash_table_unref); + g_clear_pointer(&ddc->kbd, qkbd_state_free); + + G_OBJECT_CLASS(dbus_display_console_parent_class)->dispose(object); +} + +static void +dbus_display_console_class_init(DBusDisplayConsoleClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->dispose = dbus_display_console_dispose; +} + +static void +listener_vanished_cb(DBusDisplayListener *listener) +{ + DBusDisplayConsole *ddc = dbus_display_listener_get_console(listener); + const char *name = dbus_display_listener_get_bus_name(listener); + + trace_dbus_listener_vanished(name); + + g_hash_table_remove(ddc->listeners, name); + qkbd_state_lift_all_keys(ddc->kbd); +} + +static gboolean +dbus_console_set_ui_info(DBusDisplayConsole *ddc, + GDBusMethodInvocation *invocation, + guint16 arg_width_mm, + guint16 arg_height_mm, + gint arg_xoff, + gint arg_yoff, + guint arg_width, + guint arg_height) +{ + QemuUIInfo info = { + .width_mm = arg_width_mm, + .height_mm = arg_height_mm, + .xoff = arg_xoff, + .yoff = arg_yoff, + .width = arg_width, + .height = arg_height, + }; + + if (!dpy_ui_info_supported(ddc->con)) { + g_dbus_method_invocation_return_error(invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_UNSUPPORTED, + "SetUIInfo is not supported"); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + dpy_set_ui_info(ddc->con, &info, false); + qemu_dbus_display1_console_complete_set_uiinfo(ddc->iface, invocation); + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +dbus_console_register_listener(DBusDisplayConsole *ddc, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + GVariant *arg_listener) +{ + const char *sender = g_dbus_method_invocation_get_sender(invocation); + GDBusConnection *listener_conn; + g_autoptr(GError) err = NULL; + g_autoptr(GSocket) socket = NULL; + g_autoptr(GSocketConnection) socket_conn = NULL; + g_autofree char *guid = g_dbus_generate_guid(); + DBusDisplayListener *listener; + int fd; + + if (g_hash_table_contains(ddc->listeners, sender)) { + g_dbus_method_invocation_return_error( + invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_INVALID, + "`%s` is already registered!", + sender); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + fd = g_unix_fd_list_get(fd_list, g_variant_get_handle(arg_listener), &err); + if (err) { + g_dbus_method_invocation_return_error( + invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Couldn't get peer fd: %s", err->message); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + socket = g_socket_new_from_fd(fd, &err); + if (err) { + g_dbus_method_invocation_return_error( + invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Couldn't make a socket: %s", err->message); + close(fd); + return DBUS_METHOD_INVOCATION_HANDLED; + } + socket_conn = g_socket_connection_factory_create_connection(socket); + + qemu_dbus_display1_console_complete_register_listener( + ddc->iface, invocation, NULL); + + listener_conn = g_dbus_connection_new_sync( + G_IO_STREAM(socket_conn), + guid, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER, + NULL, NULL, &err); + if (err) { + error_report("Failed to setup peer connection: %s", err->message); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + listener = dbus_display_listener_new(sender, listener_conn, ddc); + if (!listener) { + return DBUS_METHOD_INVOCATION_HANDLED; + } + + g_hash_table_insert(ddc->listeners, + (gpointer)dbus_display_listener_get_bus_name(listener), + listener); + g_object_connect(listener_conn, + "swapped-signal::closed", listener_vanished_cb, listener, + NULL); + + trace_dbus_registered_listener(sender); + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +dbus_kbd_press(DBusDisplayConsole *ddc, + GDBusMethodInvocation *invocation, + guint arg_keycode) +{ + QKeyCode qcode = qemu_input_key_number_to_qcode(arg_keycode); + + trace_dbus_kbd_press(arg_keycode); + + qkbd_state_key_event(ddc->kbd, qcode, true); + + qemu_dbus_display1_keyboard_complete_press(ddc->iface_kbd, invocation); + + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +dbus_kbd_release(DBusDisplayConsole *ddc, + GDBusMethodInvocation *invocation, + guint arg_keycode) +{ + QKeyCode qcode = qemu_input_key_number_to_qcode(arg_keycode); + + trace_dbus_kbd_release(arg_keycode); + + qkbd_state_key_event(ddc->kbd, qcode, false); + + qemu_dbus_display1_keyboard_complete_release(ddc->iface_kbd, invocation); + + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static void +dbus_kbd_qemu_leds_updated(void *data, int ledstate) +{ + DBusDisplayConsole *ddc = DBUS_DISPLAY_CONSOLE(data); + + qemu_dbus_display1_keyboard_set_modifiers(ddc->iface_kbd, ledstate); +} + +static gboolean +dbus_mouse_rel_motion(DBusDisplayConsole *ddc, + GDBusMethodInvocation *invocation, + int dx, int dy) +{ + trace_dbus_mouse_rel_motion(dx, dy); + + if (qemu_input_is_absolute()) { + g_dbus_method_invocation_return_error( + invocation, DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_INVALID, + "Mouse is not relative"); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + qemu_input_queue_rel(ddc->con, INPUT_AXIS_X, dx); + qemu_input_queue_rel(ddc->con, INPUT_AXIS_Y, dy); + qemu_input_event_sync(); + + qemu_dbus_display1_mouse_complete_rel_motion(ddc->iface_mouse, + invocation); + + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +dbus_mouse_set_pos(DBusDisplayConsole *ddc, + GDBusMethodInvocation *invocation, + guint x, guint y) +{ + int width, height; + + trace_dbus_mouse_set_pos(x, y); + + if (!qemu_input_is_absolute()) { + g_dbus_method_invocation_return_error( + invocation, DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_INVALID, + "Mouse is not absolute"); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + width = qemu_console_get_width(ddc->con, 0); + height = qemu_console_get_height(ddc->con, 0); + if (x >= width || y >= height) { + g_dbus_method_invocation_return_error( + invocation, DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_INVALID, + "Invalid mouse position"); + return DBUS_METHOD_INVOCATION_HANDLED; + } + qemu_input_queue_abs(ddc->con, INPUT_AXIS_X, x, 0, width); + qemu_input_queue_abs(ddc->con, INPUT_AXIS_Y, y, 0, height); + qemu_input_event_sync(); + + qemu_dbus_display1_mouse_complete_set_abs_position(ddc->iface_mouse, + invocation); + + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +dbus_mouse_press(DBusDisplayConsole *ddc, + GDBusMethodInvocation *invocation, + guint button) +{ + trace_dbus_mouse_press(button); + + qemu_input_queue_btn(ddc->con, button, true); + qemu_input_event_sync(); + + qemu_dbus_display1_mouse_complete_press(ddc->iface_mouse, invocation); + + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +dbus_mouse_release(DBusDisplayConsole *ddc, + GDBusMethodInvocation *invocation, + guint button) +{ + trace_dbus_mouse_release(button); + + qemu_input_queue_btn(ddc->con, button, false); + qemu_input_event_sync(); + + qemu_dbus_display1_mouse_complete_release(ddc->iface_mouse, invocation); + + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static void +dbus_mouse_mode_change(Notifier *notify, void *data) +{ + DBusDisplayConsole *ddc = + container_of(notify, DBusDisplayConsole, mouse_mode_notifier); + + g_object_set(ddc->iface_mouse, + "is-absolute", qemu_input_is_absolute(), + NULL); +} + +int dbus_display_console_get_index(DBusDisplayConsole *ddc) +{ + return qemu_console_get_index(ddc->con); +} + +DBusDisplayConsole * +dbus_display_console_new(DBusDisplay *display, QemuConsole *con) +{ + g_autofree char *path = NULL; + g_autofree char *label = NULL; + char device_addr[256] = ""; + DBusDisplayConsole *ddc; + int idx; + + assert(display); + assert(con); + + label = qemu_console_get_label(con); + idx = qemu_console_get_index(con); + path = g_strdup_printf(DBUS_DISPLAY1_ROOT "/Console_%d", idx); + ddc = g_object_new(DBUS_DISPLAY_TYPE_CONSOLE, + "g-object-path", path, + NULL); + ddc->display = display; + ddc->con = con; + /* handle errors, and skip non graphics? */ + qemu_console_fill_device_address( + con, device_addr, sizeof(device_addr), NULL); + + ddc->iface = qemu_dbus_display1_console_skeleton_new(); + g_object_set(ddc->iface, + "label", label, + "type", qemu_console_is_graphic(con) ? "Graphic" : "Text", + "head", qemu_console_get_head(con), + "width", qemu_console_get_width(con, 0), + "height", qemu_console_get_height(con, 0), + "device-address", device_addr, + NULL); + g_object_connect(ddc->iface, + "swapped-signal::handle-register-listener", + dbus_console_register_listener, ddc, + "swapped-signal::handle-set-uiinfo", + dbus_console_set_ui_info, ddc, + NULL); + g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(ddc), + G_DBUS_INTERFACE_SKELETON(ddc->iface)); + + ddc->kbd = qkbd_state_init(con); + ddc->iface_kbd = qemu_dbus_display1_keyboard_skeleton_new(); + qemu_add_led_event_handler(dbus_kbd_qemu_leds_updated, ddc); + g_object_connect(ddc->iface_kbd, + "swapped-signal::handle-press", dbus_kbd_press, ddc, + "swapped-signal::handle-release", dbus_kbd_release, ddc, + NULL); + g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(ddc), + G_DBUS_INTERFACE_SKELETON(ddc->iface_kbd)); + + ddc->iface_mouse = qemu_dbus_display1_mouse_skeleton_new(); + g_object_connect(ddc->iface_mouse, + "swapped-signal::handle-set-abs-position", dbus_mouse_set_pos, ddc, + "swapped-signal::handle-rel-motion", dbus_mouse_rel_motion, ddc, + "swapped-signal::handle-press", dbus_mouse_press, ddc, + "swapped-signal::handle-release", dbus_mouse_release, ddc, + NULL); + g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(ddc), + G_DBUS_INTERFACE_SKELETON(ddc->iface_mouse)); + + register_displaychangelistener(&ddc->dcl); + ddc->mouse_mode_notifier.notify = dbus_mouse_mode_change; + qemu_add_mouse_mode_change_notifier(&ddc->mouse_mode_notifier); + + return ddc; +} diff --git a/ui/dbus-display1.xml b/ui/dbus-display1.xml index e69de29bb2..0f0ae92e4d 100644 --- a/ui/dbus-display1.xml +++ b/ui/dbus-display1.xml @@ -0,0 +1,378 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/dbus-error.c b/ui/dbus-error.c new file mode 100644 index 0000000000..85a9194d57 --- /dev/null +++ b/ui/dbus-error.c @@ -0,0 +1,48 @@ +/* + * QEMU DBus display errors + * + * Copyright (c) 2021 Marc-André Lureau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "dbus.h" + +static const GDBusErrorEntry dbus_display_error_entries[] = { + { DBUS_DISPLAY_ERROR_FAILED, "org.qemu.Display1.Error.Failed" }, + { DBUS_DISPLAY_ERROR_INVALID, "org.qemu.Display1.Error.Invalid" }, + { DBUS_DISPLAY_ERROR_UNSUPPORTED, "org.qemu.Display1.Error.Unsupported" }, +}; + +G_STATIC_ASSERT(G_N_ELEMENTS(dbus_display_error_entries) == + DBUS_DISPLAY_N_ERRORS); + +GQuark +dbus_display_error_quark(void) +{ + static gsize quark; + + g_dbus_error_register_error_domain( + "dbus-display-error-quark", + &quark, + dbus_display_error_entries, + G_N_ELEMENTS(dbus_display_error_entries)); + + return (GQuark)quark; +} diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c new file mode 100644 index 0000000000..20094fc18a --- /dev/null +++ b/ui/dbus-listener.c @@ -0,0 +1,486 @@ +/* + * QEMU DBus display console + * + * Copyright (c) 2021 Marc-André Lureau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "sysemu/sysemu.h" +#include "dbus.h" +#include + +#include "ui/shader.h" +#include "ui/egl-helpers.h" +#include "ui/egl-context.h" +#include "trace.h" + +struct _DBusDisplayListener { + GObject parent; + + char *bus_name; + DBusDisplayConsole *console; + GDBusConnection *conn; + + QemuDBusDisplay1Listener *proxy; + + DisplayChangeListener dcl; + DisplaySurface *ds; + QemuGLShader *gls; + int gl_updates; +}; + +G_DEFINE_TYPE(DBusDisplayListener, dbus_display_listener, G_TYPE_OBJECT) + +static void dbus_update_gl_cb(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) err = NULL; + DBusDisplayListener *ddl = user_data; + + if (!qemu_dbus_display1_listener_call_update_dmabuf_finish(ddl->proxy, + res, &err)) { + error_report("Failed to call update: %s", err->message); + } + + graphic_hw_gl_block(ddl->dcl.con, false); + g_object_unref(ddl); +} + +static void dbus_call_update_gl(DBusDisplayListener *ddl, + int x, int y, int w, int h) +{ + graphic_hw_gl_block(ddl->dcl.con, true); + glFlush(); + qemu_dbus_display1_listener_call_update_dmabuf(ddl->proxy, + x, y, w, h, + G_DBUS_CALL_FLAGS_NONE, + DBUS_DEFAULT_TIMEOUT, NULL, + dbus_update_gl_cb, + g_object_ref(ddl)); +} + +static void dbus_scanout_disable(DisplayChangeListener *dcl) +{ + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + + ddl->ds = NULL; + qemu_dbus_display1_listener_call_disable( + ddl->proxy, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); +} + +static void dbus_scanout_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf) +{ + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + g_autoptr(GError) err = NULL; + g_autoptr(GUnixFDList) fd_list = NULL; + + fd_list = g_unix_fd_list_new(); + if (g_unix_fd_list_append(fd_list, dmabuf->fd, &err) != 0) { + error_report("Failed to setup dmabuf fdlist: %s", err->message); + return; + } + + qemu_dbus_display1_listener_call_scanout_dmabuf( + ddl->proxy, + g_variant_new_handle(0), + dmabuf->width, + dmabuf->height, + dmabuf->stride, + dmabuf->fourcc, + dmabuf->modifier, + dmabuf->y0_top, + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + NULL, NULL, NULL); +} + +static void dbus_scanout_texture(DisplayChangeListener *dcl, + uint32_t tex_id, + bool backing_y_0_top, + uint32_t backing_width, + uint32_t backing_height, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h) +{ + QemuDmaBuf dmabuf = { + .width = backing_width, + .height = backing_height, + .y0_top = backing_y_0_top, + }; + + assert(tex_id); + dmabuf.fd = egl_get_fd_for_texture( + tex_id, (EGLint *)&dmabuf.stride, + (EGLint *)&dmabuf.fourcc, + &dmabuf.modifier); + if (dmabuf.fd < 0) { + error_report("%s: failed to get fd for texture", __func__); + return; + } + + dbus_scanout_dmabuf(dcl, &dmabuf); + close(dmabuf.fd); +} + +static void dbus_cursor_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf, bool have_hot, + uint32_t hot_x, uint32_t hot_y) +{ + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + DisplaySurface *ds; + GVariant *v_data = NULL; + egl_fb cursor_fb; + + if (!dmabuf) { + qemu_dbus_display1_listener_call_mouse_set( + ddl->proxy, 0, 0, false, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + return; + } + + egl_dmabuf_import_texture(dmabuf); + if (!dmabuf->texture) { + return; + } + egl_fb_setup_for_tex(&cursor_fb, dmabuf->width, dmabuf->height, + dmabuf->texture, false); + ds = qemu_create_displaysurface(dmabuf->width, dmabuf->height); + egl_fb_read(ds, &cursor_fb); + + v_data = g_variant_new_from_data( + G_VARIANT_TYPE("ay"), + surface_data(ds), + surface_width(ds) * surface_height(ds) * 4, + TRUE, + (GDestroyNotify)qemu_free_displaysurface, + ds); + qemu_dbus_display1_listener_call_cursor_define( + ddl->proxy, + surface_width(ds), + surface_height(ds), + hot_x, + hot_y, + v_data, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL, + NULL); +} + +static void dbus_cursor_position(DisplayChangeListener *dcl, + uint32_t pos_x, uint32_t pos_y) +{ + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + + qemu_dbus_display1_listener_call_mouse_set( + ddl->proxy, pos_x, pos_y, true, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); +} + +static void dbus_release_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf) +{ + dbus_scanout_disable(dcl); +} + +static void dbus_scanout_update(DisplayChangeListener *dcl, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h) +{ + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + + dbus_call_update_gl(ddl, x, y, w, h); +} + +static void dbus_gl_refresh(DisplayChangeListener *dcl) +{ + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + + graphic_hw_update(dcl->con); + + if (!ddl->ds || qemu_console_is_gl_blocked(ddl->dcl.con)) { + return; + } + + if (ddl->gl_updates) { + dbus_call_update_gl(ddl, 0, 0, + surface_width(ddl->ds), surface_height(ddl->ds)); + ddl->gl_updates = 0; + } +} + +static void dbus_refresh(DisplayChangeListener *dcl) +{ + graphic_hw_update(dcl->con); +} + +static void dbus_gl_gfx_update(DisplayChangeListener *dcl, + int x, int y, int w, int h) +{ + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + + if (ddl->ds) { + surface_gl_update_texture(ddl->gls, ddl->ds, x, y, w, h); + } + + ddl->gl_updates++; +} + +static void dbus_gfx_update(DisplayChangeListener *dcl, + int x, int y, int w, int h) +{ + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + pixman_image_t *img; + GVariant *v_data; + size_t stride; + + assert(ddl->ds); + stride = w * DIV_ROUND_UP(PIXMAN_FORMAT_BPP(surface_format(ddl->ds)), 8); + + trace_dbus_update(x, y, w, h); + + /* make a copy, since gvariant only handles linear data */ + img = pixman_image_create_bits(surface_format(ddl->ds), + w, h, NULL, stride); + pixman_image_composite(PIXMAN_OP_SRC, ddl->ds->image, NULL, img, + x, y, 0, 0, 0, 0, w, h); + + v_data = g_variant_new_from_data( + G_VARIANT_TYPE("ay"), + pixman_image_get_data(img), + pixman_image_get_stride(img) * h, + TRUE, + (GDestroyNotify)pixman_image_unref, + img); + qemu_dbus_display1_listener_call_update(ddl->proxy, + x, y, w, h, pixman_image_get_stride(img), pixman_image_get_format(img), + v_data, + G_DBUS_CALL_FLAGS_NONE, + DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL); +} + +static void dbus_gl_gfx_switch(DisplayChangeListener *dcl, + struct DisplaySurface *new_surface) +{ + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + + if (ddl->ds) { + surface_gl_destroy_texture(ddl->gls, ddl->ds); + } + ddl->ds = new_surface; + if (ddl->ds) { + int width = surface_width(ddl->ds); + int height = surface_height(ddl->ds); + + surface_gl_create_texture(ddl->gls, ddl->ds); + /* TODO: lazy send dmabuf (there are unnecessary sent otherwise) */ + dbus_scanout_texture(&ddl->dcl, ddl->ds->texture, false, + width, height, 0, 0, width, height); + } +} + +static void dbus_gfx_switch(DisplayChangeListener *dcl, + struct DisplaySurface *new_surface) +{ + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + GVariant *v_data = NULL; + + ddl->ds = new_surface; + if (!ddl->ds) { + /* why not call disable instead? */ + return; + } + + v_data = g_variant_new_from_data( + G_VARIANT_TYPE("ay"), + surface_data(ddl->ds), + surface_stride(ddl->ds) * surface_height(ddl->ds), + TRUE, + (GDestroyNotify)pixman_image_unref, + pixman_image_ref(ddl->ds->image)); + qemu_dbus_display1_listener_call_scanout(ddl->proxy, + surface_width(ddl->ds), + surface_height(ddl->ds), + surface_stride(ddl->ds), + surface_format(ddl->ds), + v_data, + G_DBUS_CALL_FLAGS_NONE, + DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL); +} + +static void dbus_mouse_set(DisplayChangeListener *dcl, + int x, int y, int on) +{ + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + + qemu_dbus_display1_listener_call_mouse_set( + ddl->proxy, x, y, on, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); +} + +static void dbus_cursor_define(DisplayChangeListener *dcl, + QEMUCursor *c) +{ + DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); + GVariant *v_data = NULL; + + cursor_get(c); + v_data = g_variant_new_from_data( + G_VARIANT_TYPE("ay"), + c->data, + c->width * c->height * 4, + TRUE, + (GDestroyNotify)cursor_put, + c); + + qemu_dbus_display1_listener_call_cursor_define( + ddl->proxy, + c->width, + c->height, + c->hot_x, + c->hot_y, + v_data, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL, + NULL); +} + +const DisplayChangeListenerOps dbus_gl_dcl_ops = { + .dpy_name = "dbus-gl", + .dpy_gfx_update = dbus_gl_gfx_update, + .dpy_gfx_switch = dbus_gl_gfx_switch, + .dpy_gfx_check_format = console_gl_check_format, + .dpy_refresh = dbus_gl_refresh, + .dpy_mouse_set = dbus_mouse_set, + .dpy_cursor_define = dbus_cursor_define, + + .dpy_gl_scanout_disable = dbus_scanout_disable, + .dpy_gl_scanout_texture = dbus_scanout_texture, + .dpy_gl_scanout_dmabuf = dbus_scanout_dmabuf, + .dpy_gl_cursor_dmabuf = dbus_cursor_dmabuf, + .dpy_gl_cursor_position = dbus_cursor_position, + .dpy_gl_release_dmabuf = dbus_release_dmabuf, + .dpy_gl_update = dbus_scanout_update, +}; + +const DisplayChangeListenerOps dbus_dcl_ops = { + .dpy_name = "dbus", + .dpy_gfx_update = dbus_gfx_update, + .dpy_gfx_switch = dbus_gfx_switch, + .dpy_refresh = dbus_refresh, + .dpy_mouse_set = dbus_mouse_set, + .dpy_cursor_define = dbus_cursor_define, +}; + +static void +dbus_display_listener_dispose(GObject *object) +{ + DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(object); + + unregister_displaychangelistener(&ddl->dcl); + g_clear_object(&ddl->conn); + g_clear_pointer(&ddl->bus_name, g_free); + g_clear_object(&ddl->proxy); + g_clear_pointer(&ddl->gls, qemu_gl_fini_shader); + + G_OBJECT_CLASS(dbus_display_listener_parent_class)->dispose(object); +} + +static void +dbus_display_listener_constructed(GObject *object) +{ + DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(object); + + if (display_opengl) { + ddl->gls = qemu_gl_init_shader(); + ddl->dcl.ops = &dbus_gl_dcl_ops; + } else { + ddl->dcl.ops = &dbus_dcl_ops; + } + + G_OBJECT_CLASS(dbus_display_listener_parent_class)->constructed(object); +} + +static void +dbus_display_listener_class_init(DBusDisplayListenerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + object_class->dispose = dbus_display_listener_dispose; + object_class->constructed = dbus_display_listener_constructed; +} + +static void +dbus_display_listener_init(DBusDisplayListener *ddl) +{ +} + +const char * +dbus_display_listener_get_bus_name(DBusDisplayListener *ddl) +{ + return ddl->bus_name; +} + +DBusDisplayConsole * +dbus_display_listener_get_console(DBusDisplayListener *ddl) +{ + return ddl->console; +} + +DBusDisplayListener * +dbus_display_listener_new(const char *bus_name, + GDBusConnection *conn, + DBusDisplayConsole *console) +{ + DBusDisplayListener *ddl; + QemuConsole *con; + g_autoptr(GError) err = NULL; + + ddl = g_object_new(DBUS_DISPLAY_TYPE_LISTENER, NULL); + ddl->proxy = + qemu_dbus_display1_listener_proxy_new_sync(conn, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + "/org/qemu/Display1/Listener", + NULL, + &err); + if (!ddl->proxy) { + error_report("Failed to setup proxy: %s", err->message); + g_object_unref(conn); + g_object_unref(ddl); + return NULL; + } + + ddl->bus_name = g_strdup(bus_name); + ddl->conn = conn; + ddl->console = console; + + con = qemu_console_lookup_by_index(dbus_display_console_get_index(console)); + assert(con); + ddl->dcl.con = con; + register_displaychangelistener(&ddl->dcl); + + return ddl; +} diff --git a/ui/dbus.c b/ui/dbus.c new file mode 100644 index 0000000000..12da8ffe31 --- /dev/null +++ b/ui/dbus.c @@ -0,0 +1,262 @@ +/* + * QEMU DBus display + * + * Copyright (c) 2021 Marc-André Lureau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "qemu/dbus.h" +#include "qemu/option.h" +#include "qom/object_interfaces.h" +#include "sysemu/sysemu.h" +#include "ui/egl-helpers.h" +#include "ui/egl-context.h" +#include "qapi/error.h" +#include "trace.h" + +#include "dbus.h" + +static QEMUGLContext dbus_create_context(DisplayGLCtx *dgc, + QEMUGLParams *params) +{ + eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, + qemu_egl_rn_ctx); + return qemu_egl_create_context(dgc, params); +} + +static const DisplayGLCtxOps dbus_gl_ops = { + .compatible_dcl = &dbus_gl_dcl_ops, + .dpy_gl_ctx_create = dbus_create_context, + .dpy_gl_ctx_destroy = qemu_egl_destroy_context, + .dpy_gl_ctx_make_current = qemu_egl_make_context_current, +}; + +static void +dbus_display_init(Object *o) +{ + DBusDisplay *dd = DBUS_DISPLAY(o); + g_autoptr(GDBusObjectSkeleton) vm = NULL; + + dd->glctx.ops = &dbus_gl_ops; + dd->iface = qemu_dbus_display1_vm_skeleton_new(); + dd->consoles = g_ptr_array_new_with_free_func(g_object_unref); + + dd->server = g_dbus_object_manager_server_new(DBUS_DISPLAY1_ROOT); + + vm = g_dbus_object_skeleton_new(DBUS_DISPLAY1_ROOT "/VM"); + g_dbus_object_skeleton_add_interface( + vm, G_DBUS_INTERFACE_SKELETON(dd->iface)); + g_dbus_object_manager_server_export(dd->server, vm); +} + +static void +dbus_display_finalize(Object *o) +{ + DBusDisplay *dd = DBUS_DISPLAY(o); + + g_clear_object(&dd->server); + g_clear_pointer(&dd->consoles, g_ptr_array_unref); + g_clear_object(&dd->bus); + g_clear_object(&dd->iface); + g_free(dd->dbus_addr); +} + +static bool +dbus_display_add_console(DBusDisplay *dd, int idx, Error **errp) +{ + QemuConsole *con; + DBusDisplayConsole *dbus_console; + + con = qemu_console_lookup_by_index(idx); + assert(con); + + if (qemu_console_is_graphic(con) && + dd->gl_mode != DISPLAYGL_MODE_OFF) { + qemu_console_set_display_gl_ctx(con, &dd->glctx); + } + + dbus_console = dbus_display_console_new(dd, con); + g_ptr_array_insert(dd->consoles, idx, dbus_console); + g_dbus_object_manager_server_export(dd->server, + G_DBUS_OBJECT_SKELETON(dbus_console)); + return true; +} + +static void +dbus_display_complete(UserCreatable *uc, Error **errp) +{ + DBusDisplay *dd = DBUS_DISPLAY(uc); + g_autoptr(GError) err = NULL; + g_autofree char *uuid = qemu_uuid_unparse_strdup(&qemu_uuid); + g_autoptr(GArray) consoles = NULL; + GVariant *console_ids; + int idx; + + if (!object_resolve_path_type("", TYPE_DBUS_DISPLAY, NULL)) { + error_setg(errp, "There is already an instance of %s", + TYPE_DBUS_DISPLAY); + return; + } + + if (dd->dbus_addr && *dd->dbus_addr) { + dd->bus = g_dbus_connection_new_for_address_sync(dd->dbus_addr, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | + G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION, + NULL, NULL, &err); + } else { + dd->bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &err); + } + if (err) { + error_setg(errp, "failed to connect to DBus: %s", err->message); + return; + } + + + consoles = g_array_new(FALSE, FALSE, sizeof(guint32)); + for (idx = 0;; idx++) { + if (!qemu_console_lookup_by_index(idx)) { + break; + } + if (!dbus_display_add_console(dd, idx, errp)) { + return; + } + g_array_append_val(consoles, idx); + } + + console_ids = g_variant_new_from_data( + G_VARIANT_TYPE("au"), + consoles->data, consoles->len * sizeof(guint32), TRUE, + (GDestroyNotify)g_array_unref, consoles); + g_steal_pointer(&consoles); + g_object_set(dd->iface, + "name", qemu_name ?: "QEMU " QEMU_VERSION, + "uuid", uuid, + "console-ids", console_ids, + NULL); + + g_dbus_object_manager_server_set_connection(dd->server, dd->bus); + g_bus_own_name_on_connection(dd->bus, "org.qemu", + G_BUS_NAME_OWNER_FLAGS_NONE, + NULL, NULL, NULL, NULL); +} + +static char * +get_dbus_addr(Object *o, Error **errp) +{ + DBusDisplay *dd = DBUS_DISPLAY(o); + + return g_strdup(dd->dbus_addr); +} + +static void +set_dbus_addr(Object *o, const char *str, Error **errp) +{ + DBusDisplay *dd = DBUS_DISPLAY(o); + + g_free(dd->dbus_addr); + dd->dbus_addr = g_strdup(str); +} + +static int +get_gl_mode(Object *o, Error **errp) +{ + DBusDisplay *dd = DBUS_DISPLAY(o); + + return dd->gl_mode; +} + +static void +set_gl_mode(Object *o, int val, Error **errp) +{ + DBusDisplay *dd = DBUS_DISPLAY(o); + + dd->gl_mode = val; +} + +static void +dbus_display_class_init(ObjectClass *oc, void *data) +{ + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); + + ucc->complete = dbus_display_complete; + object_class_property_add_str(oc, "addr", get_dbus_addr, set_dbus_addr); + object_class_property_add_enum(oc, "gl-mode", + "DisplayGLMode", &DisplayGLMode_lookup, + get_gl_mode, set_gl_mode); +} + +static void +early_dbus_init(DisplayOptions *opts) +{ + DisplayGLMode mode = opts->has_gl ? opts->gl : DISPLAYGL_MODE_OFF; + + if (mode != DISPLAYGL_MODE_OFF) { + if (egl_rendernode_init(opts->u.dbus.rendernode, mode) < 0) { + error_report("dbus: render node init failed"); + exit(1); + } + + display_opengl = 1; + } +} + +static void +dbus_init(DisplayState *ds, DisplayOptions *opts) +{ + DisplayGLMode mode = opts->has_gl ? opts->gl : DISPLAYGL_MODE_OFF; + + object_new_with_props(TYPE_DBUS_DISPLAY, + object_get_objects_root(), + "dbus-display", &error_fatal, + "addr", opts->u.dbus.addr ?: "", + "gl-mode", DisplayGLMode_str(mode), + NULL); +} + +static const TypeInfo dbus_display_info = { + .name = TYPE_DBUS_DISPLAY, + .parent = TYPE_OBJECT, + .instance_size = sizeof(DBusDisplay), + .instance_init = dbus_display_init, + .instance_finalize = dbus_display_finalize, + .class_init = dbus_display_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_USER_CREATABLE }, + { } + } +}; + +static QemuDisplay qemu_display_dbus = { + .type = DISPLAY_TYPE_DBUS, + .early_init = early_dbus_init, + .init = dbus_init, +}; + +static void register_dbus(void) +{ + type_register_static(&dbus_display_info); + qemu_display_register(&qemu_display_dbus); +} + +type_init(register_dbus); + +#ifdef CONFIG_OPENGL +module_dep("ui-opengl"); +#endif diff --git a/ui/dbus.h b/ui/dbus.h new file mode 100644 index 0000000000..d3c9598dd1 --- /dev/null +++ b/ui/dbus.h @@ -0,0 +1,83 @@ +/* + * QEMU DBus display + * + * Copyright (c) 2021 Marc-André Lureau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef UI_DBUS_H_ +#define UI_DBUS_H_ + +#include "qemu/dbus.h" +#include "qom/object.h" +#include "ui/console.h" + +#include "dbus-display1.h" + +struct DBusDisplay { + Object parent; + + DisplayGLMode gl_mode; + char *dbus_addr; + DisplayGLCtx glctx; + + GDBusConnection *bus; + GDBusObjectManagerServer *server; + QemuDBusDisplay1VM *iface; + GPtrArray *consoles; +}; + +#define TYPE_DBUS_DISPLAY "dbus-display" +OBJECT_DECLARE_SIMPLE_TYPE(DBusDisplay, DBUS_DISPLAY) + +#define DBUS_DISPLAY_TYPE_CONSOLE dbus_display_console_get_type() +G_DECLARE_FINAL_TYPE(DBusDisplayConsole, + dbus_display_console, + DBUS_DISPLAY, + CONSOLE, + GDBusObjectSkeleton) + +DBusDisplayConsole * +dbus_display_console_new(DBusDisplay *display, QemuConsole *con); + +int +dbus_display_console_get_index(DBusDisplayConsole *ddc); + +#define DBUS_DISPLAY_TYPE_LISTENER dbus_display_listener_get_type() +G_DECLARE_FINAL_TYPE(DBusDisplayListener, + dbus_display_listener, + DBUS_DISPLAY, + LISTENER, + GObject) + +DBusDisplayListener * +dbus_display_listener_new(const char *bus_name, + GDBusConnection *conn, + DBusDisplayConsole *console); + +DBusDisplayConsole * +dbus_display_listener_get_console(DBusDisplayListener *ddl); + +const char * +dbus_display_listener_get_bus_name(DBusDisplayListener *ddl); + +extern const DisplayChangeListenerOps dbus_gl_dcl_ops; +extern const DisplayChangeListenerOps dbus_dcl_ops; + +#endif /* UI_DBUS_H_ */ diff --git a/ui/meson.build b/ui/meson.build index a9df5b911e..6270aa768b 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -65,6 +65,28 @@ if config_host.has_key('CONFIG_OPENGL') and gbm.found() ui_modules += {'egl-headless' : egl_headless_ss} endif +if dbus_display + dbus_ss = ss.source_set() + dbus_display1 = custom_target('dbus-display gdbus-codegen', + output: ['dbus-display1.h', 'dbus-display1.c'], + input: files('dbus-display1.xml'), + command: [config_host['GDBUS_CODEGEN'], + '@INPUT@', + '--glib-min-required', '2.64', + '--output-directory', meson.current_build_dir(), + '--interface-prefix', 'org.qemu.', + '--c-namespace', 'QemuDBus', + '--generate-c-code', '@BASENAME@']) + dbus_ss.add(when: [gio, pixman, opengl, 'CONFIG_GIO'], + if_true: [files( + 'dbus-console.c', + 'dbus-error.c', + 'dbus-listener.c', + 'dbus.c', + ), dbus_display1]) + ui_modules += {'dbus' : dbus_ss} +endif + if gtk.found() softmmu_ss.add(when: 'CONFIG_WIN32', if_true: files('win32-kbd-hook.c')) diff --git a/ui/trace-events b/ui/trace-events index e832c3e365..b1ae30159a 100644 --- a/ui/trace-events +++ b/ui/trace-events @@ -136,3 +136,14 @@ vdagent_peer_cap(const char *name) "cap %s" vdagent_cb_grab_selection(const char *name) "selection %s" vdagent_cb_grab_type(const char *name) "type %s" vdagent_cb_serial_discard(uint32_t current, uint32_t received) "current=%u, received=%u" + +# dbus.c +dbus_registered_listener(const char *bus_name) "peer %s" +dbus_listener_vanished(const char *bus_name) "peer %s" +dbus_kbd_press(unsigned int keycode) "keycode %u" +dbus_kbd_release(unsigned int keycode) "keycode %u" +dbus_mouse_press(unsigned int button) "button %u" +dbus_mouse_release(unsigned int button) "button %u" +dbus_mouse_set_pos(unsigned int x, unsigned int y) "x=%u, y=%u" +dbus_mouse_rel_motion(int dx, int dy) "dx=%d, dy=%d" +dbus_update(int x, int y, int w, int h) "x=%d, y=%d, w=%d, h=%d" From 99997823bbbd23aa0cce42e03b49fd8a57222e5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sun, 10 Oct 2021 00:16:57 +0400 Subject: [PATCH 026/730] ui/dbus: add p2p=on/off option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an option to use direct connections instead of via the bus. Clients are accepted with QMP add_client. This allows to provide the D-Bus display without a bus. It also simplifies the testing setup (some CI have issues to setup a D-Bus bus in a container). Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- include/qemu/cutils.h | 5 ++ include/ui/dbus-display.h | 17 ++++++ include/ui/dbus-module.h | 11 ++++ monitor/qmp-cmds.c | 13 +++++ qapi/misc.json | 4 +- qapi/ui.json | 6 ++- qemu-options.hx | 6 ++- ui/dbus-console.c | 2 +- ui/dbus-listener.c | 2 +- ui/dbus-module.c | 35 ++++++++++++ ui/dbus.c | 109 ++++++++++++++++++++++++++++++++++++-- ui/dbus.h | 2 + ui/meson.build | 3 ++ 13 files changed, 203 insertions(+), 12 deletions(-) create mode 100644 include/ui/dbus-display.h create mode 100644 include/ui/dbus-module.h create mode 100644 ui/dbus-module.c diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h index 986ed8e15f..320543950c 100644 --- a/include/qemu/cutils.h +++ b/include/qemu/cutils.h @@ -209,4 +209,9 @@ int qemu_pstrcmp0(const char **str1, const char **str2); */ char *get_relocated_path(const char *dir); +static inline const char *yes_no(bool b) +{ + return b ? "yes" : "no"; +} + #endif diff --git a/include/ui/dbus-display.h b/include/ui/dbus-display.h new file mode 100644 index 0000000000..88f153c237 --- /dev/null +++ b/include/ui/dbus-display.h @@ -0,0 +1,17 @@ +#ifndef DBUS_DISPLAY_H_ +#define DBUS_DISPLAY_H_ + +#include "qapi/error.h" +#include "ui/dbus-module.h" + +static inline bool qemu_using_dbus_display(Error **errp) +{ + if (!using_dbus_display) { + error_set(errp, ERROR_CLASS_DEVICE_NOT_ACTIVE, + "D-Bus display is not in use"); + return false; + } + return true; +} + +#endif /* DBUS_DISPLAY_H_ */ diff --git a/include/ui/dbus-module.h b/include/ui/dbus-module.h new file mode 100644 index 0000000000..ace4a17a5c --- /dev/null +++ b/include/ui/dbus-module.h @@ -0,0 +1,11 @@ +#ifndef DBUS_MODULE_H_ +#define DBUS_MODULE_H_ + +struct QemuDBusDisplayOps { + bool (*add_client)(int csock, Error **errp); +}; + +extern int using_dbus_display; +extern struct QemuDBusDisplayOps qemu_dbus_display; + +#endif /* DBUS_MODULE_H_*/ diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index 343353e27a..14e3beeaaf 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -24,6 +24,7 @@ #include "chardev/char.h" #include "ui/qemu-spice.h" #include "ui/console.h" +#include "ui/dbus-display.h" #include "sysemu/kvm.h" #include "sysemu/runstate.h" #include "sysemu/runstate-action.h" @@ -285,6 +286,18 @@ void qmp_add_client(const char *protocol, const char *fdname, skipauth = has_skipauth ? skipauth : false; vnc_display_add_client(NULL, fd, skipauth); return; +#endif +#ifdef CONFIG_DBUS_DISPLAY + } else if (strcmp(protocol, "@dbus-display") == 0) { + if (!qemu_using_dbus_display(errp)) { + close(fd); + return; + } + if (!qemu_dbus_display.add_client(fd, errp)) { + close(fd); + return; + } + return; #endif } else if ((s = qemu_chr_find(protocol)) != NULL) { if (qemu_chr_add_client(s, fd) < 0) { diff --git a/qapi/misc.json b/qapi/misc.json index 358548abe1..e8054f415b 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -14,8 +14,8 @@ # Allow client connections for VNC, Spice and socket based # character devices to be passed in to QEMU via SCM_RIGHTS. # -# @protocol: protocol name. Valid names are "vnc", "spice" or the -# name of a character device (eg. from -chardev id=XXXX) +# @protocol: protocol name. Valid names are "vnc", "spice", "@dbus-display" or +# the name of a character device (eg. from -chardev id=XXXX) # # @fdname: file descriptor name previously passed via 'getfd' command # diff --git a/qapi/ui.json b/qapi/ui.json index 80855328b1..d435e94722 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1131,12 +1131,16 @@ # @rendernode: Which DRM render node should be used. Default is the first # available node on the host. # +# @p2p: Whether to use peer-to-peer connections (accepted through +# ``add_client``). +# # Since: 7.0 # ## { 'struct' : 'DisplayDBus', 'data' : { '*rendernode' : 'str', - '*addr': 'str' } } + '*addr': 'str', + '*p2p': 'bool' } } ## # @DisplayGLMode: diff --git a/qemu-options.hx b/qemu-options.hx index 38983a919b..977e0873a1 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1901,8 +1901,10 @@ SRST ``addr=`` : D-Bus bus address to connect to. - ``gl=on|off|core|es`` : Use OpenGL for rendering (the D-interface will - share framebuffers with DMABUF file descriptors). + ``p2p=yes|no`` : Use peer-to-peer connection, accepted via QMP ``add_client``. + + ``gl=on|off|core|es`` : Use OpenGL for rendering (the D-Bus interface + will share framebuffers with DMABUF file descriptors). ``sdl`` Display video output via SDL (usually in a separate graphics diff --git a/ui/dbus-console.c b/ui/dbus-console.c index 1ccf638c10..e062f721d7 100644 --- a/ui/dbus-console.c +++ b/ui/dbus-console.c @@ -219,7 +219,7 @@ dbus_console_register_listener(DBusDisplayConsole *ddc, DBusDisplayListener *listener; int fd; - if (g_hash_table_contains(ddc->listeners, sender)) { + if (sender && g_hash_table_contains(ddc->listeners, sender)) { g_dbus_method_invocation_return_error( invocation, DBUS_DISPLAY_ERROR, diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c index 20094fc18a..81c119b13a 100644 --- a/ui/dbus-listener.c +++ b/ui/dbus-listener.c @@ -440,7 +440,7 @@ dbus_display_listener_init(DBusDisplayListener *ddl) const char * dbus_display_listener_get_bus_name(DBusDisplayListener *ddl) { - return ddl->bus_name; + return ddl->bus_name ?: "p2p"; } DBusDisplayConsole * diff --git a/ui/dbus-module.c b/ui/dbus-module.c new file mode 100644 index 0000000000..c8771fe48c --- /dev/null +++ b/ui/dbus-module.c @@ -0,0 +1,35 @@ +/* + * D-Bus module support. + * + * Copyright (C) 2021 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "ui/dbus-module.h" + +int using_dbus_display; + +static bool +qemu_dbus_display_add_client(int csock, Error **errp) +{ + error_setg(errp, "D-Bus display isn't enabled"); + return false; +} + +struct QemuDBusDisplayOps qemu_dbus_display = { + .add_client = qemu_dbus_display_add_client, +}; diff --git a/ui/dbus.c b/ui/dbus.c index 12da8ffe31..847a667821 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -22,10 +22,12 @@ * THE SOFTWARE. */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "qemu/dbus.h" #include "qemu/option.h" #include "qom/object_interfaces.h" #include "sysemu/sysemu.h" +#include "ui/dbus-module.h" #include "ui/egl-helpers.h" #include "ui/egl-context.h" #include "qapi/error.h" @@ -33,6 +35,8 @@ #include "dbus.h" +static DBusDisplay *dbus_display; + static QEMUGLContext dbus_create_context(DisplayGLCtx *dgc, QEMUGLParams *params) { @@ -73,9 +77,14 @@ dbus_display_finalize(Object *o) g_clear_object(&dd->server); g_clear_pointer(&dd->consoles, g_ptr_array_unref); + if (dd->add_client_cancellable) { + g_cancellable_cancel(dd->add_client_cancellable); + } + g_clear_object(&dd->add_client_cancellable); g_clear_object(&dd->bus); g_clear_object(&dd->iface); g_free(dd->dbus_addr); + dbus_display = NULL; } static bool @@ -115,7 +124,10 @@ dbus_display_complete(UserCreatable *uc, Error **errp) return; } - if (dd->dbus_addr && *dd->dbus_addr) { + if (dd->p2p) { + /* wait for dbus_display_add_client() */ + dbus_display = dd; + } else if (dd->dbus_addr && *dd->dbus_addr) { dd->bus = g_dbus_connection_new_for_address_sync(dd->dbus_addr, G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION, @@ -151,10 +163,85 @@ dbus_display_complete(UserCreatable *uc, Error **errp) "console-ids", console_ids, NULL); - g_dbus_object_manager_server_set_connection(dd->server, dd->bus); - g_bus_own_name_on_connection(dd->bus, "org.qemu", - G_BUS_NAME_OWNER_FLAGS_NONE, - NULL, NULL, NULL, NULL); + if (dd->bus) { + g_dbus_object_manager_server_set_connection(dd->server, dd->bus); + g_bus_own_name_on_connection(dd->bus, "org.qemu", + G_BUS_NAME_OWNER_FLAGS_NONE, + NULL, NULL, NULL, NULL); + } +} + +static void +dbus_display_add_client_ready(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) err = NULL; + g_autoptr(GDBusConnection) conn = NULL; + + g_clear_object(&dbus_display->add_client_cancellable); + + conn = g_dbus_connection_new_finish(res, &err); + if (!conn) { + error_printf("Failed to accept D-Bus client: %s", err->message); + } + + g_dbus_object_manager_server_set_connection(dbus_display->server, conn); +} + + +static bool +dbus_display_add_client(int csock, Error **errp) +{ + g_autoptr(GError) err = NULL; + g_autoptr(GSocket) socket = NULL; + g_autoptr(GSocketConnection) conn = NULL; + g_autofree char *guid = g_dbus_generate_guid(); + + if (!dbus_display) { + error_setg(errp, "p2p connections not accepted in bus mode"); + return false; + } + + if (dbus_display->add_client_cancellable) { + g_cancellable_cancel(dbus_display->add_client_cancellable); + } + + socket = g_socket_new_from_fd(csock, &err); + if (!socket) { + error_setg(errp, "Failed to setup D-Bus socket: %s", err->message); + return false; + } + + conn = g_socket_connection_factory_create_connection(socket); + + dbus_display->add_client_cancellable = g_cancellable_new(); + + g_dbus_connection_new(G_IO_STREAM(conn), + guid, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER, + NULL, + dbus_display->add_client_cancellable, + dbus_display_add_client_ready, + NULL); + + return true; +} + +static bool +get_dbus_p2p(Object *o, Error **errp) +{ + DBusDisplay *dd = DBUS_DISPLAY(o); + + return dd->p2p; +} + +static void +set_dbus_p2p(Object *o, bool p2p, Error **errp) +{ + DBusDisplay *dd = DBUS_DISPLAY(o); + + dd->p2p = p2p; } static char * @@ -196,6 +283,7 @@ dbus_display_class_init(ObjectClass *oc, void *data) UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); ucc->complete = dbus_display_complete; + object_class_property_add_bool(oc, "p2p", get_dbus_p2p, set_dbus_p2p); object_class_property_add_str(oc, "addr", get_dbus_addr, set_dbus_addr); object_class_property_add_enum(oc, "gl-mode", "DisplayGLMode", &DisplayGLMode_lookup, @@ -222,11 +310,19 @@ dbus_init(DisplayState *ds, DisplayOptions *opts) { DisplayGLMode mode = opts->has_gl ? opts->gl : DISPLAYGL_MODE_OFF; + if (opts->u.dbus.addr && opts->u.dbus.p2p) { + error_report("dbus: can't accept both addr=X and p2p=yes options"); + exit(1); + } + + using_dbus_display = 1; + object_new_with_props(TYPE_DBUS_DISPLAY, object_get_objects_root(), "dbus-display", &error_fatal, "addr", opts->u.dbus.addr ?: "", "gl-mode", DisplayGLMode_str(mode), + "p2p", yes_no(opts->u.dbus.p2p), NULL); } @@ -251,6 +347,9 @@ static QemuDisplay qemu_display_dbus = { static void register_dbus(void) { + qemu_dbus_display = (struct QemuDBusDisplayOps) { + .add_client = dbus_display_add_client, + }; type_register_static(&dbus_display_info); qemu_display_register(&qemu_display_dbus); } diff --git a/ui/dbus.h b/ui/dbus.h index d3c9598dd1..4698d32463 100644 --- a/ui/dbus.h +++ b/ui/dbus.h @@ -34,6 +34,7 @@ struct DBusDisplay { Object parent; DisplayGLMode gl_mode; + bool p2p; char *dbus_addr; DisplayGLCtx glctx; @@ -41,6 +42,7 @@ struct DBusDisplay { GDBusObjectManagerServer *server; QemuDBusDisplay1VM *iface; GPtrArray *consoles; + GCancellable *add_client_cancellable; }; #define TYPE_DBUS_DISPLAY "dbus-display" diff --git a/ui/meson.build b/ui/meson.build index 6270aa768b..80f21704ad 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -14,6 +14,9 @@ softmmu_ss.add(files( 'qemu-pixman.c', 'util.c', )) +if dbus_display + softmmu_ss.add(files('dbus-module.c')) +endif softmmu_ss.add([spice_headers, files('spice-module.c')]) softmmu_ss.add(when: spice_protocol, if_true: files('vdagent.c')) From 2c7294d72c4086fc89935514430bd2bfb5ae5011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 7 Oct 2021 01:07:30 +0400 Subject: [PATCH 027/730] tests/qtests: add qtest_qmp_add_client() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- tests/qtest/libqos/libqtest.h | 10 ++++++++++ tests/qtest/libqtest.c | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/tests/qtest/libqos/libqtest.h b/tests/qtest/libqos/libqtest.h index dff6b31cf0..a6d38d7ef7 100644 --- a/tests/qtest/libqos/libqtest.h +++ b/tests/qtest/libqos/libqtest.h @@ -744,6 +744,16 @@ void qtest_qmp_device_add_qdict(QTestState *qts, const char *drv, void qtest_qmp_device_add(QTestState *qts, const char *driver, const char *id, const char *fmt, ...) GCC_FMT_ATTR(4, 5); +/** + * qtest_qmp_add_client: + * @qts: QTestState instance to operate on + * @protocol: the protocol to add to + * @fd: the client file-descriptor + * + * Call QMP ``getfd`` followed by ``add_client`` with the given @fd. + */ +void qtest_qmp_add_client(QTestState *qts, const char *protocol, int fd); + /** * qtest_qmp_device_del: * @qts: QTestState instance to operate on diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index 65ed949685..a68326caae 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -1453,6 +1453,25 @@ void qtest_qmp_device_add(QTestState *qts, const char *driver, const char *id, qobject_unref(args); } +void qtest_qmp_add_client(QTestState *qts, const char *protocol, int fd) +{ + QDict *resp; + + resp = qtest_qmp_fds(qts, &fd, 1, "{'execute': 'getfd'," + "'arguments': {'fdname': 'fdname'}}"); + g_assert(resp); + g_assert(!qdict_haskey(resp, "event")); /* We don't expect any events */ + g_assert(!qdict_haskey(resp, "error")); + qobject_unref(resp); + + resp = qtest_qmp( + qts, "{'execute': 'add_client'," + "'arguments': {'protocol': %s, 'fdname': 'fdname'}}", protocol); + g_assert(resp); + g_assert(!qdict_haskey(resp, "event")); /* We don't expect any events */ + g_assert(!qdict_haskey(resp, "error")); + qobject_unref(resp); +} /* * Generic hot-unplugging test via the device_del QMP command. From b4dd5b6a60eb525437c8d315d0d59dc25d4e4cb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 7 Oct 2021 01:08:15 +0400 Subject: [PATCH 028/730] tests: start dbus-display-test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cover basic display interface usage. More cases to be added to cover disconnections, multiple connections, corner cases. At this point, they would be better written in Rust or Python though. The proxy also covers reading the properties, since they are automatically loaded at creation. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- tests/qtest/dbus-display-test.c | 257 ++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 8 + 2 files changed, 265 insertions(+) create mode 100644 tests/qtest/dbus-display-test.c diff --git a/tests/qtest/dbus-display-test.c b/tests/qtest/dbus-display-test.c new file mode 100644 index 0000000000..43c77aff04 --- /dev/null +++ b/tests/qtest/dbus-display-test.c @@ -0,0 +1,257 @@ +#include "qemu/osdep.h" +#include "qemu/dbus.h" +#include +#include +#include "libqos/libqtest.h" +#include "qemu-common.h" +#include "dbus-display1.h" + +static GDBusConnection* +test_dbus_p2p_from_fd(int fd) +{ + g_autoptr(GError) err = NULL; + g_autoptr(GSocket) socket = NULL; + g_autoptr(GSocketConnection) socketc = NULL; + GDBusConnection *conn; + + socket = g_socket_new_from_fd(fd, &err); + g_assert_no_error(err); + + socketc = g_socket_connection_factory_create_connection(socket); + g_assert(socketc != NULL); + + conn = g_dbus_connection_new_sync( + G_IO_STREAM(socketc), NULL, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | + G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING, + NULL, NULL, &err); + g_assert_no_error(err); + + return conn; +} + +static void +test_setup(QTestState **qts, GDBusConnection **conn) +{ + int pair[2]; + + *qts = qtest_init("-display dbus,p2p=yes -name dbus-test"); + + g_assert_cmpint(socketpair(AF_UNIX, SOCK_STREAM, 0, pair), ==, 0); + + qtest_qmp_add_client(*qts, "@dbus-display", pair[1]); + + *conn = test_dbus_p2p_from_fd(pair[0]); + g_dbus_connection_start_message_processing(*conn); +} + +static void +test_dbus_display_vm(void) +{ + g_autoptr(GError) err = NULL; + g_autoptr(GDBusConnection) conn = NULL; + g_autoptr(QemuDBusDisplay1VMProxy) vm = NULL; + QTestState *qts = NULL; + + test_setup(&qts, &conn); + + vm = QEMU_DBUS_DISPLAY1_VM_PROXY( + qemu_dbus_display1_vm_proxy_new_sync( + conn, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + DBUS_DISPLAY1_ROOT "/VM", + NULL, + &err)); + g_assert_no_error(err); + + g_assert_cmpstr( + qemu_dbus_display1_vm_get_name(QEMU_DBUS_DISPLAY1_VM(vm)), + ==, + "dbus-test"); + qtest_quit(qts); +} + +typedef struct TestDBusConsoleRegister { + GMainLoop *loop; + GThread *thread; + GDBusConnection *listener_conn; + GDBusObjectManagerServer *server; +} TestDBusConsoleRegister; + +static gboolean listener_handle_scanout( + QemuDBusDisplay1Listener *object, + GDBusMethodInvocation *invocation, + guint arg_width, + guint arg_height, + guint arg_stride, + guint arg_pixman_format, + GVariant *arg_data, + TestDBusConsoleRegister *test) +{ + g_main_loop_quit(test->loop); + + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static void +test_dbus_console_setup_listener(TestDBusConsoleRegister *test) +{ + g_autoptr(GDBusObjectSkeleton) listener = NULL; + g_autoptr(QemuDBusDisplay1ListenerSkeleton) iface = NULL; + + test->server = g_dbus_object_manager_server_new(DBUS_DISPLAY1_ROOT); + listener = g_dbus_object_skeleton_new(DBUS_DISPLAY1_ROOT "/Listener"); + iface = QEMU_DBUS_DISPLAY1_LISTENER_SKELETON( + qemu_dbus_display1_listener_skeleton_new()); + g_object_connect(iface, + "signal::handle-scanout", listener_handle_scanout, test, + NULL); + g_dbus_object_skeleton_add_interface(listener, + G_DBUS_INTERFACE_SKELETON(iface)); + g_dbus_object_manager_server_export(test->server, listener); + g_dbus_object_manager_server_set_connection(test->server, + test->listener_conn); + + g_dbus_connection_start_message_processing(test->listener_conn); +} + +static void +test_dbus_console_registered(GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + TestDBusConsoleRegister *test = user_data; + g_autoptr(GError) err = NULL; + + qemu_dbus_display1_console_call_register_listener_finish( + QEMU_DBUS_DISPLAY1_CONSOLE(source_object), + NULL, res, &err); + g_assert_no_error(err); + + test->listener_conn = g_thread_join(test->thread); + test_dbus_console_setup_listener(test); +} + +static gpointer +test_dbus_p2p_server_setup_thread(gpointer data) +{ + return test_dbus_p2p_from_fd(GPOINTER_TO_INT(data)); +} + +static void +test_dbus_display_console(void) +{ + g_autoptr(GError) err = NULL; + g_autoptr(GDBusConnection) conn = NULL; + g_autoptr(QemuDBusDisplay1ConsoleProxy) console = NULL; + g_autoptr(GUnixFDList) fd_list = NULL; + g_autoptr(GMainLoop) loop = NULL; + QTestState *qts = NULL; + int pair[2], idx; + TestDBusConsoleRegister test; + + test_setup(&qts, &conn); + + g_assert_cmpint(socketpair(AF_UNIX, SOCK_STREAM, 0, pair), ==, 0); + fd_list = g_unix_fd_list_new(); + idx = g_unix_fd_list_append(fd_list, pair[1], NULL); + + console = QEMU_DBUS_DISPLAY1_CONSOLE_PROXY( + qemu_dbus_display1_console_proxy_new_sync( + conn, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "/org/qemu/Display1/Console_0", + NULL, + &err)); + g_assert_no_error(err); + + test.loop = loop = g_main_loop_new(NULL, FALSE); + test.thread = g_thread_new(NULL, test_dbus_p2p_server_setup_thread, + GINT_TO_POINTER(pair[0])); + + qemu_dbus_display1_console_call_register_listener( + QEMU_DBUS_DISPLAY1_CONSOLE(console), + g_variant_new_handle(idx), + G_DBUS_CALL_FLAGS_NONE, + -1, + fd_list, + NULL, + test_dbus_console_registered, + &test); + + g_main_loop_run(loop); + + g_clear_object(&test.server); + g_clear_object(&test.listener_conn); + qtest_quit(qts); +} + +static void +test_dbus_display_keyboard(void) +{ + g_autoptr(GError) err = NULL; + g_autoptr(GDBusConnection) conn = NULL; + g_autoptr(QemuDBusDisplay1KeyboardProxy) keyboard = NULL; + QTestState *qts = NULL; + + test_setup(&qts, &conn); + + keyboard = QEMU_DBUS_DISPLAY1_KEYBOARD_PROXY( + qemu_dbus_display1_keyboard_proxy_new_sync( + conn, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "/org/qemu/Display1/Console_0", + NULL, + &err)); + g_assert_no_error(err); + + + g_assert_cmpint(qtest_inb(qts, 0x64) & 0x1, ==, 0); + g_assert_cmpint(qtest_inb(qts, 0x60), ==, 0); + + qemu_dbus_display1_keyboard_call_press_sync( + QEMU_DBUS_DISPLAY1_KEYBOARD(keyboard), + 0x1C, /* qnum enter */ + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &err); + g_assert_no_error(err); + + /* may be should wait for interrupt? */ + g_assert_cmpint(qtest_inb(qts, 0x64) & 0x1, ==, 1); + g_assert_cmpint(qtest_inb(qts, 0x60), ==, 0x5A); /* scan code 2 enter */ + + qemu_dbus_display1_keyboard_call_release_sync( + QEMU_DBUS_DISPLAY1_KEYBOARD(keyboard), + 0x1C, /* qnum enter */ + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &err); + g_assert_no_error(err); + + g_assert_cmpint(qtest_inb(qts, 0x64) & 0x1, ==, 1); + g_assert_cmpint(qtest_inb(qts, 0x60), ==, 0xF0); /* scan code 2 release */ + g_assert_cmpint(qtest_inb(qts, 0x60), ==, 0x5A); /* scan code 2 enter */ + + g_assert_cmpint(qemu_dbus_display1_keyboard_get_modifiers( + QEMU_DBUS_DISPLAY1_KEYBOARD(keyboard)), ==, 0); + + qtest_quit(qts); +} + +int +main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/dbus-display/vm", test_dbus_display_vm); + qtest_add_func("/dbus-display/console", test_dbus_display_console); + qtest_add_func("/dbus-display/keyboard", test_dbus_display_keyboard); + + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 913e987409..1b2bde6660 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -92,6 +92,10 @@ qtests_i386 = \ 'test-x86-cpuid-compat', 'numa-test'] +if dbus_display + qtests_i386 += ['dbus-display-test'] +endif + dbus_daemon = find_program('dbus-daemon', required: false) if dbus_daemon.found() and config_host.has_key('GDBUS_CODEGEN') # Temporarily disabled due to Patchew failures: @@ -265,6 +269,10 @@ qtests = { 'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'), } +if dbus_display +qtests += {'dbus-display-test': [dbus_display1, gio]} +endif + qtest_executables = {} foreach dir : target_dirs if not dir.endswith('-softmmu') From 739362d4205cd90686118fe5af3e236c2f8c6be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 9 Mar 2021 17:15:28 +0400 Subject: [PATCH 029/730] audio: add "dbus" audio backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new -audio backend that accepts D-Bus clients/listeners to handle playback & recording, to be exported via the -display dbus. Example usage: -audiodev dbus,in.mixing-engine=off,out.mixing-engine=off,id=dbus -display dbus,audiodev=dbus Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- audio/audio.c | 1 + audio/audio_int.h | 7 + audio/audio_template.h | 2 + audio/dbusaudio.c | 654 +++++++++++++++++++++++++++++++++++++++++ audio/meson.build | 6 + audio/trace-events | 5 + qapi/audio.json | 3 +- qapi/ui.json | 5 +- qemu-options.hx | 3 + ui/dbus-display1.xml | 211 +++++++++++++ ui/dbus.c | 35 +++ ui/dbus.h | 1 + 12 files changed, 931 insertions(+), 2 deletions(-) create mode 100644 audio/dbusaudio.c diff --git a/audio/audio.c b/audio/audio.c index 54a153c0ef..dc28685d22 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -2000,6 +2000,7 @@ void audio_create_pdos(Audiodev *dev) CASE(NONE, none, ); CASE(ALSA, alsa, Alsa); CASE(COREAUDIO, coreaudio, Coreaudio); + CASE(DBUS, dbus, ); CASE(DSOUND, dsound, ); CASE(JACK, jack, Jack); CASE(OSS, oss, Oss); diff --git a/audio/audio_int.h b/audio/audio_int.h index 6d685e24a3..428a091d05 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -31,6 +31,10 @@ #endif #include "mixeng.h" +#ifdef CONFIG_GIO +#include +#endif + struct audio_pcm_ops; struct audio_callback { @@ -140,6 +144,9 @@ struct audio_driver { const char *descr; void *(*init) (Audiodev *); void (*fini) (void *); +#ifdef CONFIG_GIO + void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager); +#endif struct audio_pcm_ops *pcm_ops; int can_be_default; int max_voices_out; diff --git a/audio/audio_template.h b/audio/audio_template.h index c6714946aa..d2d348638b 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -327,6 +327,8 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev) case AUDIODEV_DRIVER_COREAUDIO: return qapi_AudiodevCoreaudioPerDirectionOptions_base( dev->u.coreaudio.TYPE); + case AUDIODEV_DRIVER_DBUS: + return dev->u.dbus.TYPE; case AUDIODEV_DRIVER_DSOUND: return dev->u.dsound.TYPE; case AUDIODEV_DRIVER_JACK: diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c new file mode 100644 index 0000000000..f178b47dee --- /dev/null +++ b/audio/dbusaudio.c @@ -0,0 +1,654 @@ +/* + * QEMU DBus audio + * + * Copyright (c) 2021 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/host-utils.h" +#include "qemu/module.h" +#include "qemu/timer.h" +#include "qemu/dbus.h" + +#include +#include "ui/dbus-display1.h" + +#define AUDIO_CAP "dbus" +#include "audio.h" +#include "audio_int.h" +#include "trace.h" + +#define DBUS_DISPLAY1_AUDIO_PATH DBUS_DISPLAY1_ROOT "/Audio" + +#define DBUS_AUDIO_NSAMPLES 1024 /* could be configured? */ + +typedef struct DBusAudio { + GDBusObjectManagerServer *server; + GDBusObjectSkeleton *audio; + QemuDBusDisplay1Audio *iface; + GHashTable *out_listeners; + GHashTable *in_listeners; +} DBusAudio; + +typedef struct DBusVoiceOut { + HWVoiceOut hw; + bool enabled; + RateCtl rate; + + void *buf; + size_t buf_pos; + size_t buf_size; + + bool has_volume; + Volume volume; +} DBusVoiceOut; + +typedef struct DBusVoiceIn { + HWVoiceIn hw; + bool enabled; + RateCtl rate; + + bool has_volume; + Volume volume; +} DBusVoiceIn; + +static void *dbus_get_buffer_out(HWVoiceOut *hw, size_t *size) +{ + DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw); + + if (!vo->buf) { + vo->buf_size = hw->samples * hw->info.bytes_per_frame; + vo->buf = g_malloc(vo->buf_size); + vo->buf_pos = 0; + } + + *size = MIN(vo->buf_size - vo->buf_pos, *size); + *size = audio_rate_get_bytes(&hw->info, &vo->rate, *size); + + return vo->buf + vo->buf_pos; + +} + +static size_t dbus_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) +{ + DBusAudio *da = (DBusAudio *)hw->s->drv_opaque; + DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw); + GHashTableIter iter; + QemuDBusDisplay1AudioOutListener *listener = NULL; + g_autoptr(GBytes) bytes = NULL; + g_autoptr(GVariant) v_data = NULL; + + assert(buf == vo->buf + vo->buf_pos && vo->buf_pos + size <= vo->buf_size); + vo->buf_pos += size; + + trace_dbus_audio_put_buffer_out(size); + + if (vo->buf_pos < vo->buf_size) { + return size; + } + + bytes = g_bytes_new_take(g_steal_pointer(&vo->buf), vo->buf_size); + v_data = g_variant_new_from_bytes(G_VARIANT_TYPE("ay"), bytes, TRUE); + g_variant_ref_sink(v_data); + + g_hash_table_iter_init(&iter, da->out_listeners); + while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) { + qemu_dbus_display1_audio_out_listener_call_write( + listener, + (uintptr_t)hw, + v_data, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + } + + return size; +} + +#ifdef HOST_WORDS_BIGENDIAN +#define AUDIO_HOST_BE TRUE +#else +#define AUDIO_HOST_BE FALSE +#endif + +static void +dbus_init_out_listener(QemuDBusDisplay1AudioOutListener *listener, + HWVoiceOut *hw) +{ + qemu_dbus_display1_audio_out_listener_call_init( + listener, + (uintptr_t)hw, + hw->info.bits, + hw->info.is_signed, + hw->info.is_float, + hw->info.freq, + hw->info.nchannels, + hw->info.bytes_per_frame, + hw->info.bytes_per_second, + hw->info.swap_endianness ? !AUDIO_HOST_BE : AUDIO_HOST_BE, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); +} + +static int +dbus_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque) +{ + DBusAudio *da = (DBusAudio *)hw->s->drv_opaque; + DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw); + GHashTableIter iter; + QemuDBusDisplay1AudioOutListener *listener = NULL; + + audio_pcm_init_info(&hw->info, as); + hw->samples = DBUS_AUDIO_NSAMPLES; + audio_rate_start(&vo->rate); + + g_hash_table_iter_init(&iter, da->out_listeners); + while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) { + dbus_init_out_listener(listener, hw); + } + return 0; +} + +static void +dbus_fini_out(HWVoiceOut *hw) +{ + DBusAudio *da = (DBusAudio *)hw->s->drv_opaque; + DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw); + GHashTableIter iter; + QemuDBusDisplay1AudioOutListener *listener = NULL; + + g_hash_table_iter_init(&iter, da->out_listeners); + while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) { + qemu_dbus_display1_audio_out_listener_call_fini( + listener, + (uintptr_t)hw, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + } + + g_clear_pointer(&vo->buf, g_free); +} + +static void +dbus_enable_out(HWVoiceOut *hw, bool enable) +{ + DBusAudio *da = (DBusAudio *)hw->s->drv_opaque; + DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw); + GHashTableIter iter; + QemuDBusDisplay1AudioOutListener *listener = NULL; + + vo->enabled = enable; + if (enable) { + audio_rate_start(&vo->rate); + } + + g_hash_table_iter_init(&iter, da->out_listeners); + while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) { + qemu_dbus_display1_audio_out_listener_call_set_enabled( + listener, (uintptr_t)hw, enable, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + } +} + +static void +dbus_volume_out_listener(HWVoiceOut *hw, + QemuDBusDisplay1AudioOutListener *listener) +{ + DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw); + Volume *vol = &vo->volume; + g_autoptr(GBytes) bytes = NULL; + GVariant *v_vol = NULL; + + if (!vo->has_volume) { + return; + } + + assert(vol->channels < sizeof(vol->vol)); + bytes = g_bytes_new(vol->vol, vol->channels); + v_vol = g_variant_new_from_bytes(G_VARIANT_TYPE("ay"), bytes, TRUE); + qemu_dbus_display1_audio_out_listener_call_set_volume( + listener, (uintptr_t)hw, vol->mute, v_vol, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); +} + +static void +dbus_volume_out(HWVoiceOut *hw, Volume *vol) +{ + DBusAudio *da = (DBusAudio *)hw->s->drv_opaque; + DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw); + GHashTableIter iter; + QemuDBusDisplay1AudioOutListener *listener = NULL; + + vo->has_volume = true; + vo->volume = *vol; + + g_hash_table_iter_init(&iter, da->out_listeners); + while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) { + dbus_volume_out_listener(hw, listener); + } +} + +static void +dbus_init_in_listener(QemuDBusDisplay1AudioInListener *listener, HWVoiceIn *hw) +{ + qemu_dbus_display1_audio_in_listener_call_init( + listener, + (uintptr_t)hw, + hw->info.bits, + hw->info.is_signed, + hw->info.is_float, + hw->info.freq, + hw->info.nchannels, + hw->info.bytes_per_frame, + hw->info.bytes_per_second, + hw->info.swap_endianness ? !AUDIO_HOST_BE : AUDIO_HOST_BE, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); +} + +static int +dbus_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) +{ + DBusAudio *da = (DBusAudio *)hw->s->drv_opaque; + DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw); + GHashTableIter iter; + QemuDBusDisplay1AudioInListener *listener = NULL; + + audio_pcm_init_info(&hw->info, as); + hw->samples = DBUS_AUDIO_NSAMPLES; + audio_rate_start(&vo->rate); + + g_hash_table_iter_init(&iter, da->in_listeners); + while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) { + dbus_init_in_listener(listener, hw); + } + return 0; +} + +static void +dbus_fini_in(HWVoiceIn *hw) +{ + DBusAudio *da = (DBusAudio *)hw->s->drv_opaque; + GHashTableIter iter; + QemuDBusDisplay1AudioInListener *listener = NULL; + + g_hash_table_iter_init(&iter, da->in_listeners); + while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) { + qemu_dbus_display1_audio_in_listener_call_fini( + listener, + (uintptr_t)hw, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + } +} + +static void +dbus_volume_in_listener(HWVoiceIn *hw, + QemuDBusDisplay1AudioInListener *listener) +{ + DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw); + Volume *vol = &vo->volume; + g_autoptr(GBytes) bytes = NULL; + GVariant *v_vol = NULL; + + if (!vo->has_volume) { + return; + } + + assert(vol->channels < sizeof(vol->vol)); + bytes = g_bytes_new(vol->vol, vol->channels); + v_vol = g_variant_new_from_bytes(G_VARIANT_TYPE("ay"), bytes, TRUE); + qemu_dbus_display1_audio_in_listener_call_set_volume( + listener, (uintptr_t)hw, vol->mute, v_vol, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); +} + +static void +dbus_volume_in(HWVoiceIn *hw, Volume *vol) +{ + DBusAudio *da = (DBusAudio *)hw->s->drv_opaque; + DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw); + GHashTableIter iter; + QemuDBusDisplay1AudioInListener *listener = NULL; + + vo->has_volume = true; + vo->volume = *vol; + + g_hash_table_iter_init(&iter, da->in_listeners); + while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) { + dbus_volume_in_listener(hw, listener); + } +} + +static size_t +dbus_read(HWVoiceIn *hw, void *buf, size_t size) +{ + DBusAudio *da = (DBusAudio *)hw->s->drv_opaque; + /* DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw); */ + GHashTableIter iter; + QemuDBusDisplay1AudioInListener *listener = NULL; + + trace_dbus_audio_read(size); + + /* size = audio_rate_get_bytes(&hw->info, &vo->rate, size); */ + + g_hash_table_iter_init(&iter, da->in_listeners); + while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) { + g_autoptr(GVariant) v_data = NULL; + const char *data; + gsize n = 0; + + if (qemu_dbus_display1_audio_in_listener_call_read_sync( + listener, + (uintptr_t)hw, + size, + G_DBUS_CALL_FLAGS_NONE, -1, + &v_data, NULL, NULL)) { + data = g_variant_get_fixed_array(v_data, &n, 1); + g_warn_if_fail(n <= size); + size = MIN(n, size); + memcpy(buf, data, size); + break; + } + } + + return size; +} + +static void +dbus_enable_in(HWVoiceIn *hw, bool enable) +{ + DBusAudio *da = (DBusAudio *)hw->s->drv_opaque; + DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw); + GHashTableIter iter; + QemuDBusDisplay1AudioInListener *listener = NULL; + + vo->enabled = enable; + if (enable) { + audio_rate_start(&vo->rate); + } + + g_hash_table_iter_init(&iter, da->in_listeners); + while (g_hash_table_iter_next(&iter, NULL, (void **)&listener)) { + qemu_dbus_display1_audio_in_listener_call_set_enabled( + listener, (uintptr_t)hw, enable, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + } +} + +static void * +dbus_audio_init(Audiodev *dev) +{ + DBusAudio *da = g_new0(DBusAudio, 1); + + da->out_listeners = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_object_unref); + da->in_listeners = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_object_unref); + return da; +} + +static void +dbus_audio_fini(void *opaque) +{ + DBusAudio *da = opaque; + + if (da->server) { + g_dbus_object_manager_server_unexport(da->server, + DBUS_DISPLAY1_AUDIO_PATH); + } + g_clear_object(&da->audio); + g_clear_object(&da->iface); + g_clear_pointer(&da->in_listeners, g_hash_table_unref); + g_clear_pointer(&da->out_listeners, g_hash_table_unref); + g_clear_object(&da->server); + g_free(da); +} + +static void +listener_out_vanished_cb(GDBusConnection *connection, + gboolean remote_peer_vanished, + GError *error, + DBusAudio *da) +{ + char *name = g_object_get_data(G_OBJECT(connection), "name"); + + g_hash_table_remove(da->out_listeners, name); +} + +static void +listener_in_vanished_cb(GDBusConnection *connection, + gboolean remote_peer_vanished, + GError *error, + DBusAudio *da) +{ + char *name = g_object_get_data(G_OBJECT(connection), "name"); + + g_hash_table_remove(da->in_listeners, name); +} + +static gboolean +dbus_audio_register_listener(AudioState *s, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + GVariant *arg_listener, + bool out) +{ + DBusAudio *da = s->drv_opaque; + const char *sender = g_dbus_method_invocation_get_sender(invocation); + g_autoptr(GDBusConnection) listener_conn = NULL; + g_autoptr(GError) err = NULL; + g_autoptr(GSocket) socket = NULL; + g_autoptr(GSocketConnection) socket_conn = NULL; + g_autofree char *guid = g_dbus_generate_guid(); + GHashTable *listeners = out ? da->out_listeners : da->in_listeners; + GObject *listener; + int fd; + + trace_dbus_audio_register(sender, out ? "out" : "in"); + + if (g_hash_table_contains(listeners, sender)) { + g_dbus_method_invocation_return_error(invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_INVALID, + "`%s` is already registered!", + sender); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + fd = g_unix_fd_list_get(fd_list, g_variant_get_handle(arg_listener), &err); + if (err) { + g_dbus_method_invocation_return_error(invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Couldn't get peer fd: %s", + err->message); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + socket = g_socket_new_from_fd(fd, &err); + if (err) { + g_dbus_method_invocation_return_error(invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Couldn't make a socket: %s", + err->message); + return DBUS_METHOD_INVOCATION_HANDLED; + } + socket_conn = g_socket_connection_factory_create_connection(socket); + if (out) { + qemu_dbus_display1_audio_complete_register_out_listener( + da->iface, invocation, NULL); + } else { + qemu_dbus_display1_audio_complete_register_in_listener( + da->iface, invocation, NULL); + } + + listener_conn = + g_dbus_connection_new_sync( + G_IO_STREAM(socket_conn), + guid, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER, + NULL, NULL, &err); + if (err) { + error_report("Failed to setup peer connection: %s", err->message); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + listener = out ? + G_OBJECT(qemu_dbus_display1_audio_out_listener_proxy_new_sync( + listener_conn, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + "/org/qemu/Display1/AudioOutListener", + NULL, + &err)) : + G_OBJECT(qemu_dbus_display1_audio_in_listener_proxy_new_sync( + listener_conn, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + "/org/qemu/Display1/AudioInListener", + NULL, + &err)); + if (!listener) { + error_report("Failed to setup proxy: %s", err->message); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + if (out) { + HWVoiceOut *hw; + + QLIST_FOREACH(hw, &s->hw_head_out, entries) { + DBusVoiceOut *vo = container_of(hw, DBusVoiceOut, hw); + QemuDBusDisplay1AudioOutListener *l = + QEMU_DBUS_DISPLAY1_AUDIO_OUT_LISTENER(listener); + + dbus_init_out_listener(l, hw); + qemu_dbus_display1_audio_out_listener_call_set_enabled( + l, (uintptr_t)hw, vo->enabled, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + } + } else { + HWVoiceIn *hw; + + QLIST_FOREACH(hw, &s->hw_head_in, entries) { + DBusVoiceIn *vo = container_of(hw, DBusVoiceIn, hw); + QemuDBusDisplay1AudioInListener *l = + QEMU_DBUS_DISPLAY1_AUDIO_IN_LISTENER(listener); + + dbus_init_in_listener( + QEMU_DBUS_DISPLAY1_AUDIO_IN_LISTENER(listener), hw); + qemu_dbus_display1_audio_in_listener_call_set_enabled( + l, (uintptr_t)hw, vo->enabled, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + } + } + + g_object_set_data_full(G_OBJECT(listener_conn), "name", + g_strdup(sender), g_free); + g_hash_table_insert(listeners, g_strdup(sender), listener); + g_object_connect(listener_conn, + "signal::closed", + out ? listener_out_vanished_cb : listener_in_vanished_cb, + da, + NULL); + + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +dbus_audio_register_out_listener(AudioState *s, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + GVariant *arg_listener) +{ + return dbus_audio_register_listener(s, invocation, + fd_list, arg_listener, true); + +} + +static gboolean +dbus_audio_register_in_listener(AudioState *s, + GDBusMethodInvocation *invocation, + GUnixFDList *fd_list, + GVariant *arg_listener) +{ + return dbus_audio_register_listener(s, invocation, + fd_list, arg_listener, false); +} + +static void +dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server) +{ + DBusAudio *da = s->drv_opaque; + + g_assert(da); + g_assert(!da->server); + + da->server = g_object_ref(server); + + da->audio = g_dbus_object_skeleton_new(DBUS_DISPLAY1_AUDIO_PATH); + da->iface = qemu_dbus_display1_audio_skeleton_new(); + g_object_connect(da->iface, + "swapped-signal::handle-register-in-listener", + dbus_audio_register_in_listener, s, + "swapped-signal::handle-register-out-listener", + dbus_audio_register_out_listener, s, + NULL); + + g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(da->audio), + G_DBUS_INTERFACE_SKELETON(da->iface)); + g_dbus_object_manager_server_export(da->server, da->audio); +} + +static struct audio_pcm_ops dbus_pcm_ops = { + .init_out = dbus_init_out, + .fini_out = dbus_fini_out, + .write = audio_generic_write, + .get_buffer_out = dbus_get_buffer_out, + .put_buffer_out = dbus_put_buffer_out, + .enable_out = dbus_enable_out, + .volume_out = dbus_volume_out, + + .init_in = dbus_init_in, + .fini_in = dbus_fini_in, + .read = dbus_read, + .run_buffer_in = audio_generic_run_buffer_in, + .enable_in = dbus_enable_in, + .volume_in = dbus_volume_in, +}; + +static struct audio_driver dbus_audio_driver = { + .name = "dbus", + .descr = "Timer based audio exposed with DBus interface", + .init = dbus_audio_init, + .fini = dbus_audio_fini, + .set_dbus_server = dbus_audio_set_server, + .pcm_ops = &dbus_pcm_ops, + .can_be_default = 1, + .max_voices_out = INT_MAX, + .max_voices_in = INT_MAX, + .voice_size_out = sizeof(DBusVoiceOut), + .voice_size_in = sizeof(DBusVoiceIn) +}; + +static void register_audio_dbus(void) +{ + audio_driver_register(&dbus_audio_driver); +} +type_init(register_audio_dbus); + +module_dep("ui-dbus") diff --git a/audio/meson.build b/audio/meson.build index 462533bb8c..0ac3791d0b 100644 --- a/audio/meson.build +++ b/audio/meson.build @@ -26,4 +26,10 @@ foreach m : [ endif endforeach +if dbus_display + module_ss = ss.source_set() + module_ss.add(when: gio, if_true: files('dbusaudio.c')) + audio_modules += {'dbus': module_ss} +endif + modules += {'audio': audio_modules} diff --git a/audio/trace-events b/audio/trace-events index 957c92337b..e1ab643add 100644 --- a/audio/trace-events +++ b/audio/trace-events @@ -13,6 +13,11 @@ alsa_resume_out(void) "Resuming suspended output stream" # ossaudio.c oss_version(int version) "OSS version = 0x%x" +# dbusaudio.c +dbus_audio_register(const char *s, const char *dir) "sender = %s, dir = %s" +dbus_audio_put_buffer_out(size_t len) "len = %zu" +dbus_audio_read(size_t len) "len = %zu" + # audio.c audio_timer_start(int interval) "interval %d ms" audio_timer_stop(void) "" diff --git a/qapi/audio.json b/qapi/audio.json index 9cba0df8a4..693e327c6b 100644 --- a/qapi/audio.json +++ b/qapi/audio.json @@ -386,7 +386,7 @@ # Since: 4.0 ## { 'enum': 'AudiodevDriver', - 'data': [ 'none', 'alsa', 'coreaudio', 'dsound', 'jack', 'oss', 'pa', + 'data': [ 'none', 'alsa', 'coreaudio', 'dbus', 'dsound', 'jack', 'oss', 'pa', 'sdl', 'spice', 'wav' ] } ## @@ -412,6 +412,7 @@ 'none': 'AudiodevGenericOptions', 'alsa': 'AudiodevAlsaOptions', 'coreaudio': 'AudiodevCoreaudioOptions', + 'dbus': 'AudiodevGenericOptions', 'dsound': 'AudiodevDsoundOptions', 'jack': 'AudiodevJackOptions', 'oss': 'AudiodevOssOptions', diff --git a/qapi/ui.json b/qapi/ui.json index d435e94722..2b4371da37 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -1134,13 +1134,16 @@ # @p2p: Whether to use peer-to-peer connections (accepted through # ``add_client``). # +# @audiodev: Use the specified DBus audiodev to export audio. +# # Since: 7.0 # ## { 'struct' : 'DisplayDBus', 'data' : { '*rendernode' : 'str', '*addr': 'str', - '*p2p': 'bool' } } + '*p2p': 'bool', + '*audiodev': 'str' } } ## # @DisplayGLMode: diff --git a/qemu-options.hx b/qemu-options.hx index 977e0873a1..7d47510947 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -659,6 +659,9 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, #endif #ifdef CONFIG_SPICE "-audiodev spice,id=id[,prop[=value][,...]]\n" +#endif +#ifdef CONFIG_DBUS_DISPLAY + "-audiodev dbus,id=id[,prop[=value][,...]]\n" #endif "-audiodev wav,id=id[,prop[=value][,...]]\n" " path= path of wav file to record\n", diff --git a/ui/dbus-display1.xml b/ui/dbus-display1.xml index 0f0ae92e4d..aff645220c 100644 --- a/ui/dbus-display1.xml +++ b/ui/dbus-display1.xml @@ -375,4 +375,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/dbus.c b/ui/dbus.c index 847a667821..d24f704d46 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -30,6 +30,8 @@ #include "ui/dbus-module.h" #include "ui/egl-helpers.h" #include "ui/egl-context.h" +#include "audio/audio.h" +#include "audio/audio_int.h" #include "qapi/error.h" #include "trace.h" @@ -84,6 +86,7 @@ dbus_display_finalize(Object *o) g_clear_object(&dd->bus); g_clear_object(&dd->iface); g_free(dd->dbus_addr); + g_free(dd->audiodev); dbus_display = NULL; } @@ -140,6 +143,19 @@ dbus_display_complete(UserCreatable *uc, Error **errp) return; } + if (dd->audiodev && *dd->audiodev) { + AudioState *audio_state = audio_state_by_name(dd->audiodev); + if (!audio_state) { + error_setg(errp, "Audiodev '%s' not found", dd->audiodev); + return; + } + if (!g_str_equal(audio_state->drv->name, "dbus")) { + error_setg(errp, "Audiodev '%s' is not compatible with DBus", + dd->audiodev); + return; + } + audio_state->drv->set_dbus_server(audio_state, dd->server); + } consoles = g_array_new(FALSE, FALSE, sizeof(guint32)); for (idx = 0;; idx++) { @@ -261,6 +277,23 @@ set_dbus_addr(Object *o, const char *str, Error **errp) dd->dbus_addr = g_strdup(str); } +static char * +get_audiodev(Object *o, Error **errp) +{ + DBusDisplay *dd = DBUS_DISPLAY(o); + + return g_strdup(dd->audiodev); +} + +static void +set_audiodev(Object *o, const char *str, Error **errp) +{ + DBusDisplay *dd = DBUS_DISPLAY(o); + + g_free(dd->audiodev); + dd->audiodev = g_strdup(str); +} + static int get_gl_mode(Object *o, Error **errp) { @@ -285,6 +318,7 @@ dbus_display_class_init(ObjectClass *oc, void *data) ucc->complete = dbus_display_complete; object_class_property_add_bool(oc, "p2p", get_dbus_p2p, set_dbus_p2p); object_class_property_add_str(oc, "addr", get_dbus_addr, set_dbus_addr); + object_class_property_add_str(oc, "audiodev", get_audiodev, set_audiodev); object_class_property_add_enum(oc, "gl-mode", "DisplayGLMode", &DisplayGLMode_lookup, get_gl_mode, set_gl_mode); @@ -321,6 +355,7 @@ dbus_init(DisplayState *ds, DisplayOptions *opts) object_get_objects_root(), "dbus-display", &error_fatal, "addr", opts->u.dbus.addr ?: "", + "audiodev", opts->u.dbus.audiodev ?: "", "gl-mode", DisplayGLMode_str(mode), "p2p", yes_no(opts->u.dbus.p2p), NULL); diff --git a/ui/dbus.h b/ui/dbus.h index 4698d32463..ca1f0f4ab9 100644 --- a/ui/dbus.h +++ b/ui/dbus.h @@ -36,6 +36,7 @@ struct DBusDisplay { DisplayGLMode gl_mode; bool p2p; char *dbus_addr; + char *audiodev; DisplayGLCtx glctx; GDBusConnection *bus; From ff1a5810f61f78b47ddad995f49bcc70171d9e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 20 Jul 2021 16:02:52 +0400 Subject: [PATCH 030/730] ui/dbus: add clipboard interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expose the clipboard API over D-Bus. See the interface documentation for further details. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- ui/dbus-clipboard.c | 457 +++++++++++++++++++++++++++++++++++++++++++ ui/dbus-display1.xml | 97 +++++++++ ui/dbus.c | 7 + ui/dbus.h | 14 ++ ui/meson.build | 1 + ui/trace-events | 3 + 6 files changed, 579 insertions(+) create mode 100644 ui/dbus-clipboard.c diff --git a/ui/dbus-clipboard.c b/ui/dbus-clipboard.c new file mode 100644 index 0000000000..5843d26cd2 --- /dev/null +++ b/ui/dbus-clipboard.c @@ -0,0 +1,457 @@ +/* + * QEMU DBus display + * + * Copyright (c) 2021 Marc-André Lureau + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "qemu/dbus.h" +#include "qemu/main-loop.h" +#include "qom/object_interfaces.h" +#include "sysemu/sysemu.h" +#include "qapi/error.h" +#include "trace.h" + +#include "dbus.h" + +#define MIME_TEXT_PLAIN_UTF8 "text/plain;charset=utf-8" + +static void +dbus_clipboard_complete_request( + DBusDisplay *dpy, + GDBusMethodInvocation *invocation, + QemuClipboardInfo *info, + QemuClipboardType type) +{ + GVariant *v_data = g_variant_new_from_data( + G_VARIANT_TYPE("ay"), + info->types[type].data, + info->types[type].size, + TRUE, + (GDestroyNotify)qemu_clipboard_info_unref, + qemu_clipboard_info_ref(info)); + + qemu_dbus_display1_clipboard_complete_request( + dpy->clipboard, invocation, + MIME_TEXT_PLAIN_UTF8, v_data); +} + +static void +dbus_clipboard_update_info(DBusDisplay *dpy, QemuClipboardInfo *info) +{ + bool self_update = info->owner == &dpy->clipboard_peer; + const char *mime[QEMU_CLIPBOARD_TYPE__COUNT + 1] = { 0, }; + DBusClipboardRequest *req; + int i = 0; + + if (info->owner == NULL) { + if (dpy->clipboard_proxy) { + qemu_dbus_display1_clipboard_call_release( + dpy->clipboard_proxy, + info->selection, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + } + return; + } + + if (self_update || !info->has_serial) { + return; + } + + req = &dpy->clipboard_request[info->selection]; + if (req->invocation && info->types[req->type].data) { + dbus_clipboard_complete_request(dpy, req->invocation, info, req->type); + g_clear_object(&req->invocation); + g_source_remove(req->timeout_id); + req->timeout_id = 0; + return; + } + + if (info->types[QEMU_CLIPBOARD_TYPE_TEXT].available) { + mime[i++] = MIME_TEXT_PLAIN_UTF8; + } + + if (i > 0) { + if (dpy->clipboard_proxy) { + qemu_dbus_display1_clipboard_call_grab( + dpy->clipboard_proxy, + info->selection, + info->serial, + mime, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + } + } +} + +static void +dbus_clipboard_reset_serial(DBusDisplay *dpy) +{ + if (dpy->clipboard_proxy) { + qemu_dbus_display1_clipboard_call_register( + dpy->clipboard_proxy, + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, NULL, NULL); + } +} + +static void +dbus_clipboard_notify(Notifier *notifier, void *data) +{ + DBusDisplay *dpy = + container_of(notifier, DBusDisplay, clipboard_peer.notifier); + QemuClipboardNotify *notify = data; + + switch (notify->type) { + case QEMU_CLIPBOARD_UPDATE_INFO: + dbus_clipboard_update_info(dpy, notify->info); + return; + case QEMU_CLIPBOARD_RESET_SERIAL: + dbus_clipboard_reset_serial(dpy); + return; + } +} + +static void +dbus_clipboard_qemu_request(QemuClipboardInfo *info, + QemuClipboardType type) +{ + DBusDisplay *dpy = container_of(info->owner, DBusDisplay, clipboard_peer); + g_autofree char *mime = NULL; + g_autoptr(GVariant) v_data = NULL; + g_autoptr(GError) err = NULL; + const char *data = NULL; + const char *mimes[] = { MIME_TEXT_PLAIN_UTF8, NULL }; + size_t n; + + if (type != QEMU_CLIPBOARD_TYPE_TEXT) { + /* unsupported atm */ + return; + } + + if (dpy->clipboard_proxy) { + if (!qemu_dbus_display1_clipboard_call_request_sync( + dpy->clipboard_proxy, + info->selection, + mimes, + G_DBUS_CALL_FLAGS_NONE, -1, &mime, &v_data, NULL, &err)) { + error_report("Failed to request clipboard: %s", err->message); + return; + } + + if (g_strcmp0(mime, MIME_TEXT_PLAIN_UTF8)) { + error_report("Unsupported returned MIME: %s", mime); + return; + } + + data = g_variant_get_fixed_array(v_data, &n, 1); + qemu_clipboard_set_data(&dpy->clipboard_peer, info, type, + n, data, true); + } +} + +static void +dbus_clipboard_request_cancelled(DBusClipboardRequest *req) +{ + if (!req->invocation) { + return; + } + + g_dbus_method_invocation_return_error( + req->invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Cancelled clipboard request"); + + g_clear_object(&req->invocation); + g_source_remove(req->timeout_id); + req->timeout_id = 0; +} + +static void +dbus_clipboard_unregister_proxy(DBusDisplay *dpy) +{ + const char *name = NULL; + int i; + + for (i = 0; i < G_N_ELEMENTS(dpy->clipboard_request); ++i) { + dbus_clipboard_request_cancelled(&dpy->clipboard_request[i]); + } + + if (!dpy->clipboard_proxy) { + return; + } + + name = g_dbus_proxy_get_name(G_DBUS_PROXY(dpy->clipboard_proxy)); + trace_dbus_clipboard_unregister(name); + g_clear_object(&dpy->clipboard_proxy); +} + +static void +dbus_on_clipboard_proxy_name_owner_changed( + DBusDisplay *dpy, + GObject *object, + GParamSpec *pspec) +{ + dbus_clipboard_unregister_proxy(dpy); +} + +static gboolean +dbus_clipboard_register( + DBusDisplay *dpy, + GDBusMethodInvocation *invocation) +{ + g_autoptr(GError) err = NULL; + const char *name = NULL; + + if (dpy->clipboard_proxy) { + g_dbus_method_invocation_return_error( + invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Clipboard peer already registered!"); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + dpy->clipboard_proxy = + qemu_dbus_display1_clipboard_proxy_new_sync( + g_dbus_method_invocation_get_connection(invocation), + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + g_dbus_method_invocation_get_sender(invocation), + "/org/qemu/Display1/Clipboard", + NULL, + &err); + if (!dpy->clipboard_proxy) { + g_dbus_method_invocation_return_error( + invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Failed to setup proxy: %s", err->message); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + name = g_dbus_proxy_get_name(G_DBUS_PROXY(dpy->clipboard_proxy)); + trace_dbus_clipboard_register(name); + + g_object_connect(dpy->clipboard_proxy, + "swapped-signal::notify::g-name-owner", + dbus_on_clipboard_proxy_name_owner_changed, dpy, + NULL); + qemu_clipboard_reset_serial(); + + qemu_dbus_display1_clipboard_complete_register(dpy->clipboard, invocation); + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +dbus_clipboard_check_caller(DBusDisplay *dpy, GDBusMethodInvocation *invocation) +{ + if (!dpy->clipboard_proxy || + g_strcmp0(g_dbus_proxy_get_name(G_DBUS_PROXY(dpy->clipboard_proxy)), + g_dbus_method_invocation_get_sender(invocation))) { + g_dbus_method_invocation_return_error( + invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Unregistered caller"); + return FALSE; + } + + return TRUE; +} + +static gboolean +dbus_clipboard_unregister( + DBusDisplay *dpy, + GDBusMethodInvocation *invocation) +{ + if (!dbus_clipboard_check_caller(dpy, invocation)) { + return DBUS_METHOD_INVOCATION_HANDLED; + } + + dbus_clipboard_unregister_proxy(dpy); + + qemu_dbus_display1_clipboard_complete_unregister( + dpy->clipboard, invocation); + + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +dbus_clipboard_grab( + DBusDisplay *dpy, + GDBusMethodInvocation *invocation, + gint arg_selection, + guint arg_serial, + const gchar *const *arg_mimes) +{ + QemuClipboardSelection s = arg_selection; + g_autoptr(QemuClipboardInfo) info = NULL; + + if (!dbus_clipboard_check_caller(dpy, invocation)) { + return DBUS_METHOD_INVOCATION_HANDLED; + } + + if (s >= QEMU_CLIPBOARD_SELECTION__COUNT) { + g_dbus_method_invocation_return_error( + invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Invalid clipboard selection: %d", arg_selection); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + info = qemu_clipboard_info_new(&dpy->clipboard_peer, s); + if (g_strv_contains(arg_mimes, MIME_TEXT_PLAIN_UTF8)) { + info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true; + } + info->serial = arg_serial; + info->has_serial = true; + if (qemu_clipboard_check_serial(info, true)) { + qemu_clipboard_update(info); + } else { + trace_dbus_clipboard_grab_failed(); + } + + qemu_dbus_display1_clipboard_complete_grab(dpy->clipboard, invocation); + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +dbus_clipboard_release( + DBusDisplay *dpy, + GDBusMethodInvocation *invocation, + gint arg_selection) +{ + if (!dbus_clipboard_check_caller(dpy, invocation)) { + return DBUS_METHOD_INVOCATION_HANDLED; + } + + qemu_clipboard_peer_release(&dpy->clipboard_peer, arg_selection); + + qemu_dbus_display1_clipboard_complete_release(dpy->clipboard, invocation); + return DBUS_METHOD_INVOCATION_HANDLED; +} + +static gboolean +dbus_clipboard_request_timeout(gpointer user_data) +{ + dbus_clipboard_request_cancelled(user_data); + return G_SOURCE_REMOVE; +} + +static gboolean +dbus_clipboard_request( + DBusDisplay *dpy, + GDBusMethodInvocation *invocation, + gint arg_selection, + const gchar *const *arg_mimes) +{ + QemuClipboardSelection s = arg_selection; + QemuClipboardType type = QEMU_CLIPBOARD_TYPE_TEXT; + QemuClipboardInfo *info = NULL; + + if (!dbus_clipboard_check_caller(dpy, invocation)) { + return DBUS_METHOD_INVOCATION_HANDLED; + } + + if (s >= QEMU_CLIPBOARD_SELECTION__COUNT) { + g_dbus_method_invocation_return_error( + invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Invalid clipboard selection: %d", arg_selection); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + if (dpy->clipboard_request[s].invocation) { + g_dbus_method_invocation_return_error( + invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Pending request"); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + info = qemu_clipboard_info(s); + if (!info || !info->owner || info->owner == &dpy->clipboard_peer) { + g_dbus_method_invocation_return_error( + invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Empty clipboard"); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + if (!g_strv_contains(arg_mimes, MIME_TEXT_PLAIN_UTF8) || + !info->types[type].available) { + g_dbus_method_invocation_return_error( + invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Unhandled MIME types requested"); + return DBUS_METHOD_INVOCATION_HANDLED; + } + + if (info->types[type].data) { + dbus_clipboard_complete_request(dpy, invocation, info, type); + } else { + qemu_clipboard_request(info, type); + + dpy->clipboard_request[s].invocation = g_object_ref(invocation); + dpy->clipboard_request[s].type = type; + dpy->clipboard_request[s].timeout_id = + g_timeout_add_seconds(5, dbus_clipboard_request_timeout, + &dpy->clipboard_request[s]); + } + + return DBUS_METHOD_INVOCATION_HANDLED; +} + +void +dbus_clipboard_init(DBusDisplay *dpy) +{ + g_autoptr(GDBusObjectSkeleton) clipboard = NULL; + + assert(!dpy->clipboard); + + clipboard = g_dbus_object_skeleton_new(DBUS_DISPLAY1_ROOT "/Clipboard"); + dpy->clipboard = qemu_dbus_display1_clipboard_skeleton_new(); + g_object_connect(dpy->clipboard, + "swapped-signal::handle-register", + dbus_clipboard_register, dpy, + "swapped-signal::handle-unregister", + dbus_clipboard_unregister, dpy, + "swapped-signal::handle-grab", + dbus_clipboard_grab, dpy, + "swapped-signal::handle-release", + dbus_clipboard_release, dpy, + "swapped-signal::handle-request", + dbus_clipboard_request, dpy, + NULL); + + g_dbus_object_skeleton_add_interface( + G_DBUS_OBJECT_SKELETON(clipboard), + G_DBUS_INTERFACE_SKELETON(dpy->clipboard)); + g_dbus_object_manager_server_export(dpy->server, clipboard); + dpy->clipboard_peer.name = "dbus"; + dpy->clipboard_peer.notifier.notify = dbus_clipboard_notify; + dpy->clipboard_peer.request = dbus_clipboard_qemu_request; + qemu_clipboard_peer_register(&dpy->clipboard_peer); +} diff --git a/ui/dbus-display1.xml b/ui/dbus-display1.xml index aff645220c..767562ad1e 100644 --- a/ui/dbus-display1.xml +++ b/ui/dbus-display1.xml @@ -376,6 +376,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/dbus.c b/ui/dbus.c index 4f0bc293aa..41f1716f25 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -55,6 +55,27 @@ static const DisplayGLCtxOps dbus_gl_ops = { .dpy_gl_ctx_make_current = qemu_egl_make_context_current, }; +static NotifierList dbus_display_notifiers = + NOTIFIER_LIST_INITIALIZER(dbus_display_notifiers); + +void +dbus_display_notifier_add(Notifier *notifier) +{ + notifier_list_add(&dbus_display_notifiers, notifier); +} + +static void +dbus_display_notifier_remove(Notifier *notifier) +{ + notifier_remove(notifier); +} + +void +dbus_display_notify(DBusDisplayEvent *event) +{ + notifier_list_notify(&dbus_display_notifiers, event); +} + static void dbus_display_init(Object *o) { @@ -73,6 +94,7 @@ dbus_display_init(Object *o) g_dbus_object_manager_server_export(dd->server, vm); dbus_clipboard_init(dd); + dbus_chardev_init(dd); } static void @@ -80,6 +102,10 @@ dbus_display_finalize(Object *o) { DBusDisplay *dd = DBUS_DISPLAY(o); + if (dd->notifier.notify) { + dbus_display_notifier_remove(&dd->notifier); + } + qemu_clipboard_peer_unregister(&dd->clipboard_peer); g_clear_object(&dd->clipboard); diff --git a/ui/dbus.h b/ui/dbus.h index 3e89eafcab..64c77cab44 100644 --- a/ui/dbus.h +++ b/ui/dbus.h @@ -24,6 +24,7 @@ #ifndef UI_DBUS_H_ #define UI_DBUS_H_ +#include "chardev/char-socket.h" #include "qemu/dbus.h" #include "qom/object.h" #include "ui/console.h" @@ -56,11 +57,15 @@ struct DBusDisplay { QemuDBusDisplay1Clipboard *clipboard; QemuDBusDisplay1Clipboard *clipboard_proxy; DBusClipboardRequest clipboard_request[QEMU_CLIPBOARD_SELECTION__COUNT]; + + Notifier notifier; }; #define TYPE_DBUS_DISPLAY "dbus-display" OBJECT_DECLARE_SIMPLE_TYPE(DBusDisplay, DBUS_DISPLAY) +void dbus_display_notifier_add(Notifier *notifier); + #define DBUS_DISPLAY_TYPE_CONSOLE dbus_display_console_get_type() G_DECLARE_FINAL_TYPE(DBusDisplayConsole, dbus_display_console, @@ -95,6 +100,45 @@ dbus_display_listener_get_bus_name(DBusDisplayListener *ddl); extern const DisplayChangeListenerOps dbus_gl_dcl_ops; extern const DisplayChangeListenerOps dbus_dcl_ops; +#define TYPE_CHARDEV_DBUS "chardev-dbus" + +typedef struct DBusChardevClass { + SocketChardevClass parent_class; + + void (*parent_chr_be_event)(Chardev *s, QEMUChrEvent event); +} DBusChardevClass; + +DECLARE_CLASS_CHECKERS(DBusChardevClass, DBUS_CHARDEV, + TYPE_CHARDEV_DBUS) + +typedef struct DBusChardev { + SocketChardev parent; + + bool exported; + QemuDBusDisplay1Chardev *iface; +} DBusChardev; + +DECLARE_INSTANCE_CHECKER(DBusChardev, DBUS_CHARDEV, TYPE_CHARDEV_DBUS) + +#define CHARDEV_IS_DBUS(chr) \ + object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_DBUS) + +typedef enum { + DBUS_DISPLAY_CHARDEV_OPEN, + DBUS_DISPLAY_CHARDEV_CLOSE, +} DBusDisplayEventType; + +typedef struct DBusDisplayEvent { + DBusDisplayEventType type; + union { + DBusChardev *chardev; + }; +} DBusDisplayEvent; + +void dbus_display_notify(DBusDisplayEvent *event); + +void dbus_chardev_init(DBusDisplay *dpy); + void dbus_clipboard_init(DBusDisplay *dpy); #endif /* UI_DBUS_H_ */ diff --git a/ui/meson.build b/ui/meson.build index 8982ab63c4..64286ba150 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -82,6 +82,7 @@ if dbus_display '--generate-c-code', '@BASENAME@']) dbus_ss.add(when: [gio, pixman, opengl, 'CONFIG_GIO'], if_true: [files( + 'dbus-chardev.c', 'dbus-clipboard.c', 'dbus-console.c', 'dbus-error.c', From 7f767ca35e54f391061a9f574c916168b0bee1a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 29 Sep 2021 20:32:28 +0400 Subject: [PATCH 035/730] ui/dbus: register D-Bus VC handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Export the default consoles over the D-Bus chardev. Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- ui/dbus.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/ui/dbus.c b/ui/dbus.c index 41f1716f25..b2c1c9fb52 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -357,6 +357,57 @@ dbus_display_class_init(ObjectClass *oc, void *data) get_gl_mode, set_gl_mode); } +#define TYPE_CHARDEV_VC "chardev-vc" + +typedef struct DBusVCClass { + DBusChardevClass parent_class; + + void (*parent_parse)(QemuOpts *opts, ChardevBackend *b, Error **errp); +} DBusVCClass; + +DECLARE_CLASS_CHECKERS(DBusVCClass, DBUS_VC, + TYPE_CHARDEV_VC) + +static void +dbus_vc_parse(QemuOpts *opts, ChardevBackend *backend, + Error **errp) +{ + DBusVCClass *klass = DBUS_VC_CLASS(object_class_by_name(TYPE_CHARDEV_VC)); + const char *name = qemu_opt_get(opts, "name"); + const char *id = qemu_opts_id(opts); + + if (name == NULL) { + if (g_str_has_prefix(id, "compat_monitor")) { + name = "org.qemu.monitor.hmp.0"; + } else if (g_str_has_prefix(id, "serial")) { + name = "org.qemu.console.serial.0"; + } else { + name = ""; + } + if (!qemu_opt_set(opts, "name", name, errp)) { + return; + } + } + + klass->parent_parse(opts, backend, errp); +} + +static void +dbus_vc_class_init(ObjectClass *oc, void *data) +{ + DBusVCClass *klass = DBUS_VC_CLASS(oc); + ChardevClass *cc = CHARDEV_CLASS(oc); + + klass->parent_parse = cc->parse; + cc->parse = dbus_vc_parse; +} + +static const TypeInfo dbus_vc_type_info = { + .name = TYPE_CHARDEV_VC, + .parent = TYPE_CHARDEV_DBUS, + .class_init = dbus_vc_class_init, +}; + static void early_dbus_init(DisplayOptions *opts) { @@ -370,6 +421,8 @@ early_dbus_init(DisplayOptions *opts) display_opengl = 1; } + + type_register(&dbus_vc_type_info); } static void From 89f4df9595e162ce4cc65f31a994a31e3e45ff3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Sun, 10 Oct 2021 00:30:30 +0400 Subject: [PATCH 036/730] MAINTAINERS: update D-Bus section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Acked-by: Gerd Hoffmann --- MAINTAINERS | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 1de6ce6e44..dc4b6f7c1e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2873,11 +2873,15 @@ D-Bus M: Marc-André Lureau S: Maintained F: backends/dbus-vmstate.c -F: tests/dbus-vmstate* +F: ui/dbus* +F: audio/dbus* F: util/dbus.c +F: include/ui/dbus* F: include/qemu/dbus.h -F: docs/interop/dbus.rst -F: docs/interop/dbus-vmstate.rst +F: docs/interop/dbus* +F: docs/sphinx/dbus* +F: docs/sphinx/fakedbusdoc.py +F: tests/qtest/dbus* Seccomp M: Eduardo Otubo From be16b8bf9f231d19c172961d3327f9f72a7cd45f Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Mon, 6 Sep 2021 22:06:48 +0300 Subject: [PATCH 037/730] nbd: allow reconnect on open, with corresponding new options It is useful when start of vm and start of nbd server are not simple to sync. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- block/nbd.c | 45 +++++++++++++++++++++++++++++++++++++++++++- qapi/block-core.json | 9 ++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/block/nbd.c b/block/nbd.c index 5ef462db1b..63dbfa807d 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -80,6 +80,7 @@ typedef struct BDRVNBDState { NBDClientState state; QEMUTimer *reconnect_delay_timer; + QEMUTimer *open_timer; NBDClientRequest requests[MAX_NBD_REQUESTS]; NBDReply reply; @@ -87,6 +88,7 @@ typedef struct BDRVNBDState { /* Connection parameters */ uint32_t reconnect_delay; + uint32_t open_timeout; SocketAddress *saddr; char *export, *tlscredsid; QCryptoTLSCreds *tlscreds; @@ -218,6 +220,32 @@ static void nbd_teardown_connection(BlockDriverState *bs) s->state = NBD_CLIENT_QUIT; } +static void open_timer_del(BDRVNBDState *s) +{ + if (s->open_timer) { + timer_free(s->open_timer); + s->open_timer = NULL; + } +} + +static void open_timer_cb(void *opaque) +{ + BDRVNBDState *s = opaque; + + nbd_co_establish_connection_cancel(s->conn); + open_timer_del(s); +} + +static void open_timer_init(BDRVNBDState *s, uint64_t expire_time_ns) +{ + assert(!s->open_timer); + s->open_timer = aio_timer_new(bdrv_get_aio_context(s->bs), + QEMU_CLOCK_REALTIME, + SCALE_NS, + open_timer_cb, s); + timer_mod(s->open_timer, expire_time_ns); +} + static bool nbd_client_connecting(BDRVNBDState *s) { NBDClientState state = qatomic_load_acquire(&s->state); @@ -1742,6 +1770,15 @@ static QemuOptsList nbd_runtime_opts = { "future requests before a successful reconnect will " "immediately fail. Default 0", }, + { + .name = "open-timeout", + .type = QEMU_OPT_NUMBER, + .help = "In seconds. If zero, the nbd driver tries the connection " + "only once, and fails to open if the connection fails. " + "If non-zero, the nbd driver will repeat connection " + "attempts until successful or until @open-timeout seconds " + "have elapsed. Default 0", + }, { /* end of list */ } }, }; @@ -1797,6 +1834,7 @@ static int nbd_process_options(BlockDriverState *bs, QDict *options, } s->reconnect_delay = qemu_opt_get_number(opts, "reconnect-delay", 0); + s->open_timeout = qemu_opt_get_number(opts, "open-timeout", 0); ret = 0; @@ -1828,7 +1866,12 @@ static int nbd_open(BlockDriverState *bs, QDict *options, int flags, s->conn = nbd_client_connection_new(s->saddr, true, s->export, s->x_dirty_bitmap, s->tlscreds); - /* TODO: Configurable retry-until-timeout behaviour. */ + if (s->open_timeout) { + nbd_client_connection_enable_retry(s->conn); + open_timer_init(s, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + + s->open_timeout * NANOSECONDS_PER_SECOND); + } + s->state = NBD_CLIENT_CONNECTING_WAIT; ret = nbd_do_establish_connection(bs, errp); if (ret < 0) { diff --git a/qapi/block-core.json b/qapi/block-core.json index 1d3dd9cb48..bd0b285245 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -4096,6 +4096,12 @@ # future requests before a successful reconnect will # immediately fail. Default 0 (Since 4.2) # +# @open-timeout: In seconds. If zero, the nbd driver tries the connection +# only once, and fails to open if the connection fails. +# If non-zero, the nbd driver will repeat connection attempts +# until successful or until @open-timeout seconds have elapsed. +# Default 0 (Since 7.0) +# # Features: # @unstable: Member @x-dirty-bitmap is experimental. # @@ -4106,7 +4112,8 @@ '*export': 'str', '*tls-creds': 'str', '*x-dirty-bitmap': { 'type': 'str', 'features': [ 'unstable' ] }, - '*reconnect-delay': 'uint32' } } + '*reconnect-delay': 'uint32', + '*open-timeout': 'uint32' } } ## # @BlockdevOptionsRaw: From 169b9a94ed24a40b2bfc8664ecd2e75cd33d0978 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Mon, 6 Sep 2021 22:06:49 +0300 Subject: [PATCH 038/730] nbd/client-connection: nbd_co_establish_connection(): return real error The only caller of nbd_do_establish_connection() that uses errp is nbd_open(). The only way to cancel this call is through open_timer timeout. And for this case, user will be more interested in description of last failed connect rather than in "Connection attempt cancelled by other operation". So, let's change behavior on cancel to return previous failure error if available. Do the same for non-blocking failure case. In this case we still don't have a caller that is interested in errp. But let's be consistent. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- nbd/client-connection.c | 52 +++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/nbd/client-connection.c b/nbd/client-connection.c index 695f855754..722998c985 100644 --- a/nbd/client-connection.c +++ b/nbd/client-connection.c @@ -39,16 +39,18 @@ struct NBDClientConnection { QemuMutex mutex; - /* - * @sioc and @err represent a connection attempt. While running - * is true, they are only used by the connection thread, and mutex - * locking is not needed. Once the thread finishes, - * nbd_co_establish_connection then steals these pointers while - * under the mutex. - */ NBDExportInfo updated_info; + /* + * @sioc represents a successful result. While thread is running, @sioc is + * used only by thread and not protected by mutex. When thread is not + * running, @sioc is stolen by nbd_co_establish_connection() under mutex. + */ QIOChannelSocket *sioc; QIOChannel *ioc; + /* + * @err represents previous attempt. It may be copied by + * nbd_co_establish_connection() when it reports failure. + */ Error *err; /* All further fields are accessed only under mutex */ @@ -170,18 +172,18 @@ static void *connect_thread_func(void *opaque) qemu_mutex_lock(&conn->mutex); while (!conn->detached) { + Error *local_err = NULL; + assert(!conn->sioc); conn->sioc = qio_channel_socket_new(); qemu_mutex_unlock(&conn->mutex); - error_free(conn->err); - conn->err = NULL; conn->updated_info = conn->initial_info; ret = nbd_connect(conn->sioc, conn->saddr, conn->do_negotiation ? &conn->updated_info : NULL, - conn->tlscreds, &conn->ioc, &conn->err); + conn->tlscreds, &conn->ioc, &local_err); /* * conn->updated_info will finally be returned to the user. Clear the @@ -194,6 +196,10 @@ static void *connect_thread_func(void *opaque) qemu_mutex_lock(&conn->mutex); + error_free(conn->err); + conn->err = NULL; + error_propagate(&conn->err, local_err); + if (ret < 0) { object_unref(OBJECT(conn->sioc)); conn->sioc = NULL; @@ -311,14 +317,17 @@ nbd_co_establish_connection(NBDClientConnection *conn, NBDExportInfo *info, } conn->running = true; - error_free(conn->err); - conn->err = NULL; qemu_thread_create(&thread, "nbd-connect", connect_thread_func, conn, QEMU_THREAD_DETACHED); } if (!blocking) { - error_setg(errp, "No connection at the moment"); + if (conn->err) { + error_propagate(errp, error_copy(conn->err)); + } else { + error_setg(errp, "No connection at the moment"); + } + return NULL; } @@ -339,14 +348,23 @@ nbd_co_establish_connection(NBDClientConnection *conn, NBDExportInfo *info, * attempt as failed, but leave the connection thread running, * to reuse it for the next connection attempt. */ - error_setg(errp, "Connection attempt cancelled by other operation"); + if (conn->err) { + error_propagate(errp, error_copy(conn->err)); + } else { + error_setg(errp, + "Connection attempt cancelled by other operation"); + } + return NULL; } else { - error_propagate(errp, conn->err); - conn->err = NULL; - if (!conn->sioc) { + /* Thread finished. There must be either error or sioc */ + assert(!conn->err != !conn->sioc); + + if (conn->err) { + error_propagate(errp, error_copy(conn->err)); return NULL; } + if (conn->do_negotiation) { memcpy(info, &conn->updated_info, sizeof(*info)); if (conn->ioc) { From 9e14491af473e94ea836c70c8a57da68d02e62b8 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Mon, 6 Sep 2021 22:06:50 +0300 Subject: [PATCH 039/730] nbd/client-connection: improve error message of cancelled attempt Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Eric Blake --- nbd/client-connection.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/nbd/client-connection.c b/nbd/client-connection.c index 722998c985..2bda42641d 100644 --- a/nbd/client-connection.c +++ b/nbd/client-connection.c @@ -351,8 +351,15 @@ nbd_co_establish_connection(NBDClientConnection *conn, NBDExportInfo *info, if (conn->err) { error_propagate(errp, error_copy(conn->err)); } else { - error_setg(errp, - "Connection attempt cancelled by other operation"); + /* + * The only possible case here is cancelling by open_timer + * during nbd_open(). So, the error message is for that case. + * If we have more use cases, we can refactor + * nbd_co_establish_connection_cancel() to take an additional + * parameter cancel_reason, that would be passed than to the + * caller of cancelled nbd_co_establish_connection(). + */ + error_setg(errp, "Connection attempt cancelled by timeout"); } return NULL; From e788cd297273098af26c8f6a4971df70cfa11e01 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:35 +0800 Subject: [PATCH 040/730] elf: Add machine type value for LoongArch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is already officially allocated as recorded in GNU binutils repo [1], and the description is updated in [2]. Add to enable further work. [1]: https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=4cf2ad720078a9f490dd5b5bc8893a926479196e [2]: https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=01a8c731aacbdbed0eb5682d13cc074dc7e25fb3 Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-2-git@xen0n.name> Signed-off-by: Richard Henderson --- include/elf.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/elf.h b/include/elf.h index 811bf4a1cb..3a4bcb646a 100644 --- a/include/elf.h +++ b/include/elf.h @@ -182,6 +182,8 @@ typedef struct mips_elf_abiflags_v0 { #define EM_NANOMIPS 249 /* Wave Computing nanoMIPS */ +#define EM_LOONGARCH 258 /* LoongArch */ + /* * This is an interim value that we will use until the committee comes * up with a final number. From afa33258f322b3f50e16b4fac8d32302f45c3462 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:36 +0800 Subject: [PATCH 041/730] MAINTAINERS: Add tcg/loongarch64 entry with myself as maintainer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I ported the initial code, so I should maintain it of course. Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-3-git@xen0n.name> Signed-off-by: Richard Henderson --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index dc4b6f7c1e..5dcefc0d01 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3143,6 +3143,11 @@ S: Maintained F: tcg/i386/ F: disas/i386.c +LoongArch64 TCG target +M: WANG Xuerui +S: Maintained +F: tcg/loongarch64/ + MIPS TCG target M: Philippe Mathieu-Daudé R: Aurelien Jarno From 6cb14e4de295e2d097d22289884f75a146938ecb Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:37 +0800 Subject: [PATCH 042/730] tcg/loongarch64: Add the tcg-target.h file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support for all optional TCG ops are initially marked disabled; the bits are to be set in individual commits later. Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-4-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.h | 180 +++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 tcg/loongarch64/tcg-target.h diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h new file mode 100644 index 0000000000..25328646f0 --- /dev/null +++ b/tcg/loongarch64/tcg-target.h @@ -0,0 +1,180 @@ +/* + * Tiny Code Generator for QEMU + * + * Copyright (c) 2021 WANG Xuerui + * + * Based on tcg/riscv/tcg-target.h + * + * Copyright (c) 2018 SiFive, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef LOONGARCH_TCG_TARGET_H +#define LOONGARCH_TCG_TARGET_H + +/* + * Loongson removed the (incomplete) 32-bit support from kernel and toolchain + * for the initial upstreaming of this architecture, so don't bother and just + * support the LP64* ABI for now. + */ +#if defined(__loongarch64) +# define TCG_TARGET_REG_BITS 64 +#else +# error unsupported LoongArch register size +#endif + +#define TCG_TARGET_INSN_UNIT_SIZE 4 +#define TCG_TARGET_NB_REGS 32 +#define MAX_CODE_GEN_BUFFER_SIZE SIZE_MAX + +typedef enum { + TCG_REG_ZERO, + TCG_REG_RA, + TCG_REG_TP, + TCG_REG_SP, + TCG_REG_A0, + TCG_REG_A1, + TCG_REG_A2, + TCG_REG_A3, + TCG_REG_A4, + TCG_REG_A5, + TCG_REG_A6, + TCG_REG_A7, + TCG_REG_T0, + TCG_REG_T1, + TCG_REG_T2, + TCG_REG_T3, + TCG_REG_T4, + TCG_REG_T5, + TCG_REG_T6, + TCG_REG_T7, + TCG_REG_T8, + TCG_REG_RESERVED, + TCG_REG_S9, + TCG_REG_S0, + TCG_REG_S1, + TCG_REG_S2, + TCG_REG_S3, + TCG_REG_S4, + TCG_REG_S5, + TCG_REG_S6, + TCG_REG_S7, + TCG_REG_S8, + + /* aliases */ + TCG_AREG0 = TCG_REG_S0, + TCG_REG_TMP0 = TCG_REG_T8, + TCG_REG_TMP1 = TCG_REG_T7, + TCG_REG_TMP2 = TCG_REG_T6, +} TCGReg; + +/* used for function call generation */ +#define TCG_REG_CALL_STACK TCG_REG_SP +#define TCG_TARGET_STACK_ALIGN 16 +#define TCG_TARGET_CALL_ALIGN_ARGS 1 +#define TCG_TARGET_CALL_STACK_OFFSET 0 + +/* optional instructions */ +#define TCG_TARGET_HAS_movcond_i32 0 +#define TCG_TARGET_HAS_div_i32 0 +#define TCG_TARGET_HAS_rem_i32 0 +#define TCG_TARGET_HAS_div2_i32 0 +#define TCG_TARGET_HAS_rot_i32 0 +#define TCG_TARGET_HAS_deposit_i32 0 +#define TCG_TARGET_HAS_extract_i32 0 +#define TCG_TARGET_HAS_sextract_i32 0 +#define TCG_TARGET_HAS_extract2_i32 0 +#define TCG_TARGET_HAS_add2_i32 0 +#define TCG_TARGET_HAS_sub2_i32 0 +#define TCG_TARGET_HAS_mulu2_i32 0 +#define TCG_TARGET_HAS_muls2_i32 0 +#define TCG_TARGET_HAS_muluh_i32 0 +#define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_ext8s_i32 0 +#define TCG_TARGET_HAS_ext16s_i32 0 +#define TCG_TARGET_HAS_ext8u_i32 0 +#define TCG_TARGET_HAS_ext16u_i32 0 +#define TCG_TARGET_HAS_bswap16_i32 0 +#define TCG_TARGET_HAS_bswap32_i32 0 +#define TCG_TARGET_HAS_not_i32 0 +#define TCG_TARGET_HAS_neg_i32 0 +#define TCG_TARGET_HAS_andc_i32 0 +#define TCG_TARGET_HAS_orc_i32 0 +#define TCG_TARGET_HAS_eqv_i32 0 +#define TCG_TARGET_HAS_nand_i32 0 +#define TCG_TARGET_HAS_nor_i32 0 +#define TCG_TARGET_HAS_clz_i32 0 +#define TCG_TARGET_HAS_ctz_i32 0 +#define TCG_TARGET_HAS_ctpop_i32 0 +#define TCG_TARGET_HAS_direct_jump 0 +#define TCG_TARGET_HAS_brcond2 0 +#define TCG_TARGET_HAS_setcond2 0 +#define TCG_TARGET_HAS_qemu_st8_i32 0 + +/* 64-bit operations */ +#define TCG_TARGET_HAS_movcond_i64 0 +#define TCG_TARGET_HAS_div_i64 0 +#define TCG_TARGET_HAS_rem_i64 0 +#define TCG_TARGET_HAS_div2_i64 0 +#define TCG_TARGET_HAS_rot_i64 0 +#define TCG_TARGET_HAS_deposit_i64 0 +#define TCG_TARGET_HAS_extract_i64 0 +#define TCG_TARGET_HAS_sextract_i64 0 +#define TCG_TARGET_HAS_extract2_i64 0 +#define TCG_TARGET_HAS_extrl_i64_i32 0 +#define TCG_TARGET_HAS_extrh_i64_i32 0 +#define TCG_TARGET_HAS_ext8s_i64 0 +#define TCG_TARGET_HAS_ext16s_i64 0 +#define TCG_TARGET_HAS_ext32s_i64 0 +#define TCG_TARGET_HAS_ext8u_i64 0 +#define TCG_TARGET_HAS_ext16u_i64 0 +#define TCG_TARGET_HAS_ext32u_i64 0 +#define TCG_TARGET_HAS_bswap16_i64 0 +#define TCG_TARGET_HAS_bswap32_i64 0 +#define TCG_TARGET_HAS_bswap64_i64 0 +#define TCG_TARGET_HAS_not_i64 0 +#define TCG_TARGET_HAS_neg_i64 0 +#define TCG_TARGET_HAS_andc_i64 0 +#define TCG_TARGET_HAS_orc_i64 0 +#define TCG_TARGET_HAS_eqv_i64 0 +#define TCG_TARGET_HAS_nand_i64 0 +#define TCG_TARGET_HAS_nor_i64 0 +#define TCG_TARGET_HAS_clz_i64 0 +#define TCG_TARGET_HAS_ctz_i64 0 +#define TCG_TARGET_HAS_ctpop_i64 0 +#define TCG_TARGET_HAS_add2_i64 0 +#define TCG_TARGET_HAS_sub2_i64 0 +#define TCG_TARGET_HAS_mulu2_i64 0 +#define TCG_TARGET_HAS_muls2_i64 0 +#define TCG_TARGET_HAS_muluh_i64 0 +#define TCG_TARGET_HAS_mulsh_i64 0 + +/* not defined -- call should be eliminated at compile time */ +void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); + +#define TCG_TARGET_DEFAULT_MO (0) + +#ifdef CONFIG_SOFTMMU +#define TCG_TARGET_NEED_LDST_LABELS +#endif + +#define TCG_TARGET_HAS_MEMORY_BSWAP 0 + +#endif /* LOONGARCH_TCG_TARGET_H */ From 71bb0283f5734053a962feac42f20ab70c370f28 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:38 +0800 Subject: [PATCH 043/730] tcg/loongarch64: Add generated instruction opcodes and encoding helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Philippe Mathieu-Daudé Acked-by: Richard Henderson Message-Id: <20211221054105.178795-5-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-insn-defs.c.inc | 979 ++++++++++++++++++++++++++++ 1 file changed, 979 insertions(+) create mode 100644 tcg/loongarch64/tcg-insn-defs.c.inc diff --git a/tcg/loongarch64/tcg-insn-defs.c.inc b/tcg/loongarch64/tcg-insn-defs.c.inc new file mode 100644 index 0000000000..d162571856 --- /dev/null +++ b/tcg/loongarch64/tcg-insn-defs.c.inc @@ -0,0 +1,979 @@ +/* SPDX-License-Identifier: MIT */ +/* + * LoongArch instruction formats, opcodes, and encoders for TCG use. + * + * This file is auto-generated by genqemutcgdefs from + * https://github.com/loongson-community/loongarch-opcodes, + * from commit 961f0c60f5b63e574d785995600c71ad5413fdc4. + * DO NOT EDIT. + */ + +typedef enum { + OPC_CLZ_W = 0x00001400, + OPC_CTZ_W = 0x00001c00, + OPC_CLZ_D = 0x00002400, + OPC_CTZ_D = 0x00002c00, + OPC_REVB_2H = 0x00003000, + OPC_REVB_2W = 0x00003800, + OPC_REVB_D = 0x00003c00, + OPC_SEXT_H = 0x00005800, + OPC_SEXT_B = 0x00005c00, + OPC_ADD_W = 0x00100000, + OPC_ADD_D = 0x00108000, + OPC_SUB_W = 0x00110000, + OPC_SUB_D = 0x00118000, + OPC_SLT = 0x00120000, + OPC_SLTU = 0x00128000, + OPC_MASKEQZ = 0x00130000, + OPC_MASKNEZ = 0x00138000, + OPC_NOR = 0x00140000, + OPC_AND = 0x00148000, + OPC_OR = 0x00150000, + OPC_XOR = 0x00158000, + OPC_ORN = 0x00160000, + OPC_ANDN = 0x00168000, + OPC_SLL_W = 0x00170000, + OPC_SRL_W = 0x00178000, + OPC_SRA_W = 0x00180000, + OPC_SLL_D = 0x00188000, + OPC_SRL_D = 0x00190000, + OPC_SRA_D = 0x00198000, + OPC_ROTR_W = 0x001b0000, + OPC_ROTR_D = 0x001b8000, + OPC_MUL_W = 0x001c0000, + OPC_MULH_W = 0x001c8000, + OPC_MULH_WU = 0x001d0000, + OPC_MUL_D = 0x001d8000, + OPC_MULH_D = 0x001e0000, + OPC_MULH_DU = 0x001e8000, + OPC_DIV_W = 0x00200000, + OPC_MOD_W = 0x00208000, + OPC_DIV_WU = 0x00210000, + OPC_MOD_WU = 0x00218000, + OPC_DIV_D = 0x00220000, + OPC_MOD_D = 0x00228000, + OPC_DIV_DU = 0x00230000, + OPC_MOD_DU = 0x00238000, + OPC_SLLI_W = 0x00408000, + OPC_SLLI_D = 0x00410000, + OPC_SRLI_W = 0x00448000, + OPC_SRLI_D = 0x00450000, + OPC_SRAI_W = 0x00488000, + OPC_SRAI_D = 0x00490000, + OPC_ROTRI_W = 0x004c8000, + OPC_ROTRI_D = 0x004d0000, + OPC_BSTRINS_W = 0x00600000, + OPC_BSTRPICK_W = 0x00608000, + OPC_BSTRINS_D = 0x00800000, + OPC_BSTRPICK_D = 0x00c00000, + OPC_SLTI = 0x02000000, + OPC_SLTUI = 0x02400000, + OPC_ADDI_W = 0x02800000, + OPC_ADDI_D = 0x02c00000, + OPC_CU52I_D = 0x03000000, + OPC_ANDI = 0x03400000, + OPC_ORI = 0x03800000, + OPC_XORI = 0x03c00000, + OPC_LU12I_W = 0x14000000, + OPC_CU32I_D = 0x16000000, + OPC_PCADDU2I = 0x18000000, + OPC_PCALAU12I = 0x1a000000, + OPC_PCADDU12I = 0x1c000000, + OPC_PCADDU18I = 0x1e000000, + OPC_LD_B = 0x28000000, + OPC_LD_H = 0x28400000, + OPC_LD_W = 0x28800000, + OPC_LD_D = 0x28c00000, + OPC_ST_B = 0x29000000, + OPC_ST_H = 0x29400000, + OPC_ST_W = 0x29800000, + OPC_ST_D = 0x29c00000, + OPC_LD_BU = 0x2a000000, + OPC_LD_HU = 0x2a400000, + OPC_LD_WU = 0x2a800000, + OPC_LDX_B = 0x38000000, + OPC_LDX_H = 0x38040000, + OPC_LDX_W = 0x38080000, + OPC_LDX_D = 0x380c0000, + OPC_STX_B = 0x38100000, + OPC_STX_H = 0x38140000, + OPC_STX_W = 0x38180000, + OPC_STX_D = 0x381c0000, + OPC_LDX_BU = 0x38200000, + OPC_LDX_HU = 0x38240000, + OPC_LDX_WU = 0x38280000, + OPC_DBAR = 0x38720000, + OPC_JIRL = 0x4c000000, + OPC_B = 0x50000000, + OPC_BL = 0x54000000, + OPC_BEQ = 0x58000000, + OPC_BNE = 0x5c000000, + OPC_BGT = 0x60000000, + OPC_BLE = 0x64000000, + OPC_BGTU = 0x68000000, + OPC_BLEU = 0x6c000000, +} LoongArchInsn; + +static int32_t __attribute__((unused)) +encode_d_slot(LoongArchInsn opc, uint32_t d) +{ + return opc | d; +} + +static int32_t __attribute__((unused)) +encode_dj_slots(LoongArchInsn opc, uint32_t d, uint32_t j) +{ + return opc | d | j << 5; +} + +static int32_t __attribute__((unused)) +encode_djk_slots(LoongArchInsn opc, uint32_t d, uint32_t j, uint32_t k) +{ + return opc | d | j << 5 | k << 10; +} + +static int32_t __attribute__((unused)) +encode_djkm_slots(LoongArchInsn opc, uint32_t d, uint32_t j, uint32_t k, + uint32_t m) +{ + return opc | d | j << 5 | k << 10 | m << 16; +} + +static int32_t __attribute__((unused)) +encode_dk_slots(LoongArchInsn opc, uint32_t d, uint32_t k) +{ + return opc | d | k << 10; +} + +static int32_t __attribute__((unused)) +encode_dj_insn(LoongArchInsn opc, TCGReg d, TCGReg j) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + return encode_dj_slots(opc, d, j); +} + +static int32_t __attribute__((unused)) +encode_djk_insn(LoongArchInsn opc, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(k >= 0 && k <= 0x1f); + return encode_djk_slots(opc, d, j, k); +} + +static int32_t __attribute__((unused)) +encode_djsk12_insn(LoongArchInsn opc, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(sk12 >= -0x800 && sk12 <= 0x7ff); + return encode_djk_slots(opc, d, j, sk12 & 0xfff); +} + +static int32_t __attribute__((unused)) +encode_djsk16_insn(LoongArchInsn opc, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(sk16 >= -0x8000 && sk16 <= 0x7fff); + return encode_djk_slots(opc, d, j, sk16 & 0xffff); +} + +static int32_t __attribute__((unused)) +encode_djuk12_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk12) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(uk12 <= 0xfff); + return encode_djk_slots(opc, d, j, uk12); +} + +static int32_t __attribute__((unused)) +encode_djuk5_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk5) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(uk5 <= 0x1f); + return encode_djk_slots(opc, d, j, uk5); +} + +static int32_t __attribute__((unused)) +encode_djuk5um5_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk5, + uint32_t um5) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(uk5 <= 0x1f); + tcg_debug_assert(um5 <= 0x1f); + return encode_djkm_slots(opc, d, j, uk5, um5); +} + +static int32_t __attribute__((unused)) +encode_djuk6_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk6) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(uk6 <= 0x3f); + return encode_djk_slots(opc, d, j, uk6); +} + +static int32_t __attribute__((unused)) +encode_djuk6um6_insn(LoongArchInsn opc, TCGReg d, TCGReg j, uint32_t uk6, + uint32_t um6) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(j >= 0 && j <= 0x1f); + tcg_debug_assert(uk6 <= 0x3f); + tcg_debug_assert(um6 <= 0x3f); + return encode_djkm_slots(opc, d, j, uk6, um6); +} + +static int32_t __attribute__((unused)) +encode_dsj20_insn(LoongArchInsn opc, TCGReg d, int32_t sj20) +{ + tcg_debug_assert(d >= 0 && d <= 0x1f); + tcg_debug_assert(sj20 >= -0x80000 && sj20 <= 0x7ffff); + return encode_dj_slots(opc, d, sj20 & 0xfffff); +} + +static int32_t __attribute__((unused)) +encode_sd10k16_insn(LoongArchInsn opc, int32_t sd10k16) +{ + tcg_debug_assert(sd10k16 >= -0x2000000 && sd10k16 <= 0x1ffffff); + return encode_dk_slots(opc, (sd10k16 >> 16) & 0x3ff, sd10k16 & 0xffff); +} + +static int32_t __attribute__((unused)) +encode_ud15_insn(LoongArchInsn opc, uint32_t ud15) +{ + tcg_debug_assert(ud15 <= 0x7fff); + return encode_d_slot(opc, ud15); +} + +/* Emits the `clz.w d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_clz_w(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_CLZ_W, d, j)); +} + +/* Emits the `ctz.w d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ctz_w(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_CTZ_W, d, j)); +} + +/* Emits the `clz.d d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_clz_d(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_CLZ_D, d, j)); +} + +/* Emits the `ctz.d d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ctz_d(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_CTZ_D, d, j)); +} + +/* Emits the `revb.2h d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_revb_2h(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_REVB_2H, d, j)); +} + +/* Emits the `revb.2w d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_revb_2w(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_REVB_2W, d, j)); +} + +/* Emits the `revb.d d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_revb_d(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_REVB_D, d, j)); +} + +/* Emits the `sext.h d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sext_h(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_SEXT_H, d, j)); +} + +/* Emits the `sext.b d, j` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sext_b(TCGContext *s, TCGReg d, TCGReg j) +{ + tcg_out32(s, encode_dj_insn(OPC_SEXT_B, d, j)); +} + +/* Emits the `add.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_add_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_ADD_W, d, j, k)); +} + +/* Emits the `add.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_add_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_ADD_D, d, j, k)); +} + +/* Emits the `sub.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sub_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SUB_W, d, j, k)); +} + +/* Emits the `sub.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sub_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SUB_D, d, j, k)); +} + +/* Emits the `slt d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_slt(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SLT, d, j, k)); +} + +/* Emits the `sltu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sltu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SLTU, d, j, k)); +} + +/* Emits the `maskeqz d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_maskeqz(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MASKEQZ, d, j, k)); +} + +/* Emits the `masknez d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_masknez(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MASKNEZ, d, j, k)); +} + +/* Emits the `nor d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_nor(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_NOR, d, j, k)); +} + +/* Emits the `and d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_and(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_AND, d, j, k)); +} + +/* Emits the `or d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_or(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_OR, d, j, k)); +} + +/* Emits the `xor d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_xor(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_XOR, d, j, k)); +} + +/* Emits the `orn d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_orn(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_ORN, d, j, k)); +} + +/* Emits the `andn d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_andn(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_ANDN, d, j, k)); +} + +/* Emits the `sll.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sll_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SLL_W, d, j, k)); +} + +/* Emits the `srl.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_srl_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SRL_W, d, j, k)); +} + +/* Emits the `sra.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sra_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SRA_W, d, j, k)); +} + +/* Emits the `sll.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sll_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SLL_D, d, j, k)); +} + +/* Emits the `srl.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_srl_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SRL_D, d, j, k)); +} + +/* Emits the `sra.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sra_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_SRA_D, d, j, k)); +} + +/* Emits the `rotr.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_rotr_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_ROTR_W, d, j, k)); +} + +/* Emits the `rotr.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_rotr_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_ROTR_D, d, j, k)); +} + +/* Emits the `mul.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mul_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MUL_W, d, j, k)); +} + +/* Emits the `mulh.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mulh_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MULH_W, d, j, k)); +} + +/* Emits the `mulh.wu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mulh_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MULH_WU, d, j, k)); +} + +/* Emits the `mul.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mul_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MUL_D, d, j, k)); +} + +/* Emits the `mulh.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mulh_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MULH_D, d, j, k)); +} + +/* Emits the `mulh.du d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mulh_du(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MULH_DU, d, j, k)); +} + +/* Emits the `div.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_div_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_DIV_W, d, j, k)); +} + +/* Emits the `mod.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mod_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MOD_W, d, j, k)); +} + +/* Emits the `div.wu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_div_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_DIV_WU, d, j, k)); +} + +/* Emits the `mod.wu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mod_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MOD_WU, d, j, k)); +} + +/* Emits the `div.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_div_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_DIV_D, d, j, k)); +} + +/* Emits the `mod.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mod_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MOD_D, d, j, k)); +} + +/* Emits the `div.du d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_div_du(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_DIV_DU, d, j, k)); +} + +/* Emits the `mod.du d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_mod_du(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_MOD_DU, d, j, k)); +} + +/* Emits the `slli.w d, j, uk5` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_slli_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) +{ + tcg_out32(s, encode_djuk5_insn(OPC_SLLI_W, d, j, uk5)); +} + +/* Emits the `slli.d d, j, uk6` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_slli_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) +{ + tcg_out32(s, encode_djuk6_insn(OPC_SLLI_D, d, j, uk6)); +} + +/* Emits the `srli.w d, j, uk5` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_srli_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) +{ + tcg_out32(s, encode_djuk5_insn(OPC_SRLI_W, d, j, uk5)); +} + +/* Emits the `srli.d d, j, uk6` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_srli_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) +{ + tcg_out32(s, encode_djuk6_insn(OPC_SRLI_D, d, j, uk6)); +} + +/* Emits the `srai.w d, j, uk5` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_srai_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) +{ + tcg_out32(s, encode_djuk5_insn(OPC_SRAI_W, d, j, uk5)); +} + +/* Emits the `srai.d d, j, uk6` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_srai_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) +{ + tcg_out32(s, encode_djuk6_insn(OPC_SRAI_D, d, j, uk6)); +} + +/* Emits the `rotri.w d, j, uk5` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_rotri_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5) +{ + tcg_out32(s, encode_djuk5_insn(OPC_ROTRI_W, d, j, uk5)); +} + +/* Emits the `rotri.d d, j, uk6` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_rotri_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6) +{ + tcg_out32(s, encode_djuk6_insn(OPC_ROTRI_D, d, j, uk6)); +} + +/* Emits the `bstrins.w d, j, uk5, um5` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bstrins_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5, + uint32_t um5) +{ + tcg_out32(s, encode_djuk5um5_insn(OPC_BSTRINS_W, d, j, uk5, um5)); +} + +/* Emits the `bstrpick.w d, j, uk5, um5` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bstrpick_w(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk5, + uint32_t um5) +{ + tcg_out32(s, encode_djuk5um5_insn(OPC_BSTRPICK_W, d, j, uk5, um5)); +} + +/* Emits the `bstrins.d d, j, uk6, um6` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bstrins_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6, + uint32_t um6) +{ + tcg_out32(s, encode_djuk6um6_insn(OPC_BSTRINS_D, d, j, uk6, um6)); +} + +/* Emits the `bstrpick.d d, j, uk6, um6` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bstrpick_d(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk6, + uint32_t um6) +{ + tcg_out32(s, encode_djuk6um6_insn(OPC_BSTRPICK_D, d, j, uk6, um6)); +} + +/* Emits the `slti d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_slti(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_SLTI, d, j, sk12)); +} + +/* Emits the `sltui d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_sltui(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_SLTUI, d, j, sk12)); +} + +/* Emits the `addi.w d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_addi_w(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_ADDI_W, d, j, sk12)); +} + +/* Emits the `addi.d d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_addi_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_ADDI_D, d, j, sk12)); +} + +/* Emits the `cu52i.d d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_cu52i_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_CU52I_D, d, j, sk12)); +} + +/* Emits the `andi d, j, uk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_andi(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12) +{ + tcg_out32(s, encode_djuk12_insn(OPC_ANDI, d, j, uk12)); +} + +/* Emits the `ori d, j, uk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ori(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12) +{ + tcg_out32(s, encode_djuk12_insn(OPC_ORI, d, j, uk12)); +} + +/* Emits the `xori d, j, uk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_xori(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12) +{ + tcg_out32(s, encode_djuk12_insn(OPC_XORI, d, j, uk12)); +} + +/* Emits the `lu12i.w d, sj20` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_lu12i_w(TCGContext *s, TCGReg d, int32_t sj20) +{ + tcg_out32(s, encode_dsj20_insn(OPC_LU12I_W, d, sj20)); +} + +/* Emits the `cu32i.d d, sj20` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_cu32i_d(TCGContext *s, TCGReg d, int32_t sj20) +{ + tcg_out32(s, encode_dsj20_insn(OPC_CU32I_D, d, sj20)); +} + +/* Emits the `pcaddu2i d, sj20` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_pcaddu2i(TCGContext *s, TCGReg d, int32_t sj20) +{ + tcg_out32(s, encode_dsj20_insn(OPC_PCADDU2I, d, sj20)); +} + +/* Emits the `pcalau12i d, sj20` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_pcalau12i(TCGContext *s, TCGReg d, int32_t sj20) +{ + tcg_out32(s, encode_dsj20_insn(OPC_PCALAU12I, d, sj20)); +} + +/* Emits the `pcaddu12i d, sj20` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_pcaddu12i(TCGContext *s, TCGReg d, int32_t sj20) +{ + tcg_out32(s, encode_dsj20_insn(OPC_PCADDU12I, d, sj20)); +} + +/* Emits the `pcaddu18i d, sj20` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_pcaddu18i(TCGContext *s, TCGReg d, int32_t sj20) +{ + tcg_out32(s, encode_dsj20_insn(OPC_PCADDU18I, d, sj20)); +} + +/* Emits the `ld.b d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_b(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_B, d, j, sk12)); +} + +/* Emits the `ld.h d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_h(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_H, d, j, sk12)); +} + +/* Emits the `ld.w d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_w(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_W, d, j, sk12)); +} + +/* Emits the `ld.d d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_D, d, j, sk12)); +} + +/* Emits the `st.b d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_st_b(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_ST_B, d, j, sk12)); +} + +/* Emits the `st.h d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_st_h(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_ST_H, d, j, sk12)); +} + +/* Emits the `st.w d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_st_w(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_ST_W, d, j, sk12)); +} + +/* Emits the `st.d d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_st_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_ST_D, d, j, sk12)); +} + +/* Emits the `ld.bu d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_bu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_BU, d, j, sk12)); +} + +/* Emits the `ld.hu d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_hu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_HU, d, j, sk12)); +} + +/* Emits the `ld.wu d, j, sk12` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ld_wu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk12) +{ + tcg_out32(s, encode_djsk12_insn(OPC_LD_WU, d, j, sk12)); +} + +/* Emits the `ldx.b d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_b(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_B, d, j, k)); +} + +/* Emits the `ldx.h d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_h(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_H, d, j, k)); +} + +/* Emits the `ldx.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_W, d, j, k)); +} + +/* Emits the `ldx.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_D, d, j, k)); +} + +/* Emits the `stx.b d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_stx_b(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_STX_B, d, j, k)); +} + +/* Emits the `stx.h d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_stx_h(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_STX_H, d, j, k)); +} + +/* Emits the `stx.w d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_stx_w(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_STX_W, d, j, k)); +} + +/* Emits the `stx.d d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_stx_d(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_STX_D, d, j, k)); +} + +/* Emits the `ldx.bu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_bu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_BU, d, j, k)); +} + +/* Emits the `ldx.hu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_hu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_HU, d, j, k)); +} + +/* Emits the `ldx.wu d, j, k` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ldx_wu(TCGContext *s, TCGReg d, TCGReg j, TCGReg k) +{ + tcg_out32(s, encode_djk_insn(OPC_LDX_WU, d, j, k)); +} + +/* Emits the `dbar ud15` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_dbar(TCGContext *s, uint32_t ud15) +{ + tcg_out32(s, encode_ud15_insn(OPC_DBAR, ud15)); +} + +/* Emits the `jirl d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_jirl(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_JIRL, d, j, sk16)); +} + +/* Emits the `b sd10k16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_b(TCGContext *s, int32_t sd10k16) +{ + tcg_out32(s, encode_sd10k16_insn(OPC_B, sd10k16)); +} + +/* Emits the `bl sd10k16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bl(TCGContext *s, int32_t sd10k16) +{ + tcg_out32(s, encode_sd10k16_insn(OPC_BL, sd10k16)); +} + +/* Emits the `beq d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_beq(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_BEQ, d, j, sk16)); +} + +/* Emits the `bne d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bne(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_BNE, d, j, sk16)); +} + +/* Emits the `bgt d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bgt(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_BGT, d, j, sk16)); +} + +/* Emits the `ble d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_ble(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_BLE, d, j, sk16)); +} + +/* Emits the `bgtu d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bgtu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_BGTU, d, j, sk16)); +} + +/* Emits the `bleu d, j, sk16` instruction. */ +static void __attribute__((unused)) +tcg_out_opc_bleu(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16) +{ + tcg_out32(s, encode_djsk16_insn(OPC_BLEU, d, j, sk16)); +} + +/* End of generated code. */ From 1bcfbf03dfa38c727312166081c0921590e798be Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:39 +0800 Subject: [PATCH 044/730] tcg/loongarch64: Add register names, allocation order and input/output sets Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Message-Id: <20211221054105.178795-6-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.c.inc | 118 +++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 tcg/loongarch64/tcg-target.c.inc diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc new file mode 100644 index 0000000000..653ef0a4bb --- /dev/null +++ b/tcg/loongarch64/tcg-target.c.inc @@ -0,0 +1,118 @@ +/* + * Tiny Code Generator for QEMU + * + * Copyright (c) 2021 WANG Xuerui + * + * Based on tcg/riscv/tcg-target.c.inc + * + * Copyright (c) 2018 SiFive, Inc + * Copyright (c) 2008-2009 Arnaud Patard + * Copyright (c) 2009 Aurelien Jarno + * Copyright (c) 2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef CONFIG_DEBUG_TCG +static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { + "zero", + "ra", + "tp", + "sp", + "a0", + "a1", + "a2", + "a3", + "a4", + "a5", + "a6", + "a7", + "t0", + "t1", + "t2", + "t3", + "t4", + "t5", + "t6", + "t7", + "t8", + "r21", /* reserved in the LP64* ABI, hence no ABI name */ + "s9", + "s0", + "s1", + "s2", + "s3", + "s4", + "s5", + "s6", + "s7", + "s8" +}; +#endif + +static const int tcg_target_reg_alloc_order[] = { + /* Registers preserved across calls */ + /* TCG_REG_S0 reserved for TCG_AREG0 */ + TCG_REG_S1, + TCG_REG_S2, + TCG_REG_S3, + TCG_REG_S4, + TCG_REG_S5, + TCG_REG_S6, + TCG_REG_S7, + TCG_REG_S8, + TCG_REG_S9, + + /* Registers (potentially) clobbered across calls */ + TCG_REG_T0, + TCG_REG_T1, + TCG_REG_T2, + TCG_REG_T3, + TCG_REG_T4, + TCG_REG_T5, + TCG_REG_T6, + TCG_REG_T7, + TCG_REG_T8, + + /* Argument registers, opposite order of allocation. */ + TCG_REG_A7, + TCG_REG_A6, + TCG_REG_A5, + TCG_REG_A4, + TCG_REG_A3, + TCG_REG_A2, + TCG_REG_A1, + TCG_REG_A0, +}; + +static const int tcg_target_call_iarg_regs[] = { + TCG_REG_A0, + TCG_REG_A1, + TCG_REG_A2, + TCG_REG_A3, + TCG_REG_A4, + TCG_REG_A5, + TCG_REG_A6, + TCG_REG_A7, +}; + +static const int tcg_target_call_oarg_regs[] = { + TCG_REG_A0, + TCG_REG_A1, +}; From ba0cdd8040015cd519053ca7740e24a4c7826347 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:40 +0800 Subject: [PATCH 045/730] tcg/loongarch64: Define the operand constraints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-7-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-str.h | 28 +++++++++++++++ tcg/loongarch64/tcg-target.c.inc | 52 ++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 tcg/loongarch64/tcg-target-con-str.h diff --git a/tcg/loongarch64/tcg-target-con-str.h b/tcg/loongarch64/tcg-target-con-str.h new file mode 100644 index 0000000000..c3986a4fd4 --- /dev/null +++ b/tcg/loongarch64/tcg-target-con-str.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define LoongArch target-specific operand constraints. + * + * Copyright (c) 2021 WANG Xuerui + * + * Based on tcg/riscv/tcg-target-con-str.h + * + * Copyright (c) 2021 Linaro + */ + +/* + * Define constraint letters for register sets: + * REGS(letter, register_mask) + */ +REGS('r', ALL_GENERAL_REGS) +REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS) + +/* + * Define constraint letters for constants: + * CONST(letter, TCG_CT_CONST_* bit set) + */ +CONST('I', TCG_CT_CONST_S12) +CONST('N', TCG_CT_CONST_N12) +CONST('U', TCG_CT_CONST_U12) +CONST('Z', TCG_CT_CONST_ZERO) +CONST('C', TCG_CT_CONST_C12) +CONST('W', TCG_CT_CONST_WSZ) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 653ef0a4bb..1c1b798c06 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -116,3 +116,55 @@ static const int tcg_target_call_oarg_regs[] = { TCG_REG_A0, TCG_REG_A1, }; + +#define TCG_CT_CONST_ZERO 0x100 +#define TCG_CT_CONST_S12 0x200 +#define TCG_CT_CONST_N12 0x400 +#define TCG_CT_CONST_U12 0x800 +#define TCG_CT_CONST_C12 0x1000 +#define TCG_CT_CONST_WSZ 0x2000 + +#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32) +/* + * For softmmu, we need to avoid conflicts with the first 5 + * argument registers to call the helper. Some of these are + * also used for the tlb lookup. + */ +#ifdef CONFIG_SOFTMMU +#define SOFTMMU_RESERVE_REGS MAKE_64BIT_MASK(TCG_REG_A0, 5) +#else +#define SOFTMMU_RESERVE_REGS 0 +#endif + + +static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len) +{ + return sextract64(val, pos, len); +} + +/* test if a constant matches the constraint */ +static bool tcg_target_const_match(int64_t val, TCGType type, int ct) +{ + if (ct & TCG_CT_CONST) { + return true; + } + if ((ct & TCG_CT_CONST_ZERO) && val == 0) { + return true; + } + if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) { + return true; + } + if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) { + return true; + } + if ((ct & TCG_CT_CONST_U12) && val >= 0 && val <= 0xfff) { + return true; + } + if ((ct & TCG_CT_CONST_C12) && ~val >= 0 && ~val <= 0xfff) { + return true; + } + if ((ct & TCG_CT_CONST_WSZ) && val == (type == TCG_TYPE_I32 ? 32 : 64)) { + return true; + } + return false; +} From bf8c1c8140c748a3fcddf2b5367457a34cc82fa9 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:41 +0800 Subject: [PATCH 046/730] tcg/loongarch64: Implement necessary relocation operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-8-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.c.inc | 66 ++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 1c1b798c06..a88ba9a253 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -168,3 +168,69 @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct) } return false; } + +/* + * Relocations + */ + +/* + * Relocation records defined in LoongArch ELF psABI v1.00 is way too + * complicated; a whopping stack machine is needed to stuff the fields, at + * the very least one SOP_PUSH and one SOP_POP (of the correct format) are + * needed. + * + * Hence, define our own simpler relocation types. Numbers are chosen as to + * not collide with potential future additions to the true ELF relocation + * type enum. + */ + +/* Field Sk16, shifted right by 2; suitable for conditional jumps */ +#define R_LOONGARCH_BR_SK16 256 +/* Field Sd10k16, shifted right by 2; suitable for B and BL */ +#define R_LOONGARCH_BR_SD10K16 257 + +static bool reloc_br_sk16(tcg_insn_unit *src_rw, const tcg_insn_unit *target) +{ + const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); + intptr_t offset = (intptr_t)target - (intptr_t)src_rx; + + tcg_debug_assert((offset & 3) == 0); + offset >>= 2; + if (offset == sextreg(offset, 0, 16)) { + *src_rw = deposit64(*src_rw, 10, 16, offset); + return true; + } + + return false; +} + +static bool reloc_br_sd10k16(tcg_insn_unit *src_rw, + const tcg_insn_unit *target) +{ + const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw); + intptr_t offset = (intptr_t)target - (intptr_t)src_rx; + + tcg_debug_assert((offset & 3) == 0); + offset >>= 2; + if (offset == sextreg(offset, 0, 26)) { + *src_rw = deposit64(*src_rw, 0, 10, offset >> 16); /* slot d10 */ + *src_rw = deposit64(*src_rw, 10, 16, offset); /* slot k16 */ + return true; + } + + return false; +} + +static bool patch_reloc(tcg_insn_unit *code_ptr, int type, + intptr_t value, intptr_t addend) +{ + tcg_debug_assert(addend == 0); + switch (type) { + case R_LOONGARCH_BR_SK16: + return reloc_br_sk16(code_ptr, (tcg_insn_unit *)value); + case R_LOONGARCH_BR_SD10K16: + return reloc_br_sd10k16(code_ptr, (tcg_insn_unit *)value); + default: + g_assert_not_reached(); + } +} From fae2361dc996ad68591ac8871d2c14f3a174ee3c Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:42 +0800 Subject: [PATCH 047/730] tcg/loongarch64: Implement the memory barrier op MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-9-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.c.inc | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index a88ba9a253..615bed9096 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -234,3 +234,35 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type, g_assert_not_reached(); } } + +#include "tcg-insn-defs.c.inc" + +/* + * TCG intrinsics + */ + +static void tcg_out_mb(TCGContext *s, TCGArg a0) +{ + /* Baseline LoongArch only has the full barrier, unfortunately. */ + tcg_out_opc_dbar(s, 0); +} + +/* + * Entry-points + */ + +static void tcg_out_op(TCGContext *s, TCGOpcode opc, + const TCGArg args[TCG_MAX_OP_ARGS], + const int const_args[TCG_MAX_OP_ARGS]) +{ + TCGArg a0 = args[0]; + + switch (opc) { + case INDEX_op_mb: + tcg_out_mb(s, a0); + break; + + default: + g_assert_not_reached(); + } +} From dacc51720db9ccb89201c2f800cdc26d4d9c106c Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:43 +0800 Subject: [PATCH 048/730] tcg/loongarch64: Implement tcg_out_mov and tcg_out_movi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-10-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.c.inc | 137 +++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 615bed9096..bb45ea0fcf 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -247,6 +247,141 @@ static void tcg_out_mb(TCGContext *s, TCGArg a0) tcg_out_opc_dbar(s, 0); } +static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) +{ + if (ret == arg) { + return true; + } + switch (type) { + case TCG_TYPE_I32: + case TCG_TYPE_I64: + /* + * Conventional register-register move used in LoongArch is + * `or dst, src, zero`. + */ + tcg_out_opc_or(s, ret, arg, TCG_REG_ZERO); + break; + default: + g_assert_not_reached(); + } + return true; +} + +static bool imm_part_needs_loading(bool high_bits_are_ones, + tcg_target_long part) +{ + if (high_bits_are_ones) { + return part != -1; + } else { + return part != 0; + } +} + +/* Loads a 32-bit immediate into rd, sign-extended. */ +static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val) +{ + tcg_target_long lo = sextreg(val, 0, 12); + tcg_target_long hi12 = sextreg(val, 12, 20); + + /* Single-instruction cases. */ + if (lo == val) { + /* val fits in simm12: addi.w rd, zero, val */ + tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val); + return; + } + if (0x800 <= val && val <= 0xfff) { + /* val fits in uimm12: ori rd, zero, val */ + tcg_out_opc_ori(s, rd, TCG_REG_ZERO, val); + return; + } + + /* High bits must be set; load with lu12i.w + optional ori. */ + tcg_out_opc_lu12i_w(s, rd, hi12); + if (lo != 0) { + tcg_out_opc_ori(s, rd, rd, lo & 0xfff); + } +} + +static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, + tcg_target_long val) +{ + /* + * LoongArch conventionally loads 64-bit immediates in at most 4 steps, + * with dedicated instructions for filling the respective bitfields + * below: + * + * 6 5 4 3 + * 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 + * +-----------------------+---------------------------------------+... + * | hi52 | hi32 | + * +-----------------------+---------------------------------------+... + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * ...+-------------------------------------+-------------------------+ + * | hi12 | lo | + * ...+-------------------------------------+-------------------------+ + * + * Check if val belong to one of the several fast cases, before falling + * back to the slow path. + */ + + intptr_t pc_offset; + tcg_target_long val_lo, val_hi, pc_hi, offset_hi; + tcg_target_long hi32, hi52; + bool rd_high_bits_are_ones; + + /* Value fits in signed i32. */ + if (type == TCG_TYPE_I32 || val == (int32_t)val) { + tcg_out_movi_i32(s, rd, val); + return; + } + + /* PC-relative cases. */ + pc_offset = tcg_pcrel_diff(s, (void *)val); + if (pc_offset == sextreg(pc_offset, 0, 22) && (pc_offset & 3) == 0) { + /* Single pcaddu2i. */ + tcg_out_opc_pcaddu2i(s, rd, pc_offset >> 2); + return; + } + + if (pc_offset == (int32_t)pc_offset) { + /* Offset within 32 bits; load with pcalau12i + ori. */ + val_lo = sextreg(val, 0, 12); + val_hi = val >> 12; + pc_hi = (val - pc_offset) >> 12; + offset_hi = val_hi - pc_hi; + + tcg_debug_assert(offset_hi == sextreg(offset_hi, 0, 20)); + tcg_out_opc_pcalau12i(s, rd, offset_hi); + if (val_lo != 0) { + tcg_out_opc_ori(s, rd, rd, val_lo & 0xfff); + } + return; + } + + hi32 = sextreg(val, 32, 20); + hi52 = sextreg(val, 52, 12); + + /* Single cu52i.d case. */ + if (ctz64(val) >= 52) { + tcg_out_opc_cu52i_d(s, rd, TCG_REG_ZERO, hi52); + return; + } + + /* Slow path. Initialize the low 32 bits, then concat high bits. */ + tcg_out_movi_i32(s, rd, val); + rd_high_bits_are_ones = (int32_t)val < 0; + + if (imm_part_needs_loading(rd_high_bits_are_ones, hi32)) { + tcg_out_opc_cu32i_d(s, rd, hi32); + rd_high_bits_are_ones = hi32 < 0; + } + + if (imm_part_needs_loading(rd_high_bits_are_ones, hi52)) { + tcg_out_opc_cu52i_d(s, rd, rd, hi52); + } +} + /* * Entry-points */ @@ -262,6 +397,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_mb(s, a0); break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ + case INDEX_op_mov_i64: default: g_assert_not_reached(); } From e3b15766b9020c8f7e52fc5d0d92b24a4626073b Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:44 +0800 Subject: [PATCH 049/730] tcg/loongarch64: Implement goto_ptr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-11-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-set.h | 17 +++++++++++++++++ tcg/loongarch64/tcg-target.c.inc | 15 +++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tcg/loongarch64/tcg-target-con-set.h diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h new file mode 100644 index 0000000000..5cc4407367 --- /dev/null +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Define LoongArch target-specific constraint sets. + * + * Copyright (c) 2021 WANG Xuerui + * + * Based on tcg/riscv/tcg-target-con-set.h + * + * Copyright (c) 2021 Linaro + */ + +/* + * C_On_Im(...) defines a constraint set with outputs and inputs. + * Each operand should be a sequence of constraint letters as defined by + * tcg-target-con-str.h; the constraint combination is inclusive or. + */ +C_O0_I1(r) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index bb45ea0fcf..3a8c52465b 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -397,9 +397,24 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_mb(s, a0); break; + case INDEX_op_goto_ptr: + tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0); + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: default: g_assert_not_reached(); } } + +static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) +{ + switch (op) { + case INDEX_op_goto_ptr: + return C_O0_I1(r); + + default: + g_assert_not_reached(); + } +} From 6be08fcfc3525dd61ad249d6a33add9ba5634b58 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:45 +0800 Subject: [PATCH 050/730] tcg/loongarch64: Implement sign-/zero-extension ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-12-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-set.h | 1 + tcg/loongarch64/tcg-target.c.inc | 82 ++++++++++++++++++++++++++++ tcg/loongarch64/tcg-target.h | 24 ++++---- 3 files changed, 95 insertions(+), 12 deletions(-) diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h index 5cc4407367..7e459490ea 100644 --- a/tcg/loongarch64/tcg-target-con-set.h +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -15,3 +15,4 @@ * tcg-target-con-str.h; the constraint combination is inclusive or. */ C_O0_I1(r) +C_O1_I1(r, r) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 3a8c52465b..25b58c7828 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -382,6 +382,36 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, } } +static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_out_opc_andi(s, ret, arg, 0xff); +} + +static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_out_opc_bstrpick_w(s, ret, arg, 0, 15); +} + +static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_out_opc_bstrpick_d(s, ret, arg, 0, 31); +} + +static void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_out_opc_sext_b(s, ret, arg); +} + +static void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_out_opc_sext_h(s, ret, arg); +} + +static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg) +{ + tcg_out_opc_addi_w(s, ret, arg, 0); +} + /* * Entry-points */ @@ -391,6 +421,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const int const_args[TCG_MAX_OP_ARGS]) { TCGArg a0 = args[0]; + TCGArg a1 = args[1]; switch (opc) { case INDEX_op_mb: @@ -401,6 +432,41 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0); break; + case INDEX_op_ext8s_i32: + case INDEX_op_ext8s_i64: + tcg_out_ext8s(s, a0, a1); + break; + + case INDEX_op_ext8u_i32: + case INDEX_op_ext8u_i64: + tcg_out_ext8u(s, a0, a1); + break; + + case INDEX_op_ext16s_i32: + case INDEX_op_ext16s_i64: + tcg_out_ext16s(s, a0, a1); + break; + + case INDEX_op_ext16u_i32: + case INDEX_op_ext16u_i64: + tcg_out_ext16u(s, a0, a1); + break; + + case INDEX_op_ext32u_i64: + case INDEX_op_extu_i32_i64: + tcg_out_ext32u(s, a0, a1); + break; + + case INDEX_op_ext32s_i64: + case INDEX_op_extrl_i64_i32: + case INDEX_op_ext_i32_i64: + tcg_out_ext32s(s, a0, a1); + break; + + case INDEX_op_extrh_i64_i32: + tcg_out_opc_srai_d(s, a0, a1, 32); + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: default: @@ -414,6 +480,22 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_goto_ptr: return C_O0_I1(r); + case INDEX_op_ext8s_i32: + case INDEX_op_ext8s_i64: + case INDEX_op_ext8u_i32: + case INDEX_op_ext8u_i64: + case INDEX_op_ext16s_i32: + case INDEX_op_ext16s_i64: + case INDEX_op_ext16u_i32: + case INDEX_op_ext16u_i64: + case INDEX_op_ext32s_i64: + case INDEX_op_ext32u_i64: + case INDEX_op_extu_i32_i64: + case INDEX_op_extrl_i64_i32: + case INDEX_op_extrh_i64_i32: + case INDEX_op_ext_i32_i64: + return C_O1_I1(r, r); + default: g_assert_not_reached(); } diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h index 25328646f0..a6d9e036fc 100644 --- a/tcg/loongarch64/tcg-target.h +++ b/tcg/loongarch64/tcg-target.h @@ -107,10 +107,10 @@ typedef enum { #define TCG_TARGET_HAS_muls2_i32 0 #define TCG_TARGET_HAS_muluh_i32 0 #define TCG_TARGET_HAS_mulsh_i32 0 -#define TCG_TARGET_HAS_ext8s_i32 0 -#define TCG_TARGET_HAS_ext16s_i32 0 -#define TCG_TARGET_HAS_ext8u_i32 0 -#define TCG_TARGET_HAS_ext16u_i32 0 +#define TCG_TARGET_HAS_ext8s_i32 1 +#define TCG_TARGET_HAS_ext16s_i32 1 +#define TCG_TARGET_HAS_ext8u_i32 1 +#define TCG_TARGET_HAS_ext16u_i32 1 #define TCG_TARGET_HAS_bswap16_i32 0 #define TCG_TARGET_HAS_bswap32_i32 0 #define TCG_TARGET_HAS_not_i32 0 @@ -138,14 +138,14 @@ typedef enum { #define TCG_TARGET_HAS_extract_i64 0 #define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_extract2_i64 0 -#define TCG_TARGET_HAS_extrl_i64_i32 0 -#define TCG_TARGET_HAS_extrh_i64_i32 0 -#define TCG_TARGET_HAS_ext8s_i64 0 -#define TCG_TARGET_HAS_ext16s_i64 0 -#define TCG_TARGET_HAS_ext32s_i64 0 -#define TCG_TARGET_HAS_ext8u_i64 0 -#define TCG_TARGET_HAS_ext16u_i64 0 -#define TCG_TARGET_HAS_ext32u_i64 0 +#define TCG_TARGET_HAS_extrl_i64_i32 1 +#define TCG_TARGET_HAS_extrh_i64_i32 1 +#define TCG_TARGET_HAS_ext8s_i64 1 +#define TCG_TARGET_HAS_ext16s_i64 1 +#define TCG_TARGET_HAS_ext32s_i64 1 +#define TCG_TARGET_HAS_ext8u_i64 1 +#define TCG_TARGET_HAS_ext16u_i64 1 +#define TCG_TARGET_HAS_ext32u_i64 1 #define TCG_TARGET_HAS_bswap16_i64 0 #define TCG_TARGET_HAS_bswap32_i64 0 #define TCG_TARGET_HAS_bswap64_i64 0 From 97b2fafbf707658e666cea85856148fb02e7628b Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:46 +0800 Subject: [PATCH 051/730] tcg/loongarch64: Implement not/and/or/xor/nor/andc/orc ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-13-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-set.h | 2 + tcg/loongarch64/tcg-target.c.inc | 88 ++++++++++++++++++++++++++++ tcg/loongarch64/tcg-target.h | 16 ++--- 3 files changed, 98 insertions(+), 8 deletions(-) diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h index 7e459490ea..9ac24b8ad0 100644 --- a/tcg/loongarch64/tcg-target-con-set.h +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -16,3 +16,5 @@ */ C_O0_I1(r) C_O1_I1(r, r) +C_O1_I2(r, r, rC) +C_O1_I2(r, r, rU) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 25b58c7828..d9508d5295 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -422,6 +422,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, { TCGArg a0 = args[0]; TCGArg a1 = args[1]; + TCGArg a2 = args[2]; + int c2 = const_args[2]; switch (opc) { case INDEX_op_mb: @@ -467,6 +469,68 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_opc_srai_d(s, a0, a1, 32); break; + case INDEX_op_not_i32: + case INDEX_op_not_i64: + tcg_out_opc_nor(s, a0, a1, TCG_REG_ZERO); + break; + + case INDEX_op_nor_i32: + case INDEX_op_nor_i64: + if (c2) { + tcg_out_opc_ori(s, a0, a1, a2); + tcg_out_opc_nor(s, a0, a0, TCG_REG_ZERO); + } else { + tcg_out_opc_nor(s, a0, a1, a2); + } + break; + + case INDEX_op_andc_i32: + case INDEX_op_andc_i64: + if (c2) { + /* guaranteed to fit due to constraint */ + tcg_out_opc_andi(s, a0, a1, ~a2); + } else { + tcg_out_opc_andn(s, a0, a1, a2); + } + break; + + case INDEX_op_orc_i32: + case INDEX_op_orc_i64: + if (c2) { + /* guaranteed to fit due to constraint */ + tcg_out_opc_ori(s, a0, a1, ~a2); + } else { + tcg_out_opc_orn(s, a0, a1, a2); + } + break; + + case INDEX_op_and_i32: + case INDEX_op_and_i64: + if (c2) { + tcg_out_opc_andi(s, a0, a1, a2); + } else { + tcg_out_opc_and(s, a0, a1, a2); + } + break; + + case INDEX_op_or_i32: + case INDEX_op_or_i64: + if (c2) { + tcg_out_opc_ori(s, a0, a1, a2); + } else { + tcg_out_opc_or(s, a0, a1, a2); + } + break; + + case INDEX_op_xor_i32: + case INDEX_op_xor_i64: + if (c2) { + tcg_out_opc_xori(s, a0, a1, a2); + } else { + tcg_out_opc_xor(s, a0, a1, a2); + } + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: default: @@ -494,8 +558,32 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_extrl_i64_i32: case INDEX_op_extrh_i64_i32: case INDEX_op_ext_i32_i64: + case INDEX_op_not_i32: + case INDEX_op_not_i64: return C_O1_I1(r, r); + case INDEX_op_andc_i32: + case INDEX_op_andc_i64: + case INDEX_op_orc_i32: + case INDEX_op_orc_i64: + /* + * LoongArch insns for these ops don't have reg-imm forms, but we + * can express using andi/ori if ~constant satisfies + * TCG_CT_CONST_U12. + */ + return C_O1_I2(r, r, rC); + + case INDEX_op_and_i32: + case INDEX_op_and_i64: + case INDEX_op_nor_i32: + case INDEX_op_nor_i64: + case INDEX_op_or_i32: + case INDEX_op_or_i64: + case INDEX_op_xor_i32: + case INDEX_op_xor_i64: + /* LoongArch reg-imm bitops have their imms ZERO-extended */ + return C_O1_I2(r, r, rU); + default: g_assert_not_reached(); } diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h index a6d9e036fc..cc9aecc681 100644 --- a/tcg/loongarch64/tcg-target.h +++ b/tcg/loongarch64/tcg-target.h @@ -113,13 +113,13 @@ typedef enum { #define TCG_TARGET_HAS_ext16u_i32 1 #define TCG_TARGET_HAS_bswap16_i32 0 #define TCG_TARGET_HAS_bswap32_i32 0 -#define TCG_TARGET_HAS_not_i32 0 +#define TCG_TARGET_HAS_not_i32 1 #define TCG_TARGET_HAS_neg_i32 0 -#define TCG_TARGET_HAS_andc_i32 0 -#define TCG_TARGET_HAS_orc_i32 0 +#define TCG_TARGET_HAS_andc_i32 1 +#define TCG_TARGET_HAS_orc_i32 1 #define TCG_TARGET_HAS_eqv_i32 0 #define TCG_TARGET_HAS_nand_i32 0 -#define TCG_TARGET_HAS_nor_i32 0 +#define TCG_TARGET_HAS_nor_i32 1 #define TCG_TARGET_HAS_clz_i32 0 #define TCG_TARGET_HAS_ctz_i32 0 #define TCG_TARGET_HAS_ctpop_i32 0 @@ -149,13 +149,13 @@ typedef enum { #define TCG_TARGET_HAS_bswap16_i64 0 #define TCG_TARGET_HAS_bswap32_i64 0 #define TCG_TARGET_HAS_bswap64_i64 0 -#define TCG_TARGET_HAS_not_i64 0 +#define TCG_TARGET_HAS_not_i64 1 #define TCG_TARGET_HAS_neg_i64 0 -#define TCG_TARGET_HAS_andc_i64 0 -#define TCG_TARGET_HAS_orc_i64 0 +#define TCG_TARGET_HAS_andc_i64 1 +#define TCG_TARGET_HAS_orc_i64 1 #define TCG_TARGET_HAS_eqv_i64 0 #define TCG_TARGET_HAS_nand_i64 0 -#define TCG_TARGET_HAS_nor_i64 0 +#define TCG_TARGET_HAS_nor_i64 1 #define TCG_TARGET_HAS_clz_i64 0 #define TCG_TARGET_HAS_ctz_i64 0 #define TCG_TARGET_HAS_ctpop_i64 0 From 7257809f62d8e01b6e54046b3893c80a8fbfa1b4 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:47 +0800 Subject: [PATCH 052/730] tcg/loongarch64: Implement deposit/extract ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-14-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-set.h | 1 + tcg/loongarch64/tcg-target.c.inc | 21 +++++++++++++++++++++ tcg/loongarch64/tcg-target.h | 8 ++++---- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h index 9ac24b8ad0..d958183020 100644 --- a/tcg/loongarch64/tcg-target-con-set.h +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -18,3 +18,4 @@ C_O0_I1(r) C_O1_I1(r, r) C_O1_I2(r, r, rC) C_O1_I2(r, r, rU) +C_O1_I2(r, 0, rZ) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index d9508d5295..9eba8f8146 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -531,6 +531,20 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, } break; + case INDEX_op_extract_i32: + tcg_out_opc_bstrpick_w(s, a0, a1, a2, a2 + args[3] - 1); + break; + case INDEX_op_extract_i64: + tcg_out_opc_bstrpick_d(s, a0, a1, a2, a2 + args[3] - 1); + break; + + case INDEX_op_deposit_i32: + tcg_out_opc_bstrins_w(s, a0, a2, args[3], args[3] + args[4] - 1); + break; + case INDEX_op_deposit_i64: + tcg_out_opc_bstrins_d(s, a0, a2, args[3], args[3] + args[4] - 1); + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: default: @@ -560,6 +574,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_ext_i32_i64: case INDEX_op_not_i32: case INDEX_op_not_i64: + case INDEX_op_extract_i32: + case INDEX_op_extract_i64: return C_O1_I1(r, r); case INDEX_op_andc_i32: @@ -584,6 +600,11 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) /* LoongArch reg-imm bitops have their imms ZERO-extended */ return C_O1_I2(r, r, rU); + case INDEX_op_deposit_i32: + case INDEX_op_deposit_i64: + /* Must deposit into the same register as input */ + return C_O1_I2(r, 0, rZ); + default: g_assert_not_reached(); } diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h index cc9aecc681..1c9d0a9988 100644 --- a/tcg/loongarch64/tcg-target.h +++ b/tcg/loongarch64/tcg-target.h @@ -97,8 +97,8 @@ typedef enum { #define TCG_TARGET_HAS_rem_i32 0 #define TCG_TARGET_HAS_div2_i32 0 #define TCG_TARGET_HAS_rot_i32 0 -#define TCG_TARGET_HAS_deposit_i32 0 -#define TCG_TARGET_HAS_extract_i32 0 +#define TCG_TARGET_HAS_deposit_i32 1 +#define TCG_TARGET_HAS_extract_i32 1 #define TCG_TARGET_HAS_sextract_i32 0 #define TCG_TARGET_HAS_extract2_i32 0 #define TCG_TARGET_HAS_add2_i32 0 @@ -134,8 +134,8 @@ typedef enum { #define TCG_TARGET_HAS_rem_i64 0 #define TCG_TARGET_HAS_div2_i64 0 #define TCG_TARGET_HAS_rot_i64 0 -#define TCG_TARGET_HAS_deposit_i64 0 -#define TCG_TARGET_HAS_extract_i64 0 +#define TCG_TARGET_HAS_deposit_i64 1 +#define TCG_TARGET_HAS_extract_i64 1 #define TCG_TARGET_HAS_sextract_i64 0 #define TCG_TARGET_HAS_extract2_i64 0 #define TCG_TARGET_HAS_extrl_i64_i32 1 From 4ab2aff0dbcf43ca3360dd52a4910b012a39d22e Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:48 +0800 Subject: [PATCH 053/730] tcg/loongarch64: Implement bswap{16,32,64} ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-15-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.c.inc | 32 ++++++++++++++++++++++++++++++++ tcg/loongarch64/tcg-target.h | 10 +++++----- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 9eba8f8146..3b056dd358 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -545,6 +545,33 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_opc_bstrins_d(s, a0, a2, args[3], args[3] + args[4] - 1); break; + case INDEX_op_bswap16_i32: + case INDEX_op_bswap16_i64: + tcg_out_opc_revb_2h(s, a0, a1); + if (a2 & TCG_BSWAP_OS) { + tcg_out_ext16s(s, a0, a0); + } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) { + tcg_out_ext16u(s, a0, a0); + } + break; + + case INDEX_op_bswap32_i32: + /* All 32-bit values are computed sign-extended in the register. */ + a2 = TCG_BSWAP_OS; + /* fallthrough */ + case INDEX_op_bswap32_i64: + tcg_out_opc_revb_2w(s, a0, a1); + if (a2 & TCG_BSWAP_OS) { + tcg_out_ext32s(s, a0, a0); + } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) { + tcg_out_ext32u(s, a0, a0); + } + break; + + case INDEX_op_bswap64_i64: + tcg_out_opc_revb_d(s, a0, a1); + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: default: @@ -576,6 +603,11 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_not_i64: case INDEX_op_extract_i32: case INDEX_op_extract_i64: + case INDEX_op_bswap16_i32: + case INDEX_op_bswap16_i64: + case INDEX_op_bswap32_i32: + case INDEX_op_bswap32_i64: + case INDEX_op_bswap64_i64: return C_O1_I1(r, r); case INDEX_op_andc_i32: diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h index 1c9d0a9988..5303001653 100644 --- a/tcg/loongarch64/tcg-target.h +++ b/tcg/loongarch64/tcg-target.h @@ -111,8 +111,8 @@ typedef enum { #define TCG_TARGET_HAS_ext16s_i32 1 #define TCG_TARGET_HAS_ext8u_i32 1 #define TCG_TARGET_HAS_ext16u_i32 1 -#define TCG_TARGET_HAS_bswap16_i32 0 -#define TCG_TARGET_HAS_bswap32_i32 0 +#define TCG_TARGET_HAS_bswap16_i32 1 +#define TCG_TARGET_HAS_bswap32_i32 1 #define TCG_TARGET_HAS_not_i32 1 #define TCG_TARGET_HAS_neg_i32 0 #define TCG_TARGET_HAS_andc_i32 1 @@ -146,9 +146,9 @@ typedef enum { #define TCG_TARGET_HAS_ext8u_i64 1 #define TCG_TARGET_HAS_ext16u_i64 1 #define TCG_TARGET_HAS_ext32u_i64 1 -#define TCG_TARGET_HAS_bswap16_i64 0 -#define TCG_TARGET_HAS_bswap32_i64 0 -#define TCG_TARGET_HAS_bswap64_i64 0 +#define TCG_TARGET_HAS_bswap16_i64 1 +#define TCG_TARGET_HAS_bswap32_i64 1 +#define TCG_TARGET_HAS_bswap64_i64 1 #define TCG_TARGET_HAS_not_i64 1 #define TCG_TARGET_HAS_neg_i64 0 #define TCG_TARGET_HAS_andc_i64 1 From fde693016064ce5cb954b5c132daf59f5cdbf17d Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:49 +0800 Subject: [PATCH 054/730] tcg/loongarch64: Implement clz/ctz ops Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Message-Id: <20211221054105.178795-16-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-set.h | 1 + tcg/loongarch64/tcg-target.c.inc | 42 ++++++++++++++++++++++++++++ tcg/loongarch64/tcg-target.h | 8 +++--- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h index d958183020..2975e03127 100644 --- a/tcg/loongarch64/tcg-target-con-set.h +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -18,4 +18,5 @@ C_O0_I1(r) C_O1_I1(r, r) C_O1_I2(r, r, rC) C_O1_I2(r, r, rU) +C_O1_I2(r, r, rW) C_O1_I2(r, 0, rZ) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 3b056dd358..39df2885b5 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -412,6 +412,28 @@ static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg) tcg_out_opc_addi_w(s, ret, arg, 0); } +static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc, + TCGReg a0, TCGReg a1, TCGReg a2, + bool c2, bool is_32bit) +{ + if (c2) { + /* + * Fast path: semantics already satisfied due to constraint and + * insn behavior, single instruction is enough. + */ + tcg_debug_assert(a2 == (is_32bit ? 32 : 64)); + /* all clz/ctz insns belong to DJ-format */ + tcg_out32(s, encode_dj_insn(opc, a0, a1)); + return; + } + + tcg_out32(s, encode_dj_insn(opc, TCG_REG_TMP0, a1)); + /* a0 = a1 ? REG_TMP0 : a2 */ + tcg_out_opc_maskeqz(s, TCG_REG_TMP0, TCG_REG_TMP0, a1); + tcg_out_opc_masknez(s, a0, a2, a1); + tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0); +} + /* * Entry-points */ @@ -572,6 +594,20 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_opc_revb_d(s, a0, a1); break; + case INDEX_op_clz_i32: + tcg_out_clzctz(s, OPC_CLZ_W, a0, a1, a2, c2, true); + break; + case INDEX_op_clz_i64: + tcg_out_clzctz(s, OPC_CLZ_D, a0, a1, a2, c2, false); + break; + + case INDEX_op_ctz_i32: + tcg_out_clzctz(s, OPC_CTZ_W, a0, a1, a2, c2, true); + break; + case INDEX_op_ctz_i64: + tcg_out_clzctz(s, OPC_CTZ_D, a0, a1, a2, c2, false); + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: default: @@ -632,6 +668,12 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) /* LoongArch reg-imm bitops have their imms ZERO-extended */ return C_O1_I2(r, r, rU); + case INDEX_op_clz_i32: + case INDEX_op_clz_i64: + case INDEX_op_ctz_i32: + case INDEX_op_ctz_i64: + return C_O1_I2(r, r, rW); + case INDEX_op_deposit_i32: case INDEX_op_deposit_i64: /* Must deposit into the same register as input */ diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h index 5303001653..2fd2745b63 100644 --- a/tcg/loongarch64/tcg-target.h +++ b/tcg/loongarch64/tcg-target.h @@ -120,8 +120,8 @@ typedef enum { #define TCG_TARGET_HAS_eqv_i32 0 #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 1 -#define TCG_TARGET_HAS_clz_i32 0 -#define TCG_TARGET_HAS_ctz_i32 0 +#define TCG_TARGET_HAS_clz_i32 1 +#define TCG_TARGET_HAS_ctz_i32 1 #define TCG_TARGET_HAS_ctpop_i32 0 #define TCG_TARGET_HAS_direct_jump 0 #define TCG_TARGET_HAS_brcond2 0 @@ -156,8 +156,8 @@ typedef enum { #define TCG_TARGET_HAS_eqv_i64 0 #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 1 -#define TCG_TARGET_HAS_clz_i64 0 -#define TCG_TARGET_HAS_ctz_i64 0 +#define TCG_TARGET_HAS_clz_i64 1 +#define TCG_TARGET_HAS_ctz_i64 1 #define TCG_TARGET_HAS_ctpop_i64 0 #define TCG_TARGET_HAS_add2_i64 0 #define TCG_TARGET_HAS_sub2_i64 0 From a164010b052abfd720110c46bc6835065de0e351 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:50 +0800 Subject: [PATCH 055/730] tcg/loongarch64: Implement shl/shr/sar/rotl/rotr ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-17-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-set.h | 1 + tcg/loongarch64/tcg-target.c.inc | 91 ++++++++++++++++++++++++++++ tcg/loongarch64/tcg-target.h | 4 +- 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h index 2975e03127..42f8e28741 100644 --- a/tcg/loongarch64/tcg-target-con-set.h +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -17,6 +17,7 @@ C_O0_I1(r) C_O1_I1(r, r) C_O1_I2(r, r, rC) +C_O1_I2(r, r, ri) C_O1_I2(r, r, rU) C_O1_I2(r, r, rW) C_O1_I2(r, 0, rZ) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 39df2885b5..2895769e68 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -608,6 +608,85 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_clzctz(s, OPC_CTZ_D, a0, a1, a2, c2, false); break; + case INDEX_op_shl_i32: + if (c2) { + tcg_out_opc_slli_w(s, a0, a1, a2 & 0x1f); + } else { + tcg_out_opc_sll_w(s, a0, a1, a2); + } + break; + case INDEX_op_shl_i64: + if (c2) { + tcg_out_opc_slli_d(s, a0, a1, a2 & 0x3f); + } else { + tcg_out_opc_sll_d(s, a0, a1, a2); + } + break; + + case INDEX_op_shr_i32: + if (c2) { + tcg_out_opc_srli_w(s, a0, a1, a2 & 0x1f); + } else { + tcg_out_opc_srl_w(s, a0, a1, a2); + } + break; + case INDEX_op_shr_i64: + if (c2) { + tcg_out_opc_srli_d(s, a0, a1, a2 & 0x3f); + } else { + tcg_out_opc_srl_d(s, a0, a1, a2); + } + break; + + case INDEX_op_sar_i32: + if (c2) { + tcg_out_opc_srai_w(s, a0, a1, a2 & 0x1f); + } else { + tcg_out_opc_sra_w(s, a0, a1, a2); + } + break; + case INDEX_op_sar_i64: + if (c2) { + tcg_out_opc_srai_d(s, a0, a1, a2 & 0x3f); + } else { + tcg_out_opc_sra_d(s, a0, a1, a2); + } + break; + + case INDEX_op_rotl_i32: + /* transform into equivalent rotr/rotri */ + if (c2) { + tcg_out_opc_rotri_w(s, a0, a1, (32 - a2) & 0x1f); + } else { + tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2); + tcg_out_opc_rotr_w(s, a0, a1, TCG_REG_TMP0); + } + break; + case INDEX_op_rotl_i64: + /* transform into equivalent rotr/rotri */ + if (c2) { + tcg_out_opc_rotri_d(s, a0, a1, (64 - a2) & 0x3f); + } else { + tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2); + tcg_out_opc_rotr_d(s, a0, a1, TCG_REG_TMP0); + } + break; + + case INDEX_op_rotr_i32: + if (c2) { + tcg_out_opc_rotri_w(s, a0, a1, a2 & 0x1f); + } else { + tcg_out_opc_rotr_w(s, a0, a1, a2); + } + break; + case INDEX_op_rotr_i64: + if (c2) { + tcg_out_opc_rotri_d(s, a0, a1, a2 & 0x3f); + } else { + tcg_out_opc_rotr_d(s, a0, a1, a2); + } + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: default: @@ -657,6 +736,18 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) */ return C_O1_I2(r, r, rC); + case INDEX_op_shl_i32: + case INDEX_op_shl_i64: + case INDEX_op_shr_i32: + case INDEX_op_shr_i64: + case INDEX_op_sar_i32: + case INDEX_op_sar_i64: + case INDEX_op_rotl_i32: + case INDEX_op_rotl_i64: + case INDEX_op_rotr_i32: + case INDEX_op_rotr_i64: + return C_O1_I2(r, r, ri); + case INDEX_op_and_i32: case INDEX_op_and_i64: case INDEX_op_nor_i32: diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h index 2fd2745b63..d1ded50cb0 100644 --- a/tcg/loongarch64/tcg-target.h +++ b/tcg/loongarch64/tcg-target.h @@ -96,7 +96,7 @@ typedef enum { #define TCG_TARGET_HAS_div_i32 0 #define TCG_TARGET_HAS_rem_i32 0 #define TCG_TARGET_HAS_div2_i32 0 -#define TCG_TARGET_HAS_rot_i32 0 +#define TCG_TARGET_HAS_rot_i32 1 #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_extract_i32 1 #define TCG_TARGET_HAS_sextract_i32 0 @@ -133,7 +133,7 @@ typedef enum { #define TCG_TARGET_HAS_div_i64 0 #define TCG_TARGET_HAS_rem_i64 0 #define TCG_TARGET_HAS_div2_i64 0 -#define TCG_TARGET_HAS_rot_i64 0 +#define TCG_TARGET_HAS_rot_i64 1 #define TCG_TARGET_HAS_deposit_i64 1 #define TCG_TARGET_HAS_extract_i64 1 #define TCG_TARGET_HAS_sextract_i64 0 From 39f54ce5c425047086b74ac7892ae492c9d02e9c Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:51 +0800 Subject: [PATCH 056/730] tcg/loongarch64: Implement add/sub ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The neg_i{32,64} ops is fully expressible with sub, so omitted for simplicity. Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-18-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-set.h | 2 ++ tcg/loongarch64/tcg-target.c.inc | 38 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h index 42f8e28741..4b8ce85897 100644 --- a/tcg/loongarch64/tcg-target-con-set.h +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -18,6 +18,8 @@ C_O0_I1(r) C_O1_I1(r, r) C_O1_I2(r, r, rC) C_O1_I2(r, r, ri) +C_O1_I2(r, r, rI) C_O1_I2(r, r, rU) C_O1_I2(r, r, rW) C_O1_I2(r, 0, rZ) +C_O1_I2(r, rZ, rN) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 2895769e68..c71d25d3fe 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -687,6 +687,36 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, } break; + case INDEX_op_add_i32: + if (c2) { + tcg_out_opc_addi_w(s, a0, a1, a2); + } else { + tcg_out_opc_add_w(s, a0, a1, a2); + } + break; + case INDEX_op_add_i64: + if (c2) { + tcg_out_opc_addi_d(s, a0, a1, a2); + } else { + tcg_out_opc_add_d(s, a0, a1, a2); + } + break; + + case INDEX_op_sub_i32: + if (c2) { + tcg_out_opc_addi_w(s, a0, a1, -a2); + } else { + tcg_out_opc_sub_w(s, a0, a1, a2); + } + break; + case INDEX_op_sub_i64: + if (c2) { + tcg_out_opc_addi_d(s, a0, a1, -a2); + } else { + tcg_out_opc_sub_d(s, a0, a1, a2); + } + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: default: @@ -748,6 +778,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_rotr_i64: return C_O1_I2(r, r, ri); + case INDEX_op_add_i32: + case INDEX_op_add_i64: + return C_O1_I2(r, r, rI); + case INDEX_op_and_i32: case INDEX_op_and_i64: case INDEX_op_nor_i32: @@ -770,6 +804,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) /* Must deposit into the same register as input */ return C_O1_I2(r, 0, rZ); + case INDEX_op_sub_i32: + case INDEX_op_sub_i64: + return C_O1_I2(r, rZ, rN); + default: g_assert_not_reached(); } From ff13c19689452a045c7df3e476b625d5ff1f7fb6 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:52 +0800 Subject: [PATCH 057/730] tcg/loongarch64: Implement mul/mulsh/muluh/div/divu/rem/remu ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-19-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-set.h | 1 + tcg/loongarch64/tcg-target.c.inc | 65 ++++++++++++++++++++++++++++ tcg/loongarch64/tcg-target.h | 16 +++---- 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h index 4b8ce85897..fb56f3a295 100644 --- a/tcg/loongarch64/tcg-target-con-set.h +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -23,3 +23,4 @@ C_O1_I2(r, r, rU) C_O1_I2(r, r, rW) C_O1_I2(r, 0, rZ) C_O1_I2(r, rZ, rN) +C_O1_I2(r, rZ, rZ) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index c71d25d3fe..0ae193fba5 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -717,6 +717,55 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, } break; + case INDEX_op_mul_i32: + tcg_out_opc_mul_w(s, a0, a1, a2); + break; + case INDEX_op_mul_i64: + tcg_out_opc_mul_d(s, a0, a1, a2); + break; + + case INDEX_op_mulsh_i32: + tcg_out_opc_mulh_w(s, a0, a1, a2); + break; + case INDEX_op_mulsh_i64: + tcg_out_opc_mulh_d(s, a0, a1, a2); + break; + + case INDEX_op_muluh_i32: + tcg_out_opc_mulh_wu(s, a0, a1, a2); + break; + case INDEX_op_muluh_i64: + tcg_out_opc_mulh_du(s, a0, a1, a2); + break; + + case INDEX_op_div_i32: + tcg_out_opc_div_w(s, a0, a1, a2); + break; + case INDEX_op_div_i64: + tcg_out_opc_div_d(s, a0, a1, a2); + break; + + case INDEX_op_divu_i32: + tcg_out_opc_div_wu(s, a0, a1, a2); + break; + case INDEX_op_divu_i64: + tcg_out_opc_div_du(s, a0, a1, a2); + break; + + case INDEX_op_rem_i32: + tcg_out_opc_mod_w(s, a0, a1, a2); + break; + case INDEX_op_rem_i64: + tcg_out_opc_mod_d(s, a0, a1, a2); + break; + + case INDEX_op_remu_i32: + tcg_out_opc_mod_wu(s, a0, a1, a2); + break; + case INDEX_op_remu_i64: + tcg_out_opc_mod_du(s, a0, a1, a2); + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: default: @@ -808,6 +857,22 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_sub_i64: return C_O1_I2(r, rZ, rN); + case INDEX_op_mul_i32: + case INDEX_op_mul_i64: + case INDEX_op_mulsh_i32: + case INDEX_op_mulsh_i64: + case INDEX_op_muluh_i32: + case INDEX_op_muluh_i64: + case INDEX_op_div_i32: + case INDEX_op_div_i64: + case INDEX_op_divu_i32: + case INDEX_op_divu_i64: + case INDEX_op_rem_i32: + case INDEX_op_rem_i64: + case INDEX_op_remu_i32: + case INDEX_op_remu_i64: + return C_O1_I2(r, rZ, rZ); + default: g_assert_not_reached(); } diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h index d1ded50cb0..05010805e7 100644 --- a/tcg/loongarch64/tcg-target.h +++ b/tcg/loongarch64/tcg-target.h @@ -93,8 +93,8 @@ typedef enum { /* optional instructions */ #define TCG_TARGET_HAS_movcond_i32 0 -#define TCG_TARGET_HAS_div_i32 0 -#define TCG_TARGET_HAS_rem_i32 0 +#define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 1 #define TCG_TARGET_HAS_div2_i32 0 #define TCG_TARGET_HAS_rot_i32 1 #define TCG_TARGET_HAS_deposit_i32 1 @@ -105,8 +105,8 @@ typedef enum { #define TCG_TARGET_HAS_sub2_i32 0 #define TCG_TARGET_HAS_mulu2_i32 0 #define TCG_TARGET_HAS_muls2_i32 0 -#define TCG_TARGET_HAS_muluh_i32 0 -#define TCG_TARGET_HAS_mulsh_i32 0 +#define TCG_TARGET_HAS_muluh_i32 1 +#define TCG_TARGET_HAS_mulsh_i32 1 #define TCG_TARGET_HAS_ext8s_i32 1 #define TCG_TARGET_HAS_ext16s_i32 1 #define TCG_TARGET_HAS_ext8u_i32 1 @@ -130,8 +130,8 @@ typedef enum { /* 64-bit operations */ #define TCG_TARGET_HAS_movcond_i64 0 -#define TCG_TARGET_HAS_div_i64 0 -#define TCG_TARGET_HAS_rem_i64 0 +#define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 1 #define TCG_TARGET_HAS_div2_i64 0 #define TCG_TARGET_HAS_rot_i64 1 #define TCG_TARGET_HAS_deposit_i64 1 @@ -163,8 +163,8 @@ typedef enum { #define TCG_TARGET_HAS_sub2_i64 0 #define TCG_TARGET_HAS_mulu2_i64 0 #define TCG_TARGET_HAS_muls2_i64 0 -#define TCG_TARGET_HAS_muluh_i64 0 -#define TCG_TARGET_HAS_mulsh_i64 0 +#define TCG_TARGET_HAS_muluh_i64 1 +#define TCG_TARGET_HAS_mulsh_i64 1 /* not defined -- call should be eliminated at compile time */ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); From 94505c02f4fa8ef6469b692477b9b75d5f3c1f51 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:53 +0800 Subject: [PATCH 058/730] tcg/loongarch64: Implement br/brcond ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-20-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-set.h | 1 + tcg/loongarch64/tcg-target.c.inc | 53 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h index fb56f3a295..367689c2e2 100644 --- a/tcg/loongarch64/tcg-target-con-set.h +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -15,6 +15,7 @@ * tcg-target-con-str.h; the constraint combination is inclusive or. */ C_O0_I1(r) +C_O0_I2(rZ, rZ) C_O1_I1(r, r) C_O1_I2(r, r, rC) C_O1_I2(r, r, ri) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 0ae193fba5..aedfc0df84 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -434,6 +434,44 @@ static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc, tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0); } +/* + * Branch helpers + */ + +static const struct { + LoongArchInsn op; + bool swap; +} tcg_brcond_to_loongarch[] = { + [TCG_COND_EQ] = { OPC_BEQ, false }, + [TCG_COND_NE] = { OPC_BNE, false }, + [TCG_COND_LT] = { OPC_BGT, true }, + [TCG_COND_GE] = { OPC_BLE, true }, + [TCG_COND_LE] = { OPC_BLE, false }, + [TCG_COND_GT] = { OPC_BGT, false }, + [TCG_COND_LTU] = { OPC_BGTU, true }, + [TCG_COND_GEU] = { OPC_BLEU, true }, + [TCG_COND_LEU] = { OPC_BLEU, false }, + [TCG_COND_GTU] = { OPC_BGTU, false } +}; + +static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, + TCGReg arg2, TCGLabel *l) +{ + LoongArchInsn op = tcg_brcond_to_loongarch[cond].op; + + tcg_debug_assert(op != 0); + + if (tcg_brcond_to_loongarch[cond].swap) { + TCGReg t = arg1; + arg1 = arg2; + arg2 = t; + } + + /* all conditional branch insns belong to DJSk16-format */ + tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SK16, l, 0); + tcg_out32(s, encode_djsk16_insn(op, arg1, arg2, 0)); +} + /* * Entry-points */ @@ -456,6 +494,17 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0); break; + case INDEX_op_br: + tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SD10K16, arg_label(a0), + 0); + tcg_out_opc_b(s, 0); + break; + + case INDEX_op_brcond_i32: + case INDEX_op_brcond_i64: + tcg_out_brcond(s, a2, a0, a1, arg_label(args[3])); + break; + case INDEX_op_ext8s_i32: case INDEX_op_ext8s_i64: tcg_out_ext8s(s, a0, a1); @@ -779,6 +828,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_goto_ptr: return C_O0_I1(r); + case INDEX_op_brcond_i32: + case INDEX_op_brcond_i64: + return C_O0_I2(rZ, rZ); + case INDEX_op_ext8s_i32: case INDEX_op_ext8s_i64: case INDEX_op_ext8u_i32: From 9ee775cf29dfdf6cffa9b4280bda9aa0e535d99d Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:54 +0800 Subject: [PATCH 059/730] tcg/loongarch64: Implement setcond ops Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Message-Id: <20211221054105.178795-21-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-set.h | 1 + tcg/loongarch64/tcg-target.c.inc | 69 ++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h index 367689c2e2..a2ec61237e 100644 --- a/tcg/loongarch64/tcg-target-con-set.h +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -22,6 +22,7 @@ C_O1_I2(r, r, ri) C_O1_I2(r, r, rI) C_O1_I2(r, r, rU) C_O1_I2(r, r, rW) +C_O1_I2(r, r, rZ) C_O1_I2(r, 0, rZ) C_O1_I2(r, rZ, rN) C_O1_I2(r, rZ, rZ) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index aedfc0df84..23c151f473 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -434,6 +434,66 @@ static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc, tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0); } +static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, + TCGReg arg1, TCGReg arg2, bool c2) +{ + TCGReg tmp; + + if (c2) { + tcg_debug_assert(arg2 == 0); + } + + switch (cond) { + case TCG_COND_EQ: + if (c2) { + tmp = arg1; + } else { + tcg_out_opc_sub_d(s, ret, arg1, arg2); + tmp = ret; + } + tcg_out_opc_sltui(s, ret, tmp, 1); + break; + case TCG_COND_NE: + if (c2) { + tmp = arg1; + } else { + tcg_out_opc_sub_d(s, ret, arg1, arg2); + tmp = ret; + } + tcg_out_opc_sltu(s, ret, TCG_REG_ZERO, tmp); + break; + case TCG_COND_LT: + tcg_out_opc_slt(s, ret, arg1, arg2); + break; + case TCG_COND_GE: + tcg_out_opc_slt(s, ret, arg1, arg2); + tcg_out_opc_xori(s, ret, ret, 1); + break; + case TCG_COND_LE: + tcg_out_setcond(s, TCG_COND_GE, ret, arg2, arg1, false); + break; + case TCG_COND_GT: + tcg_out_setcond(s, TCG_COND_LT, ret, arg2, arg1, false); + break; + case TCG_COND_LTU: + tcg_out_opc_sltu(s, ret, arg1, arg2); + break; + case TCG_COND_GEU: + tcg_out_opc_sltu(s, ret, arg1, arg2); + tcg_out_opc_xori(s, ret, ret, 1); + break; + case TCG_COND_LEU: + tcg_out_setcond(s, TCG_COND_GEU, ret, arg2, arg1, false); + break; + case TCG_COND_GTU: + tcg_out_setcond(s, TCG_COND_LTU, ret, arg2, arg1, false); + break; + default: + g_assert_not_reached(); + break; + } +} + /* * Branch helpers */ @@ -815,6 +875,11 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_opc_mod_du(s, a0, a1, a2); break; + case INDEX_op_setcond_i32: + case INDEX_op_setcond_i64: + tcg_out_setcond(s, args[3], a0, a1, a2, c2); + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: default: @@ -901,6 +966,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_ctz_i64: return C_O1_I2(r, r, rW); + case INDEX_op_setcond_i32: + case INDEX_op_setcond_i64: + return C_O1_I2(r, r, rZ); + case INDEX_op_deposit_i32: case INDEX_op_deposit_i64: /* Must deposit into the same register as input */ From a26d99d72f0c26a38a067b6b3596d03f612ac8c5 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:55 +0800 Subject: [PATCH 060/730] tcg/loongarch64: Implement tcg_out_call Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Message-Id: <20211221054105.178795-22-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.c.inc | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 23c151f473..151d3308ea 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -532,6 +532,39 @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, tcg_out32(s, encode_djsk16_insn(op, arg1, arg2, 0)); } +static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) +{ + TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA; + ptrdiff_t offset = tcg_pcrel_diff(s, arg); + + tcg_debug_assert((offset & 3) == 0); + if (offset == sextreg(offset, 0, 28)) { + /* short jump: +/- 256MiB */ + if (tail) { + tcg_out_opc_b(s, offset >> 2); + } else { + tcg_out_opc_bl(s, offset >> 2); + } + } else if (offset == sextreg(offset, 0, 38)) { + /* long jump: +/- 256GiB */ + tcg_target_long lo = sextreg(offset, 0, 18); + tcg_target_long hi = offset - lo; + tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, hi >> 18); + tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2); + } else { + /* far jump: 64-bit */ + tcg_target_long lo = sextreg((tcg_target_long)arg, 0, 18); + tcg_target_long hi = (tcg_target_long)arg - lo; + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, hi); + tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2); + } +} + +static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg) +{ + tcg_out_call_int(s, arg, false); +} + /* * Entry-points */ @@ -882,6 +915,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: + case INDEX_op_call: /* Always emitted via tcg_out_call. */ default: g_assert_not_reached(); } From 251ebcd8129d73b7099fbe5e9231aaaa96767cb5 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:56 +0800 Subject: [PATCH 061/730] tcg/loongarch64: Implement simple load/store ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-23-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-set.h | 1 + tcg/loongarch64/tcg-target.c.inc | 131 +++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h index a2ec61237e..e54ca9b2de 100644 --- a/tcg/loongarch64/tcg-target-con-set.h +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -15,6 +15,7 @@ * tcg-target-con-str.h; the constraint combination is inclusive or. */ C_O0_I1(r) +C_O0_I2(rZ, r) C_O0_I2(rZ, rZ) C_O1_I1(r, r) C_O1_I2(r, r, rC) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 151d3308ea..3d1d7c33c0 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -565,6 +565,73 @@ static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg) tcg_out_call_int(s, arg, false); } +/* + * Load/store helpers + */ + +static void tcg_out_ldst(TCGContext *s, LoongArchInsn opc, TCGReg data, + TCGReg addr, intptr_t offset) +{ + intptr_t imm12 = sextreg(offset, 0, 12); + + if (offset != imm12) { + intptr_t diff = offset - (uintptr_t)s->code_ptr; + + if (addr == TCG_REG_ZERO && diff == (int32_t)diff) { + imm12 = sextreg(diff, 0, 12); + tcg_out_opc_pcaddu12i(s, TCG_REG_TMP2, (diff - imm12) >> 12); + } else { + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12); + if (addr != TCG_REG_ZERO) { + tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, addr); + } + } + addr = TCG_REG_TMP2; + } + + switch (opc) { + case OPC_LD_B: + case OPC_LD_BU: + case OPC_LD_H: + case OPC_LD_HU: + case OPC_LD_W: + case OPC_LD_WU: + case OPC_LD_D: + case OPC_ST_B: + case OPC_ST_H: + case OPC_ST_W: + case OPC_ST_D: + tcg_out32(s, encode_djsk12_insn(opc, data, addr, imm12)); + break; + default: + g_assert_not_reached(); + } +} + +static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, intptr_t arg2) +{ + bool is_32bit = type == TCG_TYPE_I32; + tcg_out_ldst(s, is_32bit ? OPC_LD_W : OPC_LD_D, arg, arg1, arg2); +} + +static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, intptr_t arg2) +{ + bool is_32bit = type == TCG_TYPE_I32; + tcg_out_ldst(s, is_32bit ? OPC_ST_W : OPC_ST_D, arg, arg1, arg2); +} + +static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, + TCGReg base, intptr_t ofs) +{ + if (val == 0) { + tcg_out_st(s, type, TCG_REG_ZERO, base, ofs); + return true; + } + return false; +} + /* * Entry-points */ @@ -913,6 +980,49 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_setcond(s, args[3], a0, a1, a2, c2); break; + case INDEX_op_ld8s_i32: + case INDEX_op_ld8s_i64: + tcg_out_ldst(s, OPC_LD_B, a0, a1, a2); + break; + case INDEX_op_ld8u_i32: + case INDEX_op_ld8u_i64: + tcg_out_ldst(s, OPC_LD_BU, a0, a1, a2); + break; + case INDEX_op_ld16s_i32: + case INDEX_op_ld16s_i64: + tcg_out_ldst(s, OPC_LD_H, a0, a1, a2); + break; + case INDEX_op_ld16u_i32: + case INDEX_op_ld16u_i64: + tcg_out_ldst(s, OPC_LD_HU, a0, a1, a2); + break; + case INDEX_op_ld_i32: + case INDEX_op_ld32s_i64: + tcg_out_ldst(s, OPC_LD_W, a0, a1, a2); + break; + case INDEX_op_ld32u_i64: + tcg_out_ldst(s, OPC_LD_WU, a0, a1, a2); + break; + case INDEX_op_ld_i64: + tcg_out_ldst(s, OPC_LD_D, a0, a1, a2); + break; + + case INDEX_op_st8_i32: + case INDEX_op_st8_i64: + tcg_out_ldst(s, OPC_ST_B, a0, a1, a2); + break; + case INDEX_op_st16_i32: + case INDEX_op_st16_i64: + tcg_out_ldst(s, OPC_ST_H, a0, a1, a2); + break; + case INDEX_op_st_i32: + case INDEX_op_st32_i64: + tcg_out_ldst(s, OPC_ST_W, a0, a1, a2); + break; + case INDEX_op_st_i64: + tcg_out_ldst(s, OPC_ST_D, a0, a1, a2); + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: case INDEX_op_call: /* Always emitted via tcg_out_call. */ @@ -927,6 +1037,15 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_goto_ptr: return C_O0_I1(r); + case INDEX_op_st8_i32: + case INDEX_op_st8_i64: + case INDEX_op_st16_i32: + case INDEX_op_st16_i64: + case INDEX_op_st32_i64: + case INDEX_op_st_i32: + case INDEX_op_st_i64: + return C_O0_I2(rZ, r); + case INDEX_op_brcond_i32: case INDEX_op_brcond_i64: return C_O0_I2(rZ, rZ); @@ -954,6 +1073,18 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_bswap32_i32: case INDEX_op_bswap32_i64: case INDEX_op_bswap64_i64: + case INDEX_op_ld8s_i32: + case INDEX_op_ld8s_i64: + case INDEX_op_ld8u_i32: + case INDEX_op_ld8u_i64: + case INDEX_op_ld16s_i32: + case INDEX_op_ld16s_i64: + case INDEX_op_ld16u_i32: + case INDEX_op_ld16u_i64: + case INDEX_op_ld32s_i64: + case INDEX_op_ld32u_i64: + case INDEX_op_ld_i32: + case INDEX_op_ld_i64: return C_O1_I1(r, r); case INDEX_op_andc_i32: From d3a1727c194edec6a8cd113eb23f83fc27663744 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:57 +0800 Subject: [PATCH 062/730] tcg/loongarch64: Add softmmu load/store helpers, implement qemu_ld/qemu_st ops Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Message-Id: <20211221054105.178795-24-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target-con-set.h | 2 + tcg/loongarch64/tcg-target.c.inc | 353 +++++++++++++++++++++++++++ 2 files changed, 355 insertions(+) diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h index e54ca9b2de..349c672687 100644 --- a/tcg/loongarch64/tcg-target-con-set.h +++ b/tcg/loongarch64/tcg-target-con-set.h @@ -17,7 +17,9 @@ C_O0_I1(r) C_O0_I2(rZ, r) C_O0_I2(rZ, rZ) +C_O0_I2(LZ, L) C_O1_I1(r, r) +C_O1_I1(r, L) C_O1_I2(r, r, rC) C_O1_I2(r, r, ri) C_O1_I2(r, r, rI) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 3d1d7c33c0..f67d5fa110 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -117,6 +117,11 @@ static const int tcg_target_call_oarg_regs[] = { TCG_REG_A1, }; +#ifndef CONFIG_SOFTMMU +#define USE_GUEST_BASE (guest_base != 0) +#define TCG_GUEST_BASE_REG TCG_REG_S1 +#endif + #define TCG_CT_CONST_ZERO 0x100 #define TCG_CT_CONST_S12 0x200 #define TCG_CT_CONST_N12 0x400 @@ -632,6 +637,333 @@ static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, return false; } +/* + * Load/store helpers for SoftMMU, and qemu_ld/st implementations + */ + +#if defined(CONFIG_SOFTMMU) +#include "../tcg-ldst.c.inc" + +/* + * helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, + * MemOpIdx oi, uintptr_t ra) + */ +static void * const qemu_ld_helpers[4] = { + [MO_8] = helper_ret_ldub_mmu, + [MO_16] = helper_le_lduw_mmu, + [MO_32] = helper_le_ldul_mmu, + [MO_64] = helper_le_ldq_mmu, +}; + +/* + * helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr, + * uintxx_t val, MemOpIdx oi, + * uintptr_t ra) + */ +static void * const qemu_st_helpers[4] = { + [MO_8] = helper_ret_stb_mmu, + [MO_16] = helper_le_stw_mmu, + [MO_32] = helper_le_stl_mmu, + [MO_64] = helper_le_stq_mmu, +}; + +/* We expect to use a 12-bit negative offset from ENV. */ +QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0); +QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11)); + +static bool tcg_out_goto(TCGContext *s, const tcg_insn_unit *target) +{ + tcg_out_opc_b(s, 0); + return reloc_br_sd10k16(s->code_ptr - 1, target); +} + +/* + * Emits common code for TLB addend lookup, that eventually loads the + * addend in TCG_REG_TMP2. + */ +static void tcg_out_tlb_load(TCGContext *s, TCGReg addrl, MemOpIdx oi, + tcg_insn_unit **label_ptr, bool is_load) +{ + MemOp opc = get_memop(oi); + unsigned s_bits = opc & MO_SIZE; + unsigned a_bits = get_alignment_bits(opc); + tcg_target_long compare_mask; + int mem_index = get_mmuidx(oi); + int fast_ofs = TLB_MASK_TABLE_OFS(mem_index); + int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask); + int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table); + + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs); + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs); + + tcg_out_opc_srli_d(s, TCG_REG_TMP2, addrl, + TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); + tcg_out_opc_and(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0); + tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1); + + /* Load the tlb comparator and the addend. */ + tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP0, TCG_REG_TMP2, + is_load ? offsetof(CPUTLBEntry, addr_read) + : offsetof(CPUTLBEntry, addr_write)); + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2, + offsetof(CPUTLBEntry, addend)); + + /* We don't support unaligned accesses. */ + if (a_bits < s_bits) { + a_bits = s_bits; + } + /* Clear the non-page, non-alignment bits from the address. */ + compare_mask = (tcg_target_long)TARGET_PAGE_MASK | ((1 << a_bits) - 1); + tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_TMP1, compare_mask); + tcg_out_opc_and(s, TCG_REG_TMP1, TCG_REG_TMP1, addrl); + + /* Compare masked address with the TLB entry. */ + label_ptr[0] = s->code_ptr; + tcg_out_opc_bne(s, TCG_REG_TMP0, TCG_REG_TMP1, 0); + + /* TLB Hit - addend in TCG_REG_TMP2, ready for use. */ +} + +static void add_qemu_ldst_label(TCGContext *s, int is_ld, MemOpIdx oi, + TCGType type, + TCGReg datalo, TCGReg addrlo, + void *raddr, tcg_insn_unit **label_ptr) +{ + TCGLabelQemuLdst *label = new_ldst_label(s); + + label->is_ld = is_ld; + label->oi = oi; + label->type = type; + label->datalo_reg = datalo; + label->datahi_reg = 0; /* unused */ + label->addrlo_reg = addrlo; + label->addrhi_reg = 0; /* unused */ + label->raddr = tcg_splitwx_to_rx(raddr); + label->label_ptr[0] = label_ptr[0]; +} + +static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) +{ + MemOpIdx oi = l->oi; + MemOp opc = get_memop(oi); + MemOp size = opc & MO_SIZE; + TCGType type = l->type; + + /* resolve label address */ + if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { + return false; + } + + /* call load helper */ + tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); + tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A1, l->addrlo_reg); + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A2, oi); + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A3, (tcg_target_long)l->raddr); + + tcg_out_call(s, qemu_ld_helpers[size]); + + switch (opc & MO_SSIZE) { + case MO_SB: + tcg_out_ext8s(s, l->datalo_reg, TCG_REG_A0); + break; + case MO_SW: + tcg_out_ext16s(s, l->datalo_reg, TCG_REG_A0); + break; + case MO_SL: + tcg_out_ext32s(s, l->datalo_reg, TCG_REG_A0); + break; + case MO_UL: + if (type == TCG_TYPE_I32) { + /* MO_UL loads of i32 should be sign-extended too */ + tcg_out_ext32s(s, l->datalo_reg, TCG_REG_A0); + break; + } + /* fallthrough */ + default: + tcg_out_mov(s, type, l->datalo_reg, TCG_REG_A0); + break; + } + + return tcg_out_goto(s, l->raddr); +} + +static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) +{ + MemOpIdx oi = l->oi; + MemOp opc = get_memop(oi); + MemOp size = opc & MO_SIZE; + + /* resolve label address */ + if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) { + return false; + } + + /* call store helper */ + tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_AREG0); + tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_A1, l->addrlo_reg); + switch (size) { + case MO_8: + tcg_out_ext8u(s, TCG_REG_A2, l->datalo_reg); + break; + case MO_16: + tcg_out_ext16u(s, TCG_REG_A2, l->datalo_reg); + break; + case MO_32: + tcg_out_ext32u(s, TCG_REG_A2, l->datalo_reg); + break; + case MO_64: + tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_A2, l->datalo_reg); + break; + default: + g_assert_not_reached(); + break; + } + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A3, oi); + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A4, (tcg_target_long)l->raddr); + + tcg_out_call(s, qemu_st_helpers[size]); + + return tcg_out_goto(s, l->raddr); +} +#endif /* CONFIG_SOFTMMU */ + +/* + * `ext32u` the address register into the temp register given, + * if target is 32-bit, no-op otherwise. + * + * Returns the address register ready for use with TLB addend. + */ +static TCGReg tcg_out_zext_addr_if_32_bit(TCGContext *s, + TCGReg addr, TCGReg tmp) +{ + if (TARGET_LONG_BITS == 32) { + tcg_out_ext32u(s, tmp, addr); + return tmp; + } + return addr; +} + +static void tcg_out_qemu_ld_indexed(TCGContext *s, TCGReg rd, TCGReg rj, + TCGReg rk, MemOp opc, TCGType type) +{ + /* Byte swapping is left to middle-end expansion. */ + tcg_debug_assert((opc & MO_BSWAP) == 0); + + switch (opc & MO_SSIZE) { + case MO_UB: + tcg_out_opc_ldx_bu(s, rd, rj, rk); + break; + case MO_SB: + tcg_out_opc_ldx_b(s, rd, rj, rk); + break; + case MO_UW: + tcg_out_opc_ldx_hu(s, rd, rj, rk); + break; + case MO_SW: + tcg_out_opc_ldx_h(s, rd, rj, rk); + break; + case MO_UL: + if (type == TCG_TYPE_I64) { + tcg_out_opc_ldx_wu(s, rd, rj, rk); + break; + } + /* fallthrough */ + case MO_SL: + tcg_out_opc_ldx_w(s, rd, rj, rk); + break; + case MO_Q: + tcg_out_opc_ldx_d(s, rd, rj, rk); + break; + default: + g_assert_not_reached(); + } +} + +static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, TCGType type) +{ + TCGReg addr_regl; + TCGReg data_regl; + MemOpIdx oi; + MemOp opc; +#if defined(CONFIG_SOFTMMU) + tcg_insn_unit *label_ptr[1]; +#endif + TCGReg base; + + data_regl = *args++; + addr_regl = *args++; + oi = *args++; + opc = get_memop(oi); + +#if defined(CONFIG_SOFTMMU) + tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 1); + base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); + tcg_out_qemu_ld_indexed(s, data_regl, base, TCG_REG_TMP2, opc, type); + add_qemu_ldst_label(s, 1, oi, type, + data_regl, addr_regl, + s->code_ptr, label_ptr); +#else + base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); + TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; + tcg_out_qemu_ld_indexed(s, data_regl, base, guest_base_reg, opc, type); +#endif +} + +static void tcg_out_qemu_st_indexed(TCGContext *s, TCGReg data, + TCGReg rj, TCGReg rk, MemOp opc) +{ + /* Byte swapping is left to middle-end expansion. */ + tcg_debug_assert((opc & MO_BSWAP) == 0); + + switch (opc & MO_SIZE) { + case MO_8: + tcg_out_opc_stx_b(s, data, rj, rk); + break; + case MO_16: + tcg_out_opc_stx_h(s, data, rj, rk); + break; + case MO_32: + tcg_out_opc_stx_w(s, data, rj, rk); + break; + case MO_64: + tcg_out_opc_stx_d(s, data, rj, rk); + break; + default: + g_assert_not_reached(); + } +} + +static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args) +{ + TCGReg addr_regl; + TCGReg data_regl; + MemOpIdx oi; + MemOp opc; +#if defined(CONFIG_SOFTMMU) + tcg_insn_unit *label_ptr[1]; +#endif + TCGReg base; + + data_regl = *args++; + addr_regl = *args++; + oi = *args++; + opc = get_memop(oi); + +#if defined(CONFIG_SOFTMMU) + tcg_out_tlb_load(s, addr_regl, oi, label_ptr, 0); + base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); + tcg_out_qemu_st_indexed(s, data_regl, base, TCG_REG_TMP2, opc); + add_qemu_ldst_label(s, 0, oi, + 0, /* type param is unused for stores */ + data_regl, addr_regl, + s->code_ptr, label_ptr); +#else + base = tcg_out_zext_addr_if_32_bit(s, addr_regl, TCG_REG_TMP0); + TCGReg guest_base_reg = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO; + tcg_out_qemu_st_indexed(s, data_regl, base, guest_base_reg, opc); +#endif +} + /* * Entry-points */ @@ -1023,6 +1355,19 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_ldst(s, OPC_ST_D, a0, a1, a2); break; + case INDEX_op_qemu_ld_i32: + tcg_out_qemu_ld(s, args, TCG_TYPE_I32); + break; + case INDEX_op_qemu_ld_i64: + tcg_out_qemu_ld(s, args, TCG_TYPE_I64); + break; + case INDEX_op_qemu_st_i32: + tcg_out_qemu_st(s, args); + break; + case INDEX_op_qemu_st_i64: + tcg_out_qemu_st(s, args); + break; + case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: case INDEX_op_call: /* Always emitted via tcg_out_call. */ @@ -1050,6 +1395,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_brcond_i64: return C_O0_I2(rZ, rZ); + case INDEX_op_qemu_st_i32: + case INDEX_op_qemu_st_i64: + return C_O0_I2(LZ, L); + case INDEX_op_ext8s_i32: case INDEX_op_ext8s_i64: case INDEX_op_ext8u_i32: @@ -1087,6 +1436,10 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) case INDEX_op_ld_i64: return C_O1_I1(r, r); + case INDEX_op_qemu_ld_i32: + case INDEX_op_qemu_ld_i64: + return C_O1_I1(r, L); + case INDEX_op_andc_i32: case INDEX_op_andc_i64: case INDEX_op_orc_i32: From 697a59805933ca58f20d407ee2cb0f2a2c19fba1 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:58 +0800 Subject: [PATCH 063/730] tcg/loongarch64: Implement tcg_target_qemu_prologue Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Message-Id: <20211221054105.178795-25-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.c.inc | 68 ++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index f67d5fa110..0b7d6458c5 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -968,6 +968,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args) * Entry-points */ +static const tcg_insn_unit *tb_ret_addr; + static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg args[TCG_MAX_OP_ARGS], const int const_args[TCG_MAX_OP_ARGS]) @@ -1517,3 +1519,69 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) g_assert_not_reached(); } } + +static const int tcg_target_callee_save_regs[] = { + TCG_REG_S0, /* used for the global env (TCG_AREG0) */ + TCG_REG_S1, + TCG_REG_S2, + TCG_REG_S3, + TCG_REG_S4, + TCG_REG_S5, + TCG_REG_S6, + TCG_REG_S7, + TCG_REG_S8, + TCG_REG_S9, + TCG_REG_RA, /* should be last for ABI compliance */ +}; + +/* Stack frame parameters. */ +#define REG_SIZE (TCG_TARGET_REG_BITS / 8) +#define SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE) +#define TEMP_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long)) +#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \ + + TCG_TARGET_STACK_ALIGN - 1) \ + & -TCG_TARGET_STACK_ALIGN) +#define SAVE_OFS (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE) + +/* We're expecting to be able to use an immediate for frame allocation. */ +QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff); + +/* Generate global QEMU prologue and epilogue code */ +static void tcg_target_qemu_prologue(TCGContext *s) +{ + int i; + + tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE); + + /* TB prologue */ + tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE); + for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { + tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], + TCG_REG_SP, SAVE_OFS + i * REG_SIZE); + } + +#if !defined(CONFIG_SOFTMMU) + if (USE_GUEST_BASE) { + tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base); + tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); + } +#endif + + /* Call generated code */ + tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); + tcg_out_opc_jirl(s, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0); + + /* Return path for goto_ptr. Set return value to 0 */ + tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr); + tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO); + + /* TB epilogue */ + tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr); + for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { + tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i], + TCG_REG_SP, SAVE_OFS + i * REG_SIZE); + } + + tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE); + tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_RA, 0); +} From 30d420e4d35eca26e61c57b21ddc5c9f34894846 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:40:59 +0800 Subject: [PATCH 064/730] tcg/loongarch64: Implement exit_tb/goto_tb Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Message-Id: <20211221054105.178795-26-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.c.inc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 0b7d6458c5..92a30b791a 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -980,6 +980,25 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, int c2 = const_args[2]; switch (opc) { + case INDEX_op_exit_tb: + /* Reuse the zeroing that exists for goto_ptr. */ + if (a0 == 0) { + tcg_out_call_int(s, tcg_code_gen_epilogue, true); + } else { + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); + tcg_out_call_int(s, tb_ret_addr, true); + } + break; + + case INDEX_op_goto_tb: + assert(s->tb_jmp_insn_offset == 0); + /* indirect jump method */ + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, + (uintptr_t)(s->tb_jmp_target_addr + a0)); + tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0); + set_jmp_reset_offset(s, a0); + break; + case INDEX_op_mb: tcg_out_mb(s, a0); break; From 8df89cf0ae5f5ff658a27bdf8a045679eaf763c1 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:41:00 +0800 Subject: [PATCH 065/730] tcg/loongarch64: Implement tcg_target_init Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Message-Id: <20211221054105.178795-27-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.c.inc | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 92a30b791a..19bfc135f6 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -1604,3 +1604,30 @@ static void tcg_target_qemu_prologue(TCGContext *s) tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE); tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_RA, 0); } + +static void tcg_target_init(TCGContext *s) +{ + tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS; + tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS; + + tcg_target_call_clobber_regs = ALL_GENERAL_REGS; + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8); + tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9); + + s->reserved_regs = 0; + tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP); + tcg_regset_set_reg(s->reserved_regs, TCG_REG_RESERVED); +} From a9ae47486a001420606fae9cd10b7764ec4dbf7d Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:41:01 +0800 Subject: [PATCH 066/730] tcg/loongarch64: Register the JIT Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Message-Id: <20211221054105.178795-28-git@xen0n.name> Signed-off-by: Richard Henderson --- tcg/loongarch64/tcg-target.c.inc | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 19bfc135f6..9cd46c9be3 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -1631,3 +1631,47 @@ static void tcg_target_init(TCGContext *s) tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP); tcg_regset_set_reg(s->reserved_regs, TCG_REG_RESERVED); } + +typedef struct { + DebugFrameHeader h; + uint8_t fde_def_cfa[4]; + uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2]; +} DebugFrame; + +#define ELF_HOST_MACHINE EM_LOONGARCH + +static const DebugFrame debug_frame = { + .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */ + .h.cie.id = -1, + .h.cie.version = 1, + .h.cie.code_align = 1, + .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */ + .h.cie.return_column = TCG_REG_RA, + + /* Total FDE size does not include the "len" member. */ + .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset), + + .fde_def_cfa = { + 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */ + (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ + (FRAME_SIZE >> 7) + }, + .fde_reg_ofs = { + 0x80 + 23, 11, /* DW_CFA_offset, s0, -88 */ + 0x80 + 24, 10, /* DW_CFA_offset, s1, -80 */ + 0x80 + 25, 9, /* DW_CFA_offset, s2, -72 */ + 0x80 + 26, 8, /* DW_CFA_offset, s3, -64 */ + 0x80 + 27, 7, /* DW_CFA_offset, s4, -56 */ + 0x80 + 28, 6, /* DW_CFA_offset, s5, -48 */ + 0x80 + 29, 5, /* DW_CFA_offset, s6, -40 */ + 0x80 + 30, 4, /* DW_CFA_offset, s7, -32 */ + 0x80 + 31, 3, /* DW_CFA_offset, s8, -24 */ + 0x80 + 22, 2, /* DW_CFA_offset, s9, -16 */ + 0x80 + 1 , 1, /* DW_CFA_offset, ra, -8 */ + } +}; + +void tcg_register_jit(const void *buf, size_t buf_size) +{ + tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); +} From 6016b7b46edb714a53a31536b30ead9c3aafaef7 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:41:02 +0800 Subject: [PATCH 067/730] common-user: Add safe syscall handling for loongarch64 hosts Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Message-Id: <20211221054105.178795-29-git@xen0n.name> Signed-off-by: Richard Henderson --- .../host/loongarch64/safe-syscall.inc.S | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 common-user/host/loongarch64/safe-syscall.inc.S diff --git a/common-user/host/loongarch64/safe-syscall.inc.S b/common-user/host/loongarch64/safe-syscall.inc.S new file mode 100644 index 0000000000..b88a069c45 --- /dev/null +++ b/common-user/host/loongarch64/safe-syscall.inc.S @@ -0,0 +1,90 @@ +/* + * safe-syscall.inc.S : host-specific assembly fragment + * to handle signals occurring at the same time as system calls. + * This is intended to be included by common-user/safe-syscall.S + * + * Ported to LoongArch by WANG Xuerui + * + * Based on safe-syscall.inc.S code for RISC-V, + * originally written by Richard Henderson + * Copyright (C) 2018 Linaro, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + + .global safe_syscall_base + .global safe_syscall_start + .global safe_syscall_end + .type safe_syscall_base, @function + .type safe_syscall_start, @function + .type safe_syscall_end, @function + + /* + * This is the entry point for making a system call. The calling + * convention here is that of a C varargs function with the + * first argument an 'int *' to the signal_pending flag, the + * second one the system call number (as a 'long'), and all further + * arguments being syscall arguments (also 'long'). + */ +safe_syscall_base: + .cfi_startproc + /* + * The syscall calling convention is nearly the same as C: + * we enter with a0 == &signal_pending + * a1 == syscall number + * a2 ... a7 == syscall arguments + * and return the result in a0 + * and the syscall instruction needs + * a7 == syscall number + * a0 ... a5 == syscall arguments + * and returns the result in a0 + * Shuffle everything around appropriately. + */ + move $t0, $a0 /* signal_pending pointer */ + move $t1, $a1 /* syscall number */ + move $a0, $a2 /* syscall arguments */ + move $a1, $a3 + move $a2, $a4 + move $a3, $a5 + move $a4, $a6 + move $a5, $a7 + move $a7, $t1 + + /* + * We need to preserve the signal_pending pointer but t0 is + * clobbered by syscalls on LoongArch, so we need to move it + * somewhere else, ideally both preserved across syscalls and + * clobbered by procedure calls so we don't have to allocate a + * stack frame; a6 is just the register we want here. + */ + move $a6, $t0 + + /* + * This next sequence of code works in conjunction with the + * rewind_if_safe_syscall_function(). If a signal is taken + * and the interrupted PC is anywhere between 'safe_syscall_start' + * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. + * The code sequence must therefore be able to cope with this, and + * the syscall instruction must be the final one in the sequence. + */ +safe_syscall_start: + /* If signal_pending is non-zero, don't do the call */ + ld.w $t1, $a6, 0 + bnez $t1, 2f + syscall 0 +safe_syscall_end: + /* code path for having successfully executed the syscall */ + li.w $t2, -4096 + bgtu $a0, $t2, 0f + jr $ra + + /* code path setting errno */ +0: sub.d $a0, $zero, $a0 + b safe_syscall_set_errno_tail + + /* code path when we didn't execute the syscall */ +2: li.w $a0, QEMU_ERESTARTSYS + b safe_syscall_set_errno_tail + .cfi_endproc + .size safe_syscall_base, .-safe_syscall_base From ad812c3bd6504948ee387f3e94eca7f28e8cd56f Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:41:03 +0800 Subject: [PATCH 068/730] linux-user: Implement CPU-specific signal handler for loongarch64 hosts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-30-git@xen0n.name> Signed-off-by: Richard Henderson --- linux-user/host/loongarch64/host-signal.h | 87 +++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 linux-user/host/loongarch64/host-signal.h diff --git a/linux-user/host/loongarch64/host-signal.h b/linux-user/host/loongarch64/host-signal.h new file mode 100644 index 0000000000..05e2c82371 --- /dev/null +++ b/linux-user/host/loongarch64/host-signal.h @@ -0,0 +1,87 @@ +/* + * host-signal.h: signal info dependent on the host architecture + * + * Copyright (c) 2003-2005 Fabrice Bellard + * Copyright (c) 2021 WANG Xuerui + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef LOONGARCH64_HOST_SIGNAL_H +#define LOONGARCH64_HOST_SIGNAL_H + +static inline uintptr_t host_signal_pc(ucontext_t *uc) +{ + return uc->uc_mcontext.__pc; +} + +static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc) +{ + uc->uc_mcontext.__pc = pc; +} + +static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc) +{ + const uint32_t *pinsn = (const uint32_t *)host_signal_pc(uc); + uint32_t insn = pinsn[0]; + + /* Detect store by reading the instruction at the program counter. */ + switch ((insn >> 26) & 0b111111) { + case 0b001000: /* {ll,sc}.[wd] */ + switch ((insn >> 24) & 0b11) { + case 0b01: /* sc.w */ + case 0b11: /* sc.d */ + return true; + } + break; + case 0b001001: /* {ld,st}ox4.[wd] ({ld,st}ptr.[wd]) */ + switch ((insn >> 24) & 0b11) { + case 0b01: /* stox4.w (stptr.w) */ + case 0b11: /* stox4.d (stptr.d) */ + return true; + } + break; + case 0b001010: /* {ld,st}.* family */ + switch ((insn >> 22) & 0b1111) { + case 0b0100: /* st.b */ + case 0b0101: /* st.h */ + case 0b0110: /* st.w */ + case 0b0111: /* st.d */ + case 0b1101: /* fst.s */ + case 0b1111: /* fst.d */ + return true; + } + break; + case 0b001110: /* indexed, atomic, bounds-checking memory operations */ + uint32_t sel = (insn >> 15) & 0b11111111111; + + switch (sel) { + case 0b00000100000: /* stx.b */ + case 0b00000101000: /* stx.h */ + case 0b00000110000: /* stx.w */ + case 0b00000111000: /* stx.d */ + case 0b00001110000: /* fstx.s */ + case 0b00001111000: /* fstx.d */ + case 0b00011101100: /* fstgt.s */ + case 0b00011101101: /* fstgt.d */ + case 0b00011101110: /* fstle.s */ + case 0b00011101111: /* fstle.d */ + case 0b00011111000: /* stgt.b */ + case 0b00011111001: /* stgt.h */ + case 0b00011111010: /* stgt.w */ + case 0b00011111011: /* stgt.d */ + case 0b00011111100: /* stle.b */ + case 0b00011111101: /* stle.h */ + case 0b00011111110: /* stle.w */ + case 0b00011111111: /* stle.d */ + case 0b00011000000 ... 0b00011100011: /* am* insns */ + return true; + } + break; + } + + return false; +} + +#endif From dfcf900ba67040ea9aa839aa38b33b4c091721d8 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 21 Dec 2021 13:41:04 +0800 Subject: [PATCH 069/730] configure, meson.build: Mark support for loongarch64 hosts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Example output of `uname -a` on an initial Gentoo LA64 port, running the upstream submission version of Linux (with some very minor patches not influencing output here): > Linux 5.14.0-10342-g37a00851b145 #5 SMP PREEMPT Tue Aug 10 12:56:24 PM CST 2021 loongarch64 GNU/Linux And the same on the vendor-supplied Loongnix 20 system, with an early in-house port of Linux, and using the old-world ABI: > Linux 4.19.167-rc5.lnd.1-loongson-3 #1 SMP Sat Apr 17 07:32:32 UTC 2021 loongarch64 loongarch64 loongarch64 GNU/Linux So a name of "loongarch64" matches both, fortunately. Signed-off-by: WANG Xuerui Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211221054105.178795-31-git@xen0n.name> Signed-off-by: Richard Henderson --- configure | 5 +++++ meson.build | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 51eae49daf..eb977e5b6f 100755 --- a/configure +++ b/configure @@ -631,6 +631,8 @@ elif check_define __arm__ ; then cpu="arm" elif check_define __aarch64__ ; then cpu="aarch64" +elif check_define __loongarch64 ; then + cpu="loongarch64" else cpu=$(uname -m) fi @@ -3720,6 +3722,9 @@ if test "$linux" = "yes" ; then aarch64) linux_arch=arm64 ;; + loongarch*) + linux_arch=loongarch + ;; mips64) linux_arch=mips ;; diff --git a/meson.build b/meson.build index 73d4b241df..17c7280f78 100644 --- a/meson.build +++ b/meson.build @@ -56,7 +56,7 @@ python = import('python').find_installation() supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux'] supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv', 'x86', 'x86_64', - 'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64'] + 'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc', 'sparc64'] cpu = host_machine.cpu_family() From 1b529d908d1e97ac154ab0e68573f8c211aac3f1 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Mon, 20 Dec 2021 15:53:14 +0100 Subject: [PATCH 070/730] failover: Silence warning messages during qtest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit virtio-net-failover test tries several device combinations that produces some expected warnings. These warning can be confusing, so we disable them during the qtest sequence. Reported-by: Thomas Huth Signed-off-by: Laurent Vivier Message-Id: <20211220145314.390697-1-lvivier@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Acked-by: Jason Wang [thuth: Fix memory leak by using error_free()] Signed-off-by: Thomas Huth --- hw/net/virtio-net.c | 7 ++++++- migration/migration.c | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index f2014d5ea0..cf8ab0f8af 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -44,6 +44,7 @@ #include "hw/pci/pci.h" #include "net_rx_pkt.h" #include "hw/virtio/vhost.h" +#include "sysemu/qtest.h" #define VIRTIO_NET_VM_VERSION 11 @@ -926,7 +927,11 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features) qatomic_set(&n->failover_primary_hidden, false); failover_add_primary(n, &err); if (err) { - warn_report_err(err); + if (!qtest_enabled()) { + warn_report_err(err); + } else { + error_free(err); + } } } } diff --git a/migration/migration.c b/migration/migration.c index 3de11ae921..0652165610 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -60,6 +60,7 @@ #include "qemu/yank.h" #include "sysemu/cpus.h" #include "yank_functions.h" +#include "sysemu/qtest.h" #define MAX_THROTTLE (128 << 20) /* Migration transfer speed throttling */ @@ -3766,7 +3767,8 @@ static void qemu_savevm_wait_unplug(MigrationState *s, int old_state, while (timeout-- && qemu_savevm_state_guest_unplug_pending()) { qemu_sem_timedwait(&s->wait_unplug_sem, 250); } - if (qemu_savevm_state_guest_unplug_pending()) { + if (qemu_savevm_state_guest_unplug_pending() && + !qtest_enabled()) { warn_report("migration: partially unplugged device on " "failure"); } From 046da5ef5747b8ae8efa02bd1d068abd5d639a12 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 20 Dec 2021 17:40:42 +0100 Subject: [PATCH 071/730] tests/qtest/boot-serial-test: Silence the warning about deprecated sga device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When running the qtests, there are currently a bunch of warnings about the deprecated sga device during the boot-serial-test. Switch to "-M graphics=off" to silence these warnings. Message-Id: <20211220164042.397028-1-thuth@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Signed-off-by: Thomas Huth --- tests/qtest/boot-serial-test.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c index 4d8e1343bd..d72a82d629 100644 --- a/tests/qtest/boot-serial-test.c +++ b/tests/qtest/boot-serial-test.c @@ -157,11 +157,11 @@ static testdef_t tests[] = { { "ppc64", "powernv8", "", "OPAL" }, { "ppc64", "powernv9", "", "OPAL" }, { "ppc64", "sam460ex", "-device e1000", "8086 100e" }, - { "i386", "isapc", "-cpu qemu32 -device sga", "SGABIOS" }, - { "i386", "pc", "-device sga", "SGABIOS" }, - { "i386", "q35", "-device sga", "SGABIOS" }, - { "x86_64", "isapc", "-cpu qemu32 -device sga", "SGABIOS" }, - { "x86_64", "q35", "-device sga", "SGABIOS" }, + { "i386", "isapc", "-cpu qemu32 -M graphics=off", "SeaBIOS" }, + { "i386", "pc", "-M graphics=off", "SeaBIOS" }, + { "i386", "q35", "-M graphics=off", "SeaBIOS" }, + { "x86_64", "isapc", "-cpu qemu32 -M graphics=off", "SeaBIOS" }, + { "x86_64", "q35", "-M graphics=off", "SeaBIOS" }, { "sparc", "LX", "", "TMS390S10" }, { "sparc", "SS-4", "", "MB86904" }, { "sparc", "SS-600MP", "", "TMS390Z55" }, From 31fb263c2963489055789385aa8b91663756edee Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 20 Dec 2021 11:30:25 +0100 Subject: [PATCH 072/730] tests/qtest: Make the filter tests independent from a specific NIC These filter tests need a NIC, no matter which one, so they use a common NIC by default. However, these common NIC models might not always have been compiled into the QEMU target binary, so assuming that a certain NIC is available is a bad idea. Since the exact type of NIC does not really matter for these tests, let's switch to "-nic" instead of "-netdev" so that QEMU can simply pick a default NIC for us. This way we can now run the tests on other targets that have a default machine with an on-board/default NIC, too. Signed-off-by: Thomas Huth Message-Id: <20211220103025.311759-1-thuth@redhat.com> Reviewed-by: Zhang Chen Signed-off-by: Thomas Huth --- tests/qtest/meson.build | 40 +++++++++++++++++++++------- tests/qtest/test-filter-mirror.c | 10 ++----- tests/qtest/test-filter-redirector.c | 20 +++----------- tests/qtest/test-netfilter.c | 8 +----- 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 1b2bde6660..37e1eaa449 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -47,7 +47,6 @@ qtests_i386 = \ (have_tools ? ['ahci-test'] : []) + \ (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ (config_all_devices.has_key('CONFIG_SGA') ? ['boot-serial-test'] : []) + \ - (config_all_devices.has_key('CONFIG_RTL8139_PCI') ? ['test-filter-redirector'] : []) + \ (config_all_devices.has_key('CONFIG_ISA_IPMI_KCS') ? ['ipmi-kcs-test'] : []) + \ (config_host.has_key('CONFIG_LINUX') and \ config_all_devices.has_key('CONFIG_ISA_IPMI_BT') ? ['ipmi-bt-test'] : []) + \ @@ -90,7 +89,9 @@ qtests_i386 = \ 'vmgenid-test', 'migration-test', 'test-x86-cpuid-compat', - 'numa-test'] + 'numa-test', + 'test-filter-redirector' + ] if dbus_display qtests_i386 += ['dbus-display-test'] @@ -113,31 +114,49 @@ endif qtests_x86_64 = qtests_i386 -qtests_alpha = [ 'boot-serial-test' ] + \ +qtests_alpha = ['boot-serial-test'] + \ + ['test-filter-mirror', 'test-filter-redirector'] + \ + (slirp.found() ? ['test-netfilter'] : []) + \ (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) qtests_avr = [ 'boot-serial-test' ] -qtests_hppa = [ 'boot-serial-test' ] + \ +qtests_hppa = ['boot-serial-test'] + \ + ['test-filter-mirror', 'test-filter-redirector'] + \ + (slirp.found() ? ['test-netfilter'] : []) + \ (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) -qtests_m68k = [ 'boot-serial-test' ] -qtests_microblaze = [ 'boot-serial-test' ] +qtests_m68k = ['boot-serial-test'] + \ + ['test-filter-mirror', 'test-filter-redirector'] + \ + (slirp.found() ? ['test-netfilter'] : []) + +qtests_microblaze = ['boot-serial-test'] + \ + ['test-filter-mirror', 'test-filter-redirector'] + \ + (slirp.found() ? ['test-netfilter'] : []) + qtests_microblazeel = qtests_microblaze qtests_mips = \ + ['test-filter-mirror', 'test-filter-redirector'] + \ + (slirp.found() ? ['test-netfilter'] : []) + \ (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) qtests_mips64 = \ + ['test-filter-mirror', 'test-filter-redirector'] + \ + (slirp.found() ? ['test-netfilter'] : []) + \ (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) qtests_mips64el = \ + ['test-filter-mirror', 'test-filter-redirector'] + \ + (slirp.found() ? ['test-netfilter'] : []) + \ (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) qtests_ppc = \ + ['test-filter-mirror', 'test-filter-redirector'] + \ + (slirp.found() ? ['test-netfilter'] : []) + \ (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ (config_all_devices.has_key('CONFIG_M48T59') ? ['m48t59-test'] : []) + \ ['boot-order-test', 'prom-env-test', 'boot-serial-test'] \ @@ -147,19 +166,22 @@ qtests_ppc64 = \ (config_all_devices.has_key('CONFIG_PSERIES') ? ['device-plug-test'] : []) + \ (config_all_devices.has_key('CONFIG_POWERNV') ? ['pnv-xscom-test'] : []) + \ (config_all_devices.has_key('CONFIG_PSERIES') ? ['rtas-test'] : []) + \ - (slirp.found() ? ['pxe-test', 'test-netfilter'] : []) + \ + (slirp.found() ? ['pxe-test'] : []) + \ (config_all_devices.has_key('CONFIG_USB_UHCI') ? ['usb-hcd-uhci-test'] : []) + \ (config_all_devices.has_key('CONFIG_USB_XHCI_NEC') ? ['usb-hcd-xhci-test'] : []) + \ - (config_host.has_key('CONFIG_POSIX') ? ['test-filter-mirror'] : []) + \ qtests_pci + ['migration-test', 'numa-test', 'cpu-plug-test', 'drive_del-test'] qtests_sh4 = (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) qtests_sh4eb = (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) -qtests_sparc = ['prom-env-test', 'm48t59-test', 'boot-serial-test'] +qtests_sparc = ['prom-env-test', 'm48t59-test', 'boot-serial-test'] + \ + ['test-filter-mirror', 'test-filter-redirector'] + \ + (slirp.found() ? ['test-netfilter'] : []) qtests_sparc64 = \ (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ + (slirp.found() ? ['test-netfilter'] : []) + \ + ['test-filter-mirror', 'test-filter-redirector'] + \ ['prom-env-test', 'boot-serial-test'] qtests_npcm7xx = \ diff --git a/tests/qtest/test-filter-mirror.c b/tests/qtest/test-filter-mirror.c index bc0dee64dd..95367d14d3 100644 --- a/tests/qtest/test-filter-mirror.c +++ b/tests/qtest/test-filter-mirror.c @@ -28,13 +28,8 @@ static void test_mirror(void) char *recv_buf; uint32_t size = sizeof(send_buf); size = htonl(size); - const char *devstr = "e1000"; QTestState *qts; - if (g_str_equal(qtest_get_arch(), "s390x")) { - devstr = "virtio-net-ccw"; - } - ret = socketpair(PF_UNIX, SOCK_STREAM, 0, send_sock); g_assert_cmpint(ret, !=, -1); @@ -42,11 +37,10 @@ static void test_mirror(void) g_assert_cmpint(ret, !=, -1); qts = qtest_initf( - "-netdev socket,id=qtest-bn0,fd=%d " - "-device %s,netdev=qtest-bn0,id=qtest-e0 " + "-nic socket,id=qtest-bn0,fd=%d " "-chardev socket,id=mirror0,fd=%d " "-object filter-mirror,id=qtest-f0,netdev=qtest-bn0,queue=tx,outdev=mirror0 " - , send_sock[1], devstr, recv_sock[1]); + , send_sock[1], recv_sock[1]); struct iovec iov[] = { { diff --git a/tests/qtest/test-filter-redirector.c b/tests/qtest/test-filter-redirector.c index 4269b2cdd9..4f3f59cba8 100644 --- a/tests/qtest/test-filter-redirector.c +++ b/tests/qtest/test-filter-redirector.c @@ -62,16 +62,6 @@ /* TODO actually test the results and get rid of this */ #define qmp_discard_response(qs, ...) qobject_unref(qtest_qmp(qs, __VA_ARGS__)) -static const char *get_devstr(void) -{ - if (g_str_equal(qtest_get_arch(), "s390x")) { - return "virtio-net-ccw"; - } - - return "rtl8139"; -} - - static void test_redirector_tx(void) { int backend_sock[2], recv_sock; @@ -93,8 +83,7 @@ static void test_redirector_tx(void) g_assert_cmpint(ret, !=, -1); qts = qtest_initf( - "-netdev socket,id=qtest-bn0,fd=%d " - "-device %s,netdev=qtest-bn0,id=qtest-e0 " + "-nic socket,id=qtest-bn0,fd=%d " "-chardev socket,id=redirector0,path=%s,server=on,wait=off " "-chardev socket,id=redirector1,path=%s,server=on,wait=off " "-chardev socket,id=redirector2,path=%s " @@ -103,7 +92,7 @@ static void test_redirector_tx(void) "-object filter-redirector,id=qtest-f1,netdev=qtest-bn0," "queue=tx,indev=redirector2 " "-object filter-redirector,id=qtest-f2,netdev=qtest-bn0," - "queue=tx,outdev=redirector1 ", backend_sock[1], get_devstr(), + "queue=tx,outdev=redirector1 ", backend_sock[1], sock_path0, sock_path1, sock_path0); recv_sock = unix_connect(sock_path1, NULL); @@ -163,8 +152,7 @@ static void test_redirector_rx(void) g_assert_cmpint(ret, !=, -1); qts = qtest_initf( - "-netdev socket,id=qtest-bn0,fd=%d " - "-device %s,netdev=qtest-bn0,id=qtest-e0 " + "-nic socket,id=qtest-bn0,fd=%d " "-chardev socket,id=redirector0,path=%s,server=on,wait=off " "-chardev socket,id=redirector1,path=%s,server=on,wait=off " "-chardev socket,id=redirector2,path=%s " @@ -173,7 +161,7 @@ static void test_redirector_rx(void) "-object filter-redirector,id=qtest-f1,netdev=qtest-bn0," "queue=rx,outdev=redirector2 " "-object filter-redirector,id=qtest-f2,netdev=qtest-bn0," - "queue=rx,indev=redirector1 ", backend_sock[1], get_devstr(), + "queue=rx,indev=redirector1 ", backend_sock[1], sock_path0, sock_path1, sock_path0); struct iovec iov[] = { diff --git a/tests/qtest/test-netfilter.c b/tests/qtest/test-netfilter.c index 785b6f3226..b09ef7fae9 100644 --- a/tests/qtest/test-netfilter.c +++ b/tests/qtest/test-netfilter.c @@ -178,11 +178,6 @@ int main(int argc, char **argv) { int ret; char *args; - const char *devstr = "e1000"; - - if (g_str_equal(qtest_get_arch(), "s390x")) { - devstr = "virtio-net-ccw"; - } g_test_init(&argc, &argv, NULL); qtest_add_func("/netfilter/addremove_one", add_one_netfilter); @@ -192,8 +187,7 @@ int main(int argc, char **argv) qtest_add_func("/netfilter/remove_netdev_multi", remove_netdev_with_multi_netfilter); - args = g_strdup_printf("-netdev user,id=qtest-bn0 " - "-device %s,netdev=qtest-bn0", devstr); + args = g_strdup_printf("-nic user,id=qtest-bn0"); qtest_start(args); ret = g_test_run(); From 487cf3f2b23e08dacdab0ebc7aaa12e03f65c822 Mon Sep 17 00:00:00 2001 From: Zhang Chen Date: Tue, 21 Dec 2021 16:04:00 +0800 Subject: [PATCH 073/730] MAINTAINERS: Update COLO Proxy section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Zhang Chen Message-Id: <20211221080400.1492980-1-chen.zhang@intel.com> Reviewed-by: Thomas Huth Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5dcefc0d01..5456536805 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2987,6 +2987,7 @@ F: docs/colo-proxy.txt F: net/colo* F: net/filter-rewriter.c F: net/filter-mirror.c +F: tests/qtest/test-filter* Record/replay M: Pavel Dovgalyuk From ad9e129b0162a1342a407c8d8e2073e4562206f2 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 20 Dec 2021 09:10:51 +0100 Subject: [PATCH 074/730] tests/qtest: Add a function that checks whether a device is available Devices might not always be compiled into the QEMU target binaries. We already have the libqos framework that is good for handling such situations, but some of the qtests are not a real good fit for the libqos framework. Let's add a qtest_has_device() function for such tests instead. Message-Id: <20211220081054.151515-2-thuth@redhat.com> Signed-off-by: Thomas Huth --- tests/qtest/libqos/libqtest.h | 8 +++++++ tests/qtest/libqtest.c | 44 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/tests/qtest/libqos/libqtest.h b/tests/qtest/libqos/libqtest.h index a6d38d7ef7..cf38d273f5 100644 --- a/tests/qtest/libqos/libqtest.h +++ b/tests/qtest/libqos/libqtest.h @@ -718,6 +718,14 @@ void qtest_cb_for_every_machine(void (*cb)(const char *machine), */ bool qtest_has_machine(const char *machine); +/** + * qtest_has_device: + * @device: The device to look for + * + * Returns: true if the device is available in the target binary. + */ +bool qtest_has_device(const char *device); + /** * qtest_qmp_device_add_qdict: * @qts: QTestState instance to operate on diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index a68326caae..41f4da4e54 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -1418,6 +1418,50 @@ bool qtest_has_machine(const char *machine) return false; } +bool qtest_has_device(const char *device) +{ + static QList *list; + const QListEntry *p; + QObject *qobj; + QString *qstr; + QDict *devinfo; + int idx; + + if (!list) { + QDict *resp; + QDict *args; + QTestState *qts = qtest_init("-machine none"); + + args = qdict_new(); + qdict_put_bool(args, "abstract", false); + qdict_put_str(args, "implements", "device"); + + resp = qtest_qmp(qts, "{'execute': 'qom-list-types', 'arguments': %p }", + args); + g_assert(qdict_haskey(resp, "return")); + list = qdict_get_qlist(resp, "return"); + qobject_ref(list); + qobject_unref(resp); + + qtest_quit(qts); + } + + for (p = qlist_first(list), idx = 0; p; p = qlist_next(p), idx++) { + devinfo = qobject_to(QDict, qlist_entry_obj(p)); + g_assert(devinfo); + + qobj = qdict_get(devinfo, "name"); + g_assert(qobj); + qstr = qobject_to(QString, qobj); + g_assert(qstr); + if (g_str_equal(qstring_get_str(qstr), device)) { + return true; + } + } + + return false; +} + /* * Generic hot-plugging test via the device_add QMP commands. */ From 9cbd66028b82c57f3f24399c6851f21495ccc775 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 20 Dec 2021 09:10:52 +0100 Subject: [PATCH 075/730] tests/qtest: Improve endianness-test to work with missing machines and devices The users might have built QEMU with less machines or without the i82378 superio device. Add some checks to the endianess-test so that it is able to deal with such stripped down QEMU versions, too. Message-Id: <20211220081054.151515-3-thuth@redhat.com> Signed-off-by: Thomas Huth --- tests/qtest/endianness-test.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/qtest/endianness-test.c b/tests/qtest/endianness-test.c index 09ecb531f1..9c03b72dc9 100644 --- a/tests/qtest/endianness-test.c +++ b/tests/qtest/endianness-test.c @@ -281,7 +281,10 @@ int main(int argc, char **argv) for (i = 0; test_cases[i].arch; i++) { gchar *path; - if (strcmp(test_cases[i].arch, arch) != 0) { + + if (!g_str_equal(test_cases[i].arch, arch) || + !qtest_has_machine(test_cases[i].machine) || + (test_cases[i].superio && !qtest_has_device(test_cases[i].superio))) { continue; } path = g_strdup_printf("endianness/%s", From 95c0b7701885a698a067f402fa430b7c1a562534 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 20 Dec 2021 09:10:53 +0100 Subject: [PATCH 076/730] tests/qtest/cdrom-test: Check whether devices are available before using them Downstream users might want to disable legacy devices in their binaries, so we should not blindly assume that they are available. Add some proper checks before using them. Message-Id: <20211220081054.151515-4-thuth@redhat.com> Signed-off-by: Thomas Huth --- tests/qtest/cdrom-test.c | 60 ++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/tests/qtest/cdrom-test.c b/tests/qtest/cdrom-test.c index c1fcac5c45..cfca24fa94 100644 --- a/tests/qtest/cdrom-test.c +++ b/tests/qtest/cdrom-test.c @@ -142,21 +142,36 @@ static void add_x86_tests(void) qtest_add_data_func("cdrom/boot/isapc", "-M isapc " "-drive if=ide,media=cdrom,file=", test_cdboot); } - qtest_add_data_func("cdrom/boot/am53c974", - "-device am53c974 -device scsi-cd,drive=cd1 " - "-drive if=none,id=cd1,format=raw,file=", test_cdboot); - qtest_add_data_func("cdrom/boot/dc390", - "-device dc390 -device scsi-cd,drive=cd1 " - "-blockdev file,node-name=cd1,filename=", test_cdboot); - qtest_add_data_func("cdrom/boot/lsi53c895a", - "-device lsi53c895a -device scsi-cd,drive=cd1 " - "-blockdev file,node-name=cd1,filename=", test_cdboot); - qtest_add_data_func("cdrom/boot/megasas", "-M q35 " - "-device megasas -device scsi-cd,drive=cd1 " - "-blockdev file,node-name=cd1,filename=", test_cdboot); - qtest_add_data_func("cdrom/boot/megasas-gen2", "-M q35 " - "-device megasas-gen2 -device scsi-cd,drive=cd1 " - "-blockdev file,node-name=cd1,filename=", test_cdboot); + if (qtest_has_device("am53c974")) { + qtest_add_data_func("cdrom/boot/am53c974", + "-device am53c974 -device scsi-cd,drive=cd1 " + "-drive if=none,id=cd1,format=raw,file=", + test_cdboot); + } + if (qtest_has_device("dc390")) { + qtest_add_data_func("cdrom/boot/dc390", + "-device dc390 -device scsi-cd,drive=cd1 " + "-blockdev file,node-name=cd1,filename=", + test_cdboot); + } + if (qtest_has_device("lsi53c895a")) { + qtest_add_data_func("cdrom/boot/lsi53c895a", + "-device lsi53c895a -device scsi-cd,drive=cd1 " + "-blockdev file,node-name=cd1,filename=", + test_cdboot); + } + if (qtest_has_device("megasas")) { + qtest_add_data_func("cdrom/boot/megasas", "-M q35 " + "-device megasas -device scsi-cd,drive=cd1 " + "-blockdev file,node-name=cd1,filename=", + test_cdboot); + } + if (qtest_has_device("megasas-gen2")) { + qtest_add_data_func("cdrom/boot/megasas-gen2", "-M q35 " + "-device megasas-gen2 -device scsi-cd,drive=cd1 " + "-blockdev file,node-name=cd1,filename=", + test_cdboot); + } } static void add_s390x_tests(void) @@ -171,12 +186,15 @@ static void add_s390x_tests(void) "-drive driver=null-co,read-zeroes=on,if=none,id=d1 " "-device virtio-blk,drive=d2,bootindex=1 " "-drive if=none,id=d2,media=cdrom,file=", test_cdboot); - qtest_add_data_func("cdrom/boot/without-bootindex", - "-device virtio-scsi -device virtio-serial " - "-device x-terminal3270 -device virtio-blk,drive=d1 " - "-drive driver=null-co,read-zeroes=on,if=none,id=d1 " - "-device virtio-blk,drive=d2 " - "-drive if=none,id=d2,media=cdrom,file=", test_cdboot); + if (qtest_has_device("x-terminal3270")) { + qtest_add_data_func("cdrom/boot/without-bootindex", + "-device virtio-scsi -device virtio-serial " + "-device x-terminal3270 -device virtio-blk,drive=d1 " + "-drive driver=null-co,read-zeroes=on,if=none,id=d1 " + "-device virtio-blk,drive=d2 " + "-drive if=none,id=d2,media=cdrom,file=", + test_cdboot); + } } int main(int argc, char **argv) From d6a3dd741823033c9f103f19c8a81044b2cb8c0e Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 20 Dec 2021 09:10:54 +0100 Subject: [PATCH 077/730] tests/qtest/boot-order-test: Check whether machines are available Machines might not always be compiled into the QEMU binary, so we should skip the test instead of failing if it is not available. Message-Id: <20211220081054.151515-5-thuth@redhat.com> Signed-off-by: Thomas Huth --- tests/qtest/boot-order-test.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/qtest/boot-order-test.c b/tests/qtest/boot-order-test.c index fac580d6c4..f1f59b1261 100644 --- a/tests/qtest/boot-order-test.c +++ b/tests/qtest/boot-order-test.c @@ -34,6 +34,11 @@ static void test_a_boot_order(const char *machine, uint64_t actual; QTestState *qts; + if (machine && !qtest_has_machine(machine)) { + g_test_skip("Machine is not available"); + return; + } + qts = qtest_initf("-nodefaults%s%s %s", machine ? " -M " : "", machine ?: "", test_args); actual = read_boot_order(qts); From e63ed64c6d10768b3a41c3337226372a9664ef6f Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 22 Dec 2021 09:30:54 +0100 Subject: [PATCH 078/730] tests/qtest/virtio-net-failover: Use g_file_open_tmp() to create temporary file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit g_test_rand_int() must not be called before g_test_init(), otherwise the glib will show a "g_rand_int: assertion 'rand != NULL' failed" message in the log. So we could change the order here, but actually, it's safer to use g_file_open_tmp() anyway, so let's use that function now instead. Reported-by: Philippe Mathieu-Daudé Suggested-by: Richard Henderson Message-Id: <20211222083652.776592-1-thuth@redhat.com> Signed-off-by: Thomas Huth --- tests/qtest/virtio-net-failover.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/qtest/virtio-net-failover.c b/tests/qtest/virtio-net-failover.c index 4b2ba8a106..22ad54bb95 100644 --- a/tests/qtest/virtio-net-failover.c +++ b/tests/qtest/virtio-net-failover.c @@ -1306,13 +1306,15 @@ static void test_multi_in(gconstpointer opaque) int main(int argc, char **argv) { - const gchar *tmpdir = g_get_tmp_dir(); - gchar *tmpfile = g_strdup_printf("%s/failover_test_migrate-%u-%u", - tmpdir, getpid(), g_test_rand_int()); + gchar *tmpfile; int ret; g_test_init(&argc, &argv, NULL); + ret = g_file_open_tmp("failover_test_migrate-XXXXXX", &tmpfile, NULL); + g_assert_true(ret >= 0); + close(ret); + qtest_add_func("failover-virtio-net/params/error/id", test_error_id); qtest_add_func("failover-virtio-net/params/error/pcie", test_error_pcie); qtest_add_func("failover-virtio-net/params/on", test_on); From 02dd48f8598be6c6be005594c5a6adca147b3a78 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Fri, 3 Dec 2021 13:22:21 +0100 Subject: [PATCH 079/730] iotests/testrunner.py: add doc string for run_test() We are going to modify these methods and will add more documentation in further commit. As a preparation add basic documentation. Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20211203122223.2780098-2-vsementsov@virtuozzo.com> Reviewed-by: John Snow Tested-by: John Snow Signed-off-by: Hanna Reitz --- tests/qemu-iotests/testrunner.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py index 0e29c2fddd..fa842252d3 100644 --- a/tests/qemu-iotests/testrunner.py +++ b/tests/qemu-iotests/testrunner.py @@ -220,6 +220,12 @@ class TestRunner(ContextManager['TestRunner']): return f'{test}.out' def do_run_test(self, test: str) -> TestResult: + """ + Run one test + + :param test: test file path + """ + f_test = Path(test) f_bad = Path(f_test.name + '.out.bad') f_notrun = Path(f_test.name + '.notrun') @@ -287,6 +293,13 @@ class TestRunner(ContextManager['TestRunner']): def run_test(self, test: str, test_field_width: Optional[int] = None) -> TestResult: + """ + Run one test and print short status + + :param test: test file path + :param test_field_width: width for first field of status format + """ + last_el = self.last_elapsed.get(test) start = datetime.datetime.now().strftime('%H:%M:%S') From 1f257b70d143d6c3330e6194bd977483c5f61b9b Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Fri, 3 Dec 2021 13:22:22 +0100 Subject: [PATCH 080/730] iotests/testrunner.py: move updating last_elapsed to run_tests We are going to use do_run_test() in multiprocessing environment, where we'll not be able to change original runner object. Happily, the only thing we change is that last_elapsed and it's simple to do it in run_tests() instead. All other accesses to self in do_runt_test() and in run_test() are read-only. Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20211203122223.2780098-3-vsementsov@virtuozzo.com> Reviewed-by: John Snow Tested-by: John Snow Signed-off-by: Hanna Reitz --- tests/qemu-iotests/testrunner.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py index fa842252d3..a9f2feb58c 100644 --- a/tests/qemu-iotests/testrunner.py +++ b/tests/qemu-iotests/testrunner.py @@ -287,7 +287,6 @@ class TestRunner(ContextManager['TestRunner']): diff=diff, casenotrun=casenotrun) else: f_bad.unlink() - self.last_elapsed.update(test, elapsed) return TestResult(status='pass', elapsed=elapsed, casenotrun=casenotrun) @@ -353,6 +352,9 @@ class TestRunner(ContextManager['TestRunner']): print('\n'.join(res.diff)) elif res.status == 'not run': notrun.append(name) + elif res.status == 'pass': + assert res.elapsed is not None + self.last_elapsed.update(t, res.elapsed) sys.stdout.flush() if res.interrupted: From 722f87df2545b308aec49b459b028f0802b4fd9e Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Fri, 3 Dec 2021 13:22:23 +0100 Subject: [PATCH 081/730] iotests: check: multiprocessing support Add -j parameter, to run tests in several jobs simultaneously. For realization - simply utilize multiprocessing.Pool class. Notes: 1. Of course, tests can't run simultaneously in same TEST_DIR. So, use subdirectories TEST_DIR/testname/ and SOCK_DIR/testname/ instead of simply TEST_DIR and SOCK_DIR 2. multiprocessing.Pool.starmap function doesn't support passing context managers, so we can't simply pass "self". Happily, we need self only for read-only access, and it just works if it is defined in global space. So, add a temporary link TestRunner.shared_self during run_tests(). Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20211203122223.2780098-4-vsementsov@virtuozzo.com> Reviewed-by: John Snow Tested-by: John Snow Signed-off-by: Hanna Reitz --- tests/qemu-iotests/check | 4 +- tests/qemu-iotests/testrunner.py | 69 ++++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check index 43a4b694cc..0c27721a41 100755 --- a/tests/qemu-iotests/check +++ b/tests/qemu-iotests/check @@ -34,6 +34,8 @@ def make_argparser() -> argparse.ArgumentParser: help='show me, do not run tests') p.add_argument('-makecheck', action='store_true', help='pretty print output for make check') + p.add_argument('-j', dest='jobs', type=int, default=1, + help='run tests in multiple parallel jobs') p.add_argument('-d', dest='debug', action='store_true', help='debug') p.add_argument('-p', dest='print', action='store_true', @@ -165,6 +167,6 @@ if __name__ == '__main__': with TestRunner(env, makecheck=args.makecheck, color=args.color) as tr: paths = [os.path.join(env.source_iotests, t) for t in tests] - ok = tr.run_tests(paths) + ok = tr.run_tests(paths, args.jobs) if not ok: sys.exit(1) diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py index a9f2feb58c..0feaa396d0 100644 --- a/tests/qemu-iotests/testrunner.py +++ b/tests/qemu-iotests/testrunner.py @@ -26,6 +26,7 @@ import contextlib import json import termios import sys +from multiprocessing import Pool from contextlib import contextmanager from typing import List, Optional, Iterator, Any, Sequence, Dict, \ ContextManager @@ -126,6 +127,31 @@ class TestResult: class TestRunner(ContextManager['TestRunner']): + shared_self = None + + @staticmethod + def proc_run_test(test: str, test_field_width: int) -> TestResult: + # We are in a subprocess, we can't change the runner object! + runner = TestRunner.shared_self + assert runner is not None + return runner.run_test(test, test_field_width, mp=True) + + def run_tests_pool(self, tests: List[str], + test_field_width: int, jobs: int) -> List[TestResult]: + + # passing self directly to Pool.starmap() just doesn't work, because + # it's a context manager. + assert TestRunner.shared_self is None + TestRunner.shared_self = self + + with Pool(jobs) as p: + results = p.starmap(self.proc_run_test, + zip(tests, [test_field_width] * len(tests))) + + TestRunner.shared_self = None + + return results + def __init__(self, env: TestEnv, makecheck: bool = False, color: str = 'auto') -> None: self.env = env @@ -219,11 +245,16 @@ class TestRunner(ContextManager['TestRunner']): return f'{test}.out' - def do_run_test(self, test: str) -> TestResult: + def do_run_test(self, test: str, mp: bool) -> TestResult: """ Run one test :param test: test file path + :param mp: if true, we are in a multiprocessing environment, use + personal subdirectories for test run + + Note: this method may be called from subprocess, so it does not + change ``self`` object in any way! """ f_test = Path(test) @@ -249,6 +280,12 @@ class TestRunner(ContextManager['TestRunner']): args = [str(f_test.resolve())] env = self.env.prepare_subprocess(args) + if mp: + # Split test directories, so that tests running in parallel don't + # break each other. + for d in ['TEST_DIR', 'SOCK_DIR']: + env[d] = os.path.join(env[d], f_test.name) + Path(env[d]).mkdir(parents=True, exist_ok=True) t0 = time.time() with f_bad.open('w', encoding="utf-8") as f: @@ -291,23 +328,32 @@ class TestRunner(ContextManager['TestRunner']): casenotrun=casenotrun) def run_test(self, test: str, - test_field_width: Optional[int] = None) -> TestResult: + test_field_width: Optional[int] = None, + mp: bool = False) -> TestResult: """ Run one test and print short status :param test: test file path :param test_field_width: width for first field of status format + :param mp: if true, we are in a multiprocessing environment, don't try + to rewrite things in stdout + + Note: this method may be called from subprocess, so it does not + change ``self`` object in any way! """ last_el = self.last_elapsed.get(test) start = datetime.datetime.now().strftime('%H:%M:%S') if not self.makecheck: - self.test_print_one_line(test=test, starttime=start, - lasttime=last_el, end='\r', + self.test_print_one_line(test=test, + status = 'started' if mp else '...', + starttime=start, + lasttime=last_el, + end = '\n' if mp else '\r', test_field_width=test_field_width) - res = self.do_run_test(test) + res = self.do_run_test(test, mp) end = datetime.datetime.now().strftime('%H:%M:%S') self.test_print_one_line(test=test, status=res.status, @@ -321,7 +367,7 @@ class TestRunner(ContextManager['TestRunner']): return res - def run_tests(self, tests: List[str]) -> bool: + def run_tests(self, tests: List[str], jobs: int = 1) -> bool: n_run = 0 failed = [] notrun = [] @@ -332,9 +378,16 @@ class TestRunner(ContextManager['TestRunner']): test_field_width = max(len(os.path.basename(t)) for t in tests) + 2 - for t in tests: + if jobs > 1: + results = self.run_tests_pool(tests, test_field_width, jobs) + + for i, t in enumerate(tests): name = os.path.basename(t) - res = self.run_test(t, test_field_width=test_field_width) + + if jobs > 1: + res = results[i] + else: + res = self.run_test(t, test_field_width) assert res.status in ('pass', 'fail', 'not run') From c34ec5137d67bab194d5c20e1c85e0e5d392af8c Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Mon, 6 Sep 2021 22:06:51 +0300 Subject: [PATCH 082/730] iotests.py: add qemu_tool_popen() Split qemu_tool_popen() from qemu_tool_pipe_and_status() to be used separately. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Nikita Lapshin --- tests/qemu-iotests/iotests.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 83bfedb902..452d047716 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -138,14 +138,22 @@ def unarchive_sample_image(sample, fname): shutil.copyfileobj(f_in, f_out) +def qemu_tool_popen(args: Sequence[str], + connect_stderr: bool = True) -> 'subprocess.Popen[str]': + stderr = subprocess.STDOUT if connect_stderr else None + # pylint: disable=consider-using-with + return subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=stderr, + universal_newlines=True) + + def qemu_tool_pipe_and_status(tool: str, args: Sequence[str], connect_stderr: bool = True) -> Tuple[str, int]: """ Run a tool and return both its output and its exit code """ - stderr = subprocess.STDOUT if connect_stderr else None - with subprocess.Popen(args, stdout=subprocess.PIPE, - stderr=stderr, universal_newlines=True) as subp: + with qemu_tool_popen(args, connect_stderr) as subp: output = subp.communicate()[0] if subp.returncode < 0: cmd = ' '.join(args) From 94a781f220141ad9f91a1c1583368cd5f24c4d7e Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Thu, 14 Oct 2021 19:01:14 +0200 Subject: [PATCH 083/730] iotests.py: add and use qemu_io_wrap_args() For qemu_io* functions support --image-opts argument, which conflicts with -f argument from qemu_io_args. For QemuIoInteractive use new wrapper as well, which allows relying on default format. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Nikita Lapshin --- tests/qemu-iotests/iotests.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 452d047716..c4b81a291b 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -241,10 +241,15 @@ def img_info_log(filename, filter_path=None, imgopts=False, extra_args=()): filter_path = filename log(filter_img_info(output, filter_path)) +def qemu_io_wrap_args(args: Sequence[str]) -> List[str]: + if '-f' in args or '--image-opts' in args: + return qemu_io_args_no_fmt + list(args) + else: + return qemu_io_args + list(args) + def qemu_io(*args): '''Run qemu-io and return the stdout data''' - args = qemu_io_args + list(args) - return qemu_tool_pipe_and_status('qemu-io', args)[0] + return qemu_tool_pipe_and_status('qemu-io', qemu_io_wrap_args(args))[0] def qemu_io_log(*args): result = qemu_io(*args) @@ -253,12 +258,7 @@ def qemu_io_log(*args): def qemu_io_silent(*args): '''Run qemu-io and return the exit code, suppressing stdout''' - if '-f' in args or '--image-opts' in args: - default_args = qemu_io_args_no_fmt - else: - default_args = qemu_io_args - - args = default_args + list(args) + args = qemu_io_wrap_args(args) result = subprocess.run(args, stdout=subprocess.DEVNULL, check=False) if result.returncode < 0: sys.stderr.write('qemu-io received signal %i: %s\n' % @@ -267,14 +267,14 @@ def qemu_io_silent(*args): def qemu_io_silent_check(*args): '''Run qemu-io and return the true if subprocess returned 0''' - args = qemu_io_args + list(args) + args = qemu_io_wrap_args(args) result = subprocess.run(args, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, check=False) return result.returncode == 0 class QemuIoInteractive: def __init__(self, *args): - self.args = qemu_io_args_no_fmt + list(args) + self.args = qemu_io_wrap_args(args) # We need to keep the Popen objext around, and not # close it immediately. Therefore, disable the pylint check: # pylint: disable=consider-using-with From 75c90eeeaf142f70c85ee6b5839abdd7cb1486f5 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Thu, 14 Oct 2021 19:02:06 +0200 Subject: [PATCH 084/730] iotests.py: add qemu_io_popen() Add qemu-io Popen constructor wrapper. To be used in the following new test commit. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Nikita Lapshin --- tests/qemu-iotests/iotests.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index c4b81a291b..1e2f2391d1 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -247,6 +247,9 @@ def qemu_io_wrap_args(args: Sequence[str]) -> List[str]: else: return qemu_io_args + list(args) +def qemu_io_popen(*args): + return qemu_tool_popen(qemu_io_wrap_args(args)) + def qemu_io(*args): '''Run qemu-io and return the stdout data''' return qemu_tool_pipe_and_status('qemu-io', qemu_io_wrap_args(args))[0] From ab7f7e67a7e7b49964109501dfcde4ec29bae60e Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Mon, 6 Sep 2021 22:06:54 +0300 Subject: [PATCH 085/730] iotests: add nbd-reconnect-on-open test Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Nikita Lapshin --- .../qemu-iotests/tests/nbd-reconnect-on-open | 71 +++++++++++++++++++ .../tests/nbd-reconnect-on-open.out | 11 +++ 2 files changed, 82 insertions(+) create mode 100755 tests/qemu-iotests/tests/nbd-reconnect-on-open create mode 100644 tests/qemu-iotests/tests/nbd-reconnect-on-open.out diff --git a/tests/qemu-iotests/tests/nbd-reconnect-on-open b/tests/qemu-iotests/tests/nbd-reconnect-on-open new file mode 100755 index 0000000000..8be721a24f --- /dev/null +++ b/tests/qemu-iotests/tests/nbd-reconnect-on-open @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +# +# Test nbd reconnect on open +# +# Copyright (c) 2020 Virtuozzo International GmbH +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import time + +import iotests +from iotests import qemu_img_create, file_path, qemu_io_popen, qemu_nbd, \ + qemu_io_log, log + +iotests.script_initialize(supported_fmts=['qcow2']) + +disk, nbd_sock = file_path('disk', 'nbd-sock') + + +def create_args(open_timeout): + return ['--image-opts', '-c', 'read 0 1M', + f'driver=nbd,open-timeout={open_timeout},' + f'server.type=unix,server.path={nbd_sock}'] + + +def check_fail_to_connect(open_timeout): + log(f'Check fail to connect with {open_timeout} seconds of timeout') + + start_t = time.time() + qemu_io_log(*create_args(open_timeout)) + delta_t = time.time() - start_t + + max_delta = open_timeout + 0.2 + if open_timeout <= delta_t <= max_delta: + log(f'qemu_io finished in {open_timeout}..{max_delta} seconds, OK') + else: + note = 'too early' if delta_t < open_timeout else 'too long' + log(f'qemu_io finished in {delta_t:.1f} seconds, {note}') + + +qemu_img_create('-f', iotests.imgfmt, disk, '1M') + +# Start NBD client when NBD server is not yet running. It should not fail, but +# wait for 5 seconds for the server to be available. +client = qemu_io_popen(*create_args(5)) + +time.sleep(1) +qemu_nbd('-k', nbd_sock, '-f', iotests.imgfmt, disk) + +# client should succeed +log(client.communicate()[0], filters=[iotests.filter_qemu_io]) + +# Server was started without --persistent flag, so it should be off now. Let's +# check it and at the same time check that with open-timeout=0 client fails +# immediately. +check_fail_to_connect(0) + +# Check that we will fail after non-zero timeout if server is still unavailable +check_fail_to_connect(1) diff --git a/tests/qemu-iotests/tests/nbd-reconnect-on-open.out b/tests/qemu-iotests/tests/nbd-reconnect-on-open.out new file mode 100644 index 0000000000..a35ae30ea4 --- /dev/null +++ b/tests/qemu-iotests/tests/nbd-reconnect-on-open.out @@ -0,0 +1,11 @@ +read 1048576/1048576 bytes at offset 0 +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +Check fail to connect with 0 seconds of timeout +qemu-io: can't open: Failed to connect to 'TEST_DIR/PID-nbd-sock': No such file or directory + +qemu_io finished in 0..0.2 seconds, OK +Check fail to connect with 1 seconds of timeout +qemu-io: can't open: Failed to connect to 'TEST_DIR/PID-nbd-sock': No such file or directory + +qemu_io finished in 1..1.2 seconds, OK From 3d2f73ef75e25ba850aff4fcccb36d50137afd0f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 11 Feb 2021 06:15:12 -0500 Subject: [PATCH 086/730] build: use "meson test" as the test harness "meson test" starting with version 0.57 is just as capable and easy to use as QEMU's own TAP driver. All existing options for "make check" work. The only required code change involves how to mark "slow" tests; they need to belong to an additional "slow" suite. The rules for .tap output are replaced by JUnit XML; GitLab is able to parse that output and present it in the CI pipeline report. Signed-off-by: Paolo Bonzini --- Makefile | 3 +- meson.build | 5 +- scripts/mtest2make.py | 112 +++++-------- scripts/tap-driver.pl | 379 ------------------------------------------ scripts/tap-merge.pl | 111 ------------- tests/fp/meson.build | 2 +- 6 files changed, 51 insertions(+), 561 deletions(-) delete mode 100755 scripts/tap-driver.pl delete mode 100755 scripts/tap-merge.pl diff --git a/Makefile b/Makefile index 74c5b46d38..5d66c35ea5 100644 --- a/Makefile +++ b/Makefile @@ -145,7 +145,8 @@ NINJAFLAGS = $(if $V,-v) $(if $(MAKE.n), -n) $(if $(MAKE.k), -k0) \ $(filter-out -j, $(lastword -j1 $(filter -l% -j%, $(MAKEFLAGS)))) \ ninja-cmd-goals = $(or $(MAKECMDGOALS), all) -ninja-cmd-goals += $(foreach t, $(.tests), $(.test.deps.$t)) +ninja-cmd-goals += $(foreach t, $(.check.build-suites), $(.check-$t.deps)) +ninja-cmd-goals += $(foreach t, $(.bench.build-suites), $(.bench-$t.deps)) makefile-targets := build.ninja ctags TAGS cscope dist clean uninstall # "ninja -t targets" also lists all prerequisites. If build system diff --git a/meson.build b/meson.build index f45ecf31bd..f0f1d5ba9d 100644 --- a/meson.build +++ b/meson.build @@ -1,8 +1,11 @@ project('qemu', ['c'], meson_version: '>=0.58.2', default_options: ['warning_level=1', 'c_std=gnu11', 'cpp_std=gnu++11', 'b_colorout=auto', - 'b_staticpic=false'], + 'b_staticpic=false', 'stdsplit=false'], version: files('VERSION')) +add_test_setup('quick', exclude_suites: 'slow', is_default: true) +add_test_setup('slow', env: ['G_TEST_SLOW=1', 'SPEED=slow']) + not_found = dependency('', required: false) keyval = import('keyval') ss = import('sourceset') diff --git a/scripts/mtest2make.py b/scripts/mtest2make.py index 02c0453e67..7067bdadf5 100644 --- a/scripts/mtest2make.py +++ b/scripts/mtest2make.py @@ -13,101 +13,79 @@ import sys class Suite(object): def __init__(self): - self.tests = list() - self.slow_tests = list() - self.executables = set() + self.deps = set() + self.speeds = ['quick'] + + def names(self, base): + return [base if speed == 'quick' else f'{base}-{speed}' for speed in self.speeds] + print(''' SPEED = quick -# $1 = environment, $2 = test command, $3 = test name, $4 = dir -.test-human-tap = $1 $(if $4,(cd $4 && $2),$2) -m $(SPEED) < /dev/null | ./scripts/tap-driver.pl --test-name="$3" $(if $(V),,--show-failures-only) -.test-human-exitcode = $1 $(PYTHON) scripts/test-driver.py $(if $4,-C$4) $(if $(V),--verbose) -- $2 < /dev/null -.test-tap-tap = $1 $(if $4,(cd $4 && $2),$2) < /dev/null | sed "s/^[a-z][a-z]* [0-9]*/& $3/" || true -.test-tap-exitcode = printf "%s\\n" 1..1 "`$1 $(if $4,(cd $4 && $2),$2) < /dev/null > /dev/null || echo "not "`ok 1 $3" -.test.human-print = echo $(if $(V),'$1 $2','Running test $3') && -.test.env = MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$(( $${RANDOM:-0} % 255 + 1))} +.speed.quick = $(foreach s,$(sort $(filter-out %-slow, $1)), --suite $s) +.speed.slow = $(foreach s,$(sort $1), --suite $s) -# $1 = test name, $2 = test target (human or tap) -.test.run = $(call .test.$2-print,$(.test.env.$1),$(.test.cmd.$1),$(.test.name.$1)) $(call .test-$2-$(.test.driver.$1),$(.test.env.$1),$(.test.cmd.$1),$(.test.name.$1),$(.test.dir.$1)) +.mtestargs = --no-rebuild -t 0 +ifneq ($(SPEED), quick) +.mtestargs += --setup $(SPEED) +endif +.mtestargs += $(subst -j,--num-processes , $(filter-out -j, $(lastword -j1 $(filter -j%, $(MAKEFLAGS))))) -.test.output-format = human -''') +.check.mtestargs = $(MTESTARGS) $(.mtestargs) $(if $(V),--verbose,--print-errorlogs) +.bench.mtestargs = $(MTESTARGS) $(.mtestargs) --benchmark --verbose''') introspect = json.load(sys.stdin) -i = 0 def process_tests(test, targets, suites): - global i - env = ' '.join(('%s=%s' % (shlex.quote(k), shlex.quote(v)) - for k, v in test['env'].items())) executable = test['cmd'][0] try: executable = os.path.relpath(executable) except: pass - if test['workdir'] is not None: - try: - test['cmd'][0] = os.path.relpath(executable, test['workdir']) - except: - test['cmd'][0] = executable - else: - test['cmd'][0] = executable - cmd = ' '.join((shlex.quote(x) for x in test['cmd'])) - driver = test['protocol'] if 'protocol' in test else 'exitcode' - - i += 1 - if test['workdir'] is not None: - print('.test.dir.%d := %s' % (i, shlex.quote(test['workdir']))) deps = (targets.get(x, []) for x in test['depends']) deps = itertools.chain.from_iterable(deps) - - print('.test.name.%d := %s' % (i, test['name'])) - print('.test.driver.%d := %s' % (i, driver)) - print('.test.env.%d := $(.test.env) %s' % (i, env)) - print('.test.cmd.%d := %s' % (i, cmd)) - print('.test.deps.%d := %s' % (i, ' '.join(deps))) - print('.PHONY: run-test-%d' % (i,)) - print('run-test-%d: $(.test.deps.%d)' % (i,i)) - print('\t@$(call .test.run,%d,$(.test.output-format))' % (i,)) + deps = list(deps) test_suites = test['suite'] or ['default'] - is_slow = any(s.endswith('-slow') for s in test_suites) for s in test_suites: # The suite name in the introspection info is "PROJECT:SUITE" s = s.split(':')[1] + if s == 'slow': + continue if s.endswith('-slow'): s = s[:-5] - if is_slow: - suites[s].slow_tests.append(i) - else: - suites[s].tests.append(i) - suites[s].executables.add(executable) + suites[s].speeds.append('slow') + suites[s].deps.update(deps) def emit_prolog(suites, prefix): - all_tap = ' '.join(('%s-report-%s.tap' % (prefix, k) for k in suites.keys())) - print('.PHONY: %s %s-report.tap %s' % (prefix, prefix, all_tap)) - print('%s: run-tests' % (prefix,)) - print('%s-report.tap %s: %s-report%%.tap: all' % (prefix, all_tap, prefix)) - print('''\t$(MAKE) .test.output-format=tap --quiet -Otarget V=1 %s$* | ./scripts/tap-merge.pl | tee "$@" \\ - | ./scripts/tap-driver.pl $(if $(V),, --show-failures-only)''' % (prefix, )) + all_targets = ' '.join((f'{prefix}-{k}' for k in suites.keys())) + all_xml = ' '.join((f'{prefix}-report-{k}.junit.xml' for k in suites.keys())) + print() + print(f'all-{prefix}-targets = {all_targets}') + print(f'all-{prefix}-xml = {all_xml}') + print(f'.PHONY: {prefix} do-meson-{prefix} {prefix}-report.junit.xml $(all-{prefix}-targets) $(all-{prefix}-xml)') + print(f'ifeq ($(filter {prefix}, $(MAKECMDGOALS)),)') + print(f'.{prefix}.mtestargs += $(call .speed.$(SPEED), $(.{prefix}.mtest-suites))') + print(f'endif') + print(f'{prefix}-build: run-ninja') + print(f'{prefix} $(all-{prefix}-targets): do-meson-{prefix}') + print(f'do-meson-{prefix}: run-ninja; $(if $(MAKE.n),,+)$(MESON) test $(.{prefix}.mtestargs)') + print(f'{prefix}-report.junit.xml $(all-{prefix}-xml): {prefix}-report%.junit.xml: run-ninja') + print(f'\t$(MAKE) {prefix}$* MTESTARGS="$(MTESTARGS) --logbase {prefix}-report$*" && ln -f meson-logs/$@ .') def emit_suite(name, suite, prefix): - executables = ' '.join(suite.executables) - slow_test_numbers = ' '.join((str(x) for x in suite.slow_tests)) - test_numbers = ' '.join((str(x) for x in suite.tests)) - target = '%s-%s' % (prefix, name) - print('.test.quick.%s := %s' % (target, test_numbers)) - print('.test.slow.%s := $(.test.quick.%s) %s' % (target, target, slow_test_numbers)) - print('%s-build: %s' % (prefix, executables)) - print('.PHONY: %s' % (target, )) - print('.PHONY: %s-report-%s.tap' % (prefix, name)) - print('%s: run-tests' % (target, )) - print('ifneq ($(filter %s %s, $(MAKECMDGOALS)),)' % (target, prefix)) - print('.tests += $(.test.$(SPEED).%s)' % (target, )) - print('endif') - print('all-%s-targets += %s' % (prefix, target)) + deps = ' '.join(suite.deps) + targets = f'{prefix}-{name} {prefix}-report-{name}.junit.xml {prefix} {prefix}-report.junit.xml' + print() + print(f'.{prefix}-{name}.deps = {deps}') + print(f'ifneq ($(filter {prefix}-build {targets}, $(MAKECMDGOALS)),)') + print(f'.{prefix}.build-suites += {name}') + print(f'endif') + print(f'ifneq ($(filter {targets}, $(MAKECMDGOALS)),)') + print(f'.{prefix}.mtest-suites += ' + ' '.join(suite.names(name))) + print(f'endif') targets = {t['id']: [os.path.relpath(f) for f in t['filename']] for t in introspect['targets']} @@ -125,5 +103,3 @@ for test in introspect['benchmarks']: emit_prolog(benchsuites, 'bench') for name, suite in benchsuites.items(): emit_suite(name, suite, 'bench') - -print('run-tests: $(patsubst %, run-test-%, $(.tests))') diff --git a/scripts/tap-driver.pl b/scripts/tap-driver.pl deleted file mode 100755 index b1d3880c50..0000000000 --- a/scripts/tap-driver.pl +++ /dev/null @@ -1,379 +0,0 @@ -#! /usr/bin/env perl -# Copyright (C) 2011-2013 Free Software Foundation, Inc. -# Copyright (C) 2018 Red Hat, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# ---------------------------------- # -# Imports, static data, and setup. # -# ---------------------------------- # - -use warnings FATAL => 'all'; -use strict; -use Getopt::Long (); -use TAP::Parser; -use Term::ANSIColor qw(:constants); - -my $ME = "tap-driver.pl"; -my $VERSION = "2018-11-30"; - -my $USAGE = <<'END'; -Usage: - tap-driver [--test-name=TEST] [--color={always|never|auto}] - [--verbose] [--show-failures-only] -END - -my $HELP = "$ME: TAP-aware test driver for QEMU testsuite harness." . - "\n" . $USAGE; - -# It's important that NO_PLAN evaluates "false" as a boolean. -use constant NO_PLAN => 0; -use constant EARLY_PLAN => 1; -use constant LATE_PLAN => 2; - -use constant DIAG_STRING => "#"; - -# ------------------- # -# Global variables. # -# ------------------- # - -my $testno = 0; # Number of test results seen so far. -my $bailed_out = 0; # Whether a "Bail out!" directive has been seen. -my $failed = 0; # Final exit code - -# Whether the TAP plan has been seen or not, and if yes, which kind -# it is ("early" is seen before any test result, "late" otherwise). -my $plan_seen = NO_PLAN; - -# ----------------- # -# Option parsing. # -# ----------------- # - -my %cfg = ( - "color" => 0, - "verbose" => 0, - "show-failures-only" => 0, -); - -my $color = "auto"; -my $test_name = undef; - -# Perl's Getopt::Long allows options to take optional arguments after a space. -# Prevent --color by itself from consuming other arguments -foreach (@ARGV) { - if ($_ eq "--color" || $_ eq "-color") { - $_ = "--color=$color"; - } -} - -Getopt::Long::GetOptions - ( - 'help' => sub { print $HELP; exit 0; }, - 'version' => sub { print "$ME $VERSION\n"; exit 0; }, - 'test-name=s' => \$test_name, - 'color=s' => \$color, - 'show-failures-only' => sub { $cfg{"show-failures-only"} = 1; }, - 'verbose' => sub { $cfg{"verbose"} = 1; }, - ) or exit 1; - -if ($color =~ /^always$/i) { - $cfg{'color'} = 1; -} elsif ($color =~ /^never$/i) { - $cfg{'color'} = 0; -} elsif ($color =~ /^auto$/i) { - $cfg{'color'} = (-t STDOUT); -} else { - die "Invalid color mode: $color\n"; -} - -# ------------- # -# Prototypes. # -# ------------- # - -sub colored ($$); -sub decorate_result ($); -sub extract_tap_comment ($); -sub handle_tap_bailout ($); -sub handle_tap_plan ($); -sub handle_tap_result ($); -sub is_null_string ($); -sub main (); -sub report ($;$); -sub stringify_result_obj ($); -sub testsuite_error ($); - -# -------------- # -# Subroutines. # -# -------------- # - -# If the given string is undefined or empty, return true, otherwise -# return false. This function is useful to avoid pitfalls like: -# if ($message) { print "$message\n"; } -# which wouldn't print anything if $message is the literal "0". -sub is_null_string ($) -{ - my $str = shift; - return ! (defined $str and length $str); -} - -sub stringify_result_obj ($) -{ - my $result_obj = shift; - if ($result_obj->is_unplanned || $result_obj->number != $testno) - { - return "ERROR"; - } - elsif ($plan_seen == LATE_PLAN) - { - return "ERROR"; - } - elsif (!$result_obj->directive) - { - return $result_obj->is_ok ? "PASS" : "FAIL"; - } - elsif ($result_obj->has_todo) - { - return $result_obj->is_actual_ok ? "XPASS" : "XFAIL"; - } - elsif ($result_obj->has_skip) - { - return $result_obj->is_ok ? "SKIP" : "FAIL"; - } - die "$ME: INTERNAL ERROR"; # NOTREACHED -} - -sub colored ($$) -{ - my ($color_string, $text) = @_; - return $color_string . $text . RESET; -} - -sub decorate_result ($) -{ - my $result = shift; - return $result unless $cfg{"color"}; - my %color_for_result = - ( - "ERROR" => BOLD.MAGENTA, - "PASS" => GREEN, - "XPASS" => BOLD.YELLOW, - "FAIL" => BOLD.RED, - "XFAIL" => YELLOW, - "SKIP" => BLUE, - ); - if (my $color = $color_for_result{$result}) - { - return colored ($color, $result); - } - else - { - return $result; # Don't colorize unknown stuff. - } -} - -sub report ($;$) -{ - my ($msg, $result, $explanation) = (undef, @_); - if ($result =~ /^(?:X?(?:PASS|FAIL)|SKIP|ERROR)/) - { - # Output on console might be colorized. - $msg = decorate_result($result); - if ($result =~ /^(?:PASS|XFAIL|SKIP)/) - { - return if $cfg{"show-failures-only"}; - } - else - { - $failed = 1; - } - } - elsif ($result eq "#") - { - $msg = " "; - } - else - { - die "$ME: INTERNAL ERROR"; # NOTREACHED - } - $msg .= " $explanation" if defined $explanation; - print $msg . "\n"; -} - -sub testsuite_error ($) -{ - report "ERROR", "$test_name - $_[0]"; -} - -sub handle_tap_result ($) -{ - $testno++; - my $result_obj = shift; - - my $test_result = stringify_result_obj $result_obj; - my $string = $result_obj->number; - - my $description = $result_obj->description; - $string .= " $test_name" unless is_null_string $test_name; - $string .= " $description" unless is_null_string $description; - - if ($plan_seen == LATE_PLAN) - { - $string .= " # AFTER LATE PLAN"; - } - elsif ($result_obj->is_unplanned) - { - $string .= " # UNPLANNED"; - } - elsif ($result_obj->number != $testno) - { - $string .= " # OUT-OF-ORDER (expecting $testno)"; - } - elsif (my $directive = $result_obj->directive) - { - $string .= " # $directive"; - my $explanation = $result_obj->explanation; - $string .= " $explanation" - unless is_null_string $explanation; - } - - report $test_result, $string; -} - -sub handle_tap_plan ($) -{ - my $plan = shift; - if ($plan_seen) - { - # Error, only one plan per stream is acceptable. - testsuite_error "multiple test plans"; - return; - } - # The TAP plan can come before or after *all* the TAP results; we speak - # respectively of an "early" or a "late" plan. If we see the plan line - # after at least one TAP result has been seen, assume we have a late - # plan; in this case, any further test result seen after the plan will - # be flagged as an error. - $plan_seen = ($testno >= 1 ? LATE_PLAN : EARLY_PLAN); - # If $testno > 0, we have an error ("too many tests run") that will be - # automatically dealt with later, so don't worry about it here. If - # $plan_seen is true, we have an error due to a repeated plan, and that - # has already been dealt with above. Otherwise, we have a valid "plan - # with SKIP" specification, and should report it as a particular kind - # of SKIP result. - if ($plan->directive && $testno == 0) - { - my $explanation = is_null_string ($plan->explanation) ? - undef : "- " . $plan->explanation; - report "SKIP", $explanation; - } -} - -sub handle_tap_bailout ($) -{ - my ($bailout, $msg) = ($_[0], "Bail out!"); - $bailed_out = 1; - $msg .= " " . $bailout->explanation - unless is_null_string $bailout->explanation; - testsuite_error $msg; -} - -sub extract_tap_comment ($) -{ - my $line = shift; - if (index ($line, DIAG_STRING) == 0) - { - # Strip leading `DIAG_STRING' from `$line'. - $line = substr ($line, length (DIAG_STRING)); - # And strip any leading and trailing whitespace left. - $line =~ s/(?:^\s*|\s*$)//g; - # Return what is left (if any). - return $line; - } - return ""; -} - -sub main () -{ - my $iterator = TAP::Parser::Iterator::Stream->new(\*STDIN); - my $parser = TAP::Parser->new ({iterator => $iterator }); - - STDOUT->autoflush(1); - while (defined (my $cur = $parser->next)) - { - # Parsing of TAP input should stop after a "Bail out!" directive. - next if $bailed_out; - - if ($cur->is_plan) - { - handle_tap_plan ($cur); - } - elsif ($cur->is_test) - { - handle_tap_result ($cur); - } - elsif ($cur->is_bailout) - { - handle_tap_bailout ($cur); - } - elsif ($cfg{"verbose"}) - { - my $comment = extract_tap_comment ($cur->raw); - report "#", "$comment" if length $comment; - } - } - # A "Bail out!" directive should cause us to ignore any following TAP - # error. - if (!$bailed_out) - { - if (!$plan_seen) - { - testsuite_error "missing test plan"; - } - elsif ($parser->tests_planned != $parser->tests_run) - { - my ($planned, $run) = ($parser->tests_planned, $parser->tests_run); - my $bad_amount = $run > $planned ? "many" : "few"; - testsuite_error (sprintf "too %s tests run (expected %d, got %d)", - $bad_amount, $planned, $run); - } - } -} - -# ----------- # -# Main code. # -# ----------- # - -main; -exit($failed); - -# Local Variables: -# perl-indent-level: 2 -# perl-continued-statement-offset: 2 -# perl-continued-brace-offset: 0 -# perl-brace-offset: 0 -# perl-brace-imaginary-offset: 0 -# perl-label-offset: -2 -# cperl-indent-level: 2 -# cperl-brace-offset: 0 -# cperl-continued-brace-offset: 0 -# cperl-label-offset: -2 -# cperl-extra-newline-before-brace: t -# cperl-merge-trailing-else: nil -# cperl-continued-statement-offset: 2 -# End: diff --git a/scripts/tap-merge.pl b/scripts/tap-merge.pl deleted file mode 100755 index 10ccf57bb2..0000000000 --- a/scripts/tap-merge.pl +++ /dev/null @@ -1,111 +0,0 @@ -#! /usr/bin/env perl -# Copyright (C) 2018 Red Hat, Inc. -# -# Author: Paolo Bonzini -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# ---------------------------------- # -# Imports, static data, and setup. # -# ---------------------------------- # - -use warnings FATAL => 'all'; -use strict; -use Getopt::Long (); -use TAP::Parser; - -my $ME = "tap-merge.pl"; -my $VERSION = "2018-11-30"; - -my $HELP = "$ME: merge multiple TAP inputs from stdin."; - -use constant DIAG_STRING => "#"; - -# ----------------- # -# Option parsing. # -# ----------------- # - -Getopt::Long::GetOptions - ( - 'help' => sub { print $HELP; exit 0; }, - 'version' => sub { print "$ME $VERSION\n"; exit 0; }, - ); - -# -------------- # -# Subroutines. # -# -------------- # - -sub main () -{ - my $iterator = TAP::Parser::Iterator::Stream->new(\*STDIN); - my $parser = TAP::Parser->new ({iterator => $iterator }); - my $testno = 0; # Number of test results seen so far. - my $bailed_out = 0; # Whether a "Bail out!" directive has been seen. - - STDOUT->autoflush(1); - while (defined (my $cur = $parser->next)) - { - if ($cur->is_bailout) - { - $bailed_out = 1; - print DIAG_STRING . " " . $cur->as_string . "\n"; - next; - } - elsif ($cur->is_plan) - { - $bailed_out = 0; - next; - } - elsif ($cur->is_test) - { - $bailed_out = 0 if $cur->number == 1; - $testno++; - $cur = TAP::Parser::Result::Test->new({ - ok => $cur->ok, - test_num => $testno, - directive => $cur->directive, - explanation => $cur->explanation, - description => $cur->description - }); - } - elsif ($cur->is_version) - { - next if $testno > 0; - } - print $cur->as_string . "\n" unless $bailed_out; - } - print "1..$testno\n"; -} - -# ----------- # -# Main code. # -# ----------- # - -main; - -# Local Variables: -# perl-indent-level: 2 -# perl-continued-statement-offset: 2 -# perl-continued-brace-offset: 0 -# perl-brace-offset: 0 -# perl-brace-imaginary-offset: 0 -# perl-label-offset: -2 -# cperl-indent-level: 2 -# cperl-brace-offset: 0 -# cperl-continued-brace-offset: 0 -# cperl-label-offset: -2 -# cperl-extra-newline-before-brace: t -# cperl-merge-trailing-else: nil -# cperl-continued-statement-offset: 2 -# End: diff --git a/tests/fp/meson.build b/tests/fp/meson.build index 07e2cdc8d2..59776a00a7 100644 --- a/tests/fp/meson.build +++ b/tests/fp/meson.build @@ -622,7 +622,7 @@ test('fp-test-mulAdd', fptest, # no fptest_rounding_args args: fptest_args + ['f16_mulAdd', 'f32_mulAdd', 'f64_mulAdd', 'f128_mulAdd'], - suite: ['softfloat-slow', 'softfloat-ops-slow'], timeout: 90) + suite: ['softfloat-slow', 'softfloat-ops-slow', 'slow'], timeout: 90) fpbench = executable( 'fp-bench', From 05bfd4db08608bc4c22de729780c1f74612fbc0e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 13 Dec 2021 09:38:38 -0800 Subject: [PATCH 087/730] target/hppa: Fix deposit assert from trans_shrpw_imm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because sa may be 0, tcg_gen_deposit_reg(dest, t0, cpu_gr[a->r1], 32 - sa, sa); may attempt a zero-width deposit at bit 32, which will assert for TARGET_REGISTER_BITS == 32. Use the newer extract2 when possible, which itself includes the rotri special case; otherwise mirror the code from trans_shrpw_sar, using concat and shri. Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/issues/635 Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/hppa/translate.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 3b9744deb4..952027a28e 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -140,6 +140,7 @@ #define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i64 #define tcg_gen_extract_reg tcg_gen_extract_i64 #define tcg_gen_sextract_reg tcg_gen_sextract_i64 +#define tcg_gen_extract2_reg tcg_gen_extract2_i64 #define tcg_const_reg tcg_const_i64 #define tcg_const_local_reg tcg_const_local_i64 #define tcg_constant_reg tcg_constant_i64 @@ -234,6 +235,7 @@ #define tcg_gen_deposit_z_reg tcg_gen_deposit_z_i32 #define tcg_gen_extract_reg tcg_gen_extract_i32 #define tcg_gen_sextract_reg tcg_gen_sextract_i32 +#define tcg_gen_extract2_reg tcg_gen_extract2_i32 #define tcg_const_reg tcg_const_i32 #define tcg_const_local_reg tcg_const_local_i32 #define tcg_constant_reg tcg_constant_i32 @@ -3204,19 +3206,22 @@ static bool trans_shrpw_imm(DisasContext *ctx, arg_shrpw_imm *a) dest = dest_gpr(ctx, a->t); t2 = load_gpr(ctx, a->r2); - if (a->r1 == a->r2) { + if (a->r1 == 0) { + tcg_gen_extract_reg(dest, t2, sa, 32 - sa); + } else if (TARGET_REGISTER_BITS == 32) { + tcg_gen_extract2_reg(dest, t2, cpu_gr[a->r1], sa); + } else if (a->r1 == a->r2) { TCGv_i32 t32 = tcg_temp_new_i32(); tcg_gen_trunc_reg_i32(t32, t2); tcg_gen_rotri_i32(t32, t32, sa); tcg_gen_extu_i32_reg(dest, t32); tcg_temp_free_i32(t32); - } else if (a->r1 == 0) { - tcg_gen_extract_reg(dest, t2, sa, 32 - sa); } else { - TCGv_reg t0 = tcg_temp_new(); - tcg_gen_extract_reg(t0, t2, sa, 32 - sa); - tcg_gen_deposit_reg(dest, t0, cpu_gr[a->r1], 32 - sa, sa); - tcg_temp_free(t0); + TCGv_i64 t64 = tcg_temp_new_i64(); + tcg_gen_concat_reg_i64(t64, t2, cpu_gr[a->r1]); + tcg_gen_shri_i64(t64, t64, sa); + tcg_gen_trunc_i64_reg(dest, t64); + tcg_temp_free_i64(t64); } save_gpr(ctx, a->t, dest); From 252f40913a87e1e89539a08b57e1740b3482906d Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 3 Nov 2021 12:21:55 -0400 Subject: [PATCH 088/730] job.c: add missing notifier initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems that on_idle list is not properly initialized like the other notifiers. Fixes: 34dc97b9a0e ("blockjob: Wake up BDS when job becomes idle") Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Stefan Hajnoczi Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Vladimir Sementsov-Ogievskiy --- job.c | 1 + 1 file changed, 1 insertion(+) diff --git a/job.c b/job.c index dbfa67bb0a..54db80df66 100644 --- a/job.c +++ b/job.c @@ -352,6 +352,7 @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn, notifier_list_init(&job->on_finalize_completed); notifier_list_init(&job->on_pending); notifier_list_init(&job->on_ready); + notifier_list_init(&job->on_idle); job_state_transition(job, JOB_STATUS_CREATED); aio_timer_init(qemu_get_aio_context(), &job->sleep_timer, From df9a31650505278e72c6b453f1679f66eac6e633 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Thu, 6 May 2021 17:13:53 +0300 Subject: [PATCH 089/730] blockjob: implement and use block_job_get_aio_context We are going to drop BlockJob.blk. So let's retrieve block job context from underlying job instead of main node. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Nikita Lapshin --- blockdev.c | 6 +++--- blockjob.c | 5 +++++ include/block/blockjob.h | 7 +++++++ qemu-img.c | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/blockdev.c b/blockdev.c index 0eb2823b1b..b5ff9b854e 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3315,7 +3315,7 @@ static BlockJob *find_block_job(const char *id, AioContext **aio_context, return NULL; } - *aio_context = blk_get_aio_context(job->blk); + *aio_context = block_job_get_aio_context(job); aio_context_acquire(*aio_context); return job; @@ -3420,7 +3420,7 @@ void qmp_block_job_finalize(const char *id, Error **errp) * automatically acquires the new one), so make sure we release the correct * one. */ - aio_context = blk_get_aio_context(job->blk); + aio_context = block_job_get_aio_context(job); job_unref(&job->job); aio_context_release(aio_context); } @@ -3711,7 +3711,7 @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp) if (block_job_is_internal(job)) { continue; } - aio_context = blk_get_aio_context(job->blk); + aio_context = block_job_get_aio_context(job); aio_context_acquire(aio_context); value = block_job_query(job, errp); aio_context_release(aio_context); diff --git a/blockjob.c b/blockjob.c index 4bad1408cb..70bc3105a6 100644 --- a/blockjob.c +++ b/blockjob.c @@ -547,3 +547,8 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err, } return action; } + +AioContext *block_job_get_aio_context(BlockJob *job) +{ + return job->job.aio_context; +} diff --git a/include/block/blockjob.h b/include/block/blockjob.h index d200f33c10..3b84805140 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -173,4 +173,11 @@ bool block_job_is_internal(BlockJob *job); */ const BlockJobDriver *block_job_driver(BlockJob *job); +/* + * block_job_get_aio_context: + * + * Returns aio context associated with a block job. + */ +AioContext *block_job_get_aio_context(BlockJob *job); + #endif diff --git a/qemu-img.c b/qemu-img.c index f036a1d428..21ba1e6800 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -902,7 +902,7 @@ static void common_block_job_cb(void *opaque, int ret) static void run_block_job(BlockJob *job, Error **errp) { uint64_t progress_current, progress_total; - AioContext *aio_context = blk_get_aio_context(job->blk); + AioContext *aio_context = block_job_get_aio_context(job); int ret = 0; aio_context_acquire(aio_context); From 7ac68e2920d32bd164862a6bb7931bfd167f4234 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Thu, 6 May 2021 17:13:54 +0300 Subject: [PATCH 090/730] test-blockjob-txn: don't abuse job->blk Here we use job->blk to drop our own reference in job cleanup. Let's do simpler: drop our reference immediately after job creation. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Nikita Lapshin --- tests/unit/test-blockjob-txn.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/tests/unit/test-blockjob-txn.c b/tests/unit/test-blockjob-txn.c index 8bd13b9949..c69028b450 100644 --- a/tests/unit/test-blockjob-txn.c +++ b/tests/unit/test-blockjob-txn.c @@ -25,14 +25,6 @@ typedef struct { int *result; } TestBlockJob; -static void test_block_job_clean(Job *job) -{ - BlockJob *bjob = container_of(job, BlockJob, job); - BlockDriverState *bs = blk_bs(bjob->blk); - - bdrv_unref(bs); -} - static int coroutine_fn test_block_job_run(Job *job, Error **errp) { TestBlockJob *s = container_of(job, TestBlockJob, common.job); @@ -73,7 +65,6 @@ static const BlockJobDriver test_block_job_driver = { .free = block_job_free, .user_resume = block_job_user_resume, .run = test_block_job_run, - .clean = test_block_job_clean, }, }; @@ -105,6 +96,7 @@ static BlockJob *test_block_job_start(unsigned int iterations, s = block_job_create(job_id, &test_block_job_driver, txn, bs, 0, BLK_PERM_ALL, 0, JOB_DEFAULT, test_block_job_cb, data, &error_abort); + bdrv_unref(bs); /* referenced by job now */ s->iterations = iterations; s->use_timer = use_timer; s->rc = rc; From 048954e2f6d4e88383186db2d223f3a42ddb61f7 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Thu, 6 May 2021 17:13:55 +0300 Subject: [PATCH 091/730] block/stream: add own blk block-stream is the only block-job, that reasonably use BlockJob.blk. We are going to drop BlockJob.blk soon. So, let block-stream have own blk. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Nikita Lapshin --- block/stream.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/block/stream.c b/block/stream.c index e45113aed6..7c6b173ddd 100644 --- a/block/stream.c +++ b/block/stream.c @@ -33,6 +33,7 @@ enum { typedef struct StreamBlockJob { BlockJob common; + BlockBackend *blk; BlockDriverState *base_overlay; /* COW overlay (stream from this) */ BlockDriverState *above_base; /* Node directly above the base */ BlockDriverState *cor_filter_bs; @@ -88,17 +89,18 @@ static int stream_prepare(Job *job) static void stream_clean(Job *job) { StreamBlockJob *s = container_of(job, StreamBlockJob, common.job); - BlockJob *bjob = &s->common; if (s->cor_filter_bs) { bdrv_cor_filter_drop(s->cor_filter_bs); s->cor_filter_bs = NULL; } + blk_unref(s->blk); + s->blk = NULL; + /* Reopen the image back in read-only mode if necessary */ if (s->bs_read_only) { /* Give up write permissions before making it read-only */ - blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort); bdrv_reopen_set_read_only(s->target_bs, true, NULL); } @@ -108,7 +110,6 @@ static void stream_clean(Job *job) static int coroutine_fn stream_run(Job *job, Error **errp) { StreamBlockJob *s = container_of(job, StreamBlockJob, common.job); - BlockBackend *blk = s->common.blk; BlockDriverState *unfiltered_bs = bdrv_skip_filters(s->target_bs); int64_t len; int64_t offset = 0; @@ -159,7 +160,7 @@ static int coroutine_fn stream_run(Job *job, Error **errp) } trace_stream_one_iteration(s, offset, n, ret); if (copy) { - ret = stream_populate(blk, offset, n); + ret = stream_populate(s->blk, offset, n); } if (ret < 0) { BlockErrorAction action = @@ -294,13 +295,24 @@ void stream_start(const char *job_id, BlockDriverState *bs, } s = block_job_create(job_id, &stream_job_driver, NULL, cor_filter_bs, - BLK_PERM_CONSISTENT_READ, - basic_flags | BLK_PERM_WRITE, + 0, BLK_PERM_ALL, speed, creation_flags, NULL, NULL, errp); if (!s) { goto fail; } + s->blk = blk_new_with_bs(cor_filter_bs, BLK_PERM_CONSISTENT_READ, + basic_flags | BLK_PERM_WRITE, errp); + if (!s->blk) { + goto fail; + } + /* + * Disable request queuing in the BlockBackend to avoid deadlocks on drain: + * The job reports that it's busy until it reaches a pause point. + */ + blk_set_disable_request_queuing(s->blk, true); + blk_set_allow_aio_context_change(s->blk, true); + /* * Prevent concurrent jobs trying to modify the graph structure here, we * already have our own plans. Also don't allow resize as the image size is From 1b177bbea0b8725e627eb18eb60b8866cd8e1df6 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Thu, 6 May 2021 17:13:56 +0300 Subject: [PATCH 092/730] test-bdrv-drain: don't use BlockJob.blk We are going to drop BlockJob.blk in further commit. For tests it's enough to simply pass bs pointer. Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Nikita Lapshin --- tests/unit/test-bdrv-drain.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c index 2d3c17e566..36be84ae55 100644 --- a/tests/unit/test-bdrv-drain.c +++ b/tests/unit/test-bdrv-drain.c @@ -772,6 +772,7 @@ static void test_iothread_drain_subtree(void) typedef struct TestBlockJob { BlockJob common; + BlockDriverState *bs; int run_ret; int prepare_ret; bool running; @@ -783,7 +784,7 @@ static int test_job_prepare(Job *job) TestBlockJob *s = container_of(job, TestBlockJob, common.job); /* Provoke an AIO_WAIT_WHILE() call to verify there is no deadlock */ - blk_flush(s->common.blk); + bdrv_flush(s->bs); return s->prepare_ret; } @@ -792,7 +793,7 @@ static void test_job_commit(Job *job) TestBlockJob *s = container_of(job, TestBlockJob, common.job); /* Provoke an AIO_WAIT_WHILE() call to verify there is no deadlock */ - blk_flush(s->common.blk); + bdrv_flush(s->bs); } static void test_job_abort(Job *job) @@ -800,7 +801,7 @@ static void test_job_abort(Job *job) TestBlockJob *s = container_of(job, TestBlockJob, common.job); /* Provoke an AIO_WAIT_WHILE() call to verify there is no deadlock */ - blk_flush(s->common.blk); + bdrv_flush(s->bs); } static int coroutine_fn test_job_run(Job *job, Error **errp) @@ -915,6 +916,7 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, tjob = block_job_create("job0", &test_job_driver, NULL, src, 0, BLK_PERM_ALL, 0, 0, NULL, NULL, &error_abort); + tjob->bs = src; job = &tjob->common; block_job_add_bdrv(job, "target", target, 0, BLK_PERM_ALL, &error_abort); @@ -1538,6 +1540,7 @@ typedef struct TestDropBackingBlockJob { bool should_complete; bool *did_complete; BlockDriverState *detach_also; + BlockDriverState *bs; } TestDropBackingBlockJob; static int coroutine_fn test_drop_backing_job_run(Job *job, Error **errp) @@ -1557,7 +1560,7 @@ static void test_drop_backing_job_commit(Job *job) TestDropBackingBlockJob *s = container_of(job, TestDropBackingBlockJob, common.job); - bdrv_set_backing_hd(blk_bs(s->common.blk), NULL, &error_abort); + bdrv_set_backing_hd(s->bs, NULL, &error_abort); bdrv_set_backing_hd(s->detach_also, NULL, &error_abort); *s->did_complete = true; @@ -1657,6 +1660,7 @@ static void test_blockjob_commit_by_drained_end(void) job = block_job_create("job", &test_drop_backing_job_driver, NULL, bs_parents[2], 0, BLK_PERM_ALL, 0, 0, NULL, NULL, &error_abort); + job->bs = bs_parents[2]; job->detach_also = bs_parents[0]; job->did_complete = &job_has_completed; From 985cac8f200443ad952becc03b07c51ff4f80983 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Thu, 6 May 2021 17:13:57 +0300 Subject: [PATCH 093/730] blockjob: drop BlockJob.blk field It's unused now (except for permission handling)[*]. The only reasonable user of it was block-stream job, recently updated to use own blk. And other block jobs prefer to use own source node related objects. So, the arguments of dropping the field are: - block jobs prefer not to use it - block jobs usually has more then one node to operate on, and better to operate symmetrically (for example has both source and target blk's in specific block-job state structure) *: BlockJob.blk is used to keep some permissions. We simply move permissions to block-job child created in block_job_create() together with blk. In mirror, we just should not care anymore about restoring state of blk. Most probably this code could be dropped long ago, after dropping bs->job pointer. Now it finally goes away together with BlockJob.blk itself. iotest 141 output is updated, as "bdrv_has_blk(bs)" check in qmp_blockdev_del() doesn't fail (we don't have blk now). Still, new error message looks even better. In iotest 283 we need to add a job id, otherwise "Invalid job ID" happens now earlier than permission check (as permissions moved from blk to block-job node). Signed-off-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Nikita Lapshin --- block/mirror.c | 7 ------- blockjob.c | 31 ++++++++++++------------------- include/block/blockjob.h | 3 --- tests/qemu-iotests/141.out | 2 +- tests/qemu-iotests/283 | 3 ++- tests/qemu-iotests/283.out | 2 +- 6 files changed, 16 insertions(+), 32 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index efec2c7674..959e3dfbd6 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -771,13 +771,6 @@ static int mirror_exit_common(Job *job) block_job_remove_all_bdrv(bjob); bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort); - /* We just changed the BDS the job BB refers to (with either or both of the - * bdrv_replace_node() calls), so switch the BB back so the cleanup does - * the right thing. We don't need any permissions any more now. */ - blk_remove_bs(bjob->blk); - blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort); - blk_insert_bs(bjob->blk, mirror_top_bs, &error_abort); - bs_opaque->job = NULL; bdrv_drained_end(src); diff --git a/blockjob.c b/blockjob.c index 70bc3105a6..10815a89fe 100644 --- a/blockjob.c +++ b/blockjob.c @@ -86,7 +86,6 @@ void block_job_free(Job *job) BlockJob *bjob = container_of(job, BlockJob, job); block_job_remove_all_bdrv(bjob); - blk_unref(bjob->blk); ratelimit_destroy(&bjob->limit); error_free(bjob->blocker); } @@ -433,22 +432,16 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, uint64_t shared_perm, int64_t speed, int flags, BlockCompletionFunc *cb, void *opaque, Error **errp) { - BlockBackend *blk; BlockJob *job; + int ret; if (job_id == NULL && !(flags & JOB_INTERNAL)) { job_id = bdrv_get_device_name(bs); } - blk = blk_new_with_bs(bs, perm, shared_perm, errp); - if (!blk) { - return NULL; - } - - job = job_create(job_id, &driver->job_driver, txn, blk_get_aio_context(blk), + job = job_create(job_id, &driver->job_driver, txn, bdrv_get_aio_context(bs), flags, cb, opaque, errp); if (job == NULL) { - blk_unref(blk); return NULL; } @@ -458,8 +451,6 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, ratelimit_init(&job->limit); - job->blk = blk; - job->finalize_cancelled_notifier.notify = block_job_event_cancelled; job->finalize_completed_notifier.notify = block_job_event_completed; job->pending_notifier.notify = block_job_event_pending; @@ -476,21 +467,23 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, error_setg(&job->blocker, "block device is in use by block job: %s", job_type_str(&job->job)); - block_job_add_bdrv(job, "main node", bs, 0, BLK_PERM_ALL, &error_abort); + + ret = block_job_add_bdrv(job, "main node", bs, perm, shared_perm, errp); + if (ret < 0) { + goto fail; + } bdrv_op_unblock(bs, BLOCK_OP_TYPE_DATAPLANE, job->blocker); - /* Disable request queuing in the BlockBackend to avoid deadlocks on drain: - * The job reports that it's busy until it reaches a pause point. */ - blk_set_disable_request_queuing(blk, true); - blk_set_allow_aio_context_change(blk, true); - if (!block_job_set_speed(job, speed, errp)) { - job_early_fail(&job->job); - return NULL; + goto fail; } return job; + +fail: + job_early_fail(&job->job); + return NULL; } void block_job_iostatus_reset(BlockJob *job) diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 3b84805140..87fbb3985f 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -43,9 +43,6 @@ typedef struct BlockJob { /** Data belonging to the generic Job infrastructure */ Job job; - /** The block device on which the job is operating. */ - BlockBackend *blk; - /** Status that is published by the query-block-jobs QMP API */ BlockDeviceIoStatus iostatus; diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out index c4c15fb275..63203d9944 100644 --- a/tests/qemu-iotests/141.out +++ b/tests/qemu-iotests/141.out @@ -132,7 +132,7 @@ wrote 1048576/1048576 bytes at offset 0 {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} {'execute': 'blockdev-del', 'arguments': {'node-name': 'drv0'}} -{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}} +{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}} {'execute': 'block-job-cancel', 'arguments': {'device': 'job0'}} {"return": {}} diff --git a/tests/qemu-iotests/283 b/tests/qemu-iotests/283 index a09e0183ae..5defe48e97 100755 --- a/tests/qemu-iotests/283 +++ b/tests/qemu-iotests/283 @@ -93,7 +93,8 @@ vm.qmp_log('blockdev-add', **{ 'take-child-perms': ['write'] }) -vm.qmp_log('blockdev-backup', sync='full', device='source', target='target') +vm.qmp_log('blockdev-backup', sync='full', device='source', target='target', + job_id="backup0") vm.shutdown() diff --git a/tests/qemu-iotests/283.out b/tests/qemu-iotests/283.out index 5bb75952ef..5e4f456db5 100644 --- a/tests/qemu-iotests/283.out +++ b/tests/qemu-iotests/283.out @@ -4,7 +4,7 @@ {"return": {}} {"execute": "blockdev-add", "arguments": {"driver": "blkdebug", "image": "base", "node-name": "other", "take-child-perms": ["write"]}} {"return": {}} -{"execute": "blockdev-backup", "arguments": {"device": "source", "sync": "full", "target": "target"}} +{"execute": "blockdev-backup", "arguments": {"device": "source", "job-id": "backup0", "sync": "full", "target": "target"}} {"error": {"class": "GenericError", "desc": "Permission conflict on node 'base': permissions 'write' are both required by node 'other' (uses node 'base' as 'image' child) and unshared by node 'source' (uses node 'base' as 'image' child)."}} === copy-before-write filter should be gone after job-finalize === From 41d5e8da3d5e0a143a9fb397c9f34707ec544997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Dec 2021 22:43:05 +0100 Subject: [PATCH 094/730] hw/scsi/megasas: Use uint32_t for reply queue head/tail values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While the reply queue values fit in 16-bit, they are accessed as 32-bit: 661: s->reply_queue_head = ldl_le_pci_dma(pcid, s->producer_pa); 662: s->reply_queue_head %= MEGASAS_MAX_FRAMES; 663: s->reply_queue_tail = ldl_le_pci_dma(pcid, s->consumer_pa); 664: s->reply_queue_tail %= MEGASAS_MAX_FRAMES; Having: 41:#define MEGASAS_MAX_FRAMES 2048 /* Firmware limit at 65535 */ In order to update the ld/st*_pci_dma() API to pass the address of the value to access, it is simpler to have the head/tail declared as 32-bit values. Replace the uint16_t by uint32_t, wasting 4 bytes in the MegasasState structure. Acked-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-20-philmd@redhat.com> --- hw/scsi/megasas.c | 4 ++-- hw/scsi/trace-events | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 8f35784100..14ec6d68bb 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -109,8 +109,8 @@ struct MegasasState { uint64_t reply_queue_pa; void *reply_queue; uint16_t reply_queue_len; - uint16_t reply_queue_head; - uint16_t reply_queue_tail; + uint32_t reply_queue_head; + uint32_t reply_queue_tail; uint64_t consumer_pa; uint64_t producer_pa; diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events index 92d5b40f89..ae8551f279 100644 --- a/hw/scsi/trace-events +++ b/hw/scsi/trace-events @@ -42,18 +42,18 @@ mptsas_config_sas_phy(void *dev, int address, int port, int phy_handle, int dev_ # megasas.c megasas_init_firmware(uint64_t pa) "pa 0x%" PRIx64 " " -megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tail, uint32_t flags) "queue at 0x%" PRIx64 " len %d head 0x%" PRIx64 " tail 0x%" PRIx64 " flags 0x%x" +megasas_init_queue(uint64_t queue_pa, int queue_len, uint32_t head, uint32_t tail, uint32_t flags) "queue at 0x%" PRIx64 " len %d head 0x%" PRIx32 " tail 0x%" PRIx32 " flags 0x%x" megasas_initq_map_failed(int frame) "scmd %d: failed to map queue" megasas_initq_mapped(uint64_t pa) "queue already mapped at 0x%" PRIx64 megasas_initq_mismatch(int queue_len, int fw_cmds) "queue size %d max fw cmds %d" megasas_qf_mapped(unsigned int index) "skip mapped frame 0x%x" megasas_qf_new(unsigned int index, uint64_t frame) "frame 0x%x addr 0x%" PRIx64 megasas_qf_busy(unsigned long pa) "all frames busy for frame 0x%lx" -megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, unsigned int head, unsigned int tail, int busy) "frame 0x%x count %d context 0x%" PRIx64 " head 0x%x tail 0x%x busy %d" -megasas_qf_update(unsigned int head, unsigned int tail, unsigned int busy) "head 0x%x tail 0x%x busy %d" +megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, uint32_t head, uint32_t tail, unsigned int busy) "frame 0x%x count %d context 0x%" PRIx64 " head 0x%" PRIx32 " tail 0x%" PRIx32 " busy %u" +megasas_qf_update(uint32_t head, uint32_t tail, unsigned int busy) "head 0x%" PRIx32 " tail 0x%" PRIx32 " busy %u" megasas_qf_map_failed(int cmd, unsigned long frame) "scmd %d: frame %lu" megasas_qf_complete_noirq(uint64_t context) "context 0x%" PRIx64 " " -megasas_qf_complete(uint64_t context, unsigned int head, unsigned int tail, int busy) "context 0x%" PRIx64 " head 0x%x tail 0x%x busy %d" +megasas_qf_complete(uint64_t context, uint32_t head, uint32_t tail, int busy) "context 0x%" PRIx64 " head 0x%" PRIx32 " tail 0x%" PRIx32 " busy %u" megasas_frame_busy(uint64_t addr) "frame 0x%" PRIx64 " busy" megasas_unhandled_frame_cmd(int cmd, uint8_t frame_cmd) "scmd %d: MFI cmd 0x%x" megasas_handle_scsi(const char *frame, int bus, int dev, int lun, void *sdev, unsigned long size) "%s dev %x/%x/%x sdev %p xfer %lu" From 7ccb391ccd594b3f33de8deb293ff8d47bb4e219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 3 Sep 2020 09:28:49 +0200 Subject: [PATCH 095/730] dma: Let dma_memory_valid() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling dma_memory_valid(). Reviewed-by: Richard Henderson Reviewed-by: Li Qiang Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Acked-by: Stefan Hajnoczi Message-Id: <20211223115554.3155328-2-philmd@redhat.com> --- include/hw/ppc/spapr_vio.h | 2 +- include/sysemu/dma.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h index 4bea87f39c..4c45f1579f 100644 --- a/include/hw/ppc/spapr_vio.h +++ b/include/hw/ppc/spapr_vio.h @@ -91,7 +91,7 @@ static inline void spapr_vio_irq_pulse(SpaprVioDevice *dev) static inline bool spapr_vio_dma_valid(SpaprVioDevice *dev, uint64_t taddr, uint32_t size, DMADirection dir) { - return dma_memory_valid(&dev->as, taddr, size, dir); + return dma_memory_valid(&dev->as, taddr, size, dir, MEMTXATTRS_UNSPECIFIED); } static inline int spapr_vio_dma_read(SpaprVioDevice *dev, uint64_t taddr, diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 3201e7901d..296f3b57c9 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -73,11 +73,11 @@ static inline void dma_barrier(AddressSpace *as, DMADirection dir) * dma_memory_{read,write}() and check for errors */ static inline bool dma_memory_valid(AddressSpace *as, dma_addr_t addr, dma_addr_t len, - DMADirection dir) + DMADirection dir, MemTxAttrs attrs) { return address_space_access_valid(as, addr, len, dir == DMA_DIRECTION_FROM_DEVICE, - MEMTXATTRS_UNSPECIFIED); + attrs); } static inline MemTxResult dma_memory_rw_relaxed(AddressSpace *as, From 7a36e42d9114474278ce30ba36945cc62292eb60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 3 Sep 2020 10:28:32 +0200 Subject: [PATCH 096/730] dma: Let dma_memory_set() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling dma_memory_set(). Reviewed-by: Richard Henderson Reviewed-by: Li Qiang Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Acked-by: Stefan Hajnoczi Message-Id: <20211223115554.3155328-3-philmd@redhat.com> --- hw/nvram/fw_cfg.c | 3 ++- include/hw/ppc/spapr_vio.h | 3 ++- include/sysemu/dma.h | 3 ++- softmmu/dma-helpers.c | 5 ++--- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index c06b30de11..f7803fe3c3 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -399,7 +399,8 @@ static void fw_cfg_dma_transfer(FWCfgState *s) * tested before. */ if (read) { - if (dma_memory_set(s->dma_as, dma.address, 0, len)) { + if (dma_memory_set(s->dma_as, dma.address, 0, len, + MEMTXATTRS_UNSPECIFIED)) { dma.control |= FW_CFG_DMA_CTL_ERROR; } } diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h index 4c45f1579f..c90e74a67d 100644 --- a/include/hw/ppc/spapr_vio.h +++ b/include/hw/ppc/spapr_vio.h @@ -111,7 +111,8 @@ static inline int spapr_vio_dma_write(SpaprVioDevice *dev, uint64_t taddr, static inline int spapr_vio_dma_set(SpaprVioDevice *dev, uint64_t taddr, uint8_t c, uint32_t size) { - return (dma_memory_set(&dev->as, taddr, c, size) != 0) ? + return (dma_memory_set(&dev->as, taddr, + c, size, MEMTXATTRS_UNSPECIFIED) != 0) ? H_DEST_PARM : H_SUCCESS; } diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 296f3b57c9..d23516f020 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -175,9 +175,10 @@ static inline MemTxResult dma_memory_write(AddressSpace *as, dma_addr_t addr, * @addr: address within that address space * @c: constant byte to fill the memory * @len: the number of bytes to fill with the constant byte + * @attrs: memory transaction attributes */ MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr, - uint8_t c, dma_addr_t len); + uint8_t c, dma_addr_t len, MemTxAttrs attrs); /** * address_space_map: Map a physical memory region into a host virtual address. diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 7d766a5e89..1f07217ad4 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -19,7 +19,7 @@ /* #define DEBUG_IOMMU */ MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr, - uint8_t c, dma_addr_t len) + uint8_t c, dma_addr_t len, MemTxAttrs attrs) { dma_barrier(as, DMA_DIRECTION_FROM_DEVICE); @@ -31,8 +31,7 @@ MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr, memset(fillbuf, c, FILLBUF_SIZE); while (len > 0) { l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE; - error |= address_space_write(as, addr, MEMTXATTRS_UNSPECIFIED, - fillbuf, l); + error |= address_space_write(as, addr, attrs, fillbuf, l); len -= l; addr += l; } From 4afd0f2f220ec3dc8518b8de0d66cbf8d2fd1be7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 3 Sep 2020 09:30:10 +0200 Subject: [PATCH 097/730] dma: Let dma_memory_rw_relaxed() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We will add the MemTxAttrs argument to dma_memory_rw() in the next commit. Since dma_memory_rw_relaxed() is only used by dma_memory_rw(), modify it first in a separate commit to keep the next commit easier to review. Reviewed-by: Richard Henderson Reviewed-by: Li Qiang Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Acked-by: Stefan Hajnoczi Message-Id: <20211223115554.3155328-4-philmd@redhat.com> --- include/sysemu/dma.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index d23516f020..3be803cf3f 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -83,9 +83,10 @@ static inline bool dma_memory_valid(AddressSpace *as, static inline MemTxResult dma_memory_rw_relaxed(AddressSpace *as, dma_addr_t addr, void *buf, dma_addr_t len, - DMADirection dir) + DMADirection dir, + MemTxAttrs attrs) { - return address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED, + return address_space_rw(as, addr, attrs, buf, len, dir == DMA_DIRECTION_FROM_DEVICE); } @@ -93,7 +94,9 @@ static inline MemTxResult dma_memory_read_relaxed(AddressSpace *as, dma_addr_t addr, void *buf, dma_addr_t len) { - return dma_memory_rw_relaxed(as, addr, buf, len, DMA_DIRECTION_TO_DEVICE); + return dma_memory_rw_relaxed(as, addr, buf, len, + DMA_DIRECTION_TO_DEVICE, + MEMTXATTRS_UNSPECIFIED); } static inline MemTxResult dma_memory_write_relaxed(AddressSpace *as, @@ -102,7 +105,8 @@ static inline MemTxResult dma_memory_write_relaxed(AddressSpace *as, dma_addr_t len) { return dma_memory_rw_relaxed(as, addr, (void *)buf, len, - DMA_DIRECTION_FROM_DEVICE); + DMA_DIRECTION_FROM_DEVICE, + MEMTXATTRS_UNSPECIFIED); } /** @@ -124,7 +128,8 @@ static inline MemTxResult dma_memory_rw(AddressSpace *as, dma_addr_t addr, { dma_barrier(as, dir); - return dma_memory_rw_relaxed(as, addr, buf, len, dir); + return dma_memory_rw_relaxed(as, addr, buf, len, dir, + MEMTXATTRS_UNSPECIFIED); } /** From 23faf5694ff8054b847e9733297727be4a641132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 3 Sep 2020 09:37:43 +0200 Subject: [PATCH 098/730] dma: Let dma_memory_rw() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling dma_memory_rw(). Reviewed-by: Richard Henderson Reviewed-by: Li Qiang Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Acked-by: Stefan Hajnoczi Message-Id: <20211223115554.3155328-5-philmd@redhat.com> --- hw/intc/spapr_xive.c | 3 ++- hw/usb/hcd-ohci.c | 10 ++++++---- include/hw/pci/pci.h | 3 ++- include/sysemu/dma.h | 11 ++++++----- softmmu/dma-helpers.c | 3 ++- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 4ec659b93e..eae95c716f 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -1684,7 +1684,8 @@ static target_ulong h_int_esb(PowerPCCPU *cpu, mmio_addr = xive->vc_base + xive_source_esb_mgmt(xsrc, lisn) + offset; if (dma_memory_rw(&address_space_memory, mmio_addr, &data, 8, - (flags & SPAPR_XIVE_ESB_STORE))) { + (flags & SPAPR_XIVE_ESB_STORE), + MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: failed to access ESB @0x%" HWADDR_PRIx "\n", mmio_addr); return H_HARDWARE; diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 1cf2816772..56e2315c73 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -586,7 +586,8 @@ static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td, if (n > len) n = len; - if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) { + if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, + n, dir, MEMTXATTRS_UNSPECIFIED)) { return -1; } if (n == len) { @@ -595,7 +596,7 @@ static int ohci_copy_td(OHCIState *ohci, struct ohci_td *td, ptr = td->be & ~0xfffu; buf += n; if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, - len - n, dir)) { + len - n, dir, MEMTXATTRS_UNSPECIFIED)) { return -1; } return 0; @@ -613,7 +614,8 @@ static int ohci_copy_iso_td(OHCIState *ohci, if (n > len) n = len; - if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, n, dir)) { + if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, + n, dir, MEMTXATTRS_UNSPECIFIED)) { return -1; } if (n == len) { @@ -622,7 +624,7 @@ static int ohci_copy_iso_td(OHCIState *ohci, ptr = end_addr & ~0xfffu; buf += n; if (dma_memory_rw(ohci->as, ptr + ohci->localmem_base, buf, - len - n, dir)) { + len - n, dir, MEMTXATTRS_UNSPECIFIED)) { return -1; } return 0; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index e7cdf2d5ec..4383f1c95e 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -808,7 +808,8 @@ static inline MemTxResult pci_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, DMADirection dir) { - return dma_memory_rw(pci_get_address_space(dev), addr, buf, len, dir); + return dma_memory_rw(pci_get_address_space(dev), addr, buf, len, + dir, MEMTXATTRS_UNSPECIFIED); } /** diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 3be803cf3f..e8ad42226f 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -121,15 +121,15 @@ static inline MemTxResult dma_memory_write_relaxed(AddressSpace *as, * @buf: buffer with the data transferred * @len: the number of bytes to read or write * @dir: indicates the transfer direction + * @attrs: memory transaction attributes */ static inline MemTxResult dma_memory_rw(AddressSpace *as, dma_addr_t addr, void *buf, dma_addr_t len, - DMADirection dir) + DMADirection dir, MemTxAttrs attrs) { dma_barrier(as, dir); - return dma_memory_rw_relaxed(as, addr, buf, len, dir, - MEMTXATTRS_UNSPECIFIED); + return dma_memory_rw_relaxed(as, addr, buf, len, dir, attrs); } /** @@ -147,7 +147,8 @@ static inline MemTxResult dma_memory_rw(AddressSpace *as, dma_addr_t addr, static inline MemTxResult dma_memory_read(AddressSpace *as, dma_addr_t addr, void *buf, dma_addr_t len) { - return dma_memory_rw(as, addr, buf, len, DMA_DIRECTION_TO_DEVICE); + return dma_memory_rw(as, addr, buf, len, + DMA_DIRECTION_TO_DEVICE, MEMTXATTRS_UNSPECIFIED); } /** @@ -166,7 +167,7 @@ static inline MemTxResult dma_memory_write(AddressSpace *as, dma_addr_t addr, const void *buf, dma_addr_t len) { return dma_memory_rw(as, addr, (void *)buf, len, - DMA_DIRECTION_FROM_DEVICE); + DMA_DIRECTION_FROM_DEVICE, MEMTXATTRS_UNSPECIFIED); } /** diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 1f07217ad4..5bf76fff6b 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -305,7 +305,8 @@ static uint64_t dma_buf_rw(uint8_t *ptr, int32_t len, QEMUSGList *sg, while (len > 0) { ScatterGatherEntry entry = sg->sg[sg_cur_index++]; int32_t xfer = MIN(len, entry.len); - dma_memory_rw(sg->as, entry.base, ptr, xfer, dir); + dma_memory_rw(sg->as, entry.base, ptr, xfer, dir, + MEMTXATTRS_UNSPECIFIED); ptr += xfer; len -= xfer; resid -= xfer; From ba06fe8add5b788956a7317246c6280dfc157040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 3 Sep 2020 10:08:29 +0200 Subject: [PATCH 099/730] dma: Let dma_memory_read/write() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling dma_memory_read() or dma_memory_write(). Patch created mechanically using spatch with this script: @@ expression E1, E2, E3, E4; @@ ( - dma_memory_read(E1, E2, E3, E4) + dma_memory_read(E1, E2, E3, E4, MEMTXATTRS_UNSPECIFIED) | - dma_memory_write(E1, E2, E3, E4) + dma_memory_write(E1, E2, E3, E4, MEMTXATTRS_UNSPECIFIED) ) Reviewed-by: Richard Henderson Reviewed-by: Li Qiang Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Acked-by: Stefan Hajnoczi Message-Id: <20211223115554.3155328-6-philmd@redhat.com> --- hw/arm/musicpal.c | 13 +++++++------ hw/arm/smmu-common.c | 3 ++- hw/arm/smmuv3.c | 14 +++++++++----- hw/core/generic-loader.c | 3 ++- hw/dma/pl330.c | 12 ++++++++---- hw/dma/sparc32_dma.c | 16 ++++++++++------ hw/dma/xlnx-zynq-devcfg.c | 6 ++++-- hw/dma/xlnx_dpdma.c | 10 ++++++---- hw/i386/amd_iommu.c | 16 +++++++++------- hw/i386/intel_iommu.c | 28 +++++++++++++++++----------- hw/ide/macio.c | 2 +- hw/intc/xive.c | 7 ++++--- hw/misc/bcm2835_property.c | 3 ++- hw/misc/macio/mac_dbdma.c | 10 ++++++---- hw/net/allwinner-sun8i-emac.c | 18 ++++++++++++------ hw/net/ftgmac100.c | 25 ++++++++++++++++--------- hw/net/imx_fec.c | 32 ++++++++++++++++++++------------ hw/net/npcm7xx_emc.c | 20 ++++++++++++-------- hw/nvram/fw_cfg.c | 9 ++++++--- hw/pci-host/pnv_phb3.c | 5 +++-- hw/pci-host/pnv_phb3_msi.c | 9 ++++++--- hw/pci-host/pnv_phb4.c | 5 +++-- hw/sd/allwinner-sdhost.c | 14 ++++++++------ hw/sd/sdhci.c | 35 ++++++++++++++++++++++------------- hw/usb/hcd-dwc2.c | 8 ++++---- hw/usb/hcd-ehci.c | 6 ++++-- hw/usb/hcd-ohci.c | 18 +++++++++++------- hw/usb/hcd-xhci.c | 18 +++++++++++------- include/hw/ppc/spapr_vio.h | 6 ++++-- include/sysemu/dma.h | 20 ++++++++++++-------- 30 files changed, 241 insertions(+), 150 deletions(-) diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index 2d612cc0c9..2680ec55b5 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -185,13 +185,13 @@ static void eth_rx_desc_put(AddressSpace *dma_as, uint32_t addr, cpu_to_le16s(&desc->buffer_size); cpu_to_le32s(&desc->buffer); cpu_to_le32s(&desc->next); - dma_memory_write(dma_as, addr, desc, sizeof(*desc)); + dma_memory_write(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); } static void eth_rx_desc_get(AddressSpace *dma_as, uint32_t addr, mv88w8618_rx_desc *desc) { - dma_memory_read(dma_as, addr, desc, sizeof(*desc)); + dma_memory_read(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); le32_to_cpus(&desc->cmdstat); le16_to_cpus(&desc->bytes); le16_to_cpus(&desc->buffer_size); @@ -215,7 +215,7 @@ static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size) eth_rx_desc_get(&s->dma_as, desc_addr, &desc); if ((desc.cmdstat & MP_ETH_RX_OWN) && desc.buffer_size >= size) { dma_memory_write(&s->dma_as, desc.buffer + s->vlan_header, - buf, size); + buf, size, MEMTXATTRS_UNSPECIFIED); desc.bytes = size + s->vlan_header; desc.cmdstat &= ~MP_ETH_RX_OWN; s->cur_rx[i] = desc.next; @@ -241,13 +241,13 @@ static void eth_tx_desc_put(AddressSpace *dma_as, uint32_t addr, cpu_to_le16s(&desc->bytes); cpu_to_le32s(&desc->buffer); cpu_to_le32s(&desc->next); - dma_memory_write(dma_as, addr, desc, sizeof(*desc)); + dma_memory_write(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); } static void eth_tx_desc_get(AddressSpace *dma_as, uint32_t addr, mv88w8618_tx_desc *desc) { - dma_memory_read(dma_as, addr, desc, sizeof(*desc)); + dma_memory_read(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); le32_to_cpus(&desc->cmdstat); le16_to_cpus(&desc->res); le16_to_cpus(&desc->bytes); @@ -269,7 +269,8 @@ static void eth_send(mv88w8618_eth_state *s, int queue_index) if (desc.cmdstat & MP_ETH_TX_OWN) { len = desc.bytes; if (len < 2048) { - dma_memory_read(&s->dma_as, desc.buffer, buf, len); + dma_memory_read(&s->dma_as, desc.buffer, buf, len, + MEMTXATTRS_UNSPECIFIED); qemu_send_packet(qemu_get_queue(s->nic), buf, len); } desc.cmdstat &= ~MP_ETH_TX_OWN; diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 0459850a93..e09b9c13b7 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -193,7 +193,8 @@ static int get_pte(dma_addr_t baseaddr, uint32_t index, uint64_t *pte, dma_addr_t addr = baseaddr + index * sizeof(*pte); /* TODO: guarantee 64-bit single-copy atomicity */ - ret = dma_memory_read(&address_space_memory, addr, pte, sizeof(*pte)); + ret = dma_memory_read(&address_space_memory, addr, pte, sizeof(*pte), + MEMTXATTRS_UNSPECIFIED); if (ret != MEMTX_OK) { info->type = SMMU_PTW_ERR_WALK_EABT; diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 01b60bee49..3b43368be0 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -102,7 +102,8 @@ static inline MemTxResult queue_read(SMMUQueue *q, void *data) { dma_addr_t addr = Q_CONS_ENTRY(q); - return dma_memory_read(&address_space_memory, addr, data, q->entry_size); + return dma_memory_read(&address_space_memory, addr, data, q->entry_size, + MEMTXATTRS_UNSPECIFIED); } static MemTxResult queue_write(SMMUQueue *q, void *data) @@ -110,7 +111,8 @@ static MemTxResult queue_write(SMMUQueue *q, void *data) dma_addr_t addr = Q_PROD_ENTRY(q); MemTxResult ret; - ret = dma_memory_write(&address_space_memory, addr, data, q->entry_size); + ret = dma_memory_write(&address_space_memory, addr, data, q->entry_size, + MEMTXATTRS_UNSPECIFIED); if (ret != MEMTX_OK) { return ret; } @@ -285,7 +287,8 @@ static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf, trace_smmuv3_get_ste(addr); /* TODO: guarantee 64-bit single-copy atomicity */ - ret = dma_memory_read(&address_space_memory, addr, buf, sizeof(*buf)); + ret = dma_memory_read(&address_space_memory, addr, buf, sizeof(*buf), + MEMTXATTRS_UNSPECIFIED); if (ret != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "Cannot fetch pte at address=0x%"PRIx64"\n", addr); @@ -306,7 +309,8 @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, uint32_t ssid, trace_smmuv3_get_cd(addr); /* TODO: guarantee 64-bit single-copy atomicity */ - ret = dma_memory_read(&address_space_memory, addr, buf, sizeof(*buf)); + ret = dma_memory_read(&address_space_memory, addr, buf, sizeof(*buf), + MEMTXATTRS_UNSPECIFIED); if (ret != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "Cannot fetch pte at address=0x%"PRIx64"\n", addr); @@ -411,7 +415,7 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, l1ptr = (dma_addr_t)(strtab_base + l1_ste_offset * sizeof(l1std)); /* TODO: guarantee 64-bit single-copy atomicity */ ret = dma_memory_read(&address_space_memory, l1ptr, &l1std, - sizeof(l1std)); + sizeof(l1std), MEMTXATTRS_UNSPECIFIED); if (ret != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "Could not read L1PTR at 0X%"PRIx64"\n", l1ptr); diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c index d14f932eea..9a24ffb880 100644 --- a/hw/core/generic-loader.c +++ b/hw/core/generic-loader.c @@ -57,7 +57,8 @@ static void generic_loader_reset(void *opaque) if (s->data_len) { assert(s->data_len < sizeof(s->data)); - dma_memory_write(s->cpu->as, s->addr, &s->data, s->data_len); + dma_memory_write(s->cpu->as, s->addr, &s->data, s->data_len, + MEMTXATTRS_UNSPECIFIED); } } diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c index 0cb46191c1..31ce01b7c5 100644 --- a/hw/dma/pl330.c +++ b/hw/dma/pl330.c @@ -1111,7 +1111,8 @@ static inline const PL330InsnDesc *pl330_fetch_insn(PL330Chan *ch) uint8_t opcode; int i; - dma_memory_read(ch->parent->mem_as, ch->pc, &opcode, 1); + dma_memory_read(ch->parent->mem_as, ch->pc, &opcode, 1, + MEMTXATTRS_UNSPECIFIED); for (i = 0; insn_desc[i].size; i++) { if ((opcode & insn_desc[i].opmask) == insn_desc[i].opcode) { return &insn_desc[i]; @@ -1125,7 +1126,8 @@ static inline void pl330_exec_insn(PL330Chan *ch, const PL330InsnDesc *insn) uint8_t buf[PL330_INSN_MAXSIZE]; assert(insn->size <= PL330_INSN_MAXSIZE); - dma_memory_read(ch->parent->mem_as, ch->pc, buf, insn->size); + dma_memory_read(ch->parent->mem_as, ch->pc, buf, insn->size, + MEMTXATTRS_UNSPECIFIED); insn->exec(ch, buf[0], &buf[1], insn->size - 1); } @@ -1189,7 +1191,8 @@ static int pl330_exec_cycle(PL330Chan *channel) if (q != NULL && q->len <= pl330_fifo_num_free(&s->fifo)) { int len = q->len - (q->addr & (q->len - 1)); - dma_memory_read(s->mem_as, q->addr, buf, len); + dma_memory_read(s->mem_as, q->addr, buf, len, + MEMTXATTRS_UNSPECIFIED); trace_pl330_exec_cycle(q->addr, len); if (trace_event_get_state_backends(TRACE_PL330_HEXDUMP)) { pl330_hexdump(buf, len); @@ -1220,7 +1223,8 @@ static int pl330_exec_cycle(PL330Chan *channel) fifo_res = pl330_fifo_get(&s->fifo, buf, len, q->tag); } if (fifo_res == PL330_FIFO_OK || q->z) { - dma_memory_write(s->mem_as, q->addr, buf, len); + dma_memory_write(s->mem_as, q->addr, buf, len, + MEMTXATTRS_UNSPECIFIED); trace_pl330_exec_cycle(q->addr, len); if (trace_event_get_state_backends(TRACE_PL330_HEXDUMP)) { pl330_hexdump(buf, len); diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index 03bc500878..0ef13c5e9a 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -81,11 +81,11 @@ void ledma_memory_read(void *opaque, hwaddr addr, addr |= s->dmaregs[3]; trace_ledma_memory_read(addr, len); if (do_bswap) { - dma_memory_read(&is->iommu_as, addr, buf, len); + dma_memory_read(&is->iommu_as, addr, buf, len, MEMTXATTRS_UNSPECIFIED); } else { addr &= ~1; len &= ~1; - dma_memory_read(&is->iommu_as, addr, buf, len); + dma_memory_read(&is->iommu_as, addr, buf, len, MEMTXATTRS_UNSPECIFIED); for(i = 0; i < len; i += 2) { bswap16s((uint16_t *)(buf + i)); } @@ -103,7 +103,8 @@ void ledma_memory_write(void *opaque, hwaddr addr, addr |= s->dmaregs[3]; trace_ledma_memory_write(addr, len); if (do_bswap) { - dma_memory_write(&is->iommu_as, addr, buf, len); + dma_memory_write(&is->iommu_as, addr, buf, len, + MEMTXATTRS_UNSPECIFIED); } else { addr &= ~1; len &= ~1; @@ -114,7 +115,8 @@ void ledma_memory_write(void *opaque, hwaddr addr, for(i = 0; i < l; i += 2) { tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i)); } - dma_memory_write(&is->iommu_as, addr, tmp_buf, l); + dma_memory_write(&is->iommu_as, addr, tmp_buf, l, + MEMTXATTRS_UNSPECIFIED); len -= l; buf += l; addr += l; @@ -148,7 +150,8 @@ void espdma_memory_read(void *opaque, uint8_t *buf, int len) IOMMUState *is = (IOMMUState *)s->iommu; trace_espdma_memory_read(s->dmaregs[1], len); - dma_memory_read(&is->iommu_as, s->dmaregs[1], buf, len); + dma_memory_read(&is->iommu_as, s->dmaregs[1], buf, len, + MEMTXATTRS_UNSPECIFIED); s->dmaregs[1] += len; } @@ -158,7 +161,8 @@ void espdma_memory_write(void *opaque, uint8_t *buf, int len) IOMMUState *is = (IOMMUState *)s->iommu; trace_espdma_memory_write(s->dmaregs[1], len); - dma_memory_write(&is->iommu_as, s->dmaregs[1], buf, len); + dma_memory_write(&is->iommu_as, s->dmaregs[1], buf, len, + MEMTXATTRS_UNSPECIFIED); s->dmaregs[1] += len; } diff --git a/hw/dma/xlnx-zynq-devcfg.c b/hw/dma/xlnx-zynq-devcfg.c index e33112b6f0..f5ad1a0d22 100644 --- a/hw/dma/xlnx-zynq-devcfg.c +++ b/hw/dma/xlnx-zynq-devcfg.c @@ -161,12 +161,14 @@ static void xlnx_zynq_devcfg_dma_go(XlnxZynqDevcfg *s) btt = MIN(btt, dmah->dest_len); } DB_PRINT("reading %x bytes from %x\n", btt, dmah->src_addr); - dma_memory_read(&address_space_memory, dmah->src_addr, buf, btt); + dma_memory_read(&address_space_memory, dmah->src_addr, buf, btt, + MEMTXATTRS_UNSPECIFIED); dmah->src_len -= btt; dmah->src_addr += btt; if (loopback && (dmah->src_len || dmah->dest_len)) { DB_PRINT("writing %x bytes from %x\n", btt, dmah->dest_addr); - dma_memory_write(&address_space_memory, dmah->dest_addr, buf, btt); + dma_memory_write(&address_space_memory, dmah->dest_addr, buf, btt, + MEMTXATTRS_UNSPECIFIED); dmah->dest_len -= btt; dmah->dest_addr += btt; } diff --git a/hw/dma/xlnx_dpdma.c b/hw/dma/xlnx_dpdma.c index 967548abd3..2d7eae72cd 100644 --- a/hw/dma/xlnx_dpdma.c +++ b/hw/dma/xlnx_dpdma.c @@ -652,7 +652,7 @@ size_t xlnx_dpdma_start_operation(XlnxDPDMAState *s, uint8_t channel, } if (dma_memory_read(&address_space_memory, desc_addr, &desc, - sizeof(DPDMADescriptor))) { + sizeof(DPDMADescriptor), MEMTXATTRS_UNSPECIFIED)) { s->registers[DPDMA_EISR] |= ((1 << 1) << channel); xlnx_dpdma_update_irq(s); s->operation_finished[channel] = true; @@ -708,7 +708,8 @@ size_t xlnx_dpdma_start_operation(XlnxDPDMAState *s, uint8_t channel, if (dma_memory_read(&address_space_memory, source_addr[0], &s->data[channel][ptr], - line_size)) { + line_size, + MEMTXATTRS_UNSPECIFIED)) { s->registers[DPDMA_ISR] |= ((1 << 12) << channel); xlnx_dpdma_update_irq(s); DPRINTF("Can't get data.\n"); @@ -736,7 +737,8 @@ size_t xlnx_dpdma_start_operation(XlnxDPDMAState *s, uint8_t channel, if (dma_memory_read(&address_space_memory, source_addr[frag], &(s->data[channel][ptr]), - fragment_len)) { + fragment_len, + MEMTXATTRS_UNSPECIFIED)) { s->registers[DPDMA_ISR] |= ((1 << 12) << channel); xlnx_dpdma_update_irq(s); DPRINTF("Can't get data.\n"); @@ -754,7 +756,7 @@ size_t xlnx_dpdma_start_operation(XlnxDPDMAState *s, uint8_t channel, DPRINTF("update the descriptor with the done flag set.\n"); xlnx_dpdma_desc_set_done(&desc); dma_memory_write(&address_space_memory, desc_addr, &desc, - sizeof(DPDMADescriptor)); + sizeof(DPDMADescriptor), MEMTXATTRS_UNSPECIFIED); } if (xlnx_dpdma_desc_completion_interrupt(&desc)) { diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index 91fe34ae58..4d13d8e697 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -181,7 +181,7 @@ static void amdvi_log_event(AMDVIState *s, uint64_t *evt) } if (dma_memory_write(&address_space_memory, s->evtlog + s->evtlog_tail, - evt, AMDVI_EVENT_LEN)) { + evt, AMDVI_EVENT_LEN, MEMTXATTRS_UNSPECIFIED)) { trace_amdvi_evntlog_fail(s->evtlog, s->evtlog_tail); } @@ -376,7 +376,8 @@ static void amdvi_completion_wait(AMDVIState *s, uint64_t *cmd) } if (extract64(cmd[0], 0, 1)) { if (dma_memory_write(&address_space_memory, addr, &data, - AMDVI_COMPLETION_DATA_SIZE)) { + AMDVI_COMPLETION_DATA_SIZE, + MEMTXATTRS_UNSPECIFIED)) { trace_amdvi_completion_wait_fail(addr); } } @@ -502,7 +503,7 @@ static void amdvi_cmdbuf_exec(AMDVIState *s) uint64_t cmd[2]; if (dma_memory_read(&address_space_memory, s->cmdbuf + s->cmdbuf_head, - cmd, AMDVI_COMMAND_SIZE)) { + cmd, AMDVI_COMMAND_SIZE, MEMTXATTRS_UNSPECIFIED)) { trace_amdvi_command_read_fail(s->cmdbuf, s->cmdbuf_head); amdvi_log_command_error(s, s->cmdbuf + s->cmdbuf_head); return; @@ -836,7 +837,7 @@ static bool amdvi_get_dte(AMDVIState *s, int devid, uint64_t *entry) uint32_t offset = devid * AMDVI_DEVTAB_ENTRY_SIZE; if (dma_memory_read(&address_space_memory, s->devtab + offset, entry, - AMDVI_DEVTAB_ENTRY_SIZE)) { + AMDVI_DEVTAB_ENTRY_SIZE, MEMTXATTRS_UNSPECIFIED)) { trace_amdvi_dte_get_fail(s->devtab, offset); /* log error accessing dte */ amdvi_log_devtab_error(s, devid, s->devtab + offset, 0); @@ -881,7 +882,8 @@ static inline uint64_t amdvi_get_pte_entry(AMDVIState *s, uint64_t pte_addr, { uint64_t pte; - if (dma_memory_read(&address_space_memory, pte_addr, &pte, sizeof(pte))) { + if (dma_memory_read(&address_space_memory, pte_addr, + &pte, sizeof(pte), MEMTXATTRS_UNSPECIFIED)) { trace_amdvi_get_pte_hwerror(pte_addr); amdvi_log_pagetab_error(s, devid, pte_addr, 0); pte = 0; @@ -1048,7 +1050,7 @@ static int amdvi_get_irte(AMDVIState *s, MSIMessage *origin, uint64_t *dte, trace_amdvi_ir_irte(irte_root, offset); if (dma_memory_read(&address_space_memory, irte_root + offset, - irte, sizeof(*irte))) { + irte, sizeof(*irte), MEMTXATTRS_UNSPECIFIED)) { trace_amdvi_ir_err("failed to get irte"); return -AMDVI_IR_GET_IRTE; } @@ -1108,7 +1110,7 @@ static int amdvi_get_irte_ga(AMDVIState *s, MSIMessage *origin, uint64_t *dte, trace_amdvi_ir_irte(irte_root, offset); if (dma_memory_read(&address_space_memory, irte_root + offset, - irte, sizeof(*irte))) { + irte, sizeof(*irte), MEMTXATTRS_UNSPECIFIED)) { trace_amdvi_ir_err("failed to get irte_ga"); return -AMDVI_IR_GET_IRTE; } diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index f584449d8d..5b865ac08c 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -569,7 +569,8 @@ static int vtd_get_root_entry(IntelIOMMUState *s, uint8_t index, dma_addr_t addr; addr = s->root + index * sizeof(*re); - if (dma_memory_read(&address_space_memory, addr, re, sizeof(*re))) { + if (dma_memory_read(&address_space_memory, addr, + re, sizeof(*re), MEMTXATTRS_UNSPECIFIED)) { re->lo = 0; return -VTD_FR_ROOT_TABLE_INV; } @@ -602,7 +603,8 @@ static int vtd_get_context_entry_from_root(IntelIOMMUState *s, } addr = addr + index * ce_size; - if (dma_memory_read(&address_space_memory, addr, ce, ce_size)) { + if (dma_memory_read(&address_space_memory, addr, + ce, ce_size, MEMTXATTRS_UNSPECIFIED)) { return -VTD_FR_CONTEXT_TABLE_INV; } @@ -639,8 +641,8 @@ static uint64_t vtd_get_slpte(dma_addr_t base_addr, uint32_t index) assert(index < VTD_SL_PT_ENTRY_NR); if (dma_memory_read(&address_space_memory, - base_addr + index * sizeof(slpte), &slpte, - sizeof(slpte))) { + base_addr + index * sizeof(slpte), + &slpte, sizeof(slpte), MEMTXATTRS_UNSPECIFIED)) { slpte = (uint64_t)-1; return slpte; } @@ -704,7 +706,8 @@ static int vtd_get_pdire_from_pdir_table(dma_addr_t pasid_dir_base, index = VTD_PASID_DIR_INDEX(pasid); entry_size = VTD_PASID_DIR_ENTRY_SIZE; addr = pasid_dir_base + index * entry_size; - if (dma_memory_read(&address_space_memory, addr, pdire, entry_size)) { + if (dma_memory_read(&address_space_memory, addr, + pdire, entry_size, MEMTXATTRS_UNSPECIFIED)) { return -VTD_FR_PASID_TABLE_INV; } @@ -728,7 +731,8 @@ static int vtd_get_pe_in_pasid_leaf_table(IntelIOMMUState *s, index = VTD_PASID_TABLE_INDEX(pasid); entry_size = VTD_PASID_ENTRY_SIZE; addr = addr + index * entry_size; - if (dma_memory_read(&address_space_memory, addr, pe, entry_size)) { + if (dma_memory_read(&address_space_memory, addr, + pe, entry_size, MEMTXATTRS_UNSPECIFIED)) { return -VTD_FR_PASID_TABLE_INV; } @@ -2275,7 +2279,8 @@ static bool vtd_get_inv_desc(IntelIOMMUState *s, uint32_t dw = s->iq_dw ? 32 : 16; dma_addr_t addr = base_addr + offset * dw; - if (dma_memory_read(&address_space_memory, addr, inv_desc, dw)) { + if (dma_memory_read(&address_space_memory, addr, + inv_desc, dw, MEMTXATTRS_UNSPECIFIED)) { error_report_once("Read INV DESC failed."); return false; } @@ -2308,8 +2313,9 @@ static bool vtd_process_wait_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc) dma_addr_t status_addr = inv_desc->hi; trace_vtd_inv_desc_wait_sw(status_addr, status_data); status_data = cpu_to_le32(status_data); - if (dma_memory_write(&address_space_memory, status_addr, &status_data, - sizeof(status_data))) { + if (dma_memory_write(&address_space_memory, status_addr, + &status_data, sizeof(status_data), + MEMTXATTRS_UNSPECIFIED)) { trace_vtd_inv_desc_wait_write_fail(inv_desc->hi, inv_desc->lo); return false; } @@ -3120,8 +3126,8 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index, } addr = iommu->intr_root + index * sizeof(*entry); - if (dma_memory_read(&address_space_memory, addr, entry, - sizeof(*entry))) { + if (dma_memory_read(&address_space_memory, addr, + entry, sizeof(*entry), MEMTXATTRS_UNSPECIFIED)) { error_report_once("%s: read failed: ind=0x%x addr=0x%" PRIx64, __func__, index, addr); return -VTD_FR_IR_ROOT_INVAL; diff --git a/hw/ide/macio.c b/hw/ide/macio.c index b03d401ceb..f08318cf97 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -97,7 +97,7 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) /* Non-block ATAPI transfer - just copy to RAM */ s->io_buffer_size = MIN(s->io_buffer_size, io->len); dma_memory_write(&address_space_memory, io->addr, s->io_buffer, - s->io_buffer_size); + s->io_buffer_size, MEMTXATTRS_UNSPECIFIED); io->len = 0; ide_atapi_cmd_ok(s); m->dma_active = false; diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 190194d27f..f15f98588a 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -1246,8 +1246,8 @@ void xive_end_queue_pic_print_info(XiveEND *end, uint32_t width, Monitor *mon) uint64_t qaddr = qaddr_base + (qindex << 2); uint32_t qdata = -1; - if (dma_memory_read(&address_space_memory, qaddr, &qdata, - sizeof(qdata))) { + if (dma_memory_read(&address_space_memory, qaddr, + &qdata, sizeof(qdata), MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: failed to read EQ @0x%" HWADDR_PRIx "\n", qaddr); return; @@ -1311,7 +1311,8 @@ static void xive_end_enqueue(XiveEND *end, uint32_t data) uint32_t qdata = cpu_to_be32((qgen << 31) | (data & 0x7fffffff)); uint32_t qentries = 1 << (qsize + 10); - if (dma_memory_write(&address_space_memory, qaddr, &qdata, sizeof(qdata))) { + if (dma_memory_write(&address_space_memory, qaddr, + &qdata, sizeof(qdata), MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "XIVE: failed to write END data @0x%" HWADDR_PRIx "\n", qaddr); return; diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c index 73941bdae9..76ea511d53 100644 --- a/hw/misc/bcm2835_property.c +++ b/hw/misc/bcm2835_property.c @@ -69,7 +69,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) break; case 0x00010003: /* Get board MAC address */ resplen = sizeof(s->macaddr.a); - dma_memory_write(&s->dma_as, value + 12, s->macaddr.a, resplen); + dma_memory_write(&s->dma_as, value + 12, s->macaddr.a, resplen, + MEMTXATTRS_UNSPECIFIED); break; case 0x00010004: /* Get board serial */ qemu_log_mask(LOG_UNIMP, diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c index e220f1a927..efcc02609f 100644 --- a/hw/misc/macio/mac_dbdma.c +++ b/hw/misc/macio/mac_dbdma.c @@ -94,7 +94,7 @@ static void dbdma_cmdptr_load(DBDMA_channel *ch) DBDMA_DPRINTFCH(ch, "dbdma_cmdptr_load 0x%08x\n", ch->regs[DBDMA_CMDPTR_LO]); dma_memory_read(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO], - &ch->current, sizeof(dbdma_cmd)); + &ch->current, sizeof(dbdma_cmd), MEMTXATTRS_UNSPECIFIED); } static void dbdma_cmdptr_save(DBDMA_channel *ch) @@ -104,7 +104,7 @@ static void dbdma_cmdptr_save(DBDMA_channel *ch) le16_to_cpu(ch->current.xfer_status), le16_to_cpu(ch->current.res_count)); dma_memory_write(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO], - &ch->current, sizeof(dbdma_cmd)); + &ch->current, sizeof(dbdma_cmd), MEMTXATTRS_UNSPECIFIED); } static void kill_channel(DBDMA_channel *ch) @@ -371,7 +371,8 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr, return; } - dma_memory_read(&address_space_memory, addr, ¤t->cmd_dep, len); + dma_memory_read(&address_space_memory, addr, ¤t->cmd_dep, len, + MEMTXATTRS_UNSPECIFIED); if (conditional_wait(ch)) goto wait; @@ -403,7 +404,8 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr, return; } - dma_memory_write(&address_space_memory, addr, ¤t->cmd_dep, len); + dma_memory_write(&address_space_memory, addr, ¤t->cmd_dep, len, + MEMTXATTRS_UNSPECIFIED); if (conditional_wait(ch)) goto wait; diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c index ff611f18fb..ecc0245fe8 100644 --- a/hw/net/allwinner-sun8i-emac.c +++ b/hw/net/allwinner-sun8i-emac.c @@ -350,7 +350,8 @@ static void allwinner_sun8i_emac_get_desc(AwSun8iEmacState *s, FrameDescriptor *desc, uint32_t phys_addr) { - dma_memory_read(&s->dma_as, phys_addr, desc, sizeof(*desc)); + dma_memory_read(&s->dma_as, phys_addr, desc, sizeof(*desc), + MEMTXATTRS_UNSPECIFIED); } static uint32_t allwinner_sun8i_emac_next_desc(AwSun8iEmacState *s, @@ -402,7 +403,8 @@ static void allwinner_sun8i_emac_flush_desc(AwSun8iEmacState *s, FrameDescriptor *desc, uint32_t phys_addr) { - dma_memory_write(&s->dma_as, phys_addr, desc, sizeof(*desc)); + dma_memory_write(&s->dma_as, phys_addr, desc, sizeof(*desc), + MEMTXATTRS_UNSPECIFIED); } static bool allwinner_sun8i_emac_can_receive(NetClientState *nc) @@ -460,7 +462,8 @@ static ssize_t allwinner_sun8i_emac_receive(NetClientState *nc, << RX_DESC_STATUS_FRM_LEN_SHIFT; } - dma_memory_write(&s->dma_as, desc.addr, buf, desc_bytes); + dma_memory_write(&s->dma_as, desc.addr, buf, desc_bytes, + MEMTXATTRS_UNSPECIFIED); allwinner_sun8i_emac_flush_desc(s, &desc, s->rx_desc_curr); trace_allwinner_sun8i_emac_receive(s->rx_desc_curr, desc.addr, desc_bytes); @@ -512,7 +515,8 @@ static void allwinner_sun8i_emac_transmit(AwSun8iEmacState *s) desc.status |= TX_DESC_STATUS_LENGTH_ERR; break; } - dma_memory_read(&s->dma_as, desc.addr, packet_buf + packet_bytes, bytes); + dma_memory_read(&s->dma_as, desc.addr, packet_buf + packet_bytes, + bytes, MEMTXATTRS_UNSPECIFIED); packet_bytes += bytes; desc.status &= ~DESC_STATUS_CTL; allwinner_sun8i_emac_flush_desc(s, &desc, s->tx_desc_curr); @@ -634,7 +638,8 @@ static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset, break; case REG_TX_CUR_BUF: /* Transmit Current Buffer */ if (s->tx_desc_curr != 0) { - dma_memory_read(&s->dma_as, s->tx_desc_curr, &desc, sizeof(desc)); + dma_memory_read(&s->dma_as, s->tx_desc_curr, &desc, sizeof(desc), + MEMTXATTRS_UNSPECIFIED); value = desc.addr; } else { value = 0; @@ -647,7 +652,8 @@ static uint64_t allwinner_sun8i_emac_read(void *opaque, hwaddr offset, break; case REG_RX_CUR_BUF: /* Receive Current Buffer */ if (s->rx_desc_curr != 0) { - dma_memory_read(&s->dma_as, s->rx_desc_curr, &desc, sizeof(desc)); + dma_memory_read(&s->dma_as, s->rx_desc_curr, &desc, sizeof(desc), + MEMTXATTRS_UNSPECIFIED); value = desc.addr; } else { value = 0; diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c index 25685ba3a9..83ef0a783e 100644 --- a/hw/net/ftgmac100.c +++ b/hw/net/ftgmac100.c @@ -453,7 +453,8 @@ static void do_phy_ctl(FTGMAC100State *s) static int ftgmac100_read_bd(FTGMAC100Desc *bd, dma_addr_t addr) { - if (dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd))) { + if (dma_memory_read(&address_space_memory, addr, + bd, sizeof(*bd), MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to read descriptor @ 0x%" HWADDR_PRIx "\n", __func__, addr); return -1; @@ -473,7 +474,8 @@ static int ftgmac100_write_bd(FTGMAC100Desc *bd, dma_addr_t addr) lebd.des1 = cpu_to_le32(bd->des1); lebd.des2 = cpu_to_le32(bd->des2); lebd.des3 = cpu_to_le32(bd->des3); - if (dma_memory_write(&address_space_memory, addr, &lebd, sizeof(lebd))) { + if (dma_memory_write(&address_space_memory, addr, + &lebd, sizeof(lebd), MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to write descriptor @ 0x%" HWADDR_PRIx "\n", __func__, addr); return -1; @@ -554,7 +556,8 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, len = sizeof(s->frame) - frame_size; } - if (dma_memory_read(&address_space_memory, bd.des3, ptr, len)) { + if (dma_memory_read(&address_space_memory, bd.des3, + ptr, len, MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to read packet @ 0x%x\n", __func__, bd.des3); s->isr |= FTGMAC100_INT_AHB_ERR; @@ -1030,20 +1033,24 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, bd.des1 = lduw_be_p(buf + 14) | FTGMAC100_RXDES1_VLANTAG_AVAIL; if (s->maccr & FTGMAC100_MACCR_RM_VLAN) { - dma_memory_write(&address_space_memory, buf_addr, buf, 12); - dma_memory_write(&address_space_memory, buf_addr + 12, buf + 16, - buf_len - 16); + dma_memory_write(&address_space_memory, buf_addr, buf, 12, + MEMTXATTRS_UNSPECIFIED); + dma_memory_write(&address_space_memory, buf_addr + 12, + buf + 16, buf_len - 16, + MEMTXATTRS_UNSPECIFIED); } else { - dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); + dma_memory_write(&address_space_memory, buf_addr, buf, + buf_len, MEMTXATTRS_UNSPECIFIED); } } else { bd.des1 = 0; - dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); + dma_memory_write(&address_space_memory, buf_addr, buf, buf_len, + MEMTXATTRS_UNSPECIFIED); } buf += buf_len; if (size < 4) { dma_memory_write(&address_space_memory, buf_addr + buf_len, - crc_ptr, 4 - size); + crc_ptr, 4 - size, MEMTXATTRS_UNSPECIFIED); crc_ptr += 4 - size; } diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c index 9c7035bc94..0db9aaf76a 100644 --- a/hw/net/imx_fec.c +++ b/hw/net/imx_fec.c @@ -387,19 +387,22 @@ static void imx_phy_write(IMXFECState *s, int reg, uint32_t val) static void imx_fec_read_bd(IMXFECBufDesc *bd, dma_addr_t addr) { - dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd)); + dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd), + MEMTXATTRS_UNSPECIFIED); trace_imx_fec_read_bd(addr, bd->flags, bd->length, bd->data); } static void imx_fec_write_bd(IMXFECBufDesc *bd, dma_addr_t addr) { - dma_memory_write(&address_space_memory, addr, bd, sizeof(*bd)); + dma_memory_write(&address_space_memory, addr, bd, sizeof(*bd), + MEMTXATTRS_UNSPECIFIED); } static void imx_enet_read_bd(IMXENETBufDesc *bd, dma_addr_t addr) { - dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd)); + dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd), + MEMTXATTRS_UNSPECIFIED); trace_imx_enet_read_bd(addr, bd->flags, bd->length, bd->data, bd->option, bd->status); @@ -407,7 +410,8 @@ static void imx_enet_read_bd(IMXENETBufDesc *bd, dma_addr_t addr) static void imx_enet_write_bd(IMXENETBufDesc *bd, dma_addr_t addr) { - dma_memory_write(&address_space_memory, addr, bd, sizeof(*bd)); + dma_memory_write(&address_space_memory, addr, bd, sizeof(*bd), + MEMTXATTRS_UNSPECIFIED); } static void imx_eth_update(IMXFECState *s) @@ -474,7 +478,8 @@ static void imx_fec_do_tx(IMXFECState *s) len = ENET_MAX_FRAME_SIZE - frame_size; s->regs[ENET_EIR] |= ENET_INT_BABT; } - dma_memory_read(&address_space_memory, bd.data, ptr, len); + dma_memory_read(&address_space_memory, bd.data, ptr, len, + MEMTXATTRS_UNSPECIFIED); ptr += len; frame_size += len; if (bd.flags & ENET_BD_L) { @@ -555,7 +560,8 @@ static void imx_enet_do_tx(IMXFECState *s, uint32_t index) len = ENET_MAX_FRAME_SIZE - frame_size; s->regs[ENET_EIR] |= ENET_INT_BABT; } - dma_memory_read(&address_space_memory, bd.data, ptr, len); + dma_memory_read(&address_space_memory, bd.data, ptr, len, + MEMTXATTRS_UNSPECIFIED); ptr += len; frame_size += len; if (bd.flags & ENET_BD_L) { @@ -1103,11 +1109,12 @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf, buf_len += size - 4; } buf_addr = bd.data; - dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); + dma_memory_write(&address_space_memory, buf_addr, buf, buf_len, + MEMTXATTRS_UNSPECIFIED); buf += buf_len; if (size < 4) { dma_memory_write(&address_space_memory, buf_addr + buf_len, - crc_ptr, 4 - size); + crc_ptr, 4 - size, MEMTXATTRS_UNSPECIFIED); crc_ptr += 4 - size; } bd.flags &= ~ENET_BD_E; @@ -1210,8 +1217,8 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf, */ const uint8_t zeros[2] = { 0 }; - dma_memory_write(&address_space_memory, buf_addr, - zeros, sizeof(zeros)); + dma_memory_write(&address_space_memory, buf_addr, zeros, + sizeof(zeros), MEMTXATTRS_UNSPECIFIED); buf_addr += sizeof(zeros); buf_len -= sizeof(zeros); @@ -1220,11 +1227,12 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf, shift16 = false; } - dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); + dma_memory_write(&address_space_memory, buf_addr, buf, buf_len, + MEMTXATTRS_UNSPECIFIED); buf += buf_len; if (size < 4) { dma_memory_write(&address_space_memory, buf_addr + buf_len, - crc_ptr, 4 - size); + crc_ptr, 4 - size, MEMTXATTRS_UNSPECIFIED); crc_ptr += 4 - size; } bd.flags &= ~ENET_BD_E; diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c index 545b2b7410..9a2328935c 100644 --- a/hw/net/npcm7xx_emc.c +++ b/hw/net/npcm7xx_emc.c @@ -200,7 +200,8 @@ static void emc_update_irq_from_reg_change(NPCM7xxEMCState *emc) static int emc_read_tx_desc(dma_addr_t addr, NPCM7xxEMCTxDesc *desc) { - if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) { + if (dma_memory_read(&address_space_memory, addr, desc, + sizeof(*desc), MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%" HWADDR_PRIx "\n", __func__, addr); return -1; @@ -221,7 +222,7 @@ static int emc_write_tx_desc(const NPCM7xxEMCTxDesc *desc, dma_addr_t addr) le_desc.status_and_length = cpu_to_le32(desc->status_and_length); le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa); if (dma_memory_write(&address_space_memory, addr, &le_desc, - sizeof(le_desc))) { + sizeof(le_desc), MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%" HWADDR_PRIx "\n", __func__, addr); return -1; @@ -231,7 +232,8 @@ static int emc_write_tx_desc(const NPCM7xxEMCTxDesc *desc, dma_addr_t addr) static int emc_read_rx_desc(dma_addr_t addr, NPCM7xxEMCRxDesc *desc) { - if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) { + if (dma_memory_read(&address_space_memory, addr, desc, + sizeof(*desc), MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%" HWADDR_PRIx "\n", __func__, addr); return -1; @@ -252,7 +254,7 @@ static int emc_write_rx_desc(const NPCM7xxEMCRxDesc *desc, dma_addr_t addr) le_desc.reserved = cpu_to_le32(desc->reserved); le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa); if (dma_memory_write(&address_space_memory, addr, &le_desc, - sizeof(le_desc))) { + sizeof(le_desc), MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%" HWADDR_PRIx "\n", __func__, addr); return -1; @@ -366,7 +368,8 @@ static void emc_try_send_next_packet(NPCM7xxEMCState *emc) buf = malloced_buf; } - if (dma_memory_read(&address_space_memory, next_buf_addr, buf, length)) { + if (dma_memory_read(&address_space_memory, next_buf_addr, buf, + length, MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read packet @ 0x%x\n", __func__, next_buf_addr); emc_set_mista(emc, REG_MISTA_TXBERR); @@ -551,10 +554,11 @@ static ssize_t emc_receive(NetClientState *nc, const uint8_t *buf, size_t len1) buf_addr = rx_desc.rxbsa; emc->regs[REG_CRXBSA] = buf_addr; - if (dma_memory_write(&address_space_memory, buf_addr, buf, len) || + if (dma_memory_write(&address_space_memory, buf_addr, buf, + len, MEMTXATTRS_UNSPECIFIED) || (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC) && - dma_memory_write(&address_space_memory, buf_addr + len, crc_ptr, - 4))) { + dma_memory_write(&address_space_memory, buf_addr + len, + crc_ptr, 4, MEMTXATTRS_UNSPECIFIED))) { qemu_log_mask(LOG_GUEST_ERROR, "%s: Bus error writing packet\n", __func__); emc_set_mista(emc, REG_MISTA_RXBERR); diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index f7803fe3c3..9b91b15cb0 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -357,7 +357,8 @@ static void fw_cfg_dma_transfer(FWCfgState *s) dma_addr = s->dma_addr; s->dma_addr = 0; - if (dma_memory_read(s->dma_as, dma_addr, &dma, sizeof(dma))) { + if (dma_memory_read(s->dma_as, dma_addr, + &dma, sizeof(dma), MEMTXATTRS_UNSPECIFIED)) { stl_be_dma(s->dma_as, dma_addr + offsetof(FWCfgDmaAccess, control), FW_CFG_DMA_CTL_ERROR); return; @@ -419,7 +420,8 @@ static void fw_cfg_dma_transfer(FWCfgState *s) */ if (read) { if (dma_memory_write(s->dma_as, dma.address, - &e->data[s->cur_offset], len)) { + &e->data[s->cur_offset], len, + MEMTXATTRS_UNSPECIFIED)) { dma.control |= FW_CFG_DMA_CTL_ERROR; } } @@ -427,7 +429,8 @@ static void fw_cfg_dma_transfer(FWCfgState *s) if (!e->allow_write || len != dma.length || dma_memory_read(s->dma_as, dma.address, - &e->data[s->cur_offset], len)) { + &e->data[s->cur_offset], len, + MEMTXATTRS_UNSPECIFIED)) { dma.control |= FW_CFG_DMA_CTL_ERROR; } else if (e->write_cb) { e->write_cb(e->callback_opaque, s->cur_offset, len); diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index 9c4451ca0d..c6e7871ecb 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -715,7 +715,8 @@ static bool pnv_phb3_resolve_pe(PnvPhb3DMASpace *ds) bus_num = pci_bus_num(ds->bus); addr = rtt & PHB_RTT_BASE_ADDRESS_MASK; addr += 2 * ((bus_num << 8) | ds->devfn); - if (dma_memory_read(&address_space_memory, addr, &rte, sizeof(rte))) { + if (dma_memory_read(&address_space_memory, addr, &rte, + sizeof(rte), MEMTXATTRS_UNSPECIFIED)) { phb3_error(ds->phb, "Failed to read RTT entry at 0x%"PRIx64, addr); /* Set error bits ? fence ? ... */ return false; @@ -794,7 +795,7 @@ static void pnv_phb3_translate_tve(PnvPhb3DMASpace *ds, hwaddr addr, /* Grab the TCE address */ taddr = base | (((addr >> sh) & ((1ul << tbl_shift) - 1)) << 3); if (dma_memory_read(&address_space_memory, taddr, &tce, - sizeof(tce))) { + sizeof(tce), MEMTXATTRS_UNSPECIFIED)) { phb3_error(phb, "Failed to read TCE at 0x%"PRIx64, taddr); return; } diff --git a/hw/pci-host/pnv_phb3_msi.c b/hw/pci-host/pnv_phb3_msi.c index 099d2092a2..8bcbc2cc4f 100644 --- a/hw/pci-host/pnv_phb3_msi.c +++ b/hw/pci-host/pnv_phb3_msi.c @@ -53,7 +53,8 @@ static bool phb3_msi_read_ive(PnvPHB3 *phb, int srcno, uint64_t *out_ive) return false; } - if (dma_memory_read(&address_space_memory, ive_addr, &ive, sizeof(ive))) { + if (dma_memory_read(&address_space_memory, ive_addr, + &ive, sizeof(ive), MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "Failed to read IVE at 0x%" PRIx64, ive_addr); return false; @@ -73,7 +74,8 @@ static void phb3_msi_set_p(Phb3MsiState *msi, int srcno, uint8_t gen) return; } - if (dma_memory_write(&address_space_memory, ive_addr + 4, &p, 1)) { + if (dma_memory_write(&address_space_memory, ive_addr + 4, + &p, 1, MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "Failed to write IVE (set P) at 0x%" PRIx64, ive_addr); } @@ -89,7 +91,8 @@ static void phb3_msi_set_q(Phb3MsiState *msi, int srcno) return; } - if (dma_memory_write(&address_space_memory, ive_addr + 5, &q, 1)) { + if (dma_memory_write(&address_space_memory, ive_addr + 5, + &q, 1, MEMTXATTRS_UNSPECIFIED)) { qemu_log_mask(LOG_GUEST_ERROR, "Failed to write IVE (set Q) at 0x%" PRIx64, ive_addr); } diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 40b793201a..1fbf7328f5 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -891,7 +891,8 @@ static bool pnv_phb4_resolve_pe(PnvPhb4DMASpace *ds) bus_num = pci_bus_num(ds->bus); addr = rtt & PHB_RTT_BASE_ADDRESS_MASK; addr += 2 * PCI_BUILD_BDF(bus_num, ds->devfn); - if (dma_memory_read(&address_space_memory, addr, &rte, sizeof(rte))) { + if (dma_memory_read(&address_space_memory, addr, &rte, + sizeof(rte), MEMTXATTRS_UNSPECIFIED)) { phb_error(ds->phb, "Failed to read RTT entry at 0x%"PRIx64, addr); /* Set error bits ? fence ? ... */ return false; @@ -961,7 +962,7 @@ static void pnv_phb4_translate_tve(PnvPhb4DMASpace *ds, hwaddr addr, /* Grab the TCE address */ taddr = base | (((addr >> sh) & ((1ul << tbl_shift) - 1)) << 3); if (dma_memory_read(&address_space_memory, taddr, &tce, - sizeof(tce))) { + sizeof(tce), MEMTXATTRS_UNSPECIFIED)) { phb_error(ds->phb, "Failed to read TCE at 0x%"PRIx64, taddr); return; } diff --git a/hw/sd/allwinner-sdhost.c b/hw/sd/allwinner-sdhost.c index 9166d6638d..de5bc49e68 100644 --- a/hw/sd/allwinner-sdhost.c +++ b/hw/sd/allwinner-sdhost.c @@ -311,7 +311,8 @@ static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s, uint8_t buf[1024]; /* Read descriptor */ - dma_memory_read(&s->dma_as, desc_addr, desc, sizeof(*desc)); + dma_memory_read(&s->dma_as, desc_addr, desc, sizeof(*desc), + MEMTXATTRS_UNSPECIFIED); if (desc->size == 0) { desc->size = klass->max_desc_size; } else if (desc->size > klass->max_desc_size) { @@ -337,23 +338,24 @@ static uint32_t allwinner_sdhost_process_desc(AwSdHostState *s, /* Write to SD bus */ if (is_write) { dma_memory_read(&s->dma_as, - (desc->addr & DESC_SIZE_MASK) + num_done, - buf, buf_bytes); + (desc->addr & DESC_SIZE_MASK) + num_done, buf, + buf_bytes, MEMTXATTRS_UNSPECIFIED); sdbus_write_data(&s->sdbus, buf, buf_bytes); /* Read from SD bus */ } else { sdbus_read_data(&s->sdbus, buf, buf_bytes); dma_memory_write(&s->dma_as, - (desc->addr & DESC_SIZE_MASK) + num_done, - buf, buf_bytes); + (desc->addr & DESC_SIZE_MASK) + num_done, buf, + buf_bytes, MEMTXATTRS_UNSPECIFIED); } num_done += buf_bytes; } /* Clear hold flag and flush descriptor */ desc->status &= ~DESC_STATUS_HOLD; - dma_memory_write(&s->dma_as, desc_addr, desc, sizeof(*desc)); + dma_memory_write(&s->dma_as, desc_addr, desc, sizeof(*desc), + MEMTXATTRS_UNSPECIFIED); return num_done; } diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index c9dc065cc5..e0bbc90344 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -616,8 +616,8 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s) s->blkcnt--; } } - dma_memory_write(s->dma_as, s->sdmasysad, - &s->fifo_buffer[begin], s->data_count - begin); + dma_memory_write(s->dma_as, s->sdmasysad, &s->fifo_buffer[begin], + s->data_count - begin, MEMTXATTRS_UNSPECIFIED); s->sdmasysad += s->data_count - begin; if (s->data_count == block_size) { s->data_count = 0; @@ -637,8 +637,8 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s) s->data_count = block_size; boundary_count -= block_size - begin; } - dma_memory_read(s->dma_as, s->sdmasysad, - &s->fifo_buffer[begin], s->data_count - begin); + dma_memory_read(s->dma_as, s->sdmasysad, &s->fifo_buffer[begin], + s->data_count - begin, MEMTXATTRS_UNSPECIFIED); s->sdmasysad += s->data_count - begin; if (s->data_count == block_size) { sdbus_write_data(&s->sdbus, s->fifo_buffer, block_size); @@ -670,9 +670,11 @@ static void sdhci_sdma_transfer_single_block(SDHCIState *s) if (s->trnmod & SDHC_TRNS_READ) { sdbus_read_data(&s->sdbus, s->fifo_buffer, datacnt); - dma_memory_write(s->dma_as, s->sdmasysad, s->fifo_buffer, datacnt); + dma_memory_write(s->dma_as, s->sdmasysad, s->fifo_buffer, datacnt, + MEMTXATTRS_UNSPECIFIED); } else { - dma_memory_read(s->dma_as, s->sdmasysad, s->fifo_buffer, datacnt); + dma_memory_read(s->dma_as, s->sdmasysad, s->fifo_buffer, datacnt, + MEMTXATTRS_UNSPECIFIED); sdbus_write_data(&s->sdbus, s->fifo_buffer, datacnt); } s->blkcnt--; @@ -694,7 +696,8 @@ static void get_adma_description(SDHCIState *s, ADMADescr *dscr) hwaddr entry_addr = (hwaddr)s->admasysaddr; switch (SDHC_DMA_TYPE(s->hostctl1)) { case SDHC_CTRL_ADMA2_32: - dma_memory_read(s->dma_as, entry_addr, &adma2, sizeof(adma2)); + dma_memory_read(s->dma_as, entry_addr, &adma2, sizeof(adma2), + MEMTXATTRS_UNSPECIFIED); adma2 = le64_to_cpu(adma2); /* The spec does not specify endianness of descriptor table. * We currently assume that it is LE. @@ -705,7 +708,8 @@ static void get_adma_description(SDHCIState *s, ADMADescr *dscr) dscr->incr = 8; break; case SDHC_CTRL_ADMA1_32: - dma_memory_read(s->dma_as, entry_addr, &adma1, sizeof(adma1)); + dma_memory_read(s->dma_as, entry_addr, &adma1, sizeof(adma1), + MEMTXATTRS_UNSPECIFIED); adma1 = le32_to_cpu(adma1); dscr->addr = (hwaddr)(adma1 & 0xFFFFF000); dscr->attr = (uint8_t)extract32(adma1, 0, 7); @@ -717,10 +721,13 @@ static void get_adma_description(SDHCIState *s, ADMADescr *dscr) } break; case SDHC_CTRL_ADMA2_64: - dma_memory_read(s->dma_as, entry_addr, &dscr->attr, 1); - dma_memory_read(s->dma_as, entry_addr + 2, &dscr->length, 2); + dma_memory_read(s->dma_as, entry_addr, &dscr->attr, 1, + MEMTXATTRS_UNSPECIFIED); + dma_memory_read(s->dma_as, entry_addr + 2, &dscr->length, 2, + MEMTXATTRS_UNSPECIFIED); dscr->length = le16_to_cpu(dscr->length); - dma_memory_read(s->dma_as, entry_addr + 4, &dscr->addr, 8); + dma_memory_read(s->dma_as, entry_addr + 4, &dscr->addr, 8, + MEMTXATTRS_UNSPECIFIED); dscr->addr = le64_to_cpu(dscr->addr); dscr->attr &= (uint8_t) ~0xC0; dscr->incr = 12; @@ -785,7 +792,8 @@ static void sdhci_do_adma(SDHCIState *s) } dma_memory_write(s->dma_as, dscr.addr, &s->fifo_buffer[begin], - s->data_count - begin); + s->data_count - begin, + MEMTXATTRS_UNSPECIFIED); dscr.addr += s->data_count - begin; if (s->data_count == block_size) { s->data_count = 0; @@ -810,7 +818,8 @@ static void sdhci_do_adma(SDHCIState *s) } dma_memory_read(s->dma_as, dscr.addr, &s->fifo_buffer[begin], - s->data_count - begin); + s->data_count - begin, + MEMTXATTRS_UNSPECIFIED); dscr.addr += s->data_count - begin; if (s->data_count == block_size) { sdbus_write_data(&s->sdbus, s->fifo_buffer, block_size); diff --git a/hw/usb/hcd-dwc2.c b/hw/usb/hcd-dwc2.c index e1d96acf7e..8755e9cbb0 100644 --- a/hw/usb/hcd-dwc2.c +++ b/hw/usb/hcd-dwc2.c @@ -272,8 +272,8 @@ static void dwc2_handle_packet(DWC2State *s, uint32_t devadr, USBDevice *dev, if (pid != USB_TOKEN_IN) { trace_usb_dwc2_memory_read(hcdma, tlen); - if (dma_memory_read(&s->dma_as, hcdma, - s->usb_buf[chan], tlen) != MEMTX_OK) { + if (dma_memory_read(&s->dma_as, hcdma, s->usb_buf[chan], tlen, + MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "%s: dma_memory_read failed\n", __func__); } @@ -328,8 +328,8 @@ babble: if (pid == USB_TOKEN_IN) { trace_usb_dwc2_memory_write(hcdma, actual); - if (dma_memory_write(&s->dma_as, hcdma, s->usb_buf[chan], - actual) != MEMTX_OK) { + if (dma_memory_write(&s->dma_as, hcdma, s->usb_buf[chan], actual, + MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "%s: dma_memory_write failed\n", __func__); } diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 6caa7ac6c2..33a8a377bd 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -383,7 +383,8 @@ static inline int get_dwords(EHCIState *ehci, uint32_t addr, } for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - dma_memory_read(ehci->as, addr, buf, sizeof(*buf)); + dma_memory_read(ehci->as, addr, buf, sizeof(*buf), + MEMTXATTRS_UNSPECIFIED); *buf = le32_to_cpu(*buf); } @@ -405,7 +406,8 @@ static inline int put_dwords(EHCIState *ehci, uint32_t addr, for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { uint32_t tmp = cpu_to_le32(*buf); - dma_memory_write(ehci->as, addr, &tmp, sizeof(tmp)); + dma_memory_write(ehci->as, addr, &tmp, sizeof(tmp), + MEMTXATTRS_UNSPECIFIED); } return num; diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 56e2315c73..a93d6b2e98 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -452,7 +452,8 @@ static inline int get_dwords(OHCIState *ohci, addr += ohci->localmem_base; for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) { + if (dma_memory_read(ohci->as, addr, + buf, sizeof(*buf), MEMTXATTRS_UNSPECIFIED)) { return -1; } *buf = le32_to_cpu(*buf); @@ -471,7 +472,8 @@ static inline int put_dwords(OHCIState *ohci, for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { uint32_t tmp = cpu_to_le32(*buf); - if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) { + if (dma_memory_write(ohci->as, addr, + &tmp, sizeof(tmp), MEMTXATTRS_UNSPECIFIED)) { return -1; } } @@ -488,7 +490,8 @@ static inline int get_words(OHCIState *ohci, addr += ohci->localmem_base; for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - if (dma_memory_read(ohci->as, addr, buf, sizeof(*buf))) { + if (dma_memory_read(ohci->as, addr, + buf, sizeof(*buf), MEMTXATTRS_UNSPECIFIED)) { return -1; } *buf = le16_to_cpu(*buf); @@ -507,7 +510,8 @@ static inline int put_words(OHCIState *ohci, for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { uint16_t tmp = cpu_to_le16(*buf); - if (dma_memory_write(ohci->as, addr, &tmp, sizeof(tmp))) { + if (dma_memory_write(ohci->as, addr, + &tmp, sizeof(tmp), MEMTXATTRS_UNSPECIFIED)) { return -1; } } @@ -537,8 +541,8 @@ static inline int ohci_read_iso_td(OHCIState *ohci, static inline int ohci_read_hcca(OHCIState *ohci, dma_addr_t addr, struct ohci_hcca *hcca) { - return dma_memory_read(ohci->as, addr + ohci->localmem_base, - hcca, sizeof(*hcca)); + return dma_memory_read(ohci->as, addr + ohci->localmem_base, hcca, + sizeof(*hcca), MEMTXATTRS_UNSPECIFIED); } static inline int ohci_put_ed(OHCIState *ohci, @@ -572,7 +576,7 @@ static inline int ohci_put_hcca(OHCIState *ohci, return dma_memory_write(ohci->as, addr + ohci->localmem_base + HCCA_WRITEBACK_OFFSET, (char *)hcca + HCCA_WRITEBACK_OFFSET, - HCCA_WRITEBACK_SIZE); + HCCA_WRITEBACK_SIZE, MEMTXATTRS_UNSPECIFIED); } /* Read/Write the contents of a TD from/to main memory. */ diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index e01700039b..ed2b9ea456 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -487,7 +487,7 @@ static inline void xhci_dma_read_u32s(XHCIState *xhci, dma_addr_t addr, assert((len % sizeof(uint32_t)) == 0); - dma_memory_read(xhci->as, addr, buf, len); + dma_memory_read(xhci->as, addr, buf, len, MEMTXATTRS_UNSPECIFIED); for (i = 0; i < (len / sizeof(uint32_t)); i++) { buf[i] = le32_to_cpu(buf[i]); @@ -507,7 +507,7 @@ static inline void xhci_dma_write_u32s(XHCIState *xhci, dma_addr_t addr, for (i = 0; i < n; i++) { tmp[i] = cpu_to_le32(buf[i]); } - dma_memory_write(xhci->as, addr, tmp, len); + dma_memory_write(xhci->as, addr, tmp, len, MEMTXATTRS_UNSPECIFIED); } static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport) @@ -618,7 +618,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v) ev_trb.status, ev_trb.control); addr = intr->er_start + TRB_SIZE*intr->er_ep_idx; - dma_memory_write(xhci->as, addr, &ev_trb, TRB_SIZE); + dma_memory_write(xhci->as, addr, &ev_trb, TRB_SIZE, MEMTXATTRS_UNSPECIFIED); intr->er_ep_idx++; if (intr->er_ep_idx >= intr->er_size) { @@ -679,7 +679,8 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb, while (1) { TRBType type; - dma_memory_read(xhci->as, ring->dequeue, trb, TRB_SIZE); + dma_memory_read(xhci->as, ring->dequeue, trb, TRB_SIZE, + MEMTXATTRS_UNSPECIFIED); trb->addr = ring->dequeue; trb->ccs = ring->ccs; le64_to_cpus(&trb->parameter); @@ -726,7 +727,8 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring) while (1) { TRBType type; - dma_memory_read(xhci->as, dequeue, &trb, TRB_SIZE); + dma_memory_read(xhci->as, dequeue, &trb, TRB_SIZE, + MEMTXATTRS_UNSPECIFIED); le64_to_cpus(&trb.parameter); le32_to_cpus(&trb.status); le32_to_cpus(&trb.control); @@ -781,7 +783,8 @@ static void xhci_er_reset(XHCIState *xhci, int v) xhci_die(xhci); return; } - dma_memory_read(xhci->as, erstba, &seg, sizeof(seg)); + dma_memory_read(xhci->as, erstba, &seg, sizeof(seg), + MEMTXATTRS_UNSPECIFIED); le32_to_cpus(&seg.addr_low); le32_to_cpus(&seg.addr_high); le32_to_cpus(&seg.size); @@ -2397,7 +2400,8 @@ static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx) /* TODO: actually implement real values here */ bw_ctx[0] = 0; memset(&bw_ctx[1], 80, xhci->numports); /* 80% */ - dma_memory_write(xhci->as, ctx, bw_ctx, sizeof(bw_ctx)); + dma_memory_write(xhci->as, ctx, bw_ctx, sizeof(bw_ctx), + MEMTXATTRS_UNSPECIFIED); return CC_SUCCESS; } diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h index c90e74a67d..5d2ea8e665 100644 --- a/include/hw/ppc/spapr_vio.h +++ b/include/hw/ppc/spapr_vio.h @@ -97,14 +97,16 @@ static inline bool spapr_vio_dma_valid(SpaprVioDevice *dev, uint64_t taddr, static inline int spapr_vio_dma_read(SpaprVioDevice *dev, uint64_t taddr, void *buf, uint32_t size) { - return (dma_memory_read(&dev->as, taddr, buf, size) != 0) ? + return (dma_memory_read(&dev->as, taddr, + buf, size, MEMTXATTRS_UNSPECIFIED) != 0) ? H_DEST_PARM : H_SUCCESS; } static inline int spapr_vio_dma_write(SpaprVioDevice *dev, uint64_t taddr, const void *buf, uint32_t size) { - return (dma_memory_write(&dev->as, taddr, buf, size) != 0) ? + return (dma_memory_write(&dev->as, taddr, + buf, size, MEMTXATTRS_UNSPECIFIED) != 0) ? H_DEST_PARM : H_SUCCESS; } diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index e8ad42226f..522682bf38 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -143,12 +143,14 @@ static inline MemTxResult dma_memory_rw(AddressSpace *as, dma_addr_t addr, * @addr: address within that address space * @buf: buffer with the data transferred * @len: length of the data transferred + * @attrs: memory transaction attributes */ static inline MemTxResult dma_memory_read(AddressSpace *as, dma_addr_t addr, - void *buf, dma_addr_t len) + void *buf, dma_addr_t len, + MemTxAttrs attrs) { return dma_memory_rw(as, addr, buf, len, - DMA_DIRECTION_TO_DEVICE, MEMTXATTRS_UNSPECIFIED); + DMA_DIRECTION_TO_DEVICE, attrs); } /** @@ -162,12 +164,14 @@ static inline MemTxResult dma_memory_read(AddressSpace *as, dma_addr_t addr, * @addr: address within that address space * @buf: buffer with the data transferred * @len: the number of bytes to write + * @attrs: memory transaction attributes */ static inline MemTxResult dma_memory_write(AddressSpace *as, dma_addr_t addr, - const void *buf, dma_addr_t len) + const void *buf, dma_addr_t len, + MemTxAttrs attrs) { return dma_memory_rw(as, addr, (void *)buf, len, - DMA_DIRECTION_FROM_DEVICE, MEMTXATTRS_UNSPECIFIED); + DMA_DIRECTION_FROM_DEVICE, attrs); } /** @@ -239,7 +243,7 @@ static inline void dma_memory_unmap(AddressSpace *as, dma_addr_t addr) \ { \ uint##_bits##_t val; \ - dma_memory_read(as, addr, &val, (_bits) / 8); \ + dma_memory_read(as, addr, &val, (_bits) / 8, MEMTXATTRS_UNSPECIFIED); \ return _end##_bits##_to_cpu(val); \ } \ static inline void st##_sname##_##_end##_dma(AddressSpace *as, \ @@ -247,20 +251,20 @@ static inline void dma_memory_unmap(AddressSpace *as, uint##_bits##_t val) \ { \ val = cpu_to_##_end##_bits(val); \ - dma_memory_write(as, addr, &val, (_bits) / 8); \ + dma_memory_write(as, addr, &val, (_bits) / 8, MEMTXATTRS_UNSPECIFIED); \ } static inline uint8_t ldub_dma(AddressSpace *as, dma_addr_t addr) { uint8_t val; - dma_memory_read(as, addr, &val, 1); + dma_memory_read(as, addr, &val, 1, MEMTXATTRS_UNSPECIFIED); return val; } static inline void stb_dma(AddressSpace *as, dma_addr_t addr, uint8_t val) { - dma_memory_write(as, addr, &val, 1); + dma_memory_write(as, addr, &val, 1, MEMTXATTRS_UNSPECIFIED); } DEFINE_LDST_DMA(uw, w, 16, le); From a1d4b0a3051b3079c8db607f519bc0fcb30e17ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 3 Sep 2020 11:00:47 +0200 Subject: [PATCH 100/730] dma: Let dma_memory_map() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling dma_memory_map(). Patch created mechanically using spatch with this script: @@ expression E1, E2, E3, E4; @@ - dma_memory_map(E1, E2, E3, E4) + dma_memory_map(E1, E2, E3, E4, MEMTXATTRS_UNSPECIFIED) Reviewed-by: Richard Henderson Reviewed-by: Li Qiang Reviewed-by: Edgar E. Iglesias Signed-off-by: Philippe Mathieu-Daudé Acked-by: Stefan Hajnoczi Message-Id: <20211223115554.3155328-7-philmd@redhat.com> --- hw/display/virtio-gpu.c | 10 ++++++---- hw/hyperv/vmbus.c | 8 +++++--- hw/ide/ahci.c | 8 +++++--- hw/usb/libhw.c | 3 ++- hw/virtio/virtio.c | 6 ++++-- include/hw/pci/pci.h | 3 ++- include/sysemu/dma.h | 5 +++-- softmmu/dma-helpers.c | 3 ++- 8 files changed, 29 insertions(+), 17 deletions(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index d78b9700c7..c6dc818988 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -814,8 +814,9 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g, do { len = l; - map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, - a, &len, DMA_DIRECTION_TO_DEVICE); + map = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, a, &len, + DMA_DIRECTION_TO_DEVICE, + MEMTXATTRS_UNSPECIFIED); if (!map) { qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for" " element %d\n", __func__, e); @@ -1252,8 +1253,9 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, for (i = 0; i < res->iov_cnt; i++) { hwaddr len = res->iov[i].iov_len; res->iov[i].iov_base = - dma_memory_map(VIRTIO_DEVICE(g)->dma_as, - res->addrs[i], &len, DMA_DIRECTION_TO_DEVICE); + dma_memory_map(VIRTIO_DEVICE(g)->dma_as, res->addrs[i], &len, + DMA_DIRECTION_TO_DEVICE, + MEMTXATTRS_UNSPECIFIED); if (!res->iov[i].iov_base || len != res->iov[i].iov_len) { /* Clean up the half-a-mapping we just created... */ diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c index dbce3b35fb..8aad29f1bb 100644 --- a/hw/hyperv/vmbus.c +++ b/hw/hyperv/vmbus.c @@ -373,7 +373,8 @@ static ssize_t gpadl_iter_io(GpadlIter *iter, void *buf, uint32_t len) maddr = (iter->gpadl->gfns[idx] << TARGET_PAGE_BITS) | off_in_page; - iter->map = dma_memory_map(iter->as, maddr, &mlen, iter->dir); + iter->map = dma_memory_map(iter->as, maddr, &mlen, iter->dir, + MEMTXATTRS_UNSPECIFIED); if (mlen != pgleft) { dma_memory_unmap(iter->as, iter->map, mlen, iter->dir, 0); iter->map = NULL; @@ -490,7 +491,8 @@ int vmbus_map_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, goto err; } - iov[ret_cnt].iov_base = dma_memory_map(sgl->as, a, &l, dir); + iov[ret_cnt].iov_base = dma_memory_map(sgl->as, a, &l, dir, + MEMTXATTRS_UNSPECIFIED); if (!l) { ret = -EFAULT; goto err; @@ -566,7 +568,7 @@ static vmbus_ring_buffer *ringbuf_map_hdr(VMBusRingBufCommon *ringbuf) dma_addr_t mlen = sizeof(*rb); rb = dma_memory_map(ringbuf->as, ringbuf->rb_addr, &mlen, - DMA_DIRECTION_FROM_DEVICE); + DMA_DIRECTION_FROM_DEVICE, MEMTXATTRS_UNSPECIFIED); if (mlen != sizeof(*rb)) { dma_memory_unmap(ringbuf->as, rb, mlen, DMA_DIRECTION_FROM_DEVICE, 0); diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index a94c6e26fb..8e77ddb660 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -249,7 +249,8 @@ static void map_page(AddressSpace *as, uint8_t **ptr, uint64_t addr, dma_memory_unmap(as, *ptr, len, DMA_DIRECTION_FROM_DEVICE, len); } - *ptr = dma_memory_map(as, addr, &len, DMA_DIRECTION_FROM_DEVICE); + *ptr = dma_memory_map(as, addr, &len, DMA_DIRECTION_FROM_DEVICE, + MEMTXATTRS_UNSPECIFIED); if (len < wanted && *ptr) { dma_memory_unmap(as, *ptr, len, DMA_DIRECTION_FROM_DEVICE, len); *ptr = NULL; @@ -939,7 +940,8 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, /* map PRDT */ if (!(prdt = dma_memory_map(ad->hba->as, prdt_addr, &prdt_len, - DMA_DIRECTION_TO_DEVICE))){ + DMA_DIRECTION_TO_DEVICE, + MEMTXATTRS_UNSPECIFIED))){ trace_ahci_populate_sglist_no_map(ad->hba, ad->port_no); return -1; } @@ -1301,7 +1303,7 @@ static int handle_cmd(AHCIState *s, int port, uint8_t slot) tbl_addr = le64_to_cpu(cmd->tbl_addr); cmd_len = 0x80; cmd_fis = dma_memory_map(s->as, tbl_addr, &cmd_len, - DMA_DIRECTION_TO_DEVICE); + DMA_DIRECTION_TO_DEVICE, MEMTXATTRS_UNSPECIFIED); if (!cmd_fis) { trace_handle_cmd_badfis(s, port); return -1; diff --git a/hw/usb/libhw.c b/hw/usb/libhw.c index 9c33a1640f..f350eae443 100644 --- a/hw/usb/libhw.c +++ b/hw/usb/libhw.c @@ -36,7 +36,8 @@ int usb_packet_map(USBPacket *p, QEMUSGList *sgl) while (len) { dma_addr_t xlen = len; - mem = dma_memory_map(sgl->as, base, &xlen, dir); + mem = dma_memory_map(sgl->as, base, &xlen, dir, + MEMTXATTRS_UNSPECIFIED); if (!mem) { goto err; } diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index ea7c079fb0..e11a8a0dba 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1306,7 +1306,8 @@ static bool virtqueue_map_desc(VirtIODevice *vdev, unsigned int *p_num_sg, iov[num_sg].iov_base = dma_memory_map(vdev->dma_as, pa, &len, is_write ? DMA_DIRECTION_FROM_DEVICE : - DMA_DIRECTION_TO_DEVICE); + DMA_DIRECTION_TO_DEVICE, + MEMTXATTRS_UNSPECIFIED); if (!iov[num_sg].iov_base) { virtio_error(vdev, "virtio: bogus descriptor or out of resources"); goto out; @@ -1355,7 +1356,8 @@ static void virtqueue_map_iovec(VirtIODevice *vdev, struct iovec *sg, sg[i].iov_base = dma_memory_map(vdev->dma_as, addr[i], &len, is_write ? DMA_DIRECTION_FROM_DEVICE : - DMA_DIRECTION_TO_DEVICE); + DMA_DIRECTION_TO_DEVICE, + MEMTXATTRS_UNSPECIFIED); if (!sg[i].iov_base) { error_report("virtio: error trying to map MMIO memory"); exit(1); diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 4383f1c95e..1acefc2a4c 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -875,7 +875,8 @@ static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr, { void *buf; - buf = dma_memory_map(pci_get_address_space(dev), addr, plen, dir); + buf = dma_memory_map(pci_get_address_space(dev), addr, plen, dir, + MEMTXATTRS_UNSPECIFIED); return buf; } diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 522682bf38..97ff6f29f8 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -202,16 +202,17 @@ MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr, * @addr: address within that address space * @len: pointer to length of buffer; updated on return * @dir: indicates the transfer direction + * @attrs: memory attributes */ static inline void *dma_memory_map(AddressSpace *as, dma_addr_t addr, dma_addr_t *len, - DMADirection dir) + DMADirection dir, MemTxAttrs attrs) { hwaddr xlen = *len; void *p; p = address_space_map(as, addr, &xlen, dir == DMA_DIRECTION_FROM_DEVICE, - MEMTXATTRS_UNSPECIFIED); + attrs); *len = xlen; return p; } diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 5bf76fff6b..3c06a2fedd 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -143,7 +143,8 @@ static void dma_blk_cb(void *opaque, int ret) while (dbs->sg_cur_index < dbs->sg->nsg) { cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte; cur_len = dbs->sg->sg[dbs->sg_cur_index].len - dbs->sg_cur_byte; - mem = dma_memory_map(dbs->sg->as, cur_addr, &cur_len, dbs->dir); + mem = dma_memory_map(dbs->sg->as, cur_addr, &cur_len, dbs->dir, + MEMTXATTRS_UNSPECIFIED); /* * Make reads deterministic in icount mode. Windows sometimes issues * disk read requests with overlapping SGs. It leads From c0ee1527358474c75067993d1bb233ad3a4ee081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 16 Dec 2021 11:24:56 +0100 Subject: [PATCH 101/730] dma: Have dma_buf_rw() take a void pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DMA operations are run on any kind of buffer, not arrays of uint8_t. Convert dma_buf_rw() to take a void pointer argument to save us pointless casts to uint8_t *. Reviewed-by: Klaus Jensen Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-8-philmd@redhat.com> --- softmmu/dma-helpers.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 3c06a2fedd..09e29997ee 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -294,9 +294,10 @@ BlockAIOCB *dma_blk_write(BlockBackend *blk, } -static uint64_t dma_buf_rw(uint8_t *ptr, int32_t len, QEMUSGList *sg, +static uint64_t dma_buf_rw(void *buf, int32_t len, QEMUSGList *sg, DMADirection dir) { + uint8_t *ptr = buf; uint64_t resid; int sg_cur_index; From 5e468a36dcdd8fd5eb04282842b72967a29875e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 16 Dec 2021 11:27:23 +0100 Subject: [PATCH 102/730] dma: Have dma_buf_read() / dma_buf_write() take a void pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DMA operations are run on any kind of buffer, not arrays of uint8_t. Convert dma_buf_read/dma_buf_write functions to take a void pointer argument and save us pointless casts to uint8_t *. Remove this pointless casts in the megasas device model. Reviewed-by: Klaus Jensen Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-9-philmd@redhat.com> --- hw/scsi/megasas.c | 22 +++++++++++----------- include/sysemu/dma.h | 4 ++-- softmmu/dma-helpers.c | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 14ec6d68bb..2dae33f675 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -848,7 +848,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) MFI_INFO_PDMIX_SATA | MFI_INFO_PDMIX_LD); - cmd->iov_size -= dma_buf_read((uint8_t *)&info, dcmd_size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg); return MFI_STAT_OK; } @@ -878,7 +878,7 @@ static int megasas_mfc_get_defaults(MegasasState *s, MegasasCmd *cmd) info.disable_preboot_cli = 1; info.cluster_disable = 1; - cmd->iov_size -= dma_buf_read((uint8_t *)&info, dcmd_size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg); return MFI_STAT_OK; } @@ -899,7 +899,7 @@ static int megasas_dcmd_get_bios_info(MegasasState *s, MegasasCmd *cmd) info.expose_all_drives = 1; } - cmd->iov_size -= dma_buf_read((uint8_t *)&info, dcmd_size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg); return MFI_STAT_OK; } @@ -910,7 +910,7 @@ static int megasas_dcmd_get_fw_time(MegasasState *s, MegasasCmd *cmd) fw_time = cpu_to_le64(megasas_fw_time()); - cmd->iov_size -= dma_buf_read((uint8_t *)&fw_time, dcmd_size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&fw_time, dcmd_size, &cmd->qsg); return MFI_STAT_OK; } @@ -937,7 +937,7 @@ static int megasas_event_info(MegasasState *s, MegasasCmd *cmd) info.shutdown_seq_num = cpu_to_le32(s->shutdown_event); info.boot_seq_num = cpu_to_le32(s->boot_event); - cmd->iov_size -= dma_buf_read((uint8_t *)&info, dcmd_size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg); return MFI_STAT_OK; } @@ -1006,7 +1006,7 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd) info.size = cpu_to_le32(offset); info.count = cpu_to_le32(num_pd_disks); - cmd->iov_size -= dma_buf_read((uint8_t *)&info, offset, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&info, offset, &cmd->qsg); return MFI_STAT_OK; } @@ -1172,7 +1172,7 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) info.ld_count = cpu_to_le32(num_ld_disks); trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); - resid = dma_buf_read((uint8_t *)&info, dcmd_size, &cmd->qsg); + resid = dma_buf_read(&info, dcmd_size, &cmd->qsg); cmd->iov_size = dcmd_size - resid; return MFI_STAT_OK; } @@ -1221,7 +1221,7 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd) info.size = dcmd_size; trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); - resid = dma_buf_read((uint8_t *)&info, dcmd_size, &cmd->qsg); + resid = dma_buf_read(&info, dcmd_size, &cmd->qsg); cmd->iov_size = dcmd_size - resid; return MFI_STAT_OK; } @@ -1390,7 +1390,7 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd) ld_offset += sizeof(struct mfi_ld_config); } - cmd->iov_size -= dma_buf_read((uint8_t *)data, info->size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(data, info->size, &cmd->qsg); return MFI_STAT_OK; } @@ -1420,7 +1420,7 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd) info.ecc_bucket_leak_rate = cpu_to_le16(1440); info.expose_encl_devices = 1; - cmd->iov_size -= dma_buf_read((uint8_t *)&info, dcmd_size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg); return MFI_STAT_OK; } @@ -1465,7 +1465,7 @@ static int megasas_dcmd_set_properties(MegasasState *s, MegasasCmd *cmd) dcmd_size); return MFI_STAT_INVALID_PARAMETER; } - dma_buf_write((uint8_t *)&info, dcmd_size, &cmd->qsg); + dma_buf_write(&info, dcmd_size, &cmd->qsg); trace_megasas_dcmd_unsupported(cmd->index, cmd->iov_size); return MFI_STAT_OK; } diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 97ff6f29f8..0d5b836013 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -302,8 +302,8 @@ BlockAIOCB *dma_blk_read(BlockBackend *blk, BlockAIOCB *dma_blk_write(BlockBackend *blk, QEMUSGList *sg, uint64_t offset, uint32_t align, BlockCompletionFunc *cb, void *opaque); -uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg); -uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg); +uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg); +uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg); void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, QEMUSGList *sg, enum BlockAcctType type); diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 09e29997ee..7f37548394 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -317,12 +317,12 @@ static uint64_t dma_buf_rw(void *buf, int32_t len, QEMUSGList *sg, return resid; } -uint64_t dma_buf_read(uint8_t *ptr, int32_t len, QEMUSGList *sg) +uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg) { return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_FROM_DEVICE); } -uint64_t dma_buf_write(uint8_t *ptr, int32_t len, QEMUSGList *sg) +uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg) { return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_TO_DEVICE); } From e2d784b67dc724a9b0854b49255ba0ee8ca46543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 15 Dec 2021 22:18:19 +0100 Subject: [PATCH 103/730] pci: Let pci_dma_rw() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling pci_dma_rw(). Keep the default MEMTXATTRS_UNSPECIFIED in the few callers. Reviewed-by: Klaus Jensen Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-10-philmd@redhat.com> --- hw/audio/intel-hda.c | 3 ++- hw/scsi/esp-pci.c | 2 +- include/hw/pci/pci.h | 10 ++++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index 8ce9df64e3..fb3d34a4a0 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -427,7 +427,8 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output, dprint(d, 3, "dma: entry %d, pos %d/%d, copy %d\n", st->be, st->bp, st->bpl[st->be].len, copy); - pci_dma_rw(&d->pci, st->bpl[st->be].addr + st->bp, buf, copy, !output); + pci_dma_rw(&d->pci, st->bpl[st->be].addr + st->bp, buf, copy, !output, + MEMTXATTRS_UNSPECIFIED); st->lpib += copy; st->bp += copy; buf += copy; diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c index dac054aeed..1792f84cea 100644 --- a/hw/scsi/esp-pci.c +++ b/hw/scsi/esp-pci.c @@ -280,7 +280,7 @@ static void esp_pci_dma_memory_rw(PCIESPState *pci, uint8_t *buf, int len, len = pci->dma_regs[DMA_WBC]; } - pci_dma_rw(PCI_DEVICE(pci), addr, buf, len, dir); + pci_dma_rw(PCI_DEVICE(pci), addr, buf, len, dir, MEMTXATTRS_UNSPECIFIED); /* update status registers */ pci->dma_regs[DMA_WBC] -= len; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 1acefc2a4c..a751ab5a75 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -806,10 +806,10 @@ static inline AddressSpace *pci_get_address_space(PCIDevice *dev) */ static inline MemTxResult pci_dma_rw(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len, - DMADirection dir) + DMADirection dir, MemTxAttrs attrs) { return dma_memory_rw(pci_get_address_space(dev), addr, buf, len, - dir, MEMTXATTRS_UNSPECIFIED); + dir, attrs); } /** @@ -827,7 +827,8 @@ static inline MemTxResult pci_dma_rw(PCIDevice *dev, dma_addr_t addr, static inline MemTxResult pci_dma_read(PCIDevice *dev, dma_addr_t addr, void *buf, dma_addr_t len) { - return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE); + return pci_dma_rw(dev, addr, buf, len, + DMA_DIRECTION_TO_DEVICE, MEMTXATTRS_UNSPECIFIED); } /** @@ -845,7 +846,8 @@ static inline MemTxResult pci_dma_read(PCIDevice *dev, dma_addr_t addr, static inline MemTxResult pci_dma_write(PCIDevice *dev, dma_addr_t addr, const void *buf, dma_addr_t len) { - return pci_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE); + return pci_dma_rw(dev, addr, (void *) buf, len, + DMA_DIRECTION_FROM_DEVICE, MEMTXATTRS_UNSPECIFIED); } #define PCI_DMA_DEFINE_LDST(_l, _s, _bits) \ From 959384e74e1b508acc3af6e806b3d7b87335fc2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 15 Dec 2021 22:59:46 +0100 Subject: [PATCH 104/730] dma: Let dma_buf_rw() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling dma_buf_rw(). Keep the default MEMTXATTRS_UNSPECIFIED in the 2 callers. Reviewed-by: Klaus Jensen Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-11-philmd@redhat.com> --- softmmu/dma-helpers.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 7f37548394..fa81d2b386 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -295,7 +295,7 @@ BlockAIOCB *dma_blk_write(BlockBackend *blk, static uint64_t dma_buf_rw(void *buf, int32_t len, QEMUSGList *sg, - DMADirection dir) + DMADirection dir, MemTxAttrs attrs) { uint8_t *ptr = buf; uint64_t resid; @@ -307,8 +307,7 @@ static uint64_t dma_buf_rw(void *buf, int32_t len, QEMUSGList *sg, while (len > 0) { ScatterGatherEntry entry = sg->sg[sg_cur_index++]; int32_t xfer = MIN(len, entry.len); - dma_memory_rw(sg->as, entry.base, ptr, xfer, dir, - MEMTXATTRS_UNSPECIFIED); + dma_memory_rw(sg->as, entry.base, ptr, xfer, dir, attrs); ptr += xfer; len -= xfer; resid -= xfer; @@ -319,12 +318,14 @@ static uint64_t dma_buf_rw(void *buf, int32_t len, QEMUSGList *sg, uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg) { - return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_FROM_DEVICE); + return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_FROM_DEVICE, + MEMTXATTRS_UNSPECIFIED); } uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg) { - return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_TO_DEVICE); + return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_TO_DEVICE, + MEMTXATTRS_UNSPECIFIED); } void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, From 392e48af3468d7f8e49db33fdc9e28b5f99276ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 15 Dec 2021 23:02:21 +0100 Subject: [PATCH 105/730] dma: Let dma_buf_write() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling dma_buf_write(). Keep the default MEMTXATTRS_UNSPECIFIED in the few callers. Reviewed-by: Klaus Jensen Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-12-philmd@redhat.com> --- hw/ide/ahci.c | 6 ++++-- hw/nvme/ctrl.c | 3 ++- hw/scsi/megasas.c | 2 +- hw/scsi/scsi-bus.c | 2 +- include/sysemu/dma.h | 2 +- softmmu/dma-helpers.c | 5 ++--- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 8e77ddb660..079d2977f2 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1381,8 +1381,10 @@ static void ahci_pio_transfer(const IDEDMA *dma) has_sglist ? "" : "o"); if (has_sglist && size) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; + if (is_write) { - dma_buf_write(s->data_ptr, size, &s->sg); + dma_buf_write(s->data_ptr, size, &s->sg, attrs); } else { dma_buf_read(s->data_ptr, size, &s->sg); } @@ -1479,7 +1481,7 @@ static int ahci_dma_rw_buf(const IDEDMA *dma, bool is_write) if (is_write) { dma_buf_read(p, l, &s->sg); } else { - dma_buf_write(p, l, &s->sg); + dma_buf_write(p, l, &s->sg, MEMTXATTRS_UNSPECIFIED); } /* free sglist, update byte count */ diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 5f573c417b..e1a531d5d6 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -1146,10 +1146,11 @@ static uint16_t nvme_tx(NvmeCtrl *n, NvmeSg *sg, uint8_t *ptr, uint32_t len, assert(sg->flags & NVME_SG_ALLOC); if (sg->flags & NVME_SG_DMA) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; uint64_t residual; if (dir == NVME_TX_DIRECTION_TO_DEVICE) { - residual = dma_buf_write(ptr, len, &sg->qsg); + residual = dma_buf_write(ptr, len, &sg->qsg, attrs); } else { residual = dma_buf_read(ptr, len, &sg->qsg); } diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 2dae33f675..79fd14c5a3 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -1465,7 +1465,7 @@ static int megasas_dcmd_set_properties(MegasasState *s, MegasasCmd *cmd) dcmd_size); return MFI_STAT_INVALID_PARAMETER; } - dma_buf_write(&info, dcmd_size, &cmd->qsg); + dma_buf_write(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); trace_megasas_dcmd_unsupported(cmd->index, cmd->iov_size); return MFI_STAT_OK; } diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 77325d8cc7..64a506a397 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -1423,7 +1423,7 @@ void scsi_req_data(SCSIRequest *req, int len) if (req->cmd.mode == SCSI_XFER_FROM_DEV) { req->resid = dma_buf_read(buf, len, req->sg); } else { - req->resid = dma_buf_write(buf, len, req->sg); + req->resid = dma_buf_write(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); } scsi_req_continue(req); } diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 0d5b836013..e3dd74a9c4 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -303,7 +303,7 @@ BlockAIOCB *dma_blk_write(BlockBackend *blk, QEMUSGList *sg, uint64_t offset, uint32_t align, BlockCompletionFunc *cb, void *opaque); uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg); -uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg); +uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs); void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, QEMUSGList *sg, enum BlockAcctType type); diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index fa81d2b386..2f1a241b81 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -322,10 +322,9 @@ uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg) MEMTXATTRS_UNSPECIFIED); } -uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg) +uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) { - return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_TO_DEVICE, - MEMTXATTRS_UNSPECIFIED); + return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_TO_DEVICE, attrs); } void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, From 1e5a3f8b2a976054da96cbbb9de6cbac7c2efb79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 15 Dec 2021 23:29:52 +0100 Subject: [PATCH 106/730] dma: Let dma_buf_read() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling dma_buf_read(). Keep the default MEMTXATTRS_UNSPECIFIED in the few callers. Reviewed-by: Klaus Jensen Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-13-philmd@redhat.com> --- hw/ide/ahci.c | 4 ++-- hw/nvme/ctrl.c | 2 +- hw/scsi/megasas.c | 24 ++++++++++++------------ hw/scsi/scsi-bus.c | 2 +- include/sysemu/dma.h | 2 +- softmmu/dma-helpers.c | 5 ++--- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 079d2977f2..205dfdc662 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1386,7 +1386,7 @@ static void ahci_pio_transfer(const IDEDMA *dma) if (is_write) { dma_buf_write(s->data_ptr, size, &s->sg, attrs); } else { - dma_buf_read(s->data_ptr, size, &s->sg); + dma_buf_read(s->data_ptr, size, &s->sg, attrs); } } @@ -1479,7 +1479,7 @@ static int ahci_dma_rw_buf(const IDEDMA *dma, bool is_write) } if (is_write) { - dma_buf_read(p, l, &s->sg); + dma_buf_read(p, l, &s->sg, MEMTXATTRS_UNSPECIFIED); } else { dma_buf_write(p, l, &s->sg, MEMTXATTRS_UNSPECIFIED); } diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index e1a531d5d6..462f79a1f6 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -1152,7 +1152,7 @@ static uint16_t nvme_tx(NvmeCtrl *n, NvmeSg *sg, uint8_t *ptr, uint32_t len, if (dir == NVME_TX_DIRECTION_TO_DEVICE) { residual = dma_buf_write(ptr, len, &sg->qsg, attrs); } else { - residual = dma_buf_read(ptr, len, &sg->qsg); + residual = dma_buf_read(ptr, len, &sg->qsg, attrs); } if (unlikely(residual)) { diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 79fd14c5a3..091a350e05 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -848,7 +848,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) MFI_INFO_PDMIX_SATA | MFI_INFO_PDMIX_LD); - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); return MFI_STAT_OK; } @@ -878,7 +878,7 @@ static int megasas_mfc_get_defaults(MegasasState *s, MegasasCmd *cmd) info.disable_preboot_cli = 1; info.cluster_disable = 1; - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); return MFI_STAT_OK; } @@ -899,7 +899,7 @@ static int megasas_dcmd_get_bios_info(MegasasState *s, MegasasCmd *cmd) info.expose_all_drives = 1; } - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); return MFI_STAT_OK; } @@ -910,7 +910,7 @@ static int megasas_dcmd_get_fw_time(MegasasState *s, MegasasCmd *cmd) fw_time = cpu_to_le64(megasas_fw_time()); - cmd->iov_size -= dma_buf_read(&fw_time, dcmd_size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&fw_time, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); return MFI_STAT_OK; } @@ -937,7 +937,7 @@ static int megasas_event_info(MegasasState *s, MegasasCmd *cmd) info.shutdown_seq_num = cpu_to_le32(s->shutdown_event); info.boot_seq_num = cpu_to_le32(s->boot_event); - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); return MFI_STAT_OK; } @@ -1006,7 +1006,7 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd) info.size = cpu_to_le32(offset); info.count = cpu_to_le32(num_pd_disks); - cmd->iov_size -= dma_buf_read(&info, offset, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&info, offset, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); return MFI_STAT_OK; } @@ -1100,7 +1100,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, info->connected_port_bitmap = 0x1; info->device_speed = 1; info->link_speed = 1; - resid = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg); + resid = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); g_free(cmd->iov_buf); cmd->iov_size = dcmd_size - resid; cmd->iov_buf = NULL; @@ -1172,7 +1172,7 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) info.ld_count = cpu_to_le32(num_ld_disks); trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); - resid = dma_buf_read(&info, dcmd_size, &cmd->qsg); + resid = dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); cmd->iov_size = dcmd_size - resid; return MFI_STAT_OK; } @@ -1221,7 +1221,7 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd) info.size = dcmd_size; trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); - resid = dma_buf_read(&info, dcmd_size, &cmd->qsg); + resid = dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); cmd->iov_size = dcmd_size - resid; return MFI_STAT_OK; } @@ -1271,7 +1271,7 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, info->ld_config.span[0].num_blocks = info->size; info->ld_config.span[0].array_ref = cpu_to_le16(sdev_id); - resid = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg); + resid = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); g_free(cmd->iov_buf); cmd->iov_size = dcmd_size - resid; cmd->iov_buf = NULL; @@ -1390,7 +1390,7 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd) ld_offset += sizeof(struct mfi_ld_config); } - cmd->iov_size -= dma_buf_read(data, info->size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(data, info->size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); return MFI_STAT_OK; } @@ -1420,7 +1420,7 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd) info.ecc_bucket_leak_rate = cpu_to_le16(1440); info.expose_encl_devices = 1; - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg); + cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); return MFI_STAT_OK; } diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 64a506a397..2b5e9dca31 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -1421,7 +1421,7 @@ void scsi_req_data(SCSIRequest *req, int len) buf = scsi_req_get_buf(req); if (req->cmd.mode == SCSI_XFER_FROM_DEV) { - req->resid = dma_buf_read(buf, len, req->sg); + req->resid = dma_buf_read(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); } else { req->resid = dma_buf_write(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); } diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index e3dd74a9c4..fd8f16003d 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -302,7 +302,7 @@ BlockAIOCB *dma_blk_read(BlockBackend *blk, BlockAIOCB *dma_blk_write(BlockBackend *blk, QEMUSGList *sg, uint64_t offset, uint32_t align, BlockCompletionFunc *cb, void *opaque); -uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg); +uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs); uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs); void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 2f1a241b81..a391773c29 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -316,10 +316,9 @@ static uint64_t dma_buf_rw(void *buf, int32_t len, QEMUSGList *sg, return resid; } -uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg) +uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) { - return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_FROM_DEVICE, - MEMTXATTRS_UNSPECIFIED); + return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_FROM_DEVICE, attrs); } uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) From 292e13142d277c15bdd68331abc607e46628b7e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 15 Dec 2021 23:38:52 +0100 Subject: [PATCH 107/730] dma: Let dma_buf_rw() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dma_memory_rw() returns a MemTxResult type. Do not discard it, return it to the caller. Since dma_buf_rw() was previously returning the QEMUSGList size not consumed, add an extra argument where this size can be stored. Update the 2 callers. Reviewed-by: Klaus Jensen Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-14-philmd@redhat.com> --- softmmu/dma-helpers.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index a391773c29..b0be156479 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -294,12 +294,14 @@ BlockAIOCB *dma_blk_write(BlockBackend *blk, } -static uint64_t dma_buf_rw(void *buf, int32_t len, QEMUSGList *sg, - DMADirection dir, MemTxAttrs attrs) +static MemTxResult dma_buf_rw(void *buf, int32_t len, uint64_t *residp, + QEMUSGList *sg, DMADirection dir, + MemTxAttrs attrs) { uint8_t *ptr = buf; uint64_t resid; int sg_cur_index; + MemTxResult res = MEMTX_OK; resid = sg->size; sg_cur_index = 0; @@ -307,23 +309,34 @@ static uint64_t dma_buf_rw(void *buf, int32_t len, QEMUSGList *sg, while (len > 0) { ScatterGatherEntry entry = sg->sg[sg_cur_index++]; int32_t xfer = MIN(len, entry.len); - dma_memory_rw(sg->as, entry.base, ptr, xfer, dir, attrs); + res |= dma_memory_rw(sg->as, entry.base, ptr, xfer, dir, attrs); ptr += xfer; len -= xfer; resid -= xfer; } - return resid; + if (residp) { + *residp = resid; + } + return res; } uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) { - return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_FROM_DEVICE, attrs); + uint64_t resid; + + dma_buf_rw(ptr, len, &resid, sg, DMA_DIRECTION_FROM_DEVICE, attrs); + + return resid; } uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) { - return dma_buf_rw(ptr, len, sg, DMA_DIRECTION_TO_DEVICE, attrs); + uint64_t resid; + + dma_buf_rw(ptr, len, &resid, sg, DMA_DIRECTION_TO_DEVICE, attrs); + + return resid; } void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, From 2280c27afc65bb2af95dd44a88e3b7117bfe240a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Dec 2021 23:53:34 +0100 Subject: [PATCH 108/730] dma: Let st*_dma() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling st*_dma(). Keep the default MEMTXATTRS_UNSPECIFIED in the few callers. Reviewed-by: Richard Henderson Reviewed-by: Cédric Le Goater Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-16-philmd@redhat.com> --- hw/nvram/fw_cfg.c | 4 ++-- include/hw/pci/pci.h | 3 ++- include/hw/ppc/spapr_vio.h | 12 ++++++++---- include/sysemu/dma.h | 10 ++++++---- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 9b91b15cb0..e5f3c98184 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -360,7 +360,7 @@ static void fw_cfg_dma_transfer(FWCfgState *s) if (dma_memory_read(s->dma_as, dma_addr, &dma, sizeof(dma), MEMTXATTRS_UNSPECIFIED)) { stl_be_dma(s->dma_as, dma_addr + offsetof(FWCfgDmaAccess, control), - FW_CFG_DMA_CTL_ERROR); + FW_CFG_DMA_CTL_ERROR, MEMTXATTRS_UNSPECIFIED); return; } @@ -446,7 +446,7 @@ static void fw_cfg_dma_transfer(FWCfgState *s) } stl_be_dma(s->dma_as, dma_addr + offsetof(FWCfgDmaAccess, control), - dma.control); + dma.control, MEMTXATTRS_UNSPECIFIED); trace_fw_cfg_read(s, 0); } diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index a751ab5a75..d07e9707b4 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -859,7 +859,8 @@ static inline MemTxResult pci_dma_write(PCIDevice *dev, dma_addr_t addr, static inline void st##_s##_pci_dma(PCIDevice *dev, \ dma_addr_t addr, uint##_bits##_t val) \ { \ - st##_s##_dma(pci_get_address_space(dev), addr, val); \ + st##_s##_dma(pci_get_address_space(dev), addr, val, \ + MEMTXATTRS_UNSPECIFIED); \ } PCI_DMA_DEFINE_LDST(ub, b, 8); diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h index 5d2ea8e665..e87f8e6f59 100644 --- a/include/hw/ppc/spapr_vio.h +++ b/include/hw/ppc/spapr_vio.h @@ -118,10 +118,14 @@ static inline int spapr_vio_dma_set(SpaprVioDevice *dev, uint64_t taddr, H_DEST_PARM : H_SUCCESS; } -#define vio_stb(_dev, _addr, _val) (stb_dma(&(_dev)->as, (_addr), (_val))) -#define vio_sth(_dev, _addr, _val) (stw_be_dma(&(_dev)->as, (_addr), (_val))) -#define vio_stl(_dev, _addr, _val) (stl_be_dma(&(_dev)->as, (_addr), (_val))) -#define vio_stq(_dev, _addr, _val) (stq_be_dma(&(_dev)->as, (_addr), (_val))) +#define vio_stb(_dev, _addr, _val) \ + (stb_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED)) +#define vio_sth(_dev, _addr, _val) \ + (stw_be_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED)) +#define vio_stl(_dev, _addr, _val) \ + (stl_be_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED)) +#define vio_stq(_dev, _addr, _val) \ + (stq_be_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED)) #define vio_ldq(_dev, _addr) (ldq_be_dma(&(_dev)->as, (_addr))) int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq); diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index fd8f16003d..009dd3ca96 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -249,10 +249,11 @@ static inline void dma_memory_unmap(AddressSpace *as, } \ static inline void st##_sname##_##_end##_dma(AddressSpace *as, \ dma_addr_t addr, \ - uint##_bits##_t val) \ + uint##_bits##_t val, \ + MemTxAttrs attrs) \ { \ val = cpu_to_##_end##_bits(val); \ - dma_memory_write(as, addr, &val, (_bits) / 8, MEMTXATTRS_UNSPECIFIED); \ + dma_memory_write(as, addr, &val, (_bits) / 8, attrs); \ } static inline uint8_t ldub_dma(AddressSpace *as, dma_addr_t addr) @@ -263,9 +264,10 @@ static inline uint8_t ldub_dma(AddressSpace *as, dma_addr_t addr) return val; } -static inline void stb_dma(AddressSpace *as, dma_addr_t addr, uint8_t val) +static inline void stb_dma(AddressSpace *as, dma_addr_t addr, + uint8_t val, MemTxAttrs attrs) { - dma_memory_write(as, addr, &val, 1, MEMTXATTRS_UNSPECIFIED); + dma_memory_write(as, addr, &val, 1, attrs); } DEFINE_LDST_DMA(uw, w, 16, le); From 34cdea1db600540a5261dc474e986f28b637c8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Dec 2021 22:18:07 +0100 Subject: [PATCH 109/730] dma: Let ld*_dma() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling ld*_dma(). Keep the default MEMTXATTRS_UNSPECIFIED in the few callers. Reviewed-by: Richard Henderson Reviewed-by: Cédric Le Goater Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-17-philmd@redhat.com> --- hw/intc/pnv_xive.c | 7 ++++--- hw/usb/hcd-xhci.c | 6 +++--- include/hw/pci/pci.h | 3 ++- include/hw/ppc/spapr_vio.h | 3 ++- include/sysemu/dma.h | 11 ++++++----- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index ad43483612..d9249bbc0c 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -172,7 +172,7 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type, /* Get the page size of the indirect table. */ vsd_addr = vsd & VSD_ADDRESS_MASK; - vsd = ldq_be_dma(&address_space_memory, vsd_addr); + vsd = ldq_be_dma(&address_space_memory, vsd_addr, MEMTXATTRS_UNSPECIFIED); if (!(vsd & VSD_ADDRESS_MASK)) { #ifdef XIVE_DEBUG @@ -195,7 +195,8 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type, /* Load the VSD we are looking for, if not already done */ if (vsd_idx) { vsd_addr = vsd_addr + vsd_idx * XIVE_VSD_SIZE; - vsd = ldq_be_dma(&address_space_memory, vsd_addr); + vsd = ldq_be_dma(&address_space_memory, vsd_addr, + MEMTXATTRS_UNSPECIFIED); if (!(vsd & VSD_ADDRESS_MASK)) { #ifdef XIVE_DEBUG @@ -542,7 +543,7 @@ static uint64_t pnv_xive_vst_per_subpage(PnvXive *xive, uint32_t type) /* Get the page size of the indirect table. */ vsd_addr = vsd & VSD_ADDRESS_MASK; - vsd = ldq_be_dma(&address_space_memory, vsd_addr); + vsd = ldq_be_dma(&address_space_memory, vsd_addr, MEMTXATTRS_UNSPECIFIED); if (!(vsd & VSD_ADDRESS_MASK)) { #ifdef XIVE_DEBUG diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index ed2b9ea456..d960b81458 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2062,7 +2062,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, assert(slotid >= 1 && slotid <= xhci->numslots); dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high); - poctx = ldq_le_dma(xhci->as, dcbaap + 8 * slotid); + poctx = ldq_le_dma(xhci->as, dcbaap + 8 * slotid, MEMTXATTRS_UNSPECIFIED); ictx = xhci_mask64(pictx); octx = xhci_mask64(poctx); @@ -3437,8 +3437,8 @@ static int usb_xhci_post_load(void *opaque, int version_id) if (!slot->addressed) { continue; } - slot->ctx = - xhci_mask64(ldq_le_dma(xhci->as, dcbaap + 8 * slotid)); + slot->ctx = xhci_mask64(ldq_le_dma(xhci->as, dcbaap + 8 * slotid, + MEMTXATTRS_UNSPECIFIED)); xhci_dma_read_u32s(xhci, slot->ctx, slot_ctx, sizeof(slot_ctx)); slot->uport = xhci_lookup_uport(xhci, slot_ctx); if (!slot->uport) { diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index d07e9707b4..0613308b1b 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -854,7 +854,8 @@ static inline MemTxResult pci_dma_write(PCIDevice *dev, dma_addr_t addr, static inline uint##_bits##_t ld##_l##_pci_dma(PCIDevice *dev, \ dma_addr_t addr) \ { \ - return ld##_l##_dma(pci_get_address_space(dev), addr); \ + return ld##_l##_dma(pci_get_address_space(dev), addr, \ + MEMTXATTRS_UNSPECIFIED); \ } \ static inline void st##_s##_pci_dma(PCIDevice *dev, \ dma_addr_t addr, uint##_bits##_t val) \ diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h index e87f8e6f59..d2ec9b0637 100644 --- a/include/hw/ppc/spapr_vio.h +++ b/include/hw/ppc/spapr_vio.h @@ -126,7 +126,8 @@ static inline int spapr_vio_dma_set(SpaprVioDevice *dev, uint64_t taddr, (stl_be_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED)) #define vio_stq(_dev, _addr, _val) \ (stq_be_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED)) -#define vio_ldq(_dev, _addr) (ldq_be_dma(&(_dev)->as, (_addr))) +#define vio_ldq(_dev, _addr) \ + (ldq_be_dma(&(_dev)->as, (_addr), MEMTXATTRS_UNSPECIFIED)) int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq); diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 009dd3ca96..d1635f5587 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -241,10 +241,11 @@ static inline void dma_memory_unmap(AddressSpace *as, #define DEFINE_LDST_DMA(_lname, _sname, _bits, _end) \ static inline uint##_bits##_t ld##_lname##_##_end##_dma(AddressSpace *as, \ - dma_addr_t addr) \ + dma_addr_t addr, \ + MemTxAttrs attrs) \ { \ uint##_bits##_t val; \ - dma_memory_read(as, addr, &val, (_bits) / 8, MEMTXATTRS_UNSPECIFIED); \ + dma_memory_read(as, addr, &val, (_bits) / 8, attrs); \ return _end##_bits##_to_cpu(val); \ } \ static inline void st##_sname##_##_end##_dma(AddressSpace *as, \ @@ -253,14 +254,14 @@ static inline void dma_memory_unmap(AddressSpace *as, MemTxAttrs attrs) \ { \ val = cpu_to_##_end##_bits(val); \ - dma_memory_write(as, addr, &val, (_bits) / 8, attrs); \ + dma_memory_write(as, addr, &val, (_bits) / 8, attrs); \ } -static inline uint8_t ldub_dma(AddressSpace *as, dma_addr_t addr) +static inline uint8_t ldub_dma(AddressSpace *as, dma_addr_t addr, MemTxAttrs attrs) { uint8_t val; - dma_memory_read(as, addr, &val, 1, MEMTXATTRS_UNSPECIFIED); + dma_memory_read(as, addr, &val, 1, attrs); return val; } From 24aed6bcb6b6d266149591f955c2460c28759eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Dec 2021 23:56:14 +0100 Subject: [PATCH 110/730] dma: Let st*_dma() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dma_memory_write() returns a MemTxResult type. Do not discard it, return it to the caller. Reviewed-by: Richard Henderson Reviewed-by: Cédric Le Goater Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-18-philmd@redhat.com> --- include/sysemu/dma.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index d1635f5587..895044d747 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -248,13 +248,13 @@ static inline void dma_memory_unmap(AddressSpace *as, dma_memory_read(as, addr, &val, (_bits) / 8, attrs); \ return _end##_bits##_to_cpu(val); \ } \ - static inline void st##_sname##_##_end##_dma(AddressSpace *as, \ - dma_addr_t addr, \ - uint##_bits##_t val, \ - MemTxAttrs attrs) \ - { \ - val = cpu_to_##_end##_bits(val); \ - dma_memory_write(as, addr, &val, (_bits) / 8, attrs); \ + static inline MemTxResult st##_sname##_##_end##_dma(AddressSpace *as, \ + dma_addr_t addr, \ + uint##_bits##_t val, \ + MemTxAttrs attrs) \ + { \ + val = cpu_to_##_end##_bits(val); \ + return dma_memory_write(as, addr, &val, (_bits) / 8, attrs); \ } static inline uint8_t ldub_dma(AddressSpace *as, dma_addr_t addr, MemTxAttrs attrs) @@ -265,10 +265,10 @@ static inline uint8_t ldub_dma(AddressSpace *as, dma_addr_t addr, MemTxAttrs att return val; } -static inline void stb_dma(AddressSpace *as, dma_addr_t addr, - uint8_t val, MemTxAttrs attrs) +static inline MemTxResult stb_dma(AddressSpace *as, dma_addr_t addr, + uint8_t val, MemTxAttrs attrs) { - dma_memory_write(as, addr, &val, 1, attrs); + return dma_memory_write(as, addr, &val, 1, attrs); } DEFINE_LDST_DMA(uw, w, 16, le); From cd1db8df7431edd2210ed0123e2e09b9b6d1e621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Dec 2021 22:31:11 +0100 Subject: [PATCH 111/730] dma: Let ld*_dma() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dma_memory_read() returns a MemTxResult type. Do not discard it, return it to the caller. Update the few callers. Reviewed-by: Richard Henderson Reviewed-by: Cédric Le Goater Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-19-philmd@redhat.com> --- hw/intc/pnv_xive.c | 8 ++++---- hw/usb/hcd-xhci.c | 7 ++++--- include/hw/pci/pci.h | 6 ++++-- include/hw/ppc/spapr_vio.h | 6 +++++- include/sysemu/dma.h | 25 ++++++++++++------------- 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/hw/intc/pnv_xive.c b/hw/intc/pnv_xive.c index d9249bbc0c..bb207514f2 100644 --- a/hw/intc/pnv_xive.c +++ b/hw/intc/pnv_xive.c @@ -172,7 +172,7 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type, /* Get the page size of the indirect table. */ vsd_addr = vsd & VSD_ADDRESS_MASK; - vsd = ldq_be_dma(&address_space_memory, vsd_addr, MEMTXATTRS_UNSPECIFIED); + ldq_be_dma(&address_space_memory, vsd_addr, &vsd, MEMTXATTRS_UNSPECIFIED); if (!(vsd & VSD_ADDRESS_MASK)) { #ifdef XIVE_DEBUG @@ -195,8 +195,8 @@ static uint64_t pnv_xive_vst_addr_indirect(PnvXive *xive, uint32_t type, /* Load the VSD we are looking for, if not already done */ if (vsd_idx) { vsd_addr = vsd_addr + vsd_idx * XIVE_VSD_SIZE; - vsd = ldq_be_dma(&address_space_memory, vsd_addr, - MEMTXATTRS_UNSPECIFIED); + ldq_be_dma(&address_space_memory, vsd_addr, &vsd, + MEMTXATTRS_UNSPECIFIED); if (!(vsd & VSD_ADDRESS_MASK)) { #ifdef XIVE_DEBUG @@ -543,7 +543,7 @@ static uint64_t pnv_xive_vst_per_subpage(PnvXive *xive, uint32_t type) /* Get the page size of the indirect table. */ vsd_addr = vsd & VSD_ADDRESS_MASK; - vsd = ldq_be_dma(&address_space_memory, vsd_addr, MEMTXATTRS_UNSPECIFIED); + ldq_be_dma(&address_space_memory, vsd_addr, &vsd, MEMTXATTRS_UNSPECIFIED); if (!(vsd & VSD_ADDRESS_MASK)) { #ifdef XIVE_DEBUG diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index d960b81458..da5a407210 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -2062,7 +2062,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid, assert(slotid >= 1 && slotid <= xhci->numslots); dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high); - poctx = ldq_le_dma(xhci->as, dcbaap + 8 * slotid, MEMTXATTRS_UNSPECIFIED); + ldq_le_dma(xhci->as, dcbaap + 8 * slotid, &poctx, MEMTXATTRS_UNSPECIFIED); ictx = xhci_mask64(pictx); octx = xhci_mask64(poctx); @@ -3429,6 +3429,7 @@ static int usb_xhci_post_load(void *opaque, int version_id) uint32_t slot_ctx[4]; uint32_t ep_ctx[5]; int slotid, epid, state; + uint64_t addr; dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high); @@ -3437,8 +3438,8 @@ static int usb_xhci_post_load(void *opaque, int version_id) if (!slot->addressed) { continue; } - slot->ctx = xhci_mask64(ldq_le_dma(xhci->as, dcbaap + 8 * slotid, - MEMTXATTRS_UNSPECIFIED)); + ldq_le_dma(xhci->as, dcbaap + 8 * slotid, &addr, MEMTXATTRS_UNSPECIFIED); + slot->ctx = xhci_mask64(addr); xhci_dma_read_u32s(xhci, slot->ctx, slot_ctx, sizeof(slot_ctx)); slot->uport = xhci_lookup_uport(xhci, slot_ctx); if (!slot->uport) { diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 0613308b1b..8c5f2ed505 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -854,8 +854,10 @@ static inline MemTxResult pci_dma_write(PCIDevice *dev, dma_addr_t addr, static inline uint##_bits##_t ld##_l##_pci_dma(PCIDevice *dev, \ dma_addr_t addr) \ { \ - return ld##_l##_dma(pci_get_address_space(dev), addr, \ - MEMTXATTRS_UNSPECIFIED); \ + uint##_bits##_t val; \ + ld##_l##_dma(pci_get_address_space(dev), addr, &val, \ + MEMTXATTRS_UNSPECIFIED); \ + return val; \ } \ static inline void st##_s##_pci_dma(PCIDevice *dev, \ dma_addr_t addr, uint##_bits##_t val) \ diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h index d2ec9b0637..7eae1a4847 100644 --- a/include/hw/ppc/spapr_vio.h +++ b/include/hw/ppc/spapr_vio.h @@ -127,7 +127,11 @@ static inline int spapr_vio_dma_set(SpaprVioDevice *dev, uint64_t taddr, #define vio_stq(_dev, _addr, _val) \ (stq_be_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED)) #define vio_ldq(_dev, _addr) \ - (ldq_be_dma(&(_dev)->as, (_addr), MEMTXATTRS_UNSPECIFIED)) + ({ \ + uint64_t _val; \ + ldq_be_dma(&(_dev)->as, (_addr), &_val, MEMTXATTRS_UNSPECIFIED); \ + _val; \ + }) int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq); diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 895044d747..b3faef41b2 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -240,14 +240,15 @@ static inline void dma_memory_unmap(AddressSpace *as, } #define DEFINE_LDST_DMA(_lname, _sname, _bits, _end) \ - static inline uint##_bits##_t ld##_lname##_##_end##_dma(AddressSpace *as, \ - dma_addr_t addr, \ - MemTxAttrs attrs) \ - { \ - uint##_bits##_t val; \ - dma_memory_read(as, addr, &val, (_bits) / 8, attrs); \ - return _end##_bits##_to_cpu(val); \ - } \ + static inline MemTxResult ld##_lname##_##_end##_dma(AddressSpace *as, \ + dma_addr_t addr, \ + uint##_bits##_t *pval, \ + MemTxAttrs attrs) \ + { \ + MemTxResult res = dma_memory_read(as, addr, pval, (_bits) / 8, attrs); \ + _end##_bits##_to_cpus(pval); \ + return res; \ + } \ static inline MemTxResult st##_sname##_##_end##_dma(AddressSpace *as, \ dma_addr_t addr, \ uint##_bits##_t val, \ @@ -257,12 +258,10 @@ static inline void dma_memory_unmap(AddressSpace *as, return dma_memory_write(as, addr, &val, (_bits) / 8, attrs); \ } -static inline uint8_t ldub_dma(AddressSpace *as, dma_addr_t addr, MemTxAttrs attrs) +static inline MemTxResult ldub_dma(AddressSpace *as, dma_addr_t addr, + uint8_t *val, MemTxAttrs attrs) { - uint8_t val; - - dma_memory_read(as, addr, &val, 1, attrs); - return val; + return dma_memory_read(as, addr, val, 1, attrs); } static inline MemTxResult stb_dma(AddressSpace *as, dma_addr_t addr, From a423a1b523296f8798a5851aaaba64dd166c0a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Dec 2021 22:39:42 +0100 Subject: [PATCH 112/730] pci: Let st*_pci_dma() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling st*_pci_dma(). Keep the default MEMTXATTRS_UNSPECIFIED in the few callers. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-21-philmd@redhat.com> --- hw/audio/intel-hda.c | 10 ++++++---- hw/net/eepro100.c | 29 ++++++++++++++++++----------- hw/net/tulip.c | 18 ++++++++++-------- hw/scsi/megasas.c | 15 ++++++++++----- hw/scsi/vmw_pvscsi.c | 3 ++- include/hw/pci/pci.h | 11 ++++++----- 6 files changed, 52 insertions(+), 34 deletions(-) diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index fb3d34a4a0..3309ae0ea1 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -345,6 +345,7 @@ static void intel_hda_corb_run(IntelHDAState *d) static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t response) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus); IntelHDAState *d = container_of(bus, IntelHDAState, codecs); hwaddr addr; @@ -367,8 +368,8 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res ex = (solicited ? 0 : (1 << 4)) | dev->cad; wp = (d->rirb_wp + 1) & 0xff; addr = intel_hda_addr(d->rirb_lbase, d->rirb_ubase); - stl_le_pci_dma(&d->pci, addr + 8*wp, response); - stl_le_pci_dma(&d->pci, addr + 8*wp + 4, ex); + stl_le_pci_dma(&d->pci, addr + 8 * wp, response, attrs); + stl_le_pci_dma(&d->pci, addr + 8 * wp + 4, ex, attrs); d->rirb_wp = wp; dprint(d, 2, "%s: [wp 0x%x] response 0x%x, extra 0x%x\n", @@ -394,6 +395,7 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output, uint8_t *buf, uint32_t len) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus); IntelHDAState *d = container_of(bus, IntelHDAState, codecs); hwaddr addr; @@ -428,7 +430,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output, st->be, st->bp, st->bpl[st->be].len, copy); pci_dma_rw(&d->pci, st->bpl[st->be].addr + st->bp, buf, copy, !output, - MEMTXATTRS_UNSPECIFIED); + attrs); st->lpib += copy; st->bp += copy; buf += copy; @@ -451,7 +453,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output, if (d->dp_lbase & 0x01) { s = st - d->st; addr = intel_hda_addr(d->dp_lbase & ~0x01, d->dp_ubase); - stl_le_pci_dma(&d->pci, addr + 8*s, st->lpib); + stl_le_pci_dma(&d->pci, addr + 8 * s, st->lpib, attrs); } dprint(d, 3, "dma: --\n"); diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index 16e95ef9cc..83c4431b1a 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -700,6 +700,8 @@ static void set_ru_state(EEPRO100State * s, ru_state_t state) static void dump_statistics(EEPRO100State * s) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; + /* Dump statistical data. Most data is never changed by the emulation * and always 0, so we first just copy the whole block and then those * values which really matter. @@ -707,16 +709,18 @@ static void dump_statistics(EEPRO100State * s) */ pci_dma_write(&s->dev, s->statsaddr, &s->statistics, s->stats_size); stl_le_pci_dma(&s->dev, s->statsaddr + 0, - s->statistics.tx_good_frames); + s->statistics.tx_good_frames, attrs); stl_le_pci_dma(&s->dev, s->statsaddr + 36, - s->statistics.rx_good_frames); + s->statistics.rx_good_frames, attrs); stl_le_pci_dma(&s->dev, s->statsaddr + 48, - s->statistics.rx_resource_errors); + s->statistics.rx_resource_errors, attrs); stl_le_pci_dma(&s->dev, s->statsaddr + 60, - s->statistics.rx_short_frame_errors); + s->statistics.rx_short_frame_errors, attrs); #if 0 - stw_le_pci_dma(&s->dev, s->statsaddr + 76, s->statistics.xmt_tco_frames); - stw_le_pci_dma(&s->dev, s->statsaddr + 78, s->statistics.rcv_tco_frames); + stw_le_pci_dma(&s->dev, s->statsaddr + 76, + s->statistics.xmt_tco_frames, attrs); + stw_le_pci_dma(&s->dev, s->statsaddr + 78, + s->statistics.rcv_tco_frames, attrs); missing("CU dump statistical counters"); #endif } @@ -833,6 +837,7 @@ static void set_multicast_list(EEPRO100State *s) static void action_command(EEPRO100State *s) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; /* The loop below won't stop if it gets special handcrafted data. Therefore we limit the number of iterations. */ unsigned max_loop_count = 16; @@ -911,7 +916,7 @@ static void action_command(EEPRO100State *s) } /* Write new status. */ stw_le_pci_dma(&s->dev, s->cb_address, - s->tx.status | ok_status | STATUS_C); + s->tx.status | ok_status | STATUS_C, attrs); if (bit_i) { /* CU completed action. */ eepro100_cx_interrupt(s); @@ -937,6 +942,7 @@ static void action_command(EEPRO100State *s) static void eepro100_cu_command(EEPRO100State * s, uint8_t val) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; cu_state_t cu_state; switch (val) { case CU_NOP: @@ -986,7 +992,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) /* Dump statistical counters. */ TRACE(OTHER, logout("val=0x%02x (dump stats)\n", val)); dump_statistics(s); - stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa005); + stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa005, attrs); break; case CU_CMD_BASE: /* Load CU base. */ @@ -997,7 +1003,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) /* Dump and reset statistical counters. */ TRACE(OTHER, logout("val=0x%02x (dump stats and reset)\n", val)); dump_statistics(s); - stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa007); + stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa007, attrs); memset(&s->statistics, 0, sizeof(s->statistics)); break; case CU_SRESUME: @@ -1612,6 +1618,7 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) * - Magic packets should set bit 30 in power management driver register. * - Interesting packets should set bit 29 in power management driver register. */ + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; EEPRO100State *s = qemu_get_nic_opaque(nc); uint16_t rfd_status = 0xa000; #if defined(CONFIG_PAD_RECEIVED_FRAMES) @@ -1726,9 +1733,9 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size) TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n", rfd_command, rx.link, rx.rx_buf_addr, rfd_size)); stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset + - offsetof(eepro100_rx_t, status), rfd_status); + offsetof(eepro100_rx_t, status), rfd_status, attrs); stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset + - offsetof(eepro100_rx_t, count), size); + offsetof(eepro100_rx_t, count), size, attrs); /* Early receive interrupt not supported. */ #if 0 eepro100_er_interrupt(s); diff --git a/hw/net/tulip.c b/hw/net/tulip.c index ca69f7ea5e..1f2c79dd58 100644 --- a/hw/net/tulip.c +++ b/hw/net/tulip.c @@ -86,16 +86,18 @@ static void tulip_desc_read(TULIPState *s, hwaddr p, static void tulip_desc_write(TULIPState *s, hwaddr p, struct tulip_descriptor *desc) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; + if (s->csr[0] & CSR0_DBO) { - stl_be_pci_dma(&s->dev, p, desc->status); - stl_be_pci_dma(&s->dev, p + 4, desc->control); - stl_be_pci_dma(&s->dev, p + 8, desc->buf_addr1); - stl_be_pci_dma(&s->dev, p + 12, desc->buf_addr2); + stl_be_pci_dma(&s->dev, p, desc->status, attrs); + stl_be_pci_dma(&s->dev, p + 4, desc->control, attrs); + stl_be_pci_dma(&s->dev, p + 8, desc->buf_addr1, attrs); + stl_be_pci_dma(&s->dev, p + 12, desc->buf_addr2, attrs); } else { - stl_le_pci_dma(&s->dev, p, desc->status); - stl_le_pci_dma(&s->dev, p + 4, desc->control); - stl_le_pci_dma(&s->dev, p + 8, desc->buf_addr1); - stl_le_pci_dma(&s->dev, p + 12, desc->buf_addr2); + stl_le_pci_dma(&s->dev, p, desc->status, attrs); + stl_le_pci_dma(&s->dev, p + 4, desc->control, attrs); + stl_le_pci_dma(&s->dev, p + 8, desc->buf_addr1, attrs); + stl_le_pci_dma(&s->dev, p + 12, desc->buf_addr2, attrs); } } diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 091a350e05..b5e8b145c5 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -168,14 +168,16 @@ static void megasas_frame_set_cmd_status(MegasasState *s, unsigned long frame, uint8_t v) { PCIDevice *pci = &s->parent_obj; - stb_pci_dma(pci, frame + offsetof(struct mfi_frame_header, cmd_status), v); + stb_pci_dma(pci, frame + offsetof(struct mfi_frame_header, cmd_status), + v, MEMTXATTRS_UNSPECIFIED); } static void megasas_frame_set_scsi_status(MegasasState *s, unsigned long frame, uint8_t v) { PCIDevice *pci = &s->parent_obj; - stb_pci_dma(pci, frame + offsetof(struct mfi_frame_header, scsi_status), v); + stb_pci_dma(pci, frame + offsetof(struct mfi_frame_header, scsi_status), + v, MEMTXATTRS_UNSPECIFIED); } static inline const char *mfi_frame_desc(unsigned int cmd) @@ -542,6 +544,7 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s, static void megasas_complete_frame(MegasasState *s, uint64_t context) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; PCIDevice *pci_dev = PCI_DEVICE(s); int tail, queue_offset; @@ -555,10 +558,12 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context) */ if (megasas_use_queue64(s)) { queue_offset = s->reply_queue_head * sizeof(uint64_t); - stq_le_pci_dma(pci_dev, s->reply_queue_pa + queue_offset, context); + stq_le_pci_dma(pci_dev, s->reply_queue_pa + queue_offset, + context, attrs); } else { queue_offset = s->reply_queue_head * sizeof(uint32_t); - stl_le_pci_dma(pci_dev, s->reply_queue_pa + queue_offset, context); + stl_le_pci_dma(pci_dev, s->reply_queue_pa + queue_offset, + context, attrs); } s->reply_queue_tail = ldl_le_pci_dma(pci_dev, s->consumer_pa); trace_megasas_qf_complete(context, s->reply_queue_head, @@ -572,7 +577,7 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context) s->reply_queue_head = megasas_next_index(s, tail, s->fw_cmds); trace_megasas_qf_update(s->reply_queue_head, s->reply_queue_tail, s->busy); - stl_le_pci_dma(pci_dev, s->producer_pa, s->reply_queue_head); + stl_le_pci_dma(pci_dev, s->producer_pa, s->reply_queue_head, attrs); /* Notify HBA */ if (msix_enabled(pci_dev)) { trace_megasas_msix_raise(0); diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index cd76bd67ab..59c3e8ba04 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -55,7 +55,8 @@ (m)->rs_pa + offsetof(struct PVSCSIRingsState, field))) #define RS_SET_FIELD(m, field, val) \ (stl_le_pci_dma(&container_of(m, PVSCSIState, rings)->parent_obj, \ - (m)->rs_pa + offsetof(struct PVSCSIRingsState, field), val)) + (m)->rs_pa + offsetof(struct PVSCSIRingsState, field), val, \ + MEMTXATTRS_UNSPECIFIED)) struct PVSCSIClass { PCIDeviceClass parent_class; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 8c5f2ed505..9f51ef2c3c 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -859,11 +859,12 @@ static inline MemTxResult pci_dma_write(PCIDevice *dev, dma_addr_t addr, MEMTXATTRS_UNSPECIFIED); \ return val; \ } \ - static inline void st##_s##_pci_dma(PCIDevice *dev, \ - dma_addr_t addr, uint##_bits##_t val) \ - { \ - st##_s##_dma(pci_get_address_space(dev), addr, val, \ - MEMTXATTRS_UNSPECIFIED); \ + static inline void st##_s##_pci_dma(PCIDevice *dev, \ + dma_addr_t addr, \ + uint##_bits##_t val, \ + MemTxAttrs attrs) \ + { \ + st##_s##_dma(pci_get_address_space(dev), addr, val, attrs); \ } PCI_DMA_DEFINE_LDST(ub, b, 8); From 398f9a84ac7132e38caf7b066273734b3bf619ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Dec 2021 23:45:06 +0100 Subject: [PATCH 113/730] pci: Let ld*_pci_dma() take MemTxAttrs argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let devices specify transaction attributes when calling ld*_pci_dma(). Keep the default MEMTXATTRS_UNSPECIFIED in the few callers. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-22-philmd@redhat.com> --- hw/audio/intel-hda.c | 2 +- hw/net/eepro100.c | 19 +++++++++++++------ hw/net/tulip.c | 18 ++++++++++-------- hw/scsi/megasas.c | 16 ++++++++++------ hw/scsi/mptsas.c | 10 ++++++---- hw/scsi/vmw_pvscsi.c | 3 ++- hw/usb/hcd-xhci.c | 1 + include/hw/pci/pci.h | 6 +++--- 8 files changed, 46 insertions(+), 29 deletions(-) diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index 3309ae0ea1..e34b7ab0e9 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -335,7 +335,7 @@ static void intel_hda_corb_run(IntelHDAState *d) rp = (d->corb_rp + 1) & 0xff; addr = intel_hda_addr(d->corb_lbase, d->corb_ubase); - verb = ldl_le_pci_dma(&d->pci, addr + 4*rp); + verb = ldl_le_pci_dma(&d->pci, addr + 4 * rp, MEMTXATTRS_UNSPECIFIED); d->corb_rp = rp; dprint(d, 2, "%s: [rp 0x%x] verb 0x%08x\n", __func__, rp, verb); diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index 83c4431b1a..eb82e9cb11 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -737,6 +737,7 @@ static void read_cb(EEPRO100State *s) static void tx_command(EEPRO100State *s) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; uint32_t tbd_array = s->tx.tbd_array_addr; uint16_t tcb_bytes = s->tx.tcb_bytes & 0x3fff; /* Sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes. */ @@ -772,11 +773,14 @@ static void tx_command(EEPRO100State *s) /* Extended Flexible TCB. */ for (; tbd_count < 2; tbd_count++) { uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, - tbd_address); + tbd_address, + attrs); uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, - tbd_address + 4); + tbd_address + 4, + attrs); uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, - tbd_address + 6); + tbd_address + 6, + attrs); tbd_address += 8; TRACE(RXTX, logout ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n", @@ -792,9 +796,12 @@ static void tx_command(EEPRO100State *s) } tbd_address = tbd_array; for (; tbd_count < s->tx.tbd_count; tbd_count++) { - uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address); - uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4); - uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6); + uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address, + attrs); + uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4, + attrs); + uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6, + attrs); tbd_address += 8; TRACE(RXTX, logout ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n", diff --git a/hw/net/tulip.c b/hw/net/tulip.c index 1f2c79dd58..c76e4868f7 100644 --- a/hw/net/tulip.c +++ b/hw/net/tulip.c @@ -70,16 +70,18 @@ static const VMStateDescription vmstate_pci_tulip = { static void tulip_desc_read(TULIPState *s, hwaddr p, struct tulip_descriptor *desc) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; + if (s->csr[0] & CSR0_DBO) { - desc->status = ldl_be_pci_dma(&s->dev, p); - desc->control = ldl_be_pci_dma(&s->dev, p + 4); - desc->buf_addr1 = ldl_be_pci_dma(&s->dev, p + 8); - desc->buf_addr2 = ldl_be_pci_dma(&s->dev, p + 12); + desc->status = ldl_be_pci_dma(&s->dev, p, attrs); + desc->control = ldl_be_pci_dma(&s->dev, p + 4, attrs); + desc->buf_addr1 = ldl_be_pci_dma(&s->dev, p + 8, attrs); + desc->buf_addr2 = ldl_be_pci_dma(&s->dev, p + 12, attrs); } else { - desc->status = ldl_le_pci_dma(&s->dev, p); - desc->control = ldl_le_pci_dma(&s->dev, p + 4); - desc->buf_addr1 = ldl_le_pci_dma(&s->dev, p + 8); - desc->buf_addr2 = ldl_le_pci_dma(&s->dev, p + 12); + desc->status = ldl_le_pci_dma(&s->dev, p, attrs); + desc->control = ldl_le_pci_dma(&s->dev, p + 4, attrs); + desc->buf_addr1 = ldl_le_pci_dma(&s->dev, p + 8, attrs); + desc->buf_addr2 = ldl_le_pci_dma(&s->dev, p + 12, attrs); } } diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index b5e8b145c5..98b13708c1 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -202,7 +202,9 @@ static uint64_t megasas_frame_get_context(MegasasState *s, unsigned long frame) { PCIDevice *pci = &s->parent_obj; - return ldq_le_pci_dma(pci, frame + offsetof(struct mfi_frame_header, context)); + return ldq_le_pci_dma(pci, + frame + offsetof(struct mfi_frame_header, context), + MEMTXATTRS_UNSPECIFIED); } static bool megasas_frame_is_ieee_sgl(MegasasCmd *cmd) @@ -534,7 +536,8 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s, s->busy++; if (s->consumer_pa) { - s->reply_queue_tail = ldl_le_pci_dma(pcid, s->consumer_pa); + s->reply_queue_tail = ldl_le_pci_dma(pcid, s->consumer_pa, + MEMTXATTRS_UNSPECIFIED); } trace_megasas_qf_enqueue(cmd->index, cmd->count, cmd->context, s->reply_queue_head, s->reply_queue_tail, s->busy); @@ -565,14 +568,14 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context) stl_le_pci_dma(pci_dev, s->reply_queue_pa + queue_offset, context, attrs); } - s->reply_queue_tail = ldl_le_pci_dma(pci_dev, s->consumer_pa); + s->reply_queue_tail = ldl_le_pci_dma(pci_dev, s->consumer_pa, attrs); trace_megasas_qf_complete(context, s->reply_queue_head, s->reply_queue_tail, s->busy); } if (megasas_intr_enabled(s)) { /* Update reply queue pointer */ - s->reply_queue_tail = ldl_le_pci_dma(pci_dev, s->consumer_pa); + s->reply_queue_tail = ldl_le_pci_dma(pci_dev, s->consumer_pa, attrs); tail = s->reply_queue_head; s->reply_queue_head = megasas_next_index(s, tail, s->fw_cmds); trace_megasas_qf_update(s->reply_queue_head, s->reply_queue_tail, @@ -637,6 +640,7 @@ static void megasas_abort_command(MegasasCmd *cmd) static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; PCIDevice *pcid = PCI_DEVICE(s); uint32_t pa_hi, pa_lo; hwaddr iq_pa, initq_size = sizeof(struct mfi_init_qinfo); @@ -675,9 +679,9 @@ static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd) pa_lo = le32_to_cpu(initq->pi_addr_lo); pa_hi = le32_to_cpu(initq->pi_addr_hi); s->producer_pa = ((uint64_t) pa_hi << 32) | pa_lo; - s->reply_queue_head = ldl_le_pci_dma(pcid, s->producer_pa); + s->reply_queue_head = ldl_le_pci_dma(pcid, s->producer_pa, attrs); s->reply_queue_head %= MEGASAS_MAX_FRAMES; - s->reply_queue_tail = ldl_le_pci_dma(pcid, s->consumer_pa); + s->reply_queue_tail = ldl_le_pci_dma(pcid, s->consumer_pa, attrs); s->reply_queue_tail %= MEGASAS_MAX_FRAMES; flags = le32_to_cpu(initq->flags); if (flags & MFI_QUEUE_FLAG_CONTEXT64) { diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c index f6c7765544..ac9f4dfcd2 100644 --- a/hw/scsi/mptsas.c +++ b/hw/scsi/mptsas.c @@ -172,14 +172,15 @@ static const int mpi_request_sizes[] = { static dma_addr_t mptsas_ld_sg_base(MPTSASState *s, uint32_t flags_and_length, dma_addr_t *sgaddr) { + const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; PCIDevice *pci = (PCIDevice *) s; dma_addr_t addr; if (flags_and_length & MPI_SGE_FLAGS_64_BIT_ADDRESSING) { - addr = ldq_le_pci_dma(pci, *sgaddr + 4); + addr = ldq_le_pci_dma(pci, *sgaddr + 4, attrs); *sgaddr += 12; } else { - addr = ldl_le_pci_dma(pci, *sgaddr + 4); + addr = ldl_le_pci_dma(pci, *sgaddr + 4, attrs); *sgaddr += 8; } return addr; @@ -203,7 +204,7 @@ static int mptsas_build_sgl(MPTSASState *s, MPTSASRequest *req, hwaddr addr) dma_addr_t addr, len; uint32_t flags_and_length; - flags_and_length = ldl_le_pci_dma(pci, sgaddr); + flags_and_length = ldl_le_pci_dma(pci, sgaddr, MEMTXATTRS_UNSPECIFIED); len = flags_and_length & MPI_SGE_LENGTH_MASK; if ((flags_and_length & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) != MPI_SGE_FLAGS_SIMPLE_ELEMENT || @@ -234,7 +235,8 @@ static int mptsas_build_sgl(MPTSASState *s, MPTSASRequest *req, hwaddr addr) break; } - flags_and_length = ldl_le_pci_dma(pci, next_chain_addr); + flags_and_length = ldl_le_pci_dma(pci, next_chain_addr, + MEMTXATTRS_UNSPECIFIED); if ((flags_and_length & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) != MPI_SGE_FLAGS_CHAIN_ELEMENT) { return MPI_IOCSTATUS_INVALID_SGL; diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index 59c3e8ba04..33e16f9111 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -52,7 +52,8 @@ #define RS_GET_FIELD(m, field) \ (ldl_le_pci_dma(&container_of(m, PVSCSIState, rings)->parent_obj, \ - (m)->rs_pa + offsetof(struct PVSCSIRingsState, field))) + (m)->rs_pa + offsetof(struct PVSCSIRingsState, field), \ + MEMTXATTRS_UNSPECIFIED)) #define RS_SET_FIELD(m, field, val) \ (stl_le_pci_dma(&container_of(m, PVSCSIState, rings)->parent_obj, \ (m)->rs_pa + offsetof(struct PVSCSIRingsState, field), val, \ diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index da5a407210..14bdb89676 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -3440,6 +3440,7 @@ static int usb_xhci_post_load(void *opaque, int version_id) } ldq_le_dma(xhci->as, dcbaap + 8 * slotid, &addr, MEMTXATTRS_UNSPECIFIED); slot->ctx = xhci_mask64(addr); + xhci_dma_read_u32s(xhci, slot->ctx, slot_ctx, sizeof(slot_ctx)); slot->uport = xhci_lookup_uport(xhci, slot_ctx); if (!slot->uport) { diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 9f51ef2c3c..7a46c1fa22 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -852,11 +852,11 @@ static inline MemTxResult pci_dma_write(PCIDevice *dev, dma_addr_t addr, #define PCI_DMA_DEFINE_LDST(_l, _s, _bits) \ static inline uint##_bits##_t ld##_l##_pci_dma(PCIDevice *dev, \ - dma_addr_t addr) \ + dma_addr_t addr, \ + MemTxAttrs attrs) \ { \ uint##_bits##_t val; \ - ld##_l##_dma(pci_get_address_space(dev), addr, &val, \ - MEMTXATTRS_UNSPECIFIED); \ + ld##_l##_dma(pci_get_address_space(dev), addr, &val, attrs); \ return val; \ } \ static inline void st##_s##_pci_dma(PCIDevice *dev, \ From 6bebb270731758fae3114b7d24c2b12b7c325cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Dec 2021 23:47:30 +0100 Subject: [PATCH 114/730] pci: Let st*_pci_dma() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit st*_dma() returns a MemTxResult type. Do not discard it, return it to the caller. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-23-philmd@redhat.com> --- include/hw/pci/pci.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 7a46c1fa22..c90cecc85c 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -859,12 +859,12 @@ static inline MemTxResult pci_dma_write(PCIDevice *dev, dma_addr_t addr, ld##_l##_dma(pci_get_address_space(dev), addr, &val, attrs); \ return val; \ } \ - static inline void st##_s##_pci_dma(PCIDevice *dev, \ - dma_addr_t addr, \ - uint##_bits##_t val, \ - MemTxAttrs attrs) \ + static inline MemTxResult st##_s##_pci_dma(PCIDevice *dev, \ + dma_addr_t addr, \ + uint##_bits##_t val, \ + MemTxAttrs attrs) \ { \ - st##_s##_dma(pci_get_address_space(dev), addr, val, attrs); \ + return st##_s##_dma(pci_get_address_space(dev), addr, val, attrs); \ } PCI_DMA_DEFINE_LDST(ub, b, 8); From 4a63054bce23982b99f4d3c65528e47e614086b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 17 Dec 2021 23:49:30 +0100 Subject: [PATCH 115/730] pci: Let ld*_pci_dma() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ld*_dma() returns a MemTxResult type. Do not discard it, return it to the caller. Update the few callers. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211223115554.3155328-24-philmd@redhat.com> --- hw/audio/intel-hda.c | 2 +- hw/net/eepro100.c | 25 ++++++++++--------------- hw/net/tulip.c | 16 ++++++++-------- hw/scsi/megasas.c | 21 ++++++++++++--------- hw/scsi/mptsas.c | 16 +++++++++++----- hw/scsi/vmw_pvscsi.c | 16 ++++++++++------ include/hw/pci/pci.h | 17 ++++++++--------- 7 files changed, 60 insertions(+), 53 deletions(-) diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index e34b7ab0e9..2b55d52150 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -335,7 +335,7 @@ static void intel_hda_corb_run(IntelHDAState *d) rp = (d->corb_rp + 1) & 0xff; addr = intel_hda_addr(d->corb_lbase, d->corb_ubase); - verb = ldl_le_pci_dma(&d->pci, addr + 4 * rp, MEMTXATTRS_UNSPECIFIED); + ldl_le_pci_dma(&d->pci, addr + 4 * rp, &verb, MEMTXATTRS_UNSPECIFIED); d->corb_rp = rp; dprint(d, 2, "%s: [rp 0x%x] verb 0x%08x\n", __func__, rp, verb); diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index eb82e9cb11..679f52f80f 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -769,18 +769,16 @@ static void tx_command(EEPRO100State *s) } else { /* Flexible mode. */ uint8_t tbd_count = 0; + uint32_t tx_buffer_address; + uint16_t tx_buffer_size; + uint16_t tx_buffer_el; + if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) { /* Extended Flexible TCB. */ for (; tbd_count < 2; tbd_count++) { - uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, - tbd_address, - attrs); - uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, - tbd_address + 4, - attrs); - uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, - tbd_address + 6, - attrs); + ldl_le_pci_dma(&s->dev, tbd_address, &tx_buffer_address, attrs); + lduw_le_pci_dma(&s->dev, tbd_address + 4, &tx_buffer_size, attrs); + lduw_le_pci_dma(&s->dev, tbd_address + 6, &tx_buffer_el, attrs); tbd_address += 8; TRACE(RXTX, logout ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n", @@ -796,12 +794,9 @@ static void tx_command(EEPRO100State *s) } tbd_address = tbd_array; for (; tbd_count < s->tx.tbd_count; tbd_count++) { - uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address, - attrs); - uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4, - attrs); - uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6, - attrs); + ldl_le_pci_dma(&s->dev, tbd_address, &tx_buffer_address, attrs); + lduw_le_pci_dma(&s->dev, tbd_address + 4, &tx_buffer_size, attrs); + lduw_le_pci_dma(&s->dev, tbd_address + 6, &tx_buffer_el, attrs); tbd_address += 8; TRACE(RXTX, logout ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n", diff --git a/hw/net/tulip.c b/hw/net/tulip.c index c76e4868f7..d5b6cc5ee6 100644 --- a/hw/net/tulip.c +++ b/hw/net/tulip.c @@ -73,15 +73,15 @@ static void tulip_desc_read(TULIPState *s, hwaddr p, const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; if (s->csr[0] & CSR0_DBO) { - desc->status = ldl_be_pci_dma(&s->dev, p, attrs); - desc->control = ldl_be_pci_dma(&s->dev, p + 4, attrs); - desc->buf_addr1 = ldl_be_pci_dma(&s->dev, p + 8, attrs); - desc->buf_addr2 = ldl_be_pci_dma(&s->dev, p + 12, attrs); + ldl_be_pci_dma(&s->dev, p, &desc->status, attrs); + ldl_be_pci_dma(&s->dev, p + 4, &desc->control, attrs); + ldl_be_pci_dma(&s->dev, p + 8, &desc->buf_addr1, attrs); + ldl_be_pci_dma(&s->dev, p + 12, &desc->buf_addr2, attrs); } else { - desc->status = ldl_le_pci_dma(&s->dev, p, attrs); - desc->control = ldl_le_pci_dma(&s->dev, p + 4, attrs); - desc->buf_addr1 = ldl_le_pci_dma(&s->dev, p + 8, attrs); - desc->buf_addr2 = ldl_le_pci_dma(&s->dev, p + 12, attrs); + ldl_le_pci_dma(&s->dev, p, &desc->status, attrs); + ldl_le_pci_dma(&s->dev, p + 4, &desc->control, attrs); + ldl_le_pci_dma(&s->dev, p + 8, &desc->buf_addr1, attrs); + ldl_le_pci_dma(&s->dev, p + 12, &desc->buf_addr2, attrs); } } diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 98b13708c1..dc9bbdb740 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -202,9 +202,12 @@ static uint64_t megasas_frame_get_context(MegasasState *s, unsigned long frame) { PCIDevice *pci = &s->parent_obj; - return ldq_le_pci_dma(pci, - frame + offsetof(struct mfi_frame_header, context), - MEMTXATTRS_UNSPECIFIED); + uint64_t val; + + ldq_le_pci_dma(pci, frame + offsetof(struct mfi_frame_header, context), + &val, MEMTXATTRS_UNSPECIFIED); + + return val; } static bool megasas_frame_is_ieee_sgl(MegasasCmd *cmd) @@ -536,8 +539,8 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s, s->busy++; if (s->consumer_pa) { - s->reply_queue_tail = ldl_le_pci_dma(pcid, s->consumer_pa, - MEMTXATTRS_UNSPECIFIED); + ldl_le_pci_dma(pcid, s->consumer_pa, &s->reply_queue_tail, + MEMTXATTRS_UNSPECIFIED); } trace_megasas_qf_enqueue(cmd->index, cmd->count, cmd->context, s->reply_queue_head, s->reply_queue_tail, s->busy); @@ -568,14 +571,14 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context) stl_le_pci_dma(pci_dev, s->reply_queue_pa + queue_offset, context, attrs); } - s->reply_queue_tail = ldl_le_pci_dma(pci_dev, s->consumer_pa, attrs); + ldl_le_pci_dma(pci_dev, s->consumer_pa, &s->reply_queue_tail, attrs); trace_megasas_qf_complete(context, s->reply_queue_head, s->reply_queue_tail, s->busy); } if (megasas_intr_enabled(s)) { /* Update reply queue pointer */ - s->reply_queue_tail = ldl_le_pci_dma(pci_dev, s->consumer_pa, attrs); + ldl_le_pci_dma(pci_dev, s->consumer_pa, &s->reply_queue_tail, attrs); tail = s->reply_queue_head; s->reply_queue_head = megasas_next_index(s, tail, s->fw_cmds); trace_megasas_qf_update(s->reply_queue_head, s->reply_queue_tail, @@ -679,9 +682,9 @@ static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd) pa_lo = le32_to_cpu(initq->pi_addr_lo); pa_hi = le32_to_cpu(initq->pi_addr_hi); s->producer_pa = ((uint64_t) pa_hi << 32) | pa_lo; - s->reply_queue_head = ldl_le_pci_dma(pcid, s->producer_pa, attrs); + ldl_le_pci_dma(pcid, s->producer_pa, &s->reply_queue_head, attrs); s->reply_queue_head %= MEGASAS_MAX_FRAMES; - s->reply_queue_tail = ldl_le_pci_dma(pcid, s->consumer_pa, attrs); + ldl_le_pci_dma(pcid, s->consumer_pa, &s->reply_queue_tail, attrs); s->reply_queue_tail %= MEGASAS_MAX_FRAMES; flags = le32_to_cpu(initq->flags); if (flags & MFI_QUEUE_FLAG_CONTEXT64) { diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c index ac9f4dfcd2..5181b0c0b0 100644 --- a/hw/scsi/mptsas.c +++ b/hw/scsi/mptsas.c @@ -177,10 +177,16 @@ static dma_addr_t mptsas_ld_sg_base(MPTSASState *s, uint32_t flags_and_length, dma_addr_t addr; if (flags_and_length & MPI_SGE_FLAGS_64_BIT_ADDRESSING) { - addr = ldq_le_pci_dma(pci, *sgaddr + 4, attrs); + uint64_t addr64; + + ldq_le_pci_dma(pci, *sgaddr + 4, &addr64, attrs); + addr = addr64; *sgaddr += 12; } else { - addr = ldl_le_pci_dma(pci, *sgaddr + 4, attrs); + uint32_t addr32; + + ldl_le_pci_dma(pci, *sgaddr + 4, &addr32, attrs); + addr = addr32; *sgaddr += 8; } return addr; @@ -204,7 +210,7 @@ static int mptsas_build_sgl(MPTSASState *s, MPTSASRequest *req, hwaddr addr) dma_addr_t addr, len; uint32_t flags_and_length; - flags_and_length = ldl_le_pci_dma(pci, sgaddr, MEMTXATTRS_UNSPECIFIED); + ldl_le_pci_dma(pci, sgaddr, &flags_and_length, MEMTXATTRS_UNSPECIFIED); len = flags_and_length & MPI_SGE_LENGTH_MASK; if ((flags_and_length & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) != MPI_SGE_FLAGS_SIMPLE_ELEMENT || @@ -235,8 +241,8 @@ static int mptsas_build_sgl(MPTSASState *s, MPTSASRequest *req, hwaddr addr) break; } - flags_and_length = ldl_le_pci_dma(pci, next_chain_addr, - MEMTXATTRS_UNSPECIFIED); + ldl_le_pci_dma(pci, next_chain_addr, &flags_and_length, + MEMTXATTRS_UNSPECIFIED); if ((flags_and_length & MPI_SGE_FLAGS_ELEMENT_TYPE_MASK) != MPI_SGE_FLAGS_CHAIN_ELEMENT) { return MPI_IOCSTATUS_INVALID_SGL; diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index 33e16f9111..4d9969f3b1 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -50,10 +50,10 @@ #define PVSCSI_MAX_CMD_DATA_WORDS \ (sizeof(PVSCSICmdDescSetupRings)/sizeof(uint32_t)) -#define RS_GET_FIELD(m, field) \ - (ldl_le_pci_dma(&container_of(m, PVSCSIState, rings)->parent_obj, \ +#define RS_GET_FIELD(pval, m, field) \ + ldl_le_pci_dma(&container_of(m, PVSCSIState, rings)->parent_obj, \ (m)->rs_pa + offsetof(struct PVSCSIRingsState, field), \ - MEMTXATTRS_UNSPECIFIED)) + pval, MEMTXATTRS_UNSPECIFIED) #define RS_SET_FIELD(m, field, val) \ (stl_le_pci_dma(&container_of(m, PVSCSIState, rings)->parent_obj, \ (m)->rs_pa + offsetof(struct PVSCSIRingsState, field), val, \ @@ -249,10 +249,11 @@ pvscsi_ring_cleanup(PVSCSIRingInfo *mgr) static hwaddr pvscsi_ring_pop_req_descr(PVSCSIRingInfo *mgr) { - uint32_t ready_ptr = RS_GET_FIELD(mgr, reqProdIdx); + uint32_t ready_ptr; uint32_t ring_size = PVSCSI_MAX_NUM_PAGES_REQ_RING * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE; + RS_GET_FIELD(&ready_ptr, mgr, reqProdIdx); if (ready_ptr != mgr->consumed_ptr && ready_ptr - mgr->consumed_ptr < ring_size) { uint32_t next_ready_ptr = @@ -323,8 +324,11 @@ pvscsi_ring_flush_cmp(PVSCSIRingInfo *mgr) static bool pvscsi_ring_msg_has_room(PVSCSIRingInfo *mgr) { - uint32_t prodIdx = RS_GET_FIELD(mgr, msgProdIdx); - uint32_t consIdx = RS_GET_FIELD(mgr, msgConsIdx); + uint32_t prodIdx; + uint32_t consIdx; + + RS_GET_FIELD(&prodIdx, mgr, msgProdIdx); + RS_GET_FIELD(&consIdx, mgr, msgConsIdx); return (prodIdx - consIdx) < (mgr->msg_len_mask + 1); } diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index c90cecc85c..5b36334a28 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -850,15 +850,14 @@ static inline MemTxResult pci_dma_write(PCIDevice *dev, dma_addr_t addr, DMA_DIRECTION_FROM_DEVICE, MEMTXATTRS_UNSPECIFIED); } -#define PCI_DMA_DEFINE_LDST(_l, _s, _bits) \ - static inline uint##_bits##_t ld##_l##_pci_dma(PCIDevice *dev, \ - dma_addr_t addr, \ - MemTxAttrs attrs) \ - { \ - uint##_bits##_t val; \ - ld##_l##_dma(pci_get_address_space(dev), addr, &val, attrs); \ - return val; \ - } \ +#define PCI_DMA_DEFINE_LDST(_l, _s, _bits) \ + static inline MemTxResult ld##_l##_pci_dma(PCIDevice *dev, \ + dma_addr_t addr, \ + uint##_bits##_t *val, \ + MemTxAttrs attrs) \ + { \ + return ld##_l##_dma(pci_get_address_space(dev), addr, val, attrs); \ + } \ static inline MemTxResult st##_s##_pci_dma(PCIDevice *dev, \ dma_addr_t addr, \ uint##_bits##_t val, \ From 0e3ed77de51fab46d1ade0bee102e68fa376fbd8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 31 Dec 2021 05:25:11 +0000 Subject: [PATCH 116/730] meson: Unify mips and mips64 in host_arch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the build on a mips64 host. Prior to the break, we identified the arch via the __mips__ define; afterward we use meson's host_machine.cpu_family(). Restore the previous combination. Fixes: 823eb013452e ("configure, meson: move ARCH to meson.build") Reported-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- meson.build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meson.build b/meson.build index 886f0a9343..53065e96ec 100644 --- a/meson.build +++ b/meson.build @@ -74,6 +74,8 @@ if cpu not in supported_cpus host_arch = 'unknown' elif cpu == 'x86' host_arch = 'i386' +elif cpu == 'mips64' + host_arch = 'mips' else host_arch = cpu endif From fd0f79d715420eb3eac1de738983046cefc5df7d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 24 Dec 2021 12:08:18 -0800 Subject: [PATCH 117/730] tests/tcg: Use $cpu in configure.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use $cpu instead of $ARCH, which has been removed from the top-level configure. Tested-by: Philippe Mathieu-Daudé Reviewed-by: Philippe Mathieu-Daudé Fixes: 823eb013452e ("configure, meson: move ARCH to meson.build") Signed-off-by: Richard Henderson --- configure | 2 +- tests/tcg/configure.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index eb977e5b6f..030728d11e 100755 --- a/configure +++ b/configure @@ -3821,7 +3821,7 @@ done (for i in $cross_cc_vars; do export $i done -export target_list source_path use_containers ARCH +export target_list source_path use_containers cpu $source_path/tests/tcg/configure.sh) # temporary config to build submodules diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh index 9ef913df5b..8eb4287c84 100755 --- a/tests/tcg/configure.sh +++ b/tests/tcg/configure.sh @@ -326,7 +326,7 @@ for target in $target_list; do elif test $got_cross_cc = no && test "$container" != no && \ test -n "$container_image"; then for host in $container_hosts; do - if test "$host" = "$ARCH"; then + if test "$host" = "$cpu"; then echo "DOCKER_IMAGE=$container_image" >> $config_target_mak echo "DOCKER_CROSS_CC_GUEST=$container_cross_cc" >> \ $config_target_mak From 909c476d991185720a15c36fa7fe9159ccb06ab2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 30 Dec 2021 13:54:01 -0800 Subject: [PATCH 118/730] tests/tcg: Unconditionally use 90 second timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cross-i386-tci test has timeouts because we're no longer applying the timeout that we desired. Hack around it. Reviewed-by: Philippe Mathieu-Daudé Fixes: 23a77b2d18b8 ("build-system: clean up TCG/TCI configury") Signed-off-by: Richard Henderson --- tests/tcg/Makefile.target | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target index 63cf1b2573..0f8645f782 100644 --- a/tests/tcg/Makefile.target +++ b/tests/tcg/Makefile.target @@ -82,13 +82,12 @@ QEMU_OPTS= # If TCG debugging, or TCI is enabled things are a lot slower -ifneq ($(CONFIG_TCG_INTERPRETER),) +# ??? Makefile no longer has any indication that TCI is enabled, +# but for the record: +# 15s original default +# 60s with --enable-debug +# 90s with --enable-tcg-interpreter TIMEOUT=90 -else ifneq ($(CONFIG_DEBUG_TCG),) -TIMEOUT=60 -else -TIMEOUT=15 -endif ifdef CONFIG_USER_ONLY # The order we include is important. We include multiarch first and @@ -144,7 +143,6 @@ PLUGINS=$(patsubst %.c, lib%.so, $(notdir $(wildcard $(PLUGIN_SRC)/*.c))) $(foreach p,$(PLUGINS), \ $(foreach t,$(TESTS),\ $(eval run-plugin-$(t)-with-$(p): $t $p) \ - $(eval run-plugin-$(t)-with-$(p): TIMEOUT=60) \ $(eval RUN_TESTS+=run-plugin-$(t)-with-$(p)))) endif From 9f54dc1ce69045f1a5f9f2339b81274838901a3f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 29 Dec 2021 13:39:25 -0800 Subject: [PATCH 119/730] target/hppa: Fix atomic_store_3 for STBY The parallel version of STBY did not take host endianness into account, and also computed the incorrect address for STBY_E. Bswap twice to handle the merge and store. Compute mask inside the function rather than as a parameter. Force align the address, rather than subtracting one. Generalize the function to system mode by using probe_access(). Cc: qemu-stable@nongnu.org Tested-by: Helge Deller Reported-by: Helge Deller Signed-off-by: Richard Henderson --- target/hppa/op_helper.c | 27 ++++++----- tests/tcg/hppa/Makefile.target | 5 ++ tests/tcg/hppa/stby.c | 87 ++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 12 deletions(-) create mode 100644 tests/tcg/hppa/stby.c diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index 96d9391c39..1b86557d5d 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -57,26 +57,29 @@ void HELPER(tcond)(CPUHPPAState *env, target_ureg cond) } } -static void atomic_store_3(CPUHPPAState *env, target_ulong addr, uint32_t val, - uint32_t mask, uintptr_t ra) +static void atomic_store_3(CPUHPPAState *env, target_ulong addr, + uint32_t val, uintptr_t ra) { -#ifdef CONFIG_USER_ONLY - uint32_t old, new, cmp; + int mmu_idx = cpu_mmu_index(env, 0); + uint32_t old, new, cmp, mask, *haddr; + void *vaddr; + + vaddr = probe_access(env, addr, 3, MMU_DATA_STORE, mmu_idx, ra); + if (vaddr == NULL) { + cpu_loop_exit_atomic(env_cpu(env), ra); + } + haddr = (uint32_t *)((uintptr_t)vaddr & -4); + mask = addr & 1 ? 0x00ffffffu : 0xffffff00u; - uint32_t *haddr = g2h(env_cpu(env), addr - 1); old = *haddr; while (1) { - new = (old & ~mask) | (val & mask); + new = be32_to_cpu((cpu_to_be32(old) & ~mask) | (val & mask)); cmp = qatomic_cmpxchg(haddr, old, new); if (cmp == old) { return; } old = cmp; } -#else - /* FIXME -- we can do better. */ - cpu_loop_exit_atomic(env_cpu(env), ra); -#endif } static void do_stby_b(CPUHPPAState *env, target_ulong addr, target_ureg val, @@ -92,7 +95,7 @@ static void do_stby_b(CPUHPPAState *env, target_ulong addr, target_ureg val, case 1: /* The 3 byte store must appear atomic. */ if (parallel) { - atomic_store_3(env, addr, val, 0x00ffffffu, ra); + atomic_store_3(env, addr, val, ra); } else { cpu_stb_data_ra(env, addr, val >> 16, ra); cpu_stw_data_ra(env, addr + 1, val, ra); @@ -122,7 +125,7 @@ static void do_stby_e(CPUHPPAState *env, target_ulong addr, target_ureg val, case 3: /* The 3 byte store must appear atomic. */ if (parallel) { - atomic_store_3(env, addr - 3, val, 0xffffff00u, ra); + atomic_store_3(env, addr - 3, val, ra); } else { cpu_stw_data_ra(env, addr - 3, val >> 16, ra); cpu_stb_data_ra(env, addr - 1, val >> 8, ra); diff --git a/tests/tcg/hppa/Makefile.target b/tests/tcg/hppa/Makefile.target index d0d5e0e257..b78e6b4849 100644 --- a/tests/tcg/hppa/Makefile.target +++ b/tests/tcg/hppa/Makefile.target @@ -12,3 +12,8 @@ run-signals: signals $(call skip-test, $<, "BROKEN awaiting vdso support") run-plugin-signals-with-%: $(call skip-test, $<, "BROKEN awaiting vdso support") + +VPATH += $(SRC_PATH)/tests/tcg/hppa +TESTS += stby + +stby: CFLAGS += -pthread diff --git a/tests/tcg/hppa/stby.c b/tests/tcg/hppa/stby.c new file mode 100644 index 0000000000..36bd5f723c --- /dev/null +++ b/tests/tcg/hppa/stby.c @@ -0,0 +1,87 @@ +/* Test STBY */ + +#include +#include +#include +#include + + +struct S { + unsigned a; + unsigned b; + unsigned c; +}; + +static void check(const struct S *s, unsigned e, + const char *which, const char *insn, int ofs) +{ + int err = 0; + + if (s->a != 0) { + fprintf(stderr, "%s %s %d: garbage before word 0x%08x\n", + which, insn, ofs, s->a); + err = 1; + } + if (s->c != 0) { + fprintf(stderr, "%s %s %d: garbage after word 0x%08x\n", + which, insn, ofs, s->c); + err = 1; + } + if (s->b != e) { + fprintf(stderr, "%s %s %d: 0x%08x != 0x%08x\n", + which, insn, ofs, s->b, e); + err = 1; + } + + if (err) { + exit(1); + } +} + +#define TEST(INSN, OFS, E) \ + do { \ + s.b = 0; \ + asm volatile(INSN " %1, " #OFS "(%0)" \ + : : "r"(&s.b), "r" (0x11223344) : "memory"); \ + check(&s, E, which, INSN, OFS); \ + } while (0) + +static void test(const char *which) +{ + struct S s = { }; + + TEST("stby,b", 0, 0x11223344); + TEST("stby,b", 1, 0x00223344); + TEST("stby,b", 2, 0x00003344); + TEST("stby,b", 3, 0x00000044); + + TEST("stby,e", 0, 0x00000000); + TEST("stby,e", 1, 0x11000000); + TEST("stby,e", 2, 0x11220000); + TEST("stby,e", 3, 0x11223300); +} + +static void *child(void *x) +{ + return NULL; +} + +int main() +{ + int err; + pthread_t thr; + + /* Run test in serial mode */ + test("serial"); + + /* Create a dummy thread to start parallel mode. */ + err = pthread_create(&thr, NULL, child, NULL); + if (err != 0) { + fprintf(stderr, "pthread_create: %s\n", strerror(err)); + return 2; + } + + /* Run test in parallel mode */ + test("parallel"); + return 0; +} From 694804ed7b26e66e114a2330887187d697a0d92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 18 Dec 2021 13:49:24 +0100 Subject: [PATCH 120/730] hw/qdev: Cosmetic around documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add empty lines to have a clearer distinction between different functions declarations. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Yanan Wang Message-Id: <20211218130437.1516929-2-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- include/hw/qdev-core.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 20d3066595..59a822ffce 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -321,6 +321,7 @@ compat_props_add(GPtrArray *arr, * The returned object has a reference count of 1. */ DeviceState *qdev_new(const char *name); + /** * qdev_try_new: Try to create a device on the heap * @name: device type to create @@ -329,6 +330,7 @@ DeviceState *qdev_new(const char *name); * does not exist, rather than asserting. */ DeviceState *qdev_try_new(const char *name); + /** * qdev_realize: Realize @dev. * @dev: device to realize @@ -347,6 +349,7 @@ DeviceState *qdev_try_new(const char *name); * qdev_realize_and_unref() instead. */ bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp); + /** * qdev_realize_and_unref: Realize @dev and drop a reference * @dev: device to realize @@ -372,6 +375,7 @@ bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp); * would be incorrect. For that use case you want qdev_realize(). */ bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp); + /** * qdev_unrealize: Unrealize a device * @dev: device to unrealize @@ -450,6 +454,7 @@ typedef enum { * For named input GPIO lines, use qdev_get_gpio_in_named(). */ qemu_irq qdev_get_gpio_in(DeviceState *dev, int n); + /** * qdev_get_gpio_in_named: Get one of a device's named input GPIO lines * @dev: Device whose GPIO we want @@ -497,6 +502,7 @@ qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n); * For named output GPIO lines, use qdev_connect_gpio_out_named(). */ void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); + /** * qdev_connect_gpio_out: Connect one of a device's anonymous output GPIO lines * @dev: Device whose GPIO to connect @@ -524,6 +530,7 @@ void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); */ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, qemu_irq pin); + /** * qdev_get_gpio_out_connector: Get the qemu_irq connected to an output GPIO * @dev: Device whose output GPIO we are interested in @@ -541,6 +548,7 @@ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, * by the platform-bus subsystem. */ qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n); + /** * qdev_intercept_gpio_out: Intercept an existing GPIO connection * @dev: Device to intercept the outbound GPIO line from @@ -582,6 +590,7 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name); * hold of an input GPIO line to manipulate it. */ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); + /** * qdev_init_gpio_out: create an array of anonymous output GPIO lines * @dev: Device to create output GPIOs for @@ -610,6 +619,7 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); * handler. */ void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n); + /** * qdev_init_gpio_out: create an array of named output GPIO lines * @dev: Device to create output GPIOs for @@ -623,6 +633,7 @@ void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n); */ void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, const char *name, int n); + /** * qdev_init_gpio_in_named_with_opaque: create an array of input GPIO lines * for the specified device From 14b0375b39f4acbd2b313a37f5fdf886b0fe74cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 18 Dec 2021 13:52:51 +0100 Subject: [PATCH 121/730] hw/qdev: Correct qdev_init_gpio_out_named() documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qdev_init_gpio_out_named() is described as qdev_init_gpio_out(), and referring to itself in an endless loop, which is confusing. Fix. Reported-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Yanan Wang Message-Id: <20211218130437.1516929-3-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- include/hw/qdev-core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 59a822ffce..dcf20c69b8 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -621,7 +621,7 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n); void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n); /** - * qdev_init_gpio_out: create an array of named output GPIO lines + * qdev_init_gpio_out_named: create an array of named output GPIO lines * @dev: Device to create output GPIOs for * @pins: Pointer to qemu_irq or qemu_irq array for the GPIO lines * @name: Name to give this array of GPIO lines From 1fbd004b00198fb3f27e52ce7b138b9c13288f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 5 Nov 2021 17:50:28 +0100 Subject: [PATCH 122/730] hw/qdev: Correct qdev_connect_gpio_out_named() documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qdev_connect_gpio_out_named() is described as qdev_connect_gpio_out(), and referring to itself in an endless loop, which is confusing. Fix. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Yanan Wang Message-Id: <20211218130437.1516929-4-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- include/hw/qdev-core.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index dcf20c69b8..424c48daf6 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -504,7 +504,8 @@ qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n); void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); /** - * qdev_connect_gpio_out: Connect one of a device's anonymous output GPIO lines + * qdev_connect_gpio_out_named: Connect one of a device's named output + * GPIO lines * @dev: Device whose GPIO to connect * @name: Name of the output GPIO array * @n: Number of the anonymous output GPIO line (which must be in range) @@ -526,7 +527,7 @@ void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); * qemu_irqs at once, or to connect multiple outbound GPIOs to the * same qemu_irq; see qdev_connect_gpio_out() for details. * - * For named output GPIO lines, use qdev_connect_gpio_out_named(). + * For anonymous output GPIO lines, use qdev_connect_gpio_out(). */ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, qemu_irq pin); From 2ebd9ce19a324aa627c3f9b8f40285a1cf9bb0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 5 Nov 2021 17:53:21 +0100 Subject: [PATCH 123/730] hw/qdev: Rename qdev_connect_gpio_out*() 'input_pin' parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @pin is an input where we connect a device output. Rename it @input_pin to simplify the documentation. Reviewed-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211218130437.1516929-5-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- hw/core/gpio.c | 13 +++++++------ include/hw/qdev-core.h | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/hw/core/gpio.c b/hw/core/gpio.c index 8e6b4f5edf..80d07a6ec9 100644 --- a/hw/core/gpio.c +++ b/hw/core/gpio.c @@ -115,17 +115,18 @@ qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) } void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, - qemu_irq pin) + qemu_irq input_pin) { char *propname = g_strdup_printf("%s[%d]", name ? name : "unnamed-gpio-out", n); - if (pin && !OBJECT(pin)->parent) { + if (input_pin && !OBJECT(input_pin)->parent) { /* We need a name for object_property_set_link to work */ object_property_add_child(container_get(qdev_get_machine(), "/unattached"), - "non-qdev-gpio[*]", OBJECT(pin)); + "non-qdev-gpio[*]", OBJECT(input_pin)); } - object_property_set_link(OBJECT(dev), propname, OBJECT(pin), &error_abort); + object_property_set_link(OBJECT(dev), propname, + OBJECT(input_pin), &error_abort); g_free(propname); } @@ -165,9 +166,9 @@ qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt, return disconnected; } -void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin) +void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq input_pin) { - qdev_connect_gpio_out_named(dev, NULL, n, pin); + qdev_connect_gpio_out_named(dev, NULL, n, input_pin); } void qdev_pass_gpios(DeviceState *dev, DeviceState *container, diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 424c48daf6..d19c941752 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -476,7 +476,7 @@ qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n); * qdev_connect_gpio_out: Connect one of a device's anonymous output GPIO lines * @dev: Device whose GPIO to connect * @n: Number of the anonymous output GPIO line (which must be in range) - * @pin: qemu_irq to connect the output line to + * @input_pin: qemu_irq to connect the output line to * * This function connects an anonymous output GPIO line on a device * up to an arbitrary qemu_irq, so that when the device asserts that @@ -509,7 +509,7 @@ void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); * @dev: Device whose GPIO to connect * @name: Name of the output GPIO array * @n: Number of the anonymous output GPIO line (which must be in range) - * @pin: qemu_irq to connect the output line to + * @input_pin: qemu_irq to connect the output line to * * This function connects an anonymous output GPIO line on a device * up to an arbitrary qemu_irq, so that when the device asserts that @@ -530,7 +530,7 @@ void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin); * For anonymous output GPIO lines, use qdev_connect_gpio_out(). */ void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, - qemu_irq pin); + qemu_irq input_pin); /** * qdev_get_gpio_out_connector: Get the qemu_irq connected to an output GPIO From 1ab192f30caeb7dd409fa82164ffa0df5e984a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 15 Nov 2021 12:32:09 +0100 Subject: [PATCH 124/730] tests/unit/test-smp-parse: Pass machine type as argument to tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use g_test_add_data_func() instead of g_test_add_func() so we can pass the machine type to the tests (we will soon have different machine types). Reviewed-by: Richard Henderson Reviewed-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211216132015.815493-2-philmd@redhat.com> --- tests/unit/test-smp-parse.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index b02450e25a..37c6b4981d 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -487,9 +487,10 @@ static void machine_base_class_init(ObjectClass *oc, void *data) mc->name = g_strdup(SMP_MACHINE_NAME); } -static void test_generic(void) +static void test_generic(const void *opaque) { - Object *obj = object_new(TYPE_MACHINE); + const char *machine_type = opaque; + Object *obj = object_new(machine_type); MachineState *ms = MACHINE(obj); MachineClass *mc = MACHINE_GET_CLASS(obj); SMPTestData *data = &(SMPTestData){{ }}; @@ -525,9 +526,10 @@ static void test_generic(void) object_unref(obj); } -static void test_with_dies(void) +static void test_with_dies(const void *opaque) { - Object *obj = object_new(TYPE_MACHINE); + const char *machine_type = opaque; + Object *obj = object_new(machine_type); MachineState *ms = MACHINE(obj); MachineClass *mc = MACHINE_GET_CLASS(obj); SMPTestData *data = &(SMPTestData){{ }}; @@ -599,8 +601,12 @@ int main(int argc, char *argv[]) g_test_init(&argc, &argv, NULL); - g_test_add_func("/test-smp-parse/generic", test_generic); - g_test_add_func("/test-smp-parse/with_dies", test_with_dies); + g_test_add_data_func("/test-smp-parse/generic", + TYPE_MACHINE, + test_generic); + g_test_add_data_func("/test-smp-parse/with_dies", + TYPE_MACHINE, + test_with_dies); g_test_run(); From c30bdb025ce04f26ad63cbaebba911cff6573a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 15 Nov 2021 12:35:43 +0100 Subject: [PATCH 125/730] tests/unit/test-smp-parse: Split the 'generic' test in valid / invalid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the 'generic' test in two tests: 'valid' and 'invalid'. This will allow us to remove the hack which modifies the MachineClass internal state. Reviewed-by: Richard Henderson Reviewed-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211216132015.815493-3-philmd@redhat.com> --- tests/unit/test-smp-parse.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index 37c6b4981d..425ed6b6b9 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -487,7 +487,7 @@ static void machine_base_class_init(ObjectClass *oc, void *data) mc->name = g_strdup(SMP_MACHINE_NAME); } -static void test_generic(const void *opaque) +static void test_generic_valid(const void *opaque) { const char *machine_type = opaque; Object *obj = object_new(machine_type); @@ -508,6 +508,18 @@ static void test_generic(const void *opaque) smp_parse_test(ms, data, true); } + object_unref(obj); +} + +static void test_generic_invalid(const void *opaque) +{ + const char *machine_type = opaque; + Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); + SMPTestData *data = &(SMPTestData){}; + int i; + /* Force invalid min CPUs and max CPUs */ mc->min_cpus = 2; mc->max_cpus = 511; @@ -601,9 +613,12 @@ int main(int argc, char *argv[]) g_test_init(&argc, &argv, NULL); - g_test_add_data_func("/test-smp-parse/generic", + g_test_add_data_func("/test-smp-parse/generic/valid", TYPE_MACHINE, - test_generic); + test_generic_valid); + g_test_add_data_func("/test-smp-parse/generic/invalid", + TYPE_MACHINE, + test_generic_invalid); g_test_add_data_func("/test-smp-parse/with_dies", TYPE_MACHINE, test_with_dies); From 76b6d4cce364ef841a3e2e3574322ca6d8a27414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 15 Nov 2021 12:39:12 +0100 Subject: [PATCH 126/730] tests/unit/test-smp-parse: Add 'smp-with-dies' machine type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid modifying the MachineClass internals by adding the 'smp-with-dies' machine, which inherits from TYPE_MACHINE. Reviewed-by: Richard Henderson Reviewed-by: Yanan Wang Tested-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211216132015.815493-4-philmd@redhat.com> --- tests/unit/test-smp-parse.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index 425ed6b6b9..f66cf7bb59 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -487,6 +487,16 @@ static void machine_base_class_init(ObjectClass *oc, void *data) mc->name = g_strdup(SMP_MACHINE_NAME); } +static void machine_with_dies_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->min_cpus = MIN_CPUS; + mc->max_cpus = MAX_CPUS; + + mc->smp_props.dies_supported = true; +} + static void test_generic_valid(const void *opaque) { const char *machine_type = opaque; @@ -548,9 +558,6 @@ static void test_with_dies(const void *opaque) unsigned int num_dies = 2; int i; - /* Force the SMP compat properties */ - mc->smp_props.dies_supported = true; - for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { *data = data_generic_valid[i]; unsupported_params_init(mc, data); @@ -588,9 +595,6 @@ static void test_with_dies(const void *opaque) smp_parse_test(ms, data, false); } - /* Restore the SMP compat properties */ - mc->smp_props.dies_supported = false; - object_unref(obj); } @@ -602,6 +606,10 @@ static const TypeInfo smp_machine_types[] = { .class_init = machine_base_class_init, .class_size = sizeof(MachineClass), .instance_size = sizeof(MachineState), + }, { + .name = MACHINE_TYPE_NAME("smp-with-dies"), + .parent = TYPE_MACHINE, + .class_init = machine_with_dies_class_init, } }; @@ -620,7 +628,7 @@ int main(int argc, char *argv[]) TYPE_MACHINE, test_generic_invalid); g_test_add_data_func("/test-smp-parse/with_dies", - TYPE_MACHINE, + MACHINE_TYPE_NAME("smp-with-dies"), test_with_dies); g_test_run(); From 7ca0705eba00c0d38f7b37670ee6cff9b607bb74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 15 Nov 2021 15:44:07 +0100 Subject: [PATCH 127/730] tests/unit/test-smp-parse: Add 'smp-generic-invalid' machine type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid modifying the MachineClass internals by adding the 'smp-generic-invalid' machine, which inherits from TYPE_MACHINE. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Yanan Wang Message-Id: <20211216132015.815493-5-philmd@redhat.com> --- tests/unit/test-smp-parse.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index f66cf7bb59..47e11089e2 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -487,6 +487,17 @@ static void machine_base_class_init(ObjectClass *oc, void *data) mc->name = g_strdup(SMP_MACHINE_NAME); } +static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + /* Force invalid min CPUs and max CPUs */ + mc->min_cpus = 2; + mc->max_cpus = 511; + + mc->smp_props.dies_supported = false; +} + static void machine_with_dies_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -530,10 +541,6 @@ static void test_generic_invalid(const void *opaque) SMPTestData *data = &(SMPTestData){}; int i; - /* Force invalid min CPUs and max CPUs */ - mc->min_cpus = 2; - mc->max_cpus = 511; - for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) { *data = data_generic_invalid[i]; unsupported_params_init(mc, data); @@ -541,10 +548,6 @@ static void test_generic_invalid(const void *opaque) smp_parse_test(ms, data, false); } - /* Reset the supported min CPUs and max CPUs */ - mc->min_cpus = MIN_CPUS; - mc->max_cpus = MAX_CPUS; - object_unref(obj); } @@ -606,6 +609,10 @@ static const TypeInfo smp_machine_types[] = { .class_init = machine_base_class_init, .class_size = sizeof(MachineClass), .instance_size = sizeof(MachineState), + }, { + .name = MACHINE_TYPE_NAME("smp-generic-invalid"), + .parent = TYPE_MACHINE, + .class_init = machine_generic_invalid_class_init, }, { .name = MACHINE_TYPE_NAME("smp-with-dies"), .parent = TYPE_MACHINE, @@ -625,7 +632,7 @@ int main(int argc, char *argv[]) TYPE_MACHINE, test_generic_valid); g_test_add_data_func("/test-smp-parse/generic/invalid", - TYPE_MACHINE, + MACHINE_TYPE_NAME("smp-generic-invalid"), test_generic_invalid); g_test_add_data_func("/test-smp-parse/with_dies", MACHINE_TYPE_NAME("smp-with-dies"), From 2dc426c468833619afc1221666e0e6246b8f21d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 15 Nov 2021 15:49:59 +0100 Subject: [PATCH 128/730] tests/unit/test-smp-parse: Add 'smp-generic-valid' machine type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep the common TYPE_MACHINE class initialization in machine_base_class_init(), make it abstract, and move the non-common code to a new class: "smp-generic-valid". Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Yanan Wang Message-Id: <20211216132015.815493-6-philmd@redhat.com> --- tests/unit/test-smp-parse.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index 47e11089e2..b20bf2c235 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -478,13 +478,19 @@ static void machine_base_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + mc->smp_props.prefer_sockets = true; + + mc->name = g_strdup(SMP_MACHINE_NAME); +} + +static void machine_generic_valid_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + mc->min_cpus = MIN_CPUS; mc->max_cpus = MAX_CPUS; - mc->smp_props.prefer_sockets = true; mc->smp_props.dies_supported = false; - - mc->name = g_strdup(SMP_MACHINE_NAME); } static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) @@ -606,9 +612,14 @@ static const TypeInfo smp_machine_types[] = { { .name = TYPE_MACHINE, .parent = TYPE_OBJECT, + .abstract = true, .class_init = machine_base_class_init, .class_size = sizeof(MachineClass), .instance_size = sizeof(MachineState), + }, { + .name = MACHINE_TYPE_NAME("smp-generic-valid"), + .parent = TYPE_MACHINE, + .class_init = machine_generic_valid_class_init, }, { .name = MACHINE_TYPE_NAME("smp-generic-invalid"), .parent = TYPE_MACHINE, @@ -629,7 +640,7 @@ int main(int argc, char *argv[]) g_test_init(&argc, &argv, NULL); g_test_add_data_func("/test-smp-parse/generic/valid", - TYPE_MACHINE, + MACHINE_TYPE_NAME("smp-generic-valid"), test_generic_valid); g_test_add_data_func("/test-smp-parse/generic/invalid", MACHINE_TYPE_NAME("smp-generic-invalid"), From 47ab8a491ac62a884a42fb50ef3c7c7e0dac59d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 11 Nov 2021 08:58:40 +0100 Subject: [PATCH 129/730] tests/unit/test-smp-parse: Simplify pointer to compound literal use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can simply use a local variable (and pass its pointer) instead of a pointer to a compound literal. Reviewed-by: Andrew Jones Reviewed-by: Richard Henderson Reviewed-by: Yanan Wang Tested-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211216132015.815493-7-philmd@redhat.com> --- tests/unit/test-smp-parse.c | 66 ++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index b20bf2c235..395929b66c 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -520,19 +520,19 @@ static void test_generic_valid(const void *opaque) Object *obj = object_new(machine_type); MachineState *ms = MACHINE(obj); MachineClass *mc = MACHINE_GET_CLASS(obj); - SMPTestData *data = &(SMPTestData){{ }}; + SMPTestData data = {}; int i; for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { - *data = data_generic_valid[i]; - unsupported_params_init(mc, data); + data = data_generic_valid[i]; + unsupported_params_init(mc, &data); - smp_parse_test(ms, data, true); + smp_parse_test(ms, &data, true); /* Unsupported parameters can be provided with their values as 1 */ - data->config.has_dies = true; - data->config.dies = 1; - smp_parse_test(ms, data, true); + data.config.has_dies = true; + data.config.dies = 1; + smp_parse_test(ms, &data, true); } object_unref(obj); @@ -544,14 +544,14 @@ static void test_generic_invalid(const void *opaque) Object *obj = object_new(machine_type); MachineState *ms = MACHINE(obj); MachineClass *mc = MACHINE_GET_CLASS(obj); - SMPTestData *data = &(SMPTestData){}; + SMPTestData data = {}; int i; for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) { - *data = data_generic_invalid[i]; - unsupported_params_init(mc, data); + data = data_generic_invalid[i]; + unsupported_params_init(mc, &data); - smp_parse_test(ms, data, false); + smp_parse_test(ms, &data, false); } object_unref(obj); @@ -563,45 +563,45 @@ static void test_with_dies(const void *opaque) Object *obj = object_new(machine_type); MachineState *ms = MACHINE(obj); MachineClass *mc = MACHINE_GET_CLASS(obj); - SMPTestData *data = &(SMPTestData){{ }}; + SMPTestData data = {}; unsigned int num_dies = 2; int i; for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { - *data = data_generic_valid[i]; - unsupported_params_init(mc, data); + data = data_generic_valid[i]; + unsupported_params_init(mc, &data); /* when dies parameter is omitted, it will be set as 1 */ - data->expect_prefer_sockets.dies = 1; - data->expect_prefer_cores.dies = 1; + data.expect_prefer_sockets.dies = 1; + data.expect_prefer_cores.dies = 1; - smp_parse_test(ms, data, true); + smp_parse_test(ms, &data, true); /* when dies parameter is specified */ - data->config.has_dies = true; - data->config.dies = num_dies; - if (data->config.has_cpus) { - data->config.cpus *= num_dies; + data.config.has_dies = true; + data.config.dies = num_dies; + if (data.config.has_cpus) { + data.config.cpus *= num_dies; } - if (data->config.has_maxcpus) { - data->config.maxcpus *= num_dies; + if (data.config.has_maxcpus) { + data.config.maxcpus *= num_dies; } - data->expect_prefer_sockets.dies = num_dies; - data->expect_prefer_sockets.cpus *= num_dies; - data->expect_prefer_sockets.max_cpus *= num_dies; - data->expect_prefer_cores.dies = num_dies; - data->expect_prefer_cores.cpus *= num_dies; - data->expect_prefer_cores.max_cpus *= num_dies; + data.expect_prefer_sockets.dies = num_dies; + data.expect_prefer_sockets.cpus *= num_dies; + data.expect_prefer_sockets.max_cpus *= num_dies; + data.expect_prefer_cores.dies = num_dies; + data.expect_prefer_cores.cpus *= num_dies; + data.expect_prefer_cores.max_cpus *= num_dies; - smp_parse_test(ms, data, true); + smp_parse_test(ms, &data, true); } for (i = 0; i < ARRAY_SIZE(data_with_dies_invalid); i++) { - *data = data_with_dies_invalid[i]; - unsupported_params_init(mc, data); + data = data_with_dies_invalid[i]; + unsupported_params_init(mc, &data); - smp_parse_test(ms, data, false); + smp_parse_test(ms, &data, false); } object_unref(obj); From cf65000ae9884bc4bb36f2941568353ba405d966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 11 Nov 2021 10:23:06 +0100 Subject: [PATCH 130/730] tests/unit/test-smp-parse: Constify some pointer/struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Declare structures const when we don't need to modify them at runtime. Reviewed-by: Andrew Jones Reviewed-by: Richard Henderson Reviewed-by: Yanan Wang Tested-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211216132015.815493-8-philmd@redhat.com> --- tests/unit/test-smp-parse.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index 395929b66c..0f98c9509e 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -83,7 +83,7 @@ typedef struct SMPTestData { * then test the automatic calculation algorithm of the missing * values in the parser. */ -static struct SMPTestData data_generic_valid[] = { +static const struct SMPTestData data_generic_valid[] = { { /* config: no configuration provided * expect: cpus=1,sockets=1,cores=1,threads=1,maxcpus=1 */ @@ -285,7 +285,7 @@ static struct SMPTestData data_generic_valid[] = { }, }; -static struct SMPTestData data_generic_invalid[] = { +static const struct SMPTestData data_generic_invalid[] = { { /* config: -smp 2,dies=2 */ .config = SMP_CONFIG_WITH_DIES(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0), @@ -319,7 +319,7 @@ static struct SMPTestData data_generic_invalid[] = { }, }; -static struct SMPTestData data_with_dies_invalid[] = { +static const struct SMPTestData data_with_dies_invalid[] = { { /* config: -smp 16,sockets=2,dies=2,cores=4,threads=2,maxcpus=16 */ .config = SMP_CONFIG_WITH_DIES(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16), @@ -356,7 +356,7 @@ static char *smp_config_to_string(SMPConfiguration *config) config->has_maxcpus ? "true" : "false", config->maxcpus); } -static char *cpu_topology_to_string(CpuTopology *topo) +static char *cpu_topology_to_string(const CpuTopology *topo) { return g_strdup_printf( "(CpuTopology) {\n" @@ -372,7 +372,7 @@ static char *cpu_topology_to_string(CpuTopology *topo) } static void check_parse(MachineState *ms, SMPConfiguration *config, - CpuTopology *expect_topo, const char *expect_err, + const CpuTopology *expect_topo, const char *expect_err, bool is_valid) { g_autofree char *config_str = smp_config_to_string(config); @@ -466,7 +466,7 @@ static void smp_parse_test(MachineState *ms, SMPTestData *data, bool is_valid) } /* The parsed results of the unsupported parameters should be 1 */ -static void unsupported_params_init(MachineClass *mc, SMPTestData *data) +static void unsupported_params_init(const MachineClass *mc, SMPTestData *data) { if (!mc->smp_props.dies_supported) { data->expect_prefer_sockets.dies = 1; From 3e2f14981c73f0cc009963512d63f2919efed5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 11 Nov 2021 10:21:23 +0100 Subject: [PATCH 131/730] hw/core: Rename smp_parse() -> machine_parse_smp_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All methods related to MachineState are prefixed with "machine_". smp_parse() does not need to be an exception. Rename it and const'ify the SMPConfiguration argument, since it doesn't need to be modified. Reviewed-by: Andrew Jones Reviewed-by: Richard Henderson Reviewed-by: Yanan Wang Tested-by: Yanan Wang Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211216132015.815493-9-philmd@redhat.com> --- hw/core/machine-smp.c | 6 ++++-- hw/core/machine.c | 2 +- include/hw/boards.h | 3 ++- tests/unit/test-smp-parse.c | 8 ++++---- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c index 116a0cbbfa..2cbfd57429 100644 --- a/hw/core/machine-smp.c +++ b/hw/core/machine-smp.c @@ -44,7 +44,8 @@ static char *cpu_hierarchy_to_string(MachineState *ms) } /* - * smp_parse - Generic function used to parse the given SMP configuration + * machine_parse_smp_config: Generic function used to parse the given + * SMP configuration * * Any missing parameter in "cpus/maxcpus/sockets/cores/threads" will be * automatically computed based on the provided ones. @@ -63,7 +64,8 @@ static char *cpu_hierarchy_to_string(MachineState *ms) * introduced topology members which are likely to be target specific should * be directly set as 1 if they are omitted (e.g. dies for PC since 4.1). */ -void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp) +void machine_parse_smp_config(MachineState *ms, + const SMPConfiguration *config, Error **errp) { MachineClass *mc = MACHINE_GET_CLASS(ms); unsigned cpus = config->has_cpus ? config->cpus : 0; diff --git a/hw/core/machine.c b/hw/core/machine.c index 53a99abc56..3993c534b9 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -761,7 +761,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name, return; } - smp_parse(ms, config, errp); + machine_parse_smp_config(ms, config, errp); } static void machine_class_init(ObjectClass *oc, void *data) diff --git a/include/hw/boards.h b/include/hw/boards.h index 9c1c190104..7597cec440 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -34,7 +34,8 @@ HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine); void machine_set_cpu_numa_node(MachineState *machine, const CpuInstanceProperties *props, Error **errp); -void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp); +void machine_parse_smp_config(MachineState *ms, + const SMPConfiguration *config, Error **errp); /** * machine_class_allow_dynamic_sysbus_dev: Add type to list of valid devices diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index 0f98c9509e..b6df8137fc 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -337,7 +337,7 @@ static const struct SMPTestData data_with_dies_invalid[] = { }, }; -static char *smp_config_to_string(SMPConfiguration *config) +static char *smp_config_to_string(const SMPConfiguration *config) { return g_strdup_printf( "(SMPConfiguration) {\n" @@ -371,7 +371,7 @@ static char *cpu_topology_to_string(const CpuTopology *topo) topo->cores, topo->threads, topo->max_cpus); } -static void check_parse(MachineState *ms, SMPConfiguration *config, +static void check_parse(MachineState *ms, const SMPConfiguration *config, const CpuTopology *expect_topo, const char *expect_err, bool is_valid) { @@ -380,8 +380,8 @@ static void check_parse(MachineState *ms, SMPConfiguration *config, g_autofree char *output_topo_str = NULL; Error *err = NULL; - /* call the generic parser smp_parse() */ - smp_parse(ms, config, &err); + /* call the generic parser */ + machine_parse_smp_config(ms, config, &err); output_topo_str = cpu_topology_to_string(&ms->smp); From 0d8717852326db6deb4f10ab47d3458fb2b73529 Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Tue, 28 Dec 2021 17:22:08 +0800 Subject: [PATCH 132/730] qemu-options: Improve readability of SMP related Docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a description in qemu-options.hx for each CPU topology parameter to explain what it exactly means, and also an extra declaration for the target-specific one, e.g. "for PC only" when describing "dies", and "for PC, it's on one die" when describing "cores". Now we are going to introduce one more non-generic parameter "clusters", it will make the Doc less readable and if we still continue to use the legacy way to describe it. So let's at first make two tweaks of the Docs to improve the readability and also scalability: 1) In the -help text: Delete the extra specific declaration and describe each topology parameter level by level. Then add a note to declare that different machines may support different subsets and the actual meaning of the supported parameters will vary accordingly. 2) In the rST text: List all the sub-hierarchies currently supported in QEMU, and correspondingly give an example of -smp configuration for each of them. Signed-off-by: Yanan Wang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211228092221.21068-2-wangyanan55@huawei.com> Signed-off-by: Philippe Mathieu-Daudé --- qemu-options.hx | 74 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index 7d47510947..b39377de3f 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -207,14 +207,26 @@ ERST DEF("smp", HAS_ARG, QEMU_OPTION_smp, "-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]\n" - " set the number of CPUs to 'n' [default=1]\n" + " set the number of initial CPUs to 'n' [default=1]\n" " maxcpus= maximum number of total CPUs, including\n" " offline CPUs for hotplug, etc\n" - " sockets= number of discrete sockets in the system\n" - " dies= number of CPU dies on one socket (for PC only)\n" - " cores= number of CPU cores on one socket (for PC, it's on one die)\n" - " threads= number of threads on one CPU core\n", - QEMU_ARCH_ALL) + " sockets= number of sockets on the machine board\n" + " dies= number of dies in one socket\n" + " cores= number of cores in one die\n" + " threads= number of threads in one core\n" + "Note: Different machines may have different subsets of the CPU topology\n" + " parameters supported, so the actual meaning of the supported parameters\n" + " will vary accordingly. For example, for a machine type that supports a\n" + " three-level CPU hierarchy of sockets/cores/threads, the parameters will\n" + " sequentially mean as below:\n" + " sockets means the number of sockets on the machine board\n" + " cores means the number of cores in one socket\n" + " threads means the number of threads in one core\n" + " For a particular machine type board, an expected CPU topology hierarchy\n" + " can be defined through the supported sub-option. Unsupported parameters\n" + " can also be provided in addition to the sub-option, but their values\n" + " must be set as 1 in the purpose of correct parsing.\n", + QEMU_ARCH_ALL) SRST ``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]`` Simulate a SMP system with '\ ``n``\ ' CPUs initially present on @@ -225,27 +237,57 @@ SRST initial CPU count will match the maximum number. When only one of them is given then the omitted one will be set to its counterpart's value. Both parameters may be specified, but the maximum number of CPUs must - be equal to or greater than the initial CPU count. Both parameters are - subject to an upper limit that is determined by the specific machine - type chosen. + be equal to or greater than the initial CPU count. Product of the + CPU topology hierarchy must be equal to the maximum number of CPUs. + Both parameters are subject to an upper limit that is determined by + the specific machine type chosen. - To control reporting of CPU topology information, the number of sockets, - dies per socket, cores per die, and threads per core can be specified. - The sum `` sockets * cores * dies * threads `` must be equal to the - maximum CPU count. CPU targets may only support a subset of the topology - parameters. Where a CPU target does not support use of a particular - topology parameter, its value should be assumed to be 1 for the purpose - of computing the CPU maximum count. + To control reporting of CPU topology information, values of the topology + parameters can be specified. Machines may only support a subset of the + parameters and different machines may have different subsets supported + which vary depending on capacity of the corresponding CPU targets. So + for a particular machine type board, an expected topology hierarchy can + be defined through the supported sub-option. Unsupported parameters can + also be provided in addition to the sub-option, but their values must be + set as 1 in the purpose of correct parsing. Either the initial CPU count, or at least one of the topology parameters must be specified. The specified parameters must be greater than zero, explicit configuration like "cpus=0" is not allowed. Values for any omitted parameters will be computed from those which are given. + + For example, the following sub-option defines a CPU topology hierarchy + (2 sockets totally on the machine, 2 cores per socket, 2 threads per + core) for a machine that only supports sockets/cores/threads. + Some members of the option can be omitted but their values will be + automatically computed: + + :: + + -smp 8,sockets=2,cores=2,threads=2,maxcpus=8 + + The following sub-option defines a CPU topology hierarchy (2 sockets + totally on the machine, 2 dies per socket, 2 cores per die, 2 threads + per core) for PC machines which support sockets/dies/cores/threads. + Some members of the option can be omitted but their values will be + automatically computed: + + :: + + -smp 16,sockets=2,dies=2,cores=2,threads=2,maxcpus=16 + Historically preference was given to the coarsest topology parameters when computing missing values (ie sockets preferred over cores, which were preferred over threads), however, this behaviour is considered liable to change. Prior to 6.2 the preference was sockets over cores over threads. Since 6.2 the preference is cores over sockets over threads. + + For example, the following option defines a machine board with 2 sockets + of 1 core before 6.2 and 1 socket of 2 cores after 6.2: + + :: + + -smp 2 ERST DEF("numa", HAS_ARG, QEMU_OPTION_numa, From 864c3b5c32f02d3507e6a63bdb8a652803c4bd1b Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Tue, 28 Dec 2021 17:22:09 +0800 Subject: [PATCH 133/730] hw/core/machine: Introduce CPU cluster topology support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new Cluster-Aware Scheduling support has landed in Linux 5.16, which has been proved to benefit the scheduling performance (e.g. load balance and wake_affine strategy) on both x86_64 and AArch64. So now in Linux 5.16 we have four-level arch-neutral CPU topology definition like below and a new scheduler level for clusters. struct cpu_topology { int thread_id; int core_id; int cluster_id; int package_id; int llc_id; cpumask_t thread_sibling; cpumask_t core_sibling; cpumask_t cluster_sibling; cpumask_t llc_sibling; } A cluster generally means a group of CPU cores which share L2 cache or other mid-level resources, and it is the shared resources that is used to improve scheduler's behavior. From the point of view of the size range, it's between CPU die and CPU core. For example, on some ARM64 Kunpeng servers, we have 6 clusters in each NUMA node, and 4 CPU cores in each cluster. The 4 CPU cores share a separate L2 cache and a L3 cache tag, which brings cache affinity advantage. In virtualization, on the Hosts which have pClusters (physical clusters), if we can design a vCPU topology with cluster level for guest kernel and have a dedicated vCPU pinning. A Cluster-Aware Guest kernel can also make use of the cache affinity of CPU clusters to gain similar scheduling performance. This patch adds infrastructure for CPU cluster level topology configuration and parsing, so that the user can specify cluster parameter if their machines support it. Signed-off-by: Yanan Wang Message-Id: <20211228092221.21068-3-wangyanan55@huawei.com> Reviewed-by: Philippe Mathieu-Daudé [PMD: Added '(since 7.0)' to @clusters in qapi/machine.json] Signed-off-by: Philippe Mathieu-Daudé --- hw/core/machine-smp.c | 26 +++++++++++++++++++------- hw/core/machine.c | 3 +++ include/hw/boards.h | 6 +++++- qapi/machine.json | 5 ++++- qemu-options.hx | 7 ++++--- softmmu/vl.c | 3 +++ 6 files changed, 38 insertions(+), 12 deletions(-) diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c index 2cbfd57429..b39ed21e65 100644 --- a/hw/core/machine-smp.c +++ b/hw/core/machine-smp.c @@ -37,6 +37,10 @@ static char *cpu_hierarchy_to_string(MachineState *ms) g_string_append_printf(s, " * dies (%u)", ms->smp.dies); } + if (mc->smp_props.clusters_supported) { + g_string_append_printf(s, " * clusters (%u)", ms->smp.clusters); + } + g_string_append_printf(s, " * cores (%u)", ms->smp.cores); g_string_append_printf(s, " * threads (%u)", ms->smp.threads); @@ -71,6 +75,7 @@ void machine_parse_smp_config(MachineState *ms, unsigned cpus = config->has_cpus ? config->cpus : 0; unsigned sockets = config->has_sockets ? config->sockets : 0; unsigned dies = config->has_dies ? config->dies : 0; + unsigned clusters = config->has_clusters ? config->clusters : 0; unsigned cores = config->has_cores ? config->cores : 0; unsigned threads = config->has_threads ? config->threads : 0; unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0; @@ -82,6 +87,7 @@ void machine_parse_smp_config(MachineState *ms, if ((config->has_cpus && config->cpus == 0) || (config->has_sockets && config->sockets == 0) || (config->has_dies && config->dies == 0) || + (config->has_clusters && config->clusters == 0) || (config->has_cores && config->cores == 0) || (config->has_threads && config->threads == 0) || (config->has_maxcpus && config->maxcpus == 0)) { @@ -97,8 +103,13 @@ void machine_parse_smp_config(MachineState *ms, error_setg(errp, "dies not supported by this machine's CPU topology"); return; } + if (!mc->smp_props.clusters_supported && clusters > 1) { + error_setg(errp, "clusters not supported by this machine's CPU topology"); + return; + } dies = dies > 0 ? dies : 1; + clusters = clusters > 0 ? clusters : 1; /* compute missing values based on the provided ones */ if (cpus == 0 && maxcpus == 0) { @@ -113,41 +124,42 @@ void machine_parse_smp_config(MachineState *ms, if (sockets == 0) { cores = cores > 0 ? cores : 1; threads = threads > 0 ? threads : 1; - sockets = maxcpus / (dies * cores * threads); + sockets = maxcpus / (dies * clusters * cores * threads); } else if (cores == 0) { threads = threads > 0 ? threads : 1; - cores = maxcpus / (sockets * dies * threads); + cores = maxcpus / (sockets * dies * clusters * threads); } } else { /* prefer cores over sockets since 6.2 */ if (cores == 0) { sockets = sockets > 0 ? sockets : 1; threads = threads > 0 ? threads : 1; - cores = maxcpus / (sockets * dies * threads); + cores = maxcpus / (sockets * dies * clusters * threads); } else if (sockets == 0) { threads = threads > 0 ? threads : 1; - sockets = maxcpus / (dies * cores * threads); + sockets = maxcpus / (dies * clusters * cores * threads); } } /* try to calculate omitted threads at last */ if (threads == 0) { - threads = maxcpus / (sockets * dies * cores); + threads = maxcpus / (sockets * dies * clusters * cores); } } - maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads; + maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * clusters * cores * threads; cpus = cpus > 0 ? cpus : maxcpus; ms->smp.cpus = cpus; ms->smp.sockets = sockets; ms->smp.dies = dies; + ms->smp.clusters = clusters; ms->smp.cores = cores; ms->smp.threads = threads; ms->smp.max_cpus = maxcpus; /* sanity-check of the computed topology */ - if (sockets * dies * cores * threads != maxcpus) { + if (sockets * dies * clusters * cores * threads != maxcpus) { g_autofree char *topo_msg = cpu_hierarchy_to_string(ms); error_setg(errp, "Invalid CPU topology: " "product of the hierarchy must match maxcpus: " diff --git a/hw/core/machine.c b/hw/core/machine.c index 3993c534b9..a4a2df405f 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -742,10 +742,12 @@ static void machine_get_smp(Object *obj, Visitor *v, const char *name, .has_cpus = true, .cpus = ms->smp.cpus, .has_sockets = true, .sockets = ms->smp.sockets, .has_dies = true, .dies = ms->smp.dies, + .has_clusters = true, .clusters = ms->smp.clusters, .has_cores = true, .cores = ms->smp.cores, .has_threads = true, .threads = ms->smp.threads, .has_maxcpus = true, .maxcpus = ms->smp.max_cpus, }; + if (!visit_type_SMPConfiguration(v, name, &config, &error_abort)) { return; } @@ -932,6 +934,7 @@ static void machine_initfn(Object *obj) ms->smp.max_cpus = mc->default_cpus; ms->smp.sockets = 1; ms->smp.dies = 1; + ms->smp.clusters = 1; ms->smp.cores = 1; ms->smp.threads = 1; } diff --git a/include/hw/boards.h b/include/hw/boards.h index 7597cec440..f49a2578ea 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -129,10 +129,12 @@ typedef struct { * SMPCompatProps: * @prefer_sockets - whether sockets are preferred over cores in smp parsing * @dies_supported - whether dies are supported by the machine + * @clusters_supported - whether clusters are supported by the machine */ typedef struct { bool prefer_sockets; bool dies_supported; + bool clusters_supported; } SMPCompatProps; /** @@ -299,7 +301,8 @@ typedef struct DeviceMemoryState { * @cpus: the number of present logical processors on the machine * @sockets: the number of sockets on the machine * @dies: the number of dies in one socket - * @cores: the number of cores in one die + * @clusters: the number of clusters in one die + * @cores: the number of cores in one cluster * @threads: the number of threads in one core * @max_cpus: the maximum number of logical processors on the machine */ @@ -307,6 +310,7 @@ typedef struct CpuTopology { unsigned int cpus; unsigned int sockets; unsigned int dies; + unsigned int clusters; unsigned int cores; unsigned int threads; unsigned int max_cpus; diff --git a/qapi/machine.json b/qapi/machine.json index edeab6084b..372535b348 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1404,7 +1404,9 @@ # # @dies: number of dies per socket in the CPU topology # -# @cores: number of cores per die in the CPU topology +# @clusters: number of clusters per die in the CPU topology (since 7.0) +# +# @cores: number of cores per cluster in the CPU topology # # @threads: number of threads per core in the CPU topology # @@ -1416,6 +1418,7 @@ '*cpus': 'int', '*sockets': 'int', '*dies': 'int', + '*clusters': 'int', '*cores': 'int', '*threads': 'int', '*maxcpus': 'int' } } diff --git a/qemu-options.hx b/qemu-options.hx index b39377de3f..fd1f8135fb 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -206,13 +206,14 @@ SRST ERST DEF("smp", HAS_ARG, QEMU_OPTION_smp, - "-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]\n" + "-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,clusters=clusters][,cores=cores][,threads=threads]\n" " set the number of initial CPUs to 'n' [default=1]\n" " maxcpus= maximum number of total CPUs, including\n" " offline CPUs for hotplug, etc\n" " sockets= number of sockets on the machine board\n" " dies= number of dies in one socket\n" - " cores= number of cores in one die\n" + " clusters= number of clusters in one die\n" + " cores= number of cores in one cluster\n" " threads= number of threads in one core\n" "Note: Different machines may have different subsets of the CPU topology\n" " parameters supported, so the actual meaning of the supported parameters\n" @@ -228,7 +229,7 @@ DEF("smp", HAS_ARG, QEMU_OPTION_smp, " must be set as 1 in the purpose of correct parsing.\n", QEMU_ARCH_ALL) SRST -``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]`` +``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,clusters=clusters][,cores=cores][,threads=threads]`` Simulate a SMP system with '\ ``n``\ ' CPUs initially present on the machine type board. On boards supporting CPU hotplug, the optional '\ ``maxcpus``\ ' parameter can be set to enable further CPUs to be diff --git a/softmmu/vl.c b/softmmu/vl.c index 620a1f1367..d9e4c619d3 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -726,6 +726,9 @@ static QemuOptsList qemu_smp_opts = { }, { .name = "dies", .type = QEMU_OPT_NUMBER, + }, { + .name = "clusters", + .type = QEMU_OPT_NUMBER, }, { .name = "cores", .type = QEMU_OPT_NUMBER, From e5ef89ae44f6720e32dc4f516b2e997d2377f08a Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Tue, 28 Dec 2021 17:22:11 +0800 Subject: [PATCH 134/730] tests/unit/test-smp-parse: Add testcases for CPU clusters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add testcases for parsing of the four-level CPU topology hierarchy, ie sockets/clusters/cores/threads, which will be supported on ARM virt machines. Signed-off-by: Yanan Wang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211228092221.21068-5-wangyanan55@huawei.com> Signed-off-by: Philippe Mathieu-Daudé --- tests/unit/test-smp-parse.c | 130 ++++++++++++++++++++++++++++++++++-- 1 file changed, 123 insertions(+), 7 deletions(-) diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index b6df8137fc..331719bbc4 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -61,6 +61,20 @@ .has_maxcpus = hf, .maxcpus = f, \ } +/* + * Currently a 4-level topology hierarchy is supported on ARM virt machines + * -sockets/clusters/cores/threads + */ +#define SMP_CONFIG_WITH_CLUSTERS(ha, a, hb, b, hc, c, hd, d, he, e, hf, f) \ + { \ + .has_cpus = ha, .cpus = a, \ + .has_sockets = hb, .sockets = b, \ + .has_clusters = hc, .clusters = c, \ + .has_cores = hd, .cores = d, \ + .has_threads = he, .threads = e, \ + .has_maxcpus = hf, .maxcpus = f, \ + } + /** * @config - the given SMP configuration * @expect_prefer_sockets - the expected parsing result for the @@ -290,6 +304,10 @@ static const struct SMPTestData data_generic_invalid[] = { /* config: -smp 2,dies=2 */ .config = SMP_CONFIG_WITH_DIES(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0), .expect_error = "dies not supported by this machine's CPU topology", + }, { + /* config: -smp 2,clusters=2 */ + .config = SMP_CONFIG_WITH_CLUSTERS(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0), + .expect_error = "clusters not supported by this machine's CPU topology", }, { /* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=8 */ .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 8), @@ -337,20 +355,40 @@ static const struct SMPTestData data_with_dies_invalid[] = { }, }; +static const struct SMPTestData data_with_clusters_invalid[] = { + { + /* config: -smp 16,sockets=2,clusters=2,cores=4,threads=2,maxcpus=16 */ + .config = SMP_CONFIG_WITH_CLUSTERS(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16), + .expect_error = "Invalid CPU topology: " + "product of the hierarchy must match maxcpus: " + "sockets (2) * clusters (2) * cores (4) * threads (2) " + "!= maxcpus (16)", + }, { + /* config: -smp 34,sockets=2,clusters=2,cores=4,threads=2,maxcpus=32 */ + .config = SMP_CONFIG_WITH_CLUSTERS(T, 34, T, 2, T, 2, T, 4, T, 2, T, 32), + .expect_error = "Invalid CPU topology: " + "maxcpus must be equal to or greater than smp: " + "sockets (2) * clusters (2) * cores (4) * threads (2) " + "== maxcpus (32) < smp_cpus (34)", + }, +}; + static char *smp_config_to_string(const SMPConfiguration *config) { return g_strdup_printf( "(SMPConfiguration) {\n" - " .has_cpus = %5s, cpus = %" PRId64 ",\n" - " .has_sockets = %5s, sockets = %" PRId64 ",\n" - " .has_dies = %5s, dies = %" PRId64 ",\n" - " .has_cores = %5s, cores = %" PRId64 ",\n" - " .has_threads = %5s, threads = %" PRId64 ",\n" - " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n" + " .has_cpus = %5s, cpus = %" PRId64 ",\n" + " .has_sockets = %5s, sockets = %" PRId64 ",\n" + " .has_dies = %5s, dies = %" PRId64 ",\n" + " .has_clusters = %5s, clusters = %" PRId64 ",\n" + " .has_cores = %5s, cores = %" PRId64 ",\n" + " .has_threads = %5s, threads = %" PRId64 ",\n" + " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n" "}", config->has_cpus ? "true" : "false", config->cpus, config->has_sockets ? "true" : "false", config->sockets, config->has_dies ? "true" : "false", config->dies, + config->has_clusters ? "true" : "false", config->clusters, config->has_cores ? "true" : "false", config->cores, config->has_threads ? "true" : "false", config->threads, config->has_maxcpus ? "true" : "false", config->maxcpus); @@ -363,11 +401,12 @@ static char *cpu_topology_to_string(const CpuTopology *topo) " .cpus = %u,\n" " .sockets = %u,\n" " .dies = %u,\n" + " .clusters = %u,\n" " .cores = %u,\n" " .threads = %u,\n" " .max_cpus = %u,\n" "}", - topo->cpus, topo->sockets, topo->dies, + topo->cpus, topo->sockets, topo->dies, topo->clusters, topo->cores, topo->threads, topo->max_cpus); } @@ -391,6 +430,7 @@ static void check_parse(MachineState *ms, const SMPConfiguration *config, (ms->smp.cpus == expect_topo->cpus) && (ms->smp.sockets == expect_topo->sockets) && (ms->smp.dies == expect_topo->dies) && + (ms->smp.clusters == expect_topo->clusters) && (ms->smp.cores == expect_topo->cores) && (ms->smp.threads == expect_topo->threads) && (ms->smp.max_cpus == expect_topo->max_cpus)) { @@ -472,6 +512,11 @@ static void unsupported_params_init(const MachineClass *mc, SMPTestData *data) data->expect_prefer_sockets.dies = 1; data->expect_prefer_cores.dies = 1; } + + if (!mc->smp_props.clusters_supported) { + data->expect_prefer_sockets.clusters = 1; + data->expect_prefer_cores.clusters = 1; + } } static void machine_base_class_init(ObjectClass *oc, void *data) @@ -491,6 +536,7 @@ static void machine_generic_valid_class_init(ObjectClass *oc, void *data) mc->max_cpus = MAX_CPUS; mc->smp_props.dies_supported = false; + mc->smp_props.clusters_supported = false; } static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) @@ -502,6 +548,7 @@ static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) mc->max_cpus = 511; mc->smp_props.dies_supported = false; + mc->smp_props.clusters_supported = false; } static void machine_with_dies_class_init(ObjectClass *oc, void *data) @@ -512,6 +559,18 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data) mc->max_cpus = MAX_CPUS; mc->smp_props.dies_supported = true; + mc->smp_props.clusters_supported = false; +} + +static void machine_with_clusters_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->min_cpus = MIN_CPUS; + mc->max_cpus = MAX_CPUS; + + mc->smp_props.clusters_supported = true; + mc->smp_props.dies_supported = false; } static void test_generic_valid(const void *opaque) @@ -607,6 +666,56 @@ static void test_with_dies(const void *opaque) object_unref(obj); } +static void test_with_clusters(const void *opaque) +{ + const char *machine_type = opaque; + Object *obj = object_new(machine_type); + MachineState *ms = MACHINE(obj); + MachineClass *mc = MACHINE_GET_CLASS(obj); + SMPTestData data = {}; + unsigned int num_clusters = 2; + int i; + + for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) { + data = data_generic_valid[i]; + unsupported_params_init(mc, &data); + + /* when clusters parameter is omitted, it will be set as 1 */ + data.expect_prefer_sockets.clusters = 1; + data.expect_prefer_cores.clusters = 1; + + smp_parse_test(ms, &data, true); + + /* when clusters parameter is specified */ + data.config.has_clusters = true; + data.config.clusters = num_clusters; + if (data.config.has_cpus) { + data.config.cpus *= num_clusters; + } + if (data.config.has_maxcpus) { + data.config.maxcpus *= num_clusters; + } + + data.expect_prefer_sockets.clusters = num_clusters; + data.expect_prefer_sockets.cpus *= num_clusters; + data.expect_prefer_sockets.max_cpus *= num_clusters; + data.expect_prefer_cores.clusters = num_clusters; + data.expect_prefer_cores.cpus *= num_clusters; + data.expect_prefer_cores.max_cpus *= num_clusters; + + smp_parse_test(ms, &data, true); + } + + for (i = 0; i < ARRAY_SIZE(data_with_clusters_invalid); i++) { + data = data_with_clusters_invalid[i]; + unsupported_params_init(mc, &data); + + smp_parse_test(ms, &data, false); + } + + object_unref(obj); +} + /* Type info of the tested machine */ static const TypeInfo smp_machine_types[] = { { @@ -628,6 +737,10 @@ static const TypeInfo smp_machine_types[] = { .name = MACHINE_TYPE_NAME("smp-with-dies"), .parent = TYPE_MACHINE, .class_init = machine_with_dies_class_init, + }, { + .name = MACHINE_TYPE_NAME("smp-with-clusters"), + .parent = TYPE_MACHINE, + .class_init = machine_with_clusters_class_init, } }; @@ -648,6 +761,9 @@ int main(int argc, char *argv[]) g_test_add_data_func("/test-smp-parse/with_dies", MACHINE_TYPE_NAME("smp-with-dies"), test_with_dies); + g_test_add_data_func("/test-smp-parse/with_clusters", + MACHINE_TYPE_NAME("smp-with-clusters"), + test_with_clusters); g_test_run(); From 16f573847697038fae6657e2ed84ad2e1c4786ad Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Tue, 28 Dec 2021 17:22:12 +0800 Subject: [PATCH 135/730] tests/unit/test-smp-parse: No need to explicitly zero MachineClass members MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default value of the MachineClass members is 0, which means we don't have to explicitly zero them. Also the value of "mc->smp_props.prefer_sockets" will be taken care of by smp_parse_test(), we don't necessarily need the statement in machine_base_class_init() either. Signed-off-by: Yanan Wang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211228092221.21068-6-wangyanan55@huawei.com> Signed-off-by: Philippe Mathieu-Daudé --- tests/unit/test-smp-parse.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index 331719bbc4..72d83d1bbc 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -523,8 +523,6 @@ static void machine_base_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); - mc->smp_props.prefer_sockets = true; - mc->name = g_strdup(SMP_MACHINE_NAME); } @@ -534,9 +532,6 @@ static void machine_generic_valid_class_init(ObjectClass *oc, void *data) mc->min_cpus = MIN_CPUS; mc->max_cpus = MAX_CPUS; - - mc->smp_props.dies_supported = false; - mc->smp_props.clusters_supported = false; } static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) @@ -546,9 +541,6 @@ static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) /* Force invalid min CPUs and max CPUs */ mc->min_cpus = 2; mc->max_cpus = 511; - - mc->smp_props.dies_supported = false; - mc->smp_props.clusters_supported = false; } static void machine_with_dies_class_init(ObjectClass *oc, void *data) @@ -559,7 +551,6 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data) mc->max_cpus = MAX_CPUS; mc->smp_props.dies_supported = true; - mc->smp_props.clusters_supported = false; } static void machine_with_clusters_class_init(ObjectClass *oc, void *data) @@ -570,7 +561,6 @@ static void machine_with_clusters_class_init(ObjectClass *oc, void *data) mc->max_cpus = MAX_CPUS; mc->smp_props.clusters_supported = true; - mc->smp_props.dies_supported = false; } static void test_generic_valid(const void *opaque) From a2348fa23247f565ef0b0fcc5679b2a6d5c3acf6 Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Tue, 28 Dec 2021 17:22:13 +0800 Subject: [PATCH 136/730] tests/unit/test-smp-parse: Keep default MIN/MAX CPUs in machine_base_class_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most machine types in test-smp-parse will be OK to have the default MIN/MAX CPUs except "smp-generic-invalid", let's keep the default values in machine_base_class_init which will be inherited. And if we hope a different value for a specific machine, modify it in its own initialization function. Signed-off-by: Yanan Wang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211228092221.21068-7-wangyanan55@huawei.com> Signed-off-by: Philippe Mathieu-Daudé --- tests/unit/test-smp-parse.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index 72d83d1bbc..fdc39a846c 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -523,15 +523,10 @@ static void machine_base_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); - mc->name = g_strdup(SMP_MACHINE_NAME); -} - -static void machine_generic_valid_class_init(ObjectClass *oc, void *data) -{ - MachineClass *mc = MACHINE_CLASS(oc); - mc->min_cpus = MIN_CPUS; mc->max_cpus = MAX_CPUS; + + mc->name = g_strdup(SMP_MACHINE_NAME); } static void machine_generic_invalid_class_init(ObjectClass *oc, void *data) @@ -547,9 +542,6 @@ static void machine_with_dies_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); - mc->min_cpus = MIN_CPUS; - mc->max_cpus = MAX_CPUS; - mc->smp_props.dies_supported = true; } @@ -557,9 +549,6 @@ static void machine_with_clusters_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); - mc->min_cpus = MIN_CPUS; - mc->max_cpus = MAX_CPUS; - mc->smp_props.clusters_supported = true; } @@ -718,7 +707,6 @@ static const TypeInfo smp_machine_types[] = { }, { .name = MACHINE_TYPE_NAME("smp-generic-valid"), .parent = TYPE_MACHINE, - .class_init = machine_generic_valid_class_init, }, { .name = MACHINE_TYPE_NAME("smp-generic-invalid"), .parent = TYPE_MACHINE, From da7595cad36fd8db17a0e812f656ee163bfa6701 Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Tue, 28 Dec 2021 17:22:14 +0800 Subject: [PATCH 137/730] MAINTAINERS: Self-recommended as reviewer of "Machine core" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I've built interests in the generic machine subsystem and have also been working on projects related to this part, self-recommand myself as a reviewer so that I can help to review some patches familiar to me, and have a chance to learn more continuously. Signed-off-by: Yanan Wang Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211228092221.21068-8-wangyanan55@huawei.com> Signed-off-by: Philippe Mathieu-Daudé --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 5456536805..fe5eea76f6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1631,6 +1631,7 @@ Machine core M: Eduardo Habkost M: Marcel Apfelbaum R: Philippe Mathieu-Daudé +R: Yanan Wang S: Supported F: cpu.c F: hw/core/cpu.c From 90f285fd8370f404a376adb63f1555a667689745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 29 Dec 2021 17:06:39 +0100 Subject: [PATCH 138/730] MAINTAINERS: Change philmd's email address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The philmd@redhat.com email address will stop working on 2022-01-01, change it to my personal email address. Update .mailmap in case anyone wants to send me an email because of some past commit I authored. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211231000759.707519-1-philmd@redhat.com> --- .gitlab-ci.d/edk2/Dockerfile | 2 +- .mailmap | 1 + MAINTAINERS | 18 +++++++++--------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.gitlab-ci.d/edk2/Dockerfile b/.gitlab-ci.d/edk2/Dockerfile index b4584d1cf6..13029310f6 100644 --- a/.gitlab-ci.d/edk2/Dockerfile +++ b/.gitlab-ci.d/edk2/Dockerfile @@ -3,7 +3,7 @@ # FROM ubuntu:16.04 -MAINTAINER Philippe Mathieu-Daudé +MAINTAINER Philippe Mathieu-Daudé # Install packages required to build EDK2 RUN apt update \ diff --git a/.mailmap b/.mailmap index c45d1c5301..5113f55b3a 100644 --- a/.mailmap +++ b/.mailmap @@ -63,6 +63,7 @@ Paul Burton Paul Burton Paul Burton Paul Burton +Philippe Mathieu-Daudé Stefan Brankovic Yongbok Kim diff --git a/MAINTAINERS b/MAINTAINERS index fe5eea76f6..ae6c74f3ff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1630,7 +1630,7 @@ F: pc-bios/bios-microvm.bin Machine core M: Eduardo Habkost M: Marcel Apfelbaum -R: Philippe Mathieu-Daudé +R: Philippe Mathieu-Daudé R: Yanan Wang S: Supported F: cpu.c @@ -1811,7 +1811,7 @@ F: docs/virtio-net-failover.rst T: git https://github.com/jasowang/qemu.git net Parallel NOR Flash devices -M: Philippe Mathieu-Daudé +M: Philippe Mathieu-Daudé T: git https://gitlab.com/philmd/qemu.git pflash-next S: Maintained F: hw/block/pflash_cfi*.c @@ -2227,7 +2227,7 @@ F: hw/isa/piix4.c F: include/hw/southbridge/piix.h Firmware configuration (fw_cfg) -M: Philippe Mathieu-Daudé +M: Philippe Mathieu-Daudé R: Gerd Hoffmann S: Supported F: docs/specs/fw_cfg.txt @@ -2525,7 +2525,7 @@ F: scripts/coccinelle/errp-guard.cocci GDB stub M: Alex Bennée -R: Philippe Mathieu-Daudé +R: Philippe Mathieu-Daudé S: Maintained F: gdbstub* F: include/exec/gdbstub.h @@ -2536,7 +2536,7 @@ Memory API M: Paolo Bonzini M: Peter Xu M: David Hildenbrand -R: Philippe Mathieu-Daudé +R: Philippe Mathieu-Daudé S: Supported F: include/exec/ioport.h F: include/exec/memop.h @@ -3030,14 +3030,14 @@ F: include/hw/i2c/smbus_slave.h F: include/hw/i2c/smbus_eeprom.h Firmware schema specifications -M: Philippe Mathieu-Daudé +M: Philippe Mathieu-Daudé R: Daniel P. Berrange R: Kashyap Chamarthy S: Maintained F: docs/interop/firmware.json EDK2 Firmware -M: Philippe Mathieu-Daudé +M: Philippe Mathieu-Daudé R: Gerd Hoffmann S: Supported F: hw/i386/*ovmf* @@ -3275,7 +3275,7 @@ F: block/null.c NVMe Block Driver M: Stefan Hajnoczi R: Fam Zheng -R: Philippe Mathieu-Daudé +R: Philippe Mathieu-Daudé L: qemu-block@nongnu.org S: Supported F: block/nvme* @@ -3518,7 +3518,7 @@ F: tests/tcg/Makefile.include Integration Testing with the Avocado framework W: https://trello.com/b/6Qi1pxVn/avocado-qemu R: Cleber Rosa -R: Philippe Mathieu-Daudé +R: Philippe Mathieu-Daudé R: Wainer dos Santos Moschetta R: Beraldo Leal S: Odd Fixes From 2ece6e64846e1929c4ed338c73328d3b126e48d3 Mon Sep 17 00:00:00 2001 From: Li Zhijian Date: Fri, 31 Dec 2021 13:09:01 +0800 Subject: [PATCH 139/730] MAINTAINERS: email address change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fujitsu's mail service has migrated to O365 months ago, the lizhijian@cn.fujitsu.com address will stop working on 2022-06-01, change it to my new email address lizhijian@fujitsu.com. Signed-off-by: Li Zhijian Acked-by: Zhang Chen Message-Id: <20211231050901.360-1-lizhijian@cn.fujitsu.com> Signed-off-by: Philippe Mathieu-Daudé --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index ae6c74f3ff..f871d759fd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2982,7 +2982,7 @@ F: docs/COLO-FT.txt COLO Proxy M: Zhang Chen -M: Li Zhijian +M: Li Zhijian S: Supported F: docs/colo-proxy.txt F: net/colo* From 5c23f0c3191907000bab278654570a7d5879822a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 3 Jan 2022 08:00:01 -0800 Subject: [PATCH 140/730] gitlab: Disable check-python-tox Set this test to be manually run, until failures can be fixed. Suggested-by: John Snow Signed-off-by: Richard Henderson --- .gitlab-ci.d/static_checks.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.d/static_checks.yml b/.gitlab-ci.d/static_checks.yml index 902843f8b3..5e955540d3 100644 --- a/.gitlab-ci.d/static_checks.yml +++ b/.gitlab-ci.d/static_checks.yml @@ -46,4 +46,6 @@ check-python-tox: QEMU_TOX_EXTRA_ARGS: --skip-missing-interpreters=false needs: job: python-container + rules: + - when: manual allow_failure: true From 316717feb32ae5dc64802d5c3a7d1e2beac9f155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:33 +0100 Subject: [PATCH 141/730] ppc/pnv: Change the maximum of PHB3 devices for Power8NVL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The POWER8 processors with a NVLink logic unit have 4 PHB3 devices per chip. Signed-off-by: Cédric Le Goater Reviewed-by: Daniel Henrique Barboza Message-Id: <20211222063817.1541058-2-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/ppc/pnv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 29ee0d0f08..9de8b83530 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1314,7 +1314,7 @@ static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ k->cores_mask = POWER8_CORE_MASK; - k->num_phbs = 3; + k->num_phbs = 4; k->core_pir = pnv_chip_core_pir_p8; k->intc_create = pnv_chip_power8_intc_create; k->intc_reset = pnv_chip_power8_intc_reset; From 81fbb57b7b0feee2db38c7416366f5cfc109bb9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 142/730] ppc/pnv: Remove PHB4 reset handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PHB4 reset handler was preparing ground for PHB5 to set appropriately the device id. We don't need it for the PHB4 since the device id is already set in the root port complex. PH5 will introduce its own. "device-id" property is now useless. It should be removed. Signed-off-by: Cédric Le Goater Reviewed-by: Daniel Henrique Barboza Message-Id: <20211222063817.1541058-3-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 1fbf7328f5..2074621405 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1230,18 +1230,6 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) phb->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs); } -static void pnv_phb4_reset(DeviceState *dev) -{ - PnvPHB4 *phb = PNV_PHB4(dev); - PCIDevice *root_dev = PCI_DEVICE(&phb->root); - - /* - * Configure PCI device id at reset using a property. - */ - pci_config_set_vendor_id(root_dev->config, PCI_VENDOR_ID_IBM); - pci_config_set_device_id(root_dev->config, phb->device_id); -} - static const char *pnv_phb4_root_bus_path(PCIHostState *host_bridge, PCIBus *rootbus) { @@ -1291,7 +1279,6 @@ static void pnv_phb4_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, pnv_phb4_properties); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->user_creatable = false; - dc->reset = pnv_phb4_reset; xfc->notify = pnv_phb4_xive_notify; } From c42b9c8b33e4334ba623c72408da06e96ead6f2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 143/730] ppc/pnv: Remove the PHB4 "device-id" property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's unused. Signed-off-by: Cédric Le Goater Reviewed-by: Daniel Henrique Barboza Message-Id: <20211222063817.1541058-4-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 1 - hw/pci-host/pnv_phb4_pec.c | 3 --- include/hw/pci-host/pnv_phb4.h | 2 -- 3 files changed, 6 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 2074621405..371abda5c6 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1262,7 +1262,6 @@ static Property pnv_phb4_properties[] = { DEFINE_PROP_UINT32("index", PnvPHB4, phb_id, 0), DEFINE_PROP_UINT32("chip-id", PnvPHB4, chip_id, 0), DEFINE_PROP_UINT64("version", PnvPHB4, version, 0), - DEFINE_PROP_UINT16("device-id", PnvPHB4, device_id, 0), DEFINE_PROP_LINK("stack", PnvPHB4, stack, TYPE_PNV_PHB4_PEC_STACK, PnvPhb4PecStack *), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 24a3adcae3..f3e4fa0c82 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -527,7 +527,6 @@ static void pnv_pec_class_init(ObjectClass *klass, void *data) pecc->stk_compat = stk_compat; pecc->stk_compat_size = sizeof(stk_compat); pecc->version = PNV_PHB4_VERSION; - pecc->device_id = PNV_PHB4_DEVICE_ID; pecc->num_stacks = pnv_pec_num_stacks; } @@ -587,8 +586,6 @@ static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) &error_fatal); object_property_set_int(OBJECT(&stack->phb), "version", pecc->version, &error_fatal); - object_property_set_int(OBJECT(&stack->phb), "device-id", pecc->device_id, - &error_fatal); object_property_set_link(OBJECT(&stack->phb), "stack", OBJECT(stack), &error_abort); if (!sysbus_realize(SYS_BUS_DEVICE(&stack->phb), errp)) { diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 60de3031a6..4a19338db3 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -84,7 +84,6 @@ struct PnvPHB4 { uint32_t phb_id; uint64_t version; - uint16_t device_id; char bus_path[8]; @@ -222,7 +221,6 @@ struct PnvPhb4PecClass { const char *stk_compat; int stk_compat_size; uint64_t version; - uint64_t device_id; const uint32_t *num_stacks; }; From dec4e2897ca97dea6318e50c1dabb65905e40d9c Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 144/730] pnv_phb3.c: do not set 'root-bus' as bus name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All pnv-phb3-root-bus buses are being created as 'root-bus'. This makes it impossible to, for example, add a pnv-phb3-root-port in a specific root bus, since they all have the same name. By default the device will be parented by the pnv-phb3 device that precedeced it in the QEMU command line. Moreover, this doesn't all for custom bus naming. Libvirt, for instance, likes to name these buses as 'pcie.N', where 'N' is the index value of the controller in the domain XML, by using the 'id' command line attribute. At this moment this is also being ignored - the created root bus will always be named 'root-bus'. This patch fixes both scenarios by removing the 'root-bus' name from the pci_register_root_bus() call. If an "id" is provided, use that. Otherwise use 'NULL' as bus name. The 'NULL' value will be handled in qbus_init_internal() and it will defaulted as lowercase bus type + the global bus_id value. After this path we can define the bus name by using the 'id' attribute: qemu-system-ppc64 -m 4G -machine powernv8,accel=tcg \ -device pnv-phb3,chip-id=0,index=1,id=pcie.0 dev: pnv-phb3, id "pcie.0" index = 1 (0x1) chip-id = 0 (0x0) x-config-reg-migration-enabled = true bypass-iommu = false bus: pcie.0 type pnv-phb3-root-bus And without an 'id' we will have the following default: qemu-system-ppc64 -m 4G -machine powernv8,accel=tcg \ -device pnv-phb3,chip-id=0,index=1 dev: pnv-phb3, id "" index = 1 (0x1) chip-id = 0 (0x0) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb3-root-bus.0 type pnv-phb3-root-bus Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20211228193806.1198496-3-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index c6e7871ecb..c78084cce7 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -1045,7 +1045,8 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) memory_region_init(&phb->pci_mmio, OBJECT(phb), "pci-mmio", PCI_MMIO_TOTAL_SIZE); - pci->bus = pci_register_root_bus(dev, "root-bus", + pci->bus = pci_register_root_bus(dev, + dev->id ? dev->id : NULL, pnv_phb3_set_irq, pnv_phb3_map_irq, phb, &phb->pci_mmio, &phb->pci_io, 0, 4, TYPE_PNV_PHB3_ROOT_BUS); From 9747d061cab131efd1dcaa321848e5d8b48992b3 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 145/730] pnv_phb4.c: do not set 'root-bus' as bus name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change has the same motivation as the one done for pnv-phb3-root-bus buses previously. Defaulting every bus to 'root-bus' makes it impossible to attach root ports to specific buses and it doesn't allow for custom bus naming because we're ignoring the 'id' value when registering the root bus. After this patch, creating pnv-phb4 devices with 'id' being set will result in the following qtree: qemu-system-ppc64 -m 4G -machine powernv9,accel=tcg \ -device pnv-phb4,chip-id=0,index=0,id=pcie.0 \ -device pnv-phb4,chip-id=1,index=4,id=pcie.1 bus: main-system-bus type System dev: pnv-phb4, id "pcie.1" index = 4 (0x4) chip-id = 1 (0x1) version = 704374636546 (0xa400000002) device-id = 1217 (0x4c1) x-config-reg-migration-enabled = true bypass-iommu = false bus: pcie.1 type pnv-phb4-root-bus dev: pnv-phb4, id "pcie.0" index = 0 (0x0) chip-id = 0 (0x0) version = 704374636546 (0xa400000002) device-id = 1217 (0x4c1) x-config-reg-migration-enabled = true bypass-iommu = false bus: pcie.0 type pnv-phb4-root-bus And without setting any ids: qemu-system-ppc64 -m 4G -machine powernv9,accel=tcg \ -device pnv-phb4,chip-id=0,index=0,id=pcie.0 \ -device pnv-phb4,chip-id=1,index=4,id=pcie.1 bus: main-system-bus type System dev: pnv-phb4, id "" index = 4 (0x4) chip-id = 1 (0x1) version = 704374636546 (0xa400000002) device-id = 1217 (0x4c1) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb4-root-bus.1 type pnv-phb4-root-bus dev: pnv-phb4, id "" index = 0 (0x0) chip-id = 0 (0x0) version = 704374636546 (0xa400000002) device-id = 1217 (0x4c1) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb4-root-bus.0 type pnv-phb4-root-bus Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20211228193806.1198496-17-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 371abda5c6..5ba26e250a 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1201,7 +1201,7 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) memory_region_init(&phb->pci_mmio, OBJECT(phb), name, PCI_MMIO_TOTAL_SIZE); - pci->bus = pci_register_root_bus(dev, "root-bus", + pci->bus = pci_register_root_bus(dev, dev->id, pnv_phb4_set_irq, pnv_phb4_map_irq, phb, &phb->pci_mmio, &phb->pci_io, 0, 4, TYPE_PNV_PHB4_ROOT_BUS); From 932de569708e59eb74c6c56800a4eb8d764cc97d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 146/730] target/ppc: Improve logging in Radix MMU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédric Le Goater Reviewed-by: Richard Henderson Message-Id: <20211222071002.1568894-1-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/mmu-radix64.c | 55 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index 5b0e62e676..d10ae001d7 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -97,12 +97,22 @@ static void ppc_radix64_raise_segi(PowerPCCPU *cpu, MMUAccessType access_type, env->error_code = 0; } +static inline const char *access_str(MMUAccessType access_type) +{ + return access_type == MMU_DATA_LOAD ? "reading" : + (access_type == MMU_DATA_STORE ? "writing" : "execute"); +} + static void ppc_radix64_raise_si(PowerPCCPU *cpu, MMUAccessType access_type, vaddr eaddr, uint32_t cause) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; + qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx" cause %08x\n", + __func__, access_str(access_type), + eaddr, cause); + switch (access_type) { case MMU_INST_FETCH: /* Instruction Storage Interrupt */ @@ -130,6 +140,11 @@ static void ppc_radix64_raise_hsi(PowerPCCPU *cpu, MMUAccessType access_type, CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; + qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx" 0x%" + HWADDR_PRIx" cause %08x\n", + __func__, access_str(access_type), + eaddr, g_raddr, cause); + switch (access_type) { case MMU_INST_FETCH: /* H Instruction Storage Interrupt */ @@ -306,6 +321,15 @@ static int ppc_radix64_partition_scoped_xlate(PowerPCCPU *cpu, hwaddr pte_addr; uint64_t pte; + qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx + " mmu_idx %u (prot %c%c%c) 0x%"HWADDR_PRIx"\n", + __func__, access_str(access_type), + eaddr, mmu_idx, + *h_prot & PAGE_READ ? 'r' : '-', + *h_prot & PAGE_WRITE ? 'w' : '-', + *h_prot & PAGE_EXEC ? 'x' : '-', + g_raddr); + *h_page_size = PRTBE_R_GET_RTS(pate.dw0); /* No valid pte or access denied due to protection */ if (ppc_radix64_walk_tree(CPU(cpu)->as, g_raddr, pate.dw0 & PRTBE_R_RPDB, @@ -343,6 +367,11 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, hwaddr h_raddr, pte_addr; int ret; + qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx + " mmu_idx %u pid %"PRIu64"\n", + __func__, access_str(access_type), + eaddr, mmu_idx, pid); + /* Index Process Table by PID to Find Corresponding Process Table Entry */ offset = pid * sizeof(struct prtb_entry); size = 1ULL << ((pate.dw1 & PATE1_R_PRTS) + 12); @@ -468,9 +497,10 @@ static int ppc_radix64_process_scoped_xlate(PowerPCCPU *cpu, * | = On | Process Scoped | Scoped | * +-------------+----------------+---------------+ */ -bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, - hwaddr *raddr, int *psizep, int *protp, int mmu_idx, - bool guest_visible) +static bool ppc_radix64_xlate_impl(PowerPCCPU *cpu, vaddr eaddr, + MMUAccessType access_type, hwaddr *raddr, + int *psizep, int *protp, int mmu_idx, + bool guest_visible) { CPUPPCState *env = &cpu->env; uint64_t lpid, pid; @@ -588,3 +618,22 @@ bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, return true; } + +bool ppc_radix64_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type, + hwaddr *raddrp, int *psizep, int *protp, int mmu_idx, + bool guest_visible) +{ + bool ret = ppc_radix64_xlate_impl(cpu, eaddr, access_type, raddrp, + psizep, protp, mmu_idx, guest_visible); + + qemu_log_mask(CPU_LOG_MMU, "%s for %s @0x%"VADDR_PRIx + " mmu_idx %u (prot %c%c%c) -> 0x%"HWADDR_PRIx"\n", + __func__, access_str(access_type), + eaddr, mmu_idx, + *protp & PAGE_READ ? 'r' : '-', + *protp & PAGE_WRITE ? 'w' : '-', + *protp & PAGE_EXEC ? 'x' : '-', + *raddrp); + + return ret; +} From 9b4eaee4d47c912eb1449953ba3258f11600153a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 147/730] target/ppc: Check effective address validity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For Radix translation, the EA range is 64-bits. when EA(2:11) are nonzero, a segment interrupt should occur. Signed-off-by: Cédric Le Goater Reviewed-by: Frederic Barrat Message-Id: <20211231073122.3183583-1-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/mmu-radix64.c | 5 +++++ target/ppc/mmu-radix64.h | 1 + 2 files changed, 6 insertions(+) diff --git a/target/ppc/mmu-radix64.c b/target/ppc/mmu-radix64.c index d10ae001d7..040c055bff 100644 --- a/target/ppc/mmu-radix64.c +++ b/target/ppc/mmu-radix64.c @@ -32,6 +32,11 @@ static bool ppc_radix64_get_fully_qualified_addr(const CPUPPCState *env, vaddr eaddr, uint64_t *lpid, uint64_t *pid) { + /* When EA(2:11) are nonzero, raise a segment interrupt */ + if (eaddr & ~R_EADDR_VALID_MASK) { + return false; + } + if (msr_hv) { /* MSR[HV] -> Hypervisor/bare metal */ switch (eaddr & R_EADDR_QUADRANT) { case R_EADDR_QUADRANT0: diff --git a/target/ppc/mmu-radix64.h b/target/ppc/mmu-radix64.h index b70357cf34..4c768aa5cc 100644 --- a/target/ppc/mmu-radix64.h +++ b/target/ppc/mmu-radix64.h @@ -5,6 +5,7 @@ /* Radix Quadrants */ #define R_EADDR_MASK 0x3FFFFFFFFFFFFFFF +#define R_EADDR_VALID_MASK 0xC00FFFFFFFFFFFFF #define R_EADDR_QUADRANT 0xC000000000000000 #define R_EADDR_QUADRANT0 0x0000000000000000 #define R_EADDR_QUADRANT1 0x4000000000000000 From 62e79ef9144d5b8bf89848a59ecb62fad2f52c1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 148/730] target/ppc: Remove static inline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The compiler should know better how to inline code if necessary. Suggested-by: Richard Henderson Signed-off-by: Cédric Le Goater Reviewed-by: Richard Henderson Message-Id: <20220103063441.3424853-2-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index f90e616aac..8ba93d25ae 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -36,7 +36,7 @@ /* Exception processing */ #if !defined(CONFIG_USER_ONLY) -static inline void dump_syscall(CPUPPCState *env) +static void dump_syscall(CPUPPCState *env) { qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 @@ -48,7 +48,7 @@ static inline void dump_syscall(CPUPPCState *env) ppc_dump_gpr(env, 8), env->nip); } -static inline void dump_hcall(CPUPPCState *env) +static void dump_hcall(CPUPPCState *env) { qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 @@ -161,7 +161,7 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, * | a | h | 11 | 1 | 1 | h | * +--------------------------------------------------------------------+ */ -static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp, +static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp, target_ulong msr, target_ulong *new_msr, target_ulong *vector) @@ -258,7 +258,7 @@ static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp, #endif } -static inline void powerpc_set_excp_state(PowerPCCPU *cpu, +static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector, target_ulong msr) { CPUState *cs = CPU(cpu); @@ -293,7 +293,7 @@ static inline void powerpc_set_excp_state(PowerPCCPU *cpu, * Note that this function should be greatly optimized when called * with a constant excp, from ppc_hw_interrupt */ -static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) +static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -1167,7 +1167,7 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn) #endif /* defined(TARGET_PPC64) */ #endif /* CONFIG_TCG */ -static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) +static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) { CPUState *cs = env_cpu(env); From 6789f23b6484960b8665f6f661188dfecccdacb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 149/730] target/ppc: Print out literal exception names in logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It facilitates reading the logs when mask CPU_LOG_INT is activated. We should do the same for error codes. Cc: Fabiano Rosas Signed-off-by: Cédric Le Goater Reviewed-by: Fabiano Rosas Reviewed-by: David Gibson Reviewed-by: Richard Henderson Message-Id: <20211222064025.1541490-2-clg@kaod.org> Signed-off-by: Cédric Le Goater Message-Id: <20220103063441.3424853-3-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 75 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 8ba93d25ae..e3380722c5 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -36,6 +36,78 @@ /* Exception processing */ #if !defined(CONFIG_USER_ONLY) +static const char *powerpc_excp_name(int excp) +{ + switch (excp) { + case POWERPC_EXCP_CRITICAL: return "CRITICAL"; + case POWERPC_EXCP_MCHECK: return "MCHECK"; + case POWERPC_EXCP_DSI: return "DSI"; + case POWERPC_EXCP_ISI: return "ISI"; + case POWERPC_EXCP_EXTERNAL: return "EXTERNAL"; + case POWERPC_EXCP_ALIGN: return "ALIGN"; + case POWERPC_EXCP_PROGRAM: return "PROGRAM"; + case POWERPC_EXCP_FPU: return "FPU"; + case POWERPC_EXCP_SYSCALL: return "SYSCALL"; + case POWERPC_EXCP_APU: return "APU"; + case POWERPC_EXCP_DECR: return "DECR"; + case POWERPC_EXCP_FIT: return "FIT"; + case POWERPC_EXCP_WDT: return "WDT"; + case POWERPC_EXCP_DTLB: return "DTLB"; + case POWERPC_EXCP_ITLB: return "ITLB"; + case POWERPC_EXCP_DEBUG: return "DEBUG"; + case POWERPC_EXCP_SPEU: return "SPEU"; + case POWERPC_EXCP_EFPDI: return "EFPDI"; + case POWERPC_EXCP_EFPRI: return "EFPRI"; + case POWERPC_EXCP_EPERFM: return "EPERFM"; + case POWERPC_EXCP_DOORI: return "DOORI"; + case POWERPC_EXCP_DOORCI: return "DOORCI"; + case POWERPC_EXCP_GDOORI: return "GDOORI"; + case POWERPC_EXCP_GDOORCI: return "GDOORCI"; + case POWERPC_EXCP_HYPPRIV: return "HYPPRIV"; + case POWERPC_EXCP_RESET: return "RESET"; + case POWERPC_EXCP_DSEG: return "DSEG"; + case POWERPC_EXCP_ISEG: return "ISEG"; + case POWERPC_EXCP_HDECR: return "HDECR"; + case POWERPC_EXCP_TRACE: return "TRACE"; + case POWERPC_EXCP_HDSI: return "HDSI"; + case POWERPC_EXCP_HISI: return "HISI"; + case POWERPC_EXCP_HDSEG: return "HDSEG"; + case POWERPC_EXCP_HISEG: return "HISEG"; + case POWERPC_EXCP_VPU: return "VPU"; + case POWERPC_EXCP_PIT: return "PIT"; + case POWERPC_EXCP_IO: return "IO"; + case POWERPC_EXCP_RUNM: return "RUNM"; + case POWERPC_EXCP_EMUL: return "EMUL"; + case POWERPC_EXCP_IFTLB: return "IFTLB"; + case POWERPC_EXCP_DLTLB: return "DLTLB"; + case POWERPC_EXCP_DSTLB: return "DSTLB"; + case POWERPC_EXCP_FPA: return "FPA"; + case POWERPC_EXCP_DABR: return "DABR"; + case POWERPC_EXCP_IABR: return "IABR"; + case POWERPC_EXCP_SMI: return "SMI"; + case POWERPC_EXCP_PERFM: return "PERFM"; + case POWERPC_EXCP_THERM: return "THERM"; + case POWERPC_EXCP_VPUA: return "VPUA"; + case POWERPC_EXCP_SOFTP: return "SOFTP"; + case POWERPC_EXCP_MAINT: return "MAINT"; + case POWERPC_EXCP_MEXTBR: return "MEXTBR"; + case POWERPC_EXCP_NMEXTBR: return "NMEXTBR"; + case POWERPC_EXCP_ITLBE: return "ITLBE"; + case POWERPC_EXCP_DTLBE: return "DTLBE"; + case POWERPC_EXCP_VSXU: return "VSXU"; + case POWERPC_EXCP_FU: return "FU"; + case POWERPC_EXCP_HV_EMU: return "HV_EMU"; + case POWERPC_EXCP_HV_MAINT: return "HV_MAINT"; + case POWERPC_EXCP_HV_FU: return "HV_FU"; + case POWERPC_EXCP_SDOOR: return "SDOOR"; + case POWERPC_EXCP_SDOOR_HV: return "SDOOR_HV"; + case POWERPC_EXCP_HVIRT: return "HVIRT"; + case POWERPC_EXCP_SYSCALL_VECTORED: return "SYSCALL_VECTORED"; + default: + g_assert_not_reached(); + } +} + static void dump_syscall(CPUPPCState *env) { qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 @@ -301,7 +373,8 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) int srr0, srr1, asrr0, asrr1, lev = -1; qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx - " => %08x (%02x)\n", env->nip, excp, env->error_code); + " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp), + excp, env->error_code); /* new srr1 value excluding must-be-zero bits */ if (excp_model == POWERPC_EXCP_BOOKE) { From b3b5c5d38f42f74e8338d864e60f2f0754978131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 150/730] ppc/ppc4xx: Convert printfs() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a QEMU log primitive for errors and trace events for debug. Signed-off-by: Cédric Le Goater Reviewed-by: David Gibson Reviewed-by: Richard Henderson Message-Id: <20211222064025.1541490-3-clg@kaod.org> Signed-off-by: Cédric Le Goater Message-Id: <20220103063441.3424853-4-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/ppc/mpc8544_guts.c | 9 ++++++--- hw/ppc/ppc4xx_devs.c | 39 +++++++++++---------------------------- hw/ppc/ppc4xx_pci.c | 11 +++++++---- hw/ppc/trace-events | 5 +++++ 4 files changed, 29 insertions(+), 35 deletions(-) diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c index e8d2d51c20..a26e83d048 100644 --- a/hw/ppc/mpc8544_guts.c +++ b/hw/ppc/mpc8544_guts.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" +#include "qemu/log.h" #include "sysemu/runstate.h" #include "cpu.h" #include "hw/sysbus.h" @@ -82,7 +83,9 @@ static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr, value = env->spr[SPR_E500_SVR]; break; default: - fprintf(stderr, "guts: Unknown register read: %x\n", (int)addr); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Unknown register 0x%" HWADDR_PRIx "\n", + __func__, addr); break; } @@ -101,8 +104,8 @@ static void mpc8544_guts_write(void *opaque, hwaddr addr, } break; default: - fprintf(stderr, "guts: Unknown register write: %x = %x\n", - (int)addr, (unsigned)value); + qemu_log_mask(LOG_GUEST_ERROR, "%s: Unknown register 0x%" HWADDR_PRIx + " = 0x%" PRIx64 "\n", __func__, addr, value); break; } } diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 980c48944f..e7d82ae501 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -35,14 +35,7 @@ #include "exec/address-spaces.h" #include "qemu/error-report.h" #include "qapi/error.h" - -/*#define DEBUG_UIC*/ - -#ifdef DEBUG_UIC -# define LOG_UIC(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__) -#else -# define LOG_UIC(...) do { } while (0) -#endif +#include "trace.h" static void ppc4xx_reset(void *opaque) { @@ -137,8 +130,9 @@ static uint32_t sdram_bcr (hwaddr ram_base, bcr = 0x000C0000; break; default: - printf("%s: invalid RAM size " TARGET_FMT_plx "\n", __func__, - ram_size); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid RAM size 0x%" HWADDR_PRIx "\n", __func__, + ram_size); return 0x00000000; } bcr |= ram_base & 0xFF800000; @@ -171,10 +165,8 @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i, { if (sdram->bcr[i] & 0x00000001) { /* Unmap RAM */ -#ifdef DEBUG_SDRAM - printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n", - __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i])); -#endif + trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]), + sdram_size(sdram->bcr[i])); memory_region_del_subregion(get_system_memory(), &sdram->containers[i]); memory_region_del_subregion(&sdram->containers[i], @@ -183,10 +175,7 @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i, } sdram->bcr[i] = bcr & 0xFFDEE001; if (enabled && (bcr & 0x00000001)) { -#ifdef DEBUG_SDRAM - printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n", - __func__, sdram_base(bcr), sdram_size(bcr)); -#endif + trace_ppc4xx_sdram_unmap(sdram_base(bcr), sdram_size(bcr)); memory_region_init(&sdram->containers[i], NULL, "sdram-containers", sdram_size(bcr)); memory_region_add_subregion(&sdram->containers[i], 0, @@ -216,10 +205,8 @@ static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram) int i; for (i = 0; i < sdram->nbanks; i++) { -#ifdef DEBUG_SDRAM - printf("%s: Unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n", - __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i])); -#endif + trace_ppc4xx_sdram_unmap(sdram_base(sdram->bcr[i]), + sdram_size(sdram->bcr[i])); memory_region_del_subregion(get_system_memory(), &sdram->ram_memories[i]); } @@ -316,16 +303,12 @@ static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val) case 0x20: /* SDRAM_CFG */ val &= 0xFFE00000; if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) { -#ifdef DEBUG_SDRAM - printf("%s: enable SDRAM controller\n", __func__); -#endif + trace_ppc4xx_sdram_enable("enable"); /* validate all RAM mappings */ sdram_map_bcr(sdram); sdram->status &= ~0x80000000; } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) { -#ifdef DEBUG_SDRAM - printf("%s: disable SDRAM controller\n", __func__); -#endif + trace_ppc4xx_sdram_enable("disable"); /* invalidate all RAM mappings */ sdram_unmap_bcr(sdram); sdram->status |= 0x80000000; diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index 304a29349c..5df97e6d15 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -20,6 +20,7 @@ * 4xx SoCs, such as the 440EP. */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "hw/irq.h" #include "hw/ppc/ppc.h" #include "hw/ppc/ppc4xx.h" @@ -152,8 +153,9 @@ static void ppc4xx_pci_reg_write4(void *opaque, hwaddr offset, break; default: - printf("%s: unhandled PCI internal register 0x%lx\n", __func__, - (unsigned long)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: unhandled PCI internal register 0x%" HWADDR_PRIx "\n", + __func__, offset); break; } } @@ -218,8 +220,9 @@ static uint64_t ppc4xx_pci_reg_read4(void *opaque, hwaddr offset, break; default: - printf("%s: invalid PCI internal register 0x%lx\n", __func__, - (unsigned long)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid PCI internal register 0x%" HWADDR_PRIx "\n", + __func__, offset); value = 0; } diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index ada644652d..0c55aa5014 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -164,3 +164,8 @@ ppc4xx_gpt_init(uint64_t addr) "offet 0x%" PRIx64 ppc405ep_clocks_compute(const char *param, uint32_t param2, uint32_t val) "%s 0x%1" PRIx32 " %d" ppc405ep_clocks_setup(const char *trace) "%s" + +# ppc4xx_devs.c +ppc4xx_sdram_enable(const char *trace) "%s SDRAM controller" +ppc4xx_sdram_unmap(uint64_t addr, uint64_t size) "Unmap RAM area 0x%" PRIx64 " size 0x%" PRIx64 +ppc4xx_sdram_map(uint64_t addr, uint64_t size) "Map RAM area 0x%" PRIx64 " size 0x%" PRIx64 From 56964585a051daf2f27a6e81adf87f58952b783a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 151/730] ppc/ppc405: Activate MMU logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to deactivate MMU logging at compile time. Remove all use of defines. Only keep DUMP_PAGE_TABLES for another series since page tables could be dumped from the monitor. Signed-off-by: Cédric Le Goater Message-Id: <20211222064025.1541490-4-clg@kaod.org> Signed-off-by: Cédric Le Goater Reviewed-by: Richard Henderson Message-Id: <20220103063441.3424853-5-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/mmu_common.c | 164 +++++++++++++++++++--------------------- target/ppc/mmu_helper.c | 97 +++++++++++------------- 2 files changed, 122 insertions(+), 139 deletions(-) diff --git a/target/ppc/mmu_common.c b/target/ppc/mmu_common.c index 4e278365ca..91270c1f17 100644 --- a/target/ppc/mmu_common.c +++ b/target/ppc/mmu_common.c @@ -34,29 +34,7 @@ #include "mmu-book3s-v3.h" #include "mmu-radix64.h" -/* #define DEBUG_MMU */ -/* #define DEBUG_BATS */ -/* #define DEBUG_SOFTWARE_TLB */ /* #define DUMP_PAGE_TABLES */ -/* #define FLUSH_ALL_TLBS */ - -#ifdef DEBUG_MMU -# define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0) -#else -# define LOG_MMU_STATE(cpu) do { } while (0) -#endif - -#ifdef DEBUG_SOFTWARE_TLB -# define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__) -#else -# define LOG_SWTLB(...) do { } while (0) -#endif - -#ifdef DEBUG_BATS -# define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__) -#else -# define LOG_BATS(...) do { } while (0) -#endif void ppc_store_sdr1(CPUPPCState *env, target_ulong value) { @@ -231,18 +209,20 @@ static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx, tlb = &env->tlb.tlb6[nr]; /* This test "emulates" the PTE index match for hardware TLBs */ if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) { - LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx - "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb, - pte_is_valid(tlb->pte0) ? "valid" : "inval", - tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr); + qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx + " " TARGET_FMT_lx "] <> " TARGET_FMT_lx "\n", + nr, env->nb_tlb, + pte_is_valid(tlb->pte0) ? "valid" : "inval", + tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr); continue; } - LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " " - TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb, - pte_is_valid(tlb->pte0) ? "valid" : "inval", - tlb->EPN, eaddr, tlb->pte1, - access_type == MMU_DATA_STORE ? 'S' : 'L', - access_type == MMU_INST_FETCH ? 'I' : 'D'); + qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s " TARGET_FMT_lx " <> " + TARGET_FMT_lx " " TARGET_FMT_lx " %c %c\n", + nr, env->nb_tlb, + pte_is_valid(tlb->pte0) ? "valid" : "inval", + tlb->EPN, eaddr, tlb->pte1, + access_type == MMU_DATA_STORE ? 'S' : 'L', + access_type == MMU_INST_FETCH ? 'I' : 'D'); switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1, 0, access_type)) { case -3: @@ -272,8 +252,9 @@ static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx, } if (best != -1) { done: - LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n", - ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret); + qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " TARGET_FMT_plx + " prot=%01x ret=%d\n", + ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret); /* Update page flags */ pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, access_type); } @@ -317,7 +298,7 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, int ret = -1; bool ifetch = access_type == MMU_INST_FETCH; - LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__, + qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT v " TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D', virtual); if (ifetch) { BATlt = env->IBAT[1]; @@ -332,9 +313,9 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, BEPIu = *BATu & 0xF0000000; BEPIl = *BATu & 0x0FFE0000; bat_size_prot(env, &bl, &valid, &prot, BATu, BATl); - LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx - " BATl " TARGET_FMT_lx "\n", __func__, - ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl); + qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu " + TARGET_FMT_lx " BATl " TARGET_FMT_lx "\n", __func__, + ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl); if ((virtual & 0xF0000000) == BEPIu && ((virtual & 0x0FFE0000) & ~bl) == BEPIl) { /* BAT matches */ @@ -347,32 +328,33 @@ static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, ctx->prot = prot; ret = check_prot(ctx->prot, access_type); if (ret == 0) { - LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n", - i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-', - ctx->prot & PAGE_WRITE ? 'W' : '-'); + qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " TARGET_FMT_plx + " prot=%c%c\n", i, ctx->raddr, + ctx->prot & PAGE_READ ? 'R' : '-', + ctx->prot & PAGE_WRITE ? 'W' : '-'); } break; } } } if (ret < 0) { -#if defined(DEBUG_BATS) if (qemu_log_enabled()) { - LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual); + qemu_log_mask(CPU_LOG_MMU, "no BAT match for " + TARGET_FMT_lx ":\n", virtual); for (i = 0; i < 4; i++) { BATu = &BATut[i]; BATl = &BATlt[i]; BEPIu = *BATu & 0xF0000000; BEPIl = *BATu & 0x0FFE0000; bl = (*BATu & 0x00001FFC) << 15; - LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx - " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " " - TARGET_FMT_lx " " TARGET_FMT_lx "\n", - __func__, ifetch ? 'I' : 'D', i, virtual, - *BATu, *BATl, BEPIu, BEPIl, bl); + qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " + TARGET_FMT_lx " BATu " TARGET_FMT_lx + " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " " + TARGET_FMT_lx " " TARGET_FMT_lx "\n", + __func__, ifetch ? 'I' : 'D', i, virtual, + *BATu, *BATl, BEPIu, BEPIl, bl); } } -#endif } /* No hit */ return ret; @@ -401,11 +383,12 @@ static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx, vsid = sr & 0x00FFFFFF; target_page_bits = TARGET_PAGE_BITS; qemu_log_mask(CPU_LOG_MMU, - "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx - " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx - " ir=%d dr=%d pr=%d %d t=%d\n", - eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir, - (int)msr_dr, pr != 0 ? 1 : 0, access_type == MMU_DATA_STORE, type); + "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx + " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx + " ir=%d dr=%d pr=%d %d t=%d\n", + eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir, + (int)msr_dr, pr != 0 ? 1 : 0, + access_type == MMU_DATA_STORE, type); pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits; hash = vsid ^ pgidx; ctx->ptem = (vsid << 7) | (pgidx >> 10); @@ -536,9 +519,10 @@ int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb, return -1; } mask = ~(tlb->size - 1); - LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx - " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN, - mask, (uint32_t)tlb->PID, tlb->prot); + qemu_log_mask(CPU_LOG_MMU, "%s: TLB %d address " TARGET_FMT_lx + " PID %u <=> " TARGET_FMT_lx " " TARGET_FMT_lx " %u %x\n", + __func__, i, address, pid, tlb->EPN, + mask, (uint32_t)tlb->PID, tlb->prot); /* Check PID */ if (tlb->PID != 0 && tlb->PID != pid) { return -1; @@ -575,8 +559,9 @@ static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, } zsel = (tlb->attr >> 4) & 0xF; zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3; - LOG_SWTLB("%s: TLB %d zsel %d zpr %d ty %d attr %08x\n", - __func__, i, zsel, zpr, access_type, tlb->attr); + qemu_log_mask(CPU_LOG_MMU, + "%s: TLB %d zsel %d zpr %d ty %d attr %08x\n", + __func__, i, zsel, zpr, access_type, tlb->attr); /* Check execute enable bit */ switch (zpr) { case 0x2: @@ -610,14 +595,16 @@ static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, } if (ret >= 0) { ctx->raddr = raddr; - LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx - " %d %d\n", __func__, address, ctx->raddr, ctx->prot, - ret); + qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx + " => " TARGET_FMT_plx + " %d %d\n", __func__, address, ctx->raddr, ctx->prot, + ret); return 0; } } - LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx - " %d %d\n", __func__, address, raddr, ctx->prot, ret); + qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx + " => " TARGET_FMT_plx + " %d %d\n", __func__, address, raddr, ctx->prot, ret); return ret; } @@ -646,7 +633,7 @@ static int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb, goto found_tlb; } - LOG_SWTLB("%s: TLB entry not found\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: TLB entry not found\n", __func__); return -1; found_tlb: @@ -659,17 +646,17 @@ found_tlb: /* Check the address space */ if ((access_type == MMU_INST_FETCH ? msr_ir : msr_dr) != (tlb->attr & 1)) { - LOG_SWTLB("%s: AS doesn't match\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__); return -1; } *prot = prot2; if (prot2 & prot_for_access_type(access_type)) { - LOG_SWTLB("%s: good TLB!\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__); return 0; } - LOG_SWTLB("%s: no prot match: %x\n", __func__, prot2); + qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, prot2); return access_type == MMU_INST_FETCH ? -3 : -2; } @@ -694,12 +681,13 @@ static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx, if (ret >= 0) { ctx->raddr = raddr; - LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx - " %d %d\n", __func__, address, ctx->raddr, ctx->prot, - ret); + qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx + " => " TARGET_FMT_plx " %d %d\n", __func__, + address, ctx->raddr, ctx->prot, ret); } else { - LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx - " %d %d\n", __func__, address, raddr, ctx->prot, ret); + qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx + " => " TARGET_FMT_plx " %d %d\n", __func__, + address, raddr, ctx->prot, ret); } return ret; @@ -734,10 +722,11 @@ int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, } mask = ~(booke206_tlb_to_page_size(env, tlb) - 1); - LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%" - PRIx64 " mask=0x%" HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" - PRIx32 "\n", __func__, address, pid, tlb->mas1, tlb->mas2, mask, - tlb->mas7_3, tlb->mas8); + qemu_log_mask(CPU_LOG_MMU, "%s: TLB ADDR=0x" TARGET_FMT_lx + " PID=0x%x MAS1=0x%x MAS2=0x%" PRIx64 " mask=0x%" + HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%" PRIx32 "\n", + __func__, address, pid, tlb->mas1, tlb->mas2, mask, + tlb->mas7_3, tlb->mas8); /* Check PID */ tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT; @@ -838,7 +827,7 @@ static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb, } } - LOG_SWTLB("%s: TLB entry not found\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: TLB entry not found\n", __func__); return -1; found_tlb: @@ -873,17 +862,17 @@ found_tlb: } if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) { - LOG_SWTLB("%s: AS doesn't match\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: AS doesn't match\n", __func__); return -1; } *prot = prot2; if (prot2 & prot_for_access_type(access_type)) { - LOG_SWTLB("%s: good TLB!\n", __func__); + qemu_log_mask(CPU_LOG_MMU, "%s: good TLB!\n", __func__); return 0; } - LOG_SWTLB("%s: no prot match: %x\n", __func__, prot2); + qemu_log_mask(CPU_LOG_MMU, "%s: no prot match: %x\n", __func__, prot2); return access_type == MMU_INST_FETCH ? -3 : -2; } @@ -919,12 +908,13 @@ found_tlb: if (ret >= 0) { ctx->raddr = raddr; - LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx - " %d %d\n", __func__, address, ctx->raddr, ctx->prot, - ret); + qemu_log_mask(CPU_LOG_MMU, "%s: access granted " TARGET_FMT_lx + " => " TARGET_FMT_plx " %d %d\n", __func__, address, + ctx->raddr, ctx->prot, ret); } else { - LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx - " %d %d\n", __func__, address, raddr, ctx->prot, ret); + qemu_log_mask(CPU_LOG_MMU, "%s: access refused " TARGET_FMT_lx + " => " TARGET_FMT_plx " %d %d\n", __func__, address, + raddr, ctx->prot, ret); } return ret; @@ -1338,7 +1328,7 @@ static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr, } if (guest_visible) { - LOG_MMU_STATE(cs); + log_cpu_state_mask(CPU_LOG_MMU, cs, 0); if (type == ACCESS_CODE) { switch (ret) { case -1: diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c index 2ec3d203a0..59df6952ae 100644 --- a/target/ppc/mmu_helper.c +++ b/target/ppc/mmu_helper.c @@ -36,23 +36,8 @@ #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" -/* #define DEBUG_BATS */ -/* #define DEBUG_SOFTWARE_TLB */ -/* #define DUMP_PAGE_TABLES */ /* #define FLUSH_ALL_TLBS */ -#ifdef DEBUG_SOFTWARE_TLB -# define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__) -#else -# define LOG_SWTLB(...) do { } while (0) -#endif - -#ifdef DEBUG_BATS -# define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__) -#else -# define LOG_BATS(...) do { } while (0) -#endif - /*****************************************************************************/ /* PowerPC MMU emulation */ @@ -89,8 +74,8 @@ static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState *env, nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code); tlb = &env->tlb.tlb6[nr]; if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) { - LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr, - env->nb_tlb, eaddr); + qemu_log_mask(CPU_LOG_MMU, "TLB invalidate %d/%d " + TARGET_FMT_lx "\n", nr, env->nb_tlb, eaddr); pte_invalidate(&tlb->pte0); tlb_flush_page(cs, tlb->EPN); } @@ -115,8 +100,9 @@ static void ppc6xx_tlb_store(CPUPPCState *env, target_ulong EPN, int way, nr = ppc6xx_tlb_getnum(env, EPN, way, is_code); tlb = &env->tlb.tlb6[nr]; - LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx - " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1); + qemu_log_mask(CPU_LOG_MMU, "Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " + TARGET_FMT_lx " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, + EPN, pte0, pte1); /* Invalidate any pending reference in QEMU for this virtual address */ ppc6xx_tlb_invalidate_virt2(env, EPN, is_code, 1); tlb->pte0 = pte0; @@ -204,25 +190,27 @@ static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu, end = base + mask + 0x00020000; if (((end - base) >> TARGET_PAGE_BITS) > 1024) { /* Flushing 1024 4K pages is slower than a complete flush */ - LOG_BATS("Flush all BATs\n"); + qemu_log_mask(CPU_LOG_MMU, "Flush all BATs\n"); tlb_flush(cs); - LOG_BATS("Flush done\n"); + qemu_log_mask(CPU_LOG_MMU, "Flush done\n"); return; } - LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " (" - TARGET_FMT_lx ")\n", base, end, mask); + qemu_log_mask(CPU_LOG_MMU, "Flush BAT from " TARGET_FMT_lx + " to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", + base, end, mask); for (page = base; page != end; page += TARGET_PAGE_SIZE) { tlb_flush_page(cs, page); } - LOG_BATS("Flush done\n"); + qemu_log_mask(CPU_LOG_MMU, "Flush done\n"); } #endif static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr, target_ulong value) { - LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID, - nr, ul == 0 ? 'u' : 'l', value, env->nip); + qemu_log_mask(CPU_LOG_MMU, "Set %cBAT%d%c to " TARGET_FMT_lx " (" + TARGET_FMT_lx ")\n", ID, nr, ul == 0 ? 'u' : 'l', + value, env->nip); } void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value) @@ -550,9 +538,9 @@ static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code) } way = (env->spr[SPR_SRR1] >> 17) & 1; (void)EPN; /* avoid a compiler warning */ - LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx - " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP, - RPN, way); + qemu_log_mask(CPU_LOG_MMU, "%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx + " PTE0 " TARGET_FMT_lx " PTE1 " TARGET_FMT_lx " way %d\n", + __func__, new_EPN, EPN, CMP, RPN, way); /* Store this TLB */ ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK), way, is_code, CMP, RPN); @@ -721,15 +709,17 @@ void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry, ppcemb_tlb_t *tlb; target_ulong page, end; - LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry, + qemu_log_mask(CPU_LOG_MMU, "%s entry %d val " TARGET_FMT_lx "\n", + __func__, (int)entry, val); entry &= PPC4XX_TLB_ENTRY_MASK; tlb = &env->tlb.tlbe[entry]; /* Invalidate previous TLB (if it's valid) */ if (tlb->prot & PAGE_VALID) { end = tlb->EPN + tlb->size; - LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end " - TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end); + qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start " + TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__, + (int)entry, tlb->EPN, end); for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) { tlb_flush_page(cs, page); } @@ -758,18 +748,20 @@ void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry, tlb->prot &= ~PAGE_VALID; } tlb->PID = env->spr[SPR_40x_PID]; /* PID */ - LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx - " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__, - (int)entry, tlb->RPN, tlb->EPN, tlb->size, - tlb->prot & PAGE_READ ? 'r' : '-', - tlb->prot & PAGE_WRITE ? 'w' : '-', - tlb->prot & PAGE_EXEC ? 'x' : '-', - tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); + qemu_log_mask(CPU_LOG_MMU, "%s: set up TLB %d RPN " TARGET_FMT_plx + " EPN " TARGET_FMT_lx " size " TARGET_FMT_lx + " prot %c%c%c%c PID %d\n", __func__, + (int)entry, tlb->RPN, tlb->EPN, tlb->size, + tlb->prot & PAGE_READ ? 'r' : '-', + tlb->prot & PAGE_WRITE ? 'w' : '-', + tlb->prot & PAGE_EXEC ? 'x' : '-', + tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); /* Invalidate new TLB (if valid) */ if (tlb->prot & PAGE_VALID) { end = tlb->EPN + tlb->size; - LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end " - TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end); + qemu_log_mask(CPU_LOG_MMU, "%s: invalidate TLB %d start " + TARGET_FMT_lx " end " TARGET_FMT_lx "\n", __func__, + (int)entry, tlb->EPN, end); for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) { tlb_flush_page(cs, page); } @@ -781,8 +773,8 @@ void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry, { ppcemb_tlb_t *tlb; - LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry, - val); + qemu_log_mask(CPU_LOG_MMU, "%s entry %i val " TARGET_FMT_lx "\n", + __func__, (int)entry, val); entry &= PPC4XX_TLB_ENTRY_MASK; tlb = &env->tlb.tlbe[entry]; tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK; @@ -794,13 +786,14 @@ void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry, if (val & PPC4XX_TLBLO_WR) { tlb->prot |= PAGE_WRITE; } - LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx - " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__, - (int)entry, tlb->RPN, tlb->EPN, tlb->size, - tlb->prot & PAGE_READ ? 'r' : '-', - tlb->prot & PAGE_WRITE ? 'w' : '-', - tlb->prot & PAGE_EXEC ? 'x' : '-', - tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); + qemu_log_mask(CPU_LOG_MMU, "%s: set up TLB %d RPN " TARGET_FMT_plx + " EPN " TARGET_FMT_lx + " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__, + (int)entry, tlb->RPN, tlb->EPN, tlb->size, + tlb->prot & PAGE_READ ? 'r' : '-', + tlb->prot & PAGE_WRITE ? 'w' : '-', + tlb->prot & PAGE_EXEC ? 'x' : '-', + tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); } target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address) @@ -816,8 +809,8 @@ void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry, target_ulong EPN, RPN, size; int do_flush_tlbs; - LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n", - __func__, word, (int)entry, value); + qemu_log_mask(CPU_LOG_MMU, "%s word %d entry %d value " TARGET_FMT_lx "\n", + __func__, word, (int)entry, value); do_flush_tlbs = 0; entry &= 0x3F; tlb = &env->tlb.tlbe[entry]; From cbd8f17d16c890e6d9316627e2d4def6f965988d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 152/730] ppc/ppc405: Restore TCR and STR write handlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 405 timers were broken when booke support was added. Assumption was made that the register numbers were the same but it's not : SPR_BOOKE_TSR (0x150) SPR_BOOKE_TCR (0x154) SPR_40x_TSR (0x3D8) SPR_40x_TCR (0x3DA) Cc: Christophe Leroy Fixes: ddd1055b07fd ("PPC: booke timers") Reviewed-by: Richard Henderson Signed-off-by: Cédric Le Goater Message-Id: <20211222064025.1541490-5-clg@kaod.org> Signed-off-by: Cédric Le Goater Message-Id: <20220103063441.3424853-6-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/ppc/ppc.c | 25 +++++++++++++++++++++++++ hw/ppc/trace-events | 2 ++ target/ppc/cpu.h | 2 ++ target/ppc/cpu_init.c | 4 ++-- target/ppc/helper.h | 2 ++ target/ppc/spr_tcg.h | 2 ++ target/ppc/timebase_helper.c | 10 ++++++++++ target/ppc/translate.c | 12 ++++++++++++ 8 files changed, 57 insertions(+), 2 deletions(-) diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 818d757985..cca99cb86f 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -1300,6 +1300,31 @@ target_ulong load_40x_pit (CPUPPCState *env) return cpu_ppc_load_decr(env); } +void store_40x_tsr(CPUPPCState *env, target_ulong val) +{ + PowerPCCPU *cpu = env_archcpu(env); + + trace_ppc40x_store_tcr(val); + + env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000); + if (val & 0x80000000) { + ppc_set_irq(cpu, PPC_INTERRUPT_PIT, 0); + } +} + +void store_40x_tcr(CPUPPCState *env, target_ulong val) +{ + PowerPCCPU *cpu = env_archcpu(env); + ppc_tb_t *tb_env; + + trace_ppc40x_store_tsr(val); + + tb_env = env->tb_env; + env->spr[SPR_40x_TCR] = val & 0xFFC00000; + start_stop_pit(env, tb_env, 1); + cpu_4xx_wdt_cb(cpu); +} + static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq) { CPUPPCState *env = opaque; diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index 0c55aa5014..5c0a215cad 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -110,6 +110,8 @@ ppc4xx_pit_start(uint64_t reload) "PIT 0x%016" PRIx64 ppc4xx_pit(uint32_t ar, uint32_t ir, uint64_t tcr, uint64_t tsr, uint64_t reload) "ar %d ir %d TCR 0x%" PRIx64 " TSR 0x%" PRIx64 " PIT 0x%016" PRIx64 ppc4xx_wdt(uint64_t tcr, uint64_t tsr) "TCR 0x%" PRIx64 " TSR 0x%" PRIx64 ppc40x_store_pit(uint64_t value) "val 0x%" PRIx64 +ppc40x_store_tcr(uint64_t value) "val 0x%" PRIx64 +ppc40x_store_tsr(uint64_t value) "val 0x%" PRIx64 ppc40x_set_tb_clk(uint32_t value) "new frequency %" PRIu32 ppc40x_timers_init(uint32_t value) "frequency %" PRIu32 diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index fc66c3561d..4808e10ebe 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1399,6 +1399,8 @@ target_ulong load_40x_pit(CPUPPCState *env); void store_40x_pit(CPUPPCState *env, target_ulong val); void store_40x_dbcr0(CPUPPCState *env, uint32_t val); void store_40x_sler(CPUPPCState *env, uint32_t val); +void store_40x_tcr(CPUPPCState *env, target_ulong val); +void store_40x_tsr(CPUPPCState *env, target_ulong val); void store_booke_tcr(CPUPPCState *env, target_ulong val); void store_booke_tsr(CPUPPCState *env, target_ulong val); void ppc_tlb_invalidate_all(CPUPPCState *env); diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 06ef15cd9e..b5e2fde9ec 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -1440,11 +1440,11 @@ static void register_40x_sprs(CPUPPCState *env) 0x00000000); spr_register(env, SPR_40x_TCR, "TCR", SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_booke_tcr, + &spr_read_generic, &spr_write_40x_tcr, 0x00000000); spr_register(env, SPR_40x_TSR, "TSR", SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_booke_tsr, + &spr_read_generic, &spr_write_40x_tsr, 0x00000000); } diff --git a/target/ppc/helper.h b/target/ppc/helper.h index fb6cac38b4..f9c72dcd50 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -706,6 +706,8 @@ DEF_HELPER_2(store_hid0_601, void, env, tl) DEF_HELPER_3(store_403_pbr, void, env, i32, tl) DEF_HELPER_FLAGS_1(load_40x_pit, TCG_CALL_NO_RWG, tl, env) DEF_HELPER_FLAGS_2(store_40x_pit, TCG_CALL_NO_RWG, void, env, tl) +DEF_HELPER_FLAGS_2(store_40x_tcr, TCG_CALL_NO_RWG, void, env, tl) +DEF_HELPER_FLAGS_2(store_40x_tsr, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_2(store_40x_dbcr0, void, env, tl) DEF_HELPER_2(store_40x_sler, void, env, tl) DEF_HELPER_FLAGS_2(store_booke_tcr, TCG_CALL_NO_RWG, void, env, tl) diff --git a/target/ppc/spr_tcg.h b/target/ppc/spr_tcg.h index f98d97c0ba..64cf5302cb 100644 --- a/target/ppc/spr_tcg.h +++ b/target/ppc/spr_tcg.h @@ -87,6 +87,8 @@ void spr_read_40x_pit(DisasContext *ctx, int gprn, int sprn); void spr_write_40x_pit(DisasContext *ctx, int sprn, int gprn); void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn); void spr_write_40x_sler(DisasContext *ctx, int sprn, int gprn); +void spr_write_40x_tcr(DisasContext *ctx, int sprn, int gprn); +void spr_write_40x_tsr(DisasContext *ctx, int sprn, int gprn); void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn); void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn); void spr_read_403_pbr(DisasContext *ctx, int gprn, int sprn); diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c index 8ff4080eb9..af378318c1 100644 --- a/target/ppc/timebase_helper.c +++ b/target/ppc/timebase_helper.c @@ -144,6 +144,16 @@ void helper_store_40x_pit(CPUPPCState *env, target_ulong val) store_40x_pit(env, val); } +void helper_store_40x_tcr(CPUPPCState *env, target_ulong val) +{ + store_40x_tcr(env, val); +} + +void helper_store_40x_tsr(CPUPPCState *env, target_ulong val) +{ + store_40x_tsr(env, val); +} + void helper_store_booke_tcr(CPUPPCState *env, target_ulong val) { store_booke_tcr(env, val); diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 114456148c..eb45f679d3 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -878,6 +878,18 @@ void spr_write_40x_sler(DisasContext *ctx, int sprn, int gprn) gen_helper_store_40x_sler(cpu_env, cpu_gpr[gprn]); } +void spr_write_40x_tcr(DisasContext *ctx, int sprn, int gprn) +{ + gen_icount_io_start(ctx); + gen_helper_store_40x_tcr(cpu_env, cpu_gpr[gprn]); +} + +void spr_write_40x_tsr(DisasContext *ctx, int sprn, int gprn) +{ + gen_icount_io_start(ctx); + gen_helper_store_40x_tsr(cpu_env, cpu_gpr[gprn]); +} + void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn) { gen_icount_io_start(ctx); From b1273a5e13b7245e93f777c3eaa1c1477157b3de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 153/730] ppc/ppc405: Rework ppc_40x_timers_init() to use a PowerPCCPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a small cleanup to ease reading. It includes the removal of a check done on the returned value of g_malloc0(), which can not fail. Reviewed-by: Richard Henderson Signed-off-by: Cédric Le Goater Message-Id: <20211222064025.1541490-6-clg@kaod.org> Signed-off-by: Cédric Le Goater Message-Id: <20220103063441.3424853-7-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/ppc/ppc.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index cca99cb86f..bb5bee9a33 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -1124,14 +1124,12 @@ struct ppc40x_timer_t { /* Fixed interval timer */ static void cpu_4xx_fit_cb (void *opaque) { - PowerPCCPU *cpu; - CPUPPCState *env; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; uint64_t now, next; - env = opaque; - cpu = env_archcpu(env); tb_env = env->tb_env; ppc40x_timer = tb_env->opaque; now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); @@ -1193,13 +1191,11 @@ static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp) static void cpu_4xx_pit_cb (void *opaque) { - PowerPCCPU *cpu; - CPUPPCState *env; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; - env = opaque; - cpu = env_archcpu(env); tb_env = env->tb_env; ppc40x_timer = tb_env->opaque; env->spr[SPR_40x_TSR] |= 1 << 27; @@ -1216,14 +1212,12 @@ static void cpu_4xx_pit_cb (void *opaque) /* Watchdog timer */ static void cpu_4xx_wdt_cb (void *opaque) { - PowerPCCPU *cpu; - CPUPPCState *env; + PowerPCCPU *cpu = opaque; + CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; uint64_t now, next; - env = opaque; - cpu = env_archcpu(env); tb_env = env->tb_env; ppc40x_timer = tb_env->opaque; now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); @@ -1341,24 +1335,26 @@ clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq, { ppc_tb_t *tb_env; ppc40x_timer_t *ppc40x_timer; + PowerPCCPU *cpu = env_archcpu(env); + + trace_ppc40x_timers_init(freq); tb_env = g_malloc0(sizeof(ppc_tb_t)); + ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t)); + env->tb_env = tb_env; tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED; - ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t)); tb_env->tb_freq = freq; tb_env->decr_freq = freq; tb_env->opaque = ppc40x_timer; - trace_ppc40x_timers_init(freq); - if (ppc40x_timer != NULL) { - /* We use decr timer for PIT */ - tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_pit_cb, env); - ppc40x_timer->fit_timer = - timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_fit_cb, env); - ppc40x_timer->wdt_timer = - timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_wdt_cb, env); - ppc40x_timer->decr_excp = decr_excp; - } + + /* We use decr timer for PIT */ + tb_env->decr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_pit_cb, cpu); + ppc40x_timer->fit_timer = + timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_fit_cb, cpu); + ppc40x_timer->wdt_timer = + timer_new_ns(QEMU_CLOCK_VIRTUAL, &cpu_4xx_wdt_cb, cpu); + ppc40x_timer->decr_excp = decr_excp; return &ppc_40x_set_tb_clk; } From c316203c1ee6f9a6c301a0a6767d27cbb6a65c46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 154/730] ppc/ppc405: Fix timer initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Timers are already initialized in ppc4xx_init(). No need to do it a second time with a wrong set. Fixes: d715ea961254 ("PPC: 405: Fix ppc405ep initialization") Reviewed-by: Richard Henderson Signed-off-by: Cédric Le Goater Message-Id: <20211222064025.1541490-7-clg@kaod.org> Signed-off-by: Cédric Le Goater Message-Id: <20220103063441.3424853-8-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/ppc/ppc405_uc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index ec97b22bd0..8aacd275a6 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -1461,8 +1461,6 @@ PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem, ppc4xx_pob_init(env); /* OBP arbitrer */ ppc4xx_opba_init(0xef600600); - /* Initialize timers */ - ppc_booke_timers_init(cpu, sysclk, 0); /* Universal interrupt controller */ uicdev = qdev_new(TYPE_PPC_UIC); uicsbd = SYS_BUS_DEVICE(uicdev); From dd69d140cedc904f3491c17415f75d753c7f1be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 155/730] ppc/ppc405: Introduce a store helper for SPR_40x_PID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PID SPR of the 405 CPU contains the translation ID of the TLB which is a 8-bit field. Enforce the mask with a store helper. Cc: Christophe Leroy Reviewed-by: Richard Henderson Signed-off-by: Cédric Le Goater Message-Id: <20211222064025.1541490-8-clg@kaod.org> Signed-off-by: Cédric Le Goater Message-Id: <20220103063441.3424853-9-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/cpu_init.c | 2 +- target/ppc/spr_tcg.h | 1 + target/ppc/translate.c | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index b5e2fde9ec..9ef9a1a5dd 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -1454,7 +1454,7 @@ static void register_405_sprs(CPUPPCState *env) /* MMU */ spr_register(env, SPR_40x_PID, "PID", SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, + &spr_read_generic, &spr_write_40x_pid, 0x00000000); spr_register(env, SPR_4xx_CCR0, "CCR0", SPR_NOACCESS, SPR_NOACCESS, diff --git a/target/ppc/spr_tcg.h b/target/ppc/spr_tcg.h index 64cf5302cb..89ff111724 100644 --- a/target/ppc/spr_tcg.h +++ b/target/ppc/spr_tcg.h @@ -89,6 +89,7 @@ void spr_write_40x_dbcr0(DisasContext *ctx, int sprn, int gprn); void spr_write_40x_sler(DisasContext *ctx, int sprn, int gprn); void spr_write_40x_tcr(DisasContext *ctx, int sprn, int gprn); void spr_write_40x_tsr(DisasContext *ctx, int sprn, int gprn); +void spr_write_40x_pid(DisasContext *ctx, int sprn, int gprn); void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn); void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn); void spr_read_403_pbr(DisasContext *ctx, int gprn, int sprn); diff --git a/target/ppc/translate.c b/target/ppc/translate.c index eb45f679d3..cb8ab4d676 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -890,6 +890,14 @@ void spr_write_40x_tsr(DisasContext *ctx, int sprn, int gprn) gen_helper_store_40x_tsr(cpu_env, cpu_gpr[gprn]); } +void spr_write_40x_pid(DisasContext *ctx, int sprn, int gprn) +{ + TCGv t0 = tcg_temp_new(); + tcg_gen_andi_tl(t0, cpu_gpr[gprn], 0xFF); + gen_store_spr(SPR_40x_PID, t0); + tcg_temp_free(t0); +} + void spr_write_booke_tcr(DisasContext *ctx, int sprn, int gprn) { gen_icount_io_start(ctx); From fbe08667c5bd91395eea578398f07e83c768fa56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 156/730] ppc/ppc405: Dump specific registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework slightly ppc_cpu_dump_state() to replace the various 'if' statements with a 'switch'. Reviewed-by: Richard Henderson Signed-off-by: Cédric Le Goater Message-Id: <20211222064025.1541490-9-clg@kaod.org> Signed-off-by: Cédric Le Goater Message-Id: <20220103063441.3424853-10-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/cpu_init.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 9ef9a1a5dd..25970bd79f 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -8648,16 +8648,17 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags) env->spr[SPR_SPRG4], env->spr[SPR_SPRG5], env->spr[SPR_SPRG6], env->spr[SPR_SPRG7]); + switch (env->excp_model) { #if defined(TARGET_PPC64) - if (env->excp_model == POWERPC_EXCP_POWER7 || - env->excp_model == POWERPC_EXCP_POWER8 || - env->excp_model == POWERPC_EXCP_POWER9 || - env->excp_model == POWERPC_EXCP_POWER10) { + case POWERPC_EXCP_POWER7: + case POWERPC_EXCP_POWER8: + case POWERPC_EXCP_POWER9: + case POWERPC_EXCP_POWER10: qemu_fprintf(f, "HSRR0 " TARGET_FMT_lx " HSRR1 " TARGET_FMT_lx "\n", env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]); - } + break; #endif - if (env->excp_model == POWERPC_EXCP_BOOKE) { + case POWERPC_EXCP_BOOKE: qemu_fprintf(f, "CSRR0 " TARGET_FMT_lx " CSRR1 " TARGET_FMT_lx " MCSRR0 " TARGET_FMT_lx " MCSRR1 " TARGET_FMT_lx "\n", env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1], @@ -8688,6 +8689,20 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags) * IVORs are left out as they are large and do not change often -- * they can be read with "p $ivor0", "p $ivor1", etc. */ + break; + case POWERPC_EXCP_40x: + qemu_fprintf(f, " TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx + " ESR " TARGET_FMT_lx " DEAR " TARGET_FMT_lx "\n", + env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR], + env->spr[SPR_40x_ESR], env->spr[SPR_40x_DEAR]); + + qemu_fprintf(f, " EVPR " TARGET_FMT_lx " SRR2 " TARGET_FMT_lx + " SRR3 " TARGET_FMT_lx " PID " TARGET_FMT_lx "\n", + env->spr[SPR_40x_EVPR], env->spr[SPR_40x_SRR2], + env->spr[SPR_40x_SRR3], env->spr[SPR_40x_PID]); + break; + default: + break; } #if defined(TARGET_PPC64) From 84ade98e87ea982ec6625ffd91058aaf443c206e Mon Sep 17 00:00:00 2001 From: Matheus Ferst Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 157/730] target/ppc: do not silence snan in xscvspdpn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The non-signalling versions of VSX scalar convert to shorter/longer precision insns doesn't silence SNaNs in the hardware. To better match this behavior, use the non-arithmatic conversion of helper_todouble instead of float32_to_float64. A test is added to prevent future regressions. Signed-off-by: Matheus Ferst Message-Id: <20211228120310.1957990-1-matheus.ferst@eldorado.org.br> Signed-off-by: Cédric Le Goater --- target/ppc/fpu_helper.c | 5 +--- tests/tcg/ppc64/Makefile.target | 4 +-- tests/tcg/ppc64le/Makefile.target | 4 +-- tests/tcg/ppc64le/non_signalling_xscv.c | 37 +++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 tests/tcg/ppc64le/non_signalling_xscv.c diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index 700c79156b..e5c29b53b8 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -2816,10 +2816,7 @@ uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb) uint64_t helper_xscvspdpn(CPUPPCState *env, uint64_t xb) { - float_status tstat = env->fp_status; - set_float_exception_flags(0, &tstat); - - return float32_to_float64(xb >> 32, &tstat); + return helper_todouble(xb >> 32); } /* diff --git a/tests/tcg/ppc64/Makefile.target b/tests/tcg/ppc64/Makefile.target index 8f4c7ac4ed..0368007028 100644 --- a/tests/tcg/ppc64/Makefile.target +++ b/tests/tcg/ppc64/Makefile.target @@ -6,9 +6,9 @@ VPATH += $(SRC_PATH)/tests/tcg/ppc64 VPATH += $(SRC_PATH)/tests/tcg/ppc64le ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_POWER8_VECTOR),) -PPC64_TESTS=bcdsub +PPC64_TESTS=bcdsub non_signalling_xscv endif -bcdsub: CFLAGS += -mpower8-vector +$(PPC64_TESTS): CFLAGS += -mpower8-vector PPC64_TESTS += byte_reverse PPC64_TESTS += mtfsf diff --git a/tests/tcg/ppc64le/Makefile.target b/tests/tcg/ppc64le/Makefile.target index e031f65adc..480ff0898d 100644 --- a/tests/tcg/ppc64le/Makefile.target +++ b/tests/tcg/ppc64le/Makefile.target @@ -5,9 +5,9 @@ VPATH += $(SRC_PATH)/tests/tcg/ppc64le ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_POWER8_VECTOR),) -PPC64LE_TESTS=bcdsub +PPC64LE_TESTS=bcdsub non_signalling_xscv endif -bcdsub: CFLAGS += -mpower8-vector +$(PPC64LE_TESTS): CFLAGS += -mpower8-vector ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_POWER10),) PPC64LE_TESTS += byte_reverse diff --git a/tests/tcg/ppc64le/non_signalling_xscv.c b/tests/tcg/ppc64le/non_signalling_xscv.c new file mode 100644 index 0000000000..91e25cad46 --- /dev/null +++ b/tests/tcg/ppc64le/non_signalling_xscv.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +#define TEST(INSN, B_HI, B_LO, T_HI, T_LO) \ + do { \ + uint64_t th, tl, bh = B_HI, bl = B_LO; \ + asm("mtvsrd 0, %2\n\t" \ + "mtvsrd 1, %3\n\t" \ + "xxmrghd 0, 0, 1\n\t" \ + INSN " 0, 0\n\t" \ + "mfvsrd %0, 0\n\t" \ + "xxswapd 0, 0\n\t" \ + "mfvsrd %1, 0\n\t" \ + : "=r" (th), "=r" (tl) \ + : "r" (bh), "r" (bl) \ + : "vs0", "vs1"); \ + printf(INSN "(0x%016" PRIx64 "%016" PRIx64 ") = 0x%016" PRIx64 \ + "%016" PRIx64 "\n", bh, bl, th, tl); \ + assert(th == T_HI && tl == T_LO); \ + } while (0) + +int main(void) +{ + /* SNaN shouldn't be silenced */ + TEST("xscvspdpn", 0x7fbfffff00000000ULL, 0x0, 0x7ff7ffffe0000000ULL, 0x0); + TEST("xscvdpspn", 0x7ff7ffffffffffffULL, 0x0, 0x7fbfffff7fbfffffULL, 0x0); + + /* + * SNaN inputs having no significant bits in the upper 23 bits of the + * signifcand will return Infinity as the result. + */ + TEST("xscvdpspn", 0x7ff000001fffffffULL, 0x0, 0x7f8000007f800000ULL, 0x0); + + return 0; +} From 19e70626f8554245a30d3d46b613d80f2b670c04 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 158/730] target/ppc: powerpc_excp: Set alternate SRRs directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are currently only two interrupts that use alternate SRRs, so let them write to them directly during the setup code. No functional change intended. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Reviewed-by: Cédric Le Goater Reviewed-by: David Gibson Message-Id: <20211229165751.3774248-2-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index e3380722c5..c7efbdc305 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -370,7 +370,7 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; target_ulong msr, new_msr, vector; - int srr0, srr1, asrr0, asrr1, lev = -1; + int srr0, srr1, lev = -1; qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp), @@ -392,8 +392,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) /* target registers */ srr0 = SPR_SRR0; srr1 = SPR_SRR1; - asrr0 = -1; - asrr1 = -1; /* * check for special resume at 0x100 from doze/nap/sleep/winkle on @@ -483,8 +481,9 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) /* FIXME: choose one or the other based on CPU type */ srr0 = SPR_BOOKE_MCSRR0; srr1 = SPR_BOOKE_MCSRR1; - asrr0 = SPR_BOOKE_CSRR0; - asrr1 = SPR_BOOKE_CSRR1; + + env->spr[SPR_BOOKE_CSRR0] = env->nip; + env->spr[SPR_BOOKE_CSRR1] = msr; break; default: break; @@ -643,8 +642,10 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) /* FIXME: choose one or the other based on CPU type */ srr0 = SPR_BOOKE_DSRR0; srr1 = SPR_BOOKE_DSRR1; - asrr0 = SPR_BOOKE_CSRR0; - asrr1 = SPR_BOOKE_CSRR1; + + env->spr[SPR_BOOKE_CSRR0] = env->nip; + env->spr[SPR_BOOKE_CSRR1] = msr; + /* DBSR already modified by caller */ } else { cpu_abort(cs, "Debug exception triggered on unsupported model\n"); @@ -911,14 +912,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) vector |= env->excp_prefix; - /* If any alternate SRR register are defined, duplicate saved values */ - if (asrr0 != -1) { - env->spr[asrr0] = env->nip; - } - if (asrr1 != -1) { - env->spr[asrr1] = msr; - } - #if defined(TARGET_PPC64) if (excp_model == POWERPC_EXCP_BOOKE) { if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { From 2541e686589a86167cbee98162d3fde2bbf67bc2 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 159/730] target/ppc: powerpc_excp: Add excp_vectors bounds check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The next patch will start accessing the excp_vectors array earlier in the function, so add a bounds check as first thing here. This converts the empty return on POWERPC_EXCP_NONE to an error. This exception number never reaches this function and if it does it probably means something else went wrong up the line. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Reviewed-by: Richard Henderson Reviewed-by: David Gibson Message-Id: <20211229165751.3774248-3-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index c7efbdc305..9e7c428821 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -372,6 +372,10 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) target_ulong msr, new_msr, vector; int srr0, srr1, lev = -1; + if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) { + cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); + } + qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp), excp, env->error_code); @@ -426,9 +430,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) #endif switch (excp) { - case POWERPC_EXCP_NONE: - /* Should never happen */ - return; case POWERPC_EXCP_CRITICAL: /* Critical input */ switch (excp_model) { case POWERPC_EXCP_40x: From d1cbee61abd5ca76cd04886d066e18fcda8d1116 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 160/730] target/ppc: powerpc_excp: Set vector earlier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit None of the interrupt setup code touches 'vector', so we can move it earlier in the function. This will allow us to later move the System Call Vectored setup that is on the top level into the POWERPC_EXCP_SYSCALL_VECTORED code block. This patch also moves the verification for when 'excp' does not have an address associated with it. We now bail a little earlier when that is the case. This should not cause any visible effects. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Reviewed-by: Richard Henderson Reviewed-by: David Gibson Message-Id: <20211229165751.3774248-4-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 9e7c428821..35ac450590 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -429,6 +429,14 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } #endif + vector = env->excp_vectors[excp]; + if (vector == (target_ulong)-1ULL) { + cpu_abort(cs, "Raised an exception without defined vector %d\n", + excp); + } + + vector |= env->excp_prefix; + switch (excp) { case POWERPC_EXCP_CRITICAL: /* Critical input */ switch (excp_model) { @@ -905,14 +913,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) } #endif - vector = env->excp_vectors[excp]; - if (vector == (target_ulong)-1ULL) { - cpu_abort(cs, "Raised an exception without defined vector %d\n", - excp); - } - - vector |= env->excp_prefix; - #if defined(TARGET_PPC64) if (excp_model == POWERPC_EXCP_BOOKE) { if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { From 5ac11b126d47755c39727cc772ee16cb49b3ade7 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 161/730] target/ppc: powerpc_excp: Move system call vectored code together MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that 'vector' is known before calling the interrupt-specific setup code, we can move all of the scv setup into one place. No functional change intended. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Reviewed-by: Richard Henderson Message-Id: <20211229165751.3774248-5-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 35ac450590..2c20a8060c 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -623,6 +623,11 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) env->nip += 4; new_msr |= env->msr & ((target_ulong)1 << MSR_EE); new_msr |= env->msr & ((target_ulong)1 << MSR_RI); + + vector += lev * 0x20; + + env->lr = env->nip; + env->ctr = msr; break; case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ @@ -936,14 +941,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) /* Save MSR */ env->spr[srr1] = msr; - -#if defined(TARGET_PPC64) - } else { - vector += lev * 0x20; - - env->lr = env->nip; - env->ctr = msr; -#endif } /* This can update new_msr and vector if AIL applies */ From 93130c8475692b1e52e3d3c3beedc3a79b4562d5 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 162/730] target/ppc: powerpc_excp: Stop passing excp_model around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can just access it directly in powerpc_excp. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Reviewed-by: Richard Henderson Reviewed-by: David Gibson [ clg: Took into account removal of inline ] Message-Id: <20211229165751.3774248-6-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 43 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 2c20a8060c..a779dc936a 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -365,10 +365,11 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, * Note that this function should be greatly optimized when called * with a constant excp, from ppc_hw_interrupt */ -static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) +static void powerpc_excp(PowerPCCPU *cpu, int excp) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; + int excp_model = env->excp_model; target_ulong msr, new_msr, vector; int srr0, srr1, lev = -1; @@ -952,9 +953,8 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) void ppc_cpu_do_interrupt(CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); - CPUPPCState *env = &cpu->env; - powerpc_excp(cpu, env->excp_model, cs->exception_index); + powerpc_excp(cpu, cs->exception_index); } static void ppc_hw_interrupt(CPUPPCState *env) @@ -965,20 +965,20 @@ static void ppc_hw_interrupt(CPUPPCState *env) /* External reset */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); + powerpc_excp(cpu, POWERPC_EXCP_RESET); return; } /* Machine check exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK); + powerpc_excp(cpu, POWERPC_EXCP_MCHECK); return; } #if 0 /* TODO */ /* External debug exception */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG); + powerpc_excp(cpu, POWERPC_EXCP_DEBUG); return; } #endif @@ -998,7 +998,7 @@ static void ppc_hw_interrupt(CPUPPCState *env) if ((async_deliver || msr_hv == 0) && hdice) { /* HDEC clears on delivery */ env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR); + powerpc_excp(cpu, POWERPC_EXCP_HDECR); return; } } @@ -1008,7 +1008,7 @@ static void ppc_hw_interrupt(CPUPPCState *env) /* LPCR will be clear when not supported so this will work */ bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); if ((async_deliver || msr_hv == 0) && hvice) { - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT); + powerpc_excp(cpu, POWERPC_EXCP_HVIRT); return; } } @@ -1020,14 +1020,14 @@ static void ppc_hw_interrupt(CPUPPCState *env) /* HEIC blocks delivery to the hypervisor */ if ((async_deliver && !(heic && msr_hv && !msr_pr)) || (env->has_hv_mode && msr_hv == 0 && !lpes0)) { - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL); + powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL); return; } } if (msr_ce != 0) { /* External critical interrupt */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) { - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL); + powerpc_excp(cpu, POWERPC_EXCP_CRITICAL); return; } } @@ -1035,24 +1035,24 @@ static void ppc_hw_interrupt(CPUPPCState *env) /* Watchdog timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT); + powerpc_excp(cpu, POWERPC_EXCP_WDT); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI); + powerpc_excp(cpu, POWERPC_EXCP_DOORCI); return; } /* Fixed interval timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT); + powerpc_excp(cpu, POWERPC_EXCP_FIT); return; } /* Programmable interval timer on embedded PowerPC */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT); + powerpc_excp(cpu, POWERPC_EXCP_PIT); return; } /* Decrementer exception */ @@ -1060,32 +1060,32 @@ static void ppc_hw_interrupt(CPUPPCState *env) if (ppc_decr_clear_on_delivery(env)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR); } - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR); + powerpc_excp(cpu, POWERPC_EXCP_DECR); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); if (is_book3s_arch2x(env)) { - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR); + powerpc_excp(cpu, POWERPC_EXCP_SDOOR); } else { - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI); + powerpc_excp(cpu, POWERPC_EXCP_DOORI); } return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR_HV); + powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV); return; } if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM); + powerpc_excp(cpu, POWERPC_EXCP_PERFM); return; } /* Thermal interrupt */ if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) { env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM); - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM); + powerpc_excp(cpu, POWERPC_EXCP_THERM); return; } } @@ -1110,9 +1110,8 @@ static void ppc_hw_interrupt(CPUPPCState *env) void ppc_cpu_do_system_reset(CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); - CPUPPCState *env = &cpu->env; - powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); + powerpc_excp(cpu, POWERPC_EXCP_RESET); } void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector) From 6e8b990354d244ad5af40c747fdf3c008962b4e3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 4 Jan 2022 07:55:34 +0100 Subject: [PATCH 163/730] target/ppc: Cache per-pmc insn and cycle count settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the combination of frozen bit and counter type, on a per counter basis. So far this is only used by HFLAGS_INSN_CNT, but will be used more later. Signed-off-by: Richard Henderson [danielhb: fixed PMC4 cyc_cnt shift, insn run latch code, MMCR0_FC handling, "PMC[1-6]" comment] Signed-off-by: Daniel Henrique Barboza Message-Id: <20220103224746.167831-2-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- target/ppc/cpu.h | 3 +++ target/ppc/cpu_init.c | 1 + target/ppc/helper_regs.c | 2 +- target/ppc/machine.c | 2 ++ target/ppc/power8-pmu.c | 58 +++++++++++++++++++++++++++++++--------- target/ppc/power8-pmu.h | 14 +++++----- 6 files changed, 59 insertions(+), 21 deletions(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 4808e10ebe..f20d4ffa6d 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1144,6 +1144,9 @@ struct CPUPPCState { /* Other registers */ target_ulong spr[1024]; /* special purpose registers */ ppc_spr_t spr_cb[1024]; + /* Composite status for PMC[1-6] enabled and counting insns or cycles. */ + uint8_t pmc_ins_cnt; + uint8_t pmc_cyc_cnt; /* Vector status and control register, minus VSCR_SAT */ uint32_t vscr; /* VSX registers (including FP and AVR) */ diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 25970bd79f..cc93bff3fa 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -8313,6 +8313,7 @@ static void ppc_cpu_reset(DeviceState *dev) #endif /* CONFIG_TCG */ #endif + pmu_update_summaries(env); hreg_compute_hflags(env); env->reserve_addr = (target_ulong)-1ULL; /* Be sure no exception or interrupt is pending */ diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c index b847928842..8671b7bb69 100644 --- a/target/ppc/helper_regs.c +++ b/target/ppc/helper_regs.c @@ -123,7 +123,7 @@ static uint32_t hreg_compute_hflags_value(CPUPPCState *env) } #if defined(TARGET_PPC64) - if (pmu_insn_cnt_enabled(env)) { + if (env->pmc_ins_cnt) { hflags |= 1 << HFLAGS_INSN_CNT; } #endif diff --git a/target/ppc/machine.c b/target/ppc/machine.c index 93972df58e..756d8de5d8 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -8,6 +8,7 @@ #include "qapi/error.h" #include "qemu/main-loop.h" #include "kvm_ppc.h" +#include "power8-pmu.h" static void post_load_update_msr(CPUPPCState *env) { @@ -19,6 +20,7 @@ static void post_load_update_msr(CPUPPCState *env) */ env->msr ^= env->msr_mask & ~((1ULL << MSR_TGPR) | MSR_HVB); ppc_store_msr(env, msr); + pmu_update_summaries(env); } static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c index 08d1902cd5..1f4f611994 100644 --- a/target/ppc/power8-pmu.c +++ b/target/ppc/power8-pmu.c @@ -11,8 +11,6 @@ */ #include "qemu/osdep.h" - -#include "power8-pmu.h" #include "cpu.h" #include "helper_regs.h" #include "exec/exec-all.h" @@ -20,6 +18,7 @@ #include "qemu/error-report.h" #include "qemu/main-loop.h" #include "hw/ppc/ppc.h" +#include "power8-pmu.h" #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) @@ -121,18 +120,52 @@ static PMUEventType pmc_get_event(CPUPPCState *env, int sprn) return evt_type; } -bool pmu_insn_cnt_enabled(CPUPPCState *env) +void pmu_update_summaries(CPUPPCState *env) { - int sprn; + target_ulong mmcr0 = env->spr[SPR_POWER_MMCR0]; + target_ulong mmcr1 = env->spr[SPR_POWER_MMCR1]; + int ins_cnt = 0; + int cyc_cnt = 0; - for (sprn = SPR_POWER_PMC1; sprn <= SPR_POWER_PMC5; sprn++) { - if (pmc_get_event(env, sprn) == PMU_EVENT_INSTRUCTIONS || - pmc_get_event(env, sprn) == PMU_EVENT_INSN_RUN_LATCH) { - return true; - } + if (mmcr0 & MMCR0_FC) { + goto hflags_calc; } - return false; + if (!(mmcr0 & MMCR0_FC14) && mmcr1 != 0) { + target_ulong sel; + + sel = extract64(mmcr1, MMCR1_PMC1EVT_EXTR, MMCR1_EVT_SIZE); + switch (sel) { + case 0x02: + case 0xfe: + ins_cnt |= 1 << 1; + break; + case 0x1e: + case 0xf0: + cyc_cnt |= 1 << 1; + break; + } + + sel = extract64(mmcr1, MMCR1_PMC2EVT_EXTR, MMCR1_EVT_SIZE); + ins_cnt |= (sel == 0x02) << 2; + cyc_cnt |= (sel == 0x1e) << 2; + + sel = extract64(mmcr1, MMCR1_PMC3EVT_EXTR, MMCR1_EVT_SIZE); + ins_cnt |= (sel == 0x02) << 3; + cyc_cnt |= (sel == 0x1e) << 3; + + sel = extract64(mmcr1, MMCR1_PMC4EVT_EXTR, MMCR1_EVT_SIZE); + ins_cnt |= ((sel == 0xfa) || (sel == 0x2)) << 4; + cyc_cnt |= (sel == 0x1e) << 4; + } + + ins_cnt |= !(mmcr0 & MMCR0_FC56) << 5; + cyc_cnt |= !(mmcr0 & MMCR0_FC56) << 6; + + hflags_calc: + env->pmc_ins_cnt = ins_cnt; + env->pmc_cyc_cnt = cyc_cnt; + env->hflags = deposit32(env->hflags, HFLAGS_INSN_CNT, 1, ins_cnt != 0); } static bool pmu_increment_insns(CPUPPCState *env, uint32_t num_insns) @@ -264,8 +297,9 @@ void helper_store_mmcr0(CPUPPCState *env, target_ulong value) env->spr[SPR_POWER_MMCR0] = value; - /* MMCR0 writes can change HFLAGS_PMCCCLEAR and HFLAGS_INSN_CNT */ + /* MMCR0 writes can change HFLAGS_PMCC[01] and HFLAGS_INSN_CNT */ hreg_compute_hflags(env); + pmu_update_summaries(env); /* Update cycle overflow timers with the current MMCR0 state */ pmu_update_overflow_timers(env); @@ -278,7 +312,7 @@ void helper_store_mmcr1(CPUPPCState *env, uint64_t value) env->spr[SPR_POWER_MMCR1] = value; /* MMCR1 writes can change HFLAGS_INSN_CNT */ - hreg_compute_hflags(env); + pmu_update_summaries(env); } target_ulong helper_read_pmc(CPUPPCState *env, uint32_t sprn) diff --git a/target/ppc/power8-pmu.h b/target/ppc/power8-pmu.h index 3ee4b4cda5..a839199561 100644 --- a/target/ppc/power8-pmu.h +++ b/target/ppc/power8-pmu.h @@ -13,14 +13,12 @@ #ifndef POWER8_PMU #define POWER8_PMU -#include "qemu/osdep.h" -#include "cpu.h" -#include "exec/exec-all.h" -#include "exec/helper-proto.h" -#include "qemu/error-report.h" -#include "qemu/main-loop.h" - void cpu_ppc_pmu_init(CPUPPCState *env); -bool pmu_insn_cnt_enabled(CPUPPCState *env); + +#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) +void pmu_update_summaries(CPUPPCState *env); +#else +static inline void pmu_update_summaries(CPUPPCState *env) { } +#endif #endif From ffae5616c3677f7d6ad15267e6a15b895357b674 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 4 Jan 2022 07:55:35 +0100 Subject: [PATCH 164/730] target/ppc: Rewrite pmu_increment_insns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the cached pmc_ins_cnt value. Unroll the loop over the different PMC counters. Treat the PMC4 run-latch specially. Signed-off-by: Richard Henderson Message-Id: <20220103224746.167831-3-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- target/ppc/power8-pmu.c | 76 ++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 28 deletions(-) diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c index 1f4f611994..27c4c7915b 100644 --- a/target/ppc/power8-pmu.c +++ b/target/ppc/power8-pmu.c @@ -170,45 +170,65 @@ void pmu_update_summaries(CPUPPCState *env) static bool pmu_increment_insns(CPUPPCState *env, uint32_t num_insns) { + target_ulong mmcr0 = env->spr[SPR_POWER_MMCR0]; + unsigned ins_cnt = env->pmc_ins_cnt; bool overflow_triggered = false; - int sprn; + target_ulong tmp; - /* PMC6 never counts instructions */ - for (sprn = SPR_POWER_PMC1; sprn <= SPR_POWER_PMC5; sprn++) { - PMUEventType evt_type = pmc_get_event(env, sprn); - bool insn_event = evt_type == PMU_EVENT_INSTRUCTIONS || - evt_type == PMU_EVENT_INSN_RUN_LATCH; - - if (pmc_is_inactive(env, sprn) || !insn_event) { - continue; + if (unlikely(ins_cnt & 0x1e)) { + if (ins_cnt & (1 << 1)) { + tmp = env->spr[SPR_POWER_PMC1]; + tmp += num_insns; + if (tmp >= PMC_COUNTER_NEGATIVE_VAL && (mmcr0 & MMCR0_PMC1CE)) { + tmp = PMC_COUNTER_NEGATIVE_VAL; + overflow_triggered = true; + } + env->spr[SPR_POWER_PMC1] = tmp; } - if (evt_type == PMU_EVENT_INSTRUCTIONS) { - env->spr[sprn] += num_insns; + if (ins_cnt & (1 << 2)) { + tmp = env->spr[SPR_POWER_PMC2]; + tmp += num_insns; + if (tmp >= PMC_COUNTER_NEGATIVE_VAL && (mmcr0 & MMCR0_PMCjCE)) { + tmp = PMC_COUNTER_NEGATIVE_VAL; + overflow_triggered = true; + } + env->spr[SPR_POWER_PMC2] = tmp; } - if (evt_type == PMU_EVENT_INSN_RUN_LATCH && - env->spr[SPR_CTRL] & CTRL_RUN) { - env->spr[sprn] += num_insns; + if (ins_cnt & (1 << 3)) { + tmp = env->spr[SPR_POWER_PMC3]; + tmp += num_insns; + if (tmp >= PMC_COUNTER_NEGATIVE_VAL && (mmcr0 & MMCR0_PMCjCE)) { + tmp = PMC_COUNTER_NEGATIVE_VAL; + overflow_triggered = true; + } + env->spr[SPR_POWER_PMC3] = tmp; } - if (env->spr[sprn] >= PMC_COUNTER_NEGATIVE_VAL && - pmc_has_overflow_enabled(env, sprn)) { + if (ins_cnt & (1 << 4)) { + target_ulong mmcr1 = env->spr[SPR_POWER_MMCR1]; + int sel = extract64(mmcr1, MMCR1_PMC4EVT_EXTR, MMCR1_EVT_SIZE); + if (sel == 0x02 || (env->spr[SPR_CTRL] & CTRL_RUN)) { + tmp = env->spr[SPR_POWER_PMC4]; + tmp += num_insns; + if (tmp >= PMC_COUNTER_NEGATIVE_VAL && (mmcr0 & MMCR0_PMCjCE)) { + tmp = PMC_COUNTER_NEGATIVE_VAL; + overflow_triggered = true; + } + env->spr[SPR_POWER_PMC4] = tmp; + } + } + } + if (ins_cnt & (1 << 5)) { + tmp = env->spr[SPR_POWER_PMC5]; + tmp += num_insns; + if (tmp >= PMC_COUNTER_NEGATIVE_VAL && (mmcr0 & MMCR0_PMCjCE)) { + tmp = PMC_COUNTER_NEGATIVE_VAL; overflow_triggered = true; - - /* - * The real PMU will always trigger a counter overflow with - * PMC_COUNTER_NEGATIVE_VAL. We don't have an easy way to - * do that since we're counting block of instructions at - * the end of each translation block, and we're probably - * passing this value at this point. - * - * Let's write PMC_COUNTER_NEGATIVE_VAL to the overflowed - * counter to simulate what the real hardware would do. - */ - env->spr[sprn] = PMC_COUNTER_NEGATIVE_VAL; } + env->spr[SPR_POWER_PMC5] = tmp; } return overflow_triggered; From eec4dfdadbc68d2103a02e449618b191eb9c0886 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 4 Jan 2022 07:55:35 +0100 Subject: [PATCH 165/730] target/ppc: Use env->pnc_cyc_cnt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the cached pmc_cyc_cnt value in pmu_update_cycles and pmc_update_overflow_timer. This leaves pmc_get_event and pmc_is_inactive unused, so remove them. Signed-off-by: Richard Henderson Message-Id: <20220103224746.167831-4-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- target/ppc/power8-pmu.c | 107 ++++------------------------------------ 1 file changed, 9 insertions(+), 98 deletions(-) diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c index 27c4c7915b..73713ca2a3 100644 --- a/target/ppc/power8-pmu.c +++ b/target/ppc/power8-pmu.c @@ -24,19 +24,6 @@ #define PMC_COUNTER_NEGATIVE_VAL 0x80000000UL -static bool pmc_is_inactive(CPUPPCState *env, int sprn) -{ - if (env->spr[SPR_POWER_MMCR0] & MMCR0_FC) { - return true; - } - - if (sprn < SPR_POWER_PMC5) { - return env->spr[SPR_POWER_MMCR0] & MMCR0_FC14; - } - - return env->spr[SPR_POWER_MMCR0] & MMCR0_FC56; -} - static bool pmc_has_overflow_enabled(CPUPPCState *env, int sprn) { if (sprn == SPR_POWER_PMC1) { @@ -46,80 +33,6 @@ static bool pmc_has_overflow_enabled(CPUPPCState *env, int sprn) return env->spr[SPR_POWER_MMCR0] & MMCR0_PMCjCE; } -/* - * For PMCs 1-4, IBM POWER chips has support for an implementation - * dependent event, 0x1E, that enables cycle counting. The Linux kernel - * makes extensive use of 0x1E, so let's also support it. - * - * Likewise, event 0x2 is an implementation-dependent event that IBM - * POWER chips implement (at least since POWER8) that is equivalent to - * PM_INST_CMPL. Let's support this event on PMCs 1-4 as well. - */ -static PMUEventType pmc_get_event(CPUPPCState *env, int sprn) -{ - uint8_t mmcr1_evt_extr[] = { MMCR1_PMC1EVT_EXTR, MMCR1_PMC2EVT_EXTR, - MMCR1_PMC3EVT_EXTR, MMCR1_PMC4EVT_EXTR }; - PMUEventType evt_type = PMU_EVENT_INVALID; - uint8_t pmcsel; - int i; - - if (pmc_is_inactive(env, sprn)) { - return PMU_EVENT_INACTIVE; - } - - if (sprn == SPR_POWER_PMC5) { - return PMU_EVENT_INSTRUCTIONS; - } - - if (sprn == SPR_POWER_PMC6) { - return PMU_EVENT_CYCLES; - } - - i = sprn - SPR_POWER_PMC1; - pmcsel = extract64(env->spr[SPR_POWER_MMCR1], mmcr1_evt_extr[i], - MMCR1_EVT_SIZE); - - switch (pmcsel) { - case 0x2: - evt_type = PMU_EVENT_INSTRUCTIONS; - break; - case 0x1E: - evt_type = PMU_EVENT_CYCLES; - break; - case 0xF0: - /* - * PMC1SEL = 0xF0 is the architected PowerISA v3.1 - * event that counts cycles using PMC1. - */ - if (sprn == SPR_POWER_PMC1) { - evt_type = PMU_EVENT_CYCLES; - } - break; - case 0xFA: - /* - * PMC4SEL = 0xFA is the "instructions completed - * with run latch set" event. - */ - if (sprn == SPR_POWER_PMC4) { - evt_type = PMU_EVENT_INSN_RUN_LATCH; - } - break; - case 0xFE: - /* - * PMC1SEL = 0xFE is the architected PowerISA v3.1 - * event to sample instructions using PMC1. - */ - if (sprn == SPR_POWER_PMC1) { - evt_type = PMU_EVENT_INSTRUCTIONS; - } - break; - default: - break; - } - - return evt_type; -} - void pmu_update_summaries(CPUPPCState *env) { target_ulong mmcr0 = env->spr[SPR_POWER_MMCR0]; @@ -238,18 +151,16 @@ static void pmu_update_cycles(CPUPPCState *env) { uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t time_delta = now - env->pmu_base_time; - int sprn; + int sprn, cyc_cnt = env->pmc_cyc_cnt; for (sprn = SPR_POWER_PMC1; sprn <= SPR_POWER_PMC6; sprn++) { - if (pmc_get_event(env, sprn) != PMU_EVENT_CYCLES) { - continue; + if (cyc_cnt & (1 << (sprn - SPR_POWER_PMC1 + 1))) { + /* + * The pseries and powernv clock runs at 1Ghz, meaning + * that 1 nanosec equals 1 cycle. + */ + env->spr[sprn] += time_delta; } - - /* - * The pseries and powernv clock runs at 1Ghz, meaning - * that 1 nanosec equals 1 cycle. - */ - env->spr[sprn] += time_delta; } /* Update base_time for future calculations */ @@ -278,7 +189,7 @@ static void pmc_update_overflow_timer(CPUPPCState *env, int sprn) return; } - if (pmc_get_event(env, sprn) != PMU_EVENT_CYCLES || + if (!(env->pmc_cyc_cnt & (1 << (sprn - SPR_POWER_PMC1 + 1))) || !pmc_has_overflow_enabled(env, sprn)) { /* Overflow timer is not needed for this counter */ timer_del(pmc_overflow_timer); @@ -286,7 +197,7 @@ static void pmc_update_overflow_timer(CPUPPCState *env, int sprn) } if (env->spr[sprn] >= PMC_COUNTER_NEGATIVE_VAL) { - timeout = 0; + timeout = 0; } else { timeout = PMC_COUNTER_NEGATIVE_VAL - env->spr[sprn]; } From 0625c7760d5451d7436ef0738f763c6bb5141919 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 4 Jan 2022 07:55:35 +0100 Subject: [PATCH 166/730] target/ppc: do not call hreg_compute_hflags() in helper_store_mmcr0() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MMCR0 writes will change only MMCR0 bits which are used to calculate HFLAGS_PMCC0, HFLAGS_PMCC1 and HFLAGS_INSN_CNT hflags. No other machine register will be changed during this operation. This means that hreg_compute_hflags() is overkill for what we need to do. pmu_update_summaries() is already updating HFLAGS_INSN_CNT without calling hreg_compure_hflags(). Let's do the same for the other 2 MMCR0 hflags. Reviewed-by: Richard Henderson Signed-off-by: Daniel Henrique Barboza Message-Id: <20220103224746.167831-5-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- target/ppc/power8-pmu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/target/ppc/power8-pmu.c b/target/ppc/power8-pmu.c index 73713ca2a3..236e8e66e9 100644 --- a/target/ppc/power8-pmu.c +++ b/target/ppc/power8-pmu.c @@ -224,12 +224,17 @@ static void pmu_update_overflow_timers(CPUPPCState *env) void helper_store_mmcr0(CPUPPCState *env, target_ulong value) { + bool hflags_pmcc0 = (value & MMCR0_PMCC0) != 0; + bool hflags_pmcc1 = (value & MMCR0_PMCC1) != 0; + pmu_update_cycles(env); env->spr[SPR_POWER_MMCR0] = value; /* MMCR0 writes can change HFLAGS_PMCC[01] and HFLAGS_INSN_CNT */ - hreg_compute_hflags(env); + env->hflags = deposit32(env->hflags, HFLAGS_PMCC0, 1, hflags_pmcc0); + env->hflags = deposit32(env->hflags, HFLAGS_PMCC1, 1, hflags_pmcc1); + pmu_update_summaries(env); /* Update cycle overflow timers with the current MMCR0 state */ From 6947feca588670a0443d3e8892e6e20c6acb491c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 28 Jul 2021 19:42:24 +0200 Subject: [PATCH 167/730] hw/sd/sdcard: Rename Write Protect Group variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'wp_groups' holds a bitmap, rename it as 'wp_group_bmap'. 'wpgrps_size' is the bitmap size (in bits), rename it as 'wp_group_bits'. Patch created mechanically using: $ sed -i -e s/wp_groups/wp_group_bmap/ \ -e s/wpgrps_size/wp_group_bits/ hw/sd/sd.c Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20210728181728.2012952-4-f4bug@amsat.org> Reviewed-by: Alexander Bulekov --- hw/sd/sd.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index bb5dbff68c..c10a1e469b 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -116,8 +116,8 @@ struct SDState { int32_t state; /* current card state, one of SDCardStates */ uint32_t vhs; bool wp_switch; - unsigned long *wp_groups; - int32_t wpgrps_size; + unsigned long *wp_group_bmap; + int32_t wp_group_bits; uint64_t size; uint32_t blk_len; uint32_t multi_blk_cnt; @@ -567,10 +567,10 @@ static void sd_reset(DeviceState *dev) sd_set_cardstatus(sd); sd_set_sdstatus(sd); - g_free(sd->wp_groups); + g_free(sd->wp_group_bmap); sd->wp_switch = sd->blk ? !blk_is_writable(sd->blk) : false; - sd->wpgrps_size = sect; - sd->wp_groups = bitmap_new(sd->wpgrps_size); + sd->wp_group_bits = sect; + sd->wp_group_bmap = bitmap_new(sd->wp_group_bits); memset(sd->function_group, 0, sizeof(sd->function_group)); sd->erase_start = INVALID_ADDRESS; sd->erase_end = INVALID_ADDRESS; @@ -673,7 +673,7 @@ static const VMStateDescription sd_vmstate = { VMSTATE_UINT32(card_status, SDState), VMSTATE_PARTIAL_BUFFER(sd_status, SDState, 1), VMSTATE_UINT32(vhs, SDState), - VMSTATE_BITMAP(wp_groups, SDState, 0, wpgrps_size), + VMSTATE_BITMAP(wp_group_bmap, SDState, 0, wp_group_bits), VMSTATE_UINT32(blk_len, SDState), VMSTATE_UINT32(multi_blk_cnt, SDState), VMSTATE_UINT32(erase_start, SDState), @@ -803,8 +803,8 @@ static void sd_erase(SDState *sd) if (sdsc) { /* Only SDSC cards support write protect groups */ wpnum = sd_addr_to_wpnum(erase_addr); - assert(wpnum < sd->wpgrps_size); - if (test_bit(wpnum, sd->wp_groups)) { + assert(wpnum < sd->wp_group_bits); + if (test_bit(wpnum, sd->wp_group_bmap)) { sd->card_status |= WP_ERASE_SKIP; continue; } @@ -828,8 +828,8 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr) */ continue; } - assert(wpnum < sd->wpgrps_size); - if (test_bit(wpnum, sd->wp_groups)) { + assert(wpnum < sd->wp_group_bits); + if (test_bit(wpnum, sd->wp_group_bmap)) { ret |= (1 << i); } } @@ -869,7 +869,7 @@ static void sd_function_switch(SDState *sd, uint32_t arg) static inline bool sd_wp_addr(SDState *sd, uint64_t addr) { - return test_bit(sd_addr_to_wpnum(addr), sd->wp_groups); + return test_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap); } static void sd_lock_command(SDState *sd) @@ -897,7 +897,7 @@ static void sd_lock_command(SDState *sd) sd->card_status |= LOCK_UNLOCK_FAILED; return; } - bitmap_zero(sd->wp_groups, sd->wpgrps_size); + bitmap_zero(sd->wp_group_bmap, sd->wp_group_bits); sd->csd[14] &= ~0x10; sd->card_status &= ~CARD_IS_LOCKED; sd->pwd_len = 0; @@ -1348,7 +1348,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) } sd->state = sd_programming_state; - set_bit(sd_addr_to_wpnum(addr), sd->wp_groups); + set_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap); /* Bzzzzzzztt .... Operation complete. */ sd->state = sd_transfer_state; return sd_r1b; @@ -1370,7 +1370,7 @@ static sd_rsp_type_t sd_normal_command(SDState *sd, SDRequest req) } sd->state = sd_programming_state; - clear_bit(sd_addr_to_wpnum(addr), sd->wp_groups); + clear_bit(sd_addr_to_wpnum(addr), sd->wp_group_bmap); /* Bzzzzzzztt .... Operation complete. */ sd->state = sd_transfer_state; return sd_r1b; From b66f73a0cb312c81470433dfd5275d2824bb89de Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 28 Dec 2021 20:57:17 +0800 Subject: [PATCH 168/730] hw/sd: Add SDHC support for SD card SPI-mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In SPI-mode, SD card's OCR register: Card Capacity Status (CCS) bit is not set to 1 correclty when the assigned SD image size is larger than 2GB (SDHC). This will cause the SD card to be indentified as SDSC incorrectly. CCS bit should be set to 1 if we are using SDHC. Also, as there's no power up emulation in SPI-mode. The OCR register: Card power up status bit bit (busy) should also be set to 1 when reset. (busy bit is set to LOW if the card has not finished the power up routine.) Signed-off-by: Frank Chang Reviewed-by: Jim Shu Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211228125719.14712-1-frank.chang@sifive.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/sd/sd.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/hw/sd/sd.c b/hw/sd/sd.c index c10a1e469b..cd67a7bac8 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -290,12 +290,6 @@ FIELD(OCR, CARD_POWER_UP, 31, 1) | R_OCR_CARD_CAPACITY_MASK \ | R_OCR_CARD_POWER_UP_MASK) -static void sd_set_ocr(SDState *sd) -{ - /* All voltages OK */ - sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK; -} - static void sd_ocr_powerup(void *opaque) { SDState *sd = opaque; @@ -311,6 +305,22 @@ static void sd_ocr_powerup(void *opaque) } } +static void sd_set_ocr(SDState *sd) +{ + /* All voltages OK */ + sd->ocr = R_OCR_VDD_VOLTAGE_WIN_HI_MASK; + + if (sd->spi) { + /* + * We don't need to emulate power up sequence in SPI-mode. + * Thus, the card's power up status bit should be set to 1 when reset. + * The card's capacity status bit should also be set if SD card size + * is larger than 2GB for SDHC support. + */ + sd_ocr_powerup(sd); + } +} + static void sd_set_scr(SDState *sd) { sd->scr[0] = 0 << 4; /* SCR structure version 1.0 */ @@ -560,6 +570,7 @@ static void sd_reset(DeviceState *dev) sd->state = sd_idle_state; sd->rca = 0x0000; + sd->size = size; sd_set_ocr(sd); sd_set_scr(sd); sd_set_cid(sd); @@ -574,7 +585,6 @@ static void sd_reset(DeviceState *dev) memset(sd->function_group, 0, sizeof(sd->function_group)); sd->erase_start = INVALID_ADDRESS; sd->erase_end = INVALID_ADDRESS; - sd->size = size; sd->blk_len = 0x200; sd->pwd_len = 0; sd->expecting_acmd = false; From c578ff18584666499c3141b2d770b9e36b5e9d7e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 16 Dec 2021 06:07:25 -0800 Subject: [PATCH 169/730] tcg/optimize: Fix folding of vector ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bitwise operations are easy to fold, because the operation is identical regardless of element size. But add and sub need extra element size info that is not currently propagated. Fixes: 2f9f08ba43d Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/issues/799 Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- tcg/optimize.c | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/tcg/optimize.c b/tcg/optimize.c index 2397f2cf93..e573000951 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -308,13 +308,13 @@ static uint64_t do_constant_folding_2(TCGOpcode op, uint64_t x, uint64_t y) CASE_OP_32_64(mul): return x * y; - CASE_OP_32_64(and): + CASE_OP_32_64_VEC(and): return x & y; - CASE_OP_32_64(or): + CASE_OP_32_64_VEC(or): return x | y; - CASE_OP_32_64(xor): + CASE_OP_32_64_VEC(xor): return x ^ y; case INDEX_op_shl_i32: @@ -347,16 +347,16 @@ static uint64_t do_constant_folding_2(TCGOpcode op, uint64_t x, uint64_t y) case INDEX_op_rotl_i64: return rol64(x, y & 63); - CASE_OP_32_64(not): + CASE_OP_32_64_VEC(not): return ~x; CASE_OP_32_64(neg): return -x; - CASE_OP_32_64(andc): + CASE_OP_32_64_VEC(andc): return x & ~y; - CASE_OP_32_64(orc): + CASE_OP_32_64_VEC(orc): return x | ~y; CASE_OP_32_64(eqv): @@ -751,6 +751,12 @@ static bool fold_const2(OptContext *ctx, TCGOp *op) return false; } +static bool fold_commutative(OptContext *ctx, TCGOp *op) +{ + swap_commutative(op->args[0], &op->args[1], &op->args[2]); + return false; +} + static bool fold_const2_commutative(OptContext *ctx, TCGOp *op) { swap_commutative(op->args[0], &op->args[1], &op->args[2]); @@ -905,6 +911,16 @@ static bool fold_add(OptContext *ctx, TCGOp *op) return false; } +/* We cannot as yet do_constant_folding with vectors. */ +static bool fold_add_vec(OptContext *ctx, TCGOp *op) +{ + if (fold_commutative(ctx, op) || + fold_xi_to_x(ctx, op, 0)) { + return true; + } + return false; +} + static bool fold_addsub2(OptContext *ctx, TCGOp *op, bool add) { if (arg_is_const(op->args[2]) && arg_is_const(op->args[3]) && @@ -1938,10 +1954,10 @@ static bool fold_sub_to_neg(OptContext *ctx, TCGOp *op) return false; } -static bool fold_sub(OptContext *ctx, TCGOp *op) +/* We cannot as yet do_constant_folding with vectors. */ +static bool fold_sub_vec(OptContext *ctx, TCGOp *op) { - if (fold_const2(ctx, op) || - fold_xx_to_i(ctx, op, 0) || + if (fold_xx_to_i(ctx, op, 0) || fold_xi_to_x(ctx, op, 0) || fold_sub_to_neg(ctx, op)) { return true; @@ -1949,6 +1965,11 @@ static bool fold_sub(OptContext *ctx, TCGOp *op) return false; } +static bool fold_sub(OptContext *ctx, TCGOp *op) +{ + return fold_const2(ctx, op) || fold_sub_vec(ctx, op); +} + static bool fold_sub2(OptContext *ctx, TCGOp *op) { return fold_addsub2(ctx, op, false); @@ -2052,9 +2073,12 @@ void tcg_optimize(TCGContext *s) * Sorted alphabetically by opcode as much as possible. */ switch (opc) { - CASE_OP_32_64_VEC(add): + CASE_OP_32_64(add): done = fold_add(&ctx, op); break; + case INDEX_op_add_vec: + done = fold_add_vec(&ctx, op); + break; CASE_OP_32_64(add2): done = fold_add2(&ctx, op); break; @@ -2193,9 +2217,12 @@ void tcg_optimize(TCGContext *s) CASE_OP_32_64(sextract): done = fold_sextract(&ctx, op); break; - CASE_OP_32_64_VEC(sub): + CASE_OP_32_64(sub): done = fold_sub(&ctx, op); break; + case INDEX_op_sub_vec: + done = fold_sub_vec(&ctx, op); + break; CASE_OP_32_64(sub2): done = fold_sub2(&ctx, op); break; From f341b9aabd0e1bc6b5d3f51d43d09e64b33a5857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 4 Jan 2022 22:50:27 +0100 Subject: [PATCH 170/730] linux-user: Fix trivial build error on loongarch64 hosts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building using GCC 8.3.0 on loongarch64 (Loongnix) we get: In file included from ../linux-user/signal.c:33: ../linux-user/host/loongarch64/host-signal.h: In function ‘host_signal_write’: ../linux-user/host/loongarch64/host-signal.h:57:9: error: a label can only be part of a statement and a declaration is not a statement uint32_t sel = (insn >> 15) & 0b11111111111; ^~~~~~~~ We don't use the 'sel' variable more than once, so drop it. Meson output for the record: Host machine cpu family: loongarch64 Host machine cpu: loongarch64 C compiler for the host machine: cc (gcc 8.3.0 "cc (Loongnix 8.3.0-6.lnd.vec.27) 8.3.0") C linker for the host machine: cc ld.bfd 2.31.1-system Fixes: ad812c3bd65 ("linux-user: Implement CPU-specific signal handler for loongarch64 hosts") Reported-by: Song Gao Suggested-by: Song Gao Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: WANG Xuerui Reviewed-by: Richard Henderson Message-Id: <20220104215027.2180972-1-f4bug@amsat.org> Signed-off-by: Richard Henderson --- linux-user/host/loongarch64/host-signal.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/linux-user/host/loongarch64/host-signal.h b/linux-user/host/loongarch64/host-signal.h index 05e2c82371..7effa24251 100644 --- a/linux-user/host/loongarch64/host-signal.h +++ b/linux-user/host/loongarch64/host-signal.h @@ -54,9 +54,7 @@ static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc) } break; case 0b001110: /* indexed, atomic, bounds-checking memory operations */ - uint32_t sel = (insn >> 15) & 0b11111111111; - - switch (sel) { + switch ((insn >> 15) & 0b11111111111) { case 0b00000100000: /* stx.b */ case 0b00000101000: /* stx.h */ case 0b00000110000: /* stx.w */ From 9de225a1c27500c2d80a916d1c2a41d8e2a5f6e8 Mon Sep 17 00:00:00 2001 From: Xiaoyao Li Date: Tue, 4 Jan 2022 10:41:36 +0800 Subject: [PATCH 171/730] sysemu: Cleanup qemu_run_machine_init_done_notifiers() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove qemu_run_machine_init_done_notifiers() since no implementation and user. Fixes: f66dc8737c9 ("vl: move all generic initialization out of vl.c") Signed-off-by: Xiaoyao Li Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220104024136.1433545-1-xiaoyao.li@intel.com> Signed-off-by: Richard Henderson --- include/sysemu/sysemu.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 8fae667172..b9421e03ff 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -16,7 +16,6 @@ extern bool qemu_uuid_set; void qemu_add_exit_notifier(Notifier *notify); void qemu_remove_exit_notifier(Notifier *notify); -void qemu_run_machine_init_done_notifiers(void); void qemu_add_machine_init_done_notifier(Notifier *notify); void qemu_remove_machine_init_done_notifier(Notifier *notify); From d7478d4229f0a2b2817a55487e6b17081099fae4 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 4 Jan 2022 11:00:35 -0800 Subject: [PATCH 172/730] common-user: Fix tail calls to safe_syscall_set_errno_tail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the ABIs in which the syscall return register is not also the first function argument register, move the errno value into the correct place. Fixes: a3310c0397e2 ("linux-user: Move syscall error detection into safe_syscall_base") Reported-by: Laurent Vivier Tested-by: Laurent Vivier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-Id: <20220104190454.542225-1-richard.henderson@linaro.org> --- common-user/host/i386/safe-syscall.inc.S | 1 + common-user/host/mips/safe-syscall.inc.S | 1 + common-user/host/x86_64/safe-syscall.inc.S | 1 + 3 files changed, 3 insertions(+) diff --git a/common-user/host/i386/safe-syscall.inc.S b/common-user/host/i386/safe-syscall.inc.S index baf5400a29..9c45e56e48 100644 --- a/common-user/host/i386/safe-syscall.inc.S +++ b/common-user/host/i386/safe-syscall.inc.S @@ -120,6 +120,7 @@ safe_syscall_end: pop %ebp .cfi_adjust_cfa_offset -4 .cfi_restore ebp + mov %eax, (%esp) jmp safe_syscall_set_errno_tail .cfi_endproc diff --git a/common-user/host/mips/safe-syscall.inc.S b/common-user/host/mips/safe-syscall.inc.S index fc75a337d1..6a44614970 100644 --- a/common-user/host/mips/safe-syscall.inc.S +++ b/common-user/host/mips/safe-syscall.inc.S @@ -141,6 +141,7 @@ safe_syscall_end: 1: USE_ALT_CP(t0) SETUP_GPX(t1) SETUP_GPX64(t0, t1) + move a0, v0 PTR_LA t9, safe_syscall_set_errno_tail jr t9 diff --git a/common-user/host/x86_64/safe-syscall.inc.S b/common-user/host/x86_64/safe-syscall.inc.S index a20927a783..d1a67a303a 100644 --- a/common-user/host/x86_64/safe-syscall.inc.S +++ b/common-user/host/x86_64/safe-syscall.inc.S @@ -99,6 +99,7 @@ safe_syscall_end: 1: pop %rbp .cfi_def_cfa_offset 8 .cfi_restore rbp + mov %eax, %edi jmp safe_syscall_set_errno_tail .cfi_endproc From fb084237a3b78b20fd9d888dffd673b6656ea3be Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 4 Jan 2022 21:14:23 -0800 Subject: [PATCH 173/730] common-user: Really fix i386 calls to safe_syscall_set_errno_tail Brown bag time: offset 0 from esp is the return address, offset 4 is the first argument. Fixes: d7478d4229f0 ("common-user: Fix tail calls to safe_syscall_set_errno_tail") Signed-off-by: Richard Henderson --- common-user/host/i386/safe-syscall.inc.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common-user/host/i386/safe-syscall.inc.S b/common-user/host/i386/safe-syscall.inc.S index 9c45e56e48..db2ed09839 100644 --- a/common-user/host/i386/safe-syscall.inc.S +++ b/common-user/host/i386/safe-syscall.inc.S @@ -120,7 +120,7 @@ safe_syscall_end: pop %ebp .cfi_adjust_cfa_offset -4 .cfi_restore ebp - mov %eax, (%esp) + mov %eax, 4(%esp) jmp safe_syscall_set_errno_tail .cfi_endproc From 01854af2cfee62028693f45f1f23107b916974b1 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 17 Dec 2021 15:39:48 +0100 Subject: [PATCH 174/730] hw: Add compat machines for 7.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 7.0 machine types for arm/i440fx/q35/s390x/spapr. Signed-off-by: Cornelia Huck Reviewed-by: Juan Quintela Reviewed-by: Andrew Jones Reviewed-by: Daniel P. Berrangé Reviewed-by: Christian Borntraeger Acked-by: Cédric Le Goater Message-Id: <20211217143948.289995-1-cohuck@redhat.com> Signed-off-by: Thomas Huth --- hw/arm/virt.c | 11 +++++++++-- hw/core/machine.c | 3 +++ hw/i386/pc.c | 3 +++ hw/i386/pc_piix.c | 14 +++++++++++++- hw/i386/pc_q35.c | 13 ++++++++++++- hw/ppc/spapr.c | 17 ++++++++++++++--- hw/s390x/s390-virtio-ccw.c | 14 +++++++++++++- include/hw/boards.h | 3 +++ include/hw/i386/pc.h | 3 +++ 9 files changed, 73 insertions(+), 8 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 6bce595aba..4593fea1ce 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2856,10 +2856,17 @@ static void machvirt_machine_init(void) } type_init(machvirt_machine_init); -static void virt_machine_6_2_options(MachineClass *mc) +static void virt_machine_7_0_options(MachineClass *mc) { } -DEFINE_VIRT_MACHINE_AS_LATEST(6, 2) +DEFINE_VIRT_MACHINE_AS_LATEST(7, 0) + +static void virt_machine_6_2_options(MachineClass *mc) +{ + virt_machine_7_0_options(mc); + compat_props_add(mc->compat_props, hw_compat_6_2, hw_compat_6_2_len); +} +DEFINE_VIRT_MACHINE(6, 2) static void virt_machine_6_1_options(MachineClass *mc) { diff --git a/hw/core/machine.c b/hw/core/machine.c index a4a2df405f..debcdc0e70 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -37,6 +37,9 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-pci.h" +GlobalProperty hw_compat_6_2[] = {}; +const size_t hw_compat_6_2_len = G_N_ELEMENTS(hw_compat_6_2); + GlobalProperty hw_compat_6_1[] = { { "vhost-user-vsock-device", "seqpacket", "off" }, { "nvme-ns", "shared", "off" }, diff --git a/hw/i386/pc.c b/hw/i386/pc.c index a2ef40ecbc..fccde2ef39 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -94,6 +94,9 @@ #include "trace.h" #include CONFIG_DEVICES +GlobalProperty pc_compat_6_2[] = {}; +const size_t pc_compat_6_2_len = G_N_ELEMENTS(pc_compat_6_2); + GlobalProperty pc_compat_6_1[] = { { TYPE_X86_CPU, "hv-version-id-build", "0x1bbc" }, { TYPE_X86_CPU, "hv-version-id-major", "0x0006" }, diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 223dd3e05d..1999190276 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -413,7 +413,7 @@ static void pc_i440fx_machine_options(MachineClass *m) machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); } -static void pc_i440fx_6_2_machine_options(MachineClass *m) +static void pc_i440fx_7_0_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_machine_options(m); @@ -422,6 +422,18 @@ static void pc_i440fx_6_2_machine_options(MachineClass *m) pcmc->default_cpu_version = 1; } +DEFINE_I440FX_MACHINE(v7_0, "pc-i440fx-7.0", NULL, + pc_i440fx_7_0_machine_options); + +static void pc_i440fx_6_2_machine_options(MachineClass *m) +{ + pc_i440fx_7_0_machine_options(m); + m->alias = NULL; + m->is_default = false; + compat_props_add(m->compat_props, hw_compat_6_2, hw_compat_6_2_len); + compat_props_add(m->compat_props, pc_compat_6_2, pc_compat_6_2_len); +} + DEFINE_I440FX_MACHINE(v6_2, "pc-i440fx-6.2", NULL, pc_i440fx_6_2_machine_options); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index e1e100316d..2e981f436c 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -360,7 +360,7 @@ static void pc_q35_machine_options(MachineClass *m) m->max_cpus = 288; } -static void pc_q35_6_2_machine_options(MachineClass *m) +static void pc_q35_7_0_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_machine_options(m); @@ -368,6 +368,17 @@ static void pc_q35_6_2_machine_options(MachineClass *m) pcmc->default_cpu_version = 1; } +DEFINE_Q35_MACHINE(v7_0, "pc-q35-7.0", NULL, + pc_q35_7_0_machine_options); + +static void pc_q35_6_2_machine_options(MachineClass *m) +{ + pc_q35_7_0_machine_options(m); + m->alias = NULL; + compat_props_add(m->compat_props, hw_compat_6_2, hw_compat_6_2_len); + compat_props_add(m->compat_props, pc_compat_6_2, pc_compat_6_2_len); +} + DEFINE_Q35_MACHINE(v6_2, "pc-q35-6.2", NULL, pc_q35_6_2_machine_options); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 3b5fd749be..8373429325 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -4666,14 +4666,25 @@ static void spapr_machine_latest_class_options(MachineClass *mc) type_init(spapr_machine_register_##suffix) /* - * pseries-6.2 + * pseries-7.0 */ -static void spapr_machine_6_2_class_options(MachineClass *mc) +static void spapr_machine_7_0_class_options(MachineClass *mc) { /* Defaults for the latest behaviour inherited from the base class */ } -DEFINE_SPAPR_MACHINE(6_2, "6.2", true); +DEFINE_SPAPR_MACHINE(7_0, "7.0", true); + +/* + * pseries-6.2 + */ +static void spapr_machine_6_2_class_options(MachineClass *mc) +{ + spapr_machine_7_0_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_6_2, hw_compat_6_2_len); +} + +DEFINE_SPAPR_MACHINE(6_2, "6.2", false); /* * pseries-6.1 diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 653587ea62..84e3e63c43 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -791,14 +791,26 @@ bool css_migration_enabled(void) } \ type_init(ccw_machine_register_##suffix) +static void ccw_machine_7_0_instance_options(MachineState *machine) +{ +} + +static void ccw_machine_7_0_class_options(MachineClass *mc) +{ +} +DEFINE_CCW_MACHINE(7_0, "7.0", true); + static void ccw_machine_6_2_instance_options(MachineState *machine) { + ccw_machine_7_0_instance_options(machine); } static void ccw_machine_6_2_class_options(MachineClass *mc) { + ccw_machine_7_0_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_6_2, hw_compat_6_2_len); } -DEFINE_CCW_MACHINE(6_2, "6.2", true); +DEFINE_CCW_MACHINE(6_2, "6.2", false); static void ccw_machine_6_1_instance_options(MachineState *machine) { diff --git a/include/hw/boards.h b/include/hw/boards.h index f49a2578ea..c92ac8815c 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -380,6 +380,9 @@ struct MachineState { } \ type_init(machine_initfn##_register_types) +extern GlobalProperty hw_compat_6_2[]; +extern const size_t hw_compat_6_2_len; + extern GlobalProperty hw_compat_6_1[]; extern const size_t hw_compat_6_1_len; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 9ab39e428f..b38947c224 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -196,6 +196,9 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, /* sgx.c */ void pc_machine_init_sgx_epc(PCMachineState *pcms); +extern GlobalProperty pc_compat_6_2[]; +extern const size_t pc_compat_6_2_len; + extern GlobalProperty pc_compat_6_1[]; extern const size_t pc_compat_6_1_len; From 7539fa0116c8f84e56eace198c42a938ab4c3f8e Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 22 Dec 2021 16:39:23 +0100 Subject: [PATCH 175/730] tests/qtest/test-x86-cpuid-compat: Check for machines before using them The user might have disabled the pc-i440fx machine type (or it's older versions, like done in downstream RHEL) in the QEMU binary, so let's better check whether the machine types are available before using them. Message-Id: <20211222153923.1000420-1-thuth@redhat.com> Reviewed-by: Igor Mammedov Signed-off-by: Thomas Huth --- tests/qtest/test-x86-cpuid-compat.c | 85 ++++++++++++++++------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/tests/qtest/test-x86-cpuid-compat.c b/tests/qtest/test-x86-cpuid-compat.c index f28848e06e..39138db774 100644 --- a/tests/qtest/test-x86-cpuid-compat.c +++ b/tests/qtest/test-x86-cpuid-compat.c @@ -302,54 +302,65 @@ int main(int argc, char **argv) /* Check compatibility of old machine-types that didn't * auto-increase level/xlevel/xlevel2: */ - - add_cpuid_test("x86/cpuid/auto-level/pc-2.7", - "-machine pc-i440fx-2.7 -cpu 486,arat=on,avx512vbmi=on,xsaveopt=on", - "level", 1); - add_cpuid_test("x86/cpuid/auto-xlevel/pc-2.7", - "-machine pc-i440fx-2.7 -cpu 486,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", - "xlevel", 0); - add_cpuid_test("x86/cpuid/auto-xlevel2/pc-2.7", - "-machine pc-i440fx-2.7 -cpu 486,xstore=on", - "xlevel2", 0); + if (qtest_has_machine("pc-i440fx-2.7")) { + add_cpuid_test("x86/cpuid/auto-level/pc-2.7", + "-machine pc-i440fx-2.7 -cpu 486,arat=on,avx512vbmi=on,xsaveopt=on", + "level", 1); + add_cpuid_test("x86/cpuid/auto-xlevel/pc-2.7", + "-machine pc-i440fx-2.7 -cpu 486,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", + "xlevel", 0); + add_cpuid_test("x86/cpuid/auto-xlevel2/pc-2.7", + "-machine pc-i440fx-2.7 -cpu 486,xstore=on", + "xlevel2", 0); + } /* * QEMU 1.4.0 had auto-level enabled for CPUID[7], already, * and the compat code that sets default level shouldn't * disable the auto-level=7 code: */ - add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-1.4/off", - "-machine pc-i440fx-1.4 -cpu Nehalem", - "level", 2); - add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-1.5/on", - "-machine pc-i440fx-1.4 -cpu Nehalem,smap=on", - "level", 7); - add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/off", - "-machine pc-i440fx-2.3 -cpu Penryn", - "level", 4); - add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/on", - "-machine pc-i440fx-2.3 -cpu Penryn,erms=on", - "level", 7); - add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/off", - "-machine pc-i440fx-2.9 -cpu Conroe", - "level", 10); - add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/on", - "-machine pc-i440fx-2.9 -cpu Conroe,erms=on", - "level", 10); + if (qtest_has_machine("pc-i440fx-1.4")) { + add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-1.4/off", + "-machine pc-i440fx-1.4 -cpu Nehalem", + "level", 2); + add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-1.5/on", + "-machine pc-i440fx-1.4 -cpu Nehalem,smap=on", + "level", 7); + } + if (qtest_has_machine("pc-i440fx-2.3")) { + add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/off", + "-machine pc-i440fx-2.3 -cpu Penryn", + "level", 4); + add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/on", + "-machine pc-i440fx-2.3 -cpu Penryn,erms=on", + "level", 7); + } + if (qtest_has_machine("pc-i440fx-2.9")) { + add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/off", + "-machine pc-i440fx-2.9 -cpu Conroe", + "level", 10); + add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/on", + "-machine pc-i440fx-2.9 -cpu Conroe,erms=on", + "level", 10); + } /* * xlevel doesn't have any feature that triggers auto-level * code on old machine-types. Just check that the compat code * is working correctly: */ - add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.3", - "-machine pc-i440fx-2.3 -cpu SandyBridge", - "xlevel", 0x8000000a); - add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-off", - "-machine pc-i440fx-2.4 -cpu SandyBridge,", - "xlevel", 0x80000008); - add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-on", - "-machine pc-i440fx-2.4 -cpu SandyBridge,svm=on,npt=on", - "xlevel", 0x80000008); + if (qtest_has_machine("pc-i440fx-2.3")) { + add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.3", + "-machine pc-i440fx-2.3 -cpu SandyBridge", + "xlevel", 0x8000000a); + } + if (qtest_has_machine("pc-i440fx-2.4")) { + add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-off", + "-machine pc-i440fx-2.4 -cpu SandyBridge,", + "xlevel", 0x80000008); + add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-on", + "-machine pc-i440fx-2.4 -cpu SandyBridge,svm=on,npt=on", + "xlevel", 0x80000008); + } /* Test feature parsing */ add_feature_test("x86/cpuid/features/plus", From 961fb4b465800318792047de2339292f3ac37fa6 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 22 Dec 2021 16:36:00 +0100 Subject: [PATCH 176/730] tests/qtest/hd-geo-test: Check for the lsi53c895a controller before using it The lsi53c895a SCSI controller might have been disabled in the target binary, so let's check for its availability first before using it. Message-Id: <20211222153600.976588-1-thuth@redhat.com> Signed-off-by: Thomas Huth --- tests/qtest/hd-geo-test.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/qtest/hd-geo-test.c b/tests/qtest/hd-geo-test.c index 113126ae06..771eaa741b 100644 --- a/tests/qtest/hd-geo-test.c +++ b/tests/qtest/hd-geo-test.c @@ -960,9 +960,11 @@ int main(int argc, char **argv) qtest_add_func("hd-geo/ide/device/user/chst", test_ide_device_user_chst); if (have_qemu_img()) { qtest_add_func("hd-geo/override/ide", test_override_ide); - qtest_add_func("hd-geo/override/scsi", test_override_scsi); - qtest_add_func("hd-geo/override/scsi_2_controllers", - test_override_scsi_2_controllers); + if (qtest_has_device("lsi53c895a")) { + qtest_add_func("hd-geo/override/scsi", test_override_scsi); + qtest_add_func("hd-geo/override/scsi_2_controllers", + test_override_scsi_2_controllers); + } qtest_add_func("hd-geo/override/virtio_blk", test_override_virtio_blk); qtest_add_func("hd-geo/override/zero_chs", test_override_zero_chs); qtest_add_func("hd-geo/override/scsi_hot_unplug", From 585507017c956e6695ef4ee760440dc6153ed5cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 25 Dec 2021 00:45:04 +0100 Subject: [PATCH 177/730] tests/unit/test-util-sockets: Use g_file_open_tmp() to create temp file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similarly to commit e63ed64c6d1 ("tests/qtest/virtio-net-failover: Use g_file_open_tmp() to create temporary file"), avoid calling g_test_rand_int() before g_test_init(): use g_file_open_tmp(). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20211224234504.3413370-1-philmd@redhat.com> Signed-off-by: Thomas Huth --- tests/unit/test-util-sockets.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/unit/test-util-sockets.c b/tests/unit/test-util-sockets.c index 72b9246529..896247e3ed 100644 --- a/tests/unit/test-util-sockets.c +++ b/tests/unit/test-util-sockets.c @@ -305,9 +305,11 @@ static void test_socket_unix_abstract(void) }; int i; + i = g_file_open_tmp("unix-XXXXXX", &addr.u.q_unix.path, NULL); + g_assert_true(i >= 0); + close(i); + addr.type = SOCKET_ADDRESS_TYPE_UNIX; - addr.u.q_unix.path = g_strdup_printf("unix-%d-%u", - getpid(), g_random_int()); addr.u.q_unix.has_abstract = true; addr.u.q_unix.abstract = true; addr.u.q_unix.has_tight = false; From fe86fe237ccfe447db3a28db90d02ace47cf8c8a Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 15 Dec 2021 09:24:17 +0100 Subject: [PATCH 178/730] qemu-options: Remove the deprecated -no-quit option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This option was just a wrapper around the -display ...,window-close=off parameter, and the name "no-quit" is rather confusing compared to "window-close" (since there are still other means to quit the emulator), so let's remove this now. Message-Id: <20211215082417.180735-1-thuth@redhat.com> Acked-by: Michal Prívozník Reviewed-by: Markus Armbruster Signed-off-by: Thomas Huth --- docs/about/deprecated.rst | 6 ------ docs/about/removed-features.rst | 7 +++++++ qemu-options.hx | 8 -------- softmmu/vl.c | 8 +------- 4 files changed, 8 insertions(+), 21 deletions(-) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 5693abb663..e21e07478f 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -134,12 +134,6 @@ specified. Use ``-display sdl,window-close=...`` instead (i.e. with a minus instead of an underscore between "window" and "close"). -``-no-quit`` (since 6.1) -'''''''''''''''''''''''' - -The ``-no-quit`` is a synonym for ``-display ...,window-close=off`` which -should be used instead. - ``-alt-grab`` and ``-display sdl,alt_grab=on`` (since 6.2) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''' diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index d42c3341de..4c4da20d0f 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -330,6 +330,13 @@ RISC-V firmware not booted by default (removed in 5.1) QEMU 5.1 changes the default behaviour from ``-bios none`` to ``-bios default`` for the RISC-V ``virt`` machine and ``sifive_u`` machine. +``-no-quit`` (removed in 7.0) +''''''''''''''''''''''''''''' + +The ``-no-quit`` was a synonym for ``-display ...,window-close=off`` which +should be used instead. + + QEMU Machine Protocol (QMP) commands ------------------------------------ diff --git a/qemu-options.hx b/qemu-options.hx index fd1f8135fb..ec90505d84 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2065,14 +2065,6 @@ SRST ``-display sdl,grab-mod=rctrl`` instead. ERST -DEF("no-quit", 0, QEMU_OPTION_no_quit, - "-no-quit disable SDL/GTK window close capability (deprecated)\n", QEMU_ARCH_ALL) -SRST -``-no-quit`` - Disable window close capability (SDL and GTK only). This option is - deprecated, please use ``-display ...,window-close=off`` instead. -ERST - DEF("sdl", 0, QEMU_OPTION_sdl, "-sdl shorthand for -display sdl\n", QEMU_ARCH_ALL) SRST diff --git a/softmmu/vl.c b/softmmu/vl.c index d9e4c619d3..a8cad43691 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1941,7 +1941,7 @@ static void qemu_create_early_backends(void) "for SDL, ignoring option"); } if (dpy.has_window_close && !use_gtk && !use_sdl) { - error_report("-no-quit is only valid for GTK and SDL, " + error_report("window-close is only valid for GTK and SDL, " "ignoring option"); } @@ -3301,12 +3301,6 @@ void qemu_init(int argc, char **argv, char **envp) warn_report("-ctrl-grab is deprecated, please use " "-display sdl,grab-mod=rctrl instead."); break; - case QEMU_OPTION_no_quit: - dpy.has_window_close = true; - dpy.window_close = false; - warn_report("-no-quit is deprecated, please use " - "-display ...,window-close=off instead."); - break; case QEMU_OPTION_sdl: warn_report("-sdl is deprecated, use -display sdl instead."); #ifdef CONFIG_SDL From 9a50594761b4e329dc01cdd072c573a19e105775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 4 Jan 2022 11:46:49 +0400 Subject: [PATCH 179/730] docs/sphinx: fix compatibility with sphinx < 1.8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SphinxDirective was added with sphinx 1.8 (2018-09-13). Reported-by: Thomas Huth Signed-off-by: Marc-André Lureau Tested-by: Thomas Huth Message-Id: <20220104074649.1712440-1-marcandre.lureau@redhat.com> Signed-off-by: Thomas Huth --- docs/sphinx/fakedbusdoc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sphinx/fakedbusdoc.py b/docs/sphinx/fakedbusdoc.py index a680b25754..d2c5079046 100644 --- a/docs/sphinx/fakedbusdoc.py +++ b/docs/sphinx/fakedbusdoc.py @@ -7,12 +7,12 @@ # Author: Marc-André Lureau """dbus-doc is a Sphinx extension that provides documentation from D-Bus XML.""" +from docutils.parsers.rst import Directive from sphinx.application import Sphinx -from sphinx.util.docutils import SphinxDirective from typing import Any, Dict -class FakeDBusDocDirective(SphinxDirective): +class FakeDBusDocDirective(Directive): has_content = True required_arguments = 1 From 4cc75ce697cb36381eaf574a478197d24abfed5b Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 4 Jan 2022 10:12:40 +0100 Subject: [PATCH 180/730] gitlab-ci: Enable docs in the centos job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We just ran into a problem that the docs don't build on RHEL8 / CentOS 8 anymore. Seems like these distros are using one of the oldest Sphinx versions that we still have to support. Thus enable the docs build in the CI on CentOS so that such bugs don't slip in so easily again. Message-Id: <20220104091240.160867-1-thuth@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Marc-André Lureau Signed-off-by: Thomas Huth --- .gitlab-ci.d/buildtest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index 7e1cb0b3c2..12fb1130fe 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -164,7 +164,7 @@ build-system-centos: variables: IMAGE: centos8 CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-fdt=system - --enable-modules --enable-trace-backends=dtrace + --enable-modules --enable-trace-backends=dtrace --enable-docs TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu x86_64-softmmu rx-softmmu sh4-softmmu nios2-softmmu MAKE_CHECK_ARGS: check-build From 057dc9a635fe37118a98b32e8bd9d8ed47b1a102 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 4 Jan 2022 11:33:19 +0100 Subject: [PATCH 181/730] docs/tools/qemu-trace-stap.rst: Do not hard-code the QEMU binary name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In downstream, we want to use a different name for the QEMU binary, and some people might also use the docs for non-x86 binaries, that's why we already created the |qemu_system| placeholder in the past. Use it now in the stap trace doc, too. Message-Id: <20220104103319.179870-1-thuth@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Thomas Huth --- docs/tools/qemu-trace-stap.rst | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/tools/qemu-trace-stap.rst b/docs/tools/qemu-trace-stap.rst index d53073b52b..2169ce5d17 100644 --- a/docs/tools/qemu-trace-stap.rst +++ b/docs/tools/qemu-trace-stap.rst @@ -46,19 +46,19 @@ The following commands are valid: any of the listed names. If no *PATTERN* is given, the all possible probes will be listed. - For example, to list all probes available in the ``qemu-system-x86_64`` + For example, to list all probes available in the |qemu_system| binary: - :: + .. parsed-literal:: - $ qemu-trace-stap list qemu-system-x86_64 + $ qemu-trace-stap list |qemu_system| To filter the list to only cover probes related to QEMU's cryptographic subsystem, in a binary outside ``$PATH`` - :: + .. parsed-literal:: - $ qemu-trace-stap list /opt/qemu/4.0.0/bin/qemu-system-x86_64 'qcrypto*' + $ qemu-trace-stap list /opt/qemu/|version|/bin/|qemu_system| 'qcrypto*' .. option:: run OPTIONS BINARY PATTERN... @@ -90,26 +90,26 @@ The following commands are valid: Restrict the tracing session so that it only triggers for the process identified by *PID*. - For example, to monitor all processes executing ``qemu-system-x86_64`` + For example, to monitor all processes executing |qemu_system| as found on ``$PATH``, displaying all I/O related probes: - :: + .. parsed-literal:: - $ qemu-trace-stap run qemu-system-x86_64 'qio*' + $ qemu-trace-stap run |qemu_system| 'qio*' To monitor only the QEMU process with PID 1732 - :: + .. parsed-literal:: - $ qemu-trace-stap run --pid=1732 qemu-system-x86_64 'qio*' + $ qemu-trace-stap run --pid=1732 |qemu_system| 'qio*' To monitor QEMU processes running an alternative binary outside of ``$PATH``, displaying verbose information about setup of the tracing environment: - :: + .. parsed-literal:: - $ qemu-trace-stap -v run /opt/qemu/4.0.0/qemu-system-x86_64 'qio*' + $ qemu-trace-stap -v run /opt/qemu/|version|/bin/|qemu_system| 'qio*' See also -------- From 7656d9ce09cb1d6d76eeb2081f164a920361d1d3 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Mon, 11 Oct 2021 19:33:05 +0200 Subject: [PATCH 182/730] virtio-mem: Don't skip alignment checks when warning about block size If we warn about the block size being smaller than the default, we skip some alignment checks. This can currently only fail on x86-64, when specifying a block size of 1 MiB, however, we detect the THP size of 2 MiB. Fixes: 228957fea3a9 ("virtio-mem: Probe THP size to determine default block size") Cc: "Michael S. Tsirkin" Signed-off-by: David Hildenbrand Message-Id: <20211011173305.13778-1-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-mem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index d5a578142b..341c3fa2c1 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -733,7 +733,8 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp) warn_report("'%s' property is smaller than the default block size (%" PRIx64 " MiB)", VIRTIO_MEM_BLOCK_SIZE_PROP, virtio_mem_default_block_size(rb) / MiB); - } else if (!QEMU_IS_ALIGNED(vmem->requested_size, vmem->block_size)) { + } + if (!QEMU_IS_ALIGNED(vmem->requested_size, vmem->block_size)) { error_setg(errp, "'%s' property has to be multiples of '%s' (0x%" PRIx64 ")", VIRTIO_MEM_REQUESTED_SIZE_PROP, VIRTIO_MEM_BLOCK_SIZE_PROP, vmem->block_size); From 719fab3afad22f34f0c812a8956adc88ab3242ce Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Mon, 29 Nov 2021 14:51:00 +0100 Subject: [PATCH 183/730] qemu-binfmt-conf.sh: fix -F option qemu-binfmt-conf.sh should use "-F" as short option for "--qemu-suffix". Fix the getopt call to make this work. Fixes: 7155be7cda5c ("qemu-binfmt-conf.sh: allow to provide a suffix to the interpreter name") Signed-off-by: Martin Wilck Reviewed-by: Laurent Vivier Message-Id: <20211129135100.3934-1-mwilck@suse.com> Signed-off-by: Laurent Vivier --- scripts/qemu-binfmt-conf.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh index 7de996d536..e9bfeb94d3 100755 --- a/scripts/qemu-binfmt-conf.sh +++ b/scripts/qemu-binfmt-conf.sh @@ -340,7 +340,9 @@ PERSISTENT=no PRESERVE_ARG0=no QEMU_SUFFIX="" -options=$(getopt -o ds:Q:S:e:hc:p:g: -l debian,systemd:,qemu-path:,qemu-suffix:,exportdir:,help,credential:,persistent:,preserve-argv0: -- "$@") +_longopts="debian,systemd:,qemu-path:,qemu-suffix:,exportdir:,help,credential:,\ +persistent:,preserve-argv0:" +options=$(getopt -o ds:Q:S:e:hc:p:g:F: -l ${_longopts} -- "$@") eval set -- "$options" while true ; do From be23b0eb475e53bf0e346c20dd5277e3d96c66d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 16 Nov 2021 22:09:19 +0100 Subject: [PATCH 184/730] linux-user/hexagon: Use generic target_stat64 structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux Hexagon port doesn't define a specific 'struct stat' but uses the generic one (see Linux commit 6103ec56c65c [*] "asm-generic: add generic ABI headers" which predates the introduction of the Hexagon port). Remove the target specific target_stat (which in fact is the target_stat64 structure but uses incorrect target_long and ABI unsafe long long types) and use the generic target_stat64 instead. [*] https://github.com/torvalds/linux/commit/6103ec56c65c3#diff-5f59b07b38273b7d6a74193bc81a8cd18928c688276eae20cb10c569de3253ee Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Taylor Simpson Tested-by: Taylor Simpson Message-Id: <20211116210919.2823206-1-f4bug@amsat.org> Signed-off-by: Laurent Vivier --- linux-user/syscall_defs.h | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 0b13975937..585e933140 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2133,7 +2133,8 @@ struct target_stat64 { abi_ulong __unused5; }; -#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || defined(TARGET_RISCV) +#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) \ + || defined(TARGET_RISCV) || defined(TARGET_HEXAGON) /* These are the asm-generic versions of the stat and stat64 structures */ @@ -2244,31 +2245,6 @@ struct target_stat64 { uint64_t st_ino; }; -#elif defined(TARGET_HEXAGON) - -struct target_stat { - unsigned long long st_dev; - unsigned long long st_ino; - unsigned int st_mode; - unsigned int st_nlink; - unsigned int st_uid; - unsigned int st_gid; - unsigned long long st_rdev; - target_ulong __pad1; - long long st_size; - target_long st_blksize; - int __pad2; - long long st_blocks; - - target_long target_st_atime; - target_long target_st_atime_nsec; - target_long target_st_mtime; - target_long target_st_mtime_nsec; - target_long target_st_ctime; - target_long target_st_ctime_nsec; - int __unused[2]; -}; - #else #error unsupported CPU #endif From f93d0af88d8e4b4771144c14195dd97a5b55e149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 6 Nov 2021 12:39:16 +0100 Subject: [PATCH 185/730] linux-user: Mark cpu_loop() with noreturn attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cpu_loop() never exits, so mark it with QEMU_NORETURN. Reviewed-by: Richard Henderson Reviewed-By: Warner Losh Reviewed-by: Bin Meng Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Warner Losh Message-Id: <20211106113916.544587-1-f4bug@amsat.org> Signed-off-by: Laurent Vivier --- linux-user/user-internals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h index f71f372829..a8fdd6933b 100644 --- a/linux-user/user-internals.h +++ b/linux-user/user-internals.h @@ -64,7 +64,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg5, abi_long arg6, abi_long arg7, abi_long arg8); extern __thread CPUState *thread_cpu; -void cpu_loop(CPUArchState *env); +void QEMU_NORETURN cpu_loop(CPUArchState *env); const char *target_strerror(int err); int get_osversion(void); void init_qemu_uname_release(void); From e068b57d01bff8a6fe8ab04d0a489407557d0a1c Mon Sep 17 00:00:00 2001 From: Song Gao Date: Fri, 26 Nov 2021 10:23:06 +0800 Subject: [PATCH 186/730] linux-user: Move target_signal.h generic definitions to generic/signal.h No code change Suggested-by: Richard Henderson Signed-off-by: Song Gao Reviewed-by: Laurent Vivier Reviewed-by: Richard Henderson Message-Id: <1637893388-10282-2-git-send-email-gaosong@loongson.cn> Signed-off-by: Laurent Vivier --- linux-user/aarch64/target_signal.h | 18 ------------------ linux-user/arm/target_signal.h | 18 ------------------ linux-user/cris/target_signal.h | 18 ------------------ linux-user/generic/signal.h | 16 ++++++++++++++++ linux-user/hexagon/target_signal.h | 11 ----------- linux-user/i386/target_signal.h | 18 ------------------ linux-user/m68k/target_signal.h | 18 ------------------ linux-user/microblaze/target_signal.h | 18 ------------------ linux-user/nios2/target_signal.h | 16 ---------------- linux-user/openrisc/target_signal.h | 23 ----------------------- linux-user/ppc/target_signal.h | 18 ------------------ linux-user/riscv/target_signal.h | 12 ------------ linux-user/s390x/target_signal.h | 15 --------------- linux-user/sh4/target_signal.h | 18 ------------------ linux-user/x86_64/target_signal.h | 18 ------------------ linux-user/xtensa/target_signal.h | 17 ----------------- 16 files changed, 16 insertions(+), 256 deletions(-) diff --git a/linux-user/aarch64/target_signal.h b/linux-user/aarch64/target_signal.h index 7580d99403..40e399d990 100644 --- a/linux-user/aarch64/target_signal.h +++ b/linux-user/aarch64/target_signal.h @@ -1,24 +1,6 @@ #ifndef AARCH64_TARGET_SIGNAL_H #define AARCH64_TARGET_SIGNAL_H -/* this struct defines a stack used during syscall handling */ - -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - - -/* - * sigaltstack controls - */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" #define TARGET_SEGV_MTEAERR 8 /* Asynchronous ARM MTE error */ diff --git a/linux-user/arm/target_signal.h b/linux-user/arm/target_signal.h index 1e7fb0cecb..0e6351d9f7 100644 --- a/linux-user/arm/target_signal.h +++ b/linux-user/arm/target_signal.h @@ -1,24 +1,6 @@ #ifndef ARM_TARGET_SIGNAL_H #define ARM_TARGET_SIGNAL_H -/* this struct defines a stack used during syscall handling */ - -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - - -/* - * sigaltstack controls - */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/cris/target_signal.h b/linux-user/cris/target_signal.h index 83a5155507..ab0653fcdc 100644 --- a/linux-user/cris/target_signal.h +++ b/linux-user/cris/target_signal.h @@ -1,24 +1,6 @@ #ifndef CRIS_TARGET_SIGNAL_H #define CRIS_TARGET_SIGNAL_H -/* this struct defines a stack used during syscall handling */ - -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - - -/* - * sigaltstack controls - */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/generic/signal.h b/linux-user/generic/signal.h index 943bc1a1e2..ceaf8a876c 100644 --- a/linux-user/generic/signal.h +++ b/linux-user/generic/signal.h @@ -55,6 +55,22 @@ #define TARGET_SIG_UNBLOCK 1 /* for unblocking signals */ #define TARGET_SIG_SETMASK 2 /* for setting the signal mask */ +/* this struct defines a stack used during syscall handling */ +typedef struct target_sigaltstack { + abi_ulong ss_sp; + abi_int ss_flags; + abi_ulong ss_size; +} target_stack_t; + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK 1 +#define TARGET_SS_DISABLE 2 + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_SIGSTKSZ 8192 + /* bit-flags */ #define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */ /* mask for all SS_xxx flags */ diff --git a/linux-user/hexagon/target_signal.h b/linux-user/hexagon/target_signal.h index 9e0223d322..193abac340 100644 --- a/linux-user/hexagon/target_signal.h +++ b/linux-user/hexagon/target_signal.h @@ -18,17 +18,6 @@ #ifndef HEXAGON_TARGET_SIGNAL_H #define HEXAGON_TARGET_SIGNAL_H -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 - #include "../generic/signal.h" #define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 diff --git a/linux-user/i386/target_signal.h b/linux-user/i386/target_signal.h index 64d09f2e75..9315cba241 100644 --- a/linux-user/i386/target_signal.h +++ b/linux-user/i386/target_signal.h @@ -1,24 +1,6 @@ #ifndef I386_TARGET_SIGNAL_H #define I386_TARGET_SIGNAL_H -/* this struct defines a stack used during syscall handling */ - -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - - -/* - * sigaltstack controls - */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/m68k/target_signal.h b/linux-user/m68k/target_signal.h index 94157bf1f4..6e0f4b74e3 100644 --- a/linux-user/m68k/target_signal.h +++ b/linux-user/m68k/target_signal.h @@ -1,24 +1,6 @@ #ifndef M68K_TARGET_SIGNAL_H #define M68K_TARGET_SIGNAL_H -/* this struct defines a stack used during syscall handling */ - -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - - -/* - * sigaltstack controls - */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/microblaze/target_signal.h b/linux-user/microblaze/target_signal.h index e8b510f6b1..7dc5c45f00 100644 --- a/linux-user/microblaze/target_signal.h +++ b/linux-user/microblaze/target_signal.h @@ -1,24 +1,6 @@ #ifndef MICROBLAZE_TARGET_SIGNAL_H #define MICROBLAZE_TARGET_SIGNAL_H -/* this struct defines a stack used during syscall handling */ - -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - - -/* - * sigaltstack controls - */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" #define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 diff --git a/linux-user/nios2/target_signal.h b/linux-user/nios2/target_signal.h index fe266c4c51..46ca5948ce 100644 --- a/linux-user/nios2/target_signal.h +++ b/linux-user/nios2/target_signal.h @@ -1,22 +1,6 @@ #ifndef NIOS2_TARGET_SIGNAL_H #define NIOS2_TARGET_SIGNAL_H -/* this struct defines a stack used during syscall handling */ - -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - - -/* sigaltstack controls */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" /* Nios2 uses a fixed address on the kuser page for sigreturn. */ diff --git a/linux-user/openrisc/target_signal.h b/linux-user/openrisc/target_signal.h index 077ec3d5e8..5b9d40974a 100644 --- a/linux-user/openrisc/target_signal.h +++ b/linux-user/openrisc/target_signal.h @@ -1,29 +1,6 @@ #ifndef OPENRISC_TARGET_SIGNAL_H #define OPENRISC_TARGET_SIGNAL_H -/* this struct defines a stack used during syscall handling */ - -typedef struct target_sigaltstack { - abi_long ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - -/* sigaltstack controls */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_SA_NOCLDSTOP 0x00000001 -#define TARGET_SA_NOCLDWAIT 0x00000002 -#define TARGET_SA_SIGINFO 0x00000004 -#define TARGET_SA_ONSTACK 0x08000000 -#define TARGET_SA_RESTART 0x10000000 -#define TARGET_SA_NODEFER 0x40000000 -#define TARGET_SA_RESETHAND 0x80000000 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" #define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 diff --git a/linux-user/ppc/target_signal.h b/linux-user/ppc/target_signal.h index 82184ab8f2..5be24e152b 100644 --- a/linux-user/ppc/target_signal.h +++ b/linux-user/ppc/target_signal.h @@ -1,24 +1,6 @@ #ifndef PPC_TARGET_SIGNAL_H #define PPC_TARGET_SIGNAL_H -/* this struct defines a stack used during syscall handling */ - -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - - -/* - * sigaltstack controls - */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" #if !defined(TARGET_PPC64) diff --git a/linux-user/riscv/target_signal.h b/linux-user/riscv/target_signal.h index 3e36fddc9d..6c0470f0bc 100644 --- a/linux-user/riscv/target_signal.h +++ b/linux-user/riscv/target_signal.h @@ -1,18 +1,6 @@ #ifndef RISCV_TARGET_SIGNAL_H #define RISCV_TARGET_SIGNAL_H -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" #define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 diff --git a/linux-user/s390x/target_signal.h b/linux-user/s390x/target_signal.h index 64f5f42201..41e0e34a55 100644 --- a/linux-user/s390x/target_signal.h +++ b/linux-user/s390x/target_signal.h @@ -1,21 +1,6 @@ #ifndef S390X_TARGET_SIGNAL_H #define S390X_TARGET_SIGNAL_H -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - -/* - * sigaltstack controls - */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/sh4/target_signal.h b/linux-user/sh4/target_signal.h index 04069cba66..eee6a1a7cd 100644 --- a/linux-user/sh4/target_signal.h +++ b/linux-user/sh4/target_signal.h @@ -1,24 +1,6 @@ #ifndef SH4_TARGET_SIGNAL_H #define SH4_TARGET_SIGNAL_H -/* this struct defines a stack used during syscall handling */ - -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - - -/* - * sigaltstack controls - */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/x86_64/target_signal.h b/linux-user/x86_64/target_signal.h index 4673c5a886..9d9717406f 100644 --- a/linux-user/x86_64/target_signal.h +++ b/linux-user/x86_64/target_signal.h @@ -1,24 +1,6 @@ #ifndef X86_64_TARGET_SIGNAL_H #define X86_64_TARGET_SIGNAL_H -/* this struct defines a stack used during syscall handling */ - -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - - -/* - * sigaltstack controls - */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" /* For x86_64, use of SA_RESTORER is mandatory. */ diff --git a/linux-user/xtensa/target_signal.h b/linux-user/xtensa/target_signal.h index 1c7ee73154..e4b1bea5cb 100644 --- a/linux-user/xtensa/target_signal.h +++ b/linux-user/xtensa/target_signal.h @@ -1,23 +1,6 @@ #ifndef XTENSA_TARGET_SIGNAL_H #define XTENSA_TARGET_SIGNAL_H -/* this struct defines a stack used during syscall handling */ - -typedef struct target_sigaltstack { - abi_ulong ss_sp; - abi_int ss_flags; - abi_ulong ss_size; -} target_stack_t; - -/* - * sigaltstack controls - */ -#define TARGET_SS_ONSTACK 1 -#define TARGET_SS_DISABLE 2 - -#define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 - #include "../generic/signal.h" #define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 From f9d0707182fcf65593b55479fa891867192ebeef Mon Sep 17 00:00:00 2001 From: Song Gao Date: Fri, 26 Nov 2021 10:23:07 +0800 Subject: [PATCH 187/730] linux-user: target_syscall.h remove definition TARGET_MINSIGSTKSZ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TARGET_MINSIGSTKSZ has been defined in generic/signal.h or target_signal.h, We don't need to define it again. Signed-off-by: Song Gao Reviewed-by: Laurent Vivier Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <1637893388-10282-3-git-send-email-gaosong@loongson.cn> Signed-off-by: Laurent Vivier --- linux-user/aarch64/target_syscall.h | 1 - linux-user/alpha/target_syscall.h | 1 - linux-user/arm/target_syscall.h | 1 - linux-user/cris/target_syscall.h | 1 - linux-user/hppa/target_syscall.h | 1 - linux-user/i386/target_syscall.h | 1 - linux-user/m68k/target_syscall.h | 1 - linux-user/microblaze/target_syscall.h | 1 - linux-user/mips/target_syscall.h | 1 - linux-user/mips64/target_syscall.h | 1 - linux-user/nios2/target_syscall.h | 1 - linux-user/openrisc/target_syscall.h | 1 - linux-user/ppc/target_syscall.h | 1 - linux-user/riscv/target_syscall.h | 1 - linux-user/s390x/target_syscall.h | 1 - linux-user/sh4/target_syscall.h | 1 - linux-user/sparc/target_syscall.h | 1 - linux-user/x86_64/target_syscall.h | 1 - 18 files changed, 18 deletions(-) diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h index 76f6c3391d..508219d62a 100644 --- a/linux-user/aarch64/target_syscall.h +++ b/linux-user/aarch64/target_syscall.h @@ -15,7 +15,6 @@ struct target_pt_regs { #endif #define UNAME_MINIMUM_RELEASE "3.8.0" #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/alpha/target_syscall.h b/linux-user/alpha/target_syscall.h index 03091bf0a8..fda3a49f29 100644 --- a/linux-user/alpha/target_syscall.h +++ b/linux-user/alpha/target_syscall.h @@ -63,7 +63,6 @@ struct target_pt_regs { #define TARGET_UAC_NOPRINT 1 #define TARGET_UAC_NOFIX 2 #define TARGET_UAC_SIGBUS 4 -#define TARGET_MINSIGSTKSZ 4096 #define TARGET_MCL_CURRENT 0x2000 #define TARGET_MCL_FUTURE 0x4000 #define TARGET_MCL_ONFAULT 0x8000 diff --git a/linux-user/arm/target_syscall.h b/linux-user/arm/target_syscall.h index e870ed7a54..f04f9c9e3d 100644 --- a/linux-user/arm/target_syscall.h +++ b/linux-user/arm/target_syscall.h @@ -27,7 +27,6 @@ struct target_pt_regs { #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/cris/target_syscall.h b/linux-user/cris/target_syscall.h index 19e1281403..0b5ebf1f02 100644 --- a/linux-user/cris/target_syscall.h +++ b/linux-user/cris/target_syscall.h @@ -39,7 +39,6 @@ struct target_pt_regs { }; #define TARGET_CLONE_BACKWARDS2 -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/hppa/target_syscall.h b/linux-user/hppa/target_syscall.h index 0018bcb5c4..4b382c1fcf 100644 --- a/linux-user/hppa/target_syscall.h +++ b/linux-user/hppa/target_syscall.h @@ -22,7 +22,6 @@ struct target_pt_regs { #define UNAME_MACHINE "parisc" #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/i386/target_syscall.h b/linux-user/i386/target_syscall.h index ed356b3908..aaade06b13 100644 --- a/linux-user/i386/target_syscall.h +++ b/linux-user/i386/target_syscall.h @@ -150,7 +150,6 @@ struct target_vm86plus_struct { #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/m68k/target_syscall.h b/linux-user/m68k/target_syscall.h index 23359a6299..8d4ddbd76c 100644 --- a/linux-user/m68k/target_syscall.h +++ b/linux-user/m68k/target_syscall.h @@ -20,7 +20,6 @@ struct target_pt_regs { #define UNAME_MACHINE "m68k" #define UNAME_MINIMUM_RELEASE "2.6.32" -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/microblaze/target_syscall.h b/linux-user/microblaze/target_syscall.h index 7f653db34f..43362a1664 100644 --- a/linux-user/microblaze/target_syscall.h +++ b/linux-user/microblaze/target_syscall.h @@ -49,7 +49,6 @@ struct target_pt_regs { }; #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/mips/target_syscall.h b/linux-user/mips/target_syscall.h index f59057493a..7a82661fdb 100644 --- a/linux-user/mips/target_syscall.h +++ b/linux-user/mips/target_syscall.h @@ -24,7 +24,6 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/mips64/target_syscall.h b/linux-user/mips64/target_syscall.h index cd1e1b4969..2c7a881c74 100644 --- a/linux-user/mips64/target_syscall.h +++ b/linux-user/mips64/target_syscall.h @@ -21,7 +21,6 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/nios2/target_syscall.h b/linux-user/nios2/target_syscall.h index 78006c24d4..561b28d281 100644 --- a/linux-user/nios2/target_syscall.h +++ b/linux-user/nios2/target_syscall.h @@ -30,7 +30,6 @@ struct target_pt_regs { unsigned long orig_r7; }; -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/openrisc/target_syscall.h b/linux-user/openrisc/target_syscall.h index ef0d89a551..7fe5b73d3b 100644 --- a/linux-user/openrisc/target_syscall.h +++ b/linux-user/openrisc/target_syscall.h @@ -15,7 +15,6 @@ struct target_pt_regs { #define UNAME_MACHINE "openrisc" #define UNAME_MINIMUM_RELEASE "2.6.32" -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/ppc/target_syscall.h b/linux-user/ppc/target_syscall.h index b9c4b813d3..8b364697d4 100644 --- a/linux-user/ppc/target_syscall.h +++ b/linux-user/ppc/target_syscall.h @@ -71,7 +71,6 @@ struct target_revectored_struct { #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 0x2000 #define TARGET_MCL_FUTURE 0x4000 #define TARGET_MCL_ONFAULT 0x8000 diff --git a/linux-user/riscv/target_syscall.h b/linux-user/riscv/target_syscall.h index 9b13161324..7601f10c28 100644 --- a/linux-user/riscv/target_syscall.h +++ b/linux-user/riscv/target_syscall.h @@ -51,7 +51,6 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "4.15.0" #endif -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/s390x/target_syscall.h b/linux-user/s390x/target_syscall.h index 94f84178db..4018988a25 100644 --- a/linux-user/s390x/target_syscall.h +++ b/linux-user/s390x/target_syscall.h @@ -27,7 +27,6 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS2 -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/sh4/target_syscall.h b/linux-user/sh4/target_syscall.h index c1437adafe..148398855d 100644 --- a/linux-user/sh4/target_syscall.h +++ b/linux-user/sh4/target_syscall.h @@ -15,7 +15,6 @@ struct target_pt_regs { #define UNAME_MACHINE "sh4" #define UNAME_MINIMUM_RELEASE "2.6.32" -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/sparc/target_syscall.h b/linux-user/sparc/target_syscall.h index 087b39d39c..be77e44eb8 100644 --- a/linux-user/sparc/target_syscall.h +++ b/linux-user/sparc/target_syscall.h @@ -34,7 +34,6 @@ struct target_pt_regs { * and copy_thread(). */ #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 4096 #define TARGET_MCL_CURRENT 0x2000 #define TARGET_MCL_FUTURE 0x4000 #define TARGET_MCL_ONFAULT 0x8000 diff --git a/linux-user/x86_64/target_syscall.h b/linux-user/x86_64/target_syscall.h index 3ecccb72be..fb558345d3 100644 --- a/linux-user/x86_64/target_syscall.h +++ b/linux-user/x86_64/target_syscall.h @@ -100,7 +100,6 @@ struct target_msqid64_ds { #define TARGET_ARCH_SET_FS 0x1002 #define TARGET_ARCH_GET_FS 0x1003 #define TARGET_ARCH_GET_GS 0x1004 -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 From c1e8e3a746f6e4fb90ae65c715a4f79f6b4b6cf6 Mon Sep 17 00:00:00 2001 From: Song Gao Date: Fri, 26 Nov 2021 10:23:08 +0800 Subject: [PATCH 188/730] linux-user: Remove TARGET_SIGSTKSZ TARGET_SIGSTKSZ is not used, we should remove it. Signed-off-by: Song Gao Reviewed-by: Richard Henderson Message-Id: <1637893388-10282-4-git-send-email-gaosong@loongson.cn> Signed-off-by: Laurent Vivier --- linux-user/alpha/target_signal.h | 1 - linux-user/generic/signal.h | 1 - linux-user/hppa/target_signal.h | 1 - linux-user/mips/target_signal.h | 1 - linux-user/mips64/target_signal.h | 1 - linux-user/sparc/target_signal.h | 1 - 6 files changed, 6 deletions(-) diff --git a/linux-user/alpha/target_signal.h b/linux-user/alpha/target_signal.h index 0b6a39de65..bbb06e5463 100644 --- a/linux-user/alpha/target_signal.h +++ b/linux-user/alpha/target_signal.h @@ -62,7 +62,6 @@ typedef struct target_sigaltstack { #define TARGET_SA_SIGINFO 0x00000040 #define TARGET_MINSIGSTKSZ 4096 -#define TARGET_SIGSTKSZ 16384 /* From . */ #define TARGET_GEN_INTOVF -1 /* integer overflow */ diff --git a/linux-user/generic/signal.h b/linux-user/generic/signal.h index ceaf8a876c..6fd05b77bb 100644 --- a/linux-user/generic/signal.h +++ b/linux-user/generic/signal.h @@ -69,7 +69,6 @@ typedef struct target_sigaltstack { #define TARGET_SS_DISABLE 2 #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 /* bit-flags */ #define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */ diff --git a/linux-user/hppa/target_signal.h b/linux-user/hppa/target_signal.h index d558119ee7..af6c2fce58 100644 --- a/linux-user/hppa/target_signal.h +++ b/linux-user/hppa/target_signal.h @@ -64,7 +64,6 @@ typedef struct target_sigaltstack { #define TARGET_SA_NOCLDWAIT 0x00000080 #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 /* bit-flags */ #define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */ diff --git a/linux-user/mips/target_signal.h b/linux-user/mips/target_signal.h index 780a4ddf29..fa542c1f4e 100644 --- a/linux-user/mips/target_signal.h +++ b/linux-user/mips/target_signal.h @@ -67,7 +67,6 @@ typedef struct target_sigaltstack { #define TARGET_SA_RESTORER 0x04000000 /* Only for O32 */ #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 #if defined(TARGET_ABI_MIPSO32) /* compare linux/arch/mips/kernel/signal.c:setup_frame() */ diff --git a/linux-user/mips64/target_signal.h b/linux-user/mips64/target_signal.h index 275e9b7f9a..b05098f7f6 100644 --- a/linux-user/mips64/target_signal.h +++ b/linux-user/mips64/target_signal.h @@ -65,7 +65,6 @@ typedef struct target_sigaltstack { #define TARGET_SA_RESETHAND 0x80000000 #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 /* bit-flags */ #define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */ diff --git a/linux-user/sparc/target_signal.h b/linux-user/sparc/target_signal.h index e661ddd6ab..87757f0c4e 100644 --- a/linux-user/sparc/target_signal.h +++ b/linux-user/sparc/target_signal.h @@ -65,7 +65,6 @@ typedef struct target_sigaltstack { #define TARGET_ARCH_HAS_KA_RESTORER 1 #define TARGET_MINSIGSTKSZ 4096 -#define TARGET_SIGSTKSZ 16384 #ifdef TARGET_ABI32 #define TARGET_ARCH_HAS_SETUP_FRAME From 87e9bf23236d3c9da84f2b6164e06be3ecfd45e0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 27 Dec 2021 07:01:22 -0800 Subject: [PATCH 189/730] linux-user: Split out do_prctl and subroutines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the prctl constants are supposed to be generic, supply any that are not provided by the host. Split out subroutines for PR_GET_FP_MODE, PR_SET_FP_MODE, PR_GET_VL, PR_SET_VL, PR_RESET_KEYS, PR_SET_TAGGED_ADDR_CTRL, PR_GET_TAGGED_ADDR_CTRL. Return EINVAL for guests that do not support these options rather than pass them on to the host. Reviewed-by: Laurent Vivier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-Id: <20211227150127.2659293-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/aarch64/target_prctl.h | 160 ++++++++++ linux-user/aarch64/target_syscall.h | 23 -- linux-user/alpha/target_prctl.h | 1 + linux-user/arm/target_prctl.h | 1 + linux-user/cris/target_prctl.h | 1 + linux-user/hexagon/target_prctl.h | 1 + linux-user/hppa/target_prctl.h | 1 + linux-user/i386/target_prctl.h | 1 + linux-user/m68k/target_prctl.h | 1 + linux-user/microblaze/target_prctl.h | 1 + linux-user/mips/target_prctl.h | 88 ++++++ linux-user/mips/target_syscall.h | 6 - linux-user/mips64/target_prctl.h | 1 + linux-user/mips64/target_syscall.h | 6 - linux-user/nios2/target_prctl.h | 1 + linux-user/openrisc/target_prctl.h | 1 + linux-user/ppc/target_prctl.h | 1 + linux-user/riscv/target_prctl.h | 1 + linux-user/s390x/target_prctl.h | 1 + linux-user/sh4/target_prctl.h | 1 + linux-user/sparc/target_prctl.h | 1 + linux-user/syscall.c | 433 +++++++++------------------ linux-user/x86_64/target_prctl.h | 1 + linux-user/xtensa/target_prctl.h | 1 + 24 files changed, 414 insertions(+), 320 deletions(-) create mode 100644 linux-user/aarch64/target_prctl.h create mode 100644 linux-user/alpha/target_prctl.h create mode 100644 linux-user/arm/target_prctl.h create mode 100644 linux-user/cris/target_prctl.h create mode 100644 linux-user/hexagon/target_prctl.h create mode 100644 linux-user/hppa/target_prctl.h create mode 100644 linux-user/i386/target_prctl.h create mode 100644 linux-user/m68k/target_prctl.h create mode 100644 linux-user/microblaze/target_prctl.h create mode 100644 linux-user/mips/target_prctl.h create mode 100644 linux-user/mips64/target_prctl.h create mode 100644 linux-user/nios2/target_prctl.h create mode 100644 linux-user/openrisc/target_prctl.h create mode 100644 linux-user/ppc/target_prctl.h create mode 100644 linux-user/riscv/target_prctl.h create mode 100644 linux-user/s390x/target_prctl.h create mode 100644 linux-user/sh4/target_prctl.h create mode 100644 linux-user/sparc/target_prctl.h create mode 100644 linux-user/x86_64/target_prctl.h create mode 100644 linux-user/xtensa/target_prctl.h diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h new file mode 100644 index 0000000000..3f5a5d3933 --- /dev/null +++ b/linux-user/aarch64/target_prctl.h @@ -0,0 +1,160 @@ +/* + * AArch64 specific prctl functions for linux-user + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef AARCH64_TARGET_PRCTL_H +#define AARCH64_TARGET_PRCTL_H + +static abi_long do_prctl_get_vl(CPUArchState *env) +{ + ARMCPU *cpu = env_archcpu(env); + if (cpu_isar_feature(aa64_sve, cpu)) { + return ((cpu->env.vfp.zcr_el[1] & 0xf) + 1) * 16; + } + return -TARGET_EINVAL; +} +#define do_prctl_get_vl do_prctl_get_vl + +static abi_long do_prctl_set_vl(CPUArchState *env, abi_long arg2) +{ + /* + * We cannot support either PR_SVE_SET_VL_ONEXEC or PR_SVE_VL_INHERIT. + * Note the kernel definition of sve_vl_valid allows for VQ=512, + * i.e. VL=8192, even though the current architectural maximum is VQ=16. + */ + if (cpu_isar_feature(aa64_sve, env_archcpu(env)) + && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) { + ARMCPU *cpu = env_archcpu(env); + uint32_t vq, old_vq; + + old_vq = (env->vfp.zcr_el[1] & 0xf) + 1; + vq = MAX(arg2 / 16, 1); + vq = MIN(vq, cpu->sve_max_vq); + + if (vq < old_vq) { + aarch64_sve_narrow_vq(env, vq); + } + env->vfp.zcr_el[1] = vq - 1; + arm_rebuild_hflags(env); + return vq * 16; + } + return -TARGET_EINVAL; +} +#define do_prctl_set_vl do_prctl_set_vl + +static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2) +{ + ARMCPU *cpu = env_archcpu(env); + + if (cpu_isar_feature(aa64_pauth, cpu)) { + int all = (PR_PAC_APIAKEY | PR_PAC_APIBKEY | + PR_PAC_APDAKEY | PR_PAC_APDBKEY | PR_PAC_APGAKEY); + int ret = 0; + Error *err = NULL; + + if (arg2 == 0) { + arg2 = all; + } else if (arg2 & ~all) { + return -TARGET_EINVAL; + } + if (arg2 & PR_PAC_APIAKEY) { + ret |= qemu_guest_getrandom(&env->keys.apia, + sizeof(ARMPACKey), &err); + } + if (arg2 & PR_PAC_APIBKEY) { + ret |= qemu_guest_getrandom(&env->keys.apib, + sizeof(ARMPACKey), &err); + } + if (arg2 & PR_PAC_APDAKEY) { + ret |= qemu_guest_getrandom(&env->keys.apda, + sizeof(ARMPACKey), &err); + } + if (arg2 & PR_PAC_APDBKEY) { + ret |= qemu_guest_getrandom(&env->keys.apdb, + sizeof(ARMPACKey), &err); + } + if (arg2 & PR_PAC_APGAKEY) { + ret |= qemu_guest_getrandom(&env->keys.apga, + sizeof(ARMPACKey), &err); + } + if (ret != 0) { + /* + * Some unknown failure in the crypto. The best + * we can do is log it and fail the syscall. + * The real syscall cannot fail this way. + */ + qemu_log_mask(LOG_UNIMP, "PR_PAC_RESET_KEYS: Crypto failure: %s", + error_get_pretty(err)); + error_free(err); + return -TARGET_EIO; + } + return 0; + } + return -TARGET_EINVAL; +} +#define do_prctl_reset_keys do_prctl_reset_keys + +static abi_long do_prctl_set_tagged_addr_ctrl(CPUArchState *env, abi_long arg2) +{ + abi_ulong valid_mask = PR_TAGGED_ADDR_ENABLE; + ARMCPU *cpu = env_archcpu(env); + + if (cpu_isar_feature(aa64_mte, cpu)) { + valid_mask |= PR_MTE_TCF_MASK; + valid_mask |= PR_MTE_TAG_MASK; + } + + if (arg2 & ~valid_mask) { + return -TARGET_EINVAL; + } + env->tagged_addr_enable = arg2 & PR_TAGGED_ADDR_ENABLE; + + if (cpu_isar_feature(aa64_mte, cpu)) { + switch (arg2 & PR_MTE_TCF_MASK) { + case PR_MTE_TCF_NONE: + case PR_MTE_TCF_SYNC: + case PR_MTE_TCF_ASYNC: + break; + default: + return -EINVAL; + } + + /* + * Write PR_MTE_TCF to SCTLR_EL1[TCF0]. + * Note that the syscall values are consistent with hw. + */ + env->cp15.sctlr_el[1] = + deposit64(env->cp15.sctlr_el[1], 38, 2, arg2 >> PR_MTE_TCF_SHIFT); + + /* + * Write PR_MTE_TAG to GCR_EL1[Exclude]. + * Note that the syscall uses an include mask, + * and hardware uses an exclude mask -- invert. + */ + env->cp15.gcr_el1 = + deposit64(env->cp15.gcr_el1, 0, 16, ~arg2 >> PR_MTE_TAG_SHIFT); + arm_rebuild_hflags(env); + } + return 0; +} +#define do_prctl_set_tagged_addr_ctrl do_prctl_set_tagged_addr_ctrl + +static abi_long do_prctl_get_tagged_addr_ctrl(CPUArchState *env) +{ + ARMCPU *cpu = env_archcpu(env); + abi_long ret = 0; + + if (env->tagged_addr_enable) { + ret |= PR_TAGGED_ADDR_ENABLE; + } + if (cpu_isar_feature(aa64_mte, cpu)) { + /* See do_prctl_set_tagged_addr_ctrl. */ + ret |= extract64(env->cp15.sctlr_el[1], 38, 2) << PR_MTE_TCF_SHIFT; + ret = deposit64(ret, PR_MTE_TAG_SHIFT, 16, ~env->cp15.gcr_el1); + } + return ret; +} +#define do_prctl_get_tagged_addr_ctrl do_prctl_get_tagged_addr_ctrl + +#endif /* AARCH64_TARGET_PRCTL_H */ diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h index 508219d62a..a98f568ab4 100644 --- a/linux-user/aarch64/target_syscall.h +++ b/linux-user/aarch64/target_syscall.h @@ -19,27 +19,4 @@ struct target_pt_regs { #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 -#define TARGET_PR_SVE_SET_VL 50 -#define TARGET_PR_SVE_GET_VL 51 - -#define TARGET_PR_PAC_RESET_KEYS 54 -# define TARGET_PR_PAC_APIAKEY (1 << 0) -# define TARGET_PR_PAC_APIBKEY (1 << 1) -# define TARGET_PR_PAC_APDAKEY (1 << 2) -# define TARGET_PR_PAC_APDBKEY (1 << 3) -# define TARGET_PR_PAC_APGAKEY (1 << 4) - -#define TARGET_PR_SET_TAGGED_ADDR_CTRL 55 -#define TARGET_PR_GET_TAGGED_ADDR_CTRL 56 -# define TARGET_PR_TAGGED_ADDR_ENABLE (1UL << 0) -/* MTE tag check fault modes */ -# define TARGET_PR_MTE_TCF_SHIFT 1 -# define TARGET_PR_MTE_TCF_NONE (0UL << TARGET_PR_MTE_TCF_SHIFT) -# define TARGET_PR_MTE_TCF_SYNC (1UL << TARGET_PR_MTE_TCF_SHIFT) -# define TARGET_PR_MTE_TCF_ASYNC (2UL << TARGET_PR_MTE_TCF_SHIFT) -# define TARGET_PR_MTE_TCF_MASK (3UL << TARGET_PR_MTE_TCF_SHIFT) -/* MTE tag inclusion mask */ -# define TARGET_PR_MTE_TAG_SHIFT 3 -# define TARGET_PR_MTE_TAG_MASK (0xffffUL << TARGET_PR_MTE_TAG_SHIFT) - #endif /* AARCH64_TARGET_SYSCALL_H */ diff --git a/linux-user/alpha/target_prctl.h b/linux-user/alpha/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/alpha/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/arm/target_prctl.h b/linux-user/arm/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/arm/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/cris/target_prctl.h b/linux-user/cris/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/cris/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/hexagon/target_prctl.h b/linux-user/hexagon/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/hexagon/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/hppa/target_prctl.h b/linux-user/hppa/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/hppa/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/i386/target_prctl.h b/linux-user/i386/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/i386/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/m68k/target_prctl.h b/linux-user/m68k/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/m68k/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/microblaze/target_prctl.h b/linux-user/microblaze/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/microblaze/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/mips/target_prctl.h b/linux-user/mips/target_prctl.h new file mode 100644 index 0000000000..e028333db9 --- /dev/null +++ b/linux-user/mips/target_prctl.h @@ -0,0 +1,88 @@ +/* + * MIPS specific prctl functions for linux-user + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef MIPS_TARGET_PRCTL_H +#define MIPS_TARGET_PRCTL_H + +static abi_long do_prctl_get_fp_mode(CPUArchState *env) +{ + abi_long ret = 0; + + if (env->CP0_Status & (1 << CP0St_FR)) { + ret |= PR_FP_MODE_FR; + } + if (env->CP0_Config5 & (1 << CP0C5_FRE)) { + ret |= PR_FP_MODE_FRE; + } + return ret; +} +#define do_prctl_get_fp_mode do_prctl_get_fp_mode + +static abi_long do_prctl_set_fp_mode(CPUArchState *env, abi_long arg2) +{ + bool old_fr = env->CP0_Status & (1 << CP0St_FR); + bool old_fre = env->CP0_Config5 & (1 << CP0C5_FRE); + bool new_fr = arg2 & PR_FP_MODE_FR; + bool new_fre = arg2 & PR_FP_MODE_FRE; + const unsigned int known_bits = PR_FP_MODE_FR | PR_FP_MODE_FRE; + + /* If nothing to change, return right away, successfully. */ + if (old_fr == new_fr && old_fre == new_fre) { + return 0; + } + /* Check the value is valid */ + if (arg2 & ~known_bits) { + return -TARGET_EOPNOTSUPP; + } + /* Setting FRE without FR is not supported. */ + if (new_fre && !new_fr) { + return -TARGET_EOPNOTSUPP; + } + if (new_fr && !(env->active_fpu.fcr0 & (1 << FCR0_F64))) { + /* FR1 is not supported */ + return -TARGET_EOPNOTSUPP; + } + if (!new_fr && (env->active_fpu.fcr0 & (1 << FCR0_F64)) + && !(env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) { + /* cannot set FR=0 */ + return -TARGET_EOPNOTSUPP; + } + if (new_fre && !(env->active_fpu.fcr0 & (1 << FCR0_FREP))) { + /* Cannot set FRE=1 */ + return -TARGET_EOPNOTSUPP; + } + + int i; + fpr_t *fpr = env->active_fpu.fpr; + for (i = 0; i < 32 ; i += 2) { + if (!old_fr && new_fr) { + fpr[i].w[!FP_ENDIAN_IDX] = fpr[i + 1].w[FP_ENDIAN_IDX]; + } else if (old_fr && !new_fr) { + fpr[i + 1].w[FP_ENDIAN_IDX] = fpr[i].w[!FP_ENDIAN_IDX]; + } + } + + if (new_fr) { + env->CP0_Status |= (1 << CP0St_FR); + env->hflags |= MIPS_HFLAG_F64; + } else { + env->CP0_Status &= ~(1 << CP0St_FR); + env->hflags &= ~MIPS_HFLAG_F64; + } + if (new_fre) { + env->CP0_Config5 |= (1 << CP0C5_FRE); + if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) { + env->hflags |= MIPS_HFLAG_FRE; + } + } else { + env->CP0_Config5 &= ~(1 << CP0C5_FRE); + env->hflags &= ~MIPS_HFLAG_FRE; + } + + return 0; +} +#define do_prctl_set_fp_mode do_prctl_set_fp_mode + +#endif /* MIPS_TARGET_PRCTL_H */ diff --git a/linux-user/mips/target_syscall.h b/linux-user/mips/target_syscall.h index 7a82661fdb..08ead67810 100644 --- a/linux-user/mips/target_syscall.h +++ b/linux-user/mips/target_syscall.h @@ -35,10 +35,4 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env) return 0x40000; } -/* MIPS-specific prctl() options */ -#define TARGET_PR_SET_FP_MODE 45 -#define TARGET_PR_GET_FP_MODE 46 -#define TARGET_PR_FP_MODE_FR (1 << 0) -#define TARGET_PR_FP_MODE_FRE (1 << 1) - #endif /* MIPS_TARGET_SYSCALL_H */ diff --git a/linux-user/mips64/target_prctl.h b/linux-user/mips64/target_prctl.h new file mode 100644 index 0000000000..18da9ae619 --- /dev/null +++ b/linux-user/mips64/target_prctl.h @@ -0,0 +1 @@ +#include "../mips/target_prctl.h" diff --git a/linux-user/mips64/target_syscall.h b/linux-user/mips64/target_syscall.h index 2c7a881c74..358dc2d64c 100644 --- a/linux-user/mips64/target_syscall.h +++ b/linux-user/mips64/target_syscall.h @@ -32,10 +32,4 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env) return 0x40000; } -/* MIPS-specific prctl() options */ -#define TARGET_PR_SET_FP_MODE 45 -#define TARGET_PR_GET_FP_MODE 46 -#define TARGET_PR_FP_MODE_FR (1 << 0) -#define TARGET_PR_FP_MODE_FRE (1 << 1) - #endif /* MIPS64_TARGET_SYSCALL_H */ diff --git a/linux-user/nios2/target_prctl.h b/linux-user/nios2/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/nios2/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/openrisc/target_prctl.h b/linux-user/openrisc/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/openrisc/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/ppc/target_prctl.h b/linux-user/ppc/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/ppc/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/riscv/target_prctl.h b/linux-user/riscv/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/riscv/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/s390x/target_prctl.h b/linux-user/s390x/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/s390x/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/sh4/target_prctl.h b/linux-user/sh4/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/sh4/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/sparc/target_prctl.h b/linux-user/sparc/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/sparc/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 56a3e17183..0f0f67d567 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6294,9 +6294,155 @@ abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) return ret; } #endif /* defined(TARGET_ABI32 */ - #endif /* defined(TARGET_I386) */ +/* + * These constants are generic. Supply any that are missing from the host. + */ +#ifndef PR_SET_NAME +# define PR_SET_NAME 15 +# define PR_GET_NAME 16 +#endif +#ifndef PR_SET_FP_MODE +# define PR_SET_FP_MODE 45 +# define PR_GET_FP_MODE 46 +# define PR_FP_MODE_FR (1 << 0) +# define PR_FP_MODE_FRE (1 << 1) +#endif +#ifndef PR_SVE_SET_VL +# define PR_SVE_SET_VL 50 +# define PR_SVE_GET_VL 51 +# define PR_SVE_VL_LEN_MASK 0xffff +# define PR_SVE_VL_INHERIT (1 << 17) +#endif +#ifndef PR_PAC_RESET_KEYS +# define PR_PAC_RESET_KEYS 54 +# define PR_PAC_APIAKEY (1 << 0) +# define PR_PAC_APIBKEY (1 << 1) +# define PR_PAC_APDAKEY (1 << 2) +# define PR_PAC_APDBKEY (1 << 3) +# define PR_PAC_APGAKEY (1 << 4) +#endif +#ifndef PR_SET_TAGGED_ADDR_CTRL +# define PR_SET_TAGGED_ADDR_CTRL 55 +# define PR_GET_TAGGED_ADDR_CTRL 56 +# define PR_TAGGED_ADDR_ENABLE (1UL << 0) +#endif +#ifndef PR_MTE_TCF_SHIFT +# define PR_MTE_TCF_SHIFT 1 +# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT) +# define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT) +# define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT) +# define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT) +# define PR_MTE_TAG_SHIFT 3 +# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT) +#endif + +#include "target_prctl.h" + +static abi_long do_prctl_inval0(CPUArchState *env) +{ + return -TARGET_EINVAL; +} + +static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2) +{ + return -TARGET_EINVAL; +} + +#ifndef do_prctl_get_fp_mode +#define do_prctl_get_fp_mode do_prctl_inval0 +#endif +#ifndef do_prctl_set_fp_mode +#define do_prctl_set_fp_mode do_prctl_inval1 +#endif +#ifndef do_prctl_get_vl +#define do_prctl_get_vl do_prctl_inval0 +#endif +#ifndef do_prctl_set_vl +#define do_prctl_set_vl do_prctl_inval1 +#endif +#ifndef do_prctl_reset_keys +#define do_prctl_reset_keys do_prctl_inval1 +#endif +#ifndef do_prctl_set_tagged_addr_ctrl +#define do_prctl_set_tagged_addr_ctrl do_prctl_inval1 +#endif +#ifndef do_prctl_get_tagged_addr_ctrl +#define do_prctl_get_tagged_addr_ctrl do_prctl_inval0 +#endif + +static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + abi_long ret; + + switch (option) { + case PR_GET_PDEATHSIG: + { + int deathsig; + ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig, + arg3, arg4, arg5)); + if (!is_error(ret) && arg2 && put_user_s32(deathsig, arg2)) { + return -TARGET_EFAULT; + } + return ret; + } + case PR_GET_NAME: + { + void *name = lock_user(VERIFY_WRITE, arg2, 16, 1); + if (!name) { + return -TARGET_EFAULT; + } + ret = get_errno(prctl(PR_GET_NAME, (uintptr_t)name, + arg3, arg4, arg5)); + unlock_user(name, arg2, 16); + return ret; + } + case PR_SET_NAME: + { + void *name = lock_user(VERIFY_READ, arg2, 16, 1); + if (!name) { + return -TARGET_EFAULT; + } + ret = get_errno(prctl(PR_SET_NAME, (uintptr_t)name, + arg3, arg4, arg5)); + unlock_user(name, arg2, 0); + return ret; + } + case PR_GET_FP_MODE: + return do_prctl_get_fp_mode(env); + case PR_SET_FP_MODE: + return do_prctl_set_fp_mode(env, arg2); + case PR_SVE_GET_VL: + return do_prctl_get_vl(env); + case PR_SVE_SET_VL: + return do_prctl_set_vl(env, arg2); + case PR_PAC_RESET_KEYS: + if (arg3 || arg4 || arg5) { + return -TARGET_EINVAL; + } + return do_prctl_reset_keys(env, arg2); + case PR_SET_TAGGED_ADDR_CTRL: + if (arg3 || arg4 || arg5) { + return -TARGET_EINVAL; + } + return do_prctl_set_tagged_addr_ctrl(env, arg2); + case PR_GET_TAGGED_ADDR_CTRL: + if (arg2 || arg3 || arg4 || arg5) { + return -TARGET_EINVAL; + } + return do_prctl_get_tagged_addr_ctrl(env); + case PR_GET_SECCOMP: + case PR_SET_SECCOMP: + /* Disable seccomp to prevent the target disabling syscalls we need. */ + return -TARGET_EINVAL; + default: + /* Most prctl options have no pointer arguments */ + return get_errno(prctl(option, arg2, arg3, arg4, arg5)); + } +} + #define NEW_STACK_SIZE 0x40000 @@ -10635,290 +10781,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; #endif case TARGET_NR_prctl: - switch (arg1) { - case PR_GET_PDEATHSIG: - { - int deathsig; - ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5)); - if (!is_error(ret) && arg2 - && put_user_s32(deathsig, arg2)) { - return -TARGET_EFAULT; - } - return ret; - } -#ifdef PR_GET_NAME - case PR_GET_NAME: - { - void *name = lock_user(VERIFY_WRITE, arg2, 16, 1); - if (!name) { - return -TARGET_EFAULT; - } - ret = get_errno(prctl(arg1, (unsigned long)name, - arg3, arg4, arg5)); - unlock_user(name, arg2, 16); - return ret; - } - case PR_SET_NAME: - { - void *name = lock_user(VERIFY_READ, arg2, 16, 1); - if (!name) { - return -TARGET_EFAULT; - } - ret = get_errno(prctl(arg1, (unsigned long)name, - arg3, arg4, arg5)); - unlock_user(name, arg2, 0); - return ret; - } -#endif -#ifdef TARGET_MIPS - case TARGET_PR_GET_FP_MODE: - { - CPUMIPSState *env = ((CPUMIPSState *)cpu_env); - ret = 0; - if (env->CP0_Status & (1 << CP0St_FR)) { - ret |= TARGET_PR_FP_MODE_FR; - } - if (env->CP0_Config5 & (1 << CP0C5_FRE)) { - ret |= TARGET_PR_FP_MODE_FRE; - } - return ret; - } - case TARGET_PR_SET_FP_MODE: - { - CPUMIPSState *env = ((CPUMIPSState *)cpu_env); - bool old_fr = env->CP0_Status & (1 << CP0St_FR); - bool old_fre = env->CP0_Config5 & (1 << CP0C5_FRE); - bool new_fr = arg2 & TARGET_PR_FP_MODE_FR; - bool new_fre = arg2 & TARGET_PR_FP_MODE_FRE; - - const unsigned int known_bits = TARGET_PR_FP_MODE_FR | - TARGET_PR_FP_MODE_FRE; - - /* If nothing to change, return right away, successfully. */ - if (old_fr == new_fr && old_fre == new_fre) { - return 0; - } - /* Check the value is valid */ - if (arg2 & ~known_bits) { - return -TARGET_EOPNOTSUPP; - } - /* Setting FRE without FR is not supported. */ - if (new_fre && !new_fr) { - return -TARGET_EOPNOTSUPP; - } - if (new_fr && !(env->active_fpu.fcr0 & (1 << FCR0_F64))) { - /* FR1 is not supported */ - return -TARGET_EOPNOTSUPP; - } - if (!new_fr && (env->active_fpu.fcr0 & (1 << FCR0_F64)) - && !(env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) { - /* cannot set FR=0 */ - return -TARGET_EOPNOTSUPP; - } - if (new_fre && !(env->active_fpu.fcr0 & (1 << FCR0_FREP))) { - /* Cannot set FRE=1 */ - return -TARGET_EOPNOTSUPP; - } - - int i; - fpr_t *fpr = env->active_fpu.fpr; - for (i = 0; i < 32 ; i += 2) { - if (!old_fr && new_fr) { - fpr[i].w[!FP_ENDIAN_IDX] = fpr[i + 1].w[FP_ENDIAN_IDX]; - } else if (old_fr && !new_fr) { - fpr[i + 1].w[FP_ENDIAN_IDX] = fpr[i].w[!FP_ENDIAN_IDX]; - } - } - - if (new_fr) { - env->CP0_Status |= (1 << CP0St_FR); - env->hflags |= MIPS_HFLAG_F64; - } else { - env->CP0_Status &= ~(1 << CP0St_FR); - env->hflags &= ~MIPS_HFLAG_F64; - } - if (new_fre) { - env->CP0_Config5 |= (1 << CP0C5_FRE); - if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) { - env->hflags |= MIPS_HFLAG_FRE; - } - } else { - env->CP0_Config5 &= ~(1 << CP0C5_FRE); - env->hflags &= ~MIPS_HFLAG_FRE; - } - - return 0; - } -#endif /* MIPS */ -#ifdef TARGET_AARCH64 - case TARGET_PR_SVE_SET_VL: - /* - * We cannot support either PR_SVE_SET_VL_ONEXEC or - * PR_SVE_VL_INHERIT. Note the kernel definition - * of sve_vl_valid allows for VQ=512, i.e. VL=8192, - * even though the current architectural maximum is VQ=16. - */ - ret = -TARGET_EINVAL; - if (cpu_isar_feature(aa64_sve, env_archcpu(cpu_env)) - && arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) { - CPUARMState *env = cpu_env; - ARMCPU *cpu = env_archcpu(env); - uint32_t vq, old_vq; - - old_vq = (env->vfp.zcr_el[1] & 0xf) + 1; - vq = MAX(arg2 / 16, 1); - vq = MIN(vq, cpu->sve_max_vq); - - if (vq < old_vq) { - aarch64_sve_narrow_vq(env, vq); - } - env->vfp.zcr_el[1] = vq - 1; - arm_rebuild_hflags(env); - ret = vq * 16; - } - return ret; - case TARGET_PR_SVE_GET_VL: - ret = -TARGET_EINVAL; - { - ARMCPU *cpu = env_archcpu(cpu_env); - if (cpu_isar_feature(aa64_sve, cpu)) { - ret = ((cpu->env.vfp.zcr_el[1] & 0xf) + 1) * 16; - } - } - return ret; - case TARGET_PR_PAC_RESET_KEYS: - { - CPUARMState *env = cpu_env; - ARMCPU *cpu = env_archcpu(env); - - if (arg3 || arg4 || arg5) { - return -TARGET_EINVAL; - } - if (cpu_isar_feature(aa64_pauth, cpu)) { - int all = (TARGET_PR_PAC_APIAKEY | TARGET_PR_PAC_APIBKEY | - TARGET_PR_PAC_APDAKEY | TARGET_PR_PAC_APDBKEY | - TARGET_PR_PAC_APGAKEY); - int ret = 0; - Error *err = NULL; - - if (arg2 == 0) { - arg2 = all; - } else if (arg2 & ~all) { - return -TARGET_EINVAL; - } - if (arg2 & TARGET_PR_PAC_APIAKEY) { - ret |= qemu_guest_getrandom(&env->keys.apia, - sizeof(ARMPACKey), &err); - } - if (arg2 & TARGET_PR_PAC_APIBKEY) { - ret |= qemu_guest_getrandom(&env->keys.apib, - sizeof(ARMPACKey), &err); - } - if (arg2 & TARGET_PR_PAC_APDAKEY) { - ret |= qemu_guest_getrandom(&env->keys.apda, - sizeof(ARMPACKey), &err); - } - if (arg2 & TARGET_PR_PAC_APDBKEY) { - ret |= qemu_guest_getrandom(&env->keys.apdb, - sizeof(ARMPACKey), &err); - } - if (arg2 & TARGET_PR_PAC_APGAKEY) { - ret |= qemu_guest_getrandom(&env->keys.apga, - sizeof(ARMPACKey), &err); - } - if (ret != 0) { - /* - * Some unknown failure in the crypto. The best - * we can do is log it and fail the syscall. - * The real syscall cannot fail this way. - */ - qemu_log_mask(LOG_UNIMP, - "PR_PAC_RESET_KEYS: Crypto failure: %s", - error_get_pretty(err)); - error_free(err); - return -TARGET_EIO; - } - return 0; - } - } - return -TARGET_EINVAL; - case TARGET_PR_SET_TAGGED_ADDR_CTRL: - { - abi_ulong valid_mask = TARGET_PR_TAGGED_ADDR_ENABLE; - CPUARMState *env = cpu_env; - ARMCPU *cpu = env_archcpu(env); - - if (cpu_isar_feature(aa64_mte, cpu)) { - valid_mask |= TARGET_PR_MTE_TCF_MASK; - valid_mask |= TARGET_PR_MTE_TAG_MASK; - } - - if ((arg2 & ~valid_mask) || arg3 || arg4 || arg5) { - return -TARGET_EINVAL; - } - env->tagged_addr_enable = arg2 & TARGET_PR_TAGGED_ADDR_ENABLE; - - if (cpu_isar_feature(aa64_mte, cpu)) { - switch (arg2 & TARGET_PR_MTE_TCF_MASK) { - case TARGET_PR_MTE_TCF_NONE: - case TARGET_PR_MTE_TCF_SYNC: - case TARGET_PR_MTE_TCF_ASYNC: - break; - default: - return -EINVAL; - } - - /* - * Write PR_MTE_TCF to SCTLR_EL1[TCF0]. - * Note that the syscall values are consistent with hw. - */ - env->cp15.sctlr_el[1] = - deposit64(env->cp15.sctlr_el[1], 38, 2, - arg2 >> TARGET_PR_MTE_TCF_SHIFT); - - /* - * Write PR_MTE_TAG to GCR_EL1[Exclude]. - * Note that the syscall uses an include mask, - * and hardware uses an exclude mask -- invert. - */ - env->cp15.gcr_el1 = - deposit64(env->cp15.gcr_el1, 0, 16, - ~arg2 >> TARGET_PR_MTE_TAG_SHIFT); - arm_rebuild_hflags(env); - } - return 0; - } - case TARGET_PR_GET_TAGGED_ADDR_CTRL: - { - abi_long ret = 0; - CPUARMState *env = cpu_env; - ARMCPU *cpu = env_archcpu(env); - - if (arg2 || arg3 || arg4 || arg5) { - return -TARGET_EINVAL; - } - if (env->tagged_addr_enable) { - ret |= TARGET_PR_TAGGED_ADDR_ENABLE; - } - if (cpu_isar_feature(aa64_mte, cpu)) { - /* See above. */ - ret |= (extract64(env->cp15.sctlr_el[1], 38, 2) - << TARGET_PR_MTE_TCF_SHIFT); - ret = deposit64(ret, TARGET_PR_MTE_TAG_SHIFT, 16, - ~env->cp15.gcr_el1); - } - return ret; - } -#endif /* AARCH64 */ - case PR_GET_SECCOMP: - case PR_SET_SECCOMP: - /* Disable seccomp to prevent the target disabling syscalls we - * need. */ - return -TARGET_EINVAL; - default: - /* Most prctl options have no pointer arguments */ - return get_errno(prctl(arg1, arg2, arg3, arg4, arg5)); - } + return do_prctl(cpu_env, arg1, arg2, arg3, arg4, arg5); break; #ifdef TARGET_NR_arch_prctl case TARGET_NR_arch_prctl: diff --git a/linux-user/x86_64/target_prctl.h b/linux-user/x86_64/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/x86_64/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/xtensa/target_prctl.h b/linux-user/xtensa/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/xtensa/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ From 220717a6f46a99031a5b1af964bbf4dec1310440 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 27 Dec 2021 07:01:23 -0800 Subject: [PATCH 190/730] linux-user: Disable more prctl subcodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create a list of subcodes that we want to pass on, a list of subcodes that should not be passed on because they would affect the running qemu itself, and a list that probably could be implemented but require extra work. Do not pass on unknown subcodes. Reviewed-by: Laurent Vivier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-Id: <20211227150127.2659293-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 58 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 0f0f67d567..d868ef2910 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6337,6 +6337,13 @@ abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) # define PR_MTE_TAG_SHIFT 3 # define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT) #endif +#ifndef PR_SET_IO_FLUSHER +# define PR_SET_IO_FLUSHER 57 +# define PR_GET_IO_FLUSHER 58 +#endif +#ifndef PR_SET_SYSCALL_USER_DISPATCH +# define PR_SET_SYSCALL_USER_DISPATCH 59 +#endif #include "target_prctl.h" @@ -6433,13 +6440,58 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, return -TARGET_EINVAL; } return do_prctl_get_tagged_addr_ctrl(env); + + case PR_GET_DUMPABLE: + case PR_SET_DUMPABLE: + case PR_GET_KEEPCAPS: + case PR_SET_KEEPCAPS: + case PR_GET_TIMING: + case PR_SET_TIMING: + case PR_GET_TIMERSLACK: + case PR_SET_TIMERSLACK: + case PR_MCE_KILL: + case PR_MCE_KILL_GET: + case PR_GET_NO_NEW_PRIVS: + case PR_SET_NO_NEW_PRIVS: + case PR_GET_IO_FLUSHER: + case PR_SET_IO_FLUSHER: + /* Some prctl options have no pointer arguments and we can pass on. */ + return get_errno(prctl(option, arg2, arg3, arg4, arg5)); + + case PR_GET_CHILD_SUBREAPER: + case PR_SET_CHILD_SUBREAPER: + case PR_GET_SPECULATION_CTRL: + case PR_SET_SPECULATION_CTRL: + case PR_GET_TID_ADDRESS: + /* TODO */ + return -TARGET_EINVAL; + + case PR_GET_FPEXC: + case PR_SET_FPEXC: + /* Was used for SPE on PowerPC. */ + return -TARGET_EINVAL; + + case PR_GET_ENDIAN: + case PR_SET_ENDIAN: + case PR_GET_FPEMU: + case PR_SET_FPEMU: + case PR_SET_MM: case PR_GET_SECCOMP: case PR_SET_SECCOMP: - /* Disable seccomp to prevent the target disabling syscalls we need. */ + case PR_SET_SYSCALL_USER_DISPATCH: + case PR_GET_THP_DISABLE: + case PR_SET_THP_DISABLE: + case PR_GET_TSC: + case PR_SET_TSC: + case PR_GET_UNALIGN: + case PR_SET_UNALIGN: + /* Disable to prevent the target disabling stuff we need. */ return -TARGET_EINVAL; + default: - /* Most prctl options have no pointer arguments */ - return get_errno(prctl(option, arg2, arg3, arg4, arg5)); + qemu_log_mask(LOG_UNIMP, "Unsupported prctl: " TARGET_ABI_FMT_ld "\n", + option); + return -TARGET_EINVAL; } } From 6e8dcacd0840b3c38e7ec664bb9adbccc2108fdd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 27 Dec 2021 07:01:24 -0800 Subject: [PATCH 191/730] linux-user: Add code for PR_GET/SET_UNALIGN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This requires extra work for each target, but adds the common syscall code, and the necessary flag in CPUState. Reviewed-by: Warner Losh Reviewed-by: Laurent Vivier Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-Id: <20211227150127.2659293-4-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- cpu.c | 20 ++++++++++++----- include/hw/core/cpu.h | 3 +++ linux-user/generic/target_prctl_unalign.h | 27 +++++++++++++++++++++++ linux-user/syscall.c | 13 +++++++++-- 4 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 linux-user/generic/target_prctl_unalign.h diff --git a/cpu.c b/cpu.c index 945dd3dded..016bf06a1a 100644 --- a/cpu.c +++ b/cpu.c @@ -174,13 +174,23 @@ void cpu_exec_unrealizefn(CPUState *cpu) cpu_list_remove(cpu); } +/* + * This can't go in hw/core/cpu.c because that file is compiled only + * once for both user-mode and system builds. + */ static Property cpu_common_props[] = { -#ifndef CONFIG_USER_ONLY +#ifdef CONFIG_USER_ONLY /* - * Create a memory property for softmmu CPU object, - * so users can wire up its memory. (This can't go in hw/core/cpu.c - * because that file is compiled only once for both user-mode - * and system builds.) The default if no link is set up is to use + * Create a property for the user-only object, so users can + * adjust prctl(PR_SET_UNALIGN) from the command-line. + * Has no effect if the target does not support the feature. + */ + DEFINE_PROP_BOOL("prctl-unalign-sigbus", CPUState, + prctl_unalign_sigbus, false), +#else + /* + * Create a memory property for softmmu CPU object, so users can + * wire up its memory. The default if no link is set up is to use * the system address space. */ DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION, diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index e948e81f1a..76ab3b851c 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -413,6 +413,9 @@ struct CPUState { bool ignore_memory_transaction_failures; + /* Used for user-only emulation of prctl(PR_SET_UNALIGN). */ + bool prctl_unalign_sigbus; + struct hax_vcpu_state *hax_vcpu; struct hvf_vcpu_state *hvf; diff --git a/linux-user/generic/target_prctl_unalign.h b/linux-user/generic/target_prctl_unalign.h new file mode 100644 index 0000000000..bc3b83af2a --- /dev/null +++ b/linux-user/generic/target_prctl_unalign.h @@ -0,0 +1,27 @@ +/* + * Generic prctl unalign functions for linux-user + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef GENERIC_TARGET_PRCTL_UNALIGN_H +#define GENERIC_TARGET_PRCTL_UNALIGN_H + +static abi_long do_prctl_get_unalign(CPUArchState *env, target_long arg2) +{ + CPUState *cs = env_cpu(env); + uint32_t res = PR_UNALIGN_NOPRINT; + if (cs->prctl_unalign_sigbus) { + res |= PR_UNALIGN_SIGBUS; + } + return put_user_u32(res, arg2); +} +#define do_prctl_get_unalign do_prctl_get_unalign + +static abi_long do_prctl_set_unalign(CPUArchState *env, target_long arg2) +{ + env_cpu(env)->prctl_unalign_sigbus = arg2 & PR_UNALIGN_SIGBUS; + return 0; +} +#define do_prctl_set_unalign do_prctl_set_unalign + +#endif /* GENERIC_TARGET_PRCTL_UNALIGN_H */ diff --git a/linux-user/syscall.c b/linux-user/syscall.c index d868ef2910..b5112891b0 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6378,6 +6378,12 @@ static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2) #ifndef do_prctl_get_tagged_addr_ctrl #define do_prctl_get_tagged_addr_ctrl do_prctl_inval0 #endif +#ifndef do_prctl_get_unalign +#define do_prctl_get_unalign do_prctl_inval1 +#endif +#ifndef do_prctl_set_unalign +#define do_prctl_set_unalign do_prctl_inval1 +#endif static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) @@ -6441,6 +6447,11 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, } return do_prctl_get_tagged_addr_ctrl(env); + case PR_GET_UNALIGN: + return do_prctl_get_unalign(env, arg2); + case PR_SET_UNALIGN: + return do_prctl_set_unalign(env, arg2); + case PR_GET_DUMPABLE: case PR_SET_DUMPABLE: case PR_GET_KEEPCAPS: @@ -6483,8 +6494,6 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, case PR_SET_THP_DISABLE: case PR_GET_TSC: case PR_SET_TSC: - case PR_GET_UNALIGN: - case PR_SET_UNALIGN: /* Disable to prevent the target disabling stuff we need. */ return -TARGET_EINVAL; From fed142461780f714e83123833a8d9682c32f68ee Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 27 Dec 2021 07:01:25 -0800 Subject: [PATCH 192/730] target/alpha: Implement prctl_unalign_sigbus Leave TARGET_ALIGNED_ONLY set, but use the new CPUState flag to set MO_UNALN for the instructions that the kernel handles in the unaligned trap. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20211227150127.2659293-5-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/alpha/target_prctl.h | 2 +- target/alpha/cpu.h | 5 +++++ target/alpha/translate.c | 31 ++++++++++++++++++++++--------- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/linux-user/alpha/target_prctl.h b/linux-user/alpha/target_prctl.h index eb53b31ad5..5629ddbf39 100644 --- a/linux-user/alpha/target_prctl.h +++ b/linux-user/alpha/target_prctl.h @@ -1 +1 @@ -/* No special prctl support required. */ +#include "../generic/target_prctl_unalign.h" diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h index afd975c878..e819211503 100644 --- a/target/alpha/cpu.h +++ b/target/alpha/cpu.h @@ -383,6 +383,8 @@ enum { #define ENV_FLAG_TB_MASK \ (ENV_FLAG_PAL_MODE | ENV_FLAG_PS_USER | ENV_FLAG_FEN) +#define TB_FLAG_UNALIGN (1u << 1) + static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch) { int ret = env->flags & ENV_FLAG_PS_USER ? MMU_USER_IDX : MMU_KERNEL_IDX; @@ -470,6 +472,9 @@ static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc, *pc = env->pc; *cs_base = 0; *pflags = env->flags & ENV_FLAG_TB_MASK; +#ifdef CONFIG_USER_ONLY + *pflags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus; +#endif } #ifdef CONFIG_USER_ONLY diff --git a/target/alpha/translate.c b/target/alpha/translate.c index a4c3f43e72..208ae5fbd5 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -45,7 +45,9 @@ typedef struct DisasContext DisasContext; struct DisasContext { DisasContextBase base; -#ifndef CONFIG_USER_ONLY +#ifdef CONFIG_USER_ONLY + MemOp unalign; +#else uint64_t palbr; #endif uint32_t tbflags; @@ -68,6 +70,12 @@ struct DisasContext { TCGv sink; }; +#ifdef CONFIG_USER_ONLY +#define UNALIGN(C) (C)->unalign +#else +#define UNALIGN(C) 0 +#endif + /* Target-specific return values from translate_one, indicating the state of the TB. Note that DISAS_NEXT indicates that we are not exiting the TB. */ @@ -270,7 +278,7 @@ static inline DisasJumpType gen_invalid(DisasContext *ctx) static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr) { TCGv_i32 tmp32 = tcg_temp_new_i32(); - tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL); + tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx)); gen_helper_memory_to_f(dest, tmp32); tcg_temp_free_i32(tmp32); } @@ -278,7 +286,7 @@ static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr) static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr) { TCGv tmp = tcg_temp_new(); - tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEQ); + tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx)); gen_helper_memory_to_g(dest, tmp); tcg_temp_free(tmp); } @@ -286,14 +294,14 @@ static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr) static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr) { TCGv_i32 tmp32 = tcg_temp_new_i32(); - tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL); + tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx)); gen_helper_memory_to_s(dest, tmp32); tcg_temp_free_i32(tmp32); } static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr) { - tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEQ); + tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx)); } static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16, @@ -324,6 +332,8 @@ static void gen_load_int(DisasContext *ctx, int ra, int rb, int32_t disp16, tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16); if (clear) { tcg_gen_andi_i64(addr, addr, ~0x7); + } else if (!locked) { + op |= UNALIGN(ctx); } dest = ctx->ir[ra]; @@ -340,7 +350,7 @@ static void gen_stf(DisasContext *ctx, TCGv src, TCGv addr) { TCGv_i32 tmp32 = tcg_temp_new_i32(); gen_helper_f_to_memory(tmp32, addr); - tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL); + tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx)); tcg_temp_free_i32(tmp32); } @@ -348,7 +358,7 @@ static void gen_stg(DisasContext *ctx, TCGv src, TCGv addr) { TCGv tmp = tcg_temp_new(); gen_helper_g_to_memory(tmp, src); - tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEQ); + tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx)); tcg_temp_free(tmp); } @@ -356,13 +366,13 @@ static void gen_sts(DisasContext *ctx, TCGv src, TCGv addr) { TCGv_i32 tmp32 = tcg_temp_new_i32(); gen_helper_s_to_memory(tmp32, src); - tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL); + tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx)); tcg_temp_free_i32(tmp32); } static void gen_stt(DisasContext *ctx, TCGv src, TCGv addr) { - tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEQ); + tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx)); } static void gen_store_fp(DisasContext *ctx, int ra, int rb, int32_t disp16, @@ -383,6 +393,8 @@ static void gen_store_int(DisasContext *ctx, int ra, int rb, int32_t disp16, tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16); if (clear) { tcg_gen_andi_i64(addr, addr, ~0x7); + } else { + op |= UNALIGN(ctx); } src = load_gpr(ctx, ra); @@ -2942,6 +2954,7 @@ static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu) #ifdef CONFIG_USER_ONLY ctx->ir = cpu_std_ir; + ctx->unalign = (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN); #else ctx->palbr = env->palbr; ctx->ir = (ctx->tbflags & ENV_FLAG_PAL_MODE ? cpu_pal_ir : cpu_std_ir); From 217d1a5ef887c2013dc7446adff856e795cd8488 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 27 Dec 2021 07:01:26 -0800 Subject: [PATCH 193/730] target/hppa: Implement prctl_unalign_sigbus Leave TARGET_ALIGNED_ONLY set, but use the new CPUState flag to set MO_UNALN for the instructions that the kernel handles in the unaligned trap. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20211227150127.2659293-6-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/hppa/target_prctl.h | 2 +- target/hppa/cpu.h | 5 ++++- target/hppa/translate.c | 19 +++++++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/linux-user/hppa/target_prctl.h b/linux-user/hppa/target_prctl.h index eb53b31ad5..5629ddbf39 100644 --- a/linux-user/hppa/target_prctl.h +++ b/linux-user/hppa/target_prctl.h @@ -1 +1 @@ -/* No special prctl support required. */ +#include "../generic/target_prctl_unalign.h" diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 294fd7297f..45fd338b02 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -259,12 +259,14 @@ static inline target_ulong hppa_form_gva(CPUHPPAState *env, uint64_t spc, return hppa_form_gva_psw(env->psw, spc, off); } -/* Since PSW_{I,CB} will never need to be in tb->flags, reuse them. +/* + * Since PSW_{I,CB} will never need to be in tb->flags, reuse them. * TB_FLAG_SR_SAME indicates that SR4 through SR7 all contain the * same value. */ #define TB_FLAG_SR_SAME PSW_I #define TB_FLAG_PRIV_SHIFT 8 +#define TB_FLAG_UNALIGN 0x400 static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc, target_ulong *cs_base, @@ -279,6 +281,7 @@ static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc, #ifdef CONFIG_USER_ONLY *pc = env->iaoq_f & -4; *cs_base = env->iaoq_b & -4; + flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus; #else /* ??? E, T, H, L, B, P bits need to be here, when implemented. */ flags |= env->psw & (PSW_W | PSW_C | PSW_D); diff --git a/target/hppa/translate.c b/target/hppa/translate.c index 952027a28e..a2392a1b64 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -274,8 +274,18 @@ typedef struct DisasContext { int mmu_idx; int privilege; bool psw_n_nonzero; + +#ifdef CONFIG_USER_ONLY + MemOp unalign; +#endif } DisasContext; +#ifdef CONFIG_USER_ONLY +#define UNALIGN(C) (C)->unalign +#else +#define UNALIGN(C) 0 +#endif + /* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */ static int expand_sm_imm(DisasContext *ctx, int val) { @@ -1475,7 +1485,7 @@ static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb, form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify, ctx->mmu_idx == MMU_PHYS_IDX); - tcg_gen_qemu_ld_reg(dest, addr, ctx->mmu_idx, mop); + tcg_gen_qemu_ld_reg(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx)); if (modify) { save_gpr(ctx, rb, ofs); } @@ -1493,7 +1503,7 @@ static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb, form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify, ctx->mmu_idx == MMU_PHYS_IDX); - tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop); + tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx)); if (modify) { save_gpr(ctx, rb, ofs); } @@ -1511,7 +1521,7 @@ static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb, form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify, ctx->mmu_idx == MMU_PHYS_IDX); - tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop); + tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx)); if (modify) { save_gpr(ctx, rb, ofs); } @@ -1529,7 +1539,7 @@ static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb, form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify, ctx->mmu_idx == MMU_PHYS_IDX); - tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop); + tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx)); if (modify) { save_gpr(ctx, rb, ofs); } @@ -4107,6 +4117,7 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->mmu_idx = MMU_USER_IDX; ctx->iaoq_f = ctx->base.pc_first | MMU_USER_IDX; ctx->iaoq_b = ctx->base.tb->cs_base | MMU_USER_IDX; + ctx->unalign = (ctx->tb_flags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN); #else ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3; ctx->mmu_idx = (ctx->tb_flags & PSW_D ? ctx->privilege : MMU_PHYS_IDX); From 4da06fb306276946e227669bfc4df2077a8fa6c9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 27 Dec 2021 07:01:27 -0800 Subject: [PATCH 194/730] target/sh4: Implement prctl_unalign_sigbus Leave TARGET_ALIGNED_ONLY set, but use the new CPUState flag to set MO_UNALN for the instructions that the kernel handles in the unaligned trap. The Linux kernel does not handle all memory operations: no floating-point and no MAC. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20211227150127.2659293-7-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sh4/target_prctl.h | 2 +- target/sh4/cpu.h | 4 +++ target/sh4/translate.c | 50 ++++++++++++++++++++++++----------- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/linux-user/sh4/target_prctl.h b/linux-user/sh4/target_prctl.h index eb53b31ad5..5629ddbf39 100644 --- a/linux-user/sh4/target_prctl.h +++ b/linux-user/sh4/target_prctl.h @@ -1 +1 @@ -/* No special prctl support required. */ +#include "../generic/target_prctl_unalign.h" diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h index 4cfb109f56..fb9dd9db2f 100644 --- a/target/sh4/cpu.h +++ b/target/sh4/cpu.h @@ -83,6 +83,7 @@ #define DELAY_SLOT_RTE (1 << 2) #define TB_FLAG_PENDING_MOVCA (1 << 3) +#define TB_FLAG_UNALIGN (1 << 4) #define GUSA_SHIFT 4 #ifdef CONFIG_USER_ONLY @@ -373,6 +374,9 @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc, | (env->sr & ((1u << SR_MD) | (1u << SR_RB))) /* Bits 29-30 */ | (env->sr & (1u << SR_FD)) /* Bit 15 */ | (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 3 */ +#ifdef CONFIG_USER_ONLY + *flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus; +#endif } #endif /* SH4_CPU_H */ diff --git a/target/sh4/translate.c b/target/sh4/translate.c index ce5d674a52..50493c61ea 100644 --- a/target/sh4/translate.c +++ b/target/sh4/translate.c @@ -50,8 +50,10 @@ typedef struct DisasContext { #if defined(CONFIG_USER_ONLY) #define IS_USER(ctx) 1 +#define UNALIGN(C) (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN) #else #define IS_USER(ctx) (!(ctx->tbflags & (1u << SR_MD))) +#define UNALIGN(C) 0 #endif /* Target-specific values for ctx->base.is_jmp. */ @@ -495,7 +497,8 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new(); tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4); - tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL); + tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, + MO_TEUL | UNALIGN(ctx)); tcg_temp_free(addr); } return; @@ -503,7 +506,8 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new(); tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4); - tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL); + tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, + MO_TESL | UNALIGN(ctx)); tcg_temp_free(addr); } return; @@ -558,19 +562,23 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB); return; case 0x2001: /* mov.w Rm,@Rn */ - tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUW); + tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, + MO_TEUW | UNALIGN(ctx)); return; case 0x2002: /* mov.l Rm,@Rn */ - tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL); + tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, + MO_TEUL | UNALIGN(ctx)); return; case 0x6000: /* mov.b @Rm,Rn */ tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB); return; case 0x6001: /* mov.w @Rm,Rn */ - tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW); + tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, + MO_TESW | UNALIGN(ctx)); return; case 0x6002: /* mov.l @Rm,Rn */ - tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL); + tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, + MO_TESL | UNALIGN(ctx)); return; case 0x2004: /* mov.b Rm,@-Rn */ { @@ -586,7 +594,8 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new(); tcg_gen_subi_i32(addr, REG(B11_8), 2); - tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW); + tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, + MO_TEUW | UNALIGN(ctx)); tcg_gen_mov_i32(REG(B11_8), addr); tcg_temp_free(addr); } @@ -595,7 +604,8 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new(); tcg_gen_subi_i32(addr, REG(B11_8), 4); - tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL); + tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, + MO_TEUL | UNALIGN(ctx)); tcg_gen_mov_i32(REG(B11_8), addr); tcg_temp_free(addr); } @@ -606,12 +616,14 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1); return; case 0x6005: /* mov.w @Rm+,Rn */ - tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW); + tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, + MO_TESW | UNALIGN(ctx)); if ( B11_8 != B7_4 ) tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2); return; case 0x6006: /* mov.l @Rm+,Rn */ - tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL); + tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, + MO_TESL | UNALIGN(ctx)); if ( B11_8 != B7_4 ) tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4); return; @@ -627,7 +639,8 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new(); tcg_gen_add_i32(addr, REG(B11_8), REG(0)); - tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW); + tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, + MO_TEUW | UNALIGN(ctx)); tcg_temp_free(addr); } return; @@ -635,7 +648,8 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new(); tcg_gen_add_i32(addr, REG(B11_8), REG(0)); - tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL); + tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, + MO_TEUL | UNALIGN(ctx)); tcg_temp_free(addr); } return; @@ -651,7 +665,8 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new(); tcg_gen_add_i32(addr, REG(B7_4), REG(0)); - tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW); + tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, + MO_TESW | UNALIGN(ctx)); tcg_temp_free(addr); } return; @@ -659,7 +674,8 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new(); tcg_gen_add_i32(addr, REG(B7_4), REG(0)); - tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL); + tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, + MO_TESL | UNALIGN(ctx)); tcg_temp_free(addr); } return; @@ -1253,7 +1269,8 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new(); tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2); - tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW); + tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, + MO_TEUW | UNALIGN(ctx)); tcg_temp_free(addr); } return; @@ -1269,7 +1286,8 @@ static void _decode_opc(DisasContext * ctx) { TCGv addr = tcg_temp_new(); tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2); - tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW); + tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, + MO_TESW | UNALIGN(ctx)); tcg_temp_free(addr); } return; From 139e5de7c883522b7307e26d4b7dce489b53e307 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 23 Oct 2021 21:59:10 +0200 Subject: [PATCH 195/730] linux-user/signal: Map exit signals in SIGCHLD siginfo_t When converting a siginfo_t from waitid(), the interpretation of si_status depends on the value of si_code: For CLD_EXITED, it is an exit code and should be copied verbatim. For other codes, it is a signal number (possibly with additional high bits from ptrace) that should be mapped. This code was previously changed in commit 1c3dfb506ea3 ("linux-user/signal: Decode waitid si_code"), but the fix was incomplete. Tested with the following test program: #include #include #include #include int main() { pid_t pid = fork(); if (pid == 0) { exit(12); } else { siginfo_t siginfo = {}; waitid(P_PID, pid, &siginfo, WEXITED); printf("Code: %d, status: %d\n", (int)siginfo.si_code, (int)siginfo.si_status); } pid = fork(); if (pid == 0) { raise(SIGUSR2); } else { siginfo_t siginfo = {}; waitid(P_PID, pid, &siginfo, WEXITED); printf("Code: %d, status: %d\n", (int)siginfo.si_code, (int)siginfo.si_status); } } Output with an x86_64 host and mips64el target before 1c3dfb506ea3 (incorrect: exit code 12 is translated like a signal): Code: 1, status: 17 Code: 2, status: 17 After 1c3dfb506ea3 (incorrect: signal number is not translated): Code: 1, status: 12 Code: 2, status: 12 With this patch: Code: 1, status: 12 Code: 2, status: 17 Signed-off-by: Matthias Schiffer Reviewed-by: Laurent Vivier Message-Id: <81534fde7cdfc6acea4889d886fbefdd606630fb.1635019124.git.mschiffer@universe-factory.net> Signed-off-by: Laurent Vivier --- linux-user/signal.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index 510db73c34..1229fecf5c 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -406,7 +406,12 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, case TARGET_SIGCHLD: tinfo->_sifields._sigchld._pid = info->si_pid; tinfo->_sifields._sigchld._uid = info->si_uid; - tinfo->_sifields._sigchld._status = info->si_status; + if (si_code == CLD_EXITED) + tinfo->_sifields._sigchld._status = info->si_status; + else + tinfo->_sifields._sigchld._status + = host_to_target_signal(info->si_status & 0x7f) + | (info->si_status & ~0x7f); tinfo->_sifields._sigchld._utime = info->si_utime; tinfo->_sifields._sigchld._stime = info->si_stime; si_type = QEMU_SI_CHLD; From 45ad761c27dfb571d9a1ab3af80e8034d36d1b59 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Tue, 4 Jan 2022 20:18:18 -0800 Subject: [PATCH 196/730] linux-user: add sched_getattr support These syscalls are not exposed by glibc. The struct type need to be redefined as it can't be included directly before https://lkml.org/lkml/2020/5/28/810 . sched_attr type can grow in future kernel versions. When client sends values that QEMU does not understand it will return E2BIG with same semantics as old kernel would so client can retry with smaller inputs. Signed-off-by: Tonis Tiigi Message-Id: <20220105041819.24160-2-tonistiigi@gmail.com> Reviewed-by: Laurent Vivier Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 123 ++++++++++++++++++++++++++++++++++++++ linux-user/syscall_defs.h | 14 +++++ 2 files changed, 137 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b5112891b0..6de116eb90 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -340,6 +340,25 @@ _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len, #define __NR_sys_sched_setaffinity __NR_sched_setaffinity _syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len, unsigned long *, user_mask_ptr); +/* sched_attr is not defined in glibc */ +struct sched_attr { + uint32_t size; + uint32_t sched_policy; + uint64_t sched_flags; + int32_t sched_nice; + uint32_t sched_priority; + uint64_t sched_runtime; + uint64_t sched_deadline; + uint64_t sched_period; + uint32_t sched_util_min; + uint32_t sched_util_max; +}; +#define __NR_sys_sched_getattr __NR_sched_getattr +_syscall4(int, sys_sched_getattr, pid_t, pid, struct sched_attr *, attr, + unsigned int, size, unsigned int, flags); +#define __NR_sys_sched_setattr __NR_sched_setattr +_syscall3(int, sys_sched_setattr, pid_t, pid, struct sched_attr *, attr, + unsigned int, flags); #define __NR_sys_getcpu __NR_getcpu _syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache); _syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd, @@ -558,6 +577,24 @@ const char *target_strerror(int err) return strerror(target_to_host_errno(err)); } +static int check_zeroed_user(abi_long addr, size_t ksize, size_t usize) +{ + int i; + uint8_t b; + if (usize <= ksize) { + return 1; + } + for (i = ksize; i < usize; i++) { + if (get_user_u8(b, addr + i)) { + return -TARGET_EFAULT; + } + if (b != 0) { + return 0; + } + } + return 1; +} + #define safe_syscall0(type, name) \ static type safe_##name(void) \ { \ @@ -10801,6 +10838,92 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } case TARGET_NR_sched_getscheduler: return get_errno(sched_getscheduler(arg1)); + case TARGET_NR_sched_getattr: + { + struct target_sched_attr *target_scha; + struct sched_attr scha; + if (arg2 == 0) { + return -TARGET_EINVAL; + } + if (arg3 > sizeof(scha)) { + arg3 = sizeof(scha); + } + ret = get_errno(sys_sched_getattr(arg1, &scha, arg3, arg4)); + if (!is_error(ret)) { + target_scha = lock_user(VERIFY_WRITE, arg2, arg3, 0); + if (!target_scha) { + return -TARGET_EFAULT; + } + target_scha->size = tswap32(scha.size); + target_scha->sched_policy = tswap32(scha.sched_policy); + target_scha->sched_flags = tswap64(scha.sched_flags); + target_scha->sched_nice = tswap32(scha.sched_nice); + target_scha->sched_priority = tswap32(scha.sched_priority); + target_scha->sched_runtime = tswap64(scha.sched_runtime); + target_scha->sched_deadline = tswap64(scha.sched_deadline); + target_scha->sched_period = tswap64(scha.sched_period); + if (scha.size > offsetof(struct sched_attr, sched_util_min)) { + target_scha->sched_util_min = tswap32(scha.sched_util_min); + target_scha->sched_util_max = tswap32(scha.sched_util_max); + } + unlock_user(target_scha, arg2, arg3); + } + return ret; + } + case TARGET_NR_sched_setattr: + { + struct target_sched_attr *target_scha; + struct sched_attr scha; + uint32_t size; + int zeroed; + if (arg2 == 0) { + return -TARGET_EINVAL; + } + if (get_user_u32(size, arg2)) { + return -TARGET_EFAULT; + } + if (!size) { + size = offsetof(struct target_sched_attr, sched_util_min); + } + if (size < offsetof(struct target_sched_attr, sched_util_min)) { + if (put_user_u32(sizeof(struct target_sched_attr), arg2)) { + return -TARGET_EFAULT; + } + return -TARGET_E2BIG; + } + + zeroed = check_zeroed_user(arg2, sizeof(struct target_sched_attr), size); + if (zeroed < 0) { + return zeroed; + } else if (zeroed == 0) { + if (put_user_u32(sizeof(struct target_sched_attr), arg2)) { + return -TARGET_EFAULT; + } + return -TARGET_E2BIG; + } + if (size > sizeof(struct target_sched_attr)) { + size = sizeof(struct target_sched_attr); + } + + target_scha = lock_user(VERIFY_READ, arg2, size, 1); + if (!target_scha) { + return -TARGET_EFAULT; + } + scha.size = size; + scha.sched_policy = tswap32(target_scha->sched_policy); + scha.sched_flags = tswap64(target_scha->sched_flags); + scha.sched_nice = tswap32(target_scha->sched_nice); + scha.sched_priority = tswap32(target_scha->sched_priority); + scha.sched_runtime = tswap64(target_scha->sched_runtime); + scha.sched_deadline = tswap64(target_scha->sched_deadline); + scha.sched_period = tswap64(target_scha->sched_period); + if (size > offsetof(struct target_sched_attr, sched_util_min)) { + scha.sched_util_min = tswap32(target_scha->sched_util_min); + scha.sched_util_max = tswap32(target_scha->sched_util_max); + } + unlock_user(target_scha, arg2, 0); + return get_errno(sys_sched_setattr(arg1, &scha, arg3)); + } case TARGET_NR_sched_yield: return get_errno(sched_yield()); case TARGET_NR_sched_get_priority_max: diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 585e933140..66244589aa 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2890,4 +2890,18 @@ struct target_statx { /* 0x100 */ }; +/* from kernel's include/linux/sched/types.h */ +struct target_sched_attr { + abi_uint size; + abi_uint sched_policy; + abi_ullong sched_flags; + abi_int sched_nice; + abi_uint sched_priority; + abi_ullong sched_runtime; + abi_ullong sched_deadline; + abi_ullong sched_period; + abi_uint sched_util_min; + abi_uint sched_util_max; +}; + #endif From 407a119bfd350101a8ef947a9edd58b01644ec89 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Tue, 4 Jan 2022 20:18:19 -0800 Subject: [PATCH 197/730] linux-user: call set/getscheduler set/getparam directly There seems to be difference in syscall and libc definition of these methods and therefore musl does not implement them (1e21e78bf7). Call syscall directly to ensure the behavior of the libc of user application, not the libc that was used to build QEMU. Signed-off-by: Tonis Tiigi Message-Id: <20220105041819.24160-3-tonistiigi@gmail.com> Reviewed-by: Laurent Vivier Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 34 ++++++++++++++++++++++++---------- linux-user/syscall_defs.h | 4 ++++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 6de116eb90..01cd59cdce 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -359,6 +359,17 @@ _syscall4(int, sys_sched_getattr, pid_t, pid, struct sched_attr *, attr, #define __NR_sys_sched_setattr __NR_sched_setattr _syscall3(int, sys_sched_setattr, pid_t, pid, struct sched_attr *, attr, unsigned int, flags); +#define __NR_sys_sched_getscheduler __NR_sched_getscheduler +_syscall1(int, sys_sched_getscheduler, pid_t, pid); +#define __NR_sys_sched_setscheduler __NR_sched_setscheduler +_syscall3(int, sys_sched_setscheduler, pid_t, pid, int, policy, + const struct sched_param *, param); +#define __NR_sys_sched_getparam __NR_sched_getparam +_syscall2(int, sys_sched_getparam, pid_t, pid, + struct sched_param *, param); +#define __NR_sys_sched_setparam __NR_sched_setparam +_syscall2(int, sys_sched_setparam, pid_t, pid, + const struct sched_param *, param); #define __NR_sys_getcpu __NR_getcpu _syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache); _syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd, @@ -10794,30 +10805,32 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; case TARGET_NR_sched_setparam: { - struct sched_param *target_schp; + struct target_sched_param *target_schp; struct sched_param schp; if (arg2 == 0) { return -TARGET_EINVAL; } - if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) + if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) { return -TARGET_EFAULT; + } schp.sched_priority = tswap32(target_schp->sched_priority); unlock_user_struct(target_schp, arg2, 0); - return get_errno(sched_setparam(arg1, &schp)); + return get_errno(sys_sched_setparam(arg1, &schp)); } case TARGET_NR_sched_getparam: { - struct sched_param *target_schp; + struct target_sched_param *target_schp; struct sched_param schp; if (arg2 == 0) { return -TARGET_EINVAL; } - ret = get_errno(sched_getparam(arg1, &schp)); + ret = get_errno(sys_sched_getparam(arg1, &schp)); if (!is_error(ret)) { - if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) + if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) { return -TARGET_EFAULT; + } target_schp->sched_priority = tswap32(schp.sched_priority); unlock_user_struct(target_schp, arg2, 1); } @@ -10825,19 +10838,20 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; case TARGET_NR_sched_setscheduler: { - struct sched_param *target_schp; + struct target_sched_param *target_schp; struct sched_param schp; if (arg3 == 0) { return -TARGET_EINVAL; } - if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) + if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) { return -TARGET_EFAULT; + } schp.sched_priority = tswap32(target_schp->sched_priority); unlock_user_struct(target_schp, arg3, 0); - return get_errno(sched_setscheduler(arg1, arg2, &schp)); + return get_errno(sys_sched_setscheduler(arg1, arg2, &schp)); } case TARGET_NR_sched_getscheduler: - return get_errno(sched_getscheduler(arg1)); + return get_errno(sys_sched_getscheduler(arg1)); case TARGET_NR_sched_getattr: { struct target_sched_attr *target_scha; diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 66244589aa..cca561f622 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2904,4 +2904,8 @@ struct target_sched_attr { abi_uint sched_util_max; }; +struct target_sched_param { + abi_int sched_priority; +}; + #endif From e13685a6e5c92612c6eeeb8a17c052539c0f9da5 Mon Sep 17 00:00:00 2001 From: Andrey Kazmin Date: Mon, 27 Dec 2021 15:50:48 +0300 Subject: [PATCH 198/730] linux-user/syscall.c: fix missed flag for shared memory in open_self_maps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The possible variants for region type in /proc/self/maps are either private "p" or shared "s". In the current implementation, we mark shared regions as "-". It could break memory mapping parsers such as included into ASan/HWASan sanitizers. Fixes: 01ef6b9e4e4e ("linux-user: factor out reading of /proc/self/maps") Signed-off-by: Andrey Kazmin Reviewed-by: Laurent Vivier Acked-by: Alex Bennée Message-Id: <20211227125048.22610-1-a.kazmin@partner.samsung.com> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 01cd59cdce..3160d77154 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8045,7 +8045,7 @@ static int open_self_maps(void *cpu_env, int fd) (flags & PAGE_READ) ? 'r' : '-', (flags & PAGE_WRITE_ORG) ? 'w' : '-', (flags & PAGE_EXEC) ? 'x' : '-', - e->is_priv ? 'p' : '-', + e->is_priv ? 'p' : 's', (uint64_t) e->offset, e->dev, e->inode); if (path) { dprintf(fd, "%*s%s\n", 73 - count, "", path); From 87d7bfdba1d4a963e9a89052c38a32327fa25473 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Dec 2021 18:50:06 -0800 Subject: [PATCH 199/730] linux-user/nios2: Properly emulate EXCP_TRAP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The real kernel has to load the instruction and extract the imm5 field; for qemu, modify the translator to do this. The use of R_AT for this in cpu_loop was a bug. Handle the other trap numbers as per the kernel's trap_table. Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20211221025012.1057923-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/nios2/cpu_loop.c | 40 ++++++++++++++++++++----------------- target/nios2/cpu.h | 2 +- target/nios2/translate.c | 17 +++++++++++++++- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c index 34290fb3b5..5c3d01d22d 100644 --- a/linux-user/nios2/cpu_loop.c +++ b/linux-user/nios2/cpu_loop.c @@ -26,7 +26,6 @@ void cpu_loop(CPUNios2State *env) { CPUState *cs = env_cpu(env); - Nios2CPU *cpu = NIOS2_CPU(cs); target_siginfo_t info; int trapnr, ret; @@ -39,9 +38,10 @@ void cpu_loop(CPUNios2State *env) case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; + case EXCP_TRAP: - if (env->regs[R_AT] == 0) { - abi_long ret; + switch (env->error_code) { + case 0: qemu_log_mask(CPU_LOG_INT, "\nSyscall\n"); ret = do_syscall(env, env->regs[2], @@ -55,26 +55,30 @@ void cpu_loop(CPUNios2State *env) env->regs[2] = abs(ret); /* Return value is 0..4096 */ - env->regs[7] = (ret > 0xfffffffffffff000ULL); - env->regs[CR_ESTATUS] = env->regs[CR_STATUS]; - env->regs[CR_STATUS] &= ~0x3; - env->regs[R_EA] = env->regs[R_PC] + 4; + env->regs[7] = ret > 0xfffff000u; env->regs[R_PC] += 4; break; - } else { - qemu_log_mask(CPU_LOG_INT, "\nTrap\n"); - env->regs[CR_ESTATUS] = env->regs[CR_STATUS]; - env->regs[CR_STATUS] &= ~0x3; - env->regs[R_EA] = env->regs[R_PC] + 4; - env->regs[R_PC] = cpu->exception_addr; - - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + case 1: + qemu_log_mask(CPU_LOG_INT, "\nTrap 1\n"); + force_sig_fault(TARGET_SIGUSR1, 0, env->regs[R_PC]); + break; + case 2: + qemu_log_mask(CPU_LOG_INT, "\nTrap 2\n"); + force_sig_fault(TARGET_SIGUSR2, 0, env->regs[R_PC]); + break; + case 31: + qemu_log_mask(CPU_LOG_INT, "\nTrap 31\n"); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->regs[R_PC]); + break; + default: + qemu_log_mask(CPU_LOG_INT, "\nTrap %d\n", env->error_code); + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP, + env->regs[R_PC]); break; } + break; + case EXCP_DEBUG: info.si_signo = TARGET_SIGTRAP; info.si_errno = 0; diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h index 1a69ed7a49..d2ba0c5bbd 100644 --- a/target/nios2/cpu.h +++ b/target/nios2/cpu.h @@ -160,9 +160,9 @@ struct CPUNios2State { #if !defined(CONFIG_USER_ONLY) Nios2MMU mmu; - uint32_t irq_pending; #endif + int error_code; }; /** diff --git a/target/nios2/translate.c b/target/nios2/translate.c index 08d7ac5398..a759877519 100644 --- a/target/nios2/translate.c +++ b/target/nios2/translate.c @@ -636,6 +636,21 @@ static void divu(DisasContext *dc, uint32_t code, uint32_t flags) tcg_temp_free(t0); } +static void trap(DisasContext *dc, uint32_t code, uint32_t flags) +{ +#ifdef CONFIG_USER_ONLY + /* + * The imm5 field is not stored anywhere on real hw; the kernel + * has to load the insn and extract the field. But we can make + * things easier for cpu_loop if we pop this into env->error_code. + */ + R_TYPE(instr, code); + tcg_gen_st_i32(tcg_constant_i32(instr.imm5), cpu_env, + offsetof(CPUNios2State, error_code)); +#endif + t_gen_helper_raise_exception(dc, EXCP_TRAP); +} + static const Nios2Instruction r_type_instructions[] = { INSTRUCTION_ILLEGAL(), INSTRUCTION(eret), /* eret */ @@ -682,7 +697,7 @@ static const Nios2Instruction r_type_instructions[] = { INSTRUCTION_ILLEGAL(), INSTRUCTION_ILLEGAL(), INSTRUCTION_ILLEGAL(), - INSTRUCTION_FLG(gen_excp, EXCP_TRAP), /* trap */ + INSTRUCTION(trap), /* trap */ INSTRUCTION(wrctl), /* wrctl */ INSTRUCTION_ILLEGAL(), INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LTU), /* cmpltu */ From 80c6e9d4aea4252c3201719299adde1d55ee539e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Dec 2021 18:50:07 -0800 Subject: [PATCH 200/730] linux-user/nios2: Fixes for signal frame setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not confuse host and guest addresses. Lock and unlock the target_rt_sigframe structure in setup_rt_sigframe. Since rt_setup_ucontext always returns 0, drop the return value entirely. This eliminates the only write to the err variable in setup_rt_sigframe. Always copy the siginfo structure. Reviewed-by: Alex Bennée Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20211221025012.1057923-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/nios2/signal.c | 49 ++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c index a77e8a40f4..adbffe32e3 100644 --- a/linux-user/nios2/signal.c +++ b/linux-user/nios2/signal.c @@ -42,7 +42,7 @@ struct target_rt_sigframe { struct target_ucontext uc; }; -static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env) +static void rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env) { unsigned long *gregs = uc->tuc_mcontext.gregs; @@ -75,8 +75,6 @@ static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env) __put_user(env->regs[R_GP], &gregs[25]); __put_user(env->regs[R_EA], &gregs[27]); __put_user(env->regs[R_SP], &gregs[28]); - - return 0; } static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc, @@ -135,8 +133,8 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc, return 0; } -static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env, - size_t frame_size) +static abi_ptr get_sigframe(struct target_sigaction *ka, CPUNios2State *env, + size_t frame_size) { unsigned long usp; @@ -144,7 +142,7 @@ static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env, usp = target_sigsp(get_sp_from_cpustate(env), ka); /* Verify, is it 32 or 64 bit aligned */ - return (void *)((usp - frame_size) & -8UL); + return (usp - frame_size) & -8; } void setup_rt_frame(int sig, struct target_sigaction *ka, @@ -153,26 +151,25 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, CPUNios2State *env) { struct target_rt_sigframe *frame; - int i, err = 0; + abi_ptr frame_addr; + int i; - frame = get_sigframe(ka, env, sizeof(*frame)); - - if (ka->sa_flags & SA_SIGINFO) { - tswap_siginfo(&frame->info, info); + frame_addr = get_sigframe(ka, env, sizeof(*frame)); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { + force_sigsegv(sig); + return; } + tswap_siginfo(&frame->info, info); + /* Create the ucontext. */ __put_user(0, &frame->uc.tuc_flags); __put_user(0, &frame->uc.tuc_link); target_save_altstack(&frame->uc.tuc_stack, env); - err |= rt_setup_ucontext(&frame->uc, env); + rt_setup_ucontext(&frame->uc, env); for (i = 0; i < TARGET_NSIG_WORDS; i++) { __put_user((abi_ulong)set->sig[i], - (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]); - } - - if (err) { - goto give_sigsegv; + (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]); } /* Set up to return from userspace; jump to fixed address sigreturn @@ -180,19 +177,13 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, env->regs[R_RA] = (unsigned long) (0x1044); /* Set up registers for signal handler */ - env->regs[R_SP] = (unsigned long) frame; - env->regs[4] = (unsigned long) sig; - env->regs[5] = (unsigned long) &frame->info; - env->regs[6] = (unsigned long) &frame->uc; - env->regs[R_EA] = (unsigned long) ka->_sa_handler; - return; + env->regs[R_SP] = frame_addr; + env->regs[4] = sig; + env->regs[5] = frame_addr + offsetof(struct target_rt_sigframe, info); + env->regs[6] = frame_addr + offsetof(struct target_rt_sigframe, uc); + env->regs[R_EA] = ka->_sa_handler; -give_sigsegv: - if (sig == TARGET_SIGSEGV) { - ka->_sa_handler = TARGET_SIG_DFL; - } - force_sigsegv(sig); - return; + unlock_user_struct(frame, frame_addr, 1); } long do_sigreturn(CPUNios2State *env) From 66346faf3200a0607a5498684e14e84c718dc233 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Dec 2021 18:50:08 -0800 Subject: [PATCH 201/730] linux-user/elfload: Rename ARM_COMMPAGE to HI_COMMPAGE Arm will no longer be the only target requiring a commpage, but it will continue to be the only target placing the page at the high end of the address space. Reviewed-by: Laurent Vivier Signed-off-by: Richard Henderson Message-Id: <20211221025012.1057923-4-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/elfload.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 767f54c76d..d34cd4fe43 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -390,11 +390,11 @@ enum { /* The commpage only exists for 32 bit kernels */ -#define ARM_COMMPAGE (intptr_t)0xffff0f00u +#define HI_COMMPAGE (intptr_t)0xffff0f00u static bool init_guest_commpage(void) { - void *want = g2h_untagged(ARM_COMMPAGE & -qemu_host_page_size); + void *want = g2h_untagged(HI_COMMPAGE & -qemu_host_page_size); void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); @@ -2160,8 +2160,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, return sp; } -#ifndef ARM_COMMPAGE -#define ARM_COMMPAGE 0 +#ifndef HI_COMMPAGE +#define HI_COMMPAGE 0 #define init_guest_commpage() true #endif @@ -2361,7 +2361,7 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr, } loaddr &= -align; - if (ARM_COMMPAGE) { + if (HI_COMMPAGE) { /* * Extend the allocation to include the commpage. * For a 64-bit host, this is just 4GiB; for a 32-bit host we @@ -2372,14 +2372,14 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr, if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) { hiaddr = (uintptr_t) 4 << 30; } else { - offset = -(ARM_COMMPAGE & -align); + offset = -(HI_COMMPAGE & -align); } } addr = pgb_find_hole(loaddr, hiaddr - loaddr, align, offset); if (addr == -1) { /* - * If ARM_COMMPAGE, there *might* be a non-consecutive allocation + * If HI_COMMPAGE, there *might* be a non-consecutive allocation * that can satisfy both. But as the normal arm32 link base address * is ~32k, and we extend down to include the commpage, making the * overhead only ~96k, this is unlikely. @@ -2400,7 +2400,7 @@ static void pgb_dynamic(const char *image_name, long align) * All we need is a commpage that satisfies align. * If we do not need a commpage, leave guest_base == 0. */ - if (ARM_COMMPAGE) { + if (HI_COMMPAGE) { uintptr_t addr, commpage; /* 64-bit hosts should have used reserved_va. */ @@ -2410,7 +2410,7 @@ static void pgb_dynamic(const char *image_name, long align) * By putting the commpage at the first hole, that puts guest_base * just above that, and maximises the positive guest addresses. */ - commpage = ARM_COMMPAGE & -align; + commpage = HI_COMMPAGE & -align; addr = pgb_find_hole(commpage, -commpage, align, 0); assert(addr != -1); guest_base = addr; From f5ef0e518d0331920cef0fb6f6c1141695ffab7b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Dec 2021 18:50:09 -0800 Subject: [PATCH 202/730] linux-user/nios2: Map a real kuser page The first word of page1 is data, so the whole thing can't be implemented with emulation of addresses. Use init_guest_commpage for the allocation. Hijack trap number 16 to implement cmpxchg. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20211221025012.1057923-5-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/elfload.c | 50 ++++++++++++++++++++++++++++++++++++- linux-user/nios2/cpu_loop.c | 50 ++++++++++++++++++++----------------- target/nios2/translate.c | 9 ------- 3 files changed, 76 insertions(+), 33 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index d34cd4fe43..329b2375ef 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1099,6 +1099,47 @@ static void init_thread(struct target_pt_regs *regs, struct image_info *infop) regs->estatus = 0x3; } +#define LO_COMMPAGE TARGET_PAGE_SIZE + +static bool init_guest_commpage(void) +{ + static const uint8_t kuser_page[4 + 2 * 64] = { + /* __kuser_helper_version */ + [0x00] = 0x02, 0x00, 0x00, 0x00, + + /* __kuser_cmpxchg */ + [0x04] = 0x3a, 0x6c, 0x3b, 0x00, /* trap 16 */ + 0x3a, 0x28, 0x00, 0xf8, /* ret */ + + /* __kuser_sigtramp */ + [0x44] = 0xc4, 0x22, 0x80, 0x00, /* movi r2, __NR_rt_sigreturn */ + 0x3a, 0x68, 0x3b, 0x00, /* trap 0 */ + }; + + void *want = g2h_untagged(LO_COMMPAGE & -qemu_host_page_size); + void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); + + if (addr == MAP_FAILED) { + perror("Allocating guest commpage"); + exit(EXIT_FAILURE); + } + if (addr != want) { + return false; + } + + memcpy(addr, kuser_page, sizeof(kuser_page)); + + if (mprotect(addr, qemu_host_page_size, PROT_READ)) { + perror("Protecting guest commpage"); + exit(EXIT_FAILURE); + } + + page_set_flags(LO_COMMPAGE, LO_COMMPAGE + TARGET_PAGE_SIZE, + PAGE_READ | PAGE_EXEC | PAGE_VALID); + return true; +} + #define ELF_EXEC_PAGESIZE 4096 #define USE_ELF_CORE_DUMP @@ -2160,8 +2201,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, return sp; } -#ifndef HI_COMMPAGE +#if defined(HI_COMMPAGE) +#define LO_COMMPAGE 0 +#elif defined(LO_COMMPAGE) #define HI_COMMPAGE 0 +#else +#define HI_COMMPAGE 0 +#define LO_COMMPAGE 0 #define init_guest_commpage() true #endif @@ -2374,6 +2420,8 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr, } else { offset = -(HI_COMMPAGE & -align); } + } else if (LO_COMMPAGE) { + loaddr = MIN(loaddr, LO_COMMPAGE & -align); } addr = pgb_find_hole(loaddr, hiaddr - loaddr, align, offset); diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c index 5c3d01d22d..de0fc63e21 100644 --- a/linux-user/nios2/cpu_loop.c +++ b/linux-user/nios2/cpu_loop.c @@ -76,6 +76,32 @@ void cpu_loop(CPUNios2State *env) force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP, env->regs[R_PC]); break; + + case 16: /* QEMU specific, for __kuser_cmpxchg */ + { + abi_ptr g = env->regs[4]; + uint32_t *h, n, o; + + if (g & 0x3) { + force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, g); + break; + } + ret = page_get_flags(g); + if (!(ret & PAGE_VALID)) { + force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, g); + break; + } + if (!(ret & PAGE_READ) || !(ret & PAGE_WRITE)) { + force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_ACCERR, g); + break; + } + h = g2h(cs, g); + o = env->regs[5]; + n = env->regs[6]; + env->regs[2] = qatomic_cmpxchg(h, o, n) - o; + env->regs[R_PC] += 4; + } + break; } break; @@ -86,29 +112,7 @@ void cpu_loop(CPUNios2State *env) queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; case 0xaa: - switch (env->regs[R_PC]) { - /*case 0x1000:*/ /* TODO:__kuser_helper_version */ - case 0x1004: /* __kuser_cmpxchg */ - start_exclusive(); - if (env->regs[4] & 0x3) { - goto kuser_fail; - } - ret = get_user_u32(env->regs[2], env->regs[4]); - if (ret) { - end_exclusive(); - goto kuser_fail; - } - env->regs[2] -= env->regs[5]; - if (env->regs[2] == 0) { - put_user_u32(env->regs[6], env->regs[4]); - } - end_exclusive(); - env->regs[R_PC] = env->regs[R_RA]; - break; - /*case 0x1040:*/ /* TODO:__kuser_sigtramp */ - default: - ; -kuser_fail: + { info.si_signo = TARGET_SIGSEGV; info.si_errno = 0; /* TODO: check env->error_code */ diff --git a/target/nios2/translate.c b/target/nios2/translate.c index a759877519..f9abc2fdd2 100644 --- a/target/nios2/translate.c +++ b/target/nios2/translate.c @@ -795,15 +795,6 @@ static void nios2_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) dc->base.pc_next = pc + 4; /* Decode an instruction */ - -#if defined(CONFIG_USER_ONLY) - /* FIXME: Is this needed ? */ - if (pc >= 0x1000 && pc < 0x2000) { - t_gen_helper_raise_exception(dc, 0xaa); - return; - } -#endif - code = cpu_ldl_code(env, pc); op = get_opcode(code); From 8222d8ba6f62aaab2da81618e56c5055ccbc7be0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Dec 2021 18:50:10 -0800 Subject: [PATCH 203/730] linux-user/nios2: Fix EA vs PC confusion The real kernel will talk about the user PC as EA, because that's where the hardware will have copied it, and where it expects to put it to then use ERET. But qemu does not emulate all of the exception stuff while emulating user-only. Manipulate PC directly. This fixes signal entry and return, and eliminates some slight confusion from target_cpu_copy_regs. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20211221025012.1057923-6-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/nios2/cpu_loop.c | 5 +---- linux-user/nios2/signal.c | 6 +++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c index de0fc63e21..1e93ef34e6 100644 --- a/linux-user/nios2/cpu_loop.c +++ b/linux-user/nios2/cpu_loop.c @@ -155,9 +155,6 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) env->regs[R_SP] = regs->sp; env->regs[R_GP] = regs->gp; env->regs[CR_ESTATUS] = regs->estatus; - env->regs[R_EA] = regs->ea; - /* TODO: unsigned long orig_r7; */ - - /* Emulate eret when starting thread. */ env->regs[R_PC] = regs->ea; + /* TODO: unsigned long orig_r7; */ } diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c index adbffe32e3..20b65aa06e 100644 --- a/linux-user/nios2/signal.c +++ b/linux-user/nios2/signal.c @@ -73,7 +73,7 @@ static void rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env) __put_user(env->regs[R_RA], &gregs[23]); __put_user(env->regs[R_FP], &gregs[24]); __put_user(env->regs[R_GP], &gregs[25]); - __put_user(env->regs[R_EA], &gregs[27]); + __put_user(env->regs[R_PC], &gregs[27]); __put_user(env->regs[R_SP], &gregs[28]); } @@ -122,7 +122,7 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc, __get_user(env->regs[R_GP], &gregs[25]); /* Not really necessary no user settable bits */ __get_user(temp, &gregs[26]); - __get_user(env->regs[R_EA], &gregs[27]); + __get_user(env->regs[R_PC], &gregs[27]); __get_user(env->regs[R_RA], &gregs[23]); __get_user(env->regs[R_SP], &gregs[28]); @@ -181,7 +181,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, env->regs[4] = sig; env->regs[5] = frame_addr + offsetof(struct target_rt_sigframe, info); env->regs[6] = frame_addr + offsetof(struct target_rt_sigframe, uc); - env->regs[R_EA] = ka->_sa_handler; + env->regs[R_PC] = ka->_sa_handler; unlock_user_struct(frame, frame_addr, 1); } From 7a83cbb0b0ef46e17f953bd972a1abb899d5d56e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Dec 2021 18:50:11 -0800 Subject: [PATCH 204/730] linux-user/nios2: Fix sigmask in setup_rt_frame Do not cast the signal mask elements; trust __put_user. Reviewed-by: Laurent Vivier Signed-off-by: Richard Henderson Message-Id: <20211221025012.1057923-7-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/nios2/signal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c index 20b65aa06e..80e3d42fc9 100644 --- a/linux-user/nios2/signal.c +++ b/linux-user/nios2/signal.c @@ -168,8 +168,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, target_save_altstack(&frame->uc.tuc_stack, env); rt_setup_ucontext(&frame->uc, env); for (i = 0; i < TARGET_NSIG_WORDS; i++) { - __put_user((abi_ulong)set->sig[i], - (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]); + __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); } /* Set up to return from userspace; jump to fixed address sigreturn From 155fff93f8e7720fa476f2f9a5c08bdad2076b8b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Dec 2021 18:50:12 -0800 Subject: [PATCH 205/730] linux-user/nios2: Use set_sigmask in do_rt_sigreturn Using do_sigprocmask directly was incorrect, as it will leave the signal blocked by the outer layers of linux-user. Reviewed-by: Laurent Vivier Signed-off-by: Richard Henderson Message-Id: <20211221025012.1057923-8-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/nios2/signal.c | 2 +- linux-user/signal.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c index 80e3d42fc9..517cd39270 100644 --- a/linux-user/nios2/signal.c +++ b/linux-user/nios2/signal.c @@ -205,7 +205,7 @@ long do_rt_sigreturn(CPUNios2State *env) } target_to_host_sigset(&set, &frame->uc.tuc_sigmask); - do_sigprocmask(SIG_SETMASK, &set, NULL); + set_sigmask(&set); if (rt_restore_ucontext(env, &frame->uc, &rval)) { goto badframe; diff --git a/linux-user/signal.c b/linux-user/signal.c index 1229fecf5c..f813b4f18e 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -258,7 +258,6 @@ int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) return 0; } -#if !defined(TARGET_NIOS2) /* Just set the guest's signal mask to the specified value; the * caller is assumed to have called block_signals() already. */ @@ -268,7 +267,6 @@ void set_sigmask(const sigset_t *set) ts->signal_mask = *set; } -#endif /* sigaltstack management */ From 7a5626a1d8a193106dc709608273ed48729967d5 Mon Sep 17 00:00:00 2001 From: Ahmed Abouzied Date: Tue, 4 Jan 2022 16:38:41 +0200 Subject: [PATCH 206/730] linux-user/syscall.c: malloc to g_try_malloc Use g_try_malloc instead of malloc to alocate the target ifconfig. Also replace the corresponding free with g_free. Signed-off-by: Ahmed Abouzied Message-Id: <20220104143841.25116-1-email@aabouzied.com> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3160d77154..ce9d64896c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4915,7 +4915,7 @@ static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp, * We can't fit all the extents into the fixed size buffer. * Allocate one that is large enough and use it instead. */ - host_ifconf = malloc(outbufsz); + host_ifconf = g_try_malloc(outbufsz); if (!host_ifconf) { return -TARGET_ENOMEM; } @@ -4963,7 +4963,7 @@ static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp, } if (free_buf) { - free(host_ifconf); + g_free(host_ifconf); } return ret; From 312aef98ae3bd0685445dfbae089c559bdd0335f Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Sun, 19 Dec 2021 16:45:12 +0100 Subject: [PATCH 207/730] linux-user: netlink: update IFLA entries Add IFLA_PHYS_PORT_ID, IFLA_PARENT_DEV_NAME, IFLA_PARENT_DEV_BUS_NAME # QEMU_LOG=unimp ip a Unknown host QEMU_IFLA type: 56 Unknown host QEMU_IFLA type: 57 Unknown host QEMU_IFLA type: 34 Signed-off-by: Laurent Vivier Reviewed-by: Richard Henderson Message-Id: <20211219154514.2165728-1-laurent@vivier.eu> Signed-off-by: Laurent Vivier --- linux-user/fd-trans.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index 6941089959..14c19a90b2 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -138,6 +138,9 @@ enum { QEMU_IFLA_PROP_LIST, QEMU_IFLA_ALT_IFNAME, QEMU_IFLA_PERM_ADDRESS, + QEMU_IFLA_PROTO_DOWN_REASON, + QEMU_IFLA_PARENT_DEV_NAME, + QEMU_IFLA_PARENT_DEV_BUS_NAME, QEMU___IFLA_MAX }; @@ -818,9 +821,12 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) case QEMU_IFLA_ADDRESS: case QEMU_IFLA_BROADCAST: case QEMU_IFLA_PERM_ADDRESS: + case QEMU_IFLA_PHYS_PORT_ID: /* string */ case QEMU_IFLA_IFNAME: case QEMU_IFLA_QDISC: + case QEMU_IFLA_PARENT_DEV_NAME: + case QEMU_IFLA_PARENT_DEV_BUS_NAME: break; /* uin8_t */ case QEMU_IFLA_OPERSTATE: From a99478672c0db904c07f8c7aadc94f13f5ab32f4 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Sun, 19 Dec 2021 16:45:13 +0100 Subject: [PATCH 208/730] linux-user: netlink: Add IFLA_VFINFO_LIST # QEMU_LOG=unimp ip a Unknown host QEMU_IFLA type: 22 Signed-off-by: Laurent Vivier Reviewed-by: Richard Henderson Message-Id: <20211219154514.2165728-2-laurent@vivier.eu> Signed-off-by: Laurent Vivier --- linux-user/fd-trans.c | 174 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index 14c19a90b2..36e4a4c2aa 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -271,6 +271,37 @@ enum { QEMU___RTA_MAX }; +enum { + QEMU_IFLA_VF_STATS_RX_PACKETS, + QEMU_IFLA_VF_STATS_TX_PACKETS, + QEMU_IFLA_VF_STATS_RX_BYTES, + QEMU_IFLA_VF_STATS_TX_BYTES, + QEMU_IFLA_VF_STATS_BROADCAST, + QEMU_IFLA_VF_STATS_MULTICAST, + QEMU_IFLA_VF_STATS_PAD, + QEMU_IFLA_VF_STATS_RX_DROPPED, + QEMU_IFLA_VF_STATS_TX_DROPPED, + QEMU__IFLA_VF_STATS_MAX, +}; + +enum { + QEMU_IFLA_VF_UNSPEC, + QEMU_IFLA_VF_MAC, + QEMU_IFLA_VF_VLAN, + QEMU_IFLA_VF_TX_RATE, + QEMU_IFLA_VF_SPOOFCHK, + QEMU_IFLA_VF_LINK_STATE, + QEMU_IFLA_VF_RATE, + QEMU_IFLA_VF_RSS_QUERY_EN, + QEMU_IFLA_VF_STATS, + QEMU_IFLA_VF_TRUST, + QEMU_IFLA_VF_IB_NODE_GUID, + QEMU_IFLA_VF_IB_PORT_GUID, + QEMU_IFLA_VF_VLAN_LIST, + QEMU_IFLA_VF_BROADCAST, + QEMU__IFLA_VF_MAX, +}; + TargetFdTrans **target_fd_trans; QemuMutex target_fd_trans_lock; unsigned int target_fd_max; @@ -808,6 +839,145 @@ static abi_long host_to_target_data_xdp_nlattr(struct nlattr *nlattr, return 0; } +static abi_long host_to_target_data_vlan_list_nlattr(struct nlattr *nlattr, + void *context) +{ + struct ifla_vf_vlan_info *vlan_info; + + switch (nlattr->nla_type) { + /* struct ifla_vf_vlan_info */ + case IFLA_VF_VLAN_INFO: + vlan_info = NLA_DATA(nlattr); + vlan_info->vf = tswap32(vlan_info->vf); + vlan_info->vlan = tswap32(vlan_info->vlan); + vlan_info->qos = tswap32(vlan_info->qos); + break; + default: + qemu_log_mask(LOG_UNIMP, "Unknown host VLAN LIST type: %d\n", + nlattr->nla_type); + break; + } + return 0; +} + +static abi_long host_to_target_data_vf_stats_nlattr(struct nlattr *nlattr, + void *context) +{ + uint64_t *u64; + + switch (nlattr->nla_type) { + /* uint64_t */ + case QEMU_IFLA_VF_STATS_RX_PACKETS: + case QEMU_IFLA_VF_STATS_TX_PACKETS: + case QEMU_IFLA_VF_STATS_RX_BYTES: + case QEMU_IFLA_VF_STATS_TX_BYTES: + case QEMU_IFLA_VF_STATS_BROADCAST: + case QEMU_IFLA_VF_STATS_MULTICAST: + case QEMU_IFLA_VF_STATS_PAD: + case QEMU_IFLA_VF_STATS_RX_DROPPED: + case QEMU_IFLA_VF_STATS_TX_DROPPED: + u64 = NLA_DATA(nlattr); + *u64 = tswap64(*u64); + break; + default: + qemu_log_mask(LOG_UNIMP, "Unknown host VF STATS type: %d\n", + nlattr->nla_type); + break; + } + return 0; +} + +static abi_long host_to_target_data_vfinfo_nlattr(struct nlattr *nlattr, + void *context) +{ + struct ifla_vf_mac *mac; + struct ifla_vf_vlan *vlan; + struct ifla_vf_vlan_info *vlan_info; + struct ifla_vf_spoofchk *spoofchk; + struct ifla_vf_rate *rate; + struct ifla_vf_link_state *link_state; + struct ifla_vf_rss_query_en *rss_query_en; + struct ifla_vf_trust *trust; + struct ifla_vf_guid *guid; + + switch (nlattr->nla_type) { + /* struct ifla_vf_mac */ + case QEMU_IFLA_VF_MAC: + mac = NLA_DATA(nlattr); + mac->vf = tswap32(mac->vf); + break; + /* struct ifla_vf_broadcast */ + case QEMU_IFLA_VF_BROADCAST: + break; + /* struct struct ifla_vf_vlan */ + case QEMU_IFLA_VF_VLAN: + vlan = NLA_DATA(nlattr); + vlan->vf = tswap32(vlan->vf); + vlan->vlan = tswap32(vlan->vlan); + vlan->qos = tswap32(vlan->qos); + break; + /* struct ifla_vf_vlan_info */ + case QEMU_IFLA_VF_TX_RATE: + vlan_info = NLA_DATA(nlattr); + vlan_info->vf = tswap32(vlan_info->vf); + vlan_info->vlan = tswap32(vlan_info->vlan); + vlan_info->qos = tswap32(vlan_info->qos); + break; + /* struct ifla_vf_spoofchk */ + case QEMU_IFLA_VF_SPOOFCHK: + spoofchk = NLA_DATA(nlattr); + spoofchk->vf = tswap32(spoofchk->vf); + spoofchk->setting = tswap32(spoofchk->setting); + break; + /* struct ifla_vf_rate */ + case QEMU_IFLA_VF_RATE: + rate = NLA_DATA(nlattr); + rate->vf = tswap32(rate->vf); + rate->min_tx_rate = tswap32(rate->min_tx_rate); + rate->max_tx_rate = tswap32(rate->max_tx_rate); + break; + /* struct ifla_vf_link_state */ + case QEMU_IFLA_VF_LINK_STATE: + link_state = NLA_DATA(nlattr); + link_state->vf = tswap32(link_state->vf); + link_state->link_state = tswap32(link_state->link_state); + break; + /* struct ifla_vf_rss_query_en */ + case QEMU_IFLA_VF_RSS_QUERY_EN: + rss_query_en = NLA_DATA(nlattr); + rss_query_en->vf = tswap32(rss_query_en->vf); + rss_query_en->setting = tswap32(rss_query_en->setting); + break; + /* struct ifla_vf_trust */ + case QEMU_IFLA_VF_TRUST: + trust = NLA_DATA(nlattr); + trust->vf = tswap32(trust->vf); + trust->setting = tswap32(trust->setting); + break; + /* struct ifla_vf_guid */ + case QEMU_IFLA_VF_IB_NODE_GUID: + case QEMU_IFLA_VF_IB_PORT_GUID: + guid = NLA_DATA(nlattr); + guid->vf = tswap32(guid->vf); + guid->guid = tswap32(guid->guid); + break; + /* nested */ + case QEMU_IFLA_VF_VLAN_LIST: + return host_to_target_for_each_nlattr(RTA_DATA(nlattr), nlattr->nla_len, + NULL, + host_to_target_data_vlan_list_nlattr); + case QEMU_IFLA_VF_STATS: + return host_to_target_for_each_nlattr(RTA_DATA(nlattr), nlattr->nla_len, + NULL, + host_to_target_data_vf_stats_nlattr); + default: + qemu_log_mask(LOG_UNIMP, "Unknown host VFINFO type: %d\n", + nlattr->nla_type); + break; + } + return 0; +} + static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) { uint32_t *u32; @@ -945,6 +1115,10 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr) return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len, NULL, host_to_target_data_xdp_nlattr); + case QEMU_IFLA_VFINFO_LIST: + return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len, + NULL, + host_to_target_data_vfinfo_nlattr); default: qemu_log_mask(LOG_UNIMP, "Unknown host QEMU_IFLA type: %d\n", rtattr->rta_type); From f0effdbc2a5b43422bc4c9c22641ef9dafa0c7ae Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Sun, 19 Dec 2021 16:45:14 +0100 Subject: [PATCH 209/730] linux-user: netlink: update IFLA_BRPORT entries add IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT and IFLA_BRPORT_MCAST_EHT_HOSTS_CNT # QEMU_LOG=unimp ip a Unknown QEMU_IFLA_BRPORT type 37 Unknown QEMU_IFLA_BRPORT type 38 Signed-off-by: Laurent Vivier Reviewed-by: Richard Henderson Message-Id: <20211219154514.2165728-3-laurent@vivier.eu> Signed-off-by: Laurent Vivier --- linux-user/fd-trans.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index 36e4a4c2aa..a17d05c079 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -182,6 +182,8 @@ enum { QEMU_IFLA_BRPORT_BACKUP_PORT, QEMU_IFLA_BRPORT_MRP_RING_OPEN, QEMU_IFLA_BRPORT_MRP_IN_OPEN, + QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT, + QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_CNT, QEMU___IFLA_BRPORT_MAX }; @@ -607,6 +609,8 @@ static abi_long host_to_target_slave_data_bridge_nlattr(struct nlattr *nlattr, /* uin32_t */ case QEMU_IFLA_BRPORT_COST: case QEMU_IFLA_BRPORT_BACKUP_PORT: + case QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT: + case QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_CNT: u32 = NLA_DATA(nlattr); *u32 = tswap32(*u32); break; From 9bd6565ccee68f72d5012e24646e12a1c662827e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 21 Dec 2021 09:45:44 -0500 Subject: [PATCH 210/730] acpi: validate hotplug selector on access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When bus is looked up on a pci write, we didn't validate that the lookup succeeded. Fuzzers thus can trigger QEMU crash by dereferencing the NULL bus pointer. Fixes: b32bd763a1 ("pci: introduce acpi-index property for PCI device") Fixes: CVE-2021-4158 Cc: "Igor Mammedov" Fixes: https://gitlab.com/qemu-project/qemu/-/issues/770 Signed-off-by: Michael S. Tsirkin Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Ani Sinha --- hw/acpi/pcihp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c index 30405b5113..a5e182dd3a 100644 --- a/hw/acpi/pcihp.c +++ b/hw/acpi/pcihp.c @@ -491,6 +491,9 @@ static void pci_write(void *opaque, hwaddr addr, uint64_t data, } bus = acpi_pcihp_find_hotplug_bus(s, s->hotplug_select); + if (!bus) { + break; + } QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) { Object *o = OBJECT(kid->child); PCIDevice *dev = PCI_DEVICE(o); From bf1d85c166c19af95dbd27b1faba1d2909732323 Mon Sep 17 00:00:00 2001 From: Cindy Lu Date: Fri, 5 Nov 2021 00:48:18 +0800 Subject: [PATCH 211/730] virtio: introduce macro IRTIO_CONFIG_IRQ_IDX To support configure interrupt for vhost-vdpa Introduce VIRTIO_CONFIG_IRQ_IDX -1 as configure interrupt's queue index, Then we can reuse the functions guest_notifier_mask and guest_notifier_pending. Add the check of queue index in these drivers, if the driver does not support configure interrupt, the function will just return Signed-off-by: Cindy Lu Message-Id: <20211104164827.21911-2-lulu@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/display/vhost-user-gpu.c | 6 ++++++ hw/net/virtio-net.c | 10 ++++++++-- hw/virtio/vhost-user-fs.c | 6 ++++++ hw/virtio/vhost-vsock-common.c | 6 ++++++ hw/virtio/virtio-crypto.c | 6 ++++++ include/hw/virtio/virtio.h | 3 +++ 6 files changed, 35 insertions(+), 2 deletions(-) diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 09818231bd..d4a440e815 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -485,6 +485,9 @@ vhost_user_gpu_guest_notifier_pending(VirtIODevice *vdev, int idx) { VhostUserGPU *g = VHOST_USER_GPU(vdev); + if (idx == VIRTIO_CONFIG_IRQ_IDX) { + return false; + } return vhost_virtqueue_pending(&g->vhost->dev, idx); } @@ -493,6 +496,9 @@ vhost_user_gpu_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask) { VhostUserGPU *g = VHOST_USER_GPU(vdev); + if (idx == VIRTIO_CONFIG_IRQ_IDX) { + return; + } vhost_virtqueue_mask(&g->vhost->dev, vdev, idx, mask); } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index cf8ab0f8af..5e03c0dd14 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -3168,6 +3168,9 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) VirtIONet *n = VIRTIO_NET(vdev); NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); assert(n->vhost_started); + if (idx == VIRTIO_CONFIG_IRQ_IDX) { + return false; + } return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx); } @@ -3177,8 +3180,11 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, VirtIONet *n = VIRTIO_NET(vdev); NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); assert(n->vhost_started); - vhost_net_virtqueue_mask(get_vhost_net(nc->peer), - vdev, idx, mask); + if (idx == VIRTIO_CONFIG_IRQ_IDX) { + return; + } + + vhost_net_virtqueue_mask(get_vhost_net(nc->peer), vdev, idx, mask); } static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features) diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c index c595957983..9b0349922e 100644 --- a/hw/virtio/vhost-user-fs.c +++ b/hw/virtio/vhost-user-fs.c @@ -161,6 +161,9 @@ static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx, { VHostUserFS *fs = VHOST_USER_FS(vdev); + if (idx == VIRTIO_CONFIG_IRQ_IDX) { + return; + } vhost_virtqueue_mask(&fs->vhost_dev, vdev, idx, mask); } @@ -168,6 +171,9 @@ static bool vuf_guest_notifier_pending(VirtIODevice *vdev, int idx) { VHostUserFS *fs = VHOST_USER_FS(vdev); + if (idx == VIRTIO_CONFIG_IRQ_IDX) { + return false; + } return vhost_virtqueue_pending(&fs->vhost_dev, idx); } diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c index 3f3771274e..d1b9c027b6 100644 --- a/hw/virtio/vhost-vsock-common.c +++ b/hw/virtio/vhost-vsock-common.c @@ -125,6 +125,9 @@ static void vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx, { VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + if (idx == VIRTIO_CONFIG_IRQ_IDX) { + return; + } vhost_virtqueue_mask(&vvc->vhost_dev, vdev, idx, mask); } @@ -133,6 +136,9 @@ static bool vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev, { VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + if (idx == VIRTIO_CONFIG_IRQ_IDX) { + return false; + } return vhost_virtqueue_pending(&vvc->vhost_dev, idx); } diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c index 54f9bbb789..1d5192f8b4 100644 --- a/hw/virtio/virtio-crypto.c +++ b/hw/virtio/virtio-crypto.c @@ -948,6 +948,9 @@ static void virtio_crypto_guest_notifier_mask(VirtIODevice *vdev, int idx, assert(vcrypto->vhost_started); + if (idx == VIRTIO_CONFIG_IRQ_IDX) { + return; + } cryptodev_vhost_virtqueue_mask(vdev, queue, idx, mask); } @@ -958,6 +961,9 @@ static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx) assert(vcrypto->vhost_started); + if (idx == VIRTIO_CONFIG_IRQ_IDX) { + return false; + } return cryptodev_vhost_virtqueue_pending(vdev, queue, idx); } diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 8bab9cfb75..605ea79c90 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -67,6 +67,9 @@ typedef struct VirtQueueElement #define VIRTIO_NO_VECTOR 0xffff +/* special index value used internally for config irqs */ +#define VIRTIO_CONFIG_IRQ_IDX -1 + #define TYPE_VIRTIO_DEVICE "virtio-device" OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE) From e3480ef81f6fb61cc9c04e3b5be8b7e84484fc05 Mon Sep 17 00:00:00 2001 From: Cindy Lu Date: Fri, 5 Nov 2021 00:48:19 +0800 Subject: [PATCH 212/730] virtio-pci: decouple notifier from interrupt process To reuse the notifier process in configure interrupt. Use the virtio_pci_get_notifier function to get the notifier. the INPUT of this function is the IDX, the OUTPUT is notifier and the vector Signed-off-by: Cindy Lu Message-Id: <20211104164827.21911-3-lulu@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 88 +++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 31 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 750aa47ec1..4bdb6e5694 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -704,29 +704,41 @@ static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy, } static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy, - unsigned int queue_no, + EventNotifier *n, unsigned int vector) { VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; - VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - VirtQueue *vq = virtio_get_queue(vdev, queue_no); - EventNotifier *n = virtio_queue_get_guest_notifier(vq); return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, irqfd->virq); } static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy, - unsigned int queue_no, + EventNotifier *n , unsigned int vector) { - VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - VirtQueue *vq = virtio_get_queue(vdev, queue_no); - EventNotifier *n = virtio_queue_get_guest_notifier(vq); VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; int ret; ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, irqfd->virq); assert(ret == 0); } +static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, + EventNotifier **n, unsigned int *vector) +{ + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtQueue *vq; + + if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { + return -1; + } else { + if (!virtio_queue_get_num(vdev, queue_no)) { + return -1; + } + *vector = virtio_queue_vector(vdev, queue_no); + vq = virtio_get_queue(vdev, queue_no); + *n = virtio_queue_get_guest_notifier(vq); + } + return 0; +} static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) { @@ -735,12 +747,15 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); unsigned int vector; int ret, queue_no; - + EventNotifier *n; for (queue_no = 0; queue_no < nvqs; queue_no++) { if (!virtio_queue_get_num(vdev, queue_no)) { break; } - vector = virtio_queue_vector(vdev, queue_no); + ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); + if (ret < 0) { + break; + } if (vector >= msix_nr_vectors_allocated(dev)) { continue; } @@ -752,7 +767,7 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) * Otherwise, delay until unmasked in the frontend. */ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); + ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); if (ret < 0) { kvm_virtio_pci_vq_vector_release(proxy, vector); goto undo; @@ -768,7 +783,11 @@ undo: continue; } if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); + ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); + if (ret < 0) { + break; + } + kvm_virtio_pci_irqfd_release(proxy, n, vector); } kvm_virtio_pci_vq_vector_release(proxy, vector); } @@ -782,12 +801,16 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) unsigned int vector; int queue_no; VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - + EventNotifier *n; + int ret ; for (queue_no = 0; queue_no < nvqs; queue_no++) { if (!virtio_queue_get_num(vdev, queue_no)) { break; } - vector = virtio_queue_vector(vdev, queue_no); + ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); + if (ret < 0) { + break; + } if (vector >= msix_nr_vectors_allocated(dev)) { continue; } @@ -795,21 +818,20 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) * Otherwise, it was cleaned when masked in the frontend. */ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); + kvm_virtio_pci_irqfd_release(proxy, n, vector); } kvm_virtio_pci_vq_vector_release(proxy, vector); } } -static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy, +static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, unsigned int queue_no, unsigned int vector, - MSIMessage msg) + MSIMessage msg, + EventNotifier *n) { VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - VirtQueue *vq = virtio_get_queue(vdev, queue_no); - EventNotifier *n = virtio_queue_get_guest_notifier(vq); VirtIOIRQFD *irqfd; int ret = 0; @@ -836,14 +858,15 @@ static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy, event_notifier_set(n); } } else { - ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); + ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); } return ret; } -static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy, +static void virtio_pci_one_vector_mask(VirtIOPCIProxy *proxy, unsigned int queue_no, - unsigned int vector) + unsigned int vector, + EventNotifier *n) { VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); @@ -854,7 +877,7 @@ static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy, if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { k->guest_notifier_mask(vdev, queue_no, true); } else { - kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); + kvm_virtio_pci_irqfd_release(proxy, n, vector); } } @@ -864,6 +887,7 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); VirtQueue *vq = virtio_vector_first_queue(vdev, vector); + EventNotifier *n; int ret, index, unmasked = 0; while (vq) { @@ -872,7 +896,8 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, break; } if (index < proxy->nvqs_with_notifiers) { - ret = virtio_pci_vq_vector_unmask(proxy, index, vector, msg); + n = virtio_queue_get_guest_notifier(vq); + ret = virtio_pci_one_vector_unmask(proxy, index, vector, msg, n); if (ret < 0) { goto undo; } @@ -888,7 +913,8 @@ undo: while (vq && unmasked >= 0) { index = virtio_get_queue_index(vq); if (index < proxy->nvqs_with_notifiers) { - virtio_pci_vq_vector_mask(proxy, index, vector); + n = virtio_queue_get_guest_notifier(vq); + virtio_pci_one_vector_mask(proxy, index, vector, n); --unmasked; } vq = virtio_vector_next_queue(vq); @@ -901,15 +927,17 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); VirtQueue *vq = virtio_vector_first_queue(vdev, vector); + EventNotifier *n; int index; while (vq) { index = virtio_get_queue_index(vq); + n = virtio_queue_get_guest_notifier(vq); if (!virtio_queue_get_num(vdev, index)) { break; } if (index < proxy->nvqs_with_notifiers) { - virtio_pci_vq_vector_mask(proxy, index, vector); + virtio_pci_one_vector_mask(proxy, index, vector, n); } vq = virtio_vector_next_queue(vq); } @@ -925,19 +953,17 @@ static void virtio_pci_vector_poll(PCIDevice *dev, int queue_no; unsigned int vector; EventNotifier *notifier; - VirtQueue *vq; + int ret; for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { - if (!virtio_queue_get_num(vdev, queue_no)) { + ret = virtio_pci_get_notifier(proxy, queue_no, ¬ifier, &vector); + if (ret < 0) { break; } - vector = virtio_queue_vector(vdev, queue_no); if (vector < vector_start || vector >= vector_end || !msix_is_masked(dev, vector)) { continue; } - vq = virtio_get_queue(vdev, queue_no); - notifier = virtio_queue_get_guest_notifier(vq); if (k->guest_notifier_pending) { if (k->guest_notifier_pending(vdev, queue_no)) { msix_set_pending(dev, vector); From 316011b8a74e777eb3ba03171cd701a291c28867 Mon Sep 17 00:00:00 2001 From: Cindy Lu Date: Fri, 5 Nov 2021 00:48:20 +0800 Subject: [PATCH 213/730] virtio-pci: decouple the single vector from the interrupt process To reuse the interrupt process in configure interrupt Need to decouple the single vector from the interrupt process. Add new function kvm_virtio_pci_vector_use_one and _release_one. These functions are use for the single vector, the whole process will finish in a loop for the vq number. Signed-off-by: Cindy Lu Message-Id: <20211104164827.21911-4-lulu@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 131 +++++++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 58 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 4bdb6e5694..7201cf3dc1 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -677,7 +677,6 @@ static uint32_t virtio_read_config(PCIDevice *pci_dev, } static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy, - unsigned int queue_no, unsigned int vector) { VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; @@ -740,87 +739,103 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, return 0; } -static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) +static int kvm_virtio_pci_vector_use_one(VirtIOPCIProxy *proxy, int queue_no) { + unsigned int vector; + int ret; + EventNotifier *n; PCIDevice *dev = &proxy->pci_dev; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - unsigned int vector; - int ret, queue_no; - EventNotifier *n; - for (queue_no = 0; queue_no < nvqs; queue_no++) { - if (!virtio_queue_get_num(vdev, queue_no)) { - break; - } - ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); - if (ret < 0) { - break; - } - if (vector >= msix_nr_vectors_allocated(dev)) { - continue; - } - ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector); + + ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); + if (ret < 0) { + return ret; + } + if (vector >= msix_nr_vectors_allocated(dev)) { + return 0; + } + ret = kvm_virtio_pci_vq_vector_use(proxy, vector); + if (ret < 0) { + goto undo; + } + /* + * If guest supports masking, set up irqfd now. + * Otherwise, delay until unmasked in the frontend. + */ + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { + ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); if (ret < 0) { + kvm_virtio_pci_vq_vector_release(proxy, vector); goto undo; } - /* If guest supports masking, set up irqfd now. - * Otherwise, delay until unmasked in the frontend. - */ - if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); - if (ret < 0) { - kvm_virtio_pci_vq_vector_release(proxy, vector); - goto undo; - } - } } - return 0; + return 0; undo: - while (--queue_no >= 0) { - vector = virtio_queue_vector(vdev, queue_no); - if (vector >= msix_nr_vectors_allocated(dev)) { - continue; + + vector = virtio_queue_vector(vdev, queue_no); + if (vector >= msix_nr_vectors_allocated(dev)) { + return ret; + } + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { + ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); + if (ret < 0) { + return ret; } - if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); - if (ret < 0) { - break; - } - kvm_virtio_pci_irqfd_release(proxy, n, vector); + kvm_virtio_pci_irqfd_release(proxy, n, vector); + } + return ret; +} +static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) +{ + int queue_no; + int ret = 0; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + + for (queue_no = 0; queue_no < nvqs; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + return -1; } - kvm_virtio_pci_vq_vector_release(proxy, vector); + ret = kvm_virtio_pci_vector_use_one(proxy, queue_no); } return ret; } -static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) + +static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy, + int queue_no) { - PCIDevice *dev = &proxy->pci_dev; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); unsigned int vector; - int queue_no; - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); EventNotifier *n; - int ret ; + int ret; + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + PCIDevice *dev = &proxy->pci_dev; + + ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); + if (ret < 0) { + return; + } + if (vector >= msix_nr_vectors_allocated(dev)) { + return; + } + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { + kvm_virtio_pci_irqfd_release(proxy, n, vector); + } + kvm_virtio_pci_vq_vector_release(proxy, vector); +} + +static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) +{ + int queue_no; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + for (queue_no = 0; queue_no < nvqs; queue_no++) { if (!virtio_queue_get_num(vdev, queue_no)) { break; } - ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); - if (ret < 0) { - break; - } - if (vector >= msix_nr_vectors_allocated(dev)) { - continue; - } - /* If guest supports masking, clean up irqfd now. - * Otherwise, it was cleaned when masked in the frontend. - */ - if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - kvm_virtio_pci_irqfd_release(proxy, n, vector); - } - kvm_virtio_pci_vq_vector_release(proxy, vector); + kvm_virtio_pci_vector_release_one(proxy, queue_no); } } From 88062372340d33090b7f089ed3b1a00f530a8914 Mon Sep 17 00:00:00 2001 From: Cindy Lu Date: Fri, 5 Nov 2021 00:48:21 +0800 Subject: [PATCH 214/730] vhost: introduce new VhostOps vhost_set_config_call This patch introduces new VhostOps vhost_set_config_call. This function allows the vhost to set the event fd to kernel Signed-off-by: Cindy Lu Message-Id: <20211104164827.21911-5-lulu@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/virtio/vhost-backend.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h index 81bf3109f8..ff34eb7c8a 100644 --- a/include/hw/virtio/vhost-backend.h +++ b/include/hw/virtio/vhost-backend.h @@ -126,6 +126,8 @@ typedef int (*vhost_get_device_id_op)(struct vhost_dev *dev, uint32_t *dev_id); typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev); +typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev, + int fd); typedef struct VhostOps { VhostBackendType backend_type; vhost_backend_init vhost_backend_init; @@ -171,6 +173,7 @@ typedef struct VhostOps { vhost_vq_get_addr_op vhost_vq_get_addr; vhost_get_device_id_op vhost_get_device_id; vhost_force_iommu_op vhost_force_iommu; + vhost_set_config_call_op vhost_set_config_call; } VhostOps; int vhost_backend_update_device_iotlb(struct vhost_dev *dev, From 634f7c89fbd78f57d00d5d6b39c0ade9df1fe27f Mon Sep 17 00:00:00 2001 From: Cindy Lu Date: Fri, 5 Nov 2021 00:48:22 +0800 Subject: [PATCH 215/730] vhost-vdpa: add support for config interrupt Add new call back function in vhost-vdpa, this function will set the event fd to kernel. This function will be called in the vhost_dev_start and vhost_dev_stop Signed-off-by: Cindy Lu Message-Id: <20211104164827.21911-6-lulu@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/trace-events | 1 + hw/virtio/vhost-vdpa.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index f7ad6be5fb..595ce015ff 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -53,6 +53,7 @@ vhost_vdpa_get_features(void *dev, uint64_t features) "dev: %p features: 0x%"PRI vhost_vdpa_set_owner(void *dev) "dev: %p" vhost_vdpa_vq_get_addr(void *dev, void *vq, uint64_t desc_user_addr, uint64_t avail_user_addr, uint64_t used_user_addr) "dev: %p vq: %p desc_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" used_user_addr: 0x%"PRIx64 vhost_vdpa_get_iova_range(void *dev, uint64_t first, uint64_t last) "dev: %p first: 0x%"PRIx64" last: 0x%"PRIx64 +vhost_vdpa_set_config_call(void *dev, int fd)"dev: %p fd: %d" # virtio.c virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned out_num) "elem %p size %zd in_num %u out_num %u" diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index bcaf00e09f..0a4a83713c 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -725,6 +725,12 @@ static int vhost_vdpa_set_vring_call(struct vhost_dev *dev, trace_vhost_vdpa_set_vring_call(dev, file->index, file->fd); return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file); } +static int vhost_vdpa_set_config_call(struct vhost_dev *dev, + int fd) +{ + trace_vhost_vdpa_set_config_call(dev, fd); + return vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG_CALL, &fd); +} static int vhost_vdpa_get_features(struct vhost_dev *dev, uint64_t *features) @@ -795,4 +801,5 @@ const VhostOps vdpa_ops = { .vhost_get_device_id = vhost_vdpa_get_device_id, .vhost_vq_get_addr = vhost_vdpa_vq_get_addr, .vhost_force_iommu = vhost_vdpa_force_iommu, + .vhost_set_config_call = vhost_vdpa_set_config_call, }; From 081f864f56307551f59c5e934e3f30a7290d0faa Mon Sep 17 00:00:00 2001 From: Cindy Lu Date: Fri, 5 Nov 2021 00:48:23 +0800 Subject: [PATCH 216/730] virtio: add support for configure interrupt Add the functions to support the configure interrupt in virtio The function virtio_config_guest_notifier_read will notify the guest if there is an configure interrupt. The function virtio_config_set_guest_notifier_fd_handler is to set the fd hander for the notifier Signed-off-by: Cindy Lu Message-Id: <20211104164827.21911-7-lulu@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 29 +++++++++++++++++++++++++++++ include/hw/virtio/virtio.h | 4 ++++ 2 files changed, 33 insertions(+) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index e11a8a0dba..36edb1dad5 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3493,7 +3493,14 @@ static void virtio_queue_guest_notifier_read(EventNotifier *n) virtio_irq(vq); } } +static void virtio_config_guest_notifier_read(EventNotifier *n) +{ + VirtIODevice *vdev = container_of(n, VirtIODevice, config_notifier); + if (event_notifier_test_and_clear(n)) { + virtio_notify_config(vdev); + } +} void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, bool with_irqfd) { @@ -3510,6 +3517,23 @@ void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, } } +void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev, + bool assign, bool with_irqfd) +{ + EventNotifier *n; + n = &vdev->config_notifier; + if (assign && !with_irqfd) { + event_notifier_set_handler(n, virtio_config_guest_notifier_read); + } else { + event_notifier_set_handler(n, NULL); + } + if (!assign) { + /* Test and clear notifier before closing it,*/ + /* in case poll callback didn't have time to run. */ + virtio_config_guest_notifier_read(n); + } +} + EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq) { return &vq->guest_notifier; @@ -3583,6 +3607,11 @@ EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq) return &vq->host_notifier; } +EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev) +{ + return &vdev->config_notifier; +} + void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled) { vq->host_notifier_enabled = enabled; diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 605ea79c90..d78088d872 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -111,6 +111,7 @@ struct VirtIODevice bool use_guest_notifier_mask; AddressSpace *dma_as; QLIST_HEAD(, VirtQueue) *vector_queues; + EventNotifier config_notifier; }; struct VirtioDeviceClass { @@ -313,11 +314,14 @@ uint16_t virtio_get_queue_index(VirtQueue *vq); EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq); void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, bool with_irqfd); +void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev, + bool assign, bool with_irqfd); int virtio_device_start_ioeventfd(VirtIODevice *vdev); int virtio_device_grab_ioeventfd(VirtIODevice *vdev); void virtio_device_release_ioeventfd(VirtIODevice *vdev); bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev); EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq); +EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev); void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled); void virtio_queue_host_notifier_read(EventNotifier *n); void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, From f7220a7ce21604a4bc6260ccca4dc9068c1f27f2 Mon Sep 17 00:00:00 2001 From: Cindy Lu Date: Fri, 5 Nov 2021 00:48:24 +0800 Subject: [PATCH 217/730] vhost: add support for configure interrupt Add functions to support configure interrupt. The configure interrupt process will start in vhost_dev_start and stop in vhost_dev_stop. Also add the functions to support vhost_config_pending and vhost_config_mask, for masked_config_notifier, we only use the notifier saved in vq 0. Signed-off-by: Cindy Lu Message-Id: <20211104164827.21911-8-lulu@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost.c | 76 +++++++++++++++++++++++++++++++++++++++ include/hw/virtio/vhost.h | 4 +++ 2 files changed, 80 insertions(+) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 20913cf8fb..98a4b0a0df 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1561,6 +1561,67 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, } } +bool vhost_config_pending(struct vhost_dev *hdev) +{ + assert(hdev->vhost_ops); + if ((hdev->started == false) || + (hdev->vhost_ops->vhost_set_config_call == NULL)) { + return false; + } + + EventNotifier *notifier = + &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier; + return event_notifier_test_and_clear(notifier); +} + +void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask) +{ + int fd; + int r; + EventNotifier *notifier = + &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier; + EventNotifier *config_notifier = &vdev->config_notifier; + assert(hdev->vhost_ops); + + if ((hdev->started == false) || + (hdev->vhost_ops->vhost_set_config_call == NULL)) { + return; + } + if (mask) { + assert(vdev->use_guest_notifier_mask); + fd = event_notifier_get_fd(notifier); + } else { + fd = event_notifier_get_fd(config_notifier); + } + r = hdev->vhost_ops->vhost_set_config_call(hdev, fd); + if (r < 0) { + VHOST_OPS_DEBUG("vhost_set_config_call failed"); + } +} + +static void vhost_stop_config_intr(struct vhost_dev *dev) +{ + int fd = -1; + assert(dev->vhost_ops); + if (dev->vhost_ops->vhost_set_config_call) { + dev->vhost_ops->vhost_set_config_call(dev, fd); + } +} + +static void vhost_start_config_intr(struct vhost_dev *dev) +{ + int r; + + assert(dev->vhost_ops); + int fd = event_notifier_get_fd(&dev->vdev->config_notifier); + if (dev->vhost_ops->vhost_set_config_call) { + r = dev->vhost_ops->vhost_set_config_call(dev, fd); + if (!r) { + event_notifier_set(&dev->vdev->config_notifier); + } + } +} + uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, uint64_t features) { @@ -1773,6 +1834,16 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) } } + r = event_notifier_init( + &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier, 0); + if (r < 0) { + return r; + } + event_notifier_test_and_clear( + &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); + if (!vdev->use_guest_notifier_mask) { + vhost_config_mask(hdev, vdev, true); + } if (hdev->log_enabled) { uint64_t log_base; @@ -1806,6 +1877,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) vhost_device_iotlb_miss(hdev, vq->used_phys, true); } } + vhost_start_config_intr(hdev); return 0; fail_log: vhost_log_put(hdev, false); @@ -1831,6 +1903,9 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) /* should only be called after backend is connected */ assert(hdev->vhost_ops); + event_notifier_test_and_clear( + &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); + event_notifier_test_and_clear(&vdev->config_notifier); if (hdev->vhost_ops->vhost_dev_start) { hdev->vhost_ops->vhost_dev_start(hdev, false); @@ -1848,6 +1923,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) } memory_listener_unregister(&hdev->iommu_listener); } + vhost_stop_config_intr(hdev); vhost_log_put(hdev, true); hdev->started = false; hdev->vdev = NULL; diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 58a73e7b7a..b0f3b78987 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -29,6 +29,7 @@ struct vhost_virtqueue { unsigned long long used_phys; unsigned used_size; EventNotifier masked_notifier; + EventNotifier masked_config_notifier; struct vhost_dev *dev; }; @@ -37,6 +38,7 @@ typedef unsigned long vhost_log_chunk_t; #define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t)) #define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS) #define VHOST_INVALID_FEATURE_BIT (0xff) +#define VHOST_QUEUE_NUM_CONFIG_INR 0 struct vhost_log { unsigned long long size; @@ -116,6 +118,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); +bool vhost_config_pending(struct vhost_dev *hdev); +void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask); /* Test and clear masked event pending status. * Should be called after unmask to avoid losing events. From 497679d51087090d5a22fd265d1b96cf92d49d9d Mon Sep 17 00:00:00 2001 From: Cindy Lu Date: Fri, 5 Nov 2021 00:48:25 +0800 Subject: [PATCH 218/730] virtio-net: add support for configure interrupt Add functions to support configure interrupt in virtio_net The functions are config_pending and config_mask, while this input idx is VIRTIO_CONFIG_IRQ_IDX will check the function of configure interrupt. Signed-off-by: Cindy Lu Message-Id: <20211104164827.21911-9-lulu@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/net/vhost_net-stub.c | 9 +++++++++ hw/net/vhost_net.c | 9 +++++++++ hw/net/virtio-net.c | 4 ++-- include/net/vhost_net.h | 2 ++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c index 89d71cfb8e..126ee35b70 100644 --- a/hw/net/vhost_net-stub.c +++ b/hw/net/vhost_net-stub.c @@ -101,3 +101,12 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu) { return 0; } + +bool vhost_net_config_pending(VHostNetState *net) +{ + return false; +} + +void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask) +{ +} diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 30379d2ca4..9c9fd0a73f 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -457,6 +457,15 @@ void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, vhost_virtqueue_mask(&net->dev, dev, idx, mask); } +bool vhost_net_config_pending(VHostNetState *net) +{ + return vhost_config_pending(&net->dev); +} + +void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask) +{ + vhost_config_mask(&net->dev, dev, mask); +} VHostNetState *get_vhost_net(NetClientState *nc) { VHostNetState *vhost_net = 0; diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 5e03c0dd14..5806a50c8d 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -3169,7 +3169,7 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); assert(n->vhost_started); if (idx == VIRTIO_CONFIG_IRQ_IDX) { - return false; + return vhost_net_config_pending(get_vhost_net(nc->peer)); } return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx); } @@ -3181,9 +3181,9 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); assert(n->vhost_started); if (idx == VIRTIO_CONFIG_IRQ_IDX) { + vhost_net_config_mask(get_vhost_net(nc->peer), vdev, mask); return; } - vhost_net_virtqueue_mask(get_vhost_net(nc->peer), vdev, idx, mask); } diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index 387e913e4e..fc37498550 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -39,6 +39,8 @@ int vhost_net_set_config(struct vhost_net *net, const uint8_t *data, bool vhost_net_virtqueue_pending(VHostNetState *net, int n); void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, int idx, bool mask); +bool vhost_net_config_pending(VHostNetState *net); +void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask); int vhost_net_notify_migration_done(VHostNetState *net, char* mac_addr); VHostNetState *get_vhost_net(NetClientState *nc); From d48185f1a40d4e4ed2fa2873a42b2a5eb8748256 Mon Sep 17 00:00:00 2001 From: Cindy Lu Date: Fri, 5 Nov 2021 00:48:26 +0800 Subject: [PATCH 219/730] virtio-mmio: add support for configure interrupt Add configure interrupt support for virtio-mmio bus. This interrupt will be working while the backend is vhost-vdpa Signed-off-by: Cindy Lu Message-Id: <20211104164827.21911-10-lulu@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-mmio.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index 72da12fea5..809132018b 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -673,7 +673,30 @@ static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign, return 0; } +static int virtio_mmio_set_config_guest_notifier(DeviceState *d, bool assign) +{ + VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d); + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); + bool with_irqfd = false; + EventNotifier *notifier = virtio_config_get_guest_notifier(vdev); + int r = 0; + if (assign) { + r = event_notifier_init(notifier, 0); + if (r < 0) { + return r; + } + virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); + } else { + virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); + event_notifier_cleanup(notifier); + } + if (vdc->guest_notifier_mask && vdev->use_guest_notifier_mask) { + vdc->guest_notifier_mask(vdev, VIRTIO_CONFIG_IRQ_IDX, !assign); + } + return r; +} static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) { @@ -695,6 +718,10 @@ static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs, goto assign_error; } } + r = virtio_mmio_set_config_guest_notifier(d, assign); + if (r < 0) { + goto assign_error; + } return 0; From d5d24d859c3957ea1674d0e102f96439cdbfe93a Mon Sep 17 00:00:00 2001 From: Cindy Lu Date: Fri, 5 Nov 2021 00:48:27 +0800 Subject: [PATCH 220/730] virtio-pci: add support for configure interrupt Add support for configure interrupt, The process is used kvm_irqfd_assign to set the gsi to kernel. When the configure notifier was signal by host, qemu will inject a msix interrupt to guest Signed-off-by: Cindy Lu Message-Id: <20211104164827.21911-11-lulu@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 92 ++++++++++++++++++++++++++++++++++++------ hw/virtio/virtio-pci.h | 4 +- 2 files changed, 83 insertions(+), 13 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 7201cf3dc1..98fb5493ae 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -727,7 +727,8 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, VirtQueue *vq; if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { - return -1; + *n = virtio_config_get_guest_notifier(vdev); + *vector = vdev->config_vector; } else { if (!virtio_queue_get_num(vdev, queue_no)) { return -1; @@ -802,6 +803,10 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) return ret; } +static int kvm_virtio_pci_vector_config_use(VirtIOPCIProxy *proxy) +{ + return kvm_virtio_pci_vector_use_one(proxy, VIRTIO_CONFIG_IRQ_IDX); +} static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy, int queue_no) @@ -839,6 +844,11 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) } } +static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy) +{ + kvm_virtio_pci_vector_release_one(proxy, VIRTIO_CONFIG_IRQ_IDX); +} + static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, unsigned int queue_no, unsigned int vector, @@ -920,9 +930,17 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, } vq = virtio_vector_next_queue(vq); } - + /* unmask config intr */ + n = virtio_config_get_guest_notifier(vdev); + ret = virtio_pci_one_vector_unmask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, + msg, n); + if (ret < 0) { + goto undo_config; + } return 0; - +undo_config: + n = virtio_config_get_guest_notifier(vdev); + virtio_pci_one_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n); undo: vq = virtio_vector_first_queue(vdev, vector); while (vq && unmasked >= 0) { @@ -956,6 +974,8 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) } vq = virtio_vector_next_queue(vq); } + n = virtio_config_get_guest_notifier(vdev); + virtio_pci_one_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n); } static void virtio_pci_vector_poll(PCIDevice *dev, @@ -987,6 +1007,34 @@ static void virtio_pci_vector_poll(PCIDevice *dev, msix_set_pending(dev, vector); } } + /* poll the config intr */ + ret = virtio_pci_get_notifier(proxy, VIRTIO_CONFIG_IRQ_IDX, ¬ifier, + &vector); + if (ret < 0) { + return; + } + if (vector < vector_start || vector >= vector_end || + !msix_is_masked(dev, vector)) { + return; + } + if (k->guest_notifier_pending) { + if (k->guest_notifier_pending(vdev, VIRTIO_CONFIG_IRQ_IDX)) { + msix_set_pending(dev, vector); + } + } else if (event_notifier_test_and_clear(notifier)) { + msix_set_pending(dev, vector); + } +} + +void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq, + int n, bool assign, + bool with_irqfd) +{ + if (n == VIRTIO_CONFIG_IRQ_IDX) { + virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); + } else { + virtio_queue_set_guest_notifier_fd_handler(vq, assign, with_irqfd); + } } static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, @@ -995,17 +1043,25 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); - VirtQueue *vq = virtio_get_queue(vdev, n); - EventNotifier *notifier = virtio_queue_get_guest_notifier(vq); + VirtQueue *vq = NULL; + EventNotifier *notifier = NULL; + + if (n == VIRTIO_CONFIG_IRQ_IDX) { + notifier = virtio_config_get_guest_notifier(vdev); + } else { + vq = virtio_get_queue(vdev, n); + notifier = virtio_queue_get_guest_notifier(vq); + } if (assign) { int r = event_notifier_init(notifier, 0); if (r < 0) { return r; } - virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd); + virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, true, with_irqfd); } else { - virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd); + virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, false, + with_irqfd); event_notifier_cleanup(notifier); } @@ -1047,6 +1103,7 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) msix_unset_vector_notifiers(&proxy->pci_dev); if (proxy->vector_irqfd) { kvm_virtio_pci_vector_release(proxy, nvqs); + kvm_virtio_pci_vector_config_release(proxy); g_free(proxy->vector_irqfd); proxy->vector_irqfd = NULL; } @@ -1062,7 +1119,11 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) goto assign_error; } } - + r = virtio_pci_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, assign, + with_irqfd); + if (r < 0) { + goto config_assign_error; + } /* Must set vector notifier after guest notifier has been assigned */ if ((with_irqfd || k->guest_notifier_mask) && assign) { if (with_irqfd) { @@ -1071,11 +1132,14 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) msix_nr_vectors_allocated(&proxy->pci_dev)); r = kvm_virtio_pci_vector_use(proxy, nvqs); if (r < 0) { - goto assign_error; + goto config_assign_error; } } - r = msix_set_vector_notifiers(&proxy->pci_dev, - virtio_pci_vector_unmask, + r = kvm_virtio_pci_vector_config_use(proxy); + if (r < 0) { + goto config_error; + } + r = msix_set_vector_notifiers(&proxy->pci_dev, virtio_pci_vector_unmask, virtio_pci_vector_mask, virtio_pci_vector_poll); if (r < 0) { @@ -1090,7 +1154,11 @@ notifiers_error: assert(assign); kvm_virtio_pci_vector_release(proxy, nvqs); } - +config_error: + kvm_virtio_pci_vector_config_release(proxy); +config_assign_error: + virtio_pci_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, !assign, + with_irqfd); assign_error: /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */ assert(assign); diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index 2446dcd9ae..b704acc5a8 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -251,5 +251,7 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t); * @fixed_queues. */ unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues); - +void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq, + int n, bool assign, + bool with_irqfd); #endif From deeb956c40e3b6f8ab95f7b53f148a836cf93da2 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Fri, 5 Nov 2021 20:25:41 +0100 Subject: [PATCH 221/730] trace-events,pci: unify trace events format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify format used by trace_pci_update_mappings_del(), trace_pci_update_mappings_add(), trace_pci_cfg_write() and trace_pci_cfg_read() to print the device name and bus number, slot number and function number. For instance: pci_cfg_read virtio-net-pci 00:0 @0x20 -> 0xffffc00c pci_cfg_write virtio-net-pci 00:0 @0x20 <- 0xfea0000c pci_update_mappings_del d=0x555810b92330 01:00.0 4,0xffffc000+0x4000 pci_update_mappings_add d=0x555810b92330 01:00.0 4,0xfea00000+0x4000 becomes pci_cfg_read virtio-net-pci 01:00.0 @0x20 -> 0xffffc00c pci_cfg_write virtio-net-pci 01:00.0 @0x20 <- 0xfea0000c pci_update_mappings_del virtio-net-pci 01:00.0 4,0xffffc000+0x4000 pci_update_mappings_add virtio-net-pci 01:00.0 4,0xfea00000+0x4000 Signed-off-by: Laurent Vivier Message-Id: <20211105192541.655831-1-lvivier@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Yanan Wang Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/pci/pci.c | 4 ++-- hw/pci/pci_host.c | 6 ++++-- hw/pci/trace-events | 8 ++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index e5993c1ef5..322ba450e7 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1390,7 +1390,7 @@ static void pci_update_mappings(PCIDevice *d) /* now do the real mapping */ if (r->addr != PCI_BAR_UNMAPPED) { - trace_pci_update_mappings_del(d, pci_dev_bus_num(d), + trace_pci_update_mappings_del(d->name, pci_dev_bus_num(d), PCI_SLOT(d->devfn), PCI_FUNC(d->devfn), i, r->addr, r->size); @@ -1398,7 +1398,7 @@ static void pci_update_mappings(PCIDevice *d) } r->addr = new_addr; if (r->addr != PCI_BAR_UNMAPPED) { - trace_pci_update_mappings_add(d, pci_dev_bus_num(d), + trace_pci_update_mappings_add(d->name, pci_dev_bus_num(d), PCI_SLOT(d->devfn), PCI_FUNC(d->devfn), i, r->addr, r->size); diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index 7beafd40a8..eaf217ff55 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -79,7 +79,8 @@ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr, return; } - trace_pci_cfg_write(pci_dev->name, PCI_SLOT(pci_dev->devfn), + trace_pci_cfg_write(pci_dev->name, pci_dev_bus_num(pci_dev), + PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn), addr, val); pci_dev->config_write(pci_dev, addr, val, MIN(len, limit - addr)); } @@ -104,7 +105,8 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr, } ret = pci_dev->config_read(pci_dev, addr, MIN(len, limit - addr)); - trace_pci_cfg_read(pci_dev->name, PCI_SLOT(pci_dev->devfn), + trace_pci_cfg_read(pci_dev->name, pci_dev_bus_num(pci_dev), + PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn), addr, ret); return ret; diff --git a/hw/pci/trace-events b/hw/pci/trace-events index fc777d0b5e..7570752c40 100644 --- a/hw/pci/trace-events +++ b/hw/pci/trace-events @@ -1,12 +1,12 @@ # See docs/devel/tracing.rst for syntax documentation. # pci.c -pci_update_mappings_del(void *d, uint32_t bus, uint32_t slot, uint32_t func, int bar, uint64_t addr, uint64_t size) "d=%p %02x:%02x.%x %d,0x%"PRIx64"+0x%"PRIx64 -pci_update_mappings_add(void *d, uint32_t bus, uint32_t slot, uint32_t func, int bar, uint64_t addr, uint64_t size) "d=%p %02x:%02x.%x %d,0x%"PRIx64"+0x%"PRIx64 +pci_update_mappings_del(const char *dev, uint32_t bus, uint32_t slot, uint32_t func, int bar, uint64_t addr, uint64_t size) "%s %02x:%02x.%x %d,0x%"PRIx64"+0x%"PRIx64 +pci_update_mappings_add(const char *dev, uint32_t bus, uint32_t slot, uint32_t func, int bar, uint64_t addr, uint64_t size) "%s %02x:%02x.%x %d,0x%"PRIx64"+0x%"PRIx64 # pci_host.c -pci_cfg_read(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x -> 0x%x" -pci_cfg_write(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x <- 0x%x" +pci_cfg_read(const char *dev, uint32_t bus, uint32_t slot, uint32_t func, unsigned offs, unsigned val) "%s %02x:%02x.%x @0x%x -> 0x%x" +pci_cfg_write(const char *dev, uint32_t bus, uint32_t slot, uint32_t func, unsigned offs, unsigned val) "%s %02x:%02x.%x @0x%x <- 0x%x" # msix.c msix_write_config(char *name, bool enabled, bool masked) "dev %s enabled %d masked %d" From b7107e758f4ecdd8f07ede3f093cbbfdb623e865 Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Thu, 11 Nov 2021 18:33:45 +0300 Subject: [PATCH 222/730] vhost-user-blk: reconnect on any error during realize vhost-user-blk realize only attempts to reconnect if the previous connection attempt failed on "a problem with the connection and not an error related to the content (which would fail again the same way in the next attempt)". However this distinction is very subtle, and may be inadvertently broken if the code changes somewhere deep down the stack and a new error gets propagated up to here. OTOH now that the number of reconnection attempts is limited it seems harmless to try reconnecting on any error. So relax the condition of whether to retry connecting to check for any error. This patch amends a527e312b5 "vhost-user-blk: Implement reconnection during realize". Signed-off-by: Roman Kagan Message-Id: <20211111153354.18807-2-rvkagan@yandex-team.ru> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Raphael Norwitz --- hw/block/vhost-user-blk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index ba13cb87e5..f9b17f6813 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -511,7 +511,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) *errp = NULL; } ret = vhost_user_blk_realize_connect(s, errp); - } while (ret == -EPROTO && retries--); + } while (ret < 0 && retries--); if (ret < 0) { goto virtio_err; From e87975051ee6071dec12d318e45a28d4770c2dd0 Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Thu, 11 Nov 2021 18:33:46 +0300 Subject: [PATCH 223/730] chardev/char-socket: tcp_chr_recv: don't clobber errno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tcp_chr_recv communicates the specific error condition to the caller via errno. However, after setting it, it may call into some system calls or library functions which can clobber the errno. Avoid this by moving the errno assignment to the end of the function. Signed-off-by: Roman Kagan Message-Id: <20211111153354.18807-3-rvkagan@yandex-team.ru> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Marc-André Lureau --- chardev/char-socket.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/chardev/char-socket.c b/chardev/char-socket.c index d619088232..3ddd98ed49 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -290,13 +290,6 @@ static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len) NULL); } - if (ret == QIO_CHANNEL_ERR_BLOCK) { - errno = EAGAIN; - ret = -1; - } else if (ret == -1) { - errno = EIO; - } - if (msgfds_num) { /* close and clean read_msgfds */ for (i = 0; i < s->read_msgfds_num; i++) { @@ -325,6 +318,13 @@ static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len) #endif } + if (ret == QIO_CHANNEL_ERR_BLOCK) { + errno = EAGAIN; + ret = -1; + } else if (ret == -1) { + errno = EIO; + } + return ret; } From 666265036fec3fd3eed2d55ae828c915a084a1d6 Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Thu, 11 Nov 2021 18:33:47 +0300 Subject: [PATCH 224/730] chardev/char-socket: tcp_chr_sync_read: don't clobber errno MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the return from tcp_chr_recv, tcp_chr_sync_read calls into a function which eventually makes a system call and may clobber errno. Make a copy of errno right after tcp_chr_recv and restore the errno on return from tcp_chr_sync_read. Signed-off-by: Roman Kagan Message-Id: <20211111153354.18807-4-rvkagan@yandex-team.ru> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Marc-André Lureau --- chardev/char-socket.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/chardev/char-socket.c b/chardev/char-socket.c index 3ddd98ed49..fab2d791d4 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -525,6 +525,7 @@ static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len) { SocketChardev *s = SOCKET_CHARDEV(chr); int size; + int saved_errno; if (s->state != TCP_CHARDEV_STATE_CONNECTED) { return 0; @@ -532,6 +533,7 @@ static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len) qio_channel_set_blocking(s->ioc, true, NULL); size = tcp_chr_recv(chr, (void *) buf, len); + saved_errno = errno; if (s->state != TCP_CHARDEV_STATE_DISCONNECTED) { qio_channel_set_blocking(s->ioc, false, NULL); } @@ -540,6 +542,7 @@ static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len) tcp_chr_disconnect(chr); } + errno = saved_errno; return size; } From 6dcae534e82520aa2280009de4b78a19059e8bbb Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Thu, 11 Nov 2021 18:33:49 +0300 Subject: [PATCH 225/730] vhost-backend: avoid overflow on memslots_limit Fix the (hypothetical) potential problem when the value parsed out of the vhost module parameter in sysfs overflows the return value from vhost_kernel_memslots_limit. Signed-off-by: Roman Kagan Message-Id: <20211111153354.18807-6-rvkagan@yandex-team.ru> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost-backend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index b65f8f7e97..44f7dbb243 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -58,7 +58,7 @@ static int vhost_kernel_memslots_limit(struct vhost_dev *dev) if (g_file_get_contents("/sys/module/vhost/parameters/max_mem_regions", &s, NULL, NULL)) { uint64_t val = g_ascii_strtoull(s, NULL, 10); - if (!((val == G_MAXUINT64 || !val) && errno)) { + if (val < INT_MAX && val > 0) { g_free(s); return val; } From 2d88d9c65cc9680ff33cf8cc0b71ab1532e2f394 Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Thu, 11 Nov 2021 18:33:50 +0300 Subject: [PATCH 226/730] vhost-backend: stick to -errno error return convention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Almost all VhostOps methods in kernel_ops follow the convention of returning negated errno on error. Adjust the only one that doesn't. Signed-off-by: Roman Kagan Message-Id: <20211111153354.18807-7-rvkagan@yandex-team.ru> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Philippe Mathieu-Daudé --- hw/virtio/vhost-backend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index 44f7dbb243..e409a865ae 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -47,7 +47,7 @@ static int vhost_kernel_cleanup(struct vhost_dev *dev) assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_KERNEL); - return close(fd); + return close(fd) < 0 ? -errno : 0; } static int vhost_kernel_memslots_limit(struct vhost_dev *dev) From 3631151b3e3c53ce70c370e68241e9876e2dbb3a Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Thu, 11 Nov 2021 18:33:51 +0300 Subject: [PATCH 227/730] vhost-vdpa: stick to -errno error return convention Almost all VhostOps methods in vdpa_ops follow the convention of returning negated errno on error. Adjust the few that don't. To that end, rework vhost_vdpa_add_status to check if setting of the requested status bits has succeeded and return the respective error code it hasn't, and propagate the error codes wherever it's appropriate. Signed-off-by: Roman Kagan Message-Id: <20211111153354.18807-8-rvkagan@yandex-team.ru> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost-vdpa.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index 0a4a83713c..ac0cb575fb 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -292,18 +292,34 @@ static int vhost_vdpa_call(struct vhost_dev *dev, unsigned long int request, return ret < 0 ? -errno : ret; } -static void vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status) +static int vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status) { uint8_t s; + int ret; trace_vhost_vdpa_add_status(dev, status); - if (vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &s)) { - return; + ret = vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &s); + if (ret < 0) { + return ret; } s |= status; - vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &s); + ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &s); + if (ret < 0) { + return ret; + } + + ret = vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &s); + if (ret < 0) { + return ret; + } + + if (!(s & status)) { + return -EIO; + } + + return 0; } static void vhost_vdpa_get_iova_range(struct vhost_vdpa *v) @@ -484,7 +500,7 @@ static int vhost_vdpa_set_mem_table(struct vhost_dev *dev, } } if (mem->padding) { - return -1; + return -EINVAL; } return 0; @@ -501,14 +517,11 @@ static int vhost_vdpa_set_features(struct vhost_dev *dev, trace_vhost_vdpa_set_features(dev, features); ret = vhost_vdpa_call(dev, VHOST_SET_FEATURES, &features); - uint8_t status = 0; if (ret) { return ret; } - vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); - vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status); - return !(status & VIRTIO_CONFIG_S_FEATURES_OK); + return vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); } static int vhost_vdpa_set_backend_cap(struct vhost_dev *dev) @@ -650,12 +663,8 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) } if (started) { - uint8_t status = 0; memory_listener_register(&v->listener, &address_space_memory); - vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); - vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status); - - return !(status & VIRTIO_CONFIG_S_DRIVER_OK); + return vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); } else { vhost_vdpa_reset_device(dev); vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE | From 025faa872bcf919259465419bee443b8a3ce3da1 Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Thu, 11 Nov 2021 18:33:52 +0300 Subject: [PATCH 228/730] vhost-user: stick to -errno error return convention VhostOps methods in user_ops are not very consistent in their error returns: some return negated errno while others just -1. Make sure all of them consistently return negated errno. This also helps error propagation from the functions being called inside. Besides, this synchronizes the error return convention with the other two vhost backends, kernel and vdpa, and will therefore allow for consistent error propagation in the generic vhost code (in a followup patch). Signed-off-by: Roman Kagan Message-Id: <20211111153354.18807-9-rvkagan@yandex-team.ru> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost-user.c | 401 +++++++++++++++++++++++------------------ 1 file changed, 223 insertions(+), 178 deletions(-) diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index bf6e50223c..662853513e 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -280,9 +280,10 @@ static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg) r = qemu_chr_fe_read_all(chr, p, size); if (r != size) { + int saved_errno = errno; error_report("Failed to read msg header. Read %d instead of %d." " Original request %d.", r, size, msg->hdr.request); - return -1; + return r < 0 ? -saved_errno : -EIO; } /* validate received flags */ @@ -290,7 +291,7 @@ static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg) error_report("Failed to read msg header." " Flags 0x%x instead of 0x%x.", msg->hdr.flags, VHOST_USER_REPLY_MASK | VHOST_USER_VERSION); - return -1; + return -EPROTO; } return 0; @@ -314,8 +315,9 @@ static gboolean vhost_user_read_cb(void *do_not_use, GIOCondition condition, uint8_t *p = (uint8_t *) msg; int r, size; - if (vhost_user_read_header(dev, msg) < 0) { - data->ret = -1; + r = vhost_user_read_header(dev, msg); + if (r < 0) { + data->ret = r; goto end; } @@ -324,7 +326,7 @@ static gboolean vhost_user_read_cb(void *do_not_use, GIOCondition condition, error_report("Failed to read msg header." " Size %d exceeds the maximum %zu.", msg->hdr.size, VHOST_USER_PAYLOAD_SIZE); - data->ret = -1; + data->ret = -EPROTO; goto end; } @@ -333,9 +335,10 @@ static gboolean vhost_user_read_cb(void *do_not_use, GIOCondition condition, size = msg->hdr.size; r = qemu_chr_fe_read_all(chr, p, size); if (r != size) { + int saved_errno = errno; error_report("Failed to read msg payload." " Read %d instead of %d.", r, msg->hdr.size); - data->ret = -1; + data->ret = r < 0 ? -saved_errno : -EIO; goto end; } } @@ -418,24 +421,26 @@ static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg) static int process_message_reply(struct vhost_dev *dev, const VhostUserMsg *msg) { + int ret; VhostUserMsg msg_reply; if ((msg->hdr.flags & VHOST_USER_NEED_REPLY_MASK) == 0) { return 0; } - if (vhost_user_read(dev, &msg_reply) < 0) { - return -1; + ret = vhost_user_read(dev, &msg_reply); + if (ret < 0) { + return ret; } if (msg_reply.hdr.request != msg->hdr.request) { error_report("Received unexpected msg type. " "Expected %d received %d", msg->hdr.request, msg_reply.hdr.request); - return -1; + return -EPROTO; } - return msg_reply.payload.u64 ? -1 : 0; + return msg_reply.payload.u64 ? -EIO : 0; } static bool vhost_user_one_time_request(VhostUserRequest request) @@ -472,14 +477,15 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg, if (qemu_chr_fe_set_msgfds(chr, fds, fd_num) < 0) { error_report("Failed to set msg fds."); - return -1; + return -EINVAL; } ret = qemu_chr_fe_write_all(chr, (const uint8_t *) msg, size); if (ret != size) { + int saved_errno = errno; error_report("Failed to write msg." " Wrote %d instead of %d.", ret, size); - return -1; + return ret < 0 ? -saved_errno : -EIO; } return 0; @@ -502,6 +508,7 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, size_t fd_num = 0; bool shmfd = virtio_has_feature(dev->protocol_features, VHOST_USER_PROTOCOL_F_LOG_SHMFD); + int ret; VhostUserMsg msg = { .hdr.request = VHOST_USER_SET_LOG_BASE, .hdr.flags = VHOST_USER_VERSION, @@ -514,21 +521,23 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, fds[fd_num++] = log->fd; } - if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { - return -1; + ret = vhost_user_write(dev, &msg, fds, fd_num); + if (ret < 0) { + return ret; } if (shmfd) { msg.hdr.size = 0; - if (vhost_user_read(dev, &msg) < 0) { - return -1; + ret = vhost_user_read(dev, &msg); + if (ret < 0) { + return ret; } if (msg.hdr.request != VHOST_USER_SET_LOG_BASE) { error_report("Received unexpected msg type. " "Expected %d received %d", VHOST_USER_SET_LOG_BASE, msg.hdr.request); - return -1; + return -EPROTO; } } @@ -588,7 +597,7 @@ static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u, u->region_rb[i] = mr->ram_block; } else if (*fd_num == VHOST_MEMORY_BASELINE_NREGIONS) { error_report("Failed preparing vhost-user memory table msg"); - return -1; + return -ENOBUFS; } vhost_user_fill_msg_region(®ion_buffer, reg, offset); msg->payload.memory.regions[*fd_num] = region_buffer; @@ -604,14 +613,14 @@ static int vhost_user_fill_set_mem_table_msg(struct vhost_user *u, if (!*fd_num) { error_report("Failed initializing vhost-user memory map, " "consider using -object memory-backend-file share=on"); - return -1; + return -EINVAL; } msg->hdr.size = sizeof(msg->payload.memory.nregions); msg->hdr.size += sizeof(msg->payload.memory.padding); msg->hdr.size += *fd_num * sizeof(VhostUserMemoryRegion); - return 1; + return 0; } static inline bool reg_equal(struct vhost_memory_region *shadow_reg, @@ -741,8 +750,9 @@ static int send_remove_regions(struct vhost_dev *dev, vhost_user_fill_msg_region(®ion_buffer, shadow_reg, 0); msg->payload.mem_reg.region = region_buffer; - if (vhost_user_write(dev, msg, &fd, 1) < 0) { - return -1; + ret = vhost_user_write(dev, msg, &fd, 1); + if (ret < 0) { + return ret; } if (reply_supported) { @@ -801,15 +811,17 @@ static int send_add_regions(struct vhost_dev *dev, vhost_user_fill_msg_region(®ion_buffer, reg, offset); msg->payload.mem_reg.region = region_buffer; - if (vhost_user_write(dev, msg, &fd, 1) < 0) { - return -1; + ret = vhost_user_write(dev, msg, &fd, 1); + if (ret < 0) { + return ret; } if (track_ramblocks) { uint64_t reply_gpa; - if (vhost_user_read(dev, &msg_reply) < 0) { - return -1; + ret = vhost_user_read(dev, &msg_reply); + if (ret < 0) { + return ret; } reply_gpa = msg_reply.payload.mem_reg.region.guest_phys_addr; @@ -819,7 +831,7 @@ static int send_add_regions(struct vhost_dev *dev, "Expected %d received %d", __func__, VHOST_USER_ADD_MEM_REG, msg_reply.hdr.request); - return -1; + return -EPROTO; } /* @@ -830,7 +842,7 @@ static int send_add_regions(struct vhost_dev *dev, error_report("%s: Unexpected size for postcopy reply " "%d vs %d", __func__, msg_reply.hdr.size, msg->hdr.size); - return -1; + return -EPROTO; } /* Get the postcopy client base from the backend's reply. */ @@ -846,7 +858,7 @@ static int send_add_regions(struct vhost_dev *dev, "Got guest physical address %" PRIX64 ", expected " "%" PRIX64, __func__, reply_gpa, dev->mem->regions[reg_idx].guest_phys_addr); - return -1; + return -EPROTO; } } else if (reply_supported) { ret = process_message_reply(dev, msg); @@ -887,6 +899,7 @@ static int vhost_user_add_remove_regions(struct vhost_dev *dev, struct scrub_regions rem_reg[VHOST_USER_MAX_RAM_SLOTS]; uint64_t shadow_pcb[VHOST_USER_MAX_RAM_SLOTS] = {}; int nr_add_reg, nr_rem_reg; + int ret; msg->hdr.size = sizeof(msg->payload.mem_reg); @@ -894,16 +907,20 @@ static int vhost_user_add_remove_regions(struct vhost_dev *dev, scrub_shadow_regions(dev, add_reg, &nr_add_reg, rem_reg, &nr_rem_reg, shadow_pcb, track_ramblocks); - if (nr_rem_reg && send_remove_regions(dev, rem_reg, nr_rem_reg, msg, - reply_supported) < 0) - { - goto err; + if (nr_rem_reg) { + ret = send_remove_regions(dev, rem_reg, nr_rem_reg, msg, + reply_supported); + if (ret < 0) { + goto err; + } } - if (nr_add_reg && send_add_regions(dev, add_reg, nr_add_reg, msg, - shadow_pcb, reply_supported, track_ramblocks) < 0) - { - goto err; + if (nr_add_reg) { + ret = send_add_regions(dev, add_reg, nr_add_reg, msg, shadow_pcb, + reply_supported, track_ramblocks); + if (ret < 0) { + goto err; + } } if (track_ramblocks) { @@ -918,8 +935,9 @@ static int vhost_user_add_remove_regions(struct vhost_dev *dev, msg->hdr.size = sizeof(msg->payload.u64); msg->payload.u64 = 0; /* OK */ - if (vhost_user_write(dev, msg, NULL, 0) < 0) { - return -1; + ret = vhost_user_write(dev, msg, NULL, 0); + if (ret < 0) { + return ret; } } @@ -931,7 +949,7 @@ err: sizeof(uint64_t) * VHOST_USER_MAX_RAM_SLOTS); } - return -1; + return ret; } static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, @@ -944,6 +962,7 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, size_t fd_num = 0; VhostUserMsg msg_reply; int region_i, msg_i; + int ret; VhostUserMsg msg = { .hdr.flags = VHOST_USER_VERSION, @@ -961,29 +980,32 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, } if (config_mem_slots) { - if (vhost_user_add_remove_regions(dev, &msg, reply_supported, - true) < 0) { - return -1; + ret = vhost_user_add_remove_regions(dev, &msg, reply_supported, true); + if (ret < 0) { + return ret; } } else { - if (vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, - true) < 0) { - return -1; + ret = vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, + true); + if (ret < 0) { + return ret; } - if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { - return -1; + ret = vhost_user_write(dev, &msg, fds, fd_num); + if (ret < 0) { + return ret; } - if (vhost_user_read(dev, &msg_reply) < 0) { - return -1; + ret = vhost_user_read(dev, &msg_reply); + if (ret < 0) { + return ret; } if (msg_reply.hdr.request != VHOST_USER_SET_MEM_TABLE) { error_report("%s: Received unexpected msg type." "Expected %d received %d", __func__, VHOST_USER_SET_MEM_TABLE, msg_reply.hdr.request); - return -1; + return -EPROTO; } /* @@ -994,7 +1016,7 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, error_report("%s: Unexpected size for postcopy reply " "%d vs %d", __func__, msg_reply.hdr.size, msg.hdr.size); - return -1; + return -EPROTO; } memset(u->postcopy_client_bases, 0, @@ -1024,7 +1046,7 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, error_report("%s: postcopy reply not fully consumed " "%d vs %zd", __func__, msg_i, fd_num); - return -1; + return -EIO; } /* @@ -1035,8 +1057,9 @@ static int vhost_user_set_mem_table_postcopy(struct vhost_dev *dev, /* TODO: Use this for failure cases as well with a bad value. */ msg.hdr.size = sizeof(msg.payload.u64); msg.payload.u64 = 0; /* OK */ - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -1; + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { + return ret; } } @@ -1055,6 +1078,7 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, bool config_mem_slots = virtio_has_feature(dev->protocol_features, VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS); + int ret; if (do_postcopy) { /* @@ -1074,17 +1098,20 @@ static int vhost_user_set_mem_table(struct vhost_dev *dev, } if (config_mem_slots) { - if (vhost_user_add_remove_regions(dev, &msg, reply_supported, - false) < 0) { - return -1; + ret = vhost_user_add_remove_regions(dev, &msg, reply_supported, false); + if (ret < 0) { + return ret; } } else { - if (vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, - false) < 0) { - return -1; + ret = vhost_user_fill_set_mem_table_msg(u, dev, &msg, fds, &fd_num, + false); + if (ret < 0) { + return ret; } - if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { - return -1; + + ret = vhost_user_write(dev, &msg, fds, fd_num); + if (ret < 0) { + return ret; } if (reply_supported) { @@ -1109,14 +1136,10 @@ static int vhost_user_set_vring_endian(struct vhost_dev *dev, if (!cross_endian) { error_report("vhost-user trying to send unhandled ioctl"); - return -1; + return -ENOTSUP; } - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -1; - } - - return 0; + return vhost_user_write(dev, &msg, NULL, 0); } static int vhost_set_vring(struct vhost_dev *dev, @@ -1130,11 +1153,7 @@ static int vhost_set_vring(struct vhost_dev *dev, .hdr.size = sizeof(msg.payload.state), }; - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -1; - } - - return 0; + return vhost_user_write(dev, &msg, NULL, 0); } static int vhost_user_set_vring_num(struct vhost_dev *dev, @@ -1182,16 +1201,25 @@ static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable) int i; if (!virtio_has_feature(dev->features, VHOST_USER_F_PROTOCOL_FEATURES)) { - return -1; + return -EINVAL; } for (i = 0; i < dev->nvqs; ++i) { + int ret; struct vhost_vring_state state = { .index = dev->vq_index + i, .num = enable, }; - vhost_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, &state); + ret = vhost_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, &state); + if (ret < 0) { + /* + * Restoring the previous state is likely infeasible, as well as + * proceeding regardless the error, so just bail out and hope for + * the device-level recovery. + */ + return ret; + } } return 0; @@ -1200,6 +1228,7 @@ static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable) static int vhost_user_get_vring_base(struct vhost_dev *dev, struct vhost_vring_state *ring) { + int ret; VhostUserMsg msg = { .hdr.request = VHOST_USER_GET_VRING_BASE, .hdr.flags = VHOST_USER_VERSION, @@ -1209,23 +1238,25 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev, vhost_user_host_notifier_remove(dev, ring->index); - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -1; + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { + return ret; } - if (vhost_user_read(dev, &msg) < 0) { - return -1; + ret = vhost_user_read(dev, &msg); + if (ret < 0) { + return ret; } if (msg.hdr.request != VHOST_USER_GET_VRING_BASE) { error_report("Received unexpected msg type. Expected %d received %d", VHOST_USER_GET_VRING_BASE, msg.hdr.request); - return -1; + return -EPROTO; } if (msg.hdr.size != sizeof(msg.payload.state)) { error_report("Received bad msg size."); - return -1; + return -EPROTO; } *ring = msg.payload.state; @@ -1252,11 +1283,7 @@ static int vhost_set_vring_file(struct vhost_dev *dev, msg.payload.u64 |= VHOST_USER_VRING_NOFD_MASK; } - if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { - return -1; - } - - return 0; + return vhost_user_write(dev, &msg, fds, fd_num); } static int vhost_user_set_vring_kick(struct vhost_dev *dev, @@ -1274,6 +1301,7 @@ static int vhost_user_set_vring_call(struct vhost_dev *dev, static int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64_t *u64) { + int ret; VhostUserMsg msg = { .hdr.request = request, .hdr.flags = VHOST_USER_VERSION, @@ -1283,23 +1311,25 @@ static int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64_t *u64) return 0; } - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -1; + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { + return ret; } - if (vhost_user_read(dev, &msg) < 0) { - return -1; + ret = vhost_user_read(dev, &msg); + if (ret < 0) { + return ret; } if (msg.hdr.request != request) { error_report("Received unexpected msg type. Expected %d received %d", request, msg.hdr.request); - return -1; + return -EPROTO; } if (msg.hdr.size != sizeof(msg.payload.u64)) { error_report("Received bad msg size."); - return -1; + return -EPROTO; } *u64 = msg.payload.u64; @@ -1337,6 +1367,7 @@ static int enforce_reply(struct vhost_dev *dev, static int vhost_user_set_vring_addr(struct vhost_dev *dev, struct vhost_vring_addr *addr) { + int ret; VhostUserMsg msg = { .hdr.request = VHOST_USER_SET_VRING_ADDR, .hdr.flags = VHOST_USER_VERSION, @@ -1357,8 +1388,9 @@ static int vhost_user_set_vring_addr(struct vhost_dev *dev, msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK; } - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -1; + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { + return ret; } if (wait_for_reply) { @@ -1377,6 +1409,7 @@ static int vhost_user_set_u64(struct vhost_dev *dev, int request, uint64_t u64, .payload.u64 = u64, .hdr.size = sizeof(msg.payload.u64), }; + int ret; if (wait_for_reply) { bool reply_supported = virtio_has_feature(dev->protocol_features, @@ -1386,8 +1419,9 @@ static int vhost_user_set_u64(struct vhost_dev *dev, int request, uint64_t u64, } } - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -1; + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { + return ret; } if (wait_for_reply) { @@ -1424,11 +1458,7 @@ static int vhost_user_set_owner(struct vhost_dev *dev) .hdr.flags = VHOST_USER_VERSION, }; - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -EPROTO; - } - - return 0; + return vhost_user_write(dev, &msg, NULL, 0); } static int vhost_user_get_max_memslots(struct vhost_dev *dev, @@ -1459,26 +1489,16 @@ static int vhost_user_reset_device(struct vhost_dev *dev) ? VHOST_USER_RESET_DEVICE : VHOST_USER_RESET_OWNER; - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -1; - } - - return 0; + return vhost_user_write(dev, &msg, NULL, 0); } static int vhost_user_slave_handle_config_change(struct vhost_dev *dev) { - int ret = -1; - - if (!dev->config_ops) { - return -1; + if (!dev->config_ops || !dev->config_ops->vhost_dev_config_notifier) { + return -ENOSYS; } - if (dev->config_ops->vhost_dev_config_notifier) { - ret = dev->config_ops->vhost_dev_config_notifier(dev); - } - - return ret; + return dev->config_ops->vhost_dev_config_notifier(dev); } static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, @@ -1497,7 +1517,7 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, if (!virtio_has_feature(dev->protocol_features, VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) || vdev == NULL || queue_idx >= virtio_get_num_queues(vdev)) { - return -1; + return -EINVAL; } n = &user->notifier[queue_idx]; @@ -1515,13 +1535,13 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, /* Sanity check. */ if (area->size != page_size) { - return -1; + return -EINVAL; } addr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, area->offset); if (addr == MAP_FAILED) { - return -1; + return -EFAULT; } name = g_strdup_printf("vhost-user/host-notifier@%p mmaps[%d]", @@ -1534,7 +1554,7 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev, if (virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true)) { object_unparent(OBJECT(&n->mr)); munmap(addr, page_size); - return -1; + return -ENXIO; } n->addr = addr; @@ -1664,14 +1684,15 @@ static int vhost_setup_slave_channel(struct vhost_dev *dev) } if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { + int saved_errno = errno; error_report("socketpair() failed"); - return -1; + return -saved_errno; } ioc = QIO_CHANNEL(qio_channel_socket_new_fd(sv[0], &local_err)); if (!ioc) { error_report_err(local_err); - return -1; + return -ECONNREFUSED; } u->slave_ioc = ioc; slave_update_read_handler(dev, NULL); @@ -1778,35 +1799,38 @@ static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp) struct vhost_user *u = dev->opaque; CharBackend *chr = u->user->chr; int ufd; + int ret; VhostUserMsg msg = { .hdr.request = VHOST_USER_POSTCOPY_ADVISE, .hdr.flags = VHOST_USER_VERSION, }; - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { error_setg(errp, "Failed to send postcopy_advise to vhost"); - return -1; + return ret; } - if (vhost_user_read(dev, &msg) < 0) { + ret = vhost_user_read(dev, &msg); + if (ret < 0) { error_setg(errp, "Failed to get postcopy_advise reply from vhost"); - return -1; + return ret; } if (msg.hdr.request != VHOST_USER_POSTCOPY_ADVISE) { error_setg(errp, "Unexpected msg type. Expected %d received %d", VHOST_USER_POSTCOPY_ADVISE, msg.hdr.request); - return -1; + return -EPROTO; } if (msg.hdr.size) { error_setg(errp, "Received bad msg size."); - return -1; + return -EPROTO; } ufd = qemu_chr_fe_get_msgfd(chr); if (ufd < 0) { error_setg(errp, "%s: Failed to get ufd", __func__); - return -1; + return -EIO; } qemu_set_nonblock(ufd); @@ -1820,7 +1844,7 @@ static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp) return 0; #else error_setg(errp, "Postcopy not supported on non-Linux systems"); - return -1; + return -ENOSYS; #endif } @@ -1836,10 +1860,13 @@ static int vhost_user_postcopy_listen(struct vhost_dev *dev, Error **errp) .hdr.flags = VHOST_USER_VERSION | VHOST_USER_NEED_REPLY_MASK, }; u->postcopy_listen = true; + trace_vhost_user_postcopy_listen(); - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { + + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { error_setg(errp, "Failed to send postcopy_listen to vhost"); - return -1; + return ret; } ret = process_message_reply(dev, &msg); @@ -1864,9 +1891,11 @@ static int vhost_user_postcopy_end(struct vhost_dev *dev, Error **errp) struct vhost_user *u = dev->opaque; trace_vhost_user_postcopy_end_entry(); - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { + + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { error_setg(errp, "Failed to send postcopy_end to vhost"); - return -1; + return ret; } ret = process_message_reply(dev, &msg); @@ -2115,7 +2144,7 @@ static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr) return vhost_user_write(dev, &msg, NULL, 0); } - return -1; + return -ENOTSUP; } static bool vhost_user_can_merge(struct vhost_dev *dev, @@ -2136,6 +2165,7 @@ static int vhost_user_net_set_mtu(struct vhost_dev *dev, uint16_t mtu) VhostUserMsg msg; bool reply_supported = virtio_has_feature(dev->protocol_features, VHOST_USER_PROTOCOL_F_REPLY_ACK); + int ret; if (!(dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_NET_MTU))) { return 0; @@ -2149,8 +2179,9 @@ static int vhost_user_net_set_mtu(struct vhost_dev *dev, uint16_t mtu) msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK; } - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -1; + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { + return ret; } /* If reply_ack supported, slave has to ack specified MTU is valid */ @@ -2164,6 +2195,7 @@ static int vhost_user_net_set_mtu(struct vhost_dev *dev, uint16_t mtu) static int vhost_user_send_device_iotlb_msg(struct vhost_dev *dev, struct vhost_iotlb_msg *imsg) { + int ret; VhostUserMsg msg = { .hdr.request = VHOST_USER_IOTLB_MSG, .hdr.size = sizeof(msg.payload.iotlb), @@ -2171,8 +2203,9 @@ static int vhost_user_send_device_iotlb_msg(struct vhost_dev *dev, .payload.iotlb = *imsg, }; - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -EFAULT; + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { + return ret; } return process_message_reply(dev, &msg); @@ -2187,6 +2220,7 @@ static void vhost_user_set_iotlb_callback(struct vhost_dev *dev, int enabled) static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config, uint32_t config_len, Error **errp) { + int ret; VhostUserMsg msg = { .hdr.request = VHOST_USER_GET_CONFIG, .hdr.flags = VHOST_USER_VERSION, @@ -2203,26 +2237,28 @@ static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config, msg.payload.config.offset = 0; msg.payload.config.size = config_len; - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - error_setg_errno(errp, EPROTO, "vhost_get_config failed"); - return -EPROTO; + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { + error_setg_errno(errp, -ret, "vhost_get_config failed"); + return ret; } - if (vhost_user_read(dev, &msg) < 0) { - error_setg_errno(errp, EPROTO, "vhost_get_config failed"); - return -EPROTO; + ret = vhost_user_read(dev, &msg); + if (ret < 0) { + error_setg_errno(errp, -ret, "vhost_get_config failed"); + return ret; } if (msg.hdr.request != VHOST_USER_GET_CONFIG) { error_setg(errp, "Received unexpected msg type. Expected %d received %d", VHOST_USER_GET_CONFIG, msg.hdr.request); - return -EINVAL; + return -EPROTO; } if (msg.hdr.size != VHOST_USER_CONFIG_HDR_SIZE + config_len) { error_setg(errp, "Received bad msg size."); - return -EINVAL; + return -EPROTO; } memcpy(config, msg.payload.config.region, config_len); @@ -2233,6 +2269,7 @@ static int vhost_user_get_config(struct vhost_dev *dev, uint8_t *config, static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, uint32_t offset, uint32_t size, uint32_t flags) { + int ret; uint8_t *p; bool reply_supported = virtio_has_feature(dev->protocol_features, VHOST_USER_PROTOCOL_F_REPLY_ACK); @@ -2245,7 +2282,7 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, if (!virtio_has_feature(dev->protocol_features, VHOST_USER_PROTOCOL_F_CONFIG)) { - return -1; + return -ENOTSUP; } if (reply_supported) { @@ -2253,7 +2290,7 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, } if (size > VHOST_USER_MAX_CONFIG_SIZE) { - return -1; + return -EINVAL; } msg.payload.config.offset = offset, @@ -2262,8 +2299,9 @@ static int vhost_user_set_config(struct vhost_dev *dev, const uint8_t *data, p = msg.payload.config.region; memcpy(p, data, size); - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -1; + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { + return ret; } if (reply_supported) { @@ -2277,6 +2315,7 @@ static int vhost_user_crypto_create_session(struct vhost_dev *dev, void *session_info, uint64_t *session_id) { + int ret; bool crypto_session = virtio_has_feature(dev->protocol_features, VHOST_USER_PROTOCOL_F_CRYPTO_SESSION); CryptoDevBackendSymSessionInfo *sess_info = session_info; @@ -2290,7 +2329,7 @@ static int vhost_user_crypto_create_session(struct vhost_dev *dev, if (!crypto_session) { error_report("vhost-user trying to send unhandled ioctl"); - return -1; + return -ENOTSUP; } memcpy(&msg.payload.session.session_setup_data, sess_info, @@ -2303,31 +2342,35 @@ static int vhost_user_crypto_create_session(struct vhost_dev *dev, memcpy(&msg.payload.session.auth_key, sess_info->auth_key, sess_info->auth_key_len); } - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - error_report("vhost_user_write() return -1, create session failed"); - return -1; + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { + error_report("vhost_user_write() return %d, create session failed", + ret); + return ret; } - if (vhost_user_read(dev, &msg) < 0) { - error_report("vhost_user_read() return -1, create session failed"); - return -1; + ret = vhost_user_read(dev, &msg); + if (ret < 0) { + error_report("vhost_user_read() return %d, create session failed", + ret); + return ret; } if (msg.hdr.request != VHOST_USER_CREATE_CRYPTO_SESSION) { error_report("Received unexpected msg type. Expected %d received %d", VHOST_USER_CREATE_CRYPTO_SESSION, msg.hdr.request); - return -1; + return -EPROTO; } if (msg.hdr.size != sizeof(msg.payload.session)) { error_report("Received bad msg size."); - return -1; + return -EPROTO; } if (msg.payload.session.session_id < 0) { error_report("Bad session id: %" PRId64 "", msg.payload.session.session_id); - return -1; + return -EINVAL; } *session_id = msg.payload.session.session_id; @@ -2337,6 +2380,7 @@ static int vhost_user_crypto_create_session(struct vhost_dev *dev, static int vhost_user_crypto_close_session(struct vhost_dev *dev, uint64_t session_id) { + int ret; bool crypto_session = virtio_has_feature(dev->protocol_features, VHOST_USER_PROTOCOL_F_CRYPTO_SESSION); VhostUserMsg msg = { @@ -2348,12 +2392,14 @@ vhost_user_crypto_close_session(struct vhost_dev *dev, uint64_t session_id) if (!crypto_session) { error_report("vhost-user trying to send unhandled ioctl"); - return -1; + return -ENOTSUP; } - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - error_report("vhost_user_write() return -1, close session failed"); - return -1; + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { + error_report("vhost_user_write() return %d, close session failed", + ret); + return ret; } return 0; @@ -2375,6 +2421,7 @@ static int vhost_user_get_inflight_fd(struct vhost_dev *dev, { void *addr; int fd; + int ret; struct vhost_user *u = dev->opaque; CharBackend *chr = u->user->chr; VhostUserMsg msg = { @@ -2390,24 +2437,26 @@ static int vhost_user_get_inflight_fd(struct vhost_dev *dev, return 0; } - if (vhost_user_write(dev, &msg, NULL, 0) < 0) { - return -1; + ret = vhost_user_write(dev, &msg, NULL, 0); + if (ret < 0) { + return ret; } - if (vhost_user_read(dev, &msg) < 0) { - return -1; + ret = vhost_user_read(dev, &msg); + if (ret < 0) { + return ret; } if (msg.hdr.request != VHOST_USER_GET_INFLIGHT_FD) { error_report("Received unexpected msg type. " "Expected %d received %d", VHOST_USER_GET_INFLIGHT_FD, msg.hdr.request); - return -1; + return -EPROTO; } if (msg.hdr.size != sizeof(msg.payload.inflight)) { error_report("Received bad msg size."); - return -1; + return -EPROTO; } if (!msg.payload.inflight.mmap_size) { @@ -2417,7 +2466,7 @@ static int vhost_user_get_inflight_fd(struct vhost_dev *dev, fd = qemu_chr_fe_get_msgfd(chr); if (fd < 0) { error_report("Failed to get mem fd"); - return -1; + return -EIO; } addr = mmap(0, msg.payload.inflight.mmap_size, PROT_READ | PROT_WRITE, @@ -2426,7 +2475,7 @@ static int vhost_user_get_inflight_fd(struct vhost_dev *dev, if (addr == MAP_FAILED) { error_report("Failed to mmap mem fd"); close(fd); - return -1; + return -EFAULT; } inflight->addr = addr; @@ -2456,11 +2505,7 @@ static int vhost_user_set_inflight_fd(struct vhost_dev *dev, return 0; } - if (vhost_user_write(dev, &msg, &inflight->fd, 1) < 0) { - return -1; - } - - return 0; + return vhost_user_write(dev, &msg, &inflight->fd, 1); } bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp) From 5d33ae4b7a9a1f57cca4fde1dc8d16bc46d0f604 Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Thu, 11 Nov 2021 18:33:53 +0300 Subject: [PATCH 229/730] vhost: stick to -errno error return convention The generic vhost code expects that many of the VhostOps methods in the respective backends set errno on errors. However, none of the existing backends actually bothers to do so. In a number of those methods errno from the failed call is clobbered by successful later calls to some library functions; on a few code paths the generic vhost code then negates and returns that errno, thus making failures look as successes to the caller. As a result, in certain scenarios (e.g. live migration) the device doesn't notice the first failure and goes on through its state transitions as if everything is ok, instead of taking recovery actions (break and reestablish the vhost-user connection, cancel migration, etc) before it's too late. To fix this, consolidate on the convention to return negated errno on failures throughout generic vhost, and use it for error propagation. Signed-off-by: Roman Kagan Message-Id: <20211111153354.18807-10-rvkagan@yandex-team.ru> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost.c | 100 +++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 54 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 98a4b0a0df..cbf3b792da 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -33,11 +33,13 @@ #define _VHOST_DEBUG 1 #ifdef _VHOST_DEBUG -#define VHOST_OPS_DEBUG(fmt, ...) \ - do { error_report(fmt ": %s (%d)", ## __VA_ARGS__, \ - strerror(errno), errno); } while (0) +#define VHOST_OPS_DEBUG(retval, fmt, ...) \ + do { \ + error_report(fmt ": %s (%d)", ## __VA_ARGS__, \ + strerror(-retval), -retval); \ + } while (0) #else -#define VHOST_OPS_DEBUG(fmt, ...) \ +#define VHOST_OPS_DEBUG(retval, fmt, ...) \ do { } while (0) #endif @@ -297,7 +299,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) releasing the current log, to ensure no logging is lost */ r = dev->vhost_ops->vhost_set_log_base(dev, log_base, log); if (r < 0) { - VHOST_OPS_DEBUG("vhost_set_log_base failed"); + VHOST_OPS_DEBUG(r, "vhost_set_log_base failed"); } vhost_log_put(dev, true); @@ -550,7 +552,7 @@ static void vhost_commit(MemoryListener *listener) if (!dev->log_enabled) { r = dev->vhost_ops->vhost_set_mem_table(dev, dev->mem); if (r < 0) { - VHOST_OPS_DEBUG("vhost_set_mem_table failed"); + VHOST_OPS_DEBUG(r, "vhost_set_mem_table failed"); } goto out; } @@ -564,7 +566,7 @@ static void vhost_commit(MemoryListener *listener) } r = dev->vhost_ops->vhost_set_mem_table(dev, dev->mem); if (r < 0) { - VHOST_OPS_DEBUG("vhost_set_mem_table failed"); + VHOST_OPS_DEBUG(r, "vhost_set_mem_table failed"); } /* To log less, can only decrease log size after table update. */ if (dev->log_size > log_size + VHOST_LOG_BUFFER) { @@ -803,8 +805,8 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev, if (dev->vhost_ops->vhost_vq_get_addr) { r = dev->vhost_ops->vhost_vq_get_addr(dev, &addr, vq); if (r < 0) { - VHOST_OPS_DEBUG("vhost_vq_get_addr failed"); - return -errno; + VHOST_OPS_DEBUG(r, "vhost_vq_get_addr failed"); + return r; } } else { addr.desc_user_addr = (uint64_t)(unsigned long)vq->desc; @@ -816,10 +818,9 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev, addr.flags = enable_log ? (1 << VHOST_VRING_F_LOG) : 0; r = dev->vhost_ops->vhost_set_vring_addr(dev, &addr); if (r < 0) { - VHOST_OPS_DEBUG("vhost_set_vring_addr failed"); - return -errno; + VHOST_OPS_DEBUG(r, "vhost_set_vring_addr failed"); } - return 0; + return r; } static int vhost_dev_set_features(struct vhost_dev *dev, @@ -840,19 +841,19 @@ static int vhost_dev_set_features(struct vhost_dev *dev, } r = dev->vhost_ops->vhost_set_features(dev, features); if (r < 0) { - VHOST_OPS_DEBUG("vhost_set_features failed"); + VHOST_OPS_DEBUG(r, "vhost_set_features failed"); goto out; } if (dev->vhost_ops->vhost_set_backend_cap) { r = dev->vhost_ops->vhost_set_backend_cap(dev); if (r < 0) { - VHOST_OPS_DEBUG("vhost_set_backend_cap failed"); + VHOST_OPS_DEBUG(r, "vhost_set_backend_cap failed"); goto out; } } out: - return r < 0 ? -errno : 0; + return r; } static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log) @@ -999,22 +1000,17 @@ static int vhost_virtqueue_set_vring_endian_legacy(struct vhost_dev *dev, bool is_big_endian, int vhost_vq_index) { + int r; struct vhost_vring_state s = { .index = vhost_vq_index, .num = is_big_endian }; - if (!dev->vhost_ops->vhost_set_vring_endian(dev, &s)) { - return 0; + r = dev->vhost_ops->vhost_set_vring_endian(dev, &s); + if (r < 0) { + VHOST_OPS_DEBUG(r, "vhost_set_vring_endian failed"); } - - VHOST_OPS_DEBUG("vhost_set_vring_endian failed"); - if (errno == ENOTTY) { - error_report("vhost does not support cross-endian"); - return -ENOSYS; - } - - return -errno; + return r; } static int vhost_memory_region_lookup(struct vhost_dev *hdev, @@ -1106,15 +1102,15 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, vq->num = state.num = virtio_queue_get_num(vdev, idx); r = dev->vhost_ops->vhost_set_vring_num(dev, &state); if (r) { - VHOST_OPS_DEBUG("vhost_set_vring_num failed"); - return -errno; + VHOST_OPS_DEBUG(r, "vhost_set_vring_num failed"); + return r; } state.num = virtio_queue_get_last_avail_idx(vdev, idx); r = dev->vhost_ops->vhost_set_vring_base(dev, &state); if (r) { - VHOST_OPS_DEBUG("vhost_set_vring_base failed"); - return -errno; + VHOST_OPS_DEBUG(r, "vhost_set_vring_base failed"); + return r; } if (vhost_needs_vring_endian(vdev)) { @@ -1122,7 +1118,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, virtio_is_big_endian(vdev), vhost_vq_index); if (r) { - return -errno; + return r; } } @@ -1150,15 +1146,13 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev->log_enabled); if (r < 0) { - r = -errno; goto fail_alloc; } file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq)); r = dev->vhost_ops->vhost_set_vring_kick(dev, &file); if (r) { - VHOST_OPS_DEBUG("vhost_set_vring_kick failed"); - r = -errno; + VHOST_OPS_DEBUG(r, "vhost_set_vring_kick failed"); goto fail_kick; } @@ -1218,7 +1212,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev, r = dev->vhost_ops->vhost_get_vring_base(dev, &state); if (r < 0) { - VHOST_OPS_DEBUG("vhost VQ %u ring restore failed: %d", idx, r); + VHOST_OPS_DEBUG(r, "vhost VQ %u ring restore failed: %d", idx, r); /* Connection to the backend is broken, so let's sync internal * last avail idx to the device used idx. */ @@ -1274,7 +1268,7 @@ static int vhost_virtqueue_set_busyloop_timeout(struct vhost_dev *dev, r = dev->vhost_ops->vhost_set_vring_busyloop_timeout(dev, &state); if (r) { - VHOST_OPS_DEBUG("vhost_set_vring_busyloop_timeout failed"); + VHOST_OPS_DEBUG(r, "vhost_set_vring_busyloop_timeout failed"); return r; } @@ -1296,8 +1290,7 @@ static int vhost_virtqueue_init(struct vhost_dev *dev, file.fd = event_notifier_get_fd(&vq->masked_notifier); r = dev->vhost_ops->vhost_set_vring_call(dev, &file); if (r) { - VHOST_OPS_DEBUG("vhost_set_vring_call failed"); - r = -errno; + VHOST_OPS_DEBUG(r, "vhost_set_vring_call failed"); goto fail_call; } @@ -1557,7 +1550,7 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, file.index = hdev->vhost_ops->vhost_get_vq_index(hdev, n); r = hdev->vhost_ops->vhost_set_vring_call(hdev, &file); if (r < 0) { - VHOST_OPS_DEBUG("vhost_set_vring_call failed"); + VHOST_OPS_DEBUG(r, "vhost_set_vring_call failed"); } } @@ -1595,7 +1588,7 @@ void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask) } r = hdev->vhost_ops->vhost_set_config_call(hdev, fd); if (r < 0) { - VHOST_OPS_DEBUG("vhost_set_config_call failed"); + VHOST_OPS_DEBUG(r, "vhost_set_config_call failed"); } } @@ -1660,7 +1653,7 @@ int vhost_dev_get_config(struct vhost_dev *hdev, uint8_t *config, } error_setg(errp, "vhost_get_config not implemented"); - return -ENOTSUP; + return -ENOSYS; } int vhost_dev_set_config(struct vhost_dev *hdev, const uint8_t *data, @@ -1673,7 +1666,7 @@ int vhost_dev_set_config(struct vhost_dev *hdev, const uint8_t *data, size, flags); } - return -1; + return -ENOSYS; } void vhost_dev_set_config_notifier(struct vhost_dev *hdev, @@ -1702,7 +1695,7 @@ static int vhost_dev_resize_inflight(struct vhost_inflight *inflight, if (err) { error_report_err(err); - return -1; + return -ENOMEM; } vhost_dev_free_inflight(inflight); @@ -1735,8 +1728,9 @@ int vhost_dev_load_inflight(struct vhost_inflight *inflight, QEMUFile *f) } if (inflight->size != size) { - if (vhost_dev_resize_inflight(inflight, size)) { - return -1; + int ret = vhost_dev_resize_inflight(inflight, size); + if (ret < 0) { + return ret; } } inflight->queue_size = qemu_get_be16(f); @@ -1759,7 +1753,7 @@ int vhost_dev_prepare_inflight(struct vhost_dev *hdev, VirtIODevice *vdev) r = vhost_dev_set_features(hdev, hdev->log_enabled); if (r < 0) { - VHOST_OPS_DEBUG("vhost_dev_prepare_inflight failed"); + VHOST_OPS_DEBUG(r, "vhost_dev_prepare_inflight failed"); return r; } @@ -1774,8 +1768,8 @@ int vhost_dev_set_inflight(struct vhost_dev *dev, if (dev->vhost_ops->vhost_set_inflight_fd && inflight->addr) { r = dev->vhost_ops->vhost_set_inflight_fd(dev, inflight); if (r) { - VHOST_OPS_DEBUG("vhost_set_inflight_fd failed"); - return -errno; + VHOST_OPS_DEBUG(r, "vhost_set_inflight_fd failed"); + return r; } } @@ -1790,8 +1784,8 @@ int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size, if (dev->vhost_ops->vhost_get_inflight_fd) { r = dev->vhost_ops->vhost_get_inflight_fd(dev, queue_size, inflight); if (r) { - VHOST_OPS_DEBUG("vhost_get_inflight_fd failed"); - return -errno; + VHOST_OPS_DEBUG(r, "vhost_get_inflight_fd failed"); + return r; } } @@ -1820,8 +1814,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) r = hdev->vhost_ops->vhost_set_mem_table(hdev, hdev->mem); if (r < 0) { - VHOST_OPS_DEBUG("vhost_set_mem_table failed"); - r = -errno; + VHOST_OPS_DEBUG(r, "vhost_set_mem_table failed"); goto fail_mem; } for (i = 0; i < hdev->nvqs; ++i) { @@ -1855,8 +1848,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) hdev->log_size ? log_base : 0, hdev->log); if (r < 0) { - VHOST_OPS_DEBUG("vhost_set_log_base failed"); - r = -errno; + VHOST_OPS_DEBUG(r, "vhost_set_log_base failed"); goto fail_log; } } @@ -1936,5 +1928,5 @@ int vhost_net_set_backend(struct vhost_dev *hdev, return hdev->vhost_ops->vhost_net_set_backend(hdev, file); } - return -1; + return -ENOSYS; } From fb767859345506d747876c23d181155b183f8e94 Mon Sep 17 00:00:00 2001 From: Roman Kagan Date: Thu, 11 Nov 2021 18:33:54 +0300 Subject: [PATCH 230/730] vhost-user-blk: propagate error return from generic vhost Fix the only callsite that doesn't propagate the error code from the generic vhost code. Signed-off-by: Roman Kagan Message-Id: <20211111153354.18807-11-rvkagan@yandex-team.ru> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Raphael Norwitz --- hw/block/vhost-user-blk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index f9b17f6813..ab11ce8252 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -100,7 +100,7 @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev) &local_err); if (ret < 0) { error_report_err(local_err); - return -1; + return ret; } /* valid for resize only */ From 2fedf46e34d2377760b2d26cf85487b772bca6fa Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Tue, 16 Nov 2021 18:01:32 +0100 Subject: [PATCH 231/730] pci: Export the pci_intx() function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the pci_intx() definition to the PCI header file, so that it can be called from other PCI files. It is used by the next patch. Signed-off-by: Frederic Barrat Message-Id: <20211116170133.724751-3-fbarrat@linux.ibm.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Cédric Le Goater --- hw/pci/pci.c | 5 ----- include/hw/pci/pci.h | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 322ba450e7..5d30f9ca60 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1497,11 +1497,6 @@ static void pci_irq_handler(void *opaque, int irq_num, int level) pci_change_irq_level(pci_dev, irq_num, change); } -static inline int pci_intx(PCIDevice *pci_dev) -{ - return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1; -} - qemu_irq pci_allocate_irq(PCIDevice *pci_dev) { int intx = pci_intx(pci_dev); diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 5b36334a28..483d5c7c72 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -735,6 +735,11 @@ void lsi53c8xx_handle_legacy_cmdline(DeviceState *lsi_dev); qemu_irq pci_allocate_irq(PCIDevice *pci_dev); void pci_set_irq(PCIDevice *pci_dev, int level); +static inline int pci_intx(PCIDevice *pci_dev) +{ + return pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1; +} + static inline void pci_irq_assert(PCIDevice *pci_dev) { pci_set_irq(pci_dev, 1); From 20766514d602c50b870ae943aaa8e5b9e2e8a161 Mon Sep 17 00:00:00 2001 From: Frederic Barrat Date: Tue, 16 Nov 2021 18:01:33 +0100 Subject: [PATCH 232/730] pcie_aer: Don't trigger a LSI if none are defined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Skip triggering an LSI when the AER root error status is updated if no LSI is defined for the device. We can have a root bridge with no LSI, MSI and MSI-X defined, for example on POWER systems. Signed-off-by: Frederic Barrat Message-Id: <20211116170133.724751-4-fbarrat@linux.ibm.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Cédric Le Goater --- hw/pci/pcie_aer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c index 27f9cc56af..e1a8a88c8c 100644 --- a/hw/pci/pcie_aer.c +++ b/hw/pci/pcie_aer.c @@ -774,7 +774,9 @@ void pcie_aer_root_write_config(PCIDevice *dev, uint32_t root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND); /* 6.2.4.1.2 Interrupt Generation */ if (!msix_enabled(dev) && !msi_enabled(dev)) { - pci_set_irq(dev, !!(root_cmd & enabled_cmd)); + if (pci_intx(dev) != -1) { + pci_set_irq(dev, !!(root_cmd & enabled_cmd)); + } return; } From 10be11d0b48f508646509844bc32b983d4204d2b Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Tue, 26 Oct 2021 11:10:58 -0400 Subject: [PATCH 233/730] smbios: Rename SMBIOS_ENTRY_POINT_* enums MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the enums to match the naming style used by QAPI, and to use "32" and "64" instead of "20" and "31". This will allow us to more easily move the enum to the QAPI schema later. About the naming choice: "SMBIOS 2.1 entry point"/"SMBIOS 3.0 entry point" and "32-bit entry point"/"64-bit entry point" are synonymous in the SMBIOS specification. However, the phrases "32-bit entry point" and "64-bit entry point" are used more often. The new names also avoid confusion between the entry point format and the actual SMBIOS version reported in the entry point structure. For example: currently the 32-bit entry point actually report SMBIOS 2.8 support, not 2.1. Based on portions of a patch submitted by Daniel P. Berrangé. Signed-off-by: Eduardo Habkost Message-Id: <20211026151100.1691925-2-ehabkost@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/arm/virt.c | 2 +- hw/i386/pc_piix.c | 2 +- hw/i386/pc_q35.c | 2 +- hw/smbios/smbios.c | 8 ++++---- include/hw/firmware/smbios.h | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 4593fea1ce..b45b52c90e 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1589,7 +1589,7 @@ static void virt_build_smbios(VirtMachineState *vms) smbios_set_defaults("QEMU", product, vmc->smbios_old_sys_ver ? "1.0" : mc->name, false, - true, SMBIOS_ENTRY_POINT_30); + true, SMBIOS_ENTRY_POINT_TYPE_64); smbios_get_tables(MACHINE(vms), NULL, 0, &smbios_tables, &smbios_tables_len, diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 1999190276..25f918b609 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -177,7 +177,7 @@ static void pc_init1(MachineState *machine, smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)", mc->name, pcmc->smbios_legacy_mode, pcmc->smbios_uuid_encoded, - SMBIOS_ENTRY_POINT_21); + SMBIOS_ENTRY_POINT_TYPE_32); } /* allocate ram and load rom/bios */ diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 2e981f436c..1103fbcd90 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -200,7 +200,7 @@ static void pc_q35_init(MachineState *machine) smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)", mc->name, pcmc->smbios_legacy_mode, pcmc->smbios_uuid_encoded, - SMBIOS_ENTRY_POINT_21); + SMBIOS_ENTRY_POINT_TYPE_32); } /* allocate ram and load rom/bios */ diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c index 7397e56737..6013df1698 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c @@ -62,7 +62,7 @@ uint8_t *smbios_tables; size_t smbios_tables_len; unsigned smbios_table_max; unsigned smbios_table_cnt; -static SmbiosEntryPointType smbios_ep_type = SMBIOS_ENTRY_POINT_21; +static SmbiosEntryPointType smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_32; static SmbiosEntryPoint ep; @@ -432,7 +432,7 @@ static void smbios_validate_table(MachineState *ms) exit(1); } - if (smbios_ep_type == SMBIOS_ENTRY_POINT_21 && + if (smbios_ep_type == SMBIOS_ENTRY_POINT_TYPE_32 && smbios_tables_len > SMBIOS_21_MAX_TABLES_LEN) { error_report("SMBIOS 2.1 table length %zu exceeds %d", smbios_tables_len, SMBIOS_21_MAX_TABLES_LEN); @@ -927,7 +927,7 @@ void smbios_set_defaults(const char *manufacturer, const char *product, static void smbios_entry_point_setup(void) { switch (smbios_ep_type) { - case SMBIOS_ENTRY_POINT_21: + case SMBIOS_ENTRY_POINT_TYPE_32: memcpy(ep.ep21.anchor_string, "_SM_", 4); memcpy(ep.ep21.intermediate_anchor_string, "_DMI_", 5); ep.ep21.length = sizeof(struct smbios_21_entry_point); @@ -950,7 +950,7 @@ static void smbios_entry_point_setup(void) ep.ep21.structure_table_address = cpu_to_le32(0); break; - case SMBIOS_ENTRY_POINT_30: + case SMBIOS_ENTRY_POINT_TYPE_64: memcpy(ep.ep30.anchor_string, "_SM3_", 5); ep.ep30.length = sizeof(struct smbios_30_entry_point); ep.ep30.entry_point_revision = 1; diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h index 5a0dd0c8cf..d916baed6a 100644 --- a/include/hw/firmware/smbios.h +++ b/include/hw/firmware/smbios.h @@ -27,8 +27,8 @@ struct smbios_phys_mem_area { * SMBIOS spec defined tables */ typedef enum SmbiosEntryPointType { - SMBIOS_ENTRY_POINT_21, - SMBIOS_ENTRY_POINT_30, + SMBIOS_ENTRY_POINT_TYPE_32, + SMBIOS_ENTRY_POINT_TYPE_64, } SmbiosEntryPointType; /* SMBIOS Entry Point From bdf54a9a7bda0bde0c0b7b5767dd670f36ccc9e0 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Tue, 26 Oct 2021 11:10:59 -0400 Subject: [PATCH 234/730] hw/smbios: Use qapi for SmbiosEntryPointType MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This prepares for exposing the SMBIOS entry point type as a machine property on x86. Based on a patch from Daniel P. Berrangé. Signed-off-by: Daniel P. Berrangé Signed-off-by: Eduardo Habkost Message-Id: <20211026151100.1691925-3-ehabkost@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Philippe Mathieu-Daudé Acked-by: Markus Armbruster --- include/hw/firmware/smbios.h | 10 ++-------- qapi/machine.json | 12 ++++++++++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h index d916baed6a..4b7ad77a44 100644 --- a/include/hw/firmware/smbios.h +++ b/include/hw/firmware/smbios.h @@ -1,6 +1,8 @@ #ifndef QEMU_SMBIOS_H #define QEMU_SMBIOS_H +#include "qapi/qapi-types-machine.h" + /* * SMBIOS Support * @@ -23,14 +25,6 @@ struct smbios_phys_mem_area { uint64_t length; }; -/* - * SMBIOS spec defined tables - */ -typedef enum SmbiosEntryPointType { - SMBIOS_ENTRY_POINT_TYPE_32, - SMBIOS_ENTRY_POINT_TYPE_64, -} SmbiosEntryPointType; - /* SMBIOS Entry Point * There are two types of entry points defined in the SMBIOS specification * (see below). BIOS must place the entry point(s) at a 16-byte-aligned diff --git a/qapi/machine.json b/qapi/machine.json index 372535b348..b6a37e17c4 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1568,3 +1568,15 @@ { 'command': 'x-query-usb', 'returns': 'HumanReadableText', 'features': [ 'unstable' ] } + +## +# @SmbiosEntryPointType: +# +# @32: SMBIOS version 2.1 (32-bit) Entry Point +# +# @64: SMBIOS version 3.0 (64-bit) Entry Point +# +# Since: 7.0 +## +{ 'enum': 'SmbiosEntryPointType', + 'data': [ '32', '64' ] } From 0e4edb3b3b5770ac325f5df02689154be5e64963 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Tue, 26 Oct 2021 11:11:00 -0400 Subject: [PATCH 235/730] hw/i386: expose a "smbios-entry-point-type" PC machine property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The i440fx and Q35 machine types are both hardcoded to use the legacy SMBIOS 2.1 (32-bit) entry point. This is a sensible conservative choice because SeaBIOS only supports SMBIOS 2.1 EDK2, however, can also support SMBIOS 3.0 (64-bit) entry points, and QEMU already uses this on the ARM virt machine type. This adds a property to allow the choice of SMBIOS entry point versions For example to opt in to 64-bit SMBIOS entry point: $QEMU -machine q35,smbios-entry-point-type=64 Based on a patch submitted by Daniel Berrangé. Signed-off-by: Daniel P. Berrangé Signed-off-by: Eduardo Habkost Message-Id: <20211026151100.1691925-4-ehabkost@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Philippe Mathieu-Daudé --- hw/i386/pc.c | 26 ++++++++++++++++++++++++++ hw/i386/pc_piix.c | 2 +- hw/i386/pc_q35.c | 2 +- include/hw/i386/pc.h | 4 ++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index fccde2ef39..959efa5b3f 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -77,6 +77,7 @@ #include "hw/mem/nvdimm.h" #include "qapi/error.h" #include "qapi/qapi-visit-common.h" +#include "qapi/qapi-visit-machine.h" #include "qapi/visitor.h" #include "hw/core/cpu.h" #include "hw/usb.h" @@ -1524,6 +1525,23 @@ static void pc_machine_set_default_bus_bypass_iommu(Object *obj, bool value, pcms->default_bus_bypass_iommu = value; } +static void pc_machine_get_smbios_ep(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + SmbiosEntryPointType smbios_entry_point_type = pcms->smbios_entry_point_type; + + visit_type_SmbiosEntryPointType(v, name, &smbios_entry_point_type, errp); +} + +static void pc_machine_set_smbios_ep(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + PCMachineState *pcms = PC_MACHINE(obj); + + visit_type_SmbiosEntryPointType(v, name, &pcms->smbios_entry_point_type, errp); +} + static void pc_machine_get_max_ram_below_4g(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) @@ -1614,6 +1632,8 @@ static void pc_machine_initfn(Object *obj) pcms->vmport = ON_OFF_AUTO_OFF; #endif /* CONFIG_VMPORT */ pcms->max_ram_below_4g = 0; /* use default */ + pcms->smbios_entry_point_type = SMBIOS_ENTRY_POINT_TYPE_32; + /* acpi build is enabled by default if machine supports it */ pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build; pcms->smbus_enabled = true; @@ -1756,6 +1776,12 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) NULL, NULL); object_class_property_set_description(oc, PC_MACHINE_MAX_FW_SIZE, "Maximum combined firmware size"); + + object_class_property_add(oc, PC_MACHINE_SMBIOS_EP, "str", + pc_machine_get_smbios_ep, pc_machine_set_smbios_ep, + NULL, NULL); + object_class_property_set_description(oc, PC_MACHINE_SMBIOS_EP, + "SMBIOS Entry Point type [32, 64]"); } static const TypeInfo pc_machine_info = { diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 25f918b609..7c7790a5ce 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -177,7 +177,7 @@ static void pc_init1(MachineState *machine, smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)", mc->name, pcmc->smbios_legacy_mode, pcmc->smbios_uuid_encoded, - SMBIOS_ENTRY_POINT_TYPE_32); + pcms->smbios_entry_point_type); } /* allocate ram and load rom/bios */ diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 1103fbcd90..1780f79bc1 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -200,7 +200,7 @@ static void pc_q35_init(MachineState *machine) smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)", mc->name, pcmc->smbios_legacy_mode, pcmc->smbios_uuid_encoded, - SMBIOS_ENTRY_POINT_TYPE_32); + pcms->smbios_entry_point_type); } /* allocate ram and load rom/bios */ diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index b38947c224..9c9f4ac748 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -13,6 +13,7 @@ #include "hw/hotplug.h" #include "qom/object.h" #include "hw/i386/sgx-epc.h" +#include "hw/firmware/smbios.h" #define HPET_INTCAP "hpet-intcap" @@ -40,6 +41,7 @@ typedef struct PCMachineState { /* Configuration options: */ uint64_t max_ram_below_4g; OnOffAuto vmport; + SmbiosEntryPointType smbios_entry_point_type; bool acpi_build_enabled; bool smbus_enabled; @@ -63,6 +65,8 @@ typedef struct PCMachineState { #define PC_MACHINE_SATA "sata" #define PC_MACHINE_PIT "pit" #define PC_MACHINE_MAX_FW_SIZE "max-fw-size" +#define PC_MACHINE_SMBIOS_EP "smbios-entry-point-type" + /** * PCMachineClass: * From 0a963af3e3c12074ed93babe0b908a1bce79f84f Mon Sep 17 00:00:00 2001 From: Andy Pei Date: Mon, 3 Jan 2022 17:28:12 +0800 Subject: [PATCH 236/730] hw/vhost-user-blk: turn on VIRTIO_BLK_F_SIZE_MAX feature for virtio blk device Turn on pre-defined feature VIRTIO_BLK_F_SIZE_MAX for virtio blk device to avoid guest DMA request sizes which are too large for hardware spec. Signed-off-by: Andy Pei Message-Id: <1641202092-149677-1-git-send-email-andy.pei@intel.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Acked-by: Raphael Norwitz --- hw/block/vhost-user-blk.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index ab11ce8252..1a42ae9187 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -252,6 +252,7 @@ static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev, VHostUserBlk *s = VHOST_USER_BLK(vdev); /* Turn on pre-defined features */ + virtio_add_feature(&features, VIRTIO_BLK_F_SIZE_MAX); virtio_add_feature(&features, VIRTIO_BLK_F_SEG_MAX); virtio_add_feature(&features, VIRTIO_BLK_F_GEOMETRY); virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY); From 6c427ab926fd79e05ff650884babee962cdeaeb9 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 17 Dec 2021 14:46:04 +0100 Subject: [PATCH 237/730] util/oslib-posix: Let touch_all_pages() return an error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's prepare touch_all_pages() for returning differing errors. Return an error from the thread and report the last processed error. Translate SIGBUS to -EFAULT, as a SIGBUS can mean all different kind of things (memory error, read error, out of memory). When allocating memory fails via the current SIGBUS-based mechanism, we'll get: os_mem_prealloc: preallocating memory failed: Bad address Reviewed-by: Daniel P. Berrangé Reviewed-by: Michal Privoznik Signed-off-by: David Hildenbrand Message-Id: <20211217134611.31172-2-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- util/oslib-posix.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/util/oslib-posix.c b/util/oslib-posix.c index e8bdb02e1d..b146beef78 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -84,7 +84,6 @@ typedef struct MemsetThread MemsetThread; static MemsetThread *memset_thread; static int memset_num_threads; -static bool memset_thread_failed; static QemuMutex page_mutex; static QemuCond page_cond; @@ -452,6 +451,7 @@ static void *do_touch_pages(void *arg) { MemsetThread *memset_args = (MemsetThread *)arg; sigset_t set, oldset; + int ret = 0; /* * On Linux, the page faults from the loop below can cause mmap_sem @@ -470,7 +470,7 @@ static void *do_touch_pages(void *arg) pthread_sigmask(SIG_UNBLOCK, &set, &oldset); if (sigsetjmp(memset_args->env, 1)) { - memset_thread_failed = true; + ret = -EFAULT; } else { char *addr = memset_args->addr; size_t numpages = memset_args->numpages; @@ -494,7 +494,7 @@ static void *do_touch_pages(void *arg) } } pthread_sigmask(SIG_SETMASK, &oldset, NULL); - return NULL; + return (void *)(uintptr_t)ret; } static inline int get_memset_num_threads(int smp_cpus) @@ -509,13 +509,13 @@ static inline int get_memset_num_threads(int smp_cpus) return ret; } -static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages, - int smp_cpus) +static int touch_all_pages(char *area, size_t hpagesize, size_t numpages, + int smp_cpus) { static gsize initialized = 0; size_t numpages_per_thread, leftover; + int ret = 0, i = 0; char *addr = area; - int i = 0; if (g_once_init_enter(&initialized)) { qemu_mutex_init(&page_mutex); @@ -523,7 +523,6 @@ static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages, g_once_init_leave(&initialized, 1); } - memset_thread_failed = false; threads_created_flag = false; memset_num_threads = get_memset_num_threads(smp_cpus); memset_thread = g_new0(MemsetThread, memset_num_threads); @@ -545,12 +544,16 @@ static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages, qemu_mutex_unlock(&page_mutex); for (i = 0; i < memset_num_threads; i++) { - qemu_thread_join(&memset_thread[i].pgthread); + int tmp = (uintptr_t)qemu_thread_join(&memset_thread[i].pgthread); + + if (tmp) { + ret = tmp; + } } g_free(memset_thread); memset_thread = NULL; - return memset_thread_failed; + return ret; } void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, @@ -573,9 +576,10 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, } /* touch pages simultaneously */ - if (touch_all_pages(area, hpagesize, numpages, smp_cpus)) { - error_setg(errp, "os_mem_prealloc: Insufficient free host memory " - "pages available to allocate guest RAM"); + ret = touch_all_pages(area, hpagesize, numpages, smp_cpus); + if (ret) { + error_setg_errno(errp, -ret, + "os_mem_prealloc: preallocating memory failed"); } ret = sigaction(SIGBUS, &oldact, NULL); From a384bfa32ed8d616d766cb33360011157ae2f5c7 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 17 Dec 2021 14:46:05 +0100 Subject: [PATCH 238/730] util/oslib-posix: Support MADV_POPULATE_WRITE for os_mem_prealloc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's sense support and use it for preallocation. MADV_POPULATE_WRITE does not require a SIGBUS handler, doesn't actually touch page content, and avoids context switches; it is, therefore, faster and easier to handle than our current approach. While MADV_POPULATE_WRITE is, in general, faster than manual prefaulting, and especially faster with 4k pages, there is still value in prefaulting using multiple threads to speed up preallocation. More details on MADV_POPULATE_WRITE can be found in the Linux commits 4ca9b3859dac ("mm/madvise: introduce MADV_POPULATE_(READ|WRITE) to prefault page tables") and eb2faa513c24 ("mm/madvise: report SIGBUS as -EFAULT for MADV_POPULATE_(READ|WRITE)"), and in the man page proposal [1]. This resolves the TODO in do_touch_pages(). In the future, we might want to look into using fallocate(), eventually combined with MADV_POPULATE_READ, when dealing with shared file/fd mappings and not caring about memory bindings. [1] https://lkml.kernel.org/r/20210816081922.5155-1-david@redhat.com Reviewed-by: Pankaj Gupta Reviewed-by: Daniel P. Berrangé Reviewed-by: Michal Privoznik Signed-off-by: David Hildenbrand Message-Id: <20211217134611.31172-3-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/qemu/osdep.h | 7 ++++ util/oslib-posix.c | 81 +++++++++++++++++++++++++++++++++----------- 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 60718fc342..d1660d67fa 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -471,6 +471,11 @@ static inline void qemu_cleanup_generic_vfree(void *p) #else #define QEMU_MADV_REMOVE QEMU_MADV_DONTNEED #endif +#ifdef MADV_POPULATE_WRITE +#define QEMU_MADV_POPULATE_WRITE MADV_POPULATE_WRITE +#else +#define QEMU_MADV_POPULATE_WRITE QEMU_MADV_INVALID +#endif #elif defined(CONFIG_POSIX_MADVISE) @@ -484,6 +489,7 @@ static inline void qemu_cleanup_generic_vfree(void *p) #define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID #define QEMU_MADV_NOHUGEPAGE QEMU_MADV_INVALID #define QEMU_MADV_REMOVE QEMU_MADV_DONTNEED +#define QEMU_MADV_POPULATE_WRITE QEMU_MADV_INVALID #else /* no-op */ @@ -497,6 +503,7 @@ static inline void qemu_cleanup_generic_vfree(void *p) #define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID #define QEMU_MADV_NOHUGEPAGE QEMU_MADV_INVALID #define QEMU_MADV_REMOVE QEMU_MADV_INVALID +#define QEMU_MADV_POPULATE_WRITE QEMU_MADV_INVALID #endif diff --git a/util/oslib-posix.c b/util/oslib-posix.c index b146beef78..cb89e07770 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -484,10 +484,6 @@ static void *do_touch_pages(void *arg) * * 'volatile' to stop compiler optimizing this away * to a no-op - * - * TODO: get a better solution from kernel so we - * don't need to write at all so we don't cause - * wear on the storage backing the region... */ *(volatile char *)addr = *addr; addr += hpagesize; @@ -497,6 +493,26 @@ static void *do_touch_pages(void *arg) return (void *)(uintptr_t)ret; } +static void *do_madv_populate_write_pages(void *arg) +{ + MemsetThread *memset_args = (MemsetThread *)arg; + const size_t size = memset_args->numpages * memset_args->hpagesize; + char * const addr = memset_args->addr; + int ret = 0; + + /* See do_touch_pages(). */ + qemu_mutex_lock(&page_mutex); + while (!threads_created_flag) { + qemu_cond_wait(&page_cond, &page_mutex); + } + qemu_mutex_unlock(&page_mutex); + + if (size && qemu_madvise(addr, size, QEMU_MADV_POPULATE_WRITE)) { + ret = -errno; + } + return (void *)(uintptr_t)ret; +} + static inline int get_memset_num_threads(int smp_cpus) { long host_procs = sysconf(_SC_NPROCESSORS_ONLN); @@ -510,10 +526,11 @@ static inline int get_memset_num_threads(int smp_cpus) } static int touch_all_pages(char *area, size_t hpagesize, size_t numpages, - int smp_cpus) + int smp_cpus, bool use_madv_populate_write) { static gsize initialized = 0; size_t numpages_per_thread, leftover; + void *(*touch_fn)(void *); int ret = 0, i = 0; char *addr = area; @@ -523,6 +540,12 @@ static int touch_all_pages(char *area, size_t hpagesize, size_t numpages, g_once_init_leave(&initialized, 1); } + if (use_madv_populate_write) { + touch_fn = do_madv_populate_write_pages; + } else { + touch_fn = do_touch_pages; + } + threads_created_flag = false; memset_num_threads = get_memset_num_threads(smp_cpus); memset_thread = g_new0(MemsetThread, memset_num_threads); @@ -533,7 +556,7 @@ static int touch_all_pages(char *area, size_t hpagesize, size_t numpages, memset_thread[i].numpages = numpages_per_thread + (i < leftover); memset_thread[i].hpagesize = hpagesize; qemu_thread_create(&memset_thread[i].pgthread, "touch_pages", - do_touch_pages, &memset_thread[i], + touch_fn, &memset_thread[i], QEMU_THREAD_JOINABLE); addr += memset_thread[i].numpages * hpagesize; } @@ -556,6 +579,12 @@ static int touch_all_pages(char *area, size_t hpagesize, size_t numpages, return ret; } +static bool madv_populate_write_possible(char *area, size_t pagesize) +{ + return !qemu_madvise(area, pagesize, QEMU_MADV_POPULATE_WRITE) || + errno != EINVAL; +} + void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, Error **errp) { @@ -563,30 +592,42 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, struct sigaction act, oldact; size_t hpagesize = qemu_fd_getpagesize(fd); size_t numpages = DIV_ROUND_UP(memory, hpagesize); + bool use_madv_populate_write; - memset(&act, 0, sizeof(act)); - act.sa_handler = &sigbus_handler; - act.sa_flags = 0; + /* + * Sense on every invocation, as MADV_POPULATE_WRITE cannot be used for + * some special mappings, such as mapping /dev/mem. + */ + use_madv_populate_write = madv_populate_write_possible(area, hpagesize); - ret = sigaction(SIGBUS, &act, &oldact); - if (ret) { - error_setg_errno(errp, errno, - "os_mem_prealloc: failed to install signal handler"); - return; + if (!use_madv_populate_write) { + memset(&act, 0, sizeof(act)); + act.sa_handler = &sigbus_handler; + act.sa_flags = 0; + + ret = sigaction(SIGBUS, &act, &oldact); + if (ret) { + error_setg_errno(errp, errno, + "os_mem_prealloc: failed to install signal handler"); + return; + } } /* touch pages simultaneously */ - ret = touch_all_pages(area, hpagesize, numpages, smp_cpus); + ret = touch_all_pages(area, hpagesize, numpages, smp_cpus, + use_madv_populate_write); if (ret) { error_setg_errno(errp, -ret, "os_mem_prealloc: preallocating memory failed"); } - ret = sigaction(SIGBUS, &oldact, NULL); - if (ret) { - /* Terminate QEMU since it can't recover from error */ - perror("os_mem_prealloc: failed to reinstall signal handler"); - exit(1); + if (!use_madv_populate_write) { + ret = sigaction(SIGBUS, &oldact, NULL); + if (ret) { + /* Terminate QEMU since it can't recover from error */ + perror("os_mem_prealloc: failed to reinstall signal handler"); + exit(1); + } } } From dba506788b0f84a45c69ee1e0100c65034edffaf Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 17 Dec 2021 14:46:06 +0100 Subject: [PATCH 239/730] util/oslib-posix: Introduce and use MemsetContext for touch_all_pages() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's minimize the number of global variables to prepare for os_mem_prealloc() getting called concurrently and make the code a bit easier to read. The only consumer that really needs a global variable is the sigbus handler, which will require protection via a mutex in the future either way as we cannot concurrently mess with the SIGBUS handler. Reviewed-by: Daniel P. Berrangé Reviewed-by: Michal Privoznik Signed-off-by: David Hildenbrand Message-Id: <20211217134611.31172-4-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- util/oslib-posix.c | 73 +++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/util/oslib-posix.c b/util/oslib-posix.c index cb89e07770..cf2ead54ad 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -73,21 +73,30 @@ #define MAX_MEM_PREALLOC_THREAD_COUNT 16 +struct MemsetThread; + +typedef struct MemsetContext { + bool all_threads_created; + bool any_thread_failed; + struct MemsetThread *threads; + int num_threads; +} MemsetContext; + struct MemsetThread { char *addr; size_t numpages; size_t hpagesize; QemuThread pgthread; sigjmp_buf env; + MemsetContext *context; }; typedef struct MemsetThread MemsetThread; -static MemsetThread *memset_thread; -static int memset_num_threads; +/* used by sigbus_handler() */ +static MemsetContext *sigbus_memset_context; static QemuMutex page_mutex; static QemuCond page_cond; -static bool threads_created_flag; int qemu_get_thread_id(void) { @@ -438,10 +447,13 @@ const char *qemu_get_exec_dir(void) static void sigbus_handler(int signal) { int i; - if (memset_thread) { - for (i = 0; i < memset_num_threads; i++) { - if (qemu_thread_is_self(&memset_thread[i].pgthread)) { - siglongjmp(memset_thread[i].env, 1); + + if (sigbus_memset_context) { + for (i = 0; i < sigbus_memset_context->num_threads; i++) { + MemsetThread *thread = &sigbus_memset_context->threads[i]; + + if (qemu_thread_is_self(&thread->pgthread)) { + siglongjmp(thread->env, 1); } } } @@ -459,7 +471,7 @@ static void *do_touch_pages(void *arg) * clearing until all threads have been created. */ qemu_mutex_lock(&page_mutex); - while(!threads_created_flag){ + while (!memset_args->context->all_threads_created) { qemu_cond_wait(&page_cond, &page_mutex); } qemu_mutex_unlock(&page_mutex); @@ -502,7 +514,7 @@ static void *do_madv_populate_write_pages(void *arg) /* See do_touch_pages(). */ qemu_mutex_lock(&page_mutex); - while (!threads_created_flag) { + while (!memset_args->context->all_threads_created) { qemu_cond_wait(&page_cond, &page_mutex); } qemu_mutex_unlock(&page_mutex); @@ -529,6 +541,9 @@ static int touch_all_pages(char *area, size_t hpagesize, size_t numpages, int smp_cpus, bool use_madv_populate_write) { static gsize initialized = 0; + MemsetContext context = { + .num_threads = get_memset_num_threads(smp_cpus), + }; size_t numpages_per_thread, leftover; void *(*touch_fn)(void *); int ret = 0, i = 0; @@ -546,35 +561,41 @@ static int touch_all_pages(char *area, size_t hpagesize, size_t numpages, touch_fn = do_touch_pages; } - threads_created_flag = false; - memset_num_threads = get_memset_num_threads(smp_cpus); - memset_thread = g_new0(MemsetThread, memset_num_threads); - numpages_per_thread = numpages / memset_num_threads; - leftover = numpages % memset_num_threads; - for (i = 0; i < memset_num_threads; i++) { - memset_thread[i].addr = addr; - memset_thread[i].numpages = numpages_per_thread + (i < leftover); - memset_thread[i].hpagesize = hpagesize; - qemu_thread_create(&memset_thread[i].pgthread, "touch_pages", - touch_fn, &memset_thread[i], + context.threads = g_new0(MemsetThread, context.num_threads); + numpages_per_thread = numpages / context.num_threads; + leftover = numpages % context.num_threads; + for (i = 0; i < context.num_threads; i++) { + context.threads[i].addr = addr; + context.threads[i].numpages = numpages_per_thread + (i < leftover); + context.threads[i].hpagesize = hpagesize; + context.threads[i].context = &context; + qemu_thread_create(&context.threads[i].pgthread, "touch_pages", + touch_fn, &context.threads[i], QEMU_THREAD_JOINABLE); - addr += memset_thread[i].numpages * hpagesize; + addr += context.threads[i].numpages * hpagesize; + } + + if (!use_madv_populate_write) { + sigbus_memset_context = &context; } qemu_mutex_lock(&page_mutex); - threads_created_flag = true; + context.all_threads_created = true; qemu_cond_broadcast(&page_cond); qemu_mutex_unlock(&page_mutex); - for (i = 0; i < memset_num_threads; i++) { - int tmp = (uintptr_t)qemu_thread_join(&memset_thread[i].pgthread); + for (i = 0; i < context.num_threads; i++) { + int tmp = (uintptr_t)qemu_thread_join(&context.threads[i].pgthread); if (tmp) { ret = tmp; } } - g_free(memset_thread); - memset_thread = NULL; + + if (!use_madv_populate_write) { + sigbus_memset_context = NULL; + } + g_free(context.threads); return ret; } From 89aec6411c429adb662c53c94a986a5397961a7f Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 17 Dec 2021 14:46:07 +0100 Subject: [PATCH 240/730] util/oslib-posix: Don't create too many threads with small memory or little pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's limit the number of threads to something sane, especially that - We don't have more threads than the number of pages we have - We don't have threads that initialize small (< 64 MiB) memory Reviewed-by: Pankaj Gupta Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Daniel P. Berrangé Reviewed-by: Michal Privoznik Signed-off-by: David Hildenbrand Message-Id: <20211217134611.31172-5-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- util/oslib-posix.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/util/oslib-posix.c b/util/oslib-posix.c index cf2ead54ad..67c08a425e 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -40,6 +40,7 @@ #include #include "qemu/cutils.h" #include "qemu/compiler.h" +#include "qemu/units.h" #ifdef CONFIG_LINUX #include @@ -525,7 +526,8 @@ static void *do_madv_populate_write_pages(void *arg) return (void *)(uintptr_t)ret; } -static inline int get_memset_num_threads(int smp_cpus) +static inline int get_memset_num_threads(size_t hpagesize, size_t numpages, + int smp_cpus) { long host_procs = sysconf(_SC_NPROCESSORS_ONLN); int ret = 1; @@ -533,6 +535,12 @@ static inline int get_memset_num_threads(int smp_cpus) if (host_procs > 0) { ret = MIN(MIN(host_procs, MAX_MEM_PREALLOC_THREAD_COUNT), smp_cpus); } + + /* Especially with gigantic pages, don't create more threads than pages. */ + ret = MIN(ret, numpages); + /* Don't start threads to prealloc comparatively little memory. */ + ret = MIN(ret, MAX(1, hpagesize * numpages / (64 * MiB))); + /* In case sysconf() fails, we fall back to single threaded */ return ret; } @@ -542,7 +550,7 @@ static int touch_all_pages(char *area, size_t hpagesize, size_t numpages, { static gsize initialized = 0; MemsetContext context = { - .num_threads = get_memset_num_threads(smp_cpus), + .num_threads = get_memset_num_threads(hpagesize, numpages, smp_cpus), }; size_t numpages_per_thread, leftover; void *(*touch_fn)(void *); From ac86e5c37df4963846d1a2e999696bb5031a99cd Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 17 Dec 2021 14:46:08 +0100 Subject: [PATCH 241/730] util/oslib-posix: Avoid creating a single thread with MADV_POPULATE_WRITE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's simplify the case when we only want a single thread and don't have to mess with signal handlers. Reviewed-by: Pankaj Gupta Reviewed-by: Daniel P. Berrangé Reviewed-by: Michal Privoznik Signed-off-by: David Hildenbrand Message-Id: <20211217134611.31172-6-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- util/oslib-posix.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 67c08a425e..efa4f96d56 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -564,6 +564,14 @@ static int touch_all_pages(char *area, size_t hpagesize, size_t numpages, } if (use_madv_populate_write) { + /* Avoid creating a single thread for MADV_POPULATE_WRITE */ + if (context.num_threads == 1) { + if (qemu_madvise(area, hpagesize * numpages, + QEMU_MADV_POPULATE_WRITE)) { + return -errno; + } + return 0; + } touch_fn = do_madv_populate_write_pages; } else { touch_fn = do_touch_pages; From a960d6642d39f7d255b7b2b8bda3c2ae4e4e649b Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 17 Dec 2021 14:46:09 +0100 Subject: [PATCH 242/730] util/oslib-posix: Support concurrent os_mem_prealloc() invocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a mutex to protect the SIGBUS case, as we cannot mess concurrently with the sigbus handler and we have to manage the global variable sigbus_memset_context. The MADV_POPULATE_WRITE path can run concurrently. Note that page_mutex and page_cond are shared between concurrent invocations, which shouldn't be a problem. This is a preparation for future virtio-mem prealloc code, which will call os_mem_prealloc() asynchronously from an iothread when handling guest requests. Reviewed-by: Pankaj Gupta Reviewed-by: Daniel P. Berrangé Reviewed-by: Michal Privoznik Signed-off-by: David Hildenbrand Message-Id: <20211217134611.31172-7-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- util/oslib-posix.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/util/oslib-posix.c b/util/oslib-posix.c index efa4f96d56..9829149e4b 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -95,6 +95,7 @@ typedef struct MemsetThread MemsetThread; /* used by sigbus_handler() */ static MemsetContext *sigbus_memset_context; +static QemuMutex sigbus_mutex; static QemuMutex page_mutex; static QemuCond page_cond; @@ -625,6 +626,7 @@ static bool madv_populate_write_possible(char *area, size_t pagesize) void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, Error **errp) { + static gsize initialized; int ret; struct sigaction act, oldact; size_t hpagesize = qemu_fd_getpagesize(fd); @@ -638,6 +640,12 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, use_madv_populate_write = madv_populate_write_possible(area, hpagesize); if (!use_madv_populate_write) { + if (g_once_init_enter(&initialized)) { + qemu_mutex_init(&sigbus_mutex); + g_once_init_leave(&initialized, 1); + } + + qemu_mutex_lock(&sigbus_mutex); memset(&act, 0, sizeof(act)); act.sa_handler = &sigbus_handler; act.sa_flags = 0; @@ -665,6 +673,7 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, perror("os_mem_prealloc: failed to reinstall signal handler"); exit(1); } + qemu_mutex_unlock(&sigbus_mutex); } } From d9e9cd59df4bc92e4cf7ad1bfa6e2a8429ff31b4 Mon Sep 17 00:00:00 2001 From: Troy Lee Date: Fri, 7 Jan 2022 17:07:57 +0000 Subject: [PATCH 243/730] Add dummy Aspeed AST2600 Display Port MCU (DPMCU) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AST2600 Display Port MCU introduces 0x18000000~0x1803FFFF as it's memory and io address. If guest machine try to access DPMCU memory, it will cause a fatal error. Signed-off-by: Troy Lee Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Cédric Le Goater Message-id: 20211210083034.726610-1-troy_lee@aspeedtech.com Signed-off-by: Peter Maydell --- hw/arm/aspeed_ast2600.c | 8 ++++++++ include/hw/arm/aspeed_soc.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index 0384357a95..e33483fb5d 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -19,9 +19,11 @@ #include "sysemu/sysemu.h" #define ASPEED_SOC_IOMEM_SIZE 0x00200000 +#define ASPEED_SOC_DPMCU_SIZE 0x00040000 static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_DEV_SRAM] = 0x10000000, + [ASPEED_DEV_DPMCU] = 0x18000000, /* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */ [ASPEED_DEV_IOMEM] = 0x1E600000, [ASPEED_DEV_PWM] = 0x1E610000, @@ -44,6 +46,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_DEV_SCU] = 0x1E6E2000, [ASPEED_DEV_XDMA] = 0x1E6E7000, [ASPEED_DEV_ADC] = 0x1E6E9000, + [ASPEED_DEV_DP] = 0x1E6EB000, [ASPEED_DEV_VIDEO] = 0x1E700000, [ASPEED_DEV_SDHCI] = 0x1E740000, [ASPEED_DEV_EMMC] = 0x1E750000, @@ -104,6 +107,7 @@ static const int aspeed_soc_ast2600_irqmap[] = { [ASPEED_DEV_ETH3] = 32, [ASPEED_DEV_ETH4] = 33, [ASPEED_DEV_KCS] = 138, /* 138 -> 142 */ + [ASPEED_DEV_DP] = 62, }; static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl) @@ -298,6 +302,10 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(get_system_memory(), sc->memmap[ASPEED_DEV_SRAM], &s->sram); + /* DPMCU */ + create_unimplemented_device("aspeed.dpmcu", sc->memmap[ASPEED_DEV_DPMCU], + ASPEED_SOC_DPMCU_SIZE); + /* SCU */ if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) { return; diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 8139358549..18fb7eed46 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -139,6 +139,8 @@ enum { ASPEED_DEV_EMMC, ASPEED_DEV_KCS, ASPEED_DEV_HACE, + ASPEED_DEV_DPMCU, + ASPEED_DEV_DP, }; #endif /* ASPEED_SOC_H */ From b7469ef92a8034b32031ba22b84fb14046f9770e Mon Sep 17 00:00:00 2001 From: Idan Horowitz Date: Fri, 7 Jan 2022 17:07:57 +0000 Subject: [PATCH 244/730] target/arm: Add missing FEAT_TLBIOS instructions Some of the instructions added by the FEAT_TLBIOS extension were forgotten when the extension was originally added to QEMU. Fixes: 7113d618505b ("target/arm: Add support for FEAT_TLBIOS") Signed-off-by: Idan Horowitz Reviewed-by: Richard Henderson Message-id: 20211231103928.1455657-1-idan.horowitz@gmail.com Signed-off-by: Peter Maydell --- target/arm/helper.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/target/arm/helper.c b/target/arm/helper.c index db837d53bd..cfca0f5ba6 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -6964,18 +6964,42 @@ static const ARMCPRegInfo tlbios_reginfo[] = { .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 0, .access = PL1_W, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_vmalle1is_write }, + { .name = "TLBI_VAE1OS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 1, + .access = PL1_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae1is_write }, { .name = "TLBI_ASIDE1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 2, .access = PL1_W, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_vmalle1is_write }, + { .name = "TLBI_VAAE1OS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 3, + .access = PL1_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae1is_write }, + { .name = "TLBI_VALE1OS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 5, + .access = PL1_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae1is_write }, + { .name = "TLBI_VAALE1OS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 7, + .access = PL1_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae1is_write }, { .name = "TLBI_ALLE2OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 0, .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_alle2is_write }, + { .name = "TLBI_VAE2OS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 1, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae2is_write }, { .name = "TLBI_ALLE1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 4, .access = PL2_W, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_alle1is_write }, + { .name = "TLBI_VALE2OS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 5, + .access = PL2_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae2is_write }, { .name = "TLBI_VMALLS12E1OS", .state = ARM_CP_STATE_AA64, .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 6, .access = PL2_W, .type = ARM_CP_NO_RAW, @@ -6996,6 +7020,14 @@ static const ARMCPRegInfo tlbios_reginfo[] = { .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 0, .access = PL3_W, .type = ARM_CP_NO_RAW, .writefn = tlbi_aa64_alle3is_write }, + { .name = "TLBI_VAE3OS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 1, + .access = PL3_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae3is_write }, + { .name = "TLBI_VALE3OS", .state = ARM_CP_STATE_AA64, + .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 5, + .access = PL3_W, .type = ARM_CP_NO_RAW, + .writefn = tlbi_aa64_vae3is_write }, REGINFO_SENTINEL }; From a120157b24c78c2d890cd9793eb5a1cbbf42c9a9 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:07:57 +0000 Subject: [PATCH 245/730] hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The checks in the ITS on the rdbase values in guest commands are off-by-one: they permit the guest to pass us a value equal to s->gicv3->num_cpu, but the valid values are 0...num_cpu-1. This meant the guest could cause us to index off the end of the s->gicv3->cpu[] array when calling gicv3_redist_process_lpi(), and we would probably crash. (This is not a security bug, because this code is only usable with emulation, not with KVM.) Cc: qemu-stable@nongnu.org Fixes: 17fb5e36aabd4b ("hw/intc: GICv3 redistributor ITS processing") Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson --- hw/intc/arm_gicv3_its.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index b99e63d58f..677b96dfe2 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -311,7 +311,7 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, */ rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U; - if (rdbase > s->gicv3->num_cpu) { + if (rdbase >= s->gicv3->num_cpu) { return result; } @@ -505,7 +505,7 @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset) valid = (value & CMD_FIELD_VALID_MASK); - if ((icid > s->ct.maxids.max_collids) || (rdbase > s->gicv3->num_cpu)) { + if ((icid > s->ct.maxids.max_collids) || (rdbase >= s->gicv3->num_cpu)) { qemu_log_mask(LOG_GUEST_ERROR, "ITS MAPC: invalid collection table attributes " "icid %d rdbase %" PRIu64 "\n", icid, rdbase); From 8d2d6dd9bb6f4a275e9acc5d97b020cd91483285 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:07:58 +0000 Subject: [PATCH 246/730] hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We currently define a bitmask for the GITS_CTLR ENABLED bit in two ways: as ITS_CTLR_ENABLED, and via the FIELD() macro as R_GITS_CTLR_ENABLED_MASK. Consistently use the FIELD macro version everywhere and remove the redundant ITS_CTLR_ENABLED define. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé --- hw/intc/arm_gicv3_its.c | 20 ++++++++++---------- hw/intc/gicv3_internal.h | 2 -- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 677b96dfe2..985ae03f5f 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -651,7 +651,7 @@ static void process_cmdq(GICv3ITSState *s) uint8_t cmd; int i; - if (!(s->ctlr & ITS_CTLR_ENABLED)) { + if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { return; } @@ -887,7 +887,7 @@ static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset, switch (offset) { case GITS_TRANSLATER: - if (s->ctlr & ITS_CTLR_ENABLED) { + if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) { devid = attrs.requester_id; result = process_its_cmd(s, data, devid, NONE); } @@ -912,13 +912,13 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, switch (offset) { case GITS_CTLR: if (value & R_GITS_CTLR_ENABLED_MASK) { - s->ctlr |= ITS_CTLR_ENABLED; + s->ctlr |= R_GITS_CTLR_ENABLED_MASK; extract_table_params(s); extract_cmdq_params(s); s->creadr = 0; process_cmdq(s); } else { - s->ctlr &= ~ITS_CTLR_ENABLED; + s->ctlr &= ~R_GITS_CTLR_ENABLED_MASK; } break; case GITS_CBASER: @@ -926,7 +926,7 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is * already enabled */ - if (!(s->ctlr & ITS_CTLR_ENABLED)) { + if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { s->cbaser = deposit64(s->cbaser, 0, 32, value); s->creadr = 0; s->cwriter = s->creadr; @@ -937,7 +937,7 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is * already enabled */ - if (!(s->ctlr & ITS_CTLR_ENABLED)) { + if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { s->cbaser = deposit64(s->cbaser, 32, 32, value); s->creadr = 0; s->cwriter = s->creadr; @@ -979,7 +979,7 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is * already enabled */ - if (!(s->ctlr & ITS_CTLR_ENABLED)) { + if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { index = (offset - GITS_BASER) / 8; if (offset & 7) { @@ -1076,7 +1076,7 @@ static bool its_writell(GICv3ITSState *s, hwaddr offset, * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is * already enabled */ - if (!(s->ctlr & ITS_CTLR_ENABLED)) { + if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { index = (offset - GITS_BASER) / 8; s->baser[index] &= GITS_BASER_RO_MASK; s->baser[index] |= (value & ~GITS_BASER_RO_MASK); @@ -1087,7 +1087,7 @@ static bool its_writell(GICv3ITSState *s, hwaddr offset, * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is * already enabled */ - if (!(s->ctlr & ITS_CTLR_ENABLED)) { + if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) { s->cbaser = value; s->creadr = 0; s->cwriter = s->creadr; @@ -1298,7 +1298,7 @@ static void gicv3_its_reset(DeviceState *dev) static void gicv3_its_post_load(GICv3ITSState *s) { - if (s->ctlr & ITS_CTLR_ENABLED) { + if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) { extract_table_params(s); extract_cmdq_params(s); } diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index b9c37453b0..63de8667c6 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -289,8 +289,6 @@ FIELD(GITS_TYPER, CIL, 36, 1) #define GITS_IDREGS 0xFFD0 -#define ITS_CTLR_ENABLED (1U) /* ITS Enabled */ - #define GITS_BASER_RO_MASK (R_GITS_BASER_ENTRYSIZE_MASK | \ R_GITS_BASER_TYPE_MASK) From 6c1db43de4965b5274830bbd36298638a6dbb468 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:07:58 +0000 Subject: [PATCH 247/730] hw/intc/arm_gicv3_its: Remove maxids union from TableDesc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TableDesc struct defines properties of the in-guest-memory tables which the guest tells us about by writing to the GITS_BASER registers. This struct currently has a union 'maxids', but all the fields of the union have the same type (uint32_t) and do the same thing (record one-greater-than the maximum ID value that can be used as an index into the table). We're about to add another table type (the GICv4 vPE table); rather than adding another specifically-named union field for that table type with the same type as the other union fields, remove the union entirely and just have a 'uint32_t max_ids' struct field. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson --- hw/intc/arm_gicv3_its.c | 20 ++++++++++---------- include/hw/intc/arm_gicv3_its_common.h | 5 +---- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 985ae03f5f..f321f10189 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -287,10 +287,10 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, * In this implementation, in case of guest errors we ignore the * command and move onto the next command in the queue. */ - if (devid > s->dt.maxids.max_devids) { + if (devid > s->dt.max_ids) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes: devid %d>%d", - __func__, devid, s->dt.maxids.max_devids); + __func__, devid, s->dt.max_ids); } else if (!dte_valid || !ite_valid || !cte_valid) { qemu_log_mask(LOG_GUEST_ERROR, @@ -384,7 +384,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1; } - if ((devid > s->dt.maxids.max_devids) || (icid > s->ct.maxids.max_collids) + if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids) || !dte_valid || (eventid > max_eventid) || (!ignore_pInt && (((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS)))) { @@ -505,7 +505,7 @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset) valid = (value & CMD_FIELD_VALID_MASK); - if ((icid > s->ct.maxids.max_collids) || (rdbase >= s->gicv3->num_cpu)) { + if ((icid > s->ct.max_ids) || (rdbase >= s->gicv3->num_cpu)) { qemu_log_mask(LOG_GUEST_ERROR, "ITS MAPC: invalid collection table attributes " "icid %d rdbase %" PRIu64 "\n", icid, rdbase); @@ -618,7 +618,7 @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset) valid = (value & CMD_FIELD_VALID_MASK); - if ((devid > s->dt.maxids.max_devids) || + if ((devid > s->dt.max_ids) || (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) { qemu_log_mask(LOG_GUEST_ERROR, "ITS MAPD: invalid device table attributes " @@ -810,8 +810,8 @@ static void extract_table_params(GICv3ITSState *s) (page_sz / s->dt.entry_sz)); } - s->dt.maxids.max_devids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER, - DEVBITS) + 1)); + s->dt.max_ids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER, + DEVBITS) + 1)); s->dt.base_addr = baser_base_addr(value, page_sz); @@ -842,11 +842,11 @@ static void extract_table_params(GICv3ITSState *s) } if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) { - s->ct.maxids.max_collids = (1UL << (FIELD_EX64(s->typer, - GITS_TYPER, CIDBITS) + 1)); + s->ct.max_ids = (1UL << (FIELD_EX64(s->typer, + GITS_TYPER, CIDBITS) + 1)); } else { /* 16-bit CollectionId supported when CIL == 0 */ - s->ct.maxids.max_collids = (1UL << 16); + s->ct.max_ids = (1UL << 16); } s->ct.base_addr = baser_base_addr(value, page_sz); diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h index 4e79145dde..85a144b0e4 100644 --- a/include/hw/intc/arm_gicv3_its_common.h +++ b/include/hw/intc/arm_gicv3_its_common.h @@ -47,10 +47,7 @@ typedef struct { uint16_t entry_sz; uint32_t page_sz; uint32_t max_entries; - union { - uint32_t max_devids; - uint32_t max_collids; - } maxids; + uint32_t max_ids; uint64_t base_addr; } TableDesc; From 62df780e3d4e918d984797f2d75b0cced157b757 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:07:58 +0000 Subject: [PATCH 248/730] hw/intc/arm_gicv3_its: Don't return early in extract_table_params() loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In extract_table_params() we process each GITS_BASER register. If the register's Valid bit is not set, this means there is no in-guest-memory table and so we should not try to interpret the other fields in the register. This was incorrectly coded as a 'return' rather than a 'break', so instead of looping round to process the next GITS_BASER we would stop entirely, treating any later tables as being not valid also. This has no real guest-visible effects because (since we don't have GITS_TYPER.HCC != 0) the guest must in any case set up all the GITS_BASER to point to valid tables, so this only happens in an odd misbehaving-guest corner case. Fix the check to 'break', so that we leave the case statement and loop back around to the next GITS_BASER. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson --- hw/intc/arm_gicv3_its.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index f321f10189..c97b9982ae 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -795,7 +795,7 @@ static void extract_table_params(GICv3ITSState *s) s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID); if (!s->dt.valid) { - return; + break; } s->dt.page_sz = page_sz; @@ -826,7 +826,7 @@ static void extract_table_params(GICv3ITSState *s) * hence writes are discarded if ct.valid is 0 */ if (!s->ct.valid) { - return; + break; } s->ct.page_sz = page_sz; From e5487a413904973ca77999c904be8949da2e8f31 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:07:58 +0000 Subject: [PATCH 249/730] hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The extract_table_params() decodes the fields in the GITS_BASER registers into TableDesc structs. Since the fields are the same for all the GITS_BASER registers, there is currently a lot of code duplication within the switch (type) statement. Refactor so that the cases include only what is genuinely different for each type: the calculation of the number of bits in the ID value that indexes into the table. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé --- hw/intc/arm_gicv3_its.c | 97 +++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 57 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index c97b9982ae..84808b1e29 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -758,6 +758,9 @@ static void extract_table_params(GICv3ITSState *s) uint64_t value; for (int i = 0; i < 8; i++) { + TableDesc *td; + int idbits; + value = s->baser[i]; if (!value) { @@ -789,73 +792,53 @@ static void extract_table_params(GICv3ITSState *s) type = FIELD_EX64(value, GITS_BASER, TYPE); switch (type) { - case GITS_BASER_TYPE_DEVICE: - memset(&s->dt, 0 , sizeof(s->dt)); - s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID); - - if (!s->dt.valid) { - break; - } - - s->dt.page_sz = page_sz; - s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT); - s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE); - - if (!s->dt.indirect) { - s->dt.max_entries = (num_pages * page_sz) / s->dt.entry_sz; - } else { - s->dt.max_entries = (((num_pages * page_sz) / - L1TABLE_ENTRY_SIZE) * - (page_sz / s->dt.entry_sz)); - } - - s->dt.max_ids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER, - DEVBITS) + 1)); - - s->dt.base_addr = baser_base_addr(value, page_sz); - + td = &s->dt; + idbits = FIELD_EX64(s->typer, GITS_TYPER, DEVBITS) + 1; break; - case GITS_BASER_TYPE_COLLECTION: - memset(&s->ct, 0 , sizeof(s->ct)); - s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID); - - /* - * GITS_TYPER.HCC is 0 for this implementation - * hence writes are discarded if ct.valid is 0 - */ - if (!s->ct.valid) { - break; - } - - s->ct.page_sz = page_sz; - s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT); - s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE); - - if (!s->ct.indirect) { - s->ct.max_entries = (num_pages * page_sz) / s->ct.entry_sz; - } else { - s->ct.max_entries = (((num_pages * page_sz) / - L1TABLE_ENTRY_SIZE) * - (page_sz / s->ct.entry_sz)); - } - + td = &s->ct; if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) { - s->ct.max_ids = (1UL << (FIELD_EX64(s->typer, - GITS_TYPER, CIDBITS) + 1)); + idbits = FIELD_EX64(s->typer, GITS_TYPER, CIDBITS) + 1; } else { /* 16-bit CollectionId supported when CIL == 0 */ - s->ct.max_ids = (1UL << 16); + idbits = 16; } - - s->ct.base_addr = baser_base_addr(value, page_sz); - break; - default: - break; + /* + * GITS_BASER.TYPE is read-only, so GITS_BASER_RO_MASK + * ensures we will only see type values corresponding to + * the values set up in gicv3_its_reset(). + */ + g_assert_not_reached(); } + + memset(td, 0, sizeof(*td)); + td->valid = FIELD_EX64(value, GITS_BASER, VALID); + /* + * If GITS_BASER.Valid is 0 for any then we will not process + * interrupts. (GITS_TYPER.HCC is 0 for this implementation, so we + * do not have a special case where the GITS_BASER.Valid bit is 0 + * for the register corresponding to the Collection table but we + * still have to process interrupts using non-memory-backed + * Collection table entries.) + */ + if (!td->valid) { + continue; + } + td->page_sz = page_sz; + td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT); + td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE); + td->base_addr = baser_base_addr(value, page_sz); + if (!td->indirect) { + td->max_entries = (num_pages * page_sz) / td->entry_sz; + } else { + td->max_entries = (((num_pages * page_sz) / + L1TABLE_ENTRY_SIZE) * + (page_sz / td->entry_sz)); + } + td->max_ids = 1ULL << idbits; } } From 9ae85431902dfa6dba594d639d1a37d709c56a73 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:07:58 +0000 Subject: [PATCH 250/730] hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We set the TableDesc entry_sz field from the appropriate GITS_BASER.ENTRYSIZE field. That ID register field specifies the number of bytes per table entry minus one. However when we use td->entry_sz we assume it to be the number of bytes per table entry (for instance we calculate the number of entries in a page by dividing the page size by the entry size). The effects of this bug are: * we miscalculate the maximum number of entries in the table, so our checks on guest index values are wrong (too lax) * when looking up an entry in the second level of an indirect table, we calculate an incorrect index into the L2 table. Because we make the same incorrect calculation on both reads and writes of the L2 table, the guest won't notice unless it's unlucky enough to use an index value that causes us to index off the end of the L2 table page and cause guest memory corruption in whatever follows Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson --- hw/intc/arm_gicv3_its.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 84808b1e29..88f4d73099 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -829,7 +829,7 @@ static void extract_table_params(GICv3ITSState *s) } td->page_sz = page_sz; td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT); - td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE); + td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE) + 1; td->base_addr = baser_base_addr(value, page_sz); if (!td->indirect) { td->max_entries = (num_pages * page_sz) / td->entry_sz; From 764d6ba10cce25d20ef9f3e11a83a9783dadf65f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:07:59 +0000 Subject: [PATCH 251/730] hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GITS_TYPE_PHYSICAL define is the value we set the GITS_TYPER.Physical field to -- this is 1 to indicate that we support physical LPIs. (Support for virtual LPIs is the GITS_TYPER.Virtual field.) We also use this define as the *value* that we write into an interrupt translation table entry's INTTYPE field, which should be 1 for a physical interrupt and 0 for a virtual interrupt. Finally, we use it as a *mask* when we read the interrupt translation table entry INTTYPE field. Untangle this confusion: define an ITE_INTTYPE_VIRTUAL and ITE_INTTYPE_PHYSICAL to be the valid values of the ITE INTTYPE field, and replace the ad-hoc collection of ITE_ENTRY_* defines with use of the FIELD() macro to define the fields of an ITE and the FIELD_EX64() and FIELD_DP64() macros to read and write them. We use ITE in the new setup, rather than ITE_ENTRY, because ITE stands for "Interrupt translation entry" and so the extra "entry" would be redundant. We take the opportunity to correct the name of the field that holds the GICv4 'doorbell' interrupt ID (this is always the value 1023 in a GICv3, which is why we were calling it the 'spurious' field). The GITS_TYPE_PHYSICAL define is then used in only one place, where we set the initial GITS_TYPER value. Since GITS_TYPER.Physical is essentially a boolean, hiding the '1' value behind a macro is more confusing than helpful, so expand out the macro there and remove the define entirely. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson --- hw/intc/arm_gicv3_its.c | 30 +++++++++++++----------------- hw/intc/gicv3_internal.h | 26 ++++++++++++++------------ 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 88f4d73099..15eb72a0a1 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -156,12 +156,11 @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte, MEMTXATTRS_UNSPECIFIED, res); if (*res == MEMTX_OK) { - if (ite.itel & TABLE_ENTRY_VALID_MASK) { - if ((ite.itel >> ITE_ENTRY_INTTYPE_SHIFT) & - GITS_TYPE_PHYSICAL) { - *pIntid = (ite.itel & ITE_ENTRY_INTID_MASK) >> - ITE_ENTRY_INTID_SHIFT; - *icid = ite.iteh & ITE_ENTRY_ICID_MASK; + if (FIELD_EX64(ite.itel, ITE_L, VALID)) { + int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE); + if (inttype == ITE_INTTYPE_PHYSICAL) { + *pIntid = FIELD_EX64(ite.itel, ITE_L, INTID); + *icid = FIELD_EX32(ite.iteh, ITE_H, ICID); status = true; } } @@ -342,8 +341,6 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, MemTxResult res = MEMTX_OK; uint16_t icid = 0; uint64_t dte = 0; - IteEntry ite; - uint32_t int_spurious = INTID_SPURIOUS; bool result = false; devid = ((value & DEVID_MASK) >> DEVID_SHIFT); @@ -400,16 +397,16 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, */ } else { /* add ite entry to interrupt translation table */ - ite.itel = (dte_valid & TABLE_ENTRY_VALID_MASK) | - (GITS_TYPE_PHYSICAL << ITE_ENTRY_INTTYPE_SHIFT); - + IteEntry ite = {}; + ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid); + ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL); if (ignore_pInt) { - ite.itel |= (eventid << ITE_ENTRY_INTID_SHIFT); + ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, eventid); } else { - ite.itel |= (pIntid << ITE_ENTRY_INTID_SHIFT); + ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid); } - ite.itel |= (int_spurious << ITE_ENTRY_INTSP_SHIFT); - ite.iteh = icid; + ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS); + ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid); result = update_ite(s, eventid, dte, ite); } @@ -1237,8 +1234,7 @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp) "gicv3-its-sysmem"); /* set the ITS default features supported */ - s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, - GITS_TYPE_PHYSICAL); + s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, 1); s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE, ITS_ITT_ENTRY_SIZE - 1); s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS); diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index 63de8667c6..5a63e9ed5c 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -354,28 +354,30 @@ FIELD(MAPC, RDBASE, 16, 32) #define L2_TABLE_VALID_MASK CMD_FIELD_VALID_MASK #define TABLE_ENTRY_VALID_MASK (1ULL << 0) -/** - * Default features advertised by this version of ITS - */ -/* Physical LPIs supported */ -#define GITS_TYPE_PHYSICAL (1U << 0) - /* * 12 bytes Interrupt translation Table Entry size * as per Table 5.3 in GICv3 spec * ITE Lower 8 Bytes * Bits: | 49 ... 26 | 25 ... 2 | 1 | 0 | - * Values: | 1023 | IntNum | IntType | Valid | + * Values: | Doorbell | IntNum | IntType | Valid | * ITE Higher 4 Bytes * Bits: | 31 ... 16 | 15 ...0 | * Values: | vPEID | ICID | + * (When Doorbell is unused, as it always is in GICv3, it is 1023) */ #define ITS_ITT_ENTRY_SIZE 0xC -#define ITE_ENTRY_INTTYPE_SHIFT 1 -#define ITE_ENTRY_INTID_SHIFT 2 -#define ITE_ENTRY_INTID_MASK MAKE_64BIT_MASK(2, 24) -#define ITE_ENTRY_INTSP_SHIFT 26 -#define ITE_ENTRY_ICID_MASK MAKE_64BIT_MASK(0, 16) + +FIELD(ITE_L, VALID, 0, 1) +FIELD(ITE_L, INTTYPE, 1, 1) +FIELD(ITE_L, INTID, 2, 24) +FIELD(ITE_L, DOORBELL, 26, 24) + +FIELD(ITE_H, ICID, 0, 16) +FIELD(ITE_H, VPEID, 16, 16) + +/* Possible values for ITE_L INTTYPE */ +#define ITE_INTTYPE_VIRTUAL 0 +#define ITE_INTTYPE_PHYSICAL 1 /* 16 bits EventId */ #define ITS_IDBITS GICD_TYPER_IDBITS From b87fab1c8e8977e8ea1233bafdbfa37090eefabf Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:07:59 +0000 Subject: [PATCH 252/730] hw/intc/arm_gicv3_its: Correct handling of MAPI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MAPI command takes arguments DeviceID, EventID, ICID, and is defined to be equivalent to MAPTI DeviceID, EventID, EventID, ICID. (That is, where MAPTI takes an explicit pINTID, MAPI uses the EventID as the pINTID.) We didn't quite get this right. In particular the error checks for MAPI include "EventID does not specify a valid LPI identifier", which is the same as MAPTI's error check for the pINTID field. QEMU's code skips the pINTID error check entirely in the MAPI case. We can fix this bug and in the process simplify the code by switching to the obvious implementation of setting pIntid = eventid early if ignore_pInt is true. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson --- hw/intc/arm_gicv3_its.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 15eb72a0a1..6f21c56fba 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -354,7 +354,9 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, eventid = (value & EVENTID_MASK); - if (!ignore_pInt) { + if (ignore_pInt) { + pIntid = eventid; + } else { pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT); } @@ -377,14 +379,12 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1)); - if (!ignore_pInt) { - max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1; - } + max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1; if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids) || !dte_valid || (eventid > max_eventid) || - (!ignore_pInt && (((pIntid < GICV3_LPI_INTID_START) || - (pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS)))) { + (((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) && + (pIntid != INTID_SPURIOUS))) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes " "devid %d or icid %d or eventid %d or pIntid %d or" @@ -400,11 +400,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, IteEntry ite = {}; ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid); ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL); - if (ignore_pInt) { - ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, eventid); - } else { - ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid); - } + ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid); ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS); ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid); From e07f844599525685db44ce74bf4ab12025d1d96a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:07:59 +0000 Subject: [PATCH 253/730] hw/intc/arm_gicv3_its: Use FIELD macros for DTEs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the ITS code that reads and writes DTEs uses open-coded shift-and-mask to assemble the various fields into the 64-bit DTE word. The names of the macros used for mask and shift values are also somewhat inconsistent, and don't follow our usual convention that a MASK macro should specify the bits in their place in the word. Replace all these with use of the FIELD macro. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson --- hw/intc/arm_gicv3_its.c | 20 +++++++++----------- hw/intc/gicv3_internal.h | 7 ++++--- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 6f21c56fba..7a217b00f8 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -114,7 +114,7 @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte, uint64_t itt_addr; MemTxResult res = MEMTX_OK; - itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT; + itt_addr = FIELD_EX64(dte, DTE, ITTADDR); itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */ address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) + @@ -141,7 +141,7 @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte, bool status = false; IteEntry ite = {}; - itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT; + itt_addr = FIELD_EX64(dte, DTE, ITTADDR); itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */ ite.itel = address_space_ldq_le(as, itt_addr + @@ -255,10 +255,10 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, if (res != MEMTX_OK) { return result; } - dte_valid = dte & TABLE_ENTRY_VALID_MASK; + dte_valid = FIELD_EX64(dte, DTE, VALID); if (dte_valid) { - max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1)); + max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1); ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res); @@ -375,10 +375,8 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, if (res != MEMTX_OK) { return result; } - dte_valid = dte & TABLE_ENTRY_VALID_MASK; - - max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1)); - + dte_valid = FIELD_EX64(dte, DTE, VALID); + max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1); max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1; if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids) @@ -529,9 +527,9 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid, if (s->dt.valid) { if (valid) { /* add mapping entry to device table */ - dte = (valid & TABLE_ENTRY_VALID_MASK) | - ((size & SIZE_MASK) << 1U) | - (itt_addr << GITS_DTE_ITTADDR_SHIFT); + dte = FIELD_DP64(dte, DTE, VALID, 1); + dte = FIELD_DP64(dte, DTE, SIZE, size); + dte = FIELD_DP64(dte, DTE, ITTADDR, itt_addr); } } else { return true; diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index 5a63e9ed5c..6a3b145f37 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -393,9 +393,10 @@ FIELD(ITE_H, VPEID, 16, 16) * Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits */ #define GITS_DTE_SIZE (0x8ULL) -#define GITS_DTE_ITTADDR_SHIFT 6 -#define GITS_DTE_ITTADDR_MASK MAKE_64BIT_MASK(GITS_DTE_ITTADDR_SHIFT, \ - ITTADDR_LENGTH) + +FIELD(DTE, VALID, 0, 1) +FIELD(DTE, SIZE, 1, 5) +FIELD(DTE, ITTADDR, 6, 44) /* * 8 bytes Collection Table Entry size From 257bb6501cda75e9ba0804cd5b45e17275928252 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:07:59 +0000 Subject: [PATCH 254/730] hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The comment says that in our CTE format the RDBase field is 36 bits; in fact for us it is only 16 bits, because we use the RDBase format where it specifies a 16-bit CPU number. The code already uses RDBASE_PROCNUM_LENGTH (16) as the field width, so fix the comment to match it. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson --- hw/intc/gicv3_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index 6a3b145f37..14e8ef68e0 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -400,7 +400,7 @@ FIELD(DTE, ITTADDR, 6, 44) /* * 8 bytes Collection Table Entry size - * Valid = 1 bit,RDBase = 36 bits(considering max RDBASE) + * Valid = 1 bit, RDBase = 16 bits */ #define GITS_CTE_SIZE (0x8ULL) #define GITS_CTE_RDBASE_PROCNUM_MASK MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH) From 437dc0ea982beb11cb9b4df82baf8aefe6af661c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:07:59 +0000 Subject: [PATCH 255/730] hw/intc/arm_gicv3_its: Use FIELD macros for CTEs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use FIELD macros to handle CTEs, rather than ad-hoc mask-and-shift. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson --- hw/intc/arm_gicv3_its.c | 7 ++++--- hw/intc/gicv3_internal.h | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 7a217b00f8..2949157df3 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -104,7 +104,7 @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte, MEMTXATTRS_UNSPECIFIED, res); } - return (*cte & TABLE_ENTRY_VALID_MASK) != 0; + return FIELD_EX64(*cte, CTE, VALID); } static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte, @@ -308,7 +308,7 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, * Current implementation only supports rdbase == procnum * Hence rdbase physical address is ignored */ - rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U; + rdbase = FIELD_EX64(cte, CTE, RDBASE); if (rdbase >= s->gicv3->num_cpu) { return result; @@ -426,7 +426,8 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid, if (valid) { /* add mapping entry to collection table */ - cte = (valid & TABLE_ENTRY_VALID_MASK) | (rdbase << 1ULL); + cte = FIELD_DP64(cte, CTE, VALID, 1); + cte = FIELD_DP64(cte, CTE, RDBASE, rdbase); } /* diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index 14e8ef68e0..1eeb99035d 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -403,7 +403,8 @@ FIELD(DTE, ITTADDR, 6, 44) * Valid = 1 bit, RDBase = 16 bits */ #define GITS_CTE_SIZE (0x8ULL) -#define GITS_CTE_RDBASE_PROCNUM_MASK MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH) +FIELD(CTE, VALID, 0, 1) +FIELD(CTE, RDBASE, 1, RDBASE_PROCNUM_LENGTH) /* Special interrupt IDs */ #define INTID_SECURE 1020 From 80dcd37feb3a249cdd6a96826836e267df5c7077 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:08:00 +0000 Subject: [PATCH 256/730] hw/intc/arm_gicv3_its: Fix various off-by-one errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ITS code has to check whether various parameters passed in commands are in-bounds, where the limit is defined in terms of the number of bits that are available for the parameter. (For example, the GITS_TYPER.Devbits ID register field specifies the number of DeviceID bits minus 1, and device IDs passed in the MAPTI and MAPD command packets must fit in that many bits.) Currently we have off-by-one bugs in many of these bounds checks. The typical problem is that we define a max_foo as 1 << n. In the Devbits example, we set s->dt.max_ids = 1UL << (GITS_TYPER.Devbits + 1). However later when we do the bounds check we write if (devid > s->dt.max_ids) { /* command error */ } which incorrectly permits a devid of 1 << n. These bugs will not cause QEMU crashes because the ID values being checked are only used for accesses into tables held in guest memory which we access with address_space_*() functions, but they are incorrect behaviour of our emulation. Fix them by standardizing on this pattern: * bounds limits are named num_foos and are the 2^n value (equal to the number of valid foo values) * bounds checks are either if (fooid < num_foos) { good } or if (fooid >= num_foos) { bad } In this commit we fix the handling of the number of IDs in the device table and the collection table, and the number of commands that will fit in the command queue. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée --- hw/intc/arm_gicv3_its.c | 26 +++++++++++++------------- include/hw/intc/arm_gicv3_its_common.h | 6 +++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 2949157df3..95c1914eb3 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -286,10 +286,10 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, * In this implementation, in case of guest errors we ignore the * command and move onto the next command in the queue. */ - if (devid > s->dt.max_ids) { + if (devid >= s->dt.num_ids) { qemu_log_mask(LOG_GUEST_ERROR, - "%s: invalid command attributes: devid %d>%d", - __func__, devid, s->dt.max_ids); + "%s: invalid command attributes: devid %d>=%d", + __func__, devid, s->dt.num_ids); } else if (!dte_valid || !ite_valid || !cte_valid) { qemu_log_mask(LOG_GUEST_ERROR, @@ -379,7 +379,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1); max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1; - if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids) + if ((devid >= s->dt.num_ids) || (icid >= s->ct.num_ids) || !dte_valid || (eventid > max_eventid) || (((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS))) { @@ -497,7 +497,7 @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset) valid = (value & CMD_FIELD_VALID_MASK); - if ((icid > s->ct.max_ids) || (rdbase >= s->gicv3->num_cpu)) { + if ((icid >= s->ct.num_ids) || (rdbase >= s->gicv3->num_cpu)) { qemu_log_mask(LOG_GUEST_ERROR, "ITS MAPC: invalid collection table attributes " "icid %d rdbase %" PRIu64 "\n", icid, rdbase); @@ -610,7 +610,7 @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset) valid = (value & CMD_FIELD_VALID_MASK); - if ((devid > s->dt.max_ids) || + if ((devid >= s->dt.num_ids) || (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) { qemu_log_mask(LOG_GUEST_ERROR, "ITS MAPD: invalid device table attributes " @@ -649,7 +649,7 @@ static void process_cmdq(GICv3ITSState *s) wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET); - if (wr_offset > s->cq.max_entries) { + if (wr_offset >= s->cq.num_entries) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid write offset " "%d\n", __func__, wr_offset); @@ -658,7 +658,7 @@ static void process_cmdq(GICv3ITSState *s) rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET); - if (rd_offset > s->cq.max_entries) { + if (rd_offset >= s->cq.num_entries) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid read offset " "%d\n", __func__, rd_offset); @@ -721,7 +721,7 @@ static void process_cmdq(GICv3ITSState *s) } if (result) { rd_offset++; - rd_offset %= s->cq.max_entries; + rd_offset %= s->cq.num_entries; s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset); } else { /* @@ -824,13 +824,13 @@ static void extract_table_params(GICv3ITSState *s) td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE) + 1; td->base_addr = baser_base_addr(value, page_sz); if (!td->indirect) { - td->max_entries = (num_pages * page_sz) / td->entry_sz; + td->num_entries = (num_pages * page_sz) / td->entry_sz; } else { - td->max_entries = (((num_pages * page_sz) / + td->num_entries = (((num_pages * page_sz) / L1TABLE_ENTRY_SIZE) * (page_sz / td->entry_sz)); } - td->max_ids = 1ULL << idbits; + td->num_ids = 1ULL << idbits; } } @@ -845,7 +845,7 @@ static void extract_cmdq_params(GICv3ITSState *s) s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID); if (s->cq.valid) { - s->cq.max_entries = (num_pages * GITS_PAGE_SIZE_4K) / + s->cq.num_entries = (num_pages * GITS_PAGE_SIZE_4K) / GITS_CMDQ_ENTRY_SIZE; s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR); s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT; diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h index 85a144b0e4..b32c697207 100644 --- a/include/hw/intc/arm_gicv3_its_common.h +++ b/include/hw/intc/arm_gicv3_its_common.h @@ -46,14 +46,14 @@ typedef struct { bool indirect; uint16_t entry_sz; uint32_t page_sz; - uint32_t max_entries; - uint32_t max_ids; + uint32_t num_entries; + uint32_t num_ids; uint64_t base_addr; } TableDesc; typedef struct { bool valid; - uint32_t max_entries; + uint32_t num_entries; uint64_t base_addr; } CmdQDesc; From 7f18ac3ab3337f3c83b2ab34001ef7c1bb4a43a7 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 7 Jan 2022 17:08:00 +0000 Subject: [PATCH 257/730] hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In several places we have a local variable max_l2_entries which is the number of entries which will fit in a level 2 table. The calculations done on this value are correct; rename it to num_l2_entries to fit the convention we're using in this code. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé --- hw/intc/arm_gicv3_its.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 95c1914eb3..fa3cdb5755 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -74,7 +74,7 @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte, uint64_t value; bool valid_l2t; uint32_t l2t_id; - uint32_t max_l2_entries; + uint32_t num_l2_entries; if (s->ct.indirect) { l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE); @@ -88,12 +88,12 @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte, valid_l2t = (value & L2_TABLE_VALID_MASK) != 0; if (valid_l2t) { - max_l2_entries = s->ct.page_sz / s->ct.entry_sz; + num_l2_entries = s->ct.page_sz / s->ct.entry_sz; l2t_addr = value & ((1ULL << 51) - 1); *cte = address_space_ldq_le(as, l2t_addr + - ((icid % max_l2_entries) * GITS_CTE_SIZE), + ((icid % num_l2_entries) * GITS_CTE_SIZE), MEMTXATTRS_UNSPECIFIED, res); } } @@ -176,7 +176,7 @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res) uint64_t value; bool valid_l2t; uint32_t l2t_id; - uint32_t max_l2_entries; + uint32_t num_l2_entries; if (s->dt.indirect) { l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE); @@ -190,12 +190,12 @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res) valid_l2t = (value & L2_TABLE_VALID_MASK) != 0; if (valid_l2t) { - max_l2_entries = s->dt.page_sz / s->dt.entry_sz; + num_l2_entries = s->dt.page_sz / s->dt.entry_sz; l2t_addr = value & ((1ULL << 51) - 1); value = address_space_ldq_le(as, l2t_addr + - ((devid % max_l2_entries) * GITS_DTE_SIZE), + ((devid % num_l2_entries) * GITS_DTE_SIZE), MEMTXATTRS_UNSPECIFIED, res); } } @@ -416,7 +416,7 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid, uint64_t l2t_addr; bool valid_l2t; uint32_t l2t_id; - uint32_t max_l2_entries; + uint32_t num_l2_entries; uint64_t cte = 0; MemTxResult res = MEMTX_OK; @@ -450,12 +450,12 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid, valid_l2t = (value & L2_TABLE_VALID_MASK) != 0; if (valid_l2t) { - max_l2_entries = s->ct.page_sz / s->ct.entry_sz; + num_l2_entries = s->ct.page_sz / s->ct.entry_sz; l2t_addr = value & ((1ULL << 51) - 1); address_space_stq_le(as, l2t_addr + - ((icid % max_l2_entries) * GITS_CTE_SIZE), + ((icid % num_l2_entries) * GITS_CTE_SIZE), cte, MEMTXATTRS_UNSPECIFIED, &res); } } else { @@ -521,7 +521,7 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid, uint64_t l2t_addr; bool valid_l2t; uint32_t l2t_id; - uint32_t max_l2_entries; + uint32_t num_l2_entries; uint64_t dte = 0; MemTxResult res = MEMTX_OK; @@ -556,12 +556,12 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid, valid_l2t = (value & L2_TABLE_VALID_MASK) != 0; if (valid_l2t) { - max_l2_entries = s->dt.page_sz / s->dt.entry_sz; + num_l2_entries = s->dt.page_sz / s->dt.entry_sz; l2t_addr = value & ((1ULL << 51) - 1); address_space_stq_le(as, l2t_addr + - ((devid % max_l2_entries) * GITS_DTE_SIZE), + ((devid % num_l2_entries) * GITS_DTE_SIZE), dte, MEMTXATTRS_UNSPECIFIED, &res); } } else { From 560223dcf0d9e83e26a85cec32d8aec272813d8e Mon Sep 17 00:00:00 2001 From: Chris Rauer Date: Fri, 7 Jan 2022 17:08:00 +0000 Subject: [PATCH 258/730] hw/arm: Add kudo i2c eeproms. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Chris Rauer Reviewed-by: Hao Wu Reviewed-by: Patrick Venture Reviewed-by: Philippe Mathieu-Daudé Message-id: 20220102215844.2888833-2-venture@google.com Signed-off-by: Peter Maydell --- hw/arm/npcm7xx_boards.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 0866d2f4f0..37de9fef43 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -328,6 +328,13 @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc) */ } +static void kudo_bmc_i2c_init(NPCM7xxState *soc) +{ + at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */ + at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */ + /* TODO: Add remaining i2c devices. */ +} + static void npcm750_evb_init(MachineState *machine) { NPCM7xxState *soc; @@ -391,6 +398,7 @@ static void kudo_bmc_init(MachineState *machine) npcm7xx_connect_flash(&soc->fiu[1], 0, "mx66u51235f", drive_get(IF_MTD, 3, 0)); + kudo_bmc_i2c_init(soc); npcm7xx_load_kernel(machine, soc); } From b27de2c57b28eac963fa0e35cad8a2a3b7977fc4 Mon Sep 17 00:00:00 2001 From: Shengtan Mao Date: Fri, 7 Jan 2022 17:08:00 +0000 Subject: [PATCH 259/730] hw/arm: attach MMC to kudo-bmc Signed-off-by: Shengtan Mao Reviewed-by: Hao Wu Reviewed-by: Chris Rauer Message-id: 20220102215844.2888833-3-venture@google.com Signed-off-by: Peter Maydell --- hw/arm/npcm7xx_boards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 37de9fef43..257bf638fd 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -399,6 +399,7 @@ static void kudo_bmc_init(MachineState *machine) drive_get(IF_MTD, 3, 0)); kudo_bmc_i2c_init(soc); + sdhci_attach_drive(&soc->mmc.sdhci, 0); npcm7xx_load_kernel(machine, soc); } From 5b0829d38cccdbf05531521e45bbaf87a2f98402 Mon Sep 17 00:00:00 2001 From: Patrick Venture Date: Fri, 7 Jan 2022 17:08:00 +0000 Subject: [PATCH 260/730] hw/arm: add i2c muxes to kudo-bmc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrick Venture Reviewed-by: Hao Wu Reviewed-by: Philippe Mathieu-Daudé Message-id: 20220102215844.2888833-4-venture@google.com Signed-off-by: Peter Maydell --- hw/arm/npcm7xx_boards.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 257bf638fd..4cd58972c5 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -330,8 +330,17 @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc) static void kudo_bmc_i2c_init(NPCM7xxState *soc) { + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x75); + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x77); + + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), TYPE_PCA9548, 0x77); + at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */ + + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), TYPE_PCA9548, 0x77); + at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */ + /* TODO: Add remaining i2c devices. */ } From b8905cc2dde95ca6be5e56d77053b1ca0b8fc182 Mon Sep 17 00:00:00 2001 From: Patrick Venture Date: Fri, 7 Jan 2022 17:08:01 +0000 Subject: [PATCH 261/730] hw/arm: kudo add lm75s on bus 13 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the four lm75s behind the mux on bus 13. Tested by booting the firmware: lm75 42-0048: hwmon0: sensor 'lm75' lm75 43-0049: supply vs not found, using dummy regulator lm75 43-0049: hwmon1: sensor 'lm75' lm75 44-0048: supply vs not found, using dummy regulator lm75 44-0048: hwmon2: sensor 'lm75' lm75 45-0049: supply vs not found, using dummy regulator lm75 45-0049: hwmon3: sensor 'lm75' Signed-off-by: Patrick Venture Reviewed-by: Titus Rwantare Reviewed-by: Philippe Mathieu-Daudé Message-id: 20220102215844.2888833-5-venture@google.com Signed-off-by: Peter Maydell --- hw/arm/npcm7xx_boards.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 4cd58972c5..7d0f3148be 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -330,6 +330,8 @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc) static void kudo_bmc_i2c_init(NPCM7xxState *soc) { + I2CSlave *i2c_mux; + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x75); i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x77); @@ -337,7 +339,14 @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc) at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */ - i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), TYPE_PCA9548, 0x77); + i2c_mux = i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), + TYPE_PCA9548, 0x77); + + /* tmp105 is compatible with the lm75 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 2), "tmp105", 0x48); + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 3), "tmp105", 0x49); + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 4), "tmp105", 0x48); + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), "tmp105", 0x49); at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */ From 29b838c05dc20fa00fc08e952f710478829aa1c7 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 17 Dec 2021 14:46:10 +0100 Subject: [PATCH 262/730] util/oslib-posix: Forward SIGBUS to MCE handler under Linux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Temporarily modifying the SIGBUS handler is really nasty, as we might be unlucky and receive an MCE SIGBUS while having our handler registered. Unfortunately, there is no way around messing with SIGBUS when MADV_POPULATE_WRITE is not applicable or not around. Let's forward SIGBUS that don't belong to us to the already registered handler and document the situation. Reviewed-by: Daniel P. Berrangé Reviewed-by: Michal Privoznik Signed-off-by: David Hildenbrand Message-Id: <20211217134611.31172-8-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- softmmu/cpus.c | 4 ++++ util/oslib-posix.c | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 071085f840..23bca46b07 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -352,6 +352,10 @@ static void qemu_init_sigbus(void) { struct sigaction action; + /* + * ALERT: when modifying this, take care that SIGBUS forwarding in + * os_mem_prealloc() will continue working as expected. + */ memset(&action, 0, sizeof(action)); action.sa_flags = SA_SIGINFO; action.sa_sigaction = sigbus_handler; diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 9829149e4b..9efdc74bba 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -35,6 +35,7 @@ #include "sysemu/sysemu.h" #include "trace.h" #include "qapi/error.h" +#include "qemu/error-report.h" #include "qemu/sockets.h" #include "qemu/thread.h" #include @@ -95,6 +96,7 @@ typedef struct MemsetThread MemsetThread; /* used by sigbus_handler() */ static MemsetContext *sigbus_memset_context; +struct sigaction sigbus_oldact; static QemuMutex sigbus_mutex; static QemuMutex page_mutex; @@ -446,7 +448,11 @@ const char *qemu_get_exec_dir(void) return exec_dir; } +#ifdef CONFIG_LINUX +static void sigbus_handler(int signal, siginfo_t *siginfo, void *ctx) +#else /* CONFIG_LINUX */ static void sigbus_handler(int signal) +#endif /* CONFIG_LINUX */ { int i; @@ -459,6 +465,26 @@ static void sigbus_handler(int signal) } } } + +#ifdef CONFIG_LINUX + /* + * We assume that the MCE SIGBUS handler could have been registered. We + * should never receive BUS_MCEERR_AO on any of our threads, but only on + * the main thread registered for PR_MCE_KILL_EARLY. Further, we should not + * receive BUS_MCEERR_AR triggered by action of other threads on one of + * our threads. So, no need to check for unrelated SIGBUS when seeing one + * for our threads. + * + * We will forward to the MCE handler, which will either handle the SIGBUS + * or reinstall the default SIGBUS handler and reraise the SIGBUS. The + * default SIGBUS handler will crash the process, so we don't care. + */ + if (sigbus_oldact.sa_flags & SA_SIGINFO) { + sigbus_oldact.sa_sigaction(signal, siginfo, ctx); + return; + } +#endif /* CONFIG_LINUX */ + warn_report("os_mem_prealloc: unrelated SIGBUS detected and ignored"); } static void *do_touch_pages(void *arg) @@ -628,10 +654,10 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, { static gsize initialized; int ret; - struct sigaction act, oldact; size_t hpagesize = qemu_fd_getpagesize(fd); size_t numpages = DIV_ROUND_UP(memory, hpagesize); bool use_madv_populate_write; + struct sigaction act; /* * Sense on every invocation, as MADV_POPULATE_WRITE cannot be used for @@ -647,10 +673,15 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, qemu_mutex_lock(&sigbus_mutex); memset(&act, 0, sizeof(act)); +#ifdef CONFIG_LINUX + act.sa_sigaction = &sigbus_handler; + act.sa_flags = SA_SIGINFO; +#else /* CONFIG_LINUX */ act.sa_handler = &sigbus_handler; act.sa_flags = 0; +#endif /* CONFIG_LINUX */ - ret = sigaction(SIGBUS, &act, &oldact); + ret = sigaction(SIGBUS, &act, &sigbus_oldact); if (ret) { error_setg_errno(errp, errno, "os_mem_prealloc: failed to install signal handler"); @@ -667,7 +698,7 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, } if (!use_madv_populate_write) { - ret = sigaction(SIGBUS, &oldact, NULL); + ret = sigaction(SIGBUS, &sigbus_oldact, NULL); if (ret) { /* Terminate QEMU since it can't recover from error */ perror("os_mem_prealloc: failed to reinstall signal handler"); From 09b3b7e092ca1d8c096fdda33d1d48b8c229d3c2 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 17 Dec 2021 14:46:11 +0100 Subject: [PATCH 263/730] virtio-mem: Support "prealloc=on" option For scarce memory resources, such as hugetlb, we want to be able to prealloc such memory resources in order to not crash later on access. On simple user errors we could otherwise easily run out of memory resources an crash the VM -- pretty much undesired. For ordinary memory devices, such as DIMMs, we preallocate memory via the memory backend for such use cases; however, with virtio-mem we're dealing with sparse memory backends; preallocating the whole memory backend destroys the whole purpose of virtio-mem. Instead, we want to preallocate memory when actually exposing memory to the VM dynamically, and fail plugging memory gracefully + warn the user in case preallocation fails. A common use case for hugetlb will be using "reserve=off,prealloc=off" for the memory backend and "prealloc=on" for the virtio-mem device. This way, no huge pages will be reserved for the process, but we can recover if there are no actual huge pages when plugging memory. Libvirt is already prepared for this. Note that preallocation cannot protect from the OOM killer -- which holds true for any kind of preallocation in QEMU. It's primarily useful only for scarce memory resources such as hugetlb, or shared file-backed memory. It's of little use for ordinary anonymous memory that can be swapped, KSM merged, ... but we won't forbid it. Reviewed-by: Michal Privoznik Signed-off-by: David Hildenbrand Message-Id: <20211217134611.31172-9-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-mem.c | 39 ++++++++++++++++++++++++++++++---- include/hw/virtio/virtio-mem.h | 4 ++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index 341c3fa2c1..ab975ff566 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -429,10 +429,40 @@ static int virtio_mem_set_block_state(VirtIOMEM *vmem, uint64_t start_gpa, return -EBUSY; } virtio_mem_notify_unplug(vmem, offset, size); - } else if (virtio_mem_notify_plug(vmem, offset, size)) { - /* Could be a mapping attempt resulted in memory getting populated. */ - ram_block_discard_range(vmem->memdev->mr.ram_block, offset, size); - return -EBUSY; + } else { + int ret = 0; + + if (vmem->prealloc) { + void *area = memory_region_get_ram_ptr(&vmem->memdev->mr) + offset; + int fd = memory_region_get_fd(&vmem->memdev->mr); + Error *local_err = NULL; + + os_mem_prealloc(fd, area, size, 1, &local_err); + if (local_err) { + static bool warned; + + /* + * Warn only once, we don't want to fill the log with these + * warnings. + */ + if (!warned) { + warn_report_err(local_err); + warned = true; + } else { + error_free(local_err); + } + ret = -EBUSY; + } + } + if (!ret) { + ret = virtio_mem_notify_plug(vmem, offset, size); + } + + if (ret) { + /* Could be preallocation or a notifier populated memory. */ + ram_block_discard_range(vmem->memdev->mr.ram_block, offset, size); + return -EBUSY; + } } virtio_mem_set_bitmap(vmem, start_gpa, size, plug); return 0; @@ -1108,6 +1138,7 @@ static void virtio_mem_instance_init(Object *obj) static Property virtio_mem_properties[] = { DEFINE_PROP_UINT64(VIRTIO_MEM_ADDR_PROP, VirtIOMEM, addr, 0), DEFINE_PROP_UINT32(VIRTIO_MEM_NODE_PROP, VirtIOMEM, node, 0), + DEFINE_PROP_BOOL(VIRTIO_MEM_PREALLOC_PROP, VirtIOMEM, prealloc, false), DEFINE_PROP_LINK(VIRTIO_MEM_MEMDEV_PROP, VirtIOMEM, memdev, TYPE_MEMORY_BACKEND, HostMemoryBackend *), DEFINE_PROP_END_OF_LIST(), diff --git a/include/hw/virtio/virtio-mem.h b/include/hw/virtio/virtio-mem.h index a5dd6a493b..0ac7bcb3b6 100644 --- a/include/hw/virtio/virtio-mem.h +++ b/include/hw/virtio/virtio-mem.h @@ -30,6 +30,7 @@ OBJECT_DECLARE_TYPE(VirtIOMEM, VirtIOMEMClass, #define VIRTIO_MEM_REQUESTED_SIZE_PROP "requested-size" #define VIRTIO_MEM_BLOCK_SIZE_PROP "block-size" #define VIRTIO_MEM_ADDR_PROP "memaddr" +#define VIRTIO_MEM_PREALLOC_PROP "prealloc" struct VirtIOMEM { VirtIODevice parent_obj; @@ -62,6 +63,9 @@ struct VirtIOMEM { /* block size and alignment */ uint64_t block_size; + /* whether to prealloc memory when plugging new blocks */ + bool prealloc; + /* notifiers to notify when "size" changes */ NotifierList size_change_notifiers; From 750539c4c4f446e12deb13fdb95d52a3466e2dff Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 30 Nov 2021 13:45:10 +0000 Subject: [PATCH 264/730] virtio: signal after wrapping packed used_idx Packed Virtqueues wrap used_idx instead of letting it run freely like Split Virtqueues do. If the used ring wraps more than once there is no way to compare vq->signalled_used and vq->used_idx in virtio_packed_should_notify() since they are modulo vq->vring.num. This causes the device to stop sending used buffer notifications when when virtio_packed_should_notify() is called less than once each time around the used ring. It is possible to trigger this with virtio-blk's dataplane notify_guest_bh() irq coalescing optimization. The call to virtio_notify_irqfd() (and virtio_packed_should_notify()) is deferred to a BH. If the guest driver is polling it can complete and submit more requests before the BH executes, causing the used ring to wrap more than once. The result is that the virtio-blk device ceases to raise interrupts and I/O hangs. Cc: Tiwei Bie Cc: Jason Wang Cc: Michael S. Tsirkin Signed-off-by: Stefan Hajnoczi Message-Id: <20211130134510.267382-1-stefanha@redhat.com> Fixes: 86044b24e865fb9596ed77a4d0f3af8b90a088a1 ("virtio: basic packed virtqueue support") Acked-by: Jason Wang Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 36edb1dad5..971e59a663 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -885,6 +885,7 @@ static void virtqueue_packed_flush(VirtQueue *vq, unsigned int count) if (vq->used_idx >= vq->vring.num) { vq->used_idx -= vq->vring.num; vq->used_wrap_counter ^= 1; + vq->signalled_used_valid = false; } } From d135536d5f33aeb0c5a937901bccc13fc0f01187 Mon Sep 17 00:00:00 2001 From: Ani Sinha Date: Mon, 13 Dec 2021 10:29:24 +0530 Subject: [PATCH 265/730] MAINTAINERS: Add a separate entry for acpi/VIOT tables All work related to VIOT tables are being done by Jean. Adding him as the maintainer for acpi VIOT table code in qemu. Signed-off-by: Ani Sinha Message-Id: <20211213045924.344214-1-ani@anisinha.ca> Acked-by: Jean-Philippe Brucker Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f871d759fd..6aa0335560 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1777,6 +1777,13 @@ F: docs/specs/acpi_mem_hotplug.rst F: docs/specs/acpi_pci_hotplug.rst F: docs/specs/acpi_hw_reduced_hotplug.rst +ACPI/VIOT +M: Jean-Philippe Brucker +R: Ani Sinha +S: Supported +F: hw/acpi/viot.c +F: hw/acpi/viot.h + ACPI/HEST/GHES R: Dongjiu Geng L: qemu-arm@nongnu.org From 3ff9b192de6501e5f15de2586b8560966436bf25 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 17 Dec 2021 14:40:37 +0100 Subject: [PATCH 266/730] linux-headers: sync VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE Let's synchronize the new feature flag, available in Linux since v5.16-rc1. Reviewed-by: Michal Privoznik Signed-off-by: David Hildenbrand Message-Id: <20211217134039.29670-2-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/standard-headers/linux/virtio_mem.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/standard-headers/linux/virtio_mem.h b/include/standard-headers/linux/virtio_mem.h index 05e5ade75d..18c74c527c 100644 --- a/include/standard-headers/linux/virtio_mem.h +++ b/include/standard-headers/linux/virtio_mem.h @@ -68,9 +68,10 @@ * explicitly triggered (VIRTIO_MEM_REQ_UNPLUG). * * There are no guarantees what will happen if unplugged memory is - * read/written. Such memory should, in general, not be touched. E.g., - * even writing might succeed, but the values will simply be discarded at - * random points in time. + * read/written. In general, unplugged memory should not be touched, because + * the resulting action is undefined. There is one exception: without + * VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, unplugged memory inside the usable + * region can be read, to simplify creation of memory dumps. * * It can happen that the device cannot process a request, because it is * busy. The device driver has to retry later. @@ -87,6 +88,8 @@ /* node_id is an ACPI PXM and is valid */ #define VIRTIO_MEM_F_ACPI_PXM 0 +/* unplugged memory must not be accessed */ +#define VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE 1 /* --- virtio-mem: guest -> host requests --- */ From 23ad8dec8d324d1fa027612eac9288e23d796a14 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 17 Dec 2021 14:40:38 +0100 Subject: [PATCH 267/730] virtio-mem: Support VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE With VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, we signal the VM that reading unplugged memory is not supported. We have to fail feature negotiation in case the guest does not support VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE. First, VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE is required to properly handle memory backends (or architectures) without support for the shared zeropage in the hypervisor cleanly. Without the shared zeropage, even reading an unpopulated virtual memory location can populate real memory and consequently consume memory in the hypervisor. We have a guaranteed shared zeropage only on MAP_PRIVATE anonymous memory. Second, we want VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE to be the default long-term as even populating the shared zeropage can be problematic: for example, without THP support (possible) or without support for the shared huge zeropage with THP (unlikely), the PTE page tables to hold the shared zeropage entries can consume quite some memory that cannot be reclaimed easily. Third, there are other optimizations+features (e.g., protection of unplugged memory, reducing the total memory slot size and bitmap sizes) that will require VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE. We really only support x86 targets with virtio-mem for now (and Linux similarly only support x86), but that might change soon, so prepare for different targets already. Add a new "unplugged-inaccessible" tristate property for x86 targets: - "off" will keep VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE unset and legacy guests working. - "on" will set VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE and stop legacy guests from using the device. - "auto" selects the default based on support for the shared zeropage. Warn in case the property is set to "off" and we don't have support for the shared zeropage. For existing compat machines, the property will default to "off", to not change the behavior but eventually warn about a problematic setup. Short-term, we'll set the property default to "auto" for new QEMU machines. Mid-term, we'll set the property default to "on" for new QEMU machines. Long-term, we'll deprecate the parameter and disallow legacy guests completely. The property has to match on the migration source and destination. "auto" will result in the same VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE setting as long as the qemu command line (esp. memdev) match -- so "auto" is good enough for migration purposes and the parameter doesn't have to be migrated explicitly. Reviewed-by: Michal Privoznik Signed-off-by: David Hildenbrand Message-Id: <20211217134039.29670-3-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-mem.c | 63 ++++++++++++++++++++++++++++++++++ include/hw/virtio/virtio-mem.h | 8 +++++ 2 files changed, 71 insertions(+) diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index ab975ff566..fb6687d4c7 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -32,6 +32,14 @@ #include CONFIG_DEVICES #include "trace.h" +/* + * We only had legacy x86 guests that did not support + * VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE. Other targets don't have legacy guests. + */ +#if defined(TARGET_X86_64) || defined(TARGET_I386) +#define VIRTIO_MEM_HAS_LEGACY_GUESTS +#endif + /* * Let's not allow blocks smaller than 1 MiB, for example, to keep the tracking * bitmap small. @@ -110,6 +118,19 @@ static uint64_t virtio_mem_default_block_size(RAMBlock *rb) return MAX(page_size, VIRTIO_MEM_MIN_BLOCK_SIZE); } +#if defined(VIRTIO_MEM_HAS_LEGACY_GUESTS) +static bool virtio_mem_has_shared_zeropage(RAMBlock *rb) +{ + /* + * We only have a guaranteed shared zeropage on ordinary MAP_PRIVATE + * anonymous RAM. In any other case, reading unplugged *can* populate a + * fresh page, consuming actual memory. + */ + return !qemu_ram_is_shared(rb) && rb->fd < 0 && + qemu_ram_pagesize(rb) == qemu_real_host_page_size; +} +#endif /* VIRTIO_MEM_HAS_LEGACY_GUESTS */ + /* * Size the usable region bigger than the requested size if possible. Esp. * Linux guests will only add (aligned) memory blocks in case they fully @@ -683,15 +704,29 @@ static uint64_t virtio_mem_get_features(VirtIODevice *vdev, uint64_t features, Error **errp) { MachineState *ms = MACHINE(qdev_get_machine()); + VirtIOMEM *vmem = VIRTIO_MEM(vdev); if (ms->numa_state) { #if defined(CONFIG_ACPI) virtio_add_feature(&features, VIRTIO_MEM_F_ACPI_PXM); #endif } + assert(vmem->unplugged_inaccessible != ON_OFF_AUTO_AUTO); + if (vmem->unplugged_inaccessible == ON_OFF_AUTO_ON) { + virtio_add_feature(&features, VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE); + } return features; } +static int virtio_mem_validate_features(VirtIODevice *vdev) +{ + if (virtio_host_has_feature(vdev, VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE) && + !virtio_vdev_has_feature(vdev, VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE)) { + return -EFAULT; + } + return 0; +} + static void virtio_mem_system_reset(void *opaque) { VirtIOMEM *vmem = VIRTIO_MEM(opaque); @@ -746,6 +781,29 @@ static void virtio_mem_device_realize(DeviceState *dev, Error **errp) rb = vmem->memdev->mr.ram_block; page_size = qemu_ram_pagesize(rb); +#if defined(VIRTIO_MEM_HAS_LEGACY_GUESTS) + switch (vmem->unplugged_inaccessible) { + case ON_OFF_AUTO_AUTO: + if (virtio_mem_has_shared_zeropage(rb)) { + vmem->unplugged_inaccessible = ON_OFF_AUTO_OFF; + } else { + vmem->unplugged_inaccessible = ON_OFF_AUTO_ON; + } + break; + case ON_OFF_AUTO_OFF: + if (!virtio_mem_has_shared_zeropage(rb)) { + warn_report("'%s' property set to 'off' with a memdev that does" + " not support the shared zeropage.", + VIRTIO_MEM_UNPLUGGED_INACCESSIBLE_PROP); + } + break; + default: + break; + } +#else /* VIRTIO_MEM_HAS_LEGACY_GUESTS */ + vmem->unplugged_inaccessible = ON_OFF_AUTO_ON; +#endif /* VIRTIO_MEM_HAS_LEGACY_GUESTS */ + /* * If the block size wasn't configured by the user, use a sane default. This * allows using hugetlbfs backends of any page size without manual @@ -1141,6 +1199,10 @@ static Property virtio_mem_properties[] = { DEFINE_PROP_BOOL(VIRTIO_MEM_PREALLOC_PROP, VirtIOMEM, prealloc, false), DEFINE_PROP_LINK(VIRTIO_MEM_MEMDEV_PROP, VirtIOMEM, memdev, TYPE_MEMORY_BACKEND, HostMemoryBackend *), +#if defined(VIRTIO_MEM_HAS_LEGACY_GUESTS) + DEFINE_PROP_ON_OFF_AUTO(VIRTIO_MEM_UNPLUGGED_INACCESSIBLE_PROP, VirtIOMEM, + unplugged_inaccessible, ON_OFF_AUTO_OFF), +#endif DEFINE_PROP_END_OF_LIST(), }; @@ -1279,6 +1341,7 @@ static void virtio_mem_class_init(ObjectClass *klass, void *data) vdc->unrealize = virtio_mem_device_unrealize; vdc->get_config = virtio_mem_get_config; vdc->get_features = virtio_mem_get_features; + vdc->validate_features = virtio_mem_validate_features; vdc->vmsd = &vmstate_virtio_mem_device; vmc->fill_device_info = virtio_mem_fill_device_info; diff --git a/include/hw/virtio/virtio-mem.h b/include/hw/virtio/virtio-mem.h index 0ac7bcb3b6..7745cfc1a3 100644 --- a/include/hw/virtio/virtio-mem.h +++ b/include/hw/virtio/virtio-mem.h @@ -30,6 +30,7 @@ OBJECT_DECLARE_TYPE(VirtIOMEM, VirtIOMEMClass, #define VIRTIO_MEM_REQUESTED_SIZE_PROP "requested-size" #define VIRTIO_MEM_BLOCK_SIZE_PROP "block-size" #define VIRTIO_MEM_ADDR_PROP "memaddr" +#define VIRTIO_MEM_UNPLUGGED_INACCESSIBLE_PROP "unplugged-inaccessible" #define VIRTIO_MEM_PREALLOC_PROP "prealloc" struct VirtIOMEM { @@ -63,6 +64,13 @@ struct VirtIOMEM { /* block size and alignment */ uint64_t block_size; + /* + * Whether we indicate VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE to the guest. + * For !x86 targets this will always be "on" and consequently indicate + * VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE. + */ + OnOffAuto unplugged_inaccessible; + /* whether to prealloc memory when plugging new blocks */ bool prealloc; From 60f1f77cabe42995fe8dff2bf8e874846339b5c0 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 17 Dec 2021 14:40:39 +0100 Subject: [PATCH 268/730] virtio-mem: Set "unplugged-inaccessible=auto" for the 7.0 machine on x86 Set the new default to "auto", keeping it set to "off" for compat machines. This property is only available for x86 targets. Reviewed-by: Michal Privoznik Reviewed-by: Pankaj Gupta Signed-off-by: David Hildenbrand Message-Id: <20211217134039.29670-4-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 4 +++- hw/virtio/virtio-mem.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 959efa5b3f..718ab81ba8 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -95,7 +95,9 @@ #include "trace.h" #include CONFIG_DEVICES -GlobalProperty pc_compat_6_2[] = {}; +GlobalProperty pc_compat_6_2[] = { + { "virtio-mem", "unplugged-inaccessible", "off" }, +}; const size_t pc_compat_6_2_len = G_N_ELEMENTS(pc_compat_6_2); GlobalProperty pc_compat_6_1[] = { diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index fb6687d4c7..04c223b0c9 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -1201,7 +1201,7 @@ static Property virtio_mem_properties[] = { TYPE_MEMORY_BACKEND, HostMemoryBackend *), #if defined(VIRTIO_MEM_HAS_LEGACY_GUESTS) DEFINE_PROP_ON_OFF_AUTO(VIRTIO_MEM_UNPLUGGED_INACCESSIBLE_PROP, VirtIOMEM, - unplugged_inaccessible, ON_OFF_AUTO_OFF), + unplugged_inaccessible, ON_OFF_AUTO_AUTO), #endif DEFINE_PROP_END_OF_LIST(), }; From 5178d78f4b61cad647d628f52922970cdfe119b6 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 5 Jan 2022 12:19:42 +0800 Subject: [PATCH 269/730] intel-iommu: correctly check passthrough during translation When scalable mode is enabled, the passthrough more is not determined by the context entry but PASID entry, so switch to use the logic of vtd_dev_pt_enabled() to determine the passthrough mode in vtd_do_iommu_translate(). Signed-off-by: Jason Wang Message-Id: <20220105041945.13459-2-jasowang@redhat.com> Reviewed-by: Peter Xu Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/intel_iommu.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 5b865ac08c..4c6c016388 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -1516,11 +1516,29 @@ static int vtd_sync_shadow_page_table(VTDAddressSpace *vtd_as) * 1st-level translation or 2nd-level translation, it depends * on PGTT setting. */ -static bool vtd_dev_pt_enabled(VTDAddressSpace *as) +static bool vtd_dev_pt_enabled(IntelIOMMUState *s, VTDContextEntry *ce) +{ + VTDPASIDEntry pe; + int ret; + + if (s->root_scalable) { + ret = vtd_ce_get_rid2pasid_entry(s, ce, &pe); + if (ret) { + error_report_once("%s: vtd_ce_get_rid2pasid_entry error: %"PRId32, + __func__, ret); + return false; + } + return (VTD_PE_GET_TYPE(&pe) == VTD_SM_PASID_ENTRY_PT); + } + + return (vtd_ce_get_type(ce) == VTD_CONTEXT_TT_PASS_THROUGH); + +} + +static bool vtd_as_pt_enabled(VTDAddressSpace *as) { IntelIOMMUState *s; VTDContextEntry ce; - VTDPASIDEntry pe; int ret; assert(as); @@ -1538,17 +1556,7 @@ static bool vtd_dev_pt_enabled(VTDAddressSpace *as) return false; } - if (s->root_scalable) { - ret = vtd_ce_get_rid2pasid_entry(s, &ce, &pe); - if (ret) { - error_report_once("%s: vtd_ce_get_rid2pasid_entry error: %"PRId32, - __func__, ret); - return false; - } - return (VTD_PE_GET_TYPE(&pe) == VTD_SM_PASID_ENTRY_PT); - } - - return (vtd_ce_get_type(&ce) == VTD_CONTEXT_TT_PASS_THROUGH); + return vtd_dev_pt_enabled(s, &ce); } /* Return whether the device is using IOMMU translation. */ @@ -1560,7 +1568,7 @@ static bool vtd_switch_address_space(VTDAddressSpace *as) assert(as); - use_iommu = as->iommu_state->dmar_enabled && !vtd_dev_pt_enabled(as); + use_iommu = as->iommu_state->dmar_enabled && !vtd_as_pt_enabled(as); trace_vtd_switch_address_space(pci_bus_num(as->bus), VTD_PCI_SLOT(as->devfn), @@ -1753,7 +1761,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace *vtd_as, PCIBus *bus, * We don't need to translate for pass-through context entries. * Also, let's ignore IOTLB caching as well for PT devices. */ - if (vtd_ce_get_type(&ce) == VTD_CONTEXT_TT_PASS_THROUGH) { + if (vtd_dev_pt_enabled(s, &ce)) { entry->iova = addr & VTD_PAGE_MASK_4K; entry->translated_addr = entry->iova; entry->addr_mask = ~VTD_PAGE_MASK_4K; From 8cdb99af45365727ac17f45239a9b8c1d5155c6d Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 27 Dec 2021 14:31:17 -0500 Subject: [PATCH 270/730] acpi: fix QEMU crash when started with SLIC table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit if QEMU is started with used provided SLIC table blob, -acpitable sig=SLIC,oem_id='CRASH ',oem_table_id="ME",oem_rev=00002210,asl_compiler_id="",asl_compiler_rev=00000000,data=/dev/null it will assert with: hw/acpi/aml-build.c:61:build_append_padded_str: assertion failed: (len <= maxlen) and following backtrace: ... build_append_padded_str (array=0x555556afe320, str=0x555556afdb2e "CRASH ME", maxlen=0x6, pad=0x20) at hw/acpi/aml-build.c:61 acpi_table_begin (desc=0x7fffffffd1b0, array=0x555556afe320) at hw/acpi/aml-build.c:1727 build_fadt (tbl=0x555556afe320, linker=0x555557ca3830, f=0x7fffffffd318, oem_id=0x555556afdb2e "CRASH ME", oem_table_id=0x555556afdb34 "ME") at hw/acpi/aml-build.c:2064 ... which happens due to acpi_table_begin() expecting NULL terminated oem_id and oem_table_id strings, which is normally the case, but in case of user provided SLIC table, oem_id points to table's blob directly and as result oem_id became longer than expected. Fix issue by handling oem_id consistently and make acpi_get_slic_oem() return NULL terminated strings. PS: After [1] refactoring, oem_id semantics became inconsistent, where NULL terminated string was coming from machine and old way pointer into byte array coming from -acpitable option. That used to work since build_header() wasn't expecting NULL terminated string and blindly copied the 1st 6 bytes only. However commit [2] broke that by replacing build_header() with acpi_table_begin(), which was expecting NULL terminated string and was checking oem_id size. 1) 602b45820 ("acpi: Permit OEM ID and OEM table ID fields to be changed") 2) Fixes: 4b56e1e4eb08 ("acpi: build_fadt: use acpi_table_begin()/acpi_table_end() instead of build_header()") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/786 Signed-off-by: Igor Mammedov Message-Id: <20211227193120.1084176-2-imammedo@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Tested-by: Denis Lisov Tested-by: Alexander Tsoy Cc: qemu-stable@nongnu.org Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/core.c | 4 ++-- hw/i386/acpi-build.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/acpi/core.c b/hw/acpi/core.c index 1e004d0078..3e811bf03c 100644 --- a/hw/acpi/core.c +++ b/hw/acpi/core.c @@ -345,8 +345,8 @@ int acpi_get_slic_oem(AcpiSlicOem *oem) struct acpi_table_header *hdr = (void *)(u - sizeof(hdr->_length)); if (memcmp(hdr->sig, "SLIC", 4) == 0) { - oem->id = hdr->oem_id; - oem->table_id = hdr->oem_table_id; + oem->id = g_strndup(hdr->oem_id, 6); + oem->table_id = g_strndup(hdr->oem_table_id, 8); return 0; } } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 8383b83ee3..0234fe7588 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2723,6 +2723,8 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) /* Cleanup memory that's no longer used. */ g_array_free(table_offsets, true); + g_free(slic_oem.id); + g_free(slic_oem.table_id); } static void acpi_ram_update(MemoryRegion *mr, GArray *data) From e71f6ab9d93a7d01e833647e7010c1079c4cef30 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 27 Dec 2021 14:31:18 -0500 Subject: [PATCH 271/730] tests: acpi: whitelist expected blobs before changing them Signed-off-by: Igor Mammedov Message-Id: <20211227193120.1084176-3-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/q35/FACP.slic | Bin 0 -> 244 bytes tests/data/acpi/q35/SLIC.slic | 0 tests/qtest/bios-tables-test-allowed-diff.h | 2 ++ 3 files changed, 2 insertions(+) create mode 100644 tests/data/acpi/q35/FACP.slic create mode 100644 tests/data/acpi/q35/SLIC.slic diff --git a/tests/data/acpi/q35/FACP.slic b/tests/data/acpi/q35/FACP.slic new file mode 100644 index 0000000000000000000000000000000000000000..f6a864cc863c7763f6c09d3814ad184a658fa0a0 GIT binary patch literal 244 zcmZ>BbPo8!z`($~)5+i2BUr&HBEVSz2pEB4AU24G0Y(N+hD|^Y6El!tgNU*~X%LSC z$X0-fGcm9T0LA|E|L2FOWMD7?GM2V5Ffej3F#P0!h{7ddihwku0+2v57svwxMxcSn X_QAxFX+{NzJ3wNL4G8yu_%Hwf>-7!+ literal 0 HcmV?d00001 diff --git a/tests/data/acpi/q35/SLIC.slic b/tests/data/acpi/q35/SLIC.slic new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..49dbf8fa3e 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,3 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/FACP.slic", +"tests/data/acpi/q35/SLIC.slic", From 11edfabee443b149468a82b5efc88c96d1d259ec Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 27 Dec 2021 14:31:19 -0500 Subject: [PATCH 272/730] tests: acpi: add SLIC table test When user uses '-acpitable' to add SLIC table, some ACPI tables (FADT) will change its 'Oem ID'/'Oem Table ID' fields to match that of SLIC. Test makes sure thati QEMU handles those fields correctly when SLIC table is added with '-acpitable' option. Signed-off-by: Igor Mammedov Message-Id: <20211227193120.1084176-4-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 9a468e29eb..e6b72d9026 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1502,6 +1502,20 @@ static void test_acpi_virt_viot(void) free_test_data(&data); } +static void test_acpi_q35_slic(void) +{ + test_data data = { + .machine = MACHINE_Q35, + .variant = ".slic", + }; + + test_acpi_one("-acpitable sig=SLIC,oem_id='CRASH ',oem_table_id='ME'," + "oem_rev=00002210,asl_compiler_id='qemu'," + "asl_compiler_rev=00000000,data=/dev/null", + &data); + free_test_data(&data); +} + static void test_oem_fields(test_data *data) { int i; @@ -1677,6 +1691,7 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/kvm/dmar", test_acpi_q35_kvm_dmar); } qtest_add_func("acpi/q35/viot", test_acpi_q35_viot); + qtest_add_func("acpi/q35/slic", test_acpi_q35_slic); } else if (strcmp(arch, "aarch64") == 0) { if (has_tcg) { qtest_add_func("acpi/virt", test_acpi_virt_tcg); From c8adb4d222c42951a9d0367e5f5d4e1f5e2c9ad7 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Mon, 27 Dec 2021 14:31:20 -0500 Subject: [PATCH 273/730] tests: acpi: SLIC: update expected blobs Signed-off-by: Igor Mammedov Message-Id: <20211227193120.1084176-5-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/q35/FACP.slic | Bin 244 -> 244 bytes tests/data/acpi/q35/SLIC.slic | Bin 0 -> 36 bytes tests/qtest/bios-tables-test-allowed-diff.h | 2 -- 3 files changed, 2 deletions(-) diff --git a/tests/data/acpi/q35/FACP.slic b/tests/data/acpi/q35/FACP.slic index f6a864cc863c7763f6c09d3814ad184a658fa0a0..891fd4b784b7b6b3ea303976db7ecd5b669bc84b 100644 GIT binary patch delta 28 jcmeyu_=Qo#&CxmF3j+fKvygL;W3Y#Uud9N>M3Dyoc<=}c delta 28 jcmeyu_=Qo#&CxmF3j+fK^G+v!XOCb7r-%UOi6RdGgN+Fa diff --git a/tests/data/acpi/q35/SLIC.slic b/tests/data/acpi/q35/SLIC.slic index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fd26592e2480c5d02a018e0d855a04106661a7b5 100644 GIT binary patch literal 36 mcmWIc@pM*UU|?YMbPjS1_E7M31#*C(gN1>iFg3Rn#0CI%)&>Cp literal 0 HcmV?d00001 diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index 49dbf8fa3e..dfb8523c8b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,3 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/q35/FACP.slic", -"tests/data/acpi/q35/SLIC.slic", From 784802689f84b716de1fbdd2cef30e303b73b3e8 Mon Sep 17 00:00:00 2001 From: Ani Sinha Date: Wed, 29 Dec 2021 13:27:53 +0530 Subject: [PATCH 274/730] acpihp: simplify acpi_pcihp_disable_root_bus Get rid of the static variable that keeps track of whether hotplug has been disabled on the root pci bus. Simply use qbus_is_hotpluggable() api to perform the same check. This eliminates additional if conditional and simplifies the function. Signed-off-by: Ani Sinha Message-Id: <1640764674-7784-1-git-send-email-ani@anirban.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/pcihp.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c index a5e182dd3a..6befd23e16 100644 --- a/hw/acpi/pcihp.c +++ b/hw/acpi/pcihp.c @@ -128,20 +128,15 @@ static void acpi_set_pci_info(void) static void acpi_pcihp_disable_root_bus(void) { - static bool root_hp_disabled; Object *host = acpi_get_i386_pci_host(); PCIBus *bus; - if (root_hp_disabled) { - return; - } - bus = PCI_HOST_BRIDGE(host)->bus; - if (bus) { + if (bus && qbus_is_hotpluggable(BUS(bus))) { /* setting the hotplug handler to NULL makes the bus non-hotpluggable */ qbus_set_hotplug_handler(BUS(bus), NULL); } - root_hp_disabled = true; + return; } From 44bff3767ced18845adb2612a2cf9691d8769d41 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 6 Dec 2021 14:42:55 +0100 Subject: [PATCH 275/730] hw/i386/pc: Add missing property descriptions When running "qemu-system-x86_64 -M pc,help" I noticed that some properties were still missing their description. Add them now so that users get at least a slightly better idea what they are all about. Signed-off-by: Thomas Huth Message-Id: <20211206134255.94784-1-thuth@redhat.com> Reviewed-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 718ab81ba8..c8696ac01e 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1759,15 +1759,23 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) object_class_property_add_bool(oc, PC_MACHINE_SMBUS, pc_machine_get_smbus, pc_machine_set_smbus); + object_class_property_set_description(oc, PC_MACHINE_SMBUS, + "Enable/disable system management bus"); object_class_property_add_bool(oc, PC_MACHINE_SATA, pc_machine_get_sata, pc_machine_set_sata); + object_class_property_set_description(oc, PC_MACHINE_SATA, + "Enable/disable Serial ATA bus"); object_class_property_add_bool(oc, PC_MACHINE_PIT, pc_machine_get_pit, pc_machine_set_pit); + object_class_property_set_description(oc, PC_MACHINE_PIT, + "Enable/disable Intel 8254 programmable interval timer emulation"); object_class_property_add_bool(oc, "hpet", pc_machine_get_hpet, pc_machine_set_hpet); + object_class_property_set_description(oc, "hpet", + "Enable/disable high precision event timer emulation"); object_class_property_add_bool(oc, "default-bus-bypass-iommu", pc_machine_get_default_bus_bypass_iommu, From 14dc58e3e0b12595e407502b93a8bb7e69621cbb Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 5 Jan 2022 12:52:45 +0100 Subject: [PATCH 276/730] docs: reSTify virtio-balloon-stats documentation and move to docs/interop The virtio-balloon-stats documentation might be useful for people that are implementing software that talks to QEMU via QMP, so this should reside in the docs/interop/ directory. While we're at it, also convert the file to restructured text and mention it in the MAINTAINERS file. Signed-off-by: Thomas Huth Message-Id: <20220105115245.420945-1-thuth@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- MAINTAINERS | 1 + docs/interop/index.rst | 1 + .../virtio-balloon-stats.rst} | 58 ++++++++++--------- 3 files changed, 32 insertions(+), 28 deletions(-) rename docs/{virtio-balloon-stats.txt => interop/virtio-balloon-stats.rst} (66%) diff --git a/MAINTAINERS b/MAINTAINERS index 6aa0335560..c98a61caee 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1932,6 +1932,7 @@ virtio-balloon M: Michael S. Tsirkin M: David Hildenbrand S: Maintained +F: docs/interop/virtio-balloon-stats.rst F: hw/virtio/virtio-balloon*.c F: include/hw/virtio/virtio-balloon.h F: softmmu/balloon.c diff --git a/docs/interop/index.rst b/docs/interop/index.rst index c59bac9834..b7632acb7b 100644 --- a/docs/interop/index.rst +++ b/docs/interop/index.rst @@ -22,3 +22,4 @@ are useful for making QEMU interoperate with other software. vhost-user vhost-user-gpu vhost-vdpa + virtio-balloon-stats diff --git a/docs/virtio-balloon-stats.txt b/docs/interop/virtio-balloon-stats.rst similarity index 66% rename from docs/virtio-balloon-stats.txt rename to docs/interop/virtio-balloon-stats.rst index 1732cc8c8a..b9a6a6edb2 100644 --- a/docs/virtio-balloon-stats.txt +++ b/docs/interop/virtio-balloon-stats.rst @@ -1,4 +1,4 @@ -virtio balloon memory statistics +Virtio balloon memory statistics ================================ The virtio balloon driver supports guest memory statistics reporting. These @@ -9,10 +9,12 @@ Before querying the available stats, clients first have to enable polling. This is done by writing a time interval value (in seconds) to the guest-stats-polling-interval property. This value can be: - > 0 enables polling in the specified interval. If polling is already + > 0 + enables polling in the specified interval. If polling is already enabled, the polling time interval is changed to the new value - 0 disables polling. Previous polled statistics are still valid and + 0 + disables polling. Previous polled statistics are still valid and can be queried. Once polling is enabled, the virtio-balloon device in QEMU will start @@ -22,7 +24,7 @@ interval. To retrieve those stats, clients have to query the guest-stats property, which will return a dictionary containing: - o A key named 'stats', containing all available stats. If the guest + * A key named 'stats', containing all available stats. If the guest doesn't support a particular stat, or if it couldn't be retrieved, its value will be -1. Currently, the following stats are supported: @@ -37,7 +39,7 @@ which will return a dictionary containing: - stat-htlb-pgalloc - stat-htlb-pgfail - o A key named last-update, which contains the last stats update + * A key named last-update, which contains the last stats update timestamp in seconds. Since this timestamp is generated by the host, a buggy guest can't influence its value. The value is 0 if the guest has not updated the stats (yet). @@ -61,32 +63,32 @@ It's also important to note the following: respond to the request the timer will never be re-armed, which has the same effect as disabling polling -Here are a few examples. QEMU is started with '-device virtio-balloon', -which generates '/machine/peripheral-anon/device[1]' as the QOM path for +Here are a few examples. QEMU is started with ``-device virtio-balloon``, +which generates ``/machine/peripheral-anon/device[1]`` as the QOM path for the balloon device. -Enable polling with 2 seconds interval: +Enable polling with 2 seconds interval:: -{ "execute": "qom-set", - "arguments": { "path": "/machine/peripheral-anon/device[1]", - "property": "guest-stats-polling-interval", "value": 2 } } + { "execute": "qom-set", + "arguments": { "path": "/machine/peripheral-anon/device[1]", + "property": "guest-stats-polling-interval", "value": 2 } } -{ "return": {} } + { "return": {} } -Change polling to 10 seconds: +Change polling to 10 seconds:: -{ "execute": "qom-set", - "arguments": { "path": "/machine/peripheral-anon/device[1]", - "property": "guest-stats-polling-interval", "value": 10 } } + { "execute": "qom-set", + "arguments": { "path": "/machine/peripheral-anon/device[1]", + "property": "guest-stats-polling-interval", "value": 10 } } -{ "return": {} } + { "return": {} } -Get stats: +Get stats:: -{ "execute": "qom-get", - "arguments": { "path": "/machine/peripheral-anon/device[1]", - "property": "guest-stats" } } -{ + { "execute": "qom-get", + "arguments": { "path": "/machine/peripheral-anon/device[1]", + "property": "guest-stats" } } + { "return": { "stats": { "stat-swap-out": 0, @@ -98,12 +100,12 @@ Get stats: }, "last-update": 1358529861 } -} + } -Disable polling: +Disable polling:: -{ "execute": "qom-set", - "arguments": { "path": "/machine/peripheral-anon/device[1]", - "property": "stats-polling-interval", "value": 0 } } + { "execute": "qom-set", + "arguments": { "path": "/machine/peripheral-anon/device[1]", + "property": "stats-polling-interval", "value": 0 } } -{ "return": {} } + { "return": {} } From b259772afc29ef6af4e911d8e695dd7e2ed31066 Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Mon, 29 Nov 2021 16:23:57 +0300 Subject: [PATCH 277/730] hw/scsi/vhost-scsi: don't leak vqs on error vhost_dev_init calls vhost_dev_cleanup in case of an error during initialization, which zeroes out the entire vsc->dev as well as the vsc->dev.vqs pointer. This prevents us from properly freeing it in free_vqs. Keep a local copy of the pointer so we can free it later. Signed-off-by: Daniil Tatianin Message-Id: <20211129132358.1110372-1-d-tatianin@yandex-team.ru> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/scsi/vhost-scsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index 039caf2614..efb3e14d9e 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -170,6 +170,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) Error *err = NULL; int vhostfd = -1; int ret; + struct vhost_virtqueue *vqs = NULL; if (!vs->conf.wwpn) { error_setg(errp, "vhost-scsi: missing wwpn"); @@ -213,7 +214,8 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) } vsc->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues; - vsc->dev.vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs); + vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs); + vsc->dev.vqs = vqs; vsc->dev.vq_index = 0; vsc->dev.backend_features = 0; @@ -232,7 +234,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) return; free_vqs: - g_free(vsc->dev.vqs); + g_free(vqs); if (!vsc->migratable) { migrate_del_blocker(vsc->migration_blocker); } From 539ba1acacb11a0f27a7e7ff7e2a7c1294e0a1ea Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Mon, 29 Nov 2021 16:23:58 +0300 Subject: [PATCH 278/730] hw/scsi/vhost-scsi: don't double close vhostfd on error vhost_dev_init calls vhost_dev_cleanup on error, which closes vhostfd, don't double close it. Signed-off-by: Daniil Tatianin Message-Id: <20211129132358.1110372-2-d-tatianin@yandex-team.ru> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/scsi/vhost-scsi.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index efb3e14d9e..778f43e4c1 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -222,6 +222,11 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) ret = vhost_dev_init(&vsc->dev, (void *)(uintptr_t)vhostfd, VHOST_BACKEND_TYPE_KERNEL, 0, errp); if (ret < 0) { + /* + * vhost_dev_init calls vhost_dev_cleanup on error, which closes + * vhostfd, don't double close it. + */ + vhostfd = -1; goto free_vqs; } @@ -242,7 +247,9 @@ static void vhost_scsi_realize(DeviceState *dev, Error **errp) error_free(vsc->migration_blocker); virtio_scsi_common_unrealize(dev); close_fd: - close(vhostfd); + if (vhostfd >= 0) { + close(vhostfd); + } return; } From d731ab31196579144457c7f2fa3649338bfb21f2 Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Mon, 29 Nov 2021 15:52:04 +0300 Subject: [PATCH 279/730] virtio/vhost-vsock: don't double close vhostfd, remove redundant cleanup In case of an error during initialization in vhost_dev_init, vhostfd is closed in vhost_dev_cleanup. Remove close from err_virtio as it's both redundant and causes a double close on vhostfd. Signed-off-by: Daniil Tatianin Message-Id: <20211129125204.1108088-1-d-tatianin@yandex-team.ru> Reviewed-by: Stefano Garzarella Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost-vsock.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c index 478c0c9a87..433d42d897 100644 --- a/hw/virtio/vhost-vsock.c +++ b/hw/virtio/vhost-vsock.c @@ -171,6 +171,10 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) ret = vhost_dev_init(&vvc->vhost_dev, (void *)(uintptr_t)vhostfd, VHOST_BACKEND_TYPE_KERNEL, 0, errp); if (ret < 0) { + /* + * vhostfd is closed by vhost_dev_cleanup, which is called + * by vhost_dev_init on initialization error. + */ goto err_virtio; } @@ -183,15 +187,10 @@ static void vhost_vsock_device_realize(DeviceState *dev, Error **errp) return; err_vhost_dev: - vhost_dev_cleanup(&vvc->vhost_dev); /* vhost_dev_cleanup() closes the vhostfd passed to vhost_dev_init() */ - vhostfd = -1; + vhost_dev_cleanup(&vvc->vhost_dev); err_virtio: vhost_vsock_common_unrealize(vdev); - if (vhostfd >= 0) { - close(vhostfd); - } - return; } static void vhost_vsock_device_unrealize(DeviceState *dev) From b193e5f9cccb322b0febd5a2aba48618506ed809 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Tue, 4 Jan 2022 12:58:04 -0500 Subject: [PATCH 280/730] tests: acpi: prepare for updated TPM related tables Replace existing TPM related tables, that are about to change, with empty files. Cc: Michael S. Tsirkin Cc: Igor Mammedov Cc: Ani Sinha Signed-off-by: Stefan Berger Acked-by: Ani Sinha Message-id: 20211223022310.575496-2-stefanb@linux.ibm.com Message-Id: <20220104175806.872996-2-stefanb@linux.ibm.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Acked-by: Igor Mammedov --- tests/qtest/bios-tables-test-allowed-diff.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..5d80e408d4 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,3 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/DSDT.tis.tpm12", +"tests/data/acpi/q35/DSDT.tis.tpm2", From 5903646d3913af6544680f6645fcb7296d0b3a1c Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Tue, 4 Jan 2022 12:58:05 -0500 Subject: [PATCH 281/730] acpi: tpm: Add missing device identification objects Add missing TPM device identification objects _STR and _UID. They will appear as files 'description' and 'uid' under Linux sysfs. Following inspection of sysfs entries for hardware TPMs we chose uid '1'. Cc: Shannon Zhao Cc: Michael S. Tsirkin Cc: Igor Mammedov Cc: Ani Sinha Resolves: https://gitlab.com/qemu-project/qemu/-/issues/708 Signed-off-by: Stefan Berger Reviewed-by: Ani Sinha Reviewed-by: Shannon Zhao Message-id: 20211223022310.575496-3-stefanb@linux.ibm.com Message-Id: <20220104175806.872996-3-stefanb@linux.ibm.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Igor Mammedov --- hw/arm/virt-acpi-build.c | 1 + hw/i386/acpi-build.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index d0f4867fdf..f2514ce77c 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -229,6 +229,7 @@ static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms) Aml *dev = aml_device("TPM0"); aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101"))); + aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device"))); aml_append(dev, aml_name_decl("_UID", aml_int(0))); Aml *crs = aml_resource_template(); diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 0234fe7588..ce823e8fcb 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1812,11 +1812,15 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, dev = aml_device("TPM"); aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101"))); + aml_append(dev, + aml_name_decl("_STR", + aml_string("TPM 2.0 Device"))); } else { dev = aml_device("ISA.TPM"); aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31"))); } + aml_append(dev, aml_name_decl("_UID", aml_int(1))); aml_append(dev, aml_name_decl("_STA", aml_int(0xF))); crs = aml_resource_template(); @@ -1844,12 +1848,15 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, if (TPM_IS_CRB(tpm)) { dev = aml_device("TPM"); aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101"))); + aml_append(dev, aml_name_decl("_STR", + aml_string("TPM 2.0 Device"))); crs = aml_resource_template(); aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE, TPM_CRB_ADDR_SIZE, AML_READ_WRITE)); aml_append(dev, aml_name_decl("_CRS", crs)); aml_append(dev, aml_name_decl("_STA", aml_int(0xf))); + aml_append(dev, aml_name_decl("_UID", aml_int(1))); tpm_build_ppi_acpi(tpm, dev); From ca745d2277496464b54fd832c15c45d0227325bb Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Tue, 4 Jan 2022 12:58:06 -0500 Subject: [PATCH 282/730] tests: acpi: Add updated TPM related tables The updated TPM related tables have the following additions: Device (TPM) { Name (_HID, "MSFT0101" /* TPM 2.0 Security Device */) // _HID: Hardware ID + Name (_STR, "TPM 2.0 Device") // _STR: Description String + Name (_UID, One) // _UID: Unique ID Name (_STA, 0x0F) // _STA: Status Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings Cc: Michael S. Tsirkin Cc: Igor Mammedov Cc: Ani Sinha Signed-off-by: Stefan Berger Acked-by: Ani Sinha Message-id: 20211223022310.575496-4-stefanb@linux.ibm.com Message-Id: <20220104175806.872996-4-stefanb@linux.ibm.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/q35/DSDT.tis.tpm12 | Bin 8894 -> 8900 bytes tests/data/acpi/q35/DSDT.tis.tpm2 | Bin 8894 -> 8921 bytes tests/qtest/bios-tables-test-allowed-diff.h | 2 -- 3 files changed, 2 deletions(-) diff --git a/tests/data/acpi/q35/DSDT.tis.tpm12 b/tests/data/acpi/q35/DSDT.tis.tpm12 index 0ebdf6fbd77967f1ab5d5337b7b1fed314cfaca8..fb9dd1f0599afd6b555ea570ecd00a3bb227aa84 100644 GIT binary patch delta 50 zcmdnzdc>8>CDH@7HQF#!OXcoHoD delta 46 zcmccVy3du%CD Date: Tue, 14 Dec 2021 12:26:59 +0300 Subject: [PATCH 283/730] target/riscv/pmp: fix no pmp illegal intrs As per the privilege specification, any access from S/U mode should fail if no pmp region is configured and pmp is present, othwerwise access should succeed. Fixes: d102f19a208 (target/riscv/pmp: Raise exception if no PMP entry is configured) Signed-off-by: Nikita Shubin Reviewed-by: Alistair Francis Message-id: 20211214092659.15709-1-nikita.shubin@maquefel.me Signed-off-by: Alistair Francis --- target/riscv/op_helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index ee7c24efe7..58d992e98a 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -146,7 +146,8 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb) uint64_t mstatus = env->mstatus; target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP); - if (!pmp_get_num_rules(env) && (prev_priv != PRV_M)) { + if (riscv_feature(env, RISCV_FEATURE_PMP) && + !pmp_get_num_rules(env) && (prev_priv != PRV_M)) { riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); } From 6fd3f397cad0867feec484a13f2656dbf736c76c Mon Sep 17 00:00:00 2001 From: Jim Shu Date: Tue, 4 Jan 2022 14:34:07 +0800 Subject: [PATCH 284/730] hw/dma: sifive_pdma: support high 32-bit access of 64-bit register Real PDMA supports high 32-bit read/write memory access of 64-bit register. The following result is PDMA tested in U-Boot on Unmatched board: 1. Real PDMA allows high 32-bit read/write to 64-bit register. => mw.l 0x3000000 0x0 <= Disclaim channel 0 => mw.l 0x3000000 0x1 <= Claim channel 0 => mw.l 0x3000010 0x80000000 <= Write low 32-bit NextDest (NextDest = 0x280000000) => mw.l 0x3000014 0x2 <= Write high 32-bit NextDest => md.l 0x3000010 1 <= Dump low 32-bit NextDest 03000010: 80000000 => md.l 0x3000014 1 <= Dump high 32-bit NextDest 03000014: 00000002 => mw.l 0x3000018 0x80001000 <= Write low 32-bit NextSrc (NextSrc = 0x280001000) => mw.l 0x300001c 0x2 <= Write high 32-bit NextSrc => md.l 0x3000018 1 <= Dump low 32-bit NextSrc 03000010: 80001000 => md.l 0x300001c 1 <= Dump high 32-bit NextSrc 03000014: 00000002 2. PDMA transfer from 0x280001000 to 0x280000000 is OK. => mw.q 0x3000008 0x4 <= NextBytes = 4 => mw.l 0x3000004 0x22000000 <= wsize = rsize = 2 (2^2 = 4 bytes) => mw.l 0x280000000 0x87654321 <= Fill test data to dst => mw.l 0x280001000 0x12345678 <= Fill test data to src => md.l 0x280000000 1; md.l 0x280001000 1 <= Dump src/dst memory contents 280000000: 87654321 !Ce. 280001000: 12345678 xV4. => md.l 0x3000000 8 <= Dump PDMA status 03000000: 00000001 22000000 00000004 00000000 ......."........ 03000010: 80000000 00000002 80001000 00000002 ................ => mw.l 0x3000000 0x3 <= Set channel 0 run and claim bits => md.l 0x3000000 8 <= Dump PDMA status 03000000: 40000001 22000000 00000004 00000000 ...@..."........ 03000010: 80000000 00000002 80001000 00000002 ................ => md.l 0x280000000 1; md.l 0x280001000 1 <= Dump src/dst memory contents 280000000: 12345678 xV4. 280001000: 12345678 xV4. Signed-off-by: Jim Shu Reviewed-by: Frank Chang Reviewed-by: Alistair Francis Reviewed-by: Bin Meng Tested-by: Bin Meng Message-id: 20220104063408.658169-2-jim.shu@sifive.com Signed-off-by: Alistair Francis --- hw/dma/sifive_pdma.c | 221 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 177 insertions(+), 44 deletions(-) diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c index 85fe34f5f3..f4df16449b 100644 --- a/hw/dma/sifive_pdma.c +++ b/hw/dma/sifive_pdma.c @@ -177,6 +177,101 @@ static inline void sifive_pdma_update_irq(SiFivePDMAState *s, int ch) s->chan[ch].state = DMA_CHAN_STATE_IDLE; } +static uint64_t sifive_pdma_readq(SiFivePDMAState *s, int ch, hwaddr offset) +{ + uint64_t val = 0; + + offset &= 0xfff; + switch (offset) { + case DMA_NEXT_BYTES: + val = s->chan[ch].next_bytes; + break; + case DMA_NEXT_DST: + val = s->chan[ch].next_dst; + break; + case DMA_NEXT_SRC: + val = s->chan[ch].next_src; + break; + case DMA_EXEC_BYTES: + val = s->chan[ch].exec_bytes; + break; + case DMA_EXEC_DST: + val = s->chan[ch].exec_dst; + break; + case DMA_EXEC_SRC: + val = s->chan[ch].exec_src; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Unexpected 64-bit access to 0x%" HWADDR_PRIX "\n", + __func__, offset); + break; + } + + return val; +} + +static uint32_t sifive_pdma_readl(SiFivePDMAState *s, int ch, hwaddr offset) +{ + uint32_t val = 0; + + offset &= 0xfff; + switch (offset) { + case DMA_CONTROL: + val = s->chan[ch].control; + break; + case DMA_NEXT_CONFIG: + val = s->chan[ch].next_config; + break; + case DMA_NEXT_BYTES: + val = extract64(s->chan[ch].next_bytes, 0, 32); + break; + case DMA_NEXT_BYTES + 4: + val = extract64(s->chan[ch].next_bytes, 32, 32); + break; + case DMA_NEXT_DST: + val = extract64(s->chan[ch].next_dst, 0, 32); + break; + case DMA_NEXT_DST + 4: + val = extract64(s->chan[ch].next_dst, 32, 32); + break; + case DMA_NEXT_SRC: + val = extract64(s->chan[ch].next_src, 0, 32); + break; + case DMA_NEXT_SRC + 4: + val = extract64(s->chan[ch].next_src, 32, 32); + break; + case DMA_EXEC_CONFIG: + val = s->chan[ch].exec_config; + break; + case DMA_EXEC_BYTES: + val = extract64(s->chan[ch].exec_bytes, 0, 32); + break; + case DMA_EXEC_BYTES + 4: + val = extract64(s->chan[ch].exec_bytes, 32, 32); + break; + case DMA_EXEC_DST: + val = extract64(s->chan[ch].exec_dst, 0, 32); + break; + case DMA_EXEC_DST + 4: + val = extract64(s->chan[ch].exec_dst, 32, 32); + break; + case DMA_EXEC_SRC: + val = extract64(s->chan[ch].exec_src, 0, 32); + break; + case DMA_EXEC_SRC + 4: + val = extract64(s->chan[ch].exec_src, 32, 32); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Unexpected 32-bit access to 0x%" HWADDR_PRIX "\n", + __func__, offset); + break; + } + + return val; +} + static uint64_t sifive_pdma_read(void *opaque, hwaddr offset, unsigned size) { SiFivePDMAState *s = opaque; @@ -189,56 +284,53 @@ static uint64_t sifive_pdma_read(void *opaque, hwaddr offset, unsigned size) return 0; } - offset &= 0xfff; - switch (offset) { - case DMA_CONTROL: - val = s->chan[ch].control; + switch (size) { + case 8: + val = sifive_pdma_readq(s, ch, offset); break; - case DMA_NEXT_CONFIG: - val = s->chan[ch].next_config; - break; - case DMA_NEXT_BYTES: - val = s->chan[ch].next_bytes; - break; - case DMA_NEXT_DST: - val = s->chan[ch].next_dst; - break; - case DMA_NEXT_SRC: - val = s->chan[ch].next_src; - break; - case DMA_EXEC_CONFIG: - val = s->chan[ch].exec_config; - break; - case DMA_EXEC_BYTES: - val = s->chan[ch].exec_bytes; - break; - case DMA_EXEC_DST: - val = s->chan[ch].exec_dst; - break; - case DMA_EXEC_SRC: - val = s->chan[ch].exec_src; + case 4: + val = sifive_pdma_readl(s, ch, offset); break; default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", - __func__, offset); - break; + qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid read size %u to PDMA\n", + __func__, size); + return 0; } return val; } -static void sifive_pdma_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) +static void sifive_pdma_writeq(SiFivePDMAState *s, int ch, + hwaddr offset, uint64_t value) { - SiFivePDMAState *s = opaque; - int ch = SIFIVE_PDMA_CHAN_NO(offset); - bool claimed, run; - - if (ch >= SIFIVE_PDMA_CHANS) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n", - __func__, ch); - return; + offset &= 0xfff; + switch (offset) { + case DMA_NEXT_BYTES: + s->chan[ch].next_bytes = value; + break; + case DMA_NEXT_DST: + s->chan[ch].next_dst = value; + break; + case DMA_NEXT_SRC: + s->chan[ch].next_src = value; + break; + case DMA_EXEC_BYTES: + case DMA_EXEC_DST: + case DMA_EXEC_SRC: + /* these are read-only registers */ + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Unexpected 64-bit access to 0x%" HWADDR_PRIX "\n", + __func__, offset); + break; } +} + +static void sifive_pdma_writel(SiFivePDMAState *s, int ch, + hwaddr offset, uint32_t value) +{ + bool claimed, run; offset &= 0xfff; switch (offset) { @@ -282,27 +374,68 @@ static void sifive_pdma_write(void *opaque, hwaddr offset, s->chan[ch].next_config = value; break; case DMA_NEXT_BYTES: - s->chan[ch].next_bytes = value; + s->chan[ch].next_bytes = + deposit64(s->chan[ch].next_bytes, 0, 32, value); + break; + case DMA_NEXT_BYTES + 4: + s->chan[ch].next_bytes = + deposit64(s->chan[ch].next_bytes, 32, 32, value); break; case DMA_NEXT_DST: - s->chan[ch].next_dst = value; + s->chan[ch].next_dst = deposit64(s->chan[ch].next_dst, 0, 32, value); + break; + case DMA_NEXT_DST + 4: + s->chan[ch].next_dst = deposit64(s->chan[ch].next_dst, 32, 32, value); break; case DMA_NEXT_SRC: - s->chan[ch].next_src = value; + s->chan[ch].next_src = deposit64(s->chan[ch].next_src, 0, 32, value); + break; + case DMA_NEXT_SRC + 4: + s->chan[ch].next_src = deposit64(s->chan[ch].next_src, 32, 32, value); break; case DMA_EXEC_CONFIG: case DMA_EXEC_BYTES: + case DMA_EXEC_BYTES + 4: case DMA_EXEC_DST: + case DMA_EXEC_DST + 4: case DMA_EXEC_SRC: + case DMA_EXEC_SRC + 4: /* these are read-only registers */ break; default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Unexpected 32-bit access to 0x%" HWADDR_PRIX "\n", __func__, offset); break; } } +static void sifive_pdma_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + SiFivePDMAState *s = opaque; + int ch = SIFIVE_PDMA_CHAN_NO(offset); + + if (ch >= SIFIVE_PDMA_CHANS) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid channel no %d\n", + __func__, ch); + return; + } + + switch (size) { + case 8: + sifive_pdma_writeq(s, ch, offset, value); + break; + case 4: + sifive_pdma_writel(s, ch, offset, (uint32_t) value); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid write size %u to PDMA\n", + __func__, size); + break; + } +} + static const MemoryRegionOps sifive_pdma_ops = { .read = sifive_pdma_read, .write = sifive_pdma_write, From e6b0408a1728c001a0cc0568b9daae5f92e239ee Mon Sep 17 00:00:00 2001 From: Jim Shu Date: Tue, 4 Jan 2022 14:34:08 +0800 Subject: [PATCH 285/730] hw/dma: sifive_pdma: permit 4/8-byte access size of PDMA registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's obvious that PDMA supports 64-bit access of 64-bit registers, and in previous commit, we confirm that PDMA supports 32-bit access of both 32/64-bit registers. Thus, we configure 32/64-bit memory access of PDMA registers as valid in general. Signed-off-by: Jim Shu Reviewed-by: Frank Chang Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Reviewed-by: Bin Meng Tested-by: Bin Meng Message-id: 20220104063408.658169-3-jim.shu@sifive.com Signed-off-by: Alistair Francis --- hw/dma/sifive_pdma.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/dma/sifive_pdma.c b/hw/dma/sifive_pdma.c index f4df16449b..1dd88f3479 100644 --- a/hw/dma/sifive_pdma.c +++ b/hw/dma/sifive_pdma.c @@ -444,6 +444,10 @@ static const MemoryRegionOps sifive_pdma_ops = { .impl = { .min_access_size = 4, .max_access_size = 8, + }, + .valid = { + .min_access_size = 4, + .max_access_size = 8, } }; From 83b92b8efca6634406361d62dbf9d3e8369a2a20 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 6 Jan 2022 07:39:30 +1000 Subject: [PATCH 286/730] hw/intc: sifive_plic: Add a reset function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Bin Meng Message-Id: <20220105213937.1113508-2-alistair.francis@opensource.wdc.com> --- hw/intc/sifive_plic.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index 877e76877c..a9f7a1bfb0 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -355,6 +355,23 @@ static const MemoryRegionOps sifive_plic_ops = { } }; +static void sifive_plic_reset(DeviceState *dev) +{ + SiFivePLICState *s = SIFIVE_PLIC(dev); + int i; + + memset(s->source_priority, 0, sizeof(uint32_t) * s->num_sources); + memset(s->target_priority, 0, sizeof(uint32_t) * s->num_addrs); + memset(s->pending, 0, sizeof(uint32_t) * s->bitfield_words); + memset(s->claimed, 0, sizeof(uint32_t) * s->bitfield_words); + memset(s->enable, 0, sizeof(uint32_t) * s->num_enables); + + for (i = 0; i < s->num_harts; i++) { + qemu_set_irq(s->m_external_irqs[i], 0); + qemu_set_irq(s->s_external_irqs[i], 0); + } +} + /* * parse PLIC hart/mode address offset config * @@ -501,6 +518,7 @@ static void sifive_plic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + dc->reset = sifive_plic_reset; device_class_set_props(dc, sifive_plic_properties); dc->realize = sifive_plic_realize; dc->vmsd = &vmstate_sifive_plic; From fb926d57cc56499523f1559f58371e09198ed75e Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 6 Jan 2022 07:39:31 +1000 Subject: [PATCH 287/730] hw/intc: sifive_plic: Cleanup the write function Signed-off-by: Alistair Francis Reviewed-by: Bin Meng Message-Id: <20220105213937.1113508-3-alistair.francis@opensource.wdc.com> --- hw/intc/sifive_plic.c | 76 +++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 49 deletions(-) diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index a9f7a1bfb0..698492ce77 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -33,6 +33,11 @@ #define RISCV_DEBUG_PLIC 0 +static bool addr_between(uint32_t addr, uint32_t base, uint32_t num) +{ + return addr >= base && addr - base < num; +} + static PLICMode char_to_mode(char c) { switch (c) { @@ -269,80 +274,53 @@ static void sifive_plic_write(void *opaque, hwaddr addr, uint64_t value, { SiFivePLICState *plic = opaque; - /* writes must be 4 byte words */ - if ((addr & 0x3) != 0) { - goto err; - } - - if (addr >= plic->priority_base && /* 4 bytes per source */ - addr < plic->priority_base + (plic->num_sources << 2)) - { + if (addr_between(addr, plic->priority_base, plic->num_sources << 2)) { uint32_t irq = ((addr - plic->priority_base) >> 2) + 1; + plic->source_priority[irq] = value & 7; - if (RISCV_DEBUG_PLIC) { - qemu_log("plic: write priority: irq=%d priority=%d\n", - irq, plic->source_priority[irq]); - } sifive_plic_update(plic); - return; - } else if (addr >= plic->pending_base && /* 1 bit per source */ - addr < plic->pending_base + (plic->num_sources >> 3)) - { + } else if (addr_between(addr, plic->pending_base, + plic->num_sources >> 3)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid pending write: 0x%" HWADDR_PRIx "", __func__, addr); - return; - } else if (addr >= plic->enable_base && /* 1 bit per source */ - addr < plic->enable_base + plic->num_addrs * plic->enable_stride) - { + } else if (addr_between(addr, plic->enable_base, + plic->num_addrs * plic->enable_stride)) { uint32_t addrid = (addr - plic->enable_base) / plic->enable_stride; uint32_t wordid = (addr & (plic->enable_stride - 1)) >> 2; + if (wordid < plic->bitfield_words) { plic->enable[addrid * plic->bitfield_words + wordid] = value; - if (RISCV_DEBUG_PLIC) { - qemu_log("plic: write enable: hart%d-%c word=%d value=%x\n", - plic->addr_config[addrid].hartid, - mode_to_char(plic->addr_config[addrid].mode), wordid, - plic->enable[addrid * plic->bitfield_words + wordid]); - } - return; + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Invalid enable write 0x%" HWADDR_PRIx "\n", + __func__, addr); } - } else if (addr >= plic->context_base && /* 4 bytes per reg */ - addr < plic->context_base + plic->num_addrs * plic->context_stride) - { + } else if (addr_between(addr, plic->context_base, + plic->num_addrs * plic->context_stride)) { uint32_t addrid = (addr - plic->context_base) / plic->context_stride; uint32_t contextid = (addr & (plic->context_stride - 1)); + if (contextid == 0) { - if (RISCV_DEBUG_PLIC) { - qemu_log("plic: write priority: hart%d-%c priority=%x\n", - plic->addr_config[addrid].hartid, - mode_to_char(plic->addr_config[addrid].mode), - plic->target_priority[addrid]); - } if (value <= plic->num_priorities) { plic->target_priority[addrid] = value; sifive_plic_update(plic); } - return; } else if (contextid == 4) { - if (RISCV_DEBUG_PLIC) { - qemu_log("plic: write claim: hart%d-%c irq=%x\n", - plic->addr_config[addrid].hartid, - mode_to_char(plic->addr_config[addrid].mode), - (uint32_t)value); - } if (value < plic->num_sources) { sifive_plic_set_claimed(plic, value, false); sifive_plic_update(plic); } - return; + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Invalid context write 0x%" HWADDR_PRIx "\n", + __func__, addr); } + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Invalid register write 0x%" HWADDR_PRIx "\n", + __func__, addr); } - -err: - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Invalid register write 0x%" HWADDR_PRIx "\n", - __func__, addr); } static const MemoryRegionOps sifive_plic_ops = { From b79e1c76c02dd01a203028c4482d975480b97f16 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 6 Jan 2022 07:39:32 +1000 Subject: [PATCH 288/730] hw/intc: sifive_plic: Cleanup the read function Signed-off-by: Alistair Francis Reviewed-by: Bin Meng Message-Id: <20220105213937.1113508-4-alistair.francis@opensource.wdc.com> --- hw/intc/sifive_plic.c | 55 +++++++++---------------------------------- 1 file changed, 11 insertions(+), 44 deletions(-) diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index 698492ce77..44d24b3c59 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -199,70 +199,37 @@ static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size) { SiFivePLICState *plic = opaque; - /* writes must be 4 byte words */ - if ((addr & 0x3) != 0) { - goto err; - } - - if (addr >= plic->priority_base && /* 4 bytes per source */ - addr < plic->priority_base + (plic->num_sources << 2)) - { + if (addr_between(addr, plic->priority_base, plic->num_sources << 2)) { uint32_t irq = ((addr - plic->priority_base) >> 2) + 1; - if (RISCV_DEBUG_PLIC) { - qemu_log("plic: read priority: irq=%d priority=%d\n", - irq, plic->source_priority[irq]); - } + return plic->source_priority[irq]; - } else if (addr >= plic->pending_base && /* 1 bit per source */ - addr < plic->pending_base + (plic->num_sources >> 3)) - { + } else if (addr_between(addr, plic->pending_base, plic->num_sources >> 3)) { uint32_t word = (addr - plic->pending_base) >> 2; - if (RISCV_DEBUG_PLIC) { - qemu_log("plic: read pending: word=%d value=%d\n", - word, plic->pending[word]); - } + return plic->pending[word]; - } else if (addr >= plic->enable_base && /* 1 bit per source */ - addr < plic->enable_base + plic->num_addrs * plic->enable_stride) - { + } else if (addr_between(addr, plic->enable_base, + plic->num_addrs * plic->enable_stride)) { uint32_t addrid = (addr - plic->enable_base) / plic->enable_stride; uint32_t wordid = (addr & (plic->enable_stride - 1)) >> 2; + if (wordid < plic->bitfield_words) { - if (RISCV_DEBUG_PLIC) { - qemu_log("plic: read enable: hart%d-%c word=%d value=%x\n", - plic->addr_config[addrid].hartid, - mode_to_char(plic->addr_config[addrid].mode), wordid, - plic->enable[addrid * plic->bitfield_words + wordid]); - } return plic->enable[addrid * plic->bitfield_words + wordid]; } - } else if (addr >= plic->context_base && /* 1 bit per source */ - addr < plic->context_base + plic->num_addrs * plic->context_stride) - { + } else if (addr_between(addr, plic->context_base, + plic->num_addrs * plic->context_stride)) { uint32_t addrid = (addr - plic->context_base) / plic->context_stride; uint32_t contextid = (addr & (plic->context_stride - 1)); + if (contextid == 0) { - if (RISCV_DEBUG_PLIC) { - qemu_log("plic: read priority: hart%d-%c priority=%x\n", - plic->addr_config[addrid].hartid, - mode_to_char(plic->addr_config[addrid].mode), - plic->target_priority[addrid]); - } return plic->target_priority[addrid]; } else if (contextid == 4) { uint32_t value = sifive_plic_claim(plic, addrid); - if (RISCV_DEBUG_PLIC) { - qemu_log("plic: read claim: hart%d-%c irq=%x\n", - plic->addr_config[addrid].hartid, - mode_to_char(plic->addr_config[addrid].mode), - value); - } + sifive_plic_update(plic); return value; } } -err: qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid register read 0x%" HWADDR_PRIx "\n", __func__, addr); From 41bcc44a2517b5775a94c5c9b2a1014be8b19235 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 6 Jan 2022 07:39:33 +1000 Subject: [PATCH 289/730] hw/intc: sifive_plic: Cleanup remaining functions We can remove the original sifive_plic_irqs_pending() function and instead just use the sifive_plic_claim() function (renamed to sifive_plic_claimed()) to determine if any interrupts are pending. This requires move the side effects outside of sifive_plic_claimed(), but as they are only invoked once that isn't a problem. We have also removed all of the old #ifdef debugging logs, so let's cleanup the last remaining debug function while we are here. Signed-off-by: Alistair Francis Reviewed-by: Bin Meng Message-Id: <20220105213937.1113508-5-alistair.francis@opensource.wdc.com> --- hw/intc/sifive_plic.c | 109 +++++++++--------------------------------- 1 file changed, 22 insertions(+), 87 deletions(-) diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index 44d24b3c59..746c0f0343 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -31,8 +31,6 @@ #include "migration/vmstate.h" #include "hw/irq.h" -#define RISCV_DEBUG_PLIC 0 - static bool addr_between(uint32_t addr, uint32_t base, uint32_t num) { return addr >= base && addr - base < num; @@ -51,47 +49,6 @@ static PLICMode char_to_mode(char c) } } -static char mode_to_char(PLICMode m) -{ - switch (m) { - case PLICMode_U: return 'U'; - case PLICMode_S: return 'S'; - case PLICMode_H: return 'H'; - case PLICMode_M: return 'M'; - default: return '?'; - } -} - -static void sifive_plic_print_state(SiFivePLICState *plic) -{ - int i; - int addrid; - - /* pending */ - qemu_log("pending : "); - for (i = plic->bitfield_words - 1; i >= 0; i--) { - qemu_log("%08x", plic->pending[i]); - } - qemu_log("\n"); - - /* pending */ - qemu_log("claimed : "); - for (i = plic->bitfield_words - 1; i >= 0; i--) { - qemu_log("%08x", plic->claimed[i]); - } - qemu_log("\n"); - - for (addrid = 0; addrid < plic->num_addrs; addrid++) { - qemu_log("hart%d-%c enable: ", - plic->addr_config[addrid].hartid, - mode_to_char(plic->addr_config[addrid].mode)); - for (i = plic->bitfield_words - 1; i >= 0; i--) { - qemu_log("%08x", plic->enable[addrid * plic->bitfield_words + i]); - } - qemu_log("\n"); - } -} - static uint32_t atomic_set_masked(uint32_t *a, uint32_t mask, uint32_t value) { uint32_t old, new, cmp = qatomic_read(a); @@ -115,26 +72,34 @@ static void sifive_plic_set_claimed(SiFivePLICState *plic, int irq, bool level) atomic_set_masked(&plic->claimed[irq >> 5], 1 << (irq & 31), -!!level); } -static int sifive_plic_irqs_pending(SiFivePLICState *plic, uint32_t addrid) +static uint32_t sifive_plic_claimed(SiFivePLICState *plic, uint32_t addrid) { + uint32_t max_irq = 0; + uint32_t max_prio = plic->target_priority[addrid]; int i, j; + for (i = 0; i < plic->bitfield_words; i++) { uint32_t pending_enabled_not_claimed = - (plic->pending[i] & ~plic->claimed[i]) & - plic->enable[addrid * plic->bitfield_words + i]; + (plic->pending[i] & ~plic->claimed[i]) & + plic->enable[addrid * plic->bitfield_words + i]; + if (!pending_enabled_not_claimed) { continue; } + for (j = 0; j < 32; j++) { int irq = (i << 5) + j; uint32_t prio = plic->source_priority[irq]; int enabled = pending_enabled_not_claimed & (1 << j); - if (enabled && prio > plic->target_priority[addrid]) { - return 1; + + if (enabled && prio > max_prio) { + max_irq = irq; + max_prio = prio; } } } - return 0; + + return max_irq; } static void sifive_plic_update(SiFivePLICState *plic) @@ -145,7 +110,7 @@ static void sifive_plic_update(SiFivePLICState *plic) for (addrid = 0; addrid < plic->num_addrs; addrid++) { uint32_t hartid = plic->addr_config[addrid].hartid; PLICMode mode = plic->addr_config[addrid].mode; - int level = sifive_plic_irqs_pending(plic, addrid); + bool level = !!sifive_plic_claimed(plic, addrid); switch (mode) { case PLICMode_M: @@ -158,41 +123,6 @@ static void sifive_plic_update(SiFivePLICState *plic) break; } } - - if (RISCV_DEBUG_PLIC) { - sifive_plic_print_state(plic); - } -} - -static uint32_t sifive_plic_claim(SiFivePLICState *plic, uint32_t addrid) -{ - int i, j; - uint32_t max_irq = 0; - uint32_t max_prio = plic->target_priority[addrid]; - - for (i = 0; i < plic->bitfield_words; i++) { - uint32_t pending_enabled_not_claimed = - (plic->pending[i] & ~plic->claimed[i]) & - plic->enable[addrid * plic->bitfield_words + i]; - if (!pending_enabled_not_claimed) { - continue; - } - for (j = 0; j < 32; j++) { - int irq = (i << 5) + j; - uint32_t prio = plic->source_priority[irq]; - int enabled = pending_enabled_not_claimed & (1 << j); - if (enabled && prio > max_prio) { - max_irq = irq; - max_prio = prio; - } - } - } - - if (max_irq) { - sifive_plic_set_pending(plic, max_irq, false); - sifive_plic_set_claimed(plic, max_irq, true); - } - return max_irq; } static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size) @@ -223,10 +153,15 @@ static uint64_t sifive_plic_read(void *opaque, hwaddr addr, unsigned size) if (contextid == 0) { return plic->target_priority[addrid]; } else if (contextid == 4) { - uint32_t value = sifive_plic_claim(plic, addrid); + uint32_t max_irq = sifive_plic_claimed(plic, addrid); + + if (max_irq) { + sifive_plic_set_pending(plic, max_irq, false); + sifive_plic_set_claimed(plic, max_irq, true); + } sifive_plic_update(plic); - return value; + return max_irq; } } From 6ca7155a8c8d88e5372f0ba337c33e86edbcb295 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 6 Jan 2022 07:39:34 +1000 Subject: [PATCH 290/730] target/riscv: Mark the Hypervisor extension as non experimental The Hypervisor spec is now frozen, so remove the experimental tag. Signed-off-by: Alistair Francis Reviewed-by: Anup Patel Reviewed-by: Bin Meng Message-Id: <20220105213937.1113508-6-alistair.francis@opensource.wdc.com> --- target/riscv/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6ef3314bce..9ea67bedd3 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -627,6 +627,7 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true), DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true), DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false), + DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, false), DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true), DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), @@ -645,7 +646,6 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true), DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true), DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true), - DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false), DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false), /* ePMP 0.9.3 */ DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false), From 07cb270a9ac914431577321b0e3e99d79cf56254 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 6 Jan 2022 07:39:35 +1000 Subject: [PATCH 291/730] target/riscv: Enable the Hypervisor extension by default Let's enable the Hypervisor extension by default. This doesn't affect named CPUs (such as lowrisc-ibex or sifive-u54) but does enable the Hypervisor extensions by default for the virt machine. Signed-off-by: Alistair Francis Reviewed-by: Anup Patel Reviewed-by: Bin Meng Message-Id: <20220105213937.1113508-7-alistair.francis@opensource.wdc.com> --- target/riscv/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 9ea67bedd3..29749e834f 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -627,7 +627,7 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true), DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true), DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false), - DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, false), + DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, true), DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true), DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), From 8f972e5b4beeeb35b15f75499d18a8cc5a320ce7 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 6 Jan 2022 07:39:36 +1000 Subject: [PATCH 292/730] hw/riscv: Use error_fatal for SoC realisation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When realising the SoC use error_fatal instead of error_abort as the process can fail and report useful information to the user. Currently a user can see this: $ ../qemu/bld/qemu-system-riscv64 -M sifive_u -S -monitor stdio -display none -drive if=pflash QEMU 6.1.93 monitor - type 'help' for more information (qemu) Unexpected error in sifive_u_otp_realize() at ../hw/misc/sifive_u_otp.c:229: qemu-system-riscv64: OTP drive size < 16K Aborted (core dumped) Which this patch addresses Reported-by: Markus Armbruster Signed-off-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Markus Armbruster Reviewed-by: Bin Meng Tested-by: Bin Meng Message-Id: <20220105213937.1113508-8-alistair.francis@opensource.wdc.com> --- hw/riscv/microchip_pfsoc.c | 2 +- hw/riscv/opentitan.c | 2 +- hw/riscv/sifive_e.c | 2 +- hw/riscv/sifive_u.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c index d1d065efbc..cafd1fc9ae 100644 --- a/hw/riscv/microchip_pfsoc.c +++ b/hw/riscv/microchip_pfsoc.c @@ -471,7 +471,7 @@ static void microchip_icicle_kit_machine_init(MachineState *machine) /* Initialize SoC */ object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_MICROCHIP_PFSOC); - qdev_realize(DEVICE(&s->soc), NULL, &error_abort); + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); /* Split RAM into low and high regions using aliases to machine->ram */ mem_low_size = memmap[MICROCHIP_PFSOC_DRAM_LO].size; diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index c531450b9f..0856c347e8 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -80,7 +80,7 @@ static void opentitan_board_init(MachineState *machine) /* Initialize SoC */ object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_IBEX_SOC); - qdev_realize(DEVICE(&s->soc), NULL, &error_abort); + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); memory_region_add_subregion(sys_mem, memmap[IBEX_DEV_RAM].base, machine->ram); diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 9b206407a6..dcb87b6cfd 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -88,7 +88,7 @@ static void sifive_e_machine_init(MachineState *machine) /* Initialize SoC */ object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_E_SOC); - qdev_realize(DEVICE(&s->soc), NULL, &error_abort); + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); /* Data Tightly Integrated Memory */ memory_region_add_subregion(sys_mem, diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index aa74e67889..7fbc7dea42 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -547,7 +547,7 @@ static void sifive_u_machine_init(MachineState *machine) &error_abort); object_property_set_str(OBJECT(&s->soc), "cpu-type", machine->cpu_type, &error_abort); - qdev_realize(DEVICE(&s->soc), NULL, &error_abort); + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); /* register RAM */ memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_DRAM].base, From d4452c692488228e6dce193f4f98ac762588d96a Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 6 Jan 2022 07:39:37 +1000 Subject: [PATCH 293/730] hw/riscv: virt: Allow support for 32 cores MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux supports up to 32 cores for both 32-bit and 64-bit RISC-V, so let's set that as the maximum for the virt board. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/435 Signed-off-by: Alistair Francis Reviewed-by: Anup Patel Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Bin Meng Message-Id: <20220105213937.1113508-9-alistair.francis@opensource.wdc.com> --- include/hw/riscv/virt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index b8ef99f348..6e9f61ccd9 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -24,7 +24,7 @@ #include "hw/block/flash.h" #include "qom/object.h" -#define VIRT_CPUS_MAX 8 +#define VIRT_CPUS_MAX 32 #define VIRT_SOCKETS_MAX 8 #define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt") From b3e0204968d4e5cc556aa5e09078dedbd1eee4a3 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 5 Jan 2022 09:42:48 +0800 Subject: [PATCH 294/730] roms/opensbi: Upgrade from v0.9 to v1.0 Upgrade OpenSBI from v0.9 to v1.0 and the pre-built bios images. The v1.0 release includes the following commits: ec5274b platform: implement K210 system reset 5487cf0 include: sbi: Simplify HSM state define names 8df1f9a lib: sbi: Use SBI_HSM_STATE_xyz defines instead of SBI_STATE_xyz defines 7c867fd lib: sbi: Rename sbi_hsm_hart_started_mask() function 638c948 lib: sbi: Remove redundant sbi_hsm_hart_started() function ca864a9 lib: sbi: Fix error codes returned by HSM start() and stop() functions 6290a22 include: sbi: Add HSM suspend related defines 4b05df6 lib: sbi: Add sbi_hart_reinit() function 807d71c include: sbi: Add hart_suspend() platform callback 7475689 lib: sbi: Implement SBI HSM suspend function b9cf617 include: sbi: Upgrade SBI implementation version to v0.3 50d4fde lib: Remove redundant sbi_platform_ipi_clear() calls ff5bd94 include: sbi: SBI function IDs for RFENCE extension 22d8ee9 firmware: Use lla to access all global symbols 0f20e8a firmware: Support position independent execution ddad02d lib: sbi: illegal CSR 0x306 access in hpm_allowed() bfc85c7 include: headers: Replace __ASSEMBLY__ with __ASSEMBLER__ 9190ad1 lib/utils: Support the official clint DT bindings ca3f358 lib/utils: Drop the 'compat' parameter of fdt_plic_fixup() 4edc822 lib/utils: Support fixing up the official DT bindings of PLIC 4ef2f5d firware: optimize the exception exit code 3d8a952 lib: fix csr detect support e71a7c1 firmware: Remove redundant add instruction from trap restore path d4a94ea include: types: Add __aligned(x) to define the minimum alignement d0e406f include: sbi: Allow direct initialization via SPIN_LOCK_INIT() 4d8e2f1 lib: sbi: Replace test-and-set locks by ticket locks 70ffc3e lib: sbi: fix atomic_add_return 27a16b1 docs: fix link to OpenPiton documentation b1df1ac lib: sbi: Domains can be registered only before finalizing domains 7495bce lib: sbi: Add sbi_domain_memregion_init() API 4dc0001 lib: sbi: Add sbi_domain_root_add_memregion() API 8b56980 lib: utils/sys: Add CLINT memregion in the root domain fc37c97 lib: sbi: Make the root domain instance global variable e7e4bcd lib: utils: Copy over restricted root domain memregions to FDT domains f41196a lib: sbi: Make sbi_domain_memregion_initfw() a local function c5d0645 lib: utils: Implement "64bit-mmio" property parsing 49e422c lib: utils: reset: Add T-HEAD sample platform reset driver 0d56293 lib: sbi: Fix sbi_domain_root_add_memregion() for merging memregions bf3ef53 firmware: Enable FW_PIC by default 1db8436 platform: Remove platform/thead 6d1642f docs: generic: Add T-HEAD C9xx series processors a3689db lib: sbi: Remove domains_root_regions() platform callback 068ca08 lib: sbi: Simplify console platform operations 559a8f1 lib: sbi: Simplify timer platform operations dc39c7b lib: sbi: Simplify ipi platform operations 043d088 lib: sbi: Simplify system reset platform operations a84a1dd lib: sbi: Simplify HSM platform operations e9a27ab lib: sbi: Show devices provided by platform in boot prints 632e27b docs/platform: sifive_fu540: Update U-Boot defconfig name 117fb6d lib: utils/serial: Add support for Gaisler APBUART 552f53f docs: platform: Sort platform names d4177e7 docs: platform: Describe sifive_fu540 as supported generic platform 26998f3 platform: Remove sifive/fu540 platform f90c4c2 lib: sbi: Have spinlock checks return bool e822b75 lib: utils/serial: Support Synopsys DesignWare APB UART 6139ab2 Makefile: unconditionally disable SSP c9ef2bc lib: utils: Add strncpy macro to libfdt_env.h ee7c2b2 lib: utils/fdt: Don't use sbi_string functions fe92347 lib: utils/fdt: Replace strcmp with strncmp b2dbbc0 lib: Check region base for merging in sbi_domain_root_add_memregion() 54d7def lib: utils: Try other FDT drivers when we see SBI_ENODEV d9ba653 docs: debugging OpenSBI 66c4fca lib: utils: consider ':' in stdout-path f30b189 lib: sbi_scratch: remove owner from sbi_scratch_alloc_offset a03ea2e platform: andes/ae350: Cosmetic fixes in plicsw.c b32fac4 docs/platform: andes-ae350: Fix missing spaces de446cc platform: andes/ae350: Drop plicsw_get_pending() 434198e platform: andes/ae350: Drop plicsw_ipi_sync() 1da3d80 lib: sbi_scratch: zero out scratch memory on all harts 360ab88 lib: utils: missing initialization in thead_reset_init 79f9b42 lib: sbi: Fix GET_F64_REG inline assembly eb90e0a lib: utils/libfdt: Upgrade to v1.6.1 release cdcf907 lib: sign conflict in sbi_tlb_entry_process() 9901794 lib: sign conflict in wake_coldboot_harts() 11c345f lib: simplify sbi_fifo_inplace_update() 4519e29 lib: utils/timer: Add ACLINT MTIMER library 5a049fe lib: utils/ipi: Add ACLINT MSWI library bd5d208 lib: utils: Add FDT parsing API common for both ACLINT and CLINT 56fc5f7 lib: utils/ipi: Add FDT based ACLINT MSWI IPI driver 03d6bb5 lib: utils/timer: Add FDT based ACLINT MTIMER driver a731c7e platform: Replace CLINT library usage with ACLINT library b7f2cd2 lib: utils: reset: unify naming of 'sifive_test' device 197e089 docs/platform: thead-c9xx: Remove FW_PIC=y 17e23b6 platform: generic: Terminate platform.name with null 3e8b31a docs: Add device tree bindings for SBI PMU extension fde28fa lib: sbi: Detect mcountinihibit support at runtime d3a96cc lib: sbi: Remove stray '\' character 0829f2b lib: sbi: Detect number of bits implemented in mhpmcounter 9c9b4ad lib: sbi: Disable m/scounteren & enable mcountinhibit 41ae63c include: Add a list empty check function fd9116b lib: sbi: Remove redundant boot time print statement 49966db lib: sbi: Use csr_read/write_num to read/update PMU counters e7cc7a3 lib: sbi: Add PMU specific platform hooks 13d40f2 lib: sbi: Add PMU support ae72ec0 utils: fdt: Add fdt helper functions to parse PMU DT nodes 37f9b0f lib: sbi: Implement SBI PMU extension 764a17d lib: sbi: Implement firmware counters ec1b8bb lib: sbi: Improve TLB function naming 0e12aa8 platform: generic: Add PMU support 14c7f71 firmware: Minor optimization in _scratch_init() dafaa0f docs: Correct a typo in platform_guide.md abfce9b docs: Make visible in the rendered platform guide dcb756b firmware: Remove the sanity checks in fw_save_info() b88b366 firmware: Define a macro for version of struct fw_dynamic_info a76ac44 lib: sbi: Fix sbi_pmu_exit() for systems not having MCOUNTINHIBIT csr 7f1be8a fw_base: Don't mark fw_platform_init as both global and weak 397afe5 fw_base: Put data in .data rather than .text a3d328a firmware: Explicitly pass -pie to the linker, not just the driver 09ad811 firmware: Only default FW_PIC to y if supported 2942777 Makefile: Support building with Clang and LLVM binutils 17729d4 lib: utils: Drop dependency on libgcc by importing part of FreeBSD's libquad e931f38 lib: utils/fdt: Add fdt_parse_phandle_with_args() API 36b8eff lib: utils/gpio: Add generic GPIO configuration library c14f1fe lib: utils/gpio: Add simple FDT based GPIO framework 4c3df2a lib: utils/gpio: Add minimal SiFive GPIO driver e3d6919 lib: utils/reset: Add generic GPIO reset driver 7210e90 firmware: use __SIZEOF_LONG__ for field offsets in fw_dynamic.h f3a8f60 include: types: Use __builtin_offsetof when supported 8a1475b firmware: Remove the unhelpful alignment codes before fdt relocation a4555e5 docs: Document parameters passed to firmware and alignment requirement 2c74dc3 docs: Document FW_PIC compile time option 81eb708 README: Update toolchain information 9890391 Makefile: Manually forward RELAX_FLAG to the assembler when linking with LLD 74db0ac firmware: use _fw_start for load address 217d5e4 generic: fu740: add workaround for CIP-1200 errata ce03c88 lib: utils: remove unused variable in fdt_reset_init e928472 lib: utils: support both of gpio-poweroff, gpio-reset d244f3d lib: sbi: Fix bug in strncmp function when count is 0 47a4765 lib: utils/fdt: Change addr and size to uint64_t e0d1b9d lib: utils/timer: Allow separate base addresses for MTIME and MTIMECMP 7a3a0cc lib: utils: Extend fdt_get_node_addr_size() for multiple register sets f3a0eb8 lib: utils/fdt: Extend fdt_parse_aclint_node() function b35f782 lib: utils/timer: Allow ACLINT MTIMER supporting only 32-bit MMIO 7aa6c9a lib: utils/timer: Simplify MTIMER synchronization 33eac76 lib: sbi: Fix bug in sbi_ecall_rfence that misses checking ee27437 lib: sbi_trap: Restore redirect for access faults b1d3e91 payloads/test: Add support for SBI v0.2 ecalls bd316e2 lib: sbi: Correct typo in faults delegation CSR name c262306 lib: sbi: protect dprintf output with spinlock 1718b16 lib: sbi: Checking fifo validness in sbi_fifo_is_empty and is_full bd35521 lib: sbi: Refine the way to construct platform features 0274a96 lib: utils/reset: Sort fdt_reset driver list 395ff7e lib: utils/reset: Add a sunxi watchdog reset driver 3477f08 lib: sbi: fix ctz bug 12753d2 lib: sbi: add some macros to detect BUG at runtime 51113fe lib: sbi: Add BUG() macro for csr_read/write_num() and misa_string() 72154f4 lib: utils/fdt: Add fdt_parse_timebase_frequency() function 12e7af9 lib: sbi: Add timer frequency to struct sbi_timer_device 6355155 lib: sbi: Print timer frequency at boot time 9d0ab35 lib: sbi: Add generic timer delay loop function fa59dd3 lib: utils/reset: use sbi_timer_mdelay() in gpio reset driver 754d511 lib: utils: identify supported GPIO reset methods 516161c lib: sbi: convert reset to list 9283d50 lib: sbi: add priority for reset handler c38973e lib: sbi: Save context for all non-retentive suspend types 67cbbcb lib: sbi: system reset with invalid parameters 422eda4 Makefile: Add build time and compiler info string 78c2b19 lib: utils/irqchip: Automatically delegate T-HEAD PLIC access 309e8bd lib: utils/reset: Register separate GPIO system reset devices 723aa88 lib: sbi: Refine addr format in sbi_printf c891acc include: sbi_utils: Introduce an helper to get fdt base address 013ba4e lib: sbi: Fix GPA passed to __sbi_hfence_gvma_xyz() functions 0979ffd lib: utils/gpio: use list for drivers 2fe2f55 lib: sbi: move sbi_boot_print_general() 57f094e platform: generic: move fdt_reset_init to final_init be245ac lib: sbi: error handling in fdt_reset_init() a74daf2 riscv: Add new CSRs introduced by Sscofpmf[1] extension 7084ad9 lib: sbi: Update csr_read/write_num for PMU 867c653 lib: sbi: Detect Sscofpmf extension at run time 9134c36 lib: sbi: Delegate PMU counter overflow interrupt to S mode 730f01b lib: sbi: Support sscofpmf extension in OpenSBI 2363f95 lib: sbi: Always enable access for all counters 0c304b6 lib: sbi: Allow programmable counters to monitor cycle/instret events 1e14732 lib: sbi: Reset the mhpmevent value upon counter reset b628cfd lib: sbi: Counter info width should be zero indexed b28f070 lib: sbi: Enable PMU extension for platforms without mcountinhibit 15906a3 lib: utils: Rename the prefix in PMU DT properties b8845e4 lib: sbi: Fix initial value mask while updating the counters 31fe5a7 lib: sbi: Fix PMP address bits detection 94eba23 lib: utils/reset: add priority to gpio reset 1d462e0 lib: utils/reset: separate driver init func 2c964a2 lib: utils/i2c: Add generic I2C configuration library 6ca6bca lib: utils/i2c: Add simple FDT based I2C framework 13a1158 lib: utils/i2c: Add minimal SiFive I2C driver f374496 platform: sifive_fu740: add platform reset driver d335a17 lib: sbi: clear pmpcfg.A before setting in pmp_set() 52af6e4 lib: utils: Add LiteX UART support 22d556d lib: sbi: Fix spelling of "address" in sbi_domain.c 7a22c78 lib: sbi: Fix missing space 7e77706 lib: sbi: Resolve the uninitialized complaint in sbi_pmu 14faee6 lib: sbi: Improve fatal error handling 2428987 lib: pmu: support the event ID encoded by a bitmap. 66fbcc0 docs/platform: spike: Enhance Spike examples 460041c lib: pmu: check SSCOF before masking 69d7e53 Makefile: Fix -msave-restore compile warning with CLANG-10 (or lower) d249d65 lib: sbi: Fix compile errors using -Os option f270359 Makefile: Improve the method to disable -m(no-)save-restore option 2082153 lib: sbi: simplify pmp_set(), pmp_get() d30bde3 firmware: Move memcpy/memset mapping to fw_base.S 48f91ee include: Bump-up version to 1.0 Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Signed-off-by: Alistair Francis --- .../opensbi-riscv32-generic-fw_dynamic.bin | Bin 78680 -> 108504 bytes .../opensbi-riscv32-generic-fw_dynamic.elf | Bin 727464 -> 838904 bytes .../opensbi-riscv64-generic-fw_dynamic.bin | Bin 75096 -> 105296 bytes .../opensbi-riscv64-generic-fw_dynamic.elf | Bin 781264 -> 934696 bytes roms/opensbi | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin b/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin index ae651e2993e253a4663c438b47f2e81e30415c39..dba8e8655fbf39c128b19675cdd205805f85e7e1 100644 GIT binary patch literal 108504 zcmc${3s_TE);GRSl9NLsYBXZBYDq)*6w~wg#1eAc1e~eG;tAaE>wu4hD{{u5rJ z&3EW1EZ=YxCe*7BJfS!YGDvOhR;dtKGDAX?{!%nT>R6D}uaH7+q|&eySyGtd5g|P5 zZkb;Vr;@1fL7K9g#VB0LpjhQ#ZP|?y6wXM|?@>C#{NJ<-9@egx-p&b-!U_^GrcT2X z3@v<8ODje~+Jep3?WQc@obBPm1c-~GqQV8kke&IXAY5=q&8@|#U_f4mxn^f>sg?d$ zkuu=UL+J-9l@mXHs7wb-7yN`$^`E~^Q7R`r{FP75BvXc5^+>$-C*_myOr$6os|@u% z*9U?$0%d?eFgU#%kApOV!8&`?;)qGP`%RUcX&*kAk_!$OKCCSk3B~L%yU4zoMut6e zQTV%{p_Rj^@W0(c0mJO@X1V+>viIFWM~8)H3sLyrooMxN%eMx~e%FEQj%v#8_!j;- zsNEJeDFq4l3y{*kn#vW75IS@zedf6e3$B^fXO#ZWk(v^`*BfRyEmR5-MgDi}T-~Qv zKOUMQQ$sCLPvc9j?V`8j3{NuRlqb};*>`;rr8SiJBG$B)%Jroghi+qk+OqH=3}RRO zMZ%Zx>SKHfL#YY}N;O3$m=;b!tsr_0^0^x%3wz(dWtr~{hX`JKB2 zDfb6-%Jp-*3;}ZmqZ@F%y8*IkqpNVt(ba-lL8bWUu)2}Q9y$5w>3~L6Q^?uSmZ|5b zUz~Mm&gG+(bw?X&PS-UZYiYQ6^784cjn|uQp1sv_=X~eIo=bg~!)XdR{o4}_{u(5F zoI{4kYmqR3ri4n4GAL^)v^aY4`~=zZrOU^xcyWbr5-l=J(ujn?oX8MdD-wp#v>`-8 z3!mULaPS`ngn;K8lLgN9$uK ztzJvb)6b(~^|6#rucPAhanyYMd}@Jy0ku%SkXoc)loF4oZBF;rzw(5+u@=rX&1bGd zQPyYH%$w_|E`nb+x(v1*qn~j<7>Xj$G6(sRz}5)@;sL?OCLN3F{5;&swLW` zbJ=6pz3oc86v8}wXy`|2TI3Ts_+2A>_?;6x{9a3W-$4}eALaS&hyU>7o3i!MSk5

F%@Us;dF+A>mt)weB7JL9u}y&5E>s|>+3 z-M~3f&Rq7-5mdoETFYj&jTwp&AySGl}{T=%(zb!=$*KP?gpu+eU#Qt+zV@{Tao_>6VziA6$N29@_M71O|};Hx^o zF`jN`B~oMv%A^aT^!1yq4msVf*TC0RrK=qi=v(Ajc4dP@LEm~nxr|UgO8-p0qS6tL zF`j4t!eqxt&$CRn5%}LEyi^eXrZ@g2KBY(Le`A@jEXCGcQ8cp)^nPXJj(LsITcath zj&r8B|4~kdK`C6BRp+FF{Cub^eKp8`xnL=m zwasCTfV4T9RlqNlAL~>%uH>IJ@GM)&ilri=#bx`dG4BxL&{I|oj>CQ7iIW1{Usz$s znlF5kXk|L^KTn=ULHhV9$A2^gktI0O!=5KJveK0UG_{|4WCohXC7|B~XME1{gTC(@;L#Wl-=E`kTRLihhASDM z$yw-3FI|jtkmEBzkzB-6v_dND=R4DL7J+sISUZ=Zwt2MU%~{dMJZ%xsmc}~M8|NEr z83IesBZ$qFj>M(R4wp`{(3xm}XP8z#MC4k+$;HU$BD7)jmx~<#m3|BKqY;Kk=_XG| zD};naJ5eQT5R|MXThPnWzA zgGrm&B(;u8YY&F;z80+Kz9FoZ<6^?B1=%(mTP(D*FoQ`_HL%n_q=v69mVcj-y zPXDmKc+;=N=}*StDh|G^O8>L>OW>cK>h`B_E%0A$^XeVKN=YqW^&qV1FOc37n67Xj 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 literal 78680 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

b$NQ2JAHOuy;x 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

JRDa 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
|OtqIR*2|1iFFYK(os){dIGUvzK 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

xw8pwO4Np|jtA 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

>T^dv_+xV`hgdOeiQBW!RxM6hRI2N?dsVuIqStJ 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%0DjMEuF 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�f)czlaO}4ZAA>z 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

F)o;`N*!_q6y{J|?s-rrI&aR~z5N8o$Uztzo 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 X_(O?EFU;-=L0*2MeL^(7B*OhKVXxQ0 literal 75096 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

1Y?19ViG3`D#FR?%BjH1 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

  • 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 z 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

    +otc}wOd)_h`=9gxYWxmj@8 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%0A0Ayt6n?nyL^umSRd_m_ofQbqhO+SUg>e^$&zJe| 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 p;!?ky~Ys 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 Z(z{G=gWgVwEdHJgl>d)Lh`%BK{|{38qZ0rC literal 781264 zcmcG%3tUr2_BcK_H}@t1AHe{Df{I3<($;1R_~2Er1}d$Vx{Fr7+ZMdwyH$(UqDv)& zOAPo328;++vW;6spLiP@sfH78JQQPz=wM z5LK{36i7?Zz-x@qgJ338GC33_6W@A~eeu~RA;ncZ$tXa`kn#14auOiqg-43=m556d zyr}s^fNbe8WFU!*fMd{*(V7Yp1y1;5%{!Bf6Cic(tVtDn-;X@-0dw(>H1jhf zltZd)!s7Xi>V3rg@oiLjluJ1kWluSIl1tg!E1w9s6DLlvL)1qZ)lSH@5lueH)LbB# zAIwDXQSvJiDayYljtY*F=F2MwGxjn+e@$_9x)93L{1GufTp(PIaw&@8lq;uf_3q%x z*(b8&-aN&q-h^_l5xu2M%{!34iTJ)WaY~|06F31WlqrZS$0md5Sigbli4p5m>Y@=>n zAhCiNsRP8~mX(QCpj4y@(<= z#8C2g;9aotpB361GGc$=1OZ}SAYKR*Oh6T)4T3iUX| z9P)s%V4p(SgcL#l8C4gkuSzlZ*eDGiSyzBBP=x)D@D~)yV}g-9bLFpgQ3N#!I3AAw zte6YW)_SdeLJ?+vKK>NcNvH@C2uGKh@I2H>IFjZRgZbr@2i2EuE|rPeCyvHWpBG4u zmLel0X+}^%2d4Z0-y7QNf372qc|Ho=7E)iSkD@#rAQ-{@E63%#s9MX+iJqJbjnka5175<5D}wk8;2O} zY9ej5>yRQT-yZP`!|dRmT!9sb3;qR=-RvQZFJFs}~cms9#BmLqQqo_U~YdpTDq> z?FtgFG|MXobt>^H^Mw+)GYcw__}z^3wD^p4%m=3>BBycYIm_lR^b&Okxvn&S(Ap=7 zab0DOZRq3RTCwXoS2OnJ59DEPJf8XL$r{G$=HqD!XUPn-H7k{q~|Hz=DIRig)X#)*5{2f4l z3Z`cG?$HpJ#%`~8glTRkEI!hyDbkme%q}OSF=bO<>?pVp%Vrqm0Z^8c(>9zh|5qaV zGV8}$HZ_i?dYQdW?ijO(DY%efq#meM0EyIZGka0(Rtg){wHZdUE7fj=pmy3kh5F6< zEKT^M*~9jXlv~Y{sNZm2<)6%xse6o$t3lCfTmE~vY+P=s@gPHq4w@~S5Sh10zhU

    Ty`sPz_~^V`f%P`CV8EO85}n*#M~wQ`|UZa2G8 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 kKF%=lRaa#%c* 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%0A3p|>H5W``$$qe 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

    E@gKsZQO-}BhJGbxFLA5&) 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 XFDuHI*RWB4;z>*Y*V)AK-KYQm|Jk{4 diff --git a/roms/opensbi b/roms/opensbi index 234ed8e427..48f91ee9c9 160000 --- a/roms/opensbi +++ b/roms/opensbi @@ -1 +1 @@ -Subproject commit 234ed8e427f4d92903123199f6590d144e0d9351 +Subproject commit 48f91ee9c960f048c4a7d1da4447d31e04931e38 From 629ccdaa4e43c39d38d67b5ba1cec2bbedb6104d Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Wed, 5 Jan 2022 10:22:44 +0800 Subject: [PATCH 295/730] target/riscv: rvv-1.0: Call the correct RVF/RVD check function for widening fp insns Vector widening floating-point instructions should use require_scale_rvf() instead of require_rvf() to check whether RVF/RVD is enabled. Signed-off-by: Frank Chang Acked-by: Alistair Francis Message-Id: <20220105022247.21131-2-frank.chang@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 5e3f7fdb77..8d92243f2b 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -2254,7 +2254,8 @@ GEN_OPFVF_TRANS(vfrsub_vf, opfvf_check) static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a) { return require_rvv(s) && - require_rvf(s) && + require_scale_rvf(s) && + (s->sew != MO_8) && vext_check_isa_ill(s) && vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm); } @@ -2292,7 +2293,8 @@ GEN_OPFVV_WIDEN_TRANS(vfwsub_vv, opfvv_widen_check) static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a) { return require_rvv(s) && - require_rvf(s) && + require_scale_rvf(s) && + (s->sew != MO_8) && vext_check_isa_ill(s) && vext_check_ds(s, a->rd, a->rs2, a->vm); } @@ -2321,7 +2323,8 @@ GEN_OPFVF_WIDEN_TRANS(vfwsub_vf) static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a) { return require_rvv(s) && - require_rvf(s) && + require_scale_rvf(s) && + (s->sew != MO_8) && vext_check_isa_ill(s) && vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm); } @@ -2359,7 +2362,8 @@ GEN_OPFWV_WIDEN_TRANS(vfwsub_wv) static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a) { return require_rvv(s) && - require_rvf(s) && + require_scale_rvf(s) && + (s->sew != MO_8) && vext_check_isa_ill(s) && vext_check_dd(s, a->rd, a->rs2, a->vm); } From 91cade44cd49e23114c3101ef22d8a0b370523ae Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Wed, 5 Jan 2022 10:22:45 +0800 Subject: [PATCH 296/730] target/riscv: rvv-1.0: Call the correct RVF/RVD check function for widening fp/int type-convert insns vfwcvt.xu.f.v, vfwcvt.x.f.v, vfwcvt.rtz.xu.f.v and vfwcvt.rtz.x.f.v convert single-width floating-point to double-width integer. Therefore, should use require_rvf() to check whether RVF/RVD is enabled. vfwcvt.f.xu.v, vfwcvt.f.x.v convert single-width integer to double-width floating-point, and vfwcvt.f.f.v convert double-width floating-point to single-width floating-point. Therefore, should use require_scale_rvf() to check whether RVF/RVD is enabled. Signed-off-by: Frank Chang Acked-by: Alistair Francis Message-Id: <20220105022247.21131-3-frank.chang@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 34 ++++++++++++++++++------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 8d92243f2b..f1b44ccad2 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -2613,16 +2613,27 @@ GEN_OPFV_CVT_TRANS(vfcvt_rtz_x_f_v, vfcvt_x_f_v, RISCV_FRM_RTZ) static bool opfv_widen_check(DisasContext *s, arg_rmr *a) { return require_rvv(s) && - require_scale_rvf(s) && - (s->sew != MO_8) && vext_check_isa_ill(s) && vext_check_ds(s, a->rd, a->rs2, a->vm); } -#define GEN_OPFV_WIDEN_TRANS(NAME, HELPER, FRM) \ +static bool opxfv_widen_check(DisasContext *s, arg_rmr *a) +{ + return opfv_widen_check(s, a) && + require_rvf(s); +} + +static bool opffv_widen_check(DisasContext *s, arg_rmr *a) +{ + return opfv_widen_check(s, a) && + require_scale_rvf(s) && + (s->sew != MO_8); +} + +#define GEN_OPFV_WIDEN_TRANS(NAME, CHECK, HELPER, FRM) \ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ { \ - if (opfv_widen_check(s, a)) { \ + if (CHECK(s, a)) { \ if (FRM != RISCV_FRM_DYN) { \ gen_set_rm(s, RISCV_FRM_DYN); \ } \ @@ -2649,12 +2660,17 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ return false; \ } -GEN_OPFV_WIDEN_TRANS(vfwcvt_xu_f_v, vfwcvt_xu_f_v, RISCV_FRM_DYN) -GEN_OPFV_WIDEN_TRANS(vfwcvt_x_f_v, vfwcvt_x_f_v, RISCV_FRM_DYN) -GEN_OPFV_WIDEN_TRANS(vfwcvt_f_f_v, vfwcvt_f_f_v, RISCV_FRM_DYN) +GEN_OPFV_WIDEN_TRANS(vfwcvt_xu_f_v, opxfv_widen_check, vfwcvt_xu_f_v, + RISCV_FRM_DYN) +GEN_OPFV_WIDEN_TRANS(vfwcvt_x_f_v, opxfv_widen_check, vfwcvt_x_f_v, + RISCV_FRM_DYN) +GEN_OPFV_WIDEN_TRANS(vfwcvt_f_f_v, opffv_widen_check, vfwcvt_f_f_v, + RISCV_FRM_DYN) /* Reuse the helper functions from vfwcvt.xu.f.v and vfwcvt.x.f.v */ -GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_xu_f_v, vfwcvt_xu_f_v, RISCV_FRM_RTZ) -GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_x_f_v, vfwcvt_x_f_v, RISCV_FRM_RTZ) +GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_xu_f_v, opxfv_widen_check, vfwcvt_xu_f_v, + RISCV_FRM_RTZ) +GEN_OPFV_WIDEN_TRANS(vfwcvt_rtz_x_f_v, opxfv_widen_check, vfwcvt_x_f_v, + RISCV_FRM_RTZ) static bool opfxv_widen_check(DisasContext *s, arg_rmr *a) { From 79e6176ea09c7615966d3ed05be0d40dc9de249f Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Wed, 5 Jan 2022 10:22:46 +0800 Subject: [PATCH 297/730] target/riscv: rvv-1.0: Call the correct RVF/RVD check function for narrowing fp/int type-convert insns vfncvt.f.xu.w, vfncvt.f.x.w convert double-width integer to single-width floating-point. Therefore, should use require_rvf() to check whether RVF/RVD is enabled. vfncvt.f.f.w, vfncvt.rod.f.f.w convert double-width floating-point to single-width integer. Therefore, should use require_scale_rvf() to check whether RVF/RVD is enabled. Signed-off-by: Frank Chang Acked-by: Alistair Francis Message-Id: <20220105022247.21131-4-frank.chang@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 32 ++++++++++++++++++------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index f1b44ccad2..6c285c958b 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -2719,17 +2719,29 @@ GEN_OPFXV_WIDEN_TRANS(vfwcvt_f_x_v) static bool opfv_narrow_check(DisasContext *s, arg_rmr *a) { return require_rvv(s) && - require_rvf(s) && - (s->sew != MO_64) && vext_check_isa_ill(s) && /* OPFV narrowing instructions ignore vs1 check */ vext_check_sd(s, a->rd, a->rs2, a->vm); } -#define GEN_OPFV_NARROW_TRANS(NAME, HELPER, FRM) \ +static bool opfxv_narrow_check(DisasContext *s, arg_rmr *a) +{ + return opfv_narrow_check(s, a) && + require_rvf(s) && + (s->sew != MO_64); +} + +static bool opffv_narrow_check(DisasContext *s, arg_rmr *a) +{ + return opfv_narrow_check(s, a) && + require_scale_rvf(s) && + (s->sew != MO_8); +} + +#define GEN_OPFV_NARROW_TRANS(NAME, CHECK, HELPER, FRM) \ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ { \ - if (opfv_narrow_check(s, a)) { \ + if (CHECK(s, a)) { \ if (FRM != RISCV_FRM_DYN) { \ gen_set_rm(s, RISCV_FRM_DYN); \ } \ @@ -2756,11 +2768,15 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ return false; \ } -GEN_OPFV_NARROW_TRANS(vfncvt_f_xu_w, vfncvt_f_xu_w, RISCV_FRM_DYN) -GEN_OPFV_NARROW_TRANS(vfncvt_f_x_w, vfncvt_f_x_w, RISCV_FRM_DYN) -GEN_OPFV_NARROW_TRANS(vfncvt_f_f_w, vfncvt_f_f_w, RISCV_FRM_DYN) +GEN_OPFV_NARROW_TRANS(vfncvt_f_xu_w, opfxv_narrow_check, vfncvt_f_xu_w, + RISCV_FRM_DYN) +GEN_OPFV_NARROW_TRANS(vfncvt_f_x_w, opfxv_narrow_check, vfncvt_f_x_w, + RISCV_FRM_DYN) +GEN_OPFV_NARROW_TRANS(vfncvt_f_f_w, opffv_narrow_check, vfncvt_f_f_w, + RISCV_FRM_DYN) /* Reuse the helper function from vfncvt.f.f.w */ -GEN_OPFV_NARROW_TRANS(vfncvt_rod_f_f_w, vfncvt_f_f_w, RISCV_FRM_ROD) +GEN_OPFV_NARROW_TRANS(vfncvt_rod_f_f_w, opffv_narrow_check, vfncvt_f_f_w, + RISCV_FRM_ROD) static bool opxfv_narrow_check(DisasContext *s, arg_rmr *a) { From dfdb46a3765bdab40a0b36722b4828d52ea8de96 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Thu, 6 Jan 2022 14:40:20 +0100 Subject: [PATCH 298/730] target/riscv: Fix position of 'experimental' comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When commit 0643c12e4b dropped the 'x-' prefix for Zb[abcs] and set them to be enabled by default, the comment about experimental extensions was kept in place above them. This moves it down a few lines to only cover experimental extensions. References: 0643c12e4b ("target/riscv: Enable bitmanip Zb[abcs] instructions") Signed-off-by: Philipp Tomsich Reviewed-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20220106134020.1628889-1-philipp.tomsich@vrull.eu Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 29749e834f..ce21c1b5b1 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -641,11 +641,12 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128), DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64), - /* These are experimental so mark with 'x-' */ DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true), DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true), DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true), DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true), + + /* These are experimental so mark with 'x-' */ DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false), /* ePMP 0.9.3 */ DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false), From fc313c64345453c7a668d765610dfd7135e21a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:00:51 +0100 Subject: [PATCH 299/730] exec/memop: Adding signedness to quad definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Renaming defines for quad in their various forms so that their signedness is now explicit. Done using git grep as suggested by Philippe, with a bit of hand edition to keep assignments aligned. Signed-off-by: Frédéric Pétrot Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-2-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- accel/tcg/cputlb.c | 30 +++++------ accel/tcg/ldst_common.c.inc | 8 +-- accel/tcg/user-exec.c | 8 +-- include/exec/memop.h | 8 +-- include/tcg/tcg-op.h | 4 +- target/alpha/translate.c | 32 ++++++------ target/arm/helper-a64.c | 8 +-- target/arm/translate-a32.h | 4 +- target/arm/translate-a64.c | 8 +-- target/arm/translate-neon.c | 6 +-- target/arm/translate-sve.c | 10 ++-- target/arm/translate-vfp.c | 8 +-- target/arm/translate.c | 2 +- target/cris/translate.c | 2 +- target/hppa/translate.c | 4 +- target/i386/tcg/mem_helper.c | 2 +- target/i386/tcg/translate.c | 36 +++++++------- target/m68k/op_helper.c | 2 +- target/mips/tcg/micromips_translate.c.inc | 10 ++-- target/mips/tcg/translate.c | 58 +++++++++++----------- target/mips/tcg/tx79_translate.c | 8 +-- target/ppc/translate.c | 32 ++++++------ target/ppc/translate/fixedpoint-impl.c.inc | 22 ++++---- target/ppc/translate/fp-impl.c.inc | 4 +- target/ppc/translate/vsx-impl.c.inc | 42 ++++++++-------- target/riscv/insn_trans/trans_rva.c.inc | 22 ++++---- target/riscv/insn_trans/trans_rvd.c.inc | 4 +- target/riscv/insn_trans/trans_rvh.c.inc | 4 +- target/riscv/insn_trans/trans_rvi.c.inc | 4 +- target/s390x/tcg/insn-data.def | 28 +++++------ target/s390x/tcg/mem_helper.c | 8 +-- target/s390x/tcg/translate.c | 8 +-- target/s390x/tcg/translate_vx.c.inc | 18 +++---- target/sh4/translate.c | 12 ++--- target/sparc/translate.c | 36 +++++++------- target/tricore/translate.c | 4 +- target/xtensa/translate.c | 4 +- tcg/aarch64/tcg-target.c.inc | 2 +- tcg/arm/tcg-target.c.inc | 10 ++-- tcg/i386/tcg-target.c.inc | 12 ++--- tcg/mips/tcg-target.c.inc | 12 ++--- tcg/ppc/tcg-target.c.inc | 16 +++--- tcg/riscv/tcg-target.c.inc | 6 +-- tcg/s390x/tcg-target.c.inc | 18 +++---- tcg/sparc/tcg-target.c.inc | 16 +++--- tcg/tcg.c | 4 +- tcg/tci.c | 16 +++--- 47 files changed, 311 insertions(+), 311 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index b69a953447..5e0d0eebc3 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1885,9 +1885,9 @@ load_memop(const void *haddr, MemOp op) return (uint32_t)ldl_be_p(haddr); case MO_LEUL: return (uint32_t)ldl_le_p(haddr); - case MO_BEQ: + case MO_BEUQ: return ldq_be_p(haddr); - case MO_LEQ: + case MO_LEUQ: return ldq_le_p(haddr); default: qemu_build_not_reached(); @@ -2081,16 +2081,16 @@ tcg_target_ulong helper_be_ldul_mmu(CPUArchState *env, target_ulong addr, uint64_t helper_le_ldq_mmu(CPUArchState *env, target_ulong addr, MemOpIdx oi, uintptr_t retaddr) { - validate_memop(oi, MO_LEQ); - return load_helper(env, addr, oi, retaddr, MO_LEQ, false, + validate_memop(oi, MO_LEUQ); + return load_helper(env, addr, oi, retaddr, MO_LEUQ, false, helper_le_ldq_mmu); } uint64_t helper_be_ldq_mmu(CPUArchState *env, target_ulong addr, MemOpIdx oi, uintptr_t retaddr) { - validate_memop(oi, MO_BEQ); - return load_helper(env, addr, oi, retaddr, MO_BEQ, false, + validate_memop(oi, MO_BEUQ); + return load_helper(env, addr, oi, retaddr, MO_BEUQ, false, helper_be_ldq_mmu); } @@ -2166,7 +2166,7 @@ uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr addr, uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr, MemOpIdx oi, uintptr_t ra) { - return cpu_load_helper(env, addr, oi, MO_BEQ, helper_be_ldq_mmu); + return cpu_load_helper(env, addr, oi, MO_BEUQ, helper_be_ldq_mmu); } uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr addr, @@ -2210,10 +2210,10 @@ store_memop(void *haddr, uint64_t val, MemOp op) case MO_LEUL: stl_le_p(haddr, val); break; - case MO_BEQ: + case MO_BEUQ: stq_be_p(haddr, val); break; - case MO_LEQ: + case MO_LEUQ: stq_le_p(haddr, val); break; default: @@ -2465,15 +2465,15 @@ void helper_be_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, void helper_le_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, MemOpIdx oi, uintptr_t retaddr) { - validate_memop(oi, MO_LEQ); - store_helper(env, addr, val, oi, retaddr, MO_LEQ); + validate_memop(oi, MO_LEUQ); + store_helper(env, addr, val, oi, retaddr, MO_LEUQ); } void helper_be_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, MemOpIdx oi, uintptr_t retaddr) { - validate_memop(oi, MO_BEQ); - store_helper(env, addr, val, oi, retaddr, MO_BEQ); + validate_memop(oi, MO_BEUQ); + store_helper(env, addr, val, oi, retaddr, MO_BEUQ); } /* @@ -2609,11 +2609,11 @@ uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr addr) static uint64_t full_ldq_code(CPUArchState *env, target_ulong addr, MemOpIdx oi, uintptr_t retaddr) { - return load_helper(env, addr, oi, retaddr, MO_TEQ, true, full_ldq_code); + return load_helper(env, addr, oi, retaddr, MO_TEUQ, true, full_ldq_code); } uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr addr) { - MemOpIdx oi = make_memop_idx(MO_TEQ, cpu_mmu_index(env, true)); + MemOpIdx oi = make_memop_idx(MO_TEUQ, cpu_mmu_index(env, true)); return full_ldq_code(env, addr, oi, 0); } diff --git a/accel/tcg/ldst_common.c.inc b/accel/tcg/ldst_common.c.inc index bfefb275e7..6ac8d871a3 100644 --- a/accel/tcg/ldst_common.c.inc +++ b/accel/tcg/ldst_common.c.inc @@ -45,7 +45,7 @@ uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, int mmu_idx, uintptr_t ra) { - MemOpIdx oi = make_memop_idx(MO_BEQ | MO_UNALN, mmu_idx); + MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx); return cpu_ldq_be_mmu(env, addr, oi, ra); } @@ -72,7 +72,7 @@ uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, int mmu_idx, uintptr_t ra) { - MemOpIdx oi = make_memop_idx(MO_LEQ | MO_UNALN, mmu_idx); + MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx); return cpu_ldq_le_mmu(env, addr, oi, ra); } @@ -100,7 +100,7 @@ void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val, int mmu_idx, uintptr_t ra) { - MemOpIdx oi = make_memop_idx(MO_BEQ | MO_UNALN, mmu_idx); + MemOpIdx oi = make_memop_idx(MO_BEUQ | MO_UNALN, mmu_idx); cpu_stq_be_mmu(env, addr, val, oi, ra); } @@ -121,7 +121,7 @@ void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val, void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val, int mmu_idx, uintptr_t ra) { - MemOpIdx oi = make_memop_idx(MO_LEQ | MO_UNALN, mmu_idx); + MemOpIdx oi = make_memop_idx(MO_LEUQ | MO_UNALN, mmu_idx); cpu_stq_le_mmu(env, addr, val, oi, ra); } diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index 1528a21fad..6f5d4933f0 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -294,7 +294,7 @@ uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr, void *haddr; uint64_t ret; - validate_memop(oi, MO_BEQ); + validate_memop(oi, MO_BEUQ); trace_guest_ld_before_exec(env_cpu(env), addr, oi); haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD); ret = ldq_be_p(haddr); @@ -339,7 +339,7 @@ uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr addr, void *haddr; uint64_t ret; - validate_memop(oi, MO_LEQ); + validate_memop(oi, MO_LEUQ); trace_guest_ld_before_exec(env_cpu(env), addr, oi); haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD); ret = ldq_le_p(haddr); @@ -392,7 +392,7 @@ void cpu_stq_be_mmu(CPUArchState *env, abi_ptr addr, uint64_t val, { void *haddr; - validate_memop(oi, MO_BEQ); + validate_memop(oi, MO_BEUQ); trace_guest_st_before_exec(env_cpu(env), addr, oi); haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE); stq_be_p(haddr, val); @@ -431,7 +431,7 @@ void cpu_stq_le_mmu(CPUArchState *env, abi_ptr addr, uint64_t val, { void *haddr; - validate_memop(oi, MO_LEQ); + validate_memop(oi, MO_LEUQ); trace_guest_st_before_exec(env_cpu(env), addr, oi); haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE); stq_le_p(haddr, val); diff --git a/include/exec/memop.h b/include/exec/memop.h index 04264ffd6b..72c2f0ff3d 100644 --- a/include/exec/memop.h +++ b/include/exec/memop.h @@ -85,29 +85,29 @@ typedef enum MemOp { MO_UB = MO_8, MO_UW = MO_16, MO_UL = MO_32, + MO_UQ = MO_64, MO_SB = MO_SIGN | MO_8, MO_SW = MO_SIGN | MO_16, MO_SL = MO_SIGN | MO_32, - MO_Q = MO_64, MO_LEUW = MO_LE | MO_UW, MO_LEUL = MO_LE | MO_UL, + MO_LEUQ = MO_LE | MO_UQ, MO_LESW = MO_LE | MO_SW, MO_LESL = MO_LE | MO_SL, - MO_LEQ = MO_LE | MO_Q, MO_BEUW = MO_BE | MO_UW, MO_BEUL = MO_BE | MO_UL, + MO_BEUQ = MO_BE | MO_UQ, MO_BESW = MO_BE | MO_SW, MO_BESL = MO_BE | MO_SL, - MO_BEQ = MO_BE | MO_Q, #ifdef NEED_CPU_H MO_TEUW = MO_TE | MO_UW, MO_TEUL = MO_TE | MO_UL, + MO_TEUQ = MO_TE | MO_UQ, MO_TESW = MO_TE | MO_SW, MO_TESL = MO_TE | MO_SL, - MO_TEQ = MO_TE | MO_Q, #endif MO_SSIZE = MO_SIZE | MO_SIGN, diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h index 0545a6224c..caa0a63612 100644 --- a/include/tcg/tcg-op.h +++ b/include/tcg/tcg-op.h @@ -894,7 +894,7 @@ static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, int mem_index) static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index) { - tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEQ); + tcg_gen_qemu_ld_i64(ret, addr, mem_index, MO_TEUQ); } static inline void tcg_gen_qemu_st8(TCGv arg, TCGv addr, int mem_index) @@ -914,7 +914,7 @@ static inline void tcg_gen_qemu_st32(TCGv arg, TCGv addr, int mem_index) static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) { - tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEQ); + tcg_gen_qemu_st_i64(arg, addr, mem_index, MO_TEUQ); } void tcg_gen_atomic_cmpxchg_i32(TCGv_i32, TCGv, TCGv_i32, TCGv_i32, diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 208ae5fbd5..ca78a0faed 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -286,7 +286,7 @@ static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr) static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr) { TCGv tmp = tcg_temp_new(); - tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx)); + tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx)); gen_helper_memory_to_g(dest, tmp); tcg_temp_free(tmp); } @@ -301,7 +301,7 @@ static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr) static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr) { - tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx)); + tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx)); } static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16, @@ -358,7 +358,7 @@ static void gen_stg(DisasContext *ctx, TCGv src, TCGv addr) { TCGv tmp = tcg_temp_new(); gen_helper_g_to_memory(tmp, src); - tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx)); + tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx)); tcg_temp_free(tmp); } @@ -372,7 +372,7 @@ static void gen_sts(DisasContext *ctx, TCGv src, TCGv addr) static void gen_stt(DisasContext *ctx, TCGv src, TCGv addr) { - tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx)); + tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx)); } static void gen_store_fp(DisasContext *ctx, int ra, int rb, int32_t disp16, @@ -1499,7 +1499,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) break; case 0x0B: /* LDQ_U */ - gen_load_int(ctx, ra, rb, disp16, MO_LEQ, 1, 0); + gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 1, 0); break; case 0x0C: /* LDWU */ @@ -1518,7 +1518,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) break; case 0x0F: /* STQ_U */ - gen_store_int(ctx, ra, rb, disp16, MO_LEQ, 1); + gen_store_int(ctx, ra, rb, disp16, MO_LEUQ, 1); break; case 0x10: @@ -2469,7 +2469,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) break; case 0x1: /* Quadword physical access (hw_ldq/p) */ - tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEQ); + tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ); break; case 0x2: /* Longword physical access with lock (hw_ldl_l/p) */ @@ -2479,7 +2479,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) break; case 0x3: /* Quadword physical access with lock (hw_ldq_l/p) */ - tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEQ); + tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ); tcg_gen_mov_i64(cpu_lock_addr, addr); tcg_gen_mov_i64(cpu_lock_value, va); break; @@ -2508,7 +2508,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) break; case 0xB: /* Quadword virtual access with protection check (hw_ldq/w) */ - tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LEQ); + tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX, MO_LEUQ); break; case 0xC: /* Longword virtual access with alt access mode (hw_ldl/a)*/ @@ -2524,7 +2524,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) case 0xF: /* Quadword virtual access with alternate access mode and protection checks (hw_ldq/wa) */ - tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LEQ); + tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX, MO_LEUQ); break; } tcg_temp_free(addr); @@ -2737,7 +2737,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) vb = load_gpr(ctx, rb); tmp = tcg_temp_new(); tcg_gen_addi_i64(tmp, vb, disp12); - tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEQ); + tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEUQ); tcg_temp_free(tmp); break; case 0x2: @@ -2748,7 +2748,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) case 0x3: /* Quadword physical access with lock */ ret = gen_store_conditional(ctx, ra, rb, disp12, - MMU_PHYS_IDX, MO_LEQ); + MMU_PHYS_IDX, MO_LEUQ); break; case 0x4: /* Longword virtual access */ @@ -2838,7 +2838,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) break; case 0x29: /* LDQ */ - gen_load_int(ctx, ra, rb, disp16, MO_LEQ, 0, 0); + gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 0, 0); break; case 0x2A: /* LDL_L */ @@ -2846,7 +2846,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) break; case 0x2B: /* LDQ_L */ - gen_load_int(ctx, ra, rb, disp16, MO_LEQ, 0, 1); + gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 0, 1); break; case 0x2C: /* STL */ @@ -2854,7 +2854,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) break; case 0x2D: /* STQ */ - gen_store_int(ctx, ra, rb, disp16, MO_LEQ, 0); + gen_store_int(ctx, ra, rb, disp16, MO_LEUQ, 0); break; case 0x2E: /* STL_C */ @@ -2864,7 +2864,7 @@ static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn) case 0x2F: /* STQ_C */ ret = gen_store_conditional(ctx, ra, rb, disp16, - ctx->mem_idx, MO_LEQ); + ctx->mem_idx, MO_LEUQ); break; case 0x30: /* BR */ diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c index 5ae2ecb0f3..d6a6fd73d9 100644 --- a/target/arm/helper-a64.c +++ b/target/arm/helper-a64.c @@ -513,8 +513,8 @@ uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr, uint64_t o0, o1; bool success; int mem_idx = cpu_mmu_index(env, false); - MemOpIdx oi0 = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx); - MemOpIdx oi1 = make_memop_idx(MO_LEQ, mem_idx); + MemOpIdx oi0 = make_memop_idx(MO_LEUQ | MO_ALIGN_16, mem_idx); + MemOpIdx oi1 = make_memop_idx(MO_LEUQ, mem_idx); o0 = cpu_ldq_le_mmu(env, addr + 0, oi0, ra); o1 = cpu_ldq_le_mmu(env, addr + 8, oi1, ra); @@ -565,8 +565,8 @@ uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr, uint64_t o0, o1; bool success; int mem_idx = cpu_mmu_index(env, false); - MemOpIdx oi0 = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx); - MemOpIdx oi1 = make_memop_idx(MO_BEQ, mem_idx); + MemOpIdx oi0 = make_memop_idx(MO_BEUQ | MO_ALIGN_16, mem_idx); + MemOpIdx oi1 = make_memop_idx(MO_BEUQ, mem_idx); o1 = cpu_ldq_be_mmu(env, addr + 0, oi0, ra); o0 = cpu_ldq_be_mmu(env, addr + 8, oi1, ra); diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h index 17af8dc95a..5be4b9b834 100644 --- a/target/arm/translate-a32.h +++ b/target/arm/translate-a32.h @@ -117,13 +117,13 @@ void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32, static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32, int index) { - gen_aa32_ld_i64(s, val, a32, index, MO_Q); + gen_aa32_ld_i64(s, val, a32, index, MO_UQ); } static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32, int index) { - gen_aa32_st_i64(s, val, a32, index, MO_Q); + gen_aa32_st_i64(s, val, a32, index, MO_UQ); } DO_GEN_LD(8u, MO_UB) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 130a9ff8d5..5a1df25f91 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -973,7 +973,7 @@ static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size) tcg_gen_ld_i64(tmphi, cpu_env, fp_reg_hi_offset(s, srcidx)); - mop = s->be_data | MO_Q; + mop = s->be_data | MO_UQ; tcg_gen_qemu_st_i64(be ? tmphi : tmplo, tcg_addr, get_mem_index(s), mop | (s->align_mem ? MO_ALIGN_16 : 0)); tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8); @@ -1007,7 +1007,7 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size) tmphi = tcg_temp_new_i64(); tcg_hiaddr = tcg_temp_new_i64(); - mop = s->be_data | MO_Q; + mop = s->be_data | MO_UQ; tcg_gen_qemu_ld_i64(be ? tmphi : tmplo, tcg_addr, get_mem_index(s), mop | (s->align_mem ? MO_ALIGN_16 : 0)); tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8); @@ -4099,10 +4099,10 @@ static void disas_ldst_tag(DisasContext *s, uint32_t insn) int i, n = (1 + is_pair) << LOG2_TAG_GRANULE; tcg_gen_qemu_st_i64(tcg_zero, clean_addr, mem_index, - MO_Q | MO_ALIGN_16); + MO_UQ | MO_ALIGN_16); for (i = 8; i < n; i += 8) { tcg_gen_addi_i64(clean_addr, clean_addr, 8); - tcg_gen_qemu_st_i64(tcg_zero, clean_addr, mem_index, MO_Q); + tcg_gen_qemu_st_i64(tcg_zero, clean_addr, mem_index, MO_UQ); } tcg_temp_free_i64(tcg_zero); } diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c index dd43de558e..3854dd3516 100644 --- a/target/arm/translate-neon.c +++ b/target/arm/translate-neon.c @@ -73,7 +73,7 @@ static void neon_load_element64(TCGv_i64 var, int reg, int ele, MemOp mop) case MO_UL: tcg_gen_ld32u_i64(var, cpu_env, offset); break; - case MO_Q: + case MO_UQ: tcg_gen_ld_i64(var, cpu_env, offset); break; default: @@ -1830,7 +1830,7 @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, return false; } - if ((a->vd & 1) || (src1_mop == MO_Q && (a->vn & 1))) { + if ((a->vd & 1) || (src1_mop == MO_UQ && (a->vn & 1))) { return false; } @@ -1910,7 +1910,7 @@ static bool do_prewiden_3d(DisasContext *s, arg_3diff *a, }; \ int narrow_mop = a->size == MO_32 ? MO_32 | SIGN : -1; \ return do_prewiden_3d(s, a, widenfn[a->size], addfn[a->size], \ - SRC1WIDE ? MO_Q : narrow_mop, \ + SRC1WIDE ? MO_UQ : narrow_mop, \ narrow_mop); \ } diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c index 76b5fe9f31..33ca1bcfac 100644 --- a/target/arm/translate-sve.c +++ b/target/arm/translate-sve.c @@ -5087,7 +5087,7 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm) t0 = tcg_temp_new_i64(); for (i = 0; i < len_align; i += 8) { - tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEQ); + tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ); tcg_gen_st_i64(t0, cpu_env, vofs + i); tcg_gen_addi_i64(clean_addr, clean_addr, 8); } @@ -5104,7 +5104,7 @@ static void do_ldr(DisasContext *s, uint32_t vofs, int len, int rn, int imm) gen_set_label(loop); t0 = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEQ); + tcg_gen_qemu_ld_i64(t0, clean_addr, midx, MO_LEUQ); tcg_gen_addi_i64(clean_addr, clean_addr, 8); tp = tcg_temp_new_ptr(); @@ -5177,7 +5177,7 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm) t0 = tcg_temp_new_i64(); for (i = 0; i < len_align; i += 8) { tcg_gen_ld_i64(t0, cpu_env, vofs + i); - tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEQ); + tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ); tcg_gen_addi_i64(clean_addr, clean_addr, 8); } tcg_temp_free_i64(t0); @@ -5199,7 +5199,7 @@ static void do_str(DisasContext *s, uint32_t vofs, int len, int rn, int imm) tcg_gen_addi_ptr(i, i, 8); tcg_temp_free_ptr(tp); - tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEQ); + tcg_gen_qemu_st_i64(t0, clean_addr, midx, MO_LEUQ); tcg_gen_addi_i64(clean_addr, clean_addr, 8); tcg_temp_free_i64(t0); @@ -5283,7 +5283,7 @@ static const MemOp dtype_mop[16] = { MO_UB, MO_UB, MO_UB, MO_UB, MO_SL, MO_UW, MO_UW, MO_UW, MO_SW, MO_SW, MO_UL, MO_UL, - MO_SB, MO_SB, MO_SB, MO_Q + MO_SB, MO_SB, MO_SB, MO_UQ }; #define dtype_msz(x) (dtype_mop[x] & MO_SIZE) diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c index 59bcaec5be..17f796e32a 100644 --- a/target/arm/translate-vfp.c +++ b/target/arm/translate-vfp.c @@ -1170,11 +1170,11 @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a) addr = add_reg_for_lit(s, a->rn, offset); tmp = tcg_temp_new_i64(); if (a->l) { - gen_aa32_ld_i64(s, tmp, addr, get_mem_index(s), MO_Q | MO_ALIGN_4); + gen_aa32_ld_i64(s, tmp, addr, get_mem_index(s), MO_UQ | MO_ALIGN_4); vfp_store_reg64(tmp, a->vd); } else { vfp_load_reg64(tmp, a->vd); - gen_aa32_st_i64(s, tmp, addr, get_mem_index(s), MO_Q | MO_ALIGN_4); + gen_aa32_st_i64(s, tmp, addr, get_mem_index(s), MO_UQ | MO_ALIGN_4); } tcg_temp_free_i64(tmp); tcg_temp_free_i32(addr); @@ -1322,12 +1322,12 @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a) for (i = 0; i < n; i++) { if (a->l) { /* load */ - gen_aa32_ld_i64(s, tmp, addr, get_mem_index(s), MO_Q | MO_ALIGN_4); + gen_aa32_ld_i64(s, tmp, addr, get_mem_index(s), MO_UQ | MO_ALIGN_4); vfp_store_reg64(tmp, a->vd + i); } else { /* store */ vfp_load_reg64(tmp, a->vd + i); - gen_aa32_st_i64(s, tmp, addr, get_mem_index(s), MO_Q | MO_ALIGN_4); + gen_aa32_st_i64(s, tmp, addr, get_mem_index(s), MO_UQ | MO_ALIGN_4); } tcg_gen_addi_i32(addr, addr, offset); } diff --git a/target/arm/translate.c b/target/arm/translate.c index 0a3840d227..bf2196b9e2 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1217,7 +1217,7 @@ void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop) case MO_UL: tcg_gen_ld32u_i64(dest, cpu_env, off); break; - case MO_Q: + case MO_UQ: tcg_gen_ld_i64(dest, cpu_env, off); break; default: diff --git a/target/cris/translate.c b/target/cris/translate.c index 59325b388a..3656cd6db1 100644 --- a/target/cris/translate.c +++ b/target/cris/translate.c @@ -1047,7 +1047,7 @@ static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr) cris_store_direct_jmp(dc); } - tcg_gen_qemu_ld_i64(dst, addr, mem_index, MO_TEQ); + tcg_gen_qemu_ld_i64(dst, addr, mem_index, MO_TEUQ); } static void gen_load(DisasContext *dc, TCGv dst, TCGv addr, diff --git a/target/hppa/translate.c b/target/hppa/translate.c index a2392a1b64..c6195590f8 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -1609,7 +1609,7 @@ static bool do_floadd(DisasContext *ctx, unsigned rt, unsigned rb, nullify_over(ctx); tmp = tcg_temp_new_i64(); - do_load_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ); + do_load_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUQ); save_frd(rt, tmp); tcg_temp_free_i64(tmp); @@ -1665,7 +1665,7 @@ static bool do_fstored(DisasContext *ctx, unsigned rt, unsigned rb, nullify_over(ctx); tmp = load_frd(rt); - do_store_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEQ); + do_store_64(ctx, tmp, rb, rx, scale, disp, sp, modify, MO_TEUQ); tcg_temp_free_i64(tmp); return nullify_end(ctx); diff --git a/target/i386/tcg/mem_helper.c b/target/i386/tcg/mem_helper.c index a207e624cb..e3cdafd2d4 100644 --- a/target/i386/tcg/mem_helper.c +++ b/target/i386/tcg/mem_helper.c @@ -67,7 +67,7 @@ void helper_cmpxchg8b(CPUX86State *env, target_ulong a0) { uintptr_t ra = GETPC(); int mem_idx = cpu_mmu_index(env, false); - MemOpIdx oi = make_memop_idx(MO_TEQ, mem_idx); + MemOpIdx oi = make_memop_idx(MO_TEUQ, mem_idx); oldv = cpu_atomic_cmpxchgq_le_mmu(env, a0, cmpv, newv, oi, ra); } diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 05f9336c9b..77878cd832 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2719,23 +2719,23 @@ static void gen_jmp(DisasContext *s, target_ulong eip) static inline void gen_ldq_env_A0(DisasContext *s, int offset) { - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ); tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset); } static inline void gen_stq_env_A0(DisasContext *s, int offset) { tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEQ); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ); } static inline void gen_ldo_env_A0(DisasContext *s, int offset) { int mem_index = s->mem_index; - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ); + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEUQ); tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0))); tcg_gen_addi_tl(s->tmp0, s->A0, 8); - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ); + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ); tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1))); } @@ -2743,10 +2743,10 @@ static inline void gen_sto_env_A0(DisasContext *s, int offset) { int mem_index = s->mem_index; tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0))); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, MO_LEQ); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, MO_LEUQ); tcg_gen_addi_tl(s->tmp0, s->A0, 8); tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1))); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEQ); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ); } static inline void gen_op_movo(DisasContext *s, int d_offset, int s_offset) @@ -4255,7 +4255,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_mov_i64(cpu_regs[rm], s->tmp1_i64); } else { tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); + s->mem_index, MO_LEUQ); } #else goto illegal_op; @@ -4328,7 +4328,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_op_mov_v_reg(s, ot, s->tmp1_i64, rm); } else { tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); + s->mem_index, MO_LEUQ); } tcg_gen_st_i64(s->tmp1_i64, cpu_env, offsetof(CPUX86State, @@ -5948,7 +5948,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; case 2: tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); + s->mem_index, MO_LEUQ); gen_helper_fldl_FT0(cpu_env, s->tmp1_i64); break; case 3: @@ -5987,7 +5987,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; case 2: tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); + s->mem_index, MO_LEUQ); gen_helper_fldl_ST0(cpu_env, s->tmp1_i64); break; case 3: @@ -6009,7 +6009,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 2: gen_helper_fisttll_ST0(s->tmp1_i64, cpu_env); tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); + s->mem_index, MO_LEUQ); break; case 3: default: @@ -6035,7 +6035,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) case 2: gen_helper_fstl_ST0(s->tmp1_i64, cpu_env); tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); + s->mem_index, MO_LEUQ); break; case 3: default: @@ -6104,13 +6104,13 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) break; case 0x3d: /* fildll */ tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); + s->mem_index, MO_LEUQ); gen_helper_fildll_ST0(cpu_env, s->tmp1_i64); break; case 0x3f: /* fistpll */ gen_helper_fistll_ST0(s->tmp1_i64, cpu_env); tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, - s->mem_index, MO_LEQ); + s->mem_index, MO_LEUQ); gen_helper_fpop(cpu_env); break; default: @@ -7932,10 +7932,10 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_lea_modrm(env, s, modrm); if (CODE64(s)) { tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0, - s->mem_index, MO_LEQ); + s->mem_index, MO_LEUQ); tcg_gen_addi_tl(s->A0, s->A0, 8); tcg_gen_qemu_ld_i64(cpu_bndu[reg], s->A0, - s->mem_index, MO_LEQ); + s->mem_index, MO_LEUQ); } else { tcg_gen_qemu_ld_i64(cpu_bndl[reg], s->A0, s->mem_index, MO_LEUL); @@ -8039,10 +8039,10 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) gen_lea_modrm(env, s, modrm); if (CODE64(s)) { tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0, - s->mem_index, MO_LEQ); + s->mem_index, MO_LEUQ); tcg_gen_addi_tl(s->A0, s->A0, 8); tcg_gen_qemu_st_i64(cpu_bndu[reg], s->A0, - s->mem_index, MO_LEQ); + s->mem_index, MO_LEUQ); } else { tcg_gen_qemu_st_i64(cpu_bndl[reg], s->A0, s->mem_index, MO_LEUL); diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index cfbc987ba6..c0f4825034 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -774,7 +774,7 @@ static void do_cas2l(CPUM68KState *env, uint32_t regs, uint32_t a1, uint32_t a2, uintptr_t ra = GETPC(); #if defined(CONFIG_ATOMIC64) int mmu_idx = cpu_mmu_index(env, 0); - MemOpIdx oi = make_memop_idx(MO_BEQ, mmu_idx); + MemOpIdx oi = make_memop_idx(MO_BEUQ, mmu_idx); #endif if (parallel) { diff --git a/target/mips/tcg/micromips_translate.c.inc b/target/mips/tcg/micromips_translate.c.inc index 0da4c802a3..0760941431 100644 --- a/target/mips/tcg/micromips_translate.c.inc +++ b/target/mips/tcg/micromips_translate.c.inc @@ -1001,20 +1001,20 @@ static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd, gen_reserved_instruction(ctx); return; } - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ); gen_store_gpr(t1, rd); tcg_gen_movi_tl(t1, 8); gen_op_addr_add(ctx, t0, t0, t1); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ); gen_store_gpr(t1, rd + 1); break; case SDP: gen_load_gpr(t1, rd); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ); tcg_gen_movi_tl(t1, 8); gen_op_addr_add(ctx, t0, t0, t1); gen_load_gpr(t1, rd + 1); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ); break; #endif } @@ -2578,7 +2578,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) case SCD: check_insn(ctx, ISA_MIPS3); check_mips_64(ctx); - gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false); + gen_st_cond(ctx, rt, rs, offset, MO_TEUQ, false); break; #endif case LD_EVA: diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 47db35d7dd..1c2264417c 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -2031,7 +2031,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, gen_store_gpr(t0, rt); break; case OPC_LD: - tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ | + tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); gen_store_gpr(t0, rt); break; @@ -2053,7 +2053,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, } tcg_gen_shli_tl(t1, t1, 3); tcg_gen_andi_tl(t0, t0, ~7); - tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ); + tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ); tcg_gen_shl_tl(t0, t0, t1); t2 = tcg_const_tl(-1); tcg_gen_shl_tl(t2, t2, t1); @@ -2077,7 +2077,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, } tcg_gen_shli_tl(t1, t1, 3); tcg_gen_andi_tl(t0, t0, ~7); - tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ); + tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ); tcg_gen_shr_tl(t0, t0, t1); tcg_gen_xori_tl(t1, t1, 63); t2 = tcg_const_tl(0xfffffffffffffffeull); @@ -2093,7 +2093,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, t1 = tcg_const_tl(pc_relative_pc(ctx)); gen_op_addr_add(ctx, t0, t0, t1); tcg_temp_free(t1); - tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ); + tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUQ); gen_store_gpr(t0, rt); break; #endif @@ -2224,7 +2224,7 @@ static void gen_st(DisasContext *ctx, uint32_t opc, int rt, switch (opc) { #if defined(TARGET_MIPS64) case OPC_SD: - tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ | + tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); break; case OPC_SDL: @@ -2334,7 +2334,7 @@ static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft, case OPC_LDC1: { TCGv_i64 fp0 = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); gen_store_fpr64(ctx, fp0, ft); tcg_temp_free_i64(fp0); @@ -2344,7 +2344,7 @@ static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft, { TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, ft); - tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); tcg_temp_free_i64(fp0); } @@ -3092,7 +3092,7 @@ static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc, check_mips_64(ctx); offset = sextract32(ctx->opcode << 3, 0, 21); addr = addr_add(ctx, (pc & ~0x7), offset); - gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ); + gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUQ); break; #endif default: @@ -4344,10 +4344,10 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt, case OPC_GSLQ: t1 = tcg_temp_new(); gen_base_offset_addr(ctx, t0, rs, lsq_offset); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); gen_store_gpr(t1, rt); gen_store_gpr(t0, lsq_rt1); @@ -4357,10 +4357,10 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt, check_cp1_enabled(ctx); t1 = tcg_temp_new(); gen_base_offset_addr(ctx, t0, rs, lsq_offset); - tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); gen_store_fpr64(ctx, t1, rt); gen_store_fpr64(ctx, t0, lsq_rt1); @@ -4370,11 +4370,11 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt, t1 = tcg_temp_new(); gen_base_offset_addr(ctx, t0, rs, lsq_offset); gen_load_gpr(t1, rt); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); gen_load_gpr(t1, lsq_rt1); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); tcg_temp_free(t1); break; @@ -4383,11 +4383,11 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt, t1 = tcg_temp_new(); gen_base_offset_addr(ctx, t0, rs, lsq_offset); gen_load_fpr64(ctx, t1, rt); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); gen_load_fpr64(ctx, t1, lsq_rt1); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); tcg_temp_free(t1); break; @@ -4467,7 +4467,7 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt, } tcg_gen_shli_tl(t1, t1, 3); tcg_gen_andi_tl(t0, t0, ~7); - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ); tcg_gen_shl_tl(t0, t0, t1); t2 = tcg_const_tl(-1); tcg_gen_shl_tl(t2, t2, t1); @@ -4489,7 +4489,7 @@ static void gen_loongson_lswc2(DisasContext *ctx, int rt, } tcg_gen_shli_tl(t1, t1, 3); tcg_gen_andi_tl(t0, t0, ~7); - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ); tcg_gen_shr_tl(t0, t0, t1); tcg_gen_xori_tl(t1, t1, 63); t2 = tcg_const_tl(0xfffffffffffffffeull); @@ -4642,7 +4642,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt, if (rd) { gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); } - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); gen_store_gpr(t0, rt); break; @@ -4664,7 +4664,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt, if (rd) { gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0); } - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); gen_store_fpr64(ctx, t0, rt); break; @@ -4693,7 +4693,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt, case OPC_GSSDX: t1 = tcg_temp_new(); gen_load_gpr(t1, rt); - tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); tcg_temp_free(t1); break; @@ -4709,7 +4709,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt, case OPC_GSSDXC1: t1 = tcg_temp_new(); gen_load_fpr64(ctx, t1, rt); - tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ | + tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEUQ | ctx->default_tcg_memop_mask); tcg_temp_free(t1); break; @@ -11330,7 +11330,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc, check_cp1_registers(ctx, fd); { TCGv_i64 fp0 = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEUQ); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -11341,7 +11341,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc, { TCGv_i64 fp0 = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEUQ); gen_store_fpr64(ctx, fp0, fd); tcg_temp_free_i64(fp0); } @@ -11361,7 +11361,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc, { TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEUQ); tcg_temp_free_i64(fp0); } break; @@ -11371,7 +11371,7 @@ static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc, { TCGv_i64 fp0 = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp0, fs); - tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEUQ); tcg_temp_free_i64(fp0); } break; @@ -12187,7 +12187,7 @@ static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc, break; #if defined(TARGET_MIPS64) case OPC_LDX: - tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUQ); gen_store_gpr(t0, rd); break; #endif @@ -14403,7 +14403,7 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx) #endif #if defined(TARGET_MIPS64) case R6_OPC_SCD: - gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false); + gen_st_cond(ctx, rt, rs, imm, MO_TEUQ, false); break; case R6_OPC_LLD: gen_ld(ctx, op1, rt, rs, imm); @@ -15843,7 +15843,7 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx) check_insn_opc_user_only(ctx, INSN_R5900); } check_mips_64(ctx); - gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false); + gen_st_cond(ctx, rt, rs, imm, MO_TEUQ, false); break; case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */ if (ctx->insn_flags & ISA_MIPS_R6) { diff --git a/target/mips/tcg/tx79_translate.c b/target/mips/tcg/tx79_translate.c index 6d51fe17c1..4e479c2d10 100644 --- a/target/mips/tcg/tx79_translate.c +++ b/target/mips/tcg/tx79_translate.c @@ -355,12 +355,12 @@ static bool trans_LQ(DisasContext *ctx, arg_i *a) tcg_gen_andi_tl(addr, addr, ~0xf); /* Lower half */ - tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ); gen_store_gpr(t0, a->rt); /* Upper half */ tcg_gen_addi_i64(addr, addr, 8); - tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_ld_i64(t0, addr, ctx->mem_idx, MO_TEUQ); gen_store_gpr_hi(t0, a->rt); tcg_temp_free(t0); @@ -383,12 +383,12 @@ static bool trans_SQ(DisasContext *ctx, arg_i *a) /* Lower half */ gen_load_gpr(t0, a->rt); - tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ); /* Upper half */ tcg_gen_addi_i64(addr, addr, 8); gen_load_gpr_hi(t0, a->rt); - tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_st_i64(t0, addr, ctx->mem_idx, MO_TEUQ); tcg_temp_free(addr); tcg_temp_free(t0); diff --git a/target/ppc/translate.c b/target/ppc/translate.c index cb8ab4d676..40232201bb 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -3277,10 +3277,10 @@ GEN_QEMU_LOAD_64(ld8u, DEF_MEMOP(MO_UB)) GEN_QEMU_LOAD_64(ld16u, DEF_MEMOP(MO_UW)) GEN_QEMU_LOAD_64(ld32u, DEF_MEMOP(MO_UL)) GEN_QEMU_LOAD_64(ld32s, DEF_MEMOP(MO_SL)) -GEN_QEMU_LOAD_64(ld64, DEF_MEMOP(MO_Q)) +GEN_QEMU_LOAD_64(ld64, DEF_MEMOP(MO_UQ)) #if defined(TARGET_PPC64) -GEN_QEMU_LOAD_64(ld64ur, BSWAP_MEMOP(MO_Q)) +GEN_QEMU_LOAD_64(ld64ur, BSWAP_MEMOP(MO_UQ)) #endif #define GEN_QEMU_STORE_TL(stop, op) \ @@ -3311,10 +3311,10 @@ static void glue(gen_qemu_, glue(stop, _i64))(DisasContext *ctx, \ GEN_QEMU_STORE_64(st8, DEF_MEMOP(MO_UB)) GEN_QEMU_STORE_64(st16, DEF_MEMOP(MO_UW)) GEN_QEMU_STORE_64(st32, DEF_MEMOP(MO_UL)) -GEN_QEMU_STORE_64(st64, DEF_MEMOP(MO_Q)) +GEN_QEMU_STORE_64(st64, DEF_MEMOP(MO_UQ)) #if defined(TARGET_PPC64) -GEN_QEMU_STORE_64(st64r, BSWAP_MEMOP(MO_Q)) +GEN_QEMU_STORE_64(st64r, BSWAP_MEMOP(MO_UQ)) #endif #define GEN_LDX_E(name, ldop, opc2, opc3, type, type2, chk) \ @@ -3351,7 +3351,7 @@ GEN_LDEPX(lb, DEF_MEMOP(MO_UB), 0x1F, 0x02) GEN_LDEPX(lh, DEF_MEMOP(MO_UW), 0x1F, 0x08) GEN_LDEPX(lw, DEF_MEMOP(MO_UL), 0x1F, 0x00) #if defined(TARGET_PPC64) -GEN_LDEPX(ld, DEF_MEMOP(MO_Q), 0x1D, 0x00) +GEN_LDEPX(ld, DEF_MEMOP(MO_UQ), 0x1D, 0x00) #endif #if defined(TARGET_PPC64) @@ -3397,7 +3397,7 @@ GEN_STEPX(stb, DEF_MEMOP(MO_UB), 0x1F, 0x06) GEN_STEPX(sth, DEF_MEMOP(MO_UW), 0x1F, 0x0C) GEN_STEPX(stw, DEF_MEMOP(MO_UL), 0x1F, 0x04) #if defined(TARGET_PPC64) -GEN_STEPX(std, DEF_MEMOP(MO_Q), 0x1d, 0x04) +GEN_STEPX(std, DEF_MEMOP(MO_UQ), 0x1d, 0x04) #endif #if defined(TARGET_PPC64) @@ -3807,7 +3807,7 @@ static void gen_lwat(DisasContext *ctx) #ifdef TARGET_PPC64 static void gen_ldat(DisasContext *ctx) { - gen_ld_atomic(ctx, DEF_MEMOP(MO_Q)); + gen_ld_atomic(ctx, DEF_MEMOP(MO_UQ)); } #endif @@ -3890,7 +3890,7 @@ static void gen_stwat(DisasContext *ctx) #ifdef TARGET_PPC64 static void gen_stdat(DisasContext *ctx) { - gen_st_atomic(ctx, DEF_MEMOP(MO_Q)); + gen_st_atomic(ctx, DEF_MEMOP(MO_UQ)); } #endif @@ -3942,9 +3942,9 @@ STCX(stwcx_, DEF_MEMOP(MO_UL)) #if defined(TARGET_PPC64) /* ldarx */ -LARX(ldarx, DEF_MEMOP(MO_Q)) +LARX(ldarx, DEF_MEMOP(MO_UQ)) /* stdcx. */ -STCX(stdcx_, DEF_MEMOP(MO_Q)) +STCX(stdcx_, DEF_MEMOP(MO_UQ)) /* lqarx */ static void gen_lqarx(DisasContext *ctx) @@ -3988,15 +3988,15 @@ static void gen_lqarx(DisasContext *ctx) return; } } else if (ctx->le_mode) { - tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEQ | MO_ALIGN_16); + tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEUQ | MO_ALIGN_16); tcg_gen_mov_tl(cpu_reserve, EA); gen_addr_add(ctx, EA, EA, 8); - tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_LEQ); + tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_LEUQ); } else { - tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_BEQ | MO_ALIGN_16); + tcg_gen_qemu_ld_i64(hi, EA, ctx->mem_idx, MO_BEUQ | MO_ALIGN_16); tcg_gen_mov_tl(cpu_reserve, EA); gen_addr_add(ctx, EA, EA, 8); - tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_BEUQ); } tcg_temp_free(EA); @@ -8018,7 +8018,7 @@ GEN_LDEPX(lb, DEF_MEMOP(MO_UB), 0x1F, 0x02) GEN_LDEPX(lh, DEF_MEMOP(MO_UW), 0x1F, 0x08) GEN_LDEPX(lw, DEF_MEMOP(MO_UL), 0x1F, 0x00) #if defined(TARGET_PPC64) -GEN_LDEPX(ld, DEF_MEMOP(MO_Q), 0x1D, 0x00) +GEN_LDEPX(ld, DEF_MEMOP(MO_UQ), 0x1D, 0x00) #endif #undef GEN_STX_E @@ -8044,7 +8044,7 @@ GEN_STEPX(stb, DEF_MEMOP(MO_UB), 0x1F, 0x06) GEN_STEPX(sth, DEF_MEMOP(MO_UW), 0x1F, 0x0C) GEN_STEPX(stw, DEF_MEMOP(MO_UL), 0x1F, 0x04) #if defined(TARGET_PPC64) -GEN_STEPX(std, DEF_MEMOP(MO_Q), 0x1D, 0x04) +GEN_STEPX(std, DEF_MEMOP(MO_UQ), 0x1D, 0x04) #endif #undef GEN_CRLOGIC diff --git a/target/ppc/translate/fixedpoint-impl.c.inc b/target/ppc/translate/fixedpoint-impl.c.inc index 7fecff4579..1aab32be03 100644 --- a/target/ppc/translate/fixedpoint-impl.c.inc +++ b/target/ppc/translate/fixedpoint-impl.c.inc @@ -137,7 +137,7 @@ static bool do_ldst_quad(DisasContext *ctx, arg_D *a, bool store, bool prefixed) ctx->base.is_jmp = DISAS_NORETURN; } } else { - mop = DEF_MEMOP(MO_Q); + mop = DEF_MEMOP(MO_UQ); if (store) { tcg_gen_qemu_st_i64(low_addr_gpr, ea, ctx->mem_idx, mop); } else { @@ -205,11 +205,11 @@ TRANS64(LWAUX, do_ldst_X, true, false, MO_SL) TRANS64(PLWA, do_ldst_PLS_D, false, false, MO_SL) /* Load Doubleword */ -TRANS64(LD, do_ldst_D, false, false, MO_Q) -TRANS64(LDX, do_ldst_X, false, false, MO_Q) -TRANS64(LDU, do_ldst_D, true, false, MO_Q) -TRANS64(LDUX, do_ldst_X, true, false, MO_Q) -TRANS64(PLD, do_ldst_PLS_D, false, false, MO_Q) +TRANS64(LD, do_ldst_D, false, false, MO_UQ) +TRANS64(LDX, do_ldst_X, false, false, MO_UQ) +TRANS64(LDU, do_ldst_D, true, false, MO_UQ) +TRANS64(LDUX, do_ldst_X, true, false, MO_UQ) +TRANS64(PLD, do_ldst_PLS_D, false, false, MO_UQ) /* Load Quadword */ TRANS64(LQ, do_ldst_quad, false, false); @@ -237,11 +237,11 @@ TRANS(STWUX, do_ldst_X, true, true, MO_UL) TRANS(PSTW, do_ldst_PLS_D, false, true, MO_UL) /* Store Doubleword */ -TRANS64(STD, do_ldst_D, false, true, MO_Q) -TRANS64(STDX, do_ldst_X, false, true, MO_Q) -TRANS64(STDU, do_ldst_D, true, true, MO_Q) -TRANS64(STDUX, do_ldst_X, true, true, MO_Q) -TRANS64(PSTD, do_ldst_PLS_D, false, true, MO_Q) +TRANS64(STD, do_ldst_D, false, true, MO_UQ) +TRANS64(STDX, do_ldst_X, false, true, MO_UQ) +TRANS64(STDU, do_ldst_D, true, true, MO_UQ) +TRANS64(STDUX, do_ldst_X, true, true, MO_UQ) +TRANS64(PSTD, do_ldst_PLS_D, false, true, MO_UQ) /* Store Quadword */ TRANS64(STQ, do_ldst_quad, true, false); diff --git a/target/ppc/translate/fp-impl.c.inc b/target/ppc/translate/fp-impl.c.inc index 2baae5988f..c96769742e 100644 --- a/target/ppc/translate/fp-impl.c.inc +++ b/target/ppc/translate/fp-impl.c.inc @@ -863,7 +863,7 @@ static void gen_lfdepx(DisasContext *ctx) EA = tcg_temp_new(); t0 = tcg_temp_new_i64(); gen_addr_reg_index(ctx, EA); - tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_Q)); + tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UQ)); set_fpr(rD(ctx->opcode), t0); tcg_temp_free(EA); tcg_temp_free_i64(t0); @@ -1021,7 +1021,7 @@ static void gen_stfdepx(DisasContext *ctx) t0 = tcg_temp_new_i64(); gen_addr_reg_index(ctx, EA); get_fpr(t0, rD(ctx->opcode)); - tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_Q)); + tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_UQ)); tcg_temp_free(EA); tcg_temp_free_i64(t0); } diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc index c08185e857..c636e38164 100644 --- a/target/ppc/translate/vsx-impl.c.inc +++ b/target/ppc/translate/vsx-impl.c.inc @@ -85,19 +85,19 @@ static void gen_lxvw4x(DisasContext *ctx) TCGv_i64 t0 = tcg_temp_new_i64(); TCGv_i64 t1 = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEQ); + tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEUQ); tcg_gen_shri_i64(t1, t0, 32); tcg_gen_deposit_i64(xth, t1, t0, 32, 32); tcg_gen_addi_tl(EA, EA, 8); - tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEQ); + tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEUQ); tcg_gen_shri_i64(t1, t0, 32); tcg_gen_deposit_i64(xtl, t1, t0, 32, 32); tcg_temp_free_i64(t0); tcg_temp_free_i64(t1); } else { - tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ); tcg_gen_addi_tl(EA, EA, 8); - tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ); } set_cpu_vsr(xT(ctx->opcode), xth, true); set_cpu_vsr(xT(ctx->opcode), xtl, false); @@ -152,8 +152,8 @@ static void gen_lxvdsx(DisasContext *ctx) gen_addr_reg_index(ctx, EA); data = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, DEF_MEMOP(MO_Q)); - tcg_gen_gvec_dup_i64(MO_Q, vsr_full_offset(xT(ctx->opcode)), 16, 16, data); + tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, DEF_MEMOP(MO_UQ)); + tcg_gen_gvec_dup_i64(MO_UQ, vsr_full_offset(xT(ctx->opcode)), 16, 16, data); tcg_temp_free(EA); tcg_temp_free_i64(data); @@ -217,9 +217,9 @@ static void gen_lxvh8x(DisasContext *ctx) EA = tcg_temp_new(); gen_addr_reg_index(ctx, EA); - tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ); tcg_gen_addi_tl(EA, EA, 8); - tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ); if (ctx->le_mode) { gen_bswap16x8(xth, xtl, xth, xtl); } @@ -245,9 +245,9 @@ static void gen_lxvb16x(DisasContext *ctx) gen_set_access_type(ctx, ACCESS_INT); EA = tcg_temp_new(); gen_addr_reg_index(ctx, EA); - tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ); tcg_gen_addi_tl(EA, EA, 8); - tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ); set_cpu_vsr(xT(ctx->opcode), xth, true); set_cpu_vsr(xT(ctx->opcode), xtl, false); tcg_temp_free(EA); @@ -382,17 +382,17 @@ static void gen_stxvw4x(DisasContext *ctx) tcg_gen_shri_i64(t0, xsh, 32); tcg_gen_deposit_i64(t1, t0, xsh, 32, 32); - tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEQ); + tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEUQ); tcg_gen_addi_tl(EA, EA, 8); tcg_gen_shri_i64(t0, xsl, 32); tcg_gen_deposit_i64(t1, t0, xsl, 32, 32); - tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEQ); + tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEUQ); tcg_temp_free_i64(t0); tcg_temp_free_i64(t1); } else { - tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ); tcg_gen_addi_tl(EA, EA, 8); - tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ); } tcg_temp_free(EA); tcg_temp_free_i64(xsh); @@ -421,15 +421,15 @@ static void gen_stxvh8x(DisasContext *ctx) TCGv_i64 outl = tcg_temp_new_i64(); gen_bswap16x8(outh, outl, xsh, xsl); - tcg_gen_qemu_st_i64(outh, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_st_i64(outh, EA, ctx->mem_idx, MO_BEUQ); tcg_gen_addi_tl(EA, EA, 8); - tcg_gen_qemu_st_i64(outl, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_st_i64(outl, EA, ctx->mem_idx, MO_BEUQ); tcg_temp_free_i64(outh); tcg_temp_free_i64(outl); } else { - tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ); tcg_gen_addi_tl(EA, EA, 8); - tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ); } tcg_temp_free(EA); tcg_temp_free_i64(xsh); @@ -453,9 +453,9 @@ static void gen_stxvb16x(DisasContext *ctx) gen_set_access_type(ctx, ACCESS_INT); EA = tcg_temp_new(); gen_addr_reg_index(ctx, EA); - tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ); tcg_gen_addi_tl(EA, EA, 8); - tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ); + tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ); tcg_temp_free(EA); tcg_temp_free_i64(xsh); tcg_temp_free_i64(xsl); @@ -2020,7 +2020,7 @@ static bool do_lstxv(DisasContext *ctx, int ra, TCGv displ, xt = tcg_temp_new_i64(); - mop = DEF_MEMOP(MO_Q); + mop = DEF_MEMOP(MO_UQ); gen_set_access_type(ctx, ACCESS_INT); ea = do_ea_calc(ctx, ra, displ); diff --git a/target/riscv/insn_trans/trans_rva.c.inc b/target/riscv/insn_trans/trans_rva.c.inc index 40fe132b04..86032fa9a7 100644 --- a/target/riscv/insn_trans/trans_rva.c.inc +++ b/target/riscv/insn_trans/trans_rva.c.inc @@ -162,65 +162,65 @@ static bool trans_amomaxu_w(DisasContext *ctx, arg_amomaxu_w *a) static bool trans_lr_d(DisasContext *ctx, arg_lr_d *a) { REQUIRE_64BIT(ctx); - return gen_lr(ctx, a, MO_ALIGN | MO_TEQ); + return gen_lr(ctx, a, MO_ALIGN | MO_TEUQ); } static bool trans_sc_d(DisasContext *ctx, arg_sc_d *a) { REQUIRE_64BIT(ctx); - return gen_sc(ctx, a, (MO_ALIGN | MO_TEQ)); + return gen_sc(ctx, a, (MO_ALIGN | MO_TEUQ)); } static bool trans_amoswap_d(DisasContext *ctx, arg_amoswap_d *a) { REQUIRE_64BIT(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, (MO_ALIGN | MO_TEQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, (MO_ALIGN | MO_TEUQ)); } static bool trans_amoadd_d(DisasContext *ctx, arg_amoadd_d *a) { REQUIRE_64BIT(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TEQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TEUQ)); } static bool trans_amoxor_d(DisasContext *ctx, arg_amoxor_d *a) { REQUIRE_64BIT(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TEQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TEUQ)); } static bool trans_amoand_d(DisasContext *ctx, arg_amoand_d *a) { REQUIRE_64BIT(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TEQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TEUQ)); } static bool trans_amoor_d(DisasContext *ctx, arg_amoor_d *a) { REQUIRE_64BIT(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TEQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TEUQ)); } static bool trans_amomin_d(DisasContext *ctx, arg_amomin_d *a) { REQUIRE_64BIT(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, (MO_ALIGN | MO_TEQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, (MO_ALIGN | MO_TEUQ)); } static bool trans_amomax_d(DisasContext *ctx, arg_amomax_d *a) { REQUIRE_64BIT(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, (MO_ALIGN | MO_TEQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, (MO_ALIGN | MO_TEUQ)); } static bool trans_amominu_d(DisasContext *ctx, arg_amominu_d *a) { REQUIRE_64BIT(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, (MO_ALIGN | MO_TEQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, (MO_ALIGN | MO_TEUQ)); } static bool trans_amomaxu_d(DisasContext *ctx, arg_amomaxu_d *a) { REQUIRE_64BIT(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, (MO_ALIGN | MO_TEQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, (MO_ALIGN | MO_TEUQ)); } diff --git a/target/riscv/insn_trans/trans_rvd.c.inc b/target/riscv/insn_trans/trans_rvd.c.inc index 64fb0046f7..ed444b042a 100644 --- a/target/riscv/insn_trans/trans_rvd.c.inc +++ b/target/riscv/insn_trans/trans_rvd.c.inc @@ -33,7 +33,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) } addr = gen_pm_adjust_address(ctx, addr); - tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEUQ); mark_fs_dirty(ctx); return true; @@ -54,7 +54,7 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a) } addr = gen_pm_adjust_address(ctx, addr); - tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEQ); + tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUQ); return true; } diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/insn_trans/trans_rvh.c.inc index ecbf77ff9c..cebcb3f8f6 100644 --- a/target/riscv/insn_trans/trans_rvh.c.inc +++ b/target/riscv/insn_trans/trans_rvh.c.inc @@ -121,14 +121,14 @@ static bool trans_hlv_d(DisasContext *ctx, arg_hlv_d *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVH); - return do_hlv(ctx, a, MO_TEQ); + return do_hlv(ctx, a, MO_TEUQ); } static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVH); - return do_hsv(ctx, a, MO_TEQ); + return do_hsv(ctx, a, MO_TEUQ); } #ifndef CONFIG_USER_ONLY diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index e51dbc41c5..4a2aefe3a5 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -216,13 +216,13 @@ static bool trans_lwu(DisasContext *ctx, arg_lwu *a) static bool trans_ld(DisasContext *ctx, arg_ld *a) { REQUIRE_64BIT(ctx); - return gen_load(ctx, a, MO_TEQ); + return gen_load(ctx, a, MO_TEUQ); } static bool trans_sd(DisasContext *ctx, arg_sd *a) { REQUIRE_64BIT(ctx); - return gen_store(ctx, a, MO_TEQ); + return gen_store(ctx, a, MO_TEUQ); } static bool trans_addi(DisasContext *ctx, arg_addi *a) diff --git a/target/s390x/tcg/insn-data.def b/target/s390x/tcg/insn-data.def index 3e5594210c..f0af458aee 100644 --- a/target/s390x/tcg/insn-data.def +++ b/target/s390x/tcg/insn-data.def @@ -45,7 +45,7 @@ D(0xeb6a, ASI, SIY, GIE, la1, i2, new, 0, asi, adds32, MO_TESL) C(0xecd8, AHIK, RIE_d, DO, r3, i2, new, r1_32, add, adds32) C(0xc208, AGFI, RIL_a, EI, r1, i2, r1, 0, add, adds64) - D(0xeb7a, AGSI, SIY, GIE, la1, i2, new, 0, asi, adds64, MO_TEQ) + D(0xeb7a, AGSI, SIY, GIE, la1, i2, new, 0, asi, adds64, MO_TEUQ) C(0xecd9, AGHIK, RIE_d, DO, r3, i2, r1, 0, add, adds64) /* ADD IMMEDIATE HIGH */ C(0xcc08, AIH, RIL_a, HW, r1_sr32, i2, new, r1_32h, add, adds32) @@ -76,7 +76,7 @@ /* ADD LOGICAL WITH SIGNED IMMEDIATE */ D(0xeb6e, ALSI, SIY, GIE, la1, i2_32u, new, 0, asi, addu32, MO_TEUL) C(0xecda, ALHSIK, RIE_d, DO, r3_32u, i2_32u, new, r1_32, add, addu32) - D(0xeb7e, ALGSI, SIY, GIE, la1, i2, new, 0, asiu64, addu64, MO_TEQ) + D(0xeb7e, ALGSI, SIY, GIE, la1, i2, new, 0, asiu64, addu64, MO_TEUQ) C(0xecdb, ALGHSIK, RIE_d, DO, r3, i2, r1, 0, addu64, addu64) /* ADD LOGICAL WITH SIGNED IMMEDIATE HIGH */ C(0xcc0a, ALSIH, RIL_a, HW, r1_sr32, i2_32u, new, r1_32h, add, addu32) @@ -269,10 +269,10 @@ /* COMPARE AND SWAP */ D(0xba00, CS, RS_a, Z, r3_32u, r1_32u, new, r1_32, cs, 0, MO_TEUL) D(0xeb14, CSY, RSY_a, LD, r3_32u, r1_32u, new, r1_32, cs, 0, MO_TEUL) - D(0xeb30, CSG, RSY_a, Z, r3_o, r1_o, new, r1, cs, 0, MO_TEQ) + D(0xeb30, CSG, RSY_a, Z, r3_o, r1_o, new, r1, cs, 0, MO_TEUQ) /* COMPARE DOUBLE AND SWAP */ - D(0xbb00, CDS, RS_a, Z, r3_D32, r1_D32, new, r1_D32, cs, 0, MO_TEQ) - D(0xeb31, CDSY, RSY_a, LD, r3_D32, r1_D32, new, r1_D32, cs, 0, MO_TEQ) + D(0xbb00, CDS, RS_a, Z, r3_D32, r1_D32, new, r1_D32, cs, 0, MO_TEUQ) + D(0xeb31, CDSY, RSY_a, LD, r3_D32, r1_D32, new, r1_D32, cs, 0, MO_TEUQ) C(0xeb3e, CDSG, RSY_a, Z, 0, 0, 0, 0, cdsg, 0) /* COMPARE AND SWAP AND STORE */ C(0xc802, CSST, SSF, CASS, la1, a2, 0, 0, csst, 0) @@ -436,19 +436,19 @@ C(0xc000, LARL, RIL_b, Z, 0, ri2, 0, r1, mov2, 0) /* LOAD AND ADD */ D(0xebf8, LAA, RSY_a, ILA, r3_32s, a2, new, in2_r1_32, laa, adds32, MO_TESL) - D(0xebe8, LAAG, RSY_a, ILA, r3, a2, new, in2_r1, laa, adds64, MO_TEQ) + D(0xebe8, LAAG, RSY_a, ILA, r3, a2, new, in2_r1, laa, adds64, MO_TEUQ) /* LOAD AND ADD LOGICAL */ D(0xebfa, LAAL, RSY_a, ILA, r3_32u, a2, new, in2_r1_32, laa, addu32, MO_TEUL) - D(0xebea, LAALG, RSY_a, ILA, r3, a2, new, in2_r1, laa, addu64, MO_TEQ) + D(0xebea, LAALG, RSY_a, ILA, r3, a2, new, in2_r1, laa, addu64, MO_TEUQ) /* LOAD AND AND */ D(0xebf4, LAN, RSY_a, ILA, r3_32s, a2, new, in2_r1_32, lan, nz32, MO_TESL) - D(0xebe4, LANG, RSY_a, ILA, r3, a2, new, in2_r1, lan, nz64, MO_TEQ) + D(0xebe4, LANG, RSY_a, ILA, r3, a2, new, in2_r1, lan, nz64, MO_TEUQ) /* LOAD AND EXCLUSIVE OR */ D(0xebf7, LAX, RSY_a, ILA, r3_32s, a2, new, in2_r1_32, lax, nz32, MO_TESL) - D(0xebe7, LAXG, RSY_a, ILA, r3, a2, new, in2_r1, lax, nz64, MO_TEQ) + D(0xebe7, LAXG, RSY_a, ILA, r3, a2, new, in2_r1, lax, nz64, MO_TEUQ) /* LOAD AND OR */ D(0xebf6, LAO, RSY_a, ILA, r3_32s, a2, new, in2_r1_32, lao, nz32, MO_TESL) - D(0xebe6, LAOG, RSY_a, ILA, r3, a2, new, in2_r1, lao, nz64, MO_TEQ) + D(0xebe6, LAOG, RSY_a, ILA, r3, a2, new, in2_r1, lao, nz64, MO_TEUQ) /* LOAD AND TEST */ C(0x1200, LTR, RR_a, Z, 0, r2_o, 0, cond_r1r2_32, mov2, s32) C(0xb902, LTGR, RRE, Z, 0, r2_o, 0, r1, mov2, s64) @@ -565,7 +565,7 @@ C(0xebe0, LOCFH, RSY_b, LOC2, r1_sr32, m2_32u, new, r1_32h, loc, 0) /* LOAD PAIR DISJOINT */ D(0xc804, LPD, SSF, ILA, 0, 0, new_P, r3_P32, lpd, 0, MO_TEUL) - D(0xc805, LPDG, SSF, ILA, 0, 0, new_P, r3_P64, lpd, 0, MO_TEQ) + D(0xc805, LPDG, SSF, ILA, 0, 0, new_P, r3_P64, lpd, 0, MO_TEUQ) /* LOAD PAIR FROM QUADWORD */ C(0xe38f, LPQ, RXY_a, Z, 0, a2, r1_P, 0, lpq, 0) /* LOAD POSITIVE */ @@ -1279,7 +1279,7 @@ #ifndef CONFIG_USER_ONLY /* COMPARE AND SWAP AND PURGE */ E(0xb250, CSP, RRE, Z, r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL, IF_PRIV) - E(0xb98a, CSPG, RRE, DAT_ENH, r1_o, ra2, r1_P, 0, csp, 0, MO_TEQ, IF_PRIV) + E(0xb98a, CSPG, RRE, DAT_ENH, r1_o, ra2, r1_P, 0, csp, 0, MO_TEUQ, IF_PRIV) /* DIAGNOSE (KVM hypercall) */ F(0x8300, DIAG, RSI, Z, 0, 0, 0, 0, diag, 0, IF_PRIV | IF_IO) /* INSERT STORAGE KEY EXTENDED */ @@ -1303,7 +1303,7 @@ F(0xe303, LRAG, RXY_a, Z, 0, a2, r1, 0, lra, 0, IF_PRIV) /* LOAD USING REAL ADDRESS */ E(0xb24b, LURA, RRE, Z, 0, ra2, new, r1_32, lura, 0, MO_TEUL, IF_PRIV) - E(0xb905, LURAG, RRE, Z, 0, ra2, r1, 0, lura, 0, MO_TEQ, IF_PRIV) + E(0xb905, LURAG, RRE, Z, 0, ra2, r1, 0, lura, 0, MO_TEUQ, IF_PRIV) /* MOVE TO PRIMARY */ F(0xda00, MVCP, SS_d, Z, la1, a2, 0, 0, mvcp, 0, IF_PRIV) /* MOVE TO SECONDARY */ @@ -1357,7 +1357,7 @@ F(0xad00, STOSM, SI, Z, la1, 0, 0, 0, stnosm, 0, IF_PRIV) /* STORE USING REAL ADDRESS */ E(0xb246, STURA, RRE, Z, r1_o, ra2, 0, 0, stura, 0, MO_TEUL, IF_PRIV) - E(0xb925, STURG, RRE, Z, r1_o, ra2, 0, 0, stura, 0, MO_TEQ, IF_PRIV) + E(0xb925, STURG, RRE, Z, r1_o, ra2, 0, 0, stura, 0, MO_TEUQ, IF_PRIV) /* TEST BLOCK */ F(0xb22c, TB, RRE, Z, 0, r2_o, 0, 0, testblock, 0, IF_PRIV) /* TEST PROTECTION */ diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index 362a30d99e..406578d105 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -1895,7 +1895,7 @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1, if (parallel) { #ifdef CONFIG_ATOMIC64 - MemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN, mem_idx); + MemOpIdx oi = make_memop_idx(MO_TEUQ | MO_ALIGN, mem_idx); ov = cpu_atomic_cmpxchgq_be_mmu(env, a1, cv, nv, oi, ra); #else /* Note that we asserted !parallel above. */ @@ -1970,7 +1970,7 @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1, cpu_stq_data_ra(env, a2 + 0, svh, ra); cpu_stq_data_ra(env, a2 + 8, svl, ra); } else if (HAVE_ATOMIC128) { - MemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx); + MemOpIdx oi = make_memop_idx(MO_TEUQ | MO_ALIGN_16, mem_idx); Int128 sv = int128_make128(svl, svh); cpu_atomic_sto_be_mmu(env, a2, sv, oi, ra); } else { @@ -2494,7 +2494,7 @@ uint64_t HELPER(lpq_parallel)(CPUS390XState *env, uint64_t addr) assert(HAVE_ATOMIC128); mem_idx = cpu_mmu_index(env, false); - oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx); + oi = make_memop_idx(MO_TEUQ | MO_ALIGN_16, mem_idx); v = cpu_atomic_ldo_be_mmu(env, addr, oi, ra); hi = int128_gethi(v); lo = int128_getlo(v); @@ -2525,7 +2525,7 @@ void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr, assert(HAVE_ATOMIC128); mem_idx = cpu_mmu_index(env, false); - oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx); + oi = make_memop_idx(MO_TEUQ | MO_ALIGN_16, mem_idx); v = int128_make128(low, high); cpu_atomic_sto_be_mmu(env, addr, v, oi, ra); } diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index dcc249a197..f180853e7a 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -3063,7 +3063,7 @@ static DisasJumpType op_lpswe(DisasContext *s, DisasOps *o) t1 = tcg_temp_new_i64(); t2 = tcg_temp_new_i64(); tcg_gen_qemu_ld_i64(t1, o->in2, get_mem_index(s), - MO_TEQ | MO_ALIGN_8); + MO_TEUQ | MO_ALIGN_8); tcg_gen_addi_i64(o->in2, o->in2, 8); tcg_gen_qemu_ld64(t2, o->in2, get_mem_index(s)); gen_helper_load_psw(cpu_env, t1, t2); @@ -4295,7 +4295,7 @@ static DisasJumpType op_stcke(DisasContext *s, DisasOps *o) #ifndef CONFIG_USER_ONLY static DisasJumpType op_sck(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEQ | MO_ALIGN); + tcg_gen_qemu_ld_i64(o->in1, o->addr1, get_mem_index(s), MO_TEUQ | MO_ALIGN); gen_helper_sck(cc_op, cpu_env, o->in1); set_cc_static(s); return DISAS_NEXT; @@ -5521,7 +5521,7 @@ static void wout_m1_64(DisasContext *s, DisasOps *o) #ifndef CONFIG_USER_ONLY static void wout_m1_64a(DisasContext *s, DisasOps *o) { - tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEQ | MO_ALIGN); + tcg_gen_qemu_st_i64(o->out, o->addr1, get_mem_index(s), MO_TEUQ | MO_ALIGN); } #define SPEC_wout_m1_64a 0 #endif @@ -5997,7 +5997,7 @@ static void in2_m2_64w(DisasContext *s, DisasOps *o) static void in2_m2_64a(DisasContext *s, DisasOps *o) { in2_a2(s, o); - tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEQ | MO_ALIGN); + tcg_gen_qemu_ld_i64(o->in2, o->in2, get_mem_index(s), MO_TEUQ | MO_ALIGN); } #define SPEC_in2_m2_64a 0 #endif diff --git a/target/s390x/tcg/translate_vx.c.inc b/target/s390x/tcg/translate_vx.c.inc index 28bf5a23b6..98eb7710a4 100644 --- a/target/s390x/tcg/translate_vx.c.inc +++ b/target/s390x/tcg/translate_vx.c.inc @@ -424,9 +424,9 @@ static DisasJumpType op_vl(DisasContext *s, DisasOps *o) TCGv_i64 t0 = tcg_temp_new_i64(); TCGv_i64 t1 = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(t0, o->addr1, get_mem_index(s), MO_TEQ); + tcg_gen_qemu_ld_i64(t0, o->addr1, get_mem_index(s), MO_TEUQ); gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8); - tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEQ); + tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEUQ); write_vec_element_i64(t0, get_field(s, v1), 0, ES_64); write_vec_element_i64(t1, get_field(s, v1), 1, ES_64); tcg_temp_free(t0); @@ -592,16 +592,16 @@ static DisasJumpType op_vlm(DisasContext *s, DisasOps *o) t0 = tcg_temp_new_i64(); t1 = tcg_temp_new_i64(); gen_addi_and_wrap_i64(s, t0, o->addr1, (v3 - v1) * 16 + 8); - tcg_gen_qemu_ld_i64(t0, t0, get_mem_index(s), MO_TEQ); + tcg_gen_qemu_ld_i64(t0, t0, get_mem_index(s), MO_TEUQ); for (;; v1++) { - tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEQ); + tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEUQ); write_vec_element_i64(t1, v1, 0, ES_64); if (v1 == v3) { break; } gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8); - tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEQ); + tcg_gen_qemu_ld_i64(t1, o->addr1, get_mem_index(s), MO_TEUQ); write_vec_element_i64(t1, v1, 1, ES_64); gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8); } @@ -950,10 +950,10 @@ static DisasJumpType op_vst(DisasContext *s, DisasOps *o) gen_helper_probe_write_access(cpu_env, o->addr1, tmp); read_vec_element_i64(tmp, get_field(s, v1), 0, ES_64); - tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEQ); + tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEUQ); gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8); read_vec_element_i64(tmp, get_field(s, v1), 1, ES_64); - tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEQ); + tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEUQ); tcg_temp_free_i64(tmp); return DISAS_NEXT; } @@ -993,10 +993,10 @@ static DisasJumpType op_vstm(DisasContext *s, DisasOps *o) for (;; v1++) { read_vec_element_i64(tmp, v1, 0, ES_64); - tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEQ); + tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEUQ); gen_addi_and_wrap_i64(s, o->addr1, o->addr1, 8); read_vec_element_i64(tmp, v1, 1, ES_64); - tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEQ); + tcg_gen_qemu_st_i64(tmp, o->addr1, get_mem_index(s), MO_TEUQ); if (v1 == v3) { break; } diff --git a/target/sh4/translate.c b/target/sh4/translate.c index 50493c61ea..43bc88b7b3 100644 --- a/target/sh4/translate.c +++ b/target/sh4/translate.c @@ -1010,7 +1010,7 @@ static void _decode_opc(DisasContext * ctx) if (ctx->tbflags & FPSCR_SZ) { TCGv_i64 fp = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp, XHACK(B7_4)); - tcg_gen_qemu_st_i64(fp, REG(B11_8), ctx->memidx, MO_TEQ); + tcg_gen_qemu_st_i64(fp, REG(B11_8), ctx->memidx, MO_TEUQ); tcg_temp_free_i64(fp); } else { tcg_gen_qemu_st_i32(FREG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL); @@ -1020,7 +1020,7 @@ static void _decode_opc(DisasContext * ctx) CHECK_FPU_ENABLED if (ctx->tbflags & FPSCR_SZ) { TCGv_i64 fp = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEQ); + tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEUQ); gen_store_fpr64(ctx, fp, XHACK(B11_8)); tcg_temp_free_i64(fp); } else { @@ -1031,7 +1031,7 @@ static void _decode_opc(DisasContext * ctx) CHECK_FPU_ENABLED if (ctx->tbflags & FPSCR_SZ) { TCGv_i64 fp = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEQ); + tcg_gen_qemu_ld_i64(fp, REG(B7_4), ctx->memidx, MO_TEUQ); gen_store_fpr64(ctx, fp, XHACK(B11_8)); tcg_temp_free_i64(fp); tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 8); @@ -1048,7 +1048,7 @@ static void _decode_opc(DisasContext * ctx) TCGv_i64 fp = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp, XHACK(B7_4)); tcg_gen_subi_i32(addr, REG(B11_8), 8); - tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEQ); + tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEUQ); tcg_temp_free_i64(fp); } else { tcg_gen_subi_i32(addr, REG(B11_8), 4); @@ -1065,7 +1065,7 @@ static void _decode_opc(DisasContext * ctx) tcg_gen_add_i32(addr, REG(B7_4), REG(0)); if (ctx->tbflags & FPSCR_SZ) { TCGv_i64 fp = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(fp, addr, ctx->memidx, MO_TEQ); + tcg_gen_qemu_ld_i64(fp, addr, ctx->memidx, MO_TEUQ); gen_store_fpr64(ctx, fp, XHACK(B11_8)); tcg_temp_free_i64(fp); } else { @@ -1082,7 +1082,7 @@ static void _decode_opc(DisasContext * ctx) if (ctx->tbflags & FPSCR_SZ) { TCGv_i64 fp = tcg_temp_new_i64(); gen_load_fpr64(ctx, fp, XHACK(B7_4)); - tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEQ); + tcg_gen_qemu_st_i64(fp, addr, ctx->memidx, MO_TEUQ); tcg_temp_free_i64(fp); } else { tcg_gen_qemu_st_i32(FREG(B7_4), addr, ctx->memidx, MO_TEUL); diff --git a/target/sparc/translate.c b/target/sparc/translate.c index fdb8bbe5dc..4c7c7b5347 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -2464,7 +2464,7 @@ static void gen_ldstub_asi(DisasContext *dc, TCGv dst, TCGv addr, int insn) static void gen_ldf_asi(DisasContext *dc, TCGv addr, int insn, int size, int rd) { - DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ)); + DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEUQ)); TCGv_i32 d32; TCGv_i64 d64; @@ -2578,7 +2578,7 @@ static void gen_ldf_asi(DisasContext *dc, TCGv addr, static void gen_stf_asi(DisasContext *dc, TCGv addr, int insn, int size, int rd) { - DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEQ)); + DisasASI da = get_asi(dc, insn, (size == 4 ? MO_TEUL : MO_TEUQ)); TCGv_i32 d32; switch (da.type) { @@ -2660,7 +2660,7 @@ static void gen_stf_asi(DisasContext *dc, TCGv addr, static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd) { - DisasASI da = get_asi(dc, insn, MO_TEQ); + DisasASI da = get_asi(dc, insn, MO_TEUQ); TCGv_i64 hi = gen_dest_gpr(dc, rd); TCGv_i64 lo = gen_dest_gpr(dc, rd + 1); @@ -2727,7 +2727,7 @@ static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd) static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, int insn, int rd) { - DisasASI da = get_asi(dc, insn, MO_TEQ); + DisasASI da = get_asi(dc, insn, MO_TEUQ); TCGv lo = gen_load_gpr(dc, rd + 1); switch (da.type) { @@ -2787,7 +2787,7 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, static void gen_casx_asi(DisasContext *dc, TCGv addr, TCGv cmpv, int insn, int rd) { - DisasASI da = get_asi(dc, insn, MO_TEQ); + DisasASI da = get_asi(dc, insn, MO_TEUQ); TCGv oldv; switch (da.type) { @@ -2817,7 +2817,7 @@ static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd) TCGv lo = gen_dest_gpr(dc, rd | 1); TCGv hi = gen_dest_gpr(dc, rd); TCGv_i64 t64 = tcg_temp_new_i64(); - DisasASI da = get_asi(dc, insn, MO_TEQ); + DisasASI da = get_asi(dc, insn, MO_TEUQ); switch (da.type) { case GET_ASI_EXCP: @@ -2830,7 +2830,7 @@ static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd) default: { TCGv_i32 r_asi = tcg_const_i32(da.asi); - TCGv_i32 r_mop = tcg_const_i32(MO_Q); + TCGv_i32 r_mop = tcg_const_i32(MO_UQ); save_state(dc); gen_helper_ld_asi(t64, cpu_env, addr, r_asi, r_mop); @@ -2849,7 +2849,7 @@ static void gen_ldda_asi(DisasContext *dc, TCGv addr, int insn, int rd) static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, int insn, int rd) { - DisasASI da = get_asi(dc, insn, MO_TEQ); + DisasASI da = get_asi(dc, insn, MO_TEUQ); TCGv lo = gen_load_gpr(dc, rd + 1); TCGv_i64 t64 = tcg_temp_new_i64(); @@ -2886,7 +2886,7 @@ static void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr, default: { TCGv_i32 r_asi = tcg_const_i32(da.asi); - TCGv_i32 r_mop = tcg_const_i32(MO_Q); + TCGv_i32 r_mop = tcg_const_i32(MO_UQ); save_state(dc); gen_helper_st_asi(cpu_env, addr, t64, r_asi, r_mop); @@ -5479,7 +5479,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TESL); break; case 0x1b: /* V9 ldxa */ - gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEQ); + gen_ld_asi(dc, cpu_val, cpu_addr, insn, MO_TEUQ); break; case 0x2d: /* V9 prefetch, no effect */ goto skip_move; @@ -5533,7 +5533,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) if (rd == 1) { TCGv_i64 t64 = tcg_temp_new_i64(); tcg_gen_qemu_ld_i64(t64, cpu_addr, - dc->mem_idx, MO_TEQ); + dc->mem_idx, MO_TEUQ); gen_helper_ldxfsr(cpu_fsr, cpu_env, cpu_fsr, t64); tcg_temp_free_i64(t64); break; @@ -5549,11 +5549,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_address_mask(dc, cpu_addr); cpu_src1_64 = tcg_temp_new_i64(); tcg_gen_qemu_ld_i64(cpu_src1_64, cpu_addr, dc->mem_idx, - MO_TEQ | MO_ALIGN_4); + MO_TEUQ | MO_ALIGN_4); tcg_gen_addi_tl(cpu_addr, cpu_addr, 8); cpu_src2_64 = tcg_temp_new_i64(); tcg_gen_qemu_ld_i64(cpu_src2_64, cpu_addr, dc->mem_idx, - MO_TEQ | MO_ALIGN_4); + MO_TEUQ | MO_ALIGN_4); gen_store_fpr_Q(dc, rd, cpu_src1_64, cpu_src2_64); tcg_temp_free_i64(cpu_src1_64); tcg_temp_free_i64(cpu_src2_64); @@ -5562,7 +5562,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_address_mask(dc, cpu_addr); cpu_dst_64 = gen_dest_fpr_D(dc, rd); tcg_gen_qemu_ld_i64(cpu_dst_64, cpu_addr, dc->mem_idx, - MO_TEQ | MO_ALIGN_4); + MO_TEUQ | MO_ALIGN_4); gen_store_fpr_D(dc, rd, cpu_dst_64); break; default: @@ -5623,7 +5623,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx); break; case 0x1e: /* V9 stxa */ - gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEQ); + gen_st_asi(dc, cpu_val, cpu_addr, insn, MO_TEUQ); break; #endif default: @@ -5664,11 +5664,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) before performing the first write. */ cpu_src1_64 = gen_load_fpr_Q0(dc, rd); tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr, - dc->mem_idx, MO_TEQ | MO_ALIGN_16); + dc->mem_idx, MO_TEUQ | MO_ALIGN_16); tcg_gen_addi_tl(cpu_addr, cpu_addr, 8); cpu_src2_64 = gen_load_fpr_Q1(dc, rd); tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr, - dc->mem_idx, MO_TEQ); + dc->mem_idx, MO_TEUQ); break; #else /* !TARGET_SPARC64 */ /* stdfq, store floating point queue */ @@ -5687,7 +5687,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) gen_address_mask(dc, cpu_addr); cpu_src1_64 = gen_load_fpr_D(dc, rd); tcg_gen_qemu_st_i64(cpu_src1_64, cpu_addr, dc->mem_idx, - MO_TEQ | MO_ALIGN_4); + MO_TEUQ | MO_ALIGN_4); break; default: goto illegal_insn; diff --git a/target/tricore/translate.c b/target/tricore/translate.c index 07084407cb..417edbd3f0 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -246,7 +246,7 @@ static void gen_st_2regs_64(TCGv rh, TCGv rl, TCGv address, DisasContext *ctx) TCGv_i64 temp = tcg_temp_new_i64(); tcg_gen_concat_i32_i64(temp, rl, rh); - tcg_gen_qemu_st_i64(temp, address, ctx->mem_idx, MO_LEQ); + tcg_gen_qemu_st_i64(temp, address, ctx->mem_idx, MO_LEUQ); tcg_temp_free_i64(temp); } @@ -264,7 +264,7 @@ static void gen_ld_2regs_64(TCGv rh, TCGv rl, TCGv address, DisasContext *ctx) { TCGv_i64 temp = tcg_temp_new_i64(); - tcg_gen_qemu_ld_i64(temp, address, ctx->mem_idx, MO_LEQ); + tcg_gen_qemu_ld_i64(temp, address, ctx->mem_idx, MO_LEUQ); /* write back to two 32 bit regs */ tcg_gen_extr_i64_i32(rl, rh, temp); diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 09430c1bf9..b1491ed625 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -7077,7 +7077,7 @@ static void translate_ldsti_d(DisasContext *dc, const OpcodeArg arg[], } else { addr = arg[1].in; } - mop = gen_load_store_alignment(dc, MO_TEQ, addr); + mop = gen_load_store_alignment(dc, MO_TEUQ, addr); if (par[0]) { tcg_gen_qemu_st_i64(arg[0].in, addr, dc->cring, mop); } else { @@ -7142,7 +7142,7 @@ static void translate_ldstx_d(DisasContext *dc, const OpcodeArg arg[], } else { addr = arg[1].in; } - mop = gen_load_store_alignment(dc, MO_TEQ, addr); + mop = gen_load_store_alignment(dc, MO_TEUQ, addr); if (par[0]) { tcg_gen_qemu_st_i64(arg[0].in, addr, dc->cring, mop); } else { diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc index 5edca8d44d..a8db553287 100644 --- a/tcg/aarch64/tcg-target.c.inc +++ b/tcg/aarch64/tcg-target.c.inc @@ -1744,7 +1744,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp memop, TCGType ext, case MO_SL: tcg_out_ldst_r(s, I3312_LDRSWX, data_r, addr_r, otype, off_r); break; - case MO_Q: + case MO_UQ: tcg_out_ldst_r(s, I3312_LDRX, data_r, addr_r, otype, off_r); break; default: diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc index 9d322cdba6..5345c4e39c 100644 --- a/tcg/arm/tcg-target.c.inc +++ b/tcg/arm/tcg-target.c.inc @@ -1443,13 +1443,13 @@ static void * const qemu_ld_helpers[MO_SSIZE + 1] = { #ifdef HOST_WORDS_BIGENDIAN [MO_UW] = helper_be_lduw_mmu, [MO_UL] = helper_be_ldul_mmu, - [MO_Q] = helper_be_ldq_mmu, + [MO_UQ] = helper_be_ldq_mmu, [MO_SW] = helper_be_ldsw_mmu, [MO_SL] = helper_be_ldul_mmu, #else [MO_UW] = helper_le_lduw_mmu, [MO_UL] = helper_le_ldul_mmu, - [MO_Q] = helper_le_ldq_mmu, + [MO_UQ] = helper_le_ldq_mmu, [MO_SW] = helper_le_ldsw_mmu, [MO_SL] = helper_le_ldul_mmu, #endif @@ -1694,7 +1694,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) default: tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0); break; - case MO_Q: + case MO_UQ: if (datalo != TCG_REG_R1) { tcg_out_mov_reg(s, COND_AL, datalo, TCG_REG_R0); tcg_out_mov_reg(s, COND_AL, datahi, TCG_REG_R1); @@ -1781,7 +1781,7 @@ static void tcg_out_qemu_ld_index(TCGContext *s, MemOp opc, case MO_UL: tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend); break; - case MO_Q: + case MO_UQ: /* Avoid ldrd for user-only emulation, to handle unaligned. */ if (USING_SOFTMMU && use_armv6_instructions && (datalo & 1) == 0 && datahi == datalo + 1) { @@ -1824,7 +1824,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg datalo, case MO_UL: tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0); break; - case MO_Q: + case MO_UQ: /* Avoid ldrd for user-only emulation, to handle unaligned. */ if (USING_SOFTMMU && use_armv6_instructions && (datalo & 1) == 0 && datahi == datalo + 1) { diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc index 84b109bb84..875311f795 100644 --- a/tcg/i386/tcg-target.c.inc +++ b/tcg/i386/tcg-target.c.inc @@ -1615,10 +1615,10 @@ static void * const qemu_ld_helpers[(MO_SIZE | MO_BSWAP) + 1] = { [MO_UB] = helper_ret_ldub_mmu, [MO_LEUW] = helper_le_lduw_mmu, [MO_LEUL] = helper_le_ldul_mmu, - [MO_LEQ] = helper_le_ldq_mmu, + [MO_LEUQ] = helper_le_ldq_mmu, [MO_BEUW] = helper_be_lduw_mmu, [MO_BEUL] = helper_be_ldul_mmu, - [MO_BEQ] = helper_be_ldq_mmu, + [MO_BEUQ] = helper_be_ldq_mmu, }; /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr, @@ -1628,10 +1628,10 @@ static void * const qemu_st_helpers[(MO_SIZE | MO_BSWAP) + 1] = { [MO_UB] = helper_ret_stb_mmu, [MO_LEUW] = helper_le_stw_mmu, [MO_LEUL] = helper_le_stl_mmu, - [MO_LEQ] = helper_le_stq_mmu, + [MO_LEUQ] = helper_le_stq_mmu, [MO_BEUW] = helper_be_stw_mmu, [MO_BEUL] = helper_be_stl_mmu, - [MO_BEQ] = helper_be_stq_mmu, + [MO_BEUQ] = helper_be_stq_mmu, }; /* Perform the TLB load and compare. @@ -1827,7 +1827,7 @@ static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) case MO_UL: tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX); break; - case MO_Q: + case MO_UQ: if (TCG_TARGET_REG_BITS == 64) { tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX); } else if (data_reg == TCG_REG_EDX) { @@ -2019,7 +2019,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, } break; #endif - case MO_Q: + case MO_UQ: if (TCG_TARGET_REG_BITS == 64) { tcg_out_modrm_sib_offset(s, movop + P_REXW + seg, datalo, base, index, 0, ofs); diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc index d8f6914f03..27b020e66c 100644 --- a/tcg/mips/tcg-target.c.inc +++ b/tcg/mips/tcg-target.c.inc @@ -1023,11 +1023,11 @@ static void * const qemu_ld_helpers[(MO_SSIZE | MO_BSWAP) + 1] = { [MO_LEUW] = helper_le_lduw_mmu, [MO_LESW] = helper_le_ldsw_mmu, [MO_LEUL] = helper_le_ldul_mmu, - [MO_LEQ] = helper_le_ldq_mmu, + [MO_LEUQ] = helper_le_ldq_mmu, [MO_BEUW] = helper_be_lduw_mmu, [MO_BESW] = helper_be_ldsw_mmu, [MO_BEUL] = helper_be_ldul_mmu, - [MO_BEQ] = helper_be_ldq_mmu, + [MO_BEUQ] = helper_be_ldq_mmu, #if TCG_TARGET_REG_BITS == 64 [MO_LESL] = helper_le_ldsl_mmu, [MO_BESL] = helper_be_ldsl_mmu, @@ -1038,10 +1038,10 @@ static void * const qemu_st_helpers[(MO_SIZE | MO_BSWAP) + 1] = { [MO_UB] = helper_ret_stb_mmu, [MO_LEUW] = helper_le_stw_mmu, [MO_LEUL] = helper_le_stl_mmu, - [MO_LEQ] = helper_le_stq_mmu, + [MO_LEUQ] = helper_le_stq_mmu, [MO_BEUW] = helper_be_stw_mmu, [MO_BEUL] = helper_be_stl_mmu, - [MO_BEQ] = helper_be_stq_mmu, + [MO_BEUQ] = helper_be_stq_mmu, }; /* Helper routines for marshalling helper function arguments into @@ -1384,7 +1384,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, case MO_SL: tcg_out_opc_imm(s, OPC_LW, lo, base, 0); break; - case MO_Q | MO_BSWAP: + case MO_UQ | MO_BSWAP: if (TCG_TARGET_REG_BITS == 64) { if (use_mips32r2_instructions) { tcg_out_opc_imm(s, OPC_LD, lo, base, 0); @@ -1413,7 +1413,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, tcg_out_mov(s, TCG_TYPE_I32, MIPS_BE ? hi : lo, TCG_TMP3); } break; - case MO_Q: + case MO_UQ: /* Prefer to load from offset 0 first, but allow for overlap. */ if (TCG_TARGET_REG_BITS == 64) { tcg_out_opc_imm(s, OPC_LD, lo, base, 0); diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc index 3e4ca2be88..9e79a7edee 100644 --- a/tcg/ppc/tcg-target.c.inc +++ b/tcg/ppc/tcg-target.c.inc @@ -1935,24 +1935,24 @@ static const uint32_t qemu_ldx_opc[(MO_SSIZE + MO_BSWAP) + 1] = { [MO_UB] = LBZX, [MO_UW] = LHZX, [MO_UL] = LWZX, - [MO_Q] = LDX, + [MO_UQ] = LDX, [MO_SW] = LHAX, [MO_SL] = LWAX, [MO_BSWAP | MO_UB] = LBZX, [MO_BSWAP | MO_UW] = LHBRX, [MO_BSWAP | MO_UL] = LWBRX, - [MO_BSWAP | MO_Q] = LDBRX, + [MO_BSWAP | MO_UQ] = LDBRX, }; static const uint32_t qemu_stx_opc[(MO_SIZE + MO_BSWAP) + 1] = { [MO_UB] = STBX, [MO_UW] = STHX, [MO_UL] = STWX, - [MO_Q] = STDX, + [MO_UQ] = STDX, [MO_BSWAP | MO_UB] = STBX, [MO_BSWAP | MO_UW] = STHBRX, [MO_BSWAP | MO_UL] = STWBRX, - [MO_BSWAP | MO_Q] = STDBRX, + [MO_BSWAP | MO_UQ] = STDBRX, }; static const uint32_t qemu_exts_opc[4] = { @@ -1969,10 +1969,10 @@ static void * const qemu_ld_helpers[(MO_SIZE | MO_BSWAP) + 1] = { [MO_UB] = helper_ret_ldub_mmu, [MO_LEUW] = helper_le_lduw_mmu, [MO_LEUL] = helper_le_ldul_mmu, - [MO_LEQ] = helper_le_ldq_mmu, + [MO_LEUQ] = helper_le_ldq_mmu, [MO_BEUW] = helper_be_lduw_mmu, [MO_BEUL] = helper_be_ldul_mmu, - [MO_BEQ] = helper_be_ldq_mmu, + [MO_BEUQ] = helper_be_ldq_mmu, }; /* helper signature: helper_st_mmu(CPUState *env, target_ulong addr, @@ -1982,10 +1982,10 @@ static void * const qemu_st_helpers[(MO_SIZE | MO_BSWAP) + 1] = { [MO_UB] = helper_ret_stb_mmu, [MO_LEUW] = helper_le_stw_mmu, [MO_LEUL] = helper_le_stl_mmu, - [MO_LEQ] = helper_le_stq_mmu, + [MO_LEUQ] = helper_le_stq_mmu, [MO_BEUW] = helper_be_stw_mmu, [MO_BEUL] = helper_be_stl_mmu, - [MO_BEQ] = helper_be_stq_mmu, + [MO_BEUQ] = helper_be_stq_mmu, }; /* We expect to use a 16-bit negative offset from ENV. */ diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc index 9b13a46fb4..e9488f7093 100644 --- a/tcg/riscv/tcg-target.c.inc +++ b/tcg/riscv/tcg-target.c.inc @@ -862,7 +862,7 @@ static void * const qemu_ld_helpers[MO_SSIZE + 1] = { #if TCG_TARGET_REG_BITS == 64 [MO_SL] = helper_be_ldsl_mmu, #endif - [MO_Q] = helper_be_ldq_mmu, + [MO_UQ] = helper_be_ldq_mmu, #else [MO_UW] = helper_le_lduw_mmu, [MO_SW] = helper_le_ldsw_mmu, @@ -870,7 +870,7 @@ static void * const qemu_ld_helpers[MO_SSIZE + 1] = { #if TCG_TARGET_REG_BITS == 64 [MO_SL] = helper_le_ldsl_mmu, #endif - [MO_Q] = helper_le_ldq_mmu, + [MO_UQ] = helper_le_ldq_mmu, #endif }; @@ -1083,7 +1083,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, case MO_SL: tcg_out_opc_imm(s, OPC_LW, lo, base, 0); break; - case MO_Q: + case MO_UQ: /* Prefer to load from offset 0 first, but allow for overlap. */ if (TCG_TARGET_REG_BITS == 64) { tcg_out_opc_imm(s, OPC_LD, lo, base, 0); diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc index 57e803e339..b12fbfda63 100644 --- a/tcg/s390x/tcg-target.c.inc +++ b/tcg/s390x/tcg-target.c.inc @@ -438,22 +438,22 @@ static void * const qemu_ld_helpers[(MO_SSIZE | MO_BSWAP) + 1] = { [MO_LESW] = helper_le_ldsw_mmu, [MO_LEUL] = helper_le_ldul_mmu, [MO_LESL] = helper_le_ldsl_mmu, - [MO_LEQ] = helper_le_ldq_mmu, + [MO_LEUQ] = helper_le_ldq_mmu, [MO_BEUW] = helper_be_lduw_mmu, [MO_BESW] = helper_be_ldsw_mmu, [MO_BEUL] = helper_be_ldul_mmu, [MO_BESL] = helper_be_ldsl_mmu, - [MO_BEQ] = helper_be_ldq_mmu, + [MO_BEUQ] = helper_be_ldq_mmu, }; static void * const qemu_st_helpers[(MO_SIZE | MO_BSWAP) + 1] = { [MO_UB] = helper_ret_stb_mmu, [MO_LEUW] = helper_le_stw_mmu, [MO_LEUL] = helper_le_stl_mmu, - [MO_LEQ] = helper_le_stq_mmu, + [MO_LEUQ] = helper_le_stq_mmu, [MO_BEUW] = helper_be_stw_mmu, [MO_BEUL] = helper_be_stl_mmu, - [MO_BEQ] = helper_be_stq_mmu, + [MO_BEUQ] = helper_be_stq_mmu, }; #endif @@ -1745,10 +1745,10 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg data, tcg_out_insn(s, RXY, LGF, data, base, index, disp); break; - case MO_Q | MO_BSWAP: + case MO_UQ | MO_BSWAP: tcg_out_insn(s, RXY, LRVG, data, base, index, disp); break; - case MO_Q: + case MO_UQ: tcg_out_insn(s, RXY, LG, data, base, index, disp); break; @@ -1791,10 +1791,10 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg data, } break; - case MO_Q | MO_BSWAP: + case MO_UQ | MO_BSWAP: tcg_out_insn(s, RXY, STRVG, data, base, index, disp); break; - case MO_Q: + case MO_UQ: tcg_out_insn(s, RXY, STG, data, base, index, disp); break; @@ -1928,7 +1928,7 @@ static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) case MO_UL: tgen_ext32u(s, TCG_REG_R4, data_reg); break; - case MO_Q: + case MO_UQ: tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_R4, data_reg); break; default: diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc index 9dd32ef95e..0c062c60eb 100644 --- a/tcg/sparc/tcg-target.c.inc +++ b/tcg/sparc/tcg-target.c.inc @@ -889,20 +889,20 @@ static void build_trampolines(TCGContext *s) [MO_LEUW] = helper_le_lduw_mmu, [MO_LESW] = helper_le_ldsw_mmu, [MO_LEUL] = helper_le_ldul_mmu, - [MO_LEQ] = helper_le_ldq_mmu, + [MO_LEUQ] = helper_le_ldq_mmu, [MO_BEUW] = helper_be_lduw_mmu, [MO_BESW] = helper_be_ldsw_mmu, [MO_BEUL] = helper_be_ldul_mmu, - [MO_BEQ] = helper_be_ldq_mmu, + [MO_BEUQ] = helper_be_ldq_mmu, }; static void * const qemu_st_helpers[] = { [MO_UB] = helper_ret_stb_mmu, [MO_LEUW] = helper_le_stw_mmu, [MO_LEUL] = helper_le_stl_mmu, - [MO_LEQ] = helper_le_stq_mmu, + [MO_LEUQ] = helper_le_stq_mmu, [MO_BEUW] = helper_be_stw_mmu, [MO_BEUL] = helper_be_stl_mmu, - [MO_BEQ] = helper_be_stq_mmu, + [MO_BEUQ] = helper_be_stq_mmu, }; int i; @@ -1126,13 +1126,13 @@ static const int qemu_ld_opc[(MO_SSIZE | MO_BSWAP) + 1] = { [MO_BESW] = LDSH, [MO_BEUL] = LDUW, [MO_BESL] = LDSW, - [MO_BEQ] = LDX, + [MO_BEUQ] = LDX, [MO_LEUW] = LDUH_LE, [MO_LESW] = LDSH_LE, [MO_LEUL] = LDUW_LE, [MO_LESL] = LDSW_LE, - [MO_LEQ] = LDX_LE, + [MO_LEUQ] = LDX_LE, }; static const int qemu_st_opc[(MO_SIZE | MO_BSWAP) + 1] = { @@ -1140,11 +1140,11 @@ static const int qemu_st_opc[(MO_SIZE | MO_BSWAP) + 1] = { [MO_BEUW] = STH, [MO_BEUL] = STW, - [MO_BEQ] = STX, + [MO_BEUQ] = STX, [MO_LEUW] = STH_LE, [MO_LEUL] = STW_LE, - [MO_LEQ] = STX_LE, + [MO_LEUQ] = STX_LE, }; static void tcg_out_qemu_ld(TCGContext *s, TCGReg data, TCGReg addr, diff --git a/tcg/tcg.c b/tcg/tcg.c index 934aa8510b..5d2f0d8b10 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1751,12 +1751,12 @@ static const char * const ldst_name[] = [MO_LESW] = "lesw", [MO_LEUL] = "leul", [MO_LESL] = "lesl", - [MO_LEQ] = "leq", + [MO_LEUQ] = "leq", [MO_BEUW] = "beuw", [MO_BESW] = "besw", [MO_BEUL] = "beul", [MO_BESL] = "besl", - [MO_BEQ] = "beq", + [MO_BEUQ] = "beq", }; static const char * const alignment_name[(MO_AMASK >> MO_ASHIFT) + 1] = { diff --git a/tcg/tci.c b/tcg/tci.c index e76087ccac..336af5945a 100644 --- a/tcg/tci.c +++ b/tcg/tci.c @@ -309,7 +309,7 @@ static uint64_t tci_qemu_ld(CPUArchState *env, target_ulong taddr, return helper_le_ldul_mmu(env, taddr, oi, ra); case MO_LESL: return helper_le_ldsl_mmu(env, taddr, oi, ra); - case MO_LEQ: + case MO_LEUQ: return helper_le_ldq_mmu(env, taddr, oi, ra); case MO_BEUW: return helper_be_lduw_mmu(env, taddr, oi, ra); @@ -319,7 +319,7 @@ static uint64_t tci_qemu_ld(CPUArchState *env, target_ulong taddr, return helper_be_ldul_mmu(env, taddr, oi, ra); case MO_BESL: return helper_be_ldsl_mmu(env, taddr, oi, ra); - case MO_BEQ: + case MO_BEUQ: return helper_be_ldq_mmu(env, taddr, oi, ra); default: g_assert_not_reached(); @@ -348,7 +348,7 @@ static uint64_t tci_qemu_ld(CPUArchState *env, target_ulong taddr, case MO_LESL: ret = (int32_t)ldl_le_p(haddr); break; - case MO_LEQ: + case MO_LEUQ: ret = ldq_le_p(haddr); break; case MO_BEUW: @@ -363,7 +363,7 @@ static uint64_t tci_qemu_ld(CPUArchState *env, target_ulong taddr, case MO_BESL: ret = (int32_t)ldl_be_p(haddr); break; - case MO_BEQ: + case MO_BEUQ: ret = ldq_be_p(haddr); break; default: @@ -391,7 +391,7 @@ static void tci_qemu_st(CPUArchState *env, target_ulong taddr, uint64_t val, case MO_LEUL: helper_le_stl_mmu(env, taddr, val, oi, ra); break; - case MO_LEQ: + case MO_LEUQ: helper_le_stq_mmu(env, taddr, val, oi, ra); break; case MO_BEUW: @@ -400,7 +400,7 @@ static void tci_qemu_st(CPUArchState *env, target_ulong taddr, uint64_t val, case MO_BEUL: helper_be_stl_mmu(env, taddr, val, oi, ra); break; - case MO_BEQ: + case MO_BEUQ: helper_be_stq_mmu(env, taddr, val, oi, ra); break; default: @@ -420,7 +420,7 @@ static void tci_qemu_st(CPUArchState *env, target_ulong taddr, uint64_t val, case MO_LEUL: stl_le_p(haddr, val); break; - case MO_LEQ: + case MO_LEUQ: stq_le_p(haddr, val); break; case MO_BEUW: @@ -429,7 +429,7 @@ static void tci_qemu_st(CPUArchState *env, target_ulong taddr, uint64_t val, case MO_BEUL: stl_be_p(haddr, val); break; - case MO_BEQ: + case MO_BEUQ: stq_be_p(haddr, val); break; default: From c7f9dd546510a27c77e8e90e4fb527bf830853fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:00:52 +0100 Subject: [PATCH 300/730] exec/memop: Adding signed quad and octo defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding defines to handle signed 64-bit and unsigned 128-bit quantities in memory accesses. Signed-off-by: Frédéric Pétrot Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-3-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- include/exec/memop.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/exec/memop.h b/include/exec/memop.h index 72c2f0ff3d..2a885f3917 100644 --- a/include/exec/memop.h +++ b/include/exec/memop.h @@ -86,28 +86,35 @@ typedef enum MemOp { MO_UW = MO_16, MO_UL = MO_32, MO_UQ = MO_64, + MO_UO = MO_128, MO_SB = MO_SIGN | MO_8, MO_SW = MO_SIGN | MO_16, MO_SL = MO_SIGN | MO_32, + MO_SQ = MO_SIGN | MO_64, + MO_SO = MO_SIGN | MO_128, MO_LEUW = MO_LE | MO_UW, MO_LEUL = MO_LE | MO_UL, MO_LEUQ = MO_LE | MO_UQ, MO_LESW = MO_LE | MO_SW, MO_LESL = MO_LE | MO_SL, + MO_LESQ = MO_LE | MO_SQ, MO_BEUW = MO_BE | MO_UW, MO_BEUL = MO_BE | MO_UL, MO_BEUQ = MO_BE | MO_UQ, MO_BESW = MO_BE | MO_SW, MO_BESL = MO_BE | MO_SL, + MO_BESQ = MO_BE | MO_SQ, #ifdef NEED_CPU_H MO_TEUW = MO_TE | MO_UW, MO_TEUL = MO_TE | MO_UL, MO_TEUQ = MO_TE | MO_UQ, + MO_TEUO = MO_TE | MO_UO, MO_TESW = MO_TE | MO_SW, MO_TESL = MO_TE | MO_SL, + MO_TESQ = MO_TE | MO_SQ, #endif MO_SSIZE = MO_SIZE | MO_SIGN, From e9d07601f6c412ef03e00b03d13ae22488be0bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:00:53 +0100 Subject: [PATCH 301/730] qemu/int128: addition of div/rem 128-bit operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addition of div and rem on 128-bit integers, using the 128/64->128 divu and 64x64->128 mulu in host-utils. These operations will be used within div/rem helpers in the 128-bit riscv target. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-4-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- include/qemu/int128.h | 27 ++++++++ util/int128.c | 147 ++++++++++++++++++++++++++++++++++++++++++ util/meson.build | 1 + 3 files changed, 175 insertions(+) create mode 100644 util/int128.c diff --git a/include/qemu/int128.h b/include/qemu/int128.h index b6d517aea4..2c4064256c 100644 --- a/include/qemu/int128.h +++ b/include/qemu/int128.h @@ -172,6 +172,26 @@ static inline Int128 bswap128(Int128 a) #endif } +static inline Int128 int128_divu(Int128 a, Int128 b) +{ + return (__uint128_t)a / (__uint128_t)b; +} + +static inline Int128 int128_remu(Int128 a, Int128 b) +{ + return (__uint128_t)a % (__uint128_t)b; +} + +static inline Int128 int128_divs(Int128 a, Int128 b) +{ + return a / b; +} + +static inline Int128 int128_rems(Int128 a, Int128 b) +{ + return a % b; +} + #else /* !CONFIG_INT128 */ typedef struct Int128 Int128; @@ -379,6 +399,11 @@ static inline Int128 bswap128(Int128 a) return int128_make128(bswap64(a.hi), bswap64(a.lo)); } +Int128 int128_divu(Int128, Int128); +Int128 int128_remu(Int128, Int128); +Int128 int128_divs(Int128, Int128); +Int128 int128_rems(Int128, Int128); + #endif /* CONFIG_INT128 */ static inline void bswap128s(Int128 *s) @@ -386,4 +411,6 @@ static inline void bswap128s(Int128 *s) *s = bswap128(*s); } +#define UINT128_MAX int128_make128(~0LL, ~0LL) + #endif /* INT128_H */ diff --git a/util/int128.c b/util/int128.c new file mode 100644 index 0000000000..ed8f25fef1 --- /dev/null +++ b/util/int128.c @@ -0,0 +1,147 @@ +/* + * 128-bit division and remainder for compilers not supporting __int128 + * + * Copyright (c) 2021 Frédéric Pétrot + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qemu/host-utils.h" +#include "qemu/int128.h" + +#ifndef CONFIG_INT128 + +/* + * Division and remainder algorithms for 128-bit due to Stefan Kanthak, + * https://skanthak.homepage.t-online.de/integer.html#udivmodti4 + * Preconditions: + * - function should never be called with v equals to 0, it has to + * be dealt with beforehand + * - quotien pointer must be valid + */ +static Int128 divrem128(Int128 u, Int128 v, Int128 *q) +{ + Int128 qq; + uint64_t hi, lo, tmp; + int s = clz64(v.hi); + + if (s == 64) { + /* we have uu÷0v => let's use divu128 */ + hi = u.hi; + lo = u.lo; + tmp = divu128(&lo, &hi, v.lo); + *q = int128_make128(lo, hi); + return int128_make128(tmp, 0); + } else { + hi = int128_gethi(int128_lshift(v, s)); + + if (hi > u.hi) { + lo = u.lo; + tmp = u.hi; + divu128(&lo, &tmp, hi); + lo = int128_gethi(int128_lshift(int128_make128(lo, 0), s)); + } else { /* prevent overflow */ + lo = u.lo; + tmp = u.hi - hi; + divu128(&lo, &tmp, hi); + lo = int128_gethi(int128_lshift(int128_make128(lo, 1), s)); + } + + qq = int128_make64(lo); + + tmp = lo * v.hi; + mulu64(&lo, &hi, lo, v.lo); + hi += tmp; + + if (hi < tmp /* quotient * divisor >= 2**128 > dividend */ + || hi > u.hi /* quotient * divisor > dividend */ + || (hi == u.hi && lo > u.lo)) { + qq.lo -= 1; + mulu64(&lo, &hi, qq.lo, v.lo); + hi += qq.lo * v.hi; + } + + *q = qq; + u.hi -= hi + (u.lo < lo); + u.lo -= lo; + return u; + } +} + +Int128 int128_divu(Int128 a, Int128 b) +{ + Int128 q; + divrem128(a, b, &q); + return q; +} + +Int128 int128_remu(Int128 a, Int128 b) +{ + Int128 q; + return divrem128(a, b, &q); +} + +Int128 int128_divs(Int128 a, Int128 b) +{ + Int128 q; + bool sgna = !int128_nonneg(a); + bool sgnb = !int128_nonneg(b); + + if (sgna) { + a = int128_neg(a); + } + + if (sgnb) { + b = int128_neg(b); + } + + divrem128(a, b, &q); + + if (sgna != sgnb) { + q = int128_neg(q); + } + + return q; +} + +Int128 int128_rems(Int128 a, Int128 b) +{ + Int128 q, r; + bool sgna = !int128_nonneg(a); + bool sgnb = !int128_nonneg(b); + + if (sgna) { + a = int128_neg(a); + } + + if (sgnb) { + b = int128_neg(b); + } + + r = divrem128(a, b, &q); + + if (sgna) { + r = int128_neg(r); + } + + return r; +} + +#endif diff --git a/util/meson.build b/util/meson.build index 05b593055a..e676b2f6c6 100644 --- a/util/meson.build +++ b/util/meson.build @@ -48,6 +48,7 @@ util_ss.add(files('transactions.c')) util_ss.add(when: 'CONFIG_POSIX', if_true: files('drm.c')) util_ss.add(files('guest-random.c')) util_ss.add(files('yank.c')) +util_ss.add(files('int128.c')) if have_user util_ss.add(files('selfmap.c')) From 344b4a82fc165798546dbf276c7b281899c177a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:00:54 +0100 Subject: [PATCH 302/730] target/riscv: additional macros to check instruction support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given that the 128-bit version of the riscv spec adds new instructions, and that some instructions that were previously only available in 64-bit mode are now available for both 64-bit and 128-bit, we added new macros to check for the processor mode during translation. Although RV128 is a superset of RV64, we keep for now the RV64 only tests for extensions other than RVI and RVM. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-5-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/translate.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 5df6c0d800..502bf0d009 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -443,10 +443,22 @@ EX_SH(12) } \ } while (0) -#define REQUIRE_64BIT(ctx) do { \ - if (get_xl(ctx) < MXL_RV64) { \ - return false; \ - } \ +#define REQUIRE_64BIT(ctx) do { \ + if (get_xl(ctx) != MXL_RV64) { \ + return false; \ + } \ +} while (0) + +#define REQUIRE_128BIT(ctx) do { \ + if (get_xl(ctx) != MXL_RV128) { \ + return false; \ + } \ +} while (0) + +#define REQUIRE_64_OR_128BIT(ctx) do { \ + if (get_xl(ctx) == MXL_RV32) { \ + return false; \ + } \ } while (0) static int ex_rvc_register(DisasContext *ctx, int reg) From a1a3aac448cced3161cd0c8a49ac24cd5d58fe14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:00:55 +0100 Subject: [PATCH 303/730] target/riscv: separation of bitwise logic and arithmetic helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduction of a gen_logic function for bitwise logic to implement instructions in which no propagation of information occurs between bits and use of this function on the bitwise instructions. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-6-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvb.c.inc | 6 +++--- target/riscv/insn_trans/trans_rvi.c.inc | 12 +++++------ target/riscv/translate.c | 27 +++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index c8d31907c5..de2cd613b1 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -86,19 +86,19 @@ static bool trans_cpop(DisasContext *ctx, arg_cpop *a) static bool trans_andn(DisasContext *ctx, arg_andn *a) { REQUIRE_ZBB(ctx); - return gen_arith(ctx, a, EXT_NONE, tcg_gen_andc_tl); + return gen_logic(ctx, a, tcg_gen_andc_tl); } static bool trans_orn(DisasContext *ctx, arg_orn *a) { REQUIRE_ZBB(ctx); - return gen_arith(ctx, a, EXT_NONE, tcg_gen_orc_tl); + return gen_logic(ctx, a, tcg_gen_orc_tl); } static bool trans_xnor(DisasContext *ctx, arg_xnor *a) { REQUIRE_ZBB(ctx); - return gen_arith(ctx, a, EXT_NONE, tcg_gen_eqv_tl); + return gen_logic(ctx, a, tcg_gen_eqv_tl); } static bool trans_min(DisasContext *ctx, arg_min *a) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 4a2aefe3a5..51607b3d40 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -252,17 +252,17 @@ static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a) static bool trans_xori(DisasContext *ctx, arg_xori *a) { - return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_xori_tl); + return gen_logic_imm_fn(ctx, a, tcg_gen_xori_tl); } static bool trans_ori(DisasContext *ctx, arg_ori *a) { - return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_ori_tl); + return gen_logic_imm_fn(ctx, a, tcg_gen_ori_tl); } static bool trans_andi(DisasContext *ctx, arg_andi *a) { - return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_andi_tl); + return gen_logic_imm_fn(ctx, a, tcg_gen_andi_tl); } static bool trans_slli(DisasContext *ctx, arg_slli *a) @@ -319,7 +319,7 @@ static bool trans_sltu(DisasContext *ctx, arg_sltu *a) static bool trans_xor(DisasContext *ctx, arg_xor *a) { - return gen_arith(ctx, a, EXT_NONE, tcg_gen_xor_tl); + return gen_logic(ctx, a, tcg_gen_xor_tl); } static bool trans_srl(DisasContext *ctx, arg_srl *a) @@ -334,12 +334,12 @@ static bool trans_sra(DisasContext *ctx, arg_sra *a) static bool trans_or(DisasContext *ctx, arg_or *a) { - return gen_arith(ctx, a, EXT_NONE, tcg_gen_or_tl); + return gen_logic(ctx, a, tcg_gen_or_tl); } static bool trans_and(DisasContext *ctx, arg_and *a) { - return gen_arith(ctx, a, EXT_NONE, tcg_gen_and_tl); + return gen_logic(ctx, a, tcg_gen_and_tl); } static bool trans_addiw(DisasContext *ctx, arg_addiw *a) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 502bf0d009..c3b4950ad0 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -475,6 +475,33 @@ static int ex_rvc_shifti(DisasContext *ctx, int imm) /* Include the auto-generated decoder for 32 bit insn */ #include "decode-insn32.c.inc" +static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a, + void (*func)(TCGv, TCGv, target_long)) +{ + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); + + func(dest, src1, a->imm); + + gen_set_gpr(ctx, a->rd, dest); + + return true; +} + +static bool gen_logic(DisasContext *ctx, arg_r *a, + void (*func)(TCGv, TCGv, TCGv)) +{ + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); + + func(dest, src1, src2); + + gen_set_gpr(ctx, a->rd, dest); + + return true; +} + static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext, void (*func)(TCGv, TCGv, target_long)) { From 2b5470843a6bf10bcc4431d81badec6bfe31f0a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:00:56 +0100 Subject: [PATCH 304/730] target/riscv: array for the 64 upper bits of 128-bit registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The upper 64-bit of the 128-bit registers have now a place inside the cpu state structure, and are created as globals for future use. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-7-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 9 +++++++++ target/riscv/cpu.h | 2 ++ target/riscv/machine.c | 20 ++++++++++++++++++++ target/riscv/translate.c | 5 ++++- 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ce21c1b5b1..1bd4a7c7aa 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -42,6 +42,15 @@ const char * const riscv_int_regnames[] = { "x28/t3", "x29/t4", "x30/t5", "x31/t6" }; +const char * const riscv_int_regnamesh[] = { + "x0h/zeroh", "x1h/rah", "x2h/sph", "x3h/gph", "x4h/tph", "x5h/t0h", + "x6h/t1h", "x7h/t2h", "x8h/s0h", "x9h/s1h", "x10h/a0h", "x11h/a1h", + "x12h/a2h", "x13h/a3h", "x14h/a4h", "x15h/a5h", "x16h/a6h", "x17h/a7h", + "x18h/s2h", "x19h/s3h", "x20h/s4h", "x21h/s5h", "x22h/s6h", "x23h/s7h", + "x24h/s8h", "x25h/s9h", "x26h/s10h", "x27h/s11h", "x28h/t3h", "x29h/t4h", + "x30h/t5h", "x31h/t6h" +}; + const char * const riscv_fpr_regnames[] = { "f0/ft0", "f1/ft1", "f2/ft2", "f3/ft3", "f4/ft4", "f5/ft5", "f6/ft6", "f7/ft7", "f8/fs0", "f9/fs1", "f10/fa0", "f11/fa1", diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index dc10f27093..fa5d238530 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -112,6 +112,7 @@ FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 1, 1) struct CPURISCVState { target_ulong gpr[32]; + target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */ uint64_t fpr[32]; /* assume both F and D extensions */ /* vector coprocessor state. */ @@ -344,6 +345,7 @@ static inline bool riscv_feature(CPURISCVState *env, int feature) #include "cpu_user.h" extern const char * const riscv_int_regnames[]; +extern const char * const riscv_int_regnamesh[]; extern const char * const riscv_fpr_regnames[]; const char *riscv_cpu_get_trap_name(target_ulong cause, bool async); diff --git a/target/riscv/machine.c b/target/riscv/machine.c index ad8248ebfd..8af9caabf5 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -164,6 +164,25 @@ static const VMStateDescription vmstate_pointermasking = { } }; +static bool rv128_needed(void *opaque) +{ + RISCVCPU *cpu = opaque; + CPURISCVState *env = &cpu->env; + + return env->misa_mxl_max == MXL_RV128; +} + +static const VMStateDescription vmstate_rv128 = { + .name = "cpu/rv128", + .version_id = 1, + .minimum_version_id = 1, + .needed = rv128_needed, + .fields = (VMStateField[]) { + VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_riscv_cpu = { .name = "cpu", .version_id = 3, @@ -218,6 +237,7 @@ const VMStateDescription vmstate_riscv_cpu = { &vmstate_hyper, &vmstate_vector, &vmstate_pointermasking, + &vmstate_rv128, NULL } }; diff --git a/target/riscv/translate.c b/target/riscv/translate.c index c3b4950ad0..6c400e8452 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -33,7 +33,7 @@ #include "internals.h" /* global register indices */ -static TCGv cpu_gpr[32], cpu_pc, cpu_vl, cpu_vstart; +static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart; static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */ static TCGv load_res; static TCGv load_val; @@ -858,10 +858,13 @@ void riscv_translate_init(void) * unless you specifically block reads/writes to reg 0. */ cpu_gpr[0] = NULL; + cpu_gprh[0] = NULL; for (i = 1; i < 32; i++) { cpu_gpr[i] = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]); + cpu_gprh[i] = tcg_global_mem_new(cpu_env, + offsetof(CPURISCVState, gprh[i]), riscv_int_regnamesh[i]); } for (i = 0; i < 32; i++) { From 332dab68785bba0381790fef94f4f433e8e806ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:00:57 +0100 Subject: [PATCH 305/730] target/riscv: setup everything for rv64 to support rv128 execution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds the support of the '-cpu rv128' option to qemu-system-riscv64 so that we can indicate that we want to run rv128 executables. Still, there is no support for 128-bit insns at that stage so qemu fails miserably (as expected) if launched with this option. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-8-frederic.petrot@univ-grenoble-alpes.fr [ Changed by AF - Rename CPU to "x-rv128" ] Signed-off-by: Alistair Francis --- disas/riscv.c | 5 +++++ include/disas/dis-asm.h | 1 + target/riscv/cpu.c | 20 ++++++++++++++++++++ target/riscv/cpu.h | 1 + target/riscv/gdbstub.c | 5 +++++ 5 files changed, 32 insertions(+) diff --git a/disas/riscv.c b/disas/riscv.c index 793ad14c27..03c8dc9961 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -3090,3 +3090,8 @@ int print_insn_riscv64(bfd_vma memaddr, struct disassemble_info *info) { return print_insn_riscv(memaddr, info, rv64); } + +int print_insn_riscv128(bfd_vma memaddr, struct disassemble_info *info) +{ + return print_insn_riscv(memaddr, info, rv128); +} diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h index 08e1beec85..102a1e7f50 100644 --- a/include/disas/dis-asm.h +++ b/include/disas/dis-asm.h @@ -459,6 +459,7 @@ int print_insn_nios2(bfd_vma, disassemble_info*); int print_insn_xtensa (bfd_vma, disassemble_info*); int print_insn_riscv32 (bfd_vma, disassemble_info*); int print_insn_riscv64 (bfd_vma, disassemble_info*); +int print_insn_riscv128 (bfd_vma, disassemble_info*); int print_insn_rx(bfd_vma, disassemble_info *); int print_insn_hexagon(bfd_vma, disassemble_info *); diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 1bd4a7c7aa..9bc25d3055 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -178,6 +178,19 @@ static void rv64_sifive_e_cpu_init(Object *obj) set_priv_version(env, PRIV_VERSION_1_10_0); qdev_prop_set_bit(DEVICE(obj), "mmu", false); } + +static void rv128_base_cpu_init(Object *obj) +{ + if (qemu_tcg_mttcg_enabled()) { + /* Missing 128-bit aligned atomics */ + error_report("128-bit RISC-V currently does not work with Multi " + "Threaded TCG. Please use: -accel tcg,thread=single"); + exit(EXIT_FAILURE); + } + CPURISCVState *env = &RISCV_CPU(obj)->env; + /* We set this in the realise function */ + set_misa(env, MXL_RV128, 0); +} #else static void rv32_base_cpu_init(Object *obj) { @@ -402,6 +415,9 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info) case MXL_RV64: info->print_insn = print_insn_riscv64; break; + case MXL_RV128: + info->print_insn = print_insn_riscv128; + break; default: g_assert_not_reached(); } @@ -464,6 +480,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) #ifdef TARGET_RISCV64 case MXL_RV64: break; + case MXL_RV128: + break; #endif case MXL_RV32: break; @@ -673,6 +691,7 @@ static gchar *riscv_gdb_arch_name(CPUState *cs) case MXL_RV32: return g_strdup("riscv:rv32"); case MXL_RV64: + case MXL_RV128: return g_strdup("riscv:rv64"); default: g_assert_not_reached(); @@ -827,6 +846,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64_sifive_e_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64_sifive_u_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C, rv64_sifive_u_cpu_init), + DEFINE_CPU(TYPE_RISCV_CPU_BASE128, rv128_base_cpu_init), #endif }; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index fa5d238530..fd583e0f41 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -38,6 +38,7 @@ #define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any") #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") +#define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c") #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index 881ab33392..a5429b92d4 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -280,6 +280,11 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg) int bitsize = 16 << env->misa_mxl_max; int i; + /* Until gdb knows about 128-bit registers */ + if (bitsize > 64) { + bitsize = 64; + } + g_string_printf(s, ""); g_string_append_printf(s, ""); g_string_append_printf(s, ""); From 76a361066f9a02b4dc587c0c62481f2ef8fbe524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:00:58 +0100 Subject: [PATCH 306/730] target/riscv: moving some insns close to similar insns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lwu and ld are functionally close to the other loads, but were after the stores in the source file. Similarly, xor was away from or and and by two arithmetic functions, while the immediate versions were nicely put together. This patch moves the aforementioned loads after lhu, and xor above or, where they more logically belong. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-9-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvi.c.inc | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 51607b3d40..710f5e6a85 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -176,6 +176,18 @@ static bool trans_lhu(DisasContext *ctx, arg_lhu *a) return gen_load(ctx, a, MO_TEUW); } +static bool trans_lwu(DisasContext *ctx, arg_lwu *a) +{ + REQUIRE_64BIT(ctx); + return gen_load(ctx, a, MO_TEUL); +} + +static bool trans_ld(DisasContext *ctx, arg_ld *a) +{ + REQUIRE_64BIT(ctx); + return gen_load(ctx, a, MO_TEUQ); +} + static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop) { TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE); @@ -207,18 +219,6 @@ static bool trans_sw(DisasContext *ctx, arg_sw *a) return gen_store(ctx, a, MO_TESL); } -static bool trans_lwu(DisasContext *ctx, arg_lwu *a) -{ - REQUIRE_64BIT(ctx); - return gen_load(ctx, a, MO_TEUL); -} - -static bool trans_ld(DisasContext *ctx, arg_ld *a) -{ - REQUIRE_64BIT(ctx); - return gen_load(ctx, a, MO_TEUQ); -} - static bool trans_sd(DisasContext *ctx, arg_sd *a) { REQUIRE_64BIT(ctx); @@ -317,11 +317,6 @@ static bool trans_sltu(DisasContext *ctx, arg_sltu *a) return gen_arith(ctx, a, EXT_SIGN, gen_sltu); } -static bool trans_xor(DisasContext *ctx, arg_xor *a) -{ - return gen_logic(ctx, a, tcg_gen_xor_tl); -} - static bool trans_srl(DisasContext *ctx, arg_srl *a) { return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl); @@ -332,6 +327,11 @@ static bool trans_sra(DisasContext *ctx, arg_sra *a) return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl); } +static bool trans_xor(DisasContext *ctx, arg_xor *a) +{ + return gen_logic(ctx, a, tcg_gen_xor_tl); +} + static bool trans_or(DisasContext *ctx, arg_or *a) { return gen_logic(ctx, a, tcg_gen_or_tl); From a2f827ff4f4486b8aa8fce180452463ec2b62f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:00:59 +0100 Subject: [PATCH 307/730] target/riscv: accessors to registers upper part and 128-bit load/store MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get function to retrieve the 64 top bits of a register, stored in the gprh field of the cpu state. Set function that writes the 128-bit value at once. The access to the gprh field can not be protected at compile time to make sure it is accessed only in the 128-bit version of the processor because we have no way to indicate that the misa_mxl_max field is const. The 128-bit ISA adds ldu, lq and sq. We provide support for these instructions. Note that (a) we compute only 64-bit addresses to actually access memory, cowardly utilizing the existing address translation mechanism of QEMU, and (b) we assume for now little-endian memory accesses. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-10-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/insn16.decode | 27 ++++++- target/riscv/insn32.decode | 5 ++ target/riscv/insn_trans/trans_rvi.c.inc | 100 ++++++++++++++++++++++-- target/riscv/translate.c | 41 ++++++++++ 4 files changed, 163 insertions(+), 10 deletions(-) diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode index 2e9212663c..02c8f61b48 100644 --- a/target/riscv/insn16.decode +++ b/target/riscv/insn16.decode @@ -25,14 +25,17 @@ # Immediates: %imm_ci 12:s1 2:5 %nzuimm_ciw 7:4 11:2 5:1 6:1 !function=ex_shift_2 +%uimm_cl_q 10:1 5:2 11:2 !function=ex_shift_4 %uimm_cl_d 5:2 10:3 !function=ex_shift_3 %uimm_cl_w 5:1 10:3 6:1 !function=ex_shift_2 %imm_cb 12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1 %imm_cj 12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1 %shimm_6bit 12:1 2:5 !function=ex_rvc_shifti +%uimm_6bit_lq 2:4 12:1 6:1 !function=ex_shift_4 %uimm_6bit_ld 2:3 12:1 5:2 !function=ex_shift_3 %uimm_6bit_lw 2:2 12:1 4:3 !function=ex_shift_2 +%uimm_6bit_sq 7:4 11:2 !function=ex_shift_4 %uimm_6bit_sd 7:3 10:3 !function=ex_shift_3 %uimm_6bit_sw 7:2 9:4 !function=ex_shift_2 @@ -54,16 +57,20 @@ # Formats 16: @cr .... ..... ..... .. &r rs2=%rs2_5 rs1=%rd %rd @ci ... . ..... ..... .. &i imm=%imm_ci rs1=%rd %rd +@cl_q ... . ..... ..... .. &i imm=%uimm_cl_q rs1=%rs1_3 rd=%rs2_3 @cl_d ... ... ... .. ... .. &i imm=%uimm_cl_d rs1=%rs1_3 rd=%rs2_3 @cl_w ... ... ... .. ... .. &i imm=%uimm_cl_w rs1=%rs1_3 rd=%rs2_3 @cs_2 ... ... ... .. ... .. &r rs2=%rs2_3 rs1=%rs1_3 rd=%rs1_3 +@cs_q ... ... ... .. ... .. &s imm=%uimm_cl_q rs1=%rs1_3 rs2=%rs2_3 @cs_d ... ... ... .. ... .. &s imm=%uimm_cl_d rs1=%rs1_3 rs2=%rs2_3 @cs_w ... ... ... .. ... .. &s imm=%uimm_cl_w rs1=%rs1_3 rs2=%rs2_3 @cj ... ........... .. &j imm=%imm_cj @cb_z ... ... ... .. ... .. &b imm=%imm_cb rs1=%rs1_3 rs2=0 +@c_lqsp ... . ..... ..... .. &i imm=%uimm_6bit_lq rs1=2 %rd @c_ldsp ... . ..... ..... .. &i imm=%uimm_6bit_ld rs1=2 %rd @c_lwsp ... . ..... ..... .. &i imm=%uimm_6bit_lw rs1=2 %rd +@c_sqsp ... . ..... ..... .. &s imm=%uimm_6bit_sq rs1=2 rs2=%rs2_5 @c_sdsp ... . ..... ..... .. &s imm=%uimm_6bit_sd rs1=2 rs2=%rs2_5 @c_swsp ... . ..... ..... .. &s imm=%uimm_6bit_sw rs1=2 rs2=%rs2_5 @c_li ... . ..... ..... .. &i imm=%imm_ci rs1=0 %rd @@ -87,9 +94,15 @@ illegal 000 000 000 00 --- 00 addi 000 ... ... .. ... 00 @c_addi4spn } -fld 001 ... ... .. ... 00 @cl_d +{ + lq 001 ... ... .. ... 00 @cl_q + fld 001 ... ... .. ... 00 @cl_d +} lw 010 ... ... .. ... 00 @cl_w -fsd 101 ... ... .. ... 00 @cs_d +{ + sq 101 ... ... .. ... 00 @cs_q + fsd 101 ... ... .. ... 00 @cs_d +} sw 110 ... ... .. ... 00 @cs_w # *** RV32C and RV64C specific Standard Extension (Quadrant 0) *** @@ -132,7 +145,10 @@ addw 100 1 11 ... 01 ... 01 @cs_2 # *** RV32/64C Standard Extension (Quadrant 2) *** slli 000 . ..... ..... 10 @c_shift2 -fld 001 . ..... ..... 10 @c_ldsp +{ + lq 001 ... ... .. ... 10 @c_lqsp + fld 001 . ..... ..... 10 @c_ldsp +} { illegal 010 - 00000 ----- 10 # c.lwsp, RES rd=0 lw 010 . ..... ..... 10 @c_lwsp @@ -147,7 +163,10 @@ fld 001 . ..... ..... 10 @c_ldsp jalr 100 1 ..... 00000 10 @c_jalr rd=1 # C.JALR add 100 1 ..... ..... 10 @cr } -fsd 101 ...... ..... 10 @c_sdsp +{ + sq 101 ... ... .. ... 10 @c_sqsp + fsd 101 ...... ..... 10 @c_sdsp +} sw 110 . ..... ..... 10 @c_swsp # *** RV32C and RV64C specific Standard Extension (Quadrant 2) *** diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 8617307b29..ddbf0da03c 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -162,6 +162,11 @@ sllw 0000000 ..... ..... 001 ..... 0111011 @r srlw 0000000 ..... ..... 101 ..... 0111011 @r sraw 0100000 ..... ..... 101 ..... 0111011 @r +# *** RV128I Base Instruction Set (in addition to RV64I) *** +ldu ............ ..... 111 ..... 0000011 @i +lq ............ ..... 010 ..... 0001111 @i +sq ............ ..... 100 ..... 0100011 @s + # *** RV32M Standard Extension *** mul 0000001 ..... ..... 000 ..... 0110011 @r mulh 0000001 ..... ..... 001 ..... 0110011 @r diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 710f5e6a85..e572976e88 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -134,7 +134,7 @@ static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a) return gen_branch(ctx, a, TCG_COND_GEU); } -static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop) +static bool gen_load_tl(DisasContext *ctx, arg_lb *a, MemOp memop) { TCGv dest = dest_gpr(ctx, a->rd); TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE); @@ -151,6 +151,45 @@ static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop) return true; } +/* Compute only 64-bit addresses to use the address translation mechanism */ +static bool gen_load_i128(DisasContext *ctx, arg_lb *a, MemOp memop) +{ + TCGv src1l = get_gpr(ctx, a->rs1, EXT_NONE); + TCGv destl = dest_gpr(ctx, a->rd); + TCGv desth = dest_gprh(ctx, a->rd); + TCGv addrl = tcg_temp_new(); + + tcg_gen_addi_tl(addrl, src1l, a->imm); + + if ((memop & MO_SIZE) <= MO_64) { + tcg_gen_qemu_ld_tl(destl, addrl, ctx->mem_idx, memop); + if (memop & MO_SIGN) { + tcg_gen_sari_tl(desth, destl, 63); + } else { + tcg_gen_movi_tl(desth, 0); + } + } else { + /* assume little-endian memory access for now */ + tcg_gen_qemu_ld_tl(destl, addrl, ctx->mem_idx, MO_TEUQ); + tcg_gen_addi_tl(addrl, addrl, 8); + tcg_gen_qemu_ld_tl(desth, addrl, ctx->mem_idx, MO_TEUQ); + } + + gen_set_gpr128(ctx, a->rd, destl, desth); + + tcg_temp_free(addrl); + return true; +} + +static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop) +{ + if (get_xl(ctx) == MXL_RV128) { + return gen_load_i128(ctx, a, memop); + } else { + return gen_load_tl(ctx, a, memop); + } +} + static bool trans_lb(DisasContext *ctx, arg_lb *a) { return gen_load(ctx, a, MO_SB); @@ -166,6 +205,18 @@ static bool trans_lw(DisasContext *ctx, arg_lw *a) return gen_load(ctx, a, MO_TESL); } +static bool trans_ld(DisasContext *ctx, arg_ld *a) +{ + REQUIRE_64_OR_128BIT(ctx); + return gen_load(ctx, a, MO_TESQ); +} + +static bool trans_lq(DisasContext *ctx, arg_lq *a) +{ + REQUIRE_128BIT(ctx); + return gen_load(ctx, a, MO_TEUO); +} + static bool trans_lbu(DisasContext *ctx, arg_lbu *a) { return gen_load(ctx, a, MO_UB); @@ -178,17 +229,17 @@ static bool trans_lhu(DisasContext *ctx, arg_lhu *a) static bool trans_lwu(DisasContext *ctx, arg_lwu *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); return gen_load(ctx, a, MO_TEUL); } -static bool trans_ld(DisasContext *ctx, arg_ld *a) +static bool trans_ldu(DisasContext *ctx, arg_ldu *a) { - REQUIRE_64BIT(ctx); + REQUIRE_128BIT(ctx); return gen_load(ctx, a, MO_TEUQ); } -static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop) +static bool gen_store_tl(DisasContext *ctx, arg_sb *a, MemOp memop) { TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE); TCGv data = get_gpr(ctx, a->rs2, EXT_NONE); @@ -204,6 +255,37 @@ static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop) return true; } +static bool gen_store_i128(DisasContext *ctx, arg_sb *a, MemOp memop) +{ + TCGv src1l = get_gpr(ctx, a->rs1, EXT_NONE); + TCGv src2l = get_gpr(ctx, a->rs2, EXT_NONE); + TCGv src2h = get_gprh(ctx, a->rs2); + TCGv addrl = tcg_temp_new(); + + tcg_gen_addi_tl(addrl, src1l, a->imm); + + if ((memop & MO_SIZE) <= MO_64) { + tcg_gen_qemu_st_tl(src2l, addrl, ctx->mem_idx, memop); + } else { + /* little-endian memory access assumed for now */ + tcg_gen_qemu_st_tl(src2l, addrl, ctx->mem_idx, MO_TEUQ); + tcg_gen_addi_tl(addrl, addrl, 8); + tcg_gen_qemu_st_tl(src2h, addrl, ctx->mem_idx, MO_TEUQ); + } + + tcg_temp_free(addrl); + return true; +} + +static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop) +{ + if (get_xl(ctx) == MXL_RV128) { + return gen_store_i128(ctx, a, memop); + } else { + return gen_store_tl(ctx, a, memop); + } +} + static bool trans_sb(DisasContext *ctx, arg_sb *a) { return gen_store(ctx, a, MO_SB); @@ -221,10 +303,16 @@ static bool trans_sw(DisasContext *ctx, arg_sw *a) static bool trans_sd(DisasContext *ctx, arg_sd *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); return gen_store(ctx, a, MO_TEUQ); } +static bool trans_sq(DisasContext *ctx, arg_sq *a) +{ + REQUIRE_128BIT(ctx); + return gen_store(ctx, a, MO_TEUO); +} + static bool trans_addi(DisasContext *ctx, arg_addi *a) { return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 6c400e8452..d4cf965c9e 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -59,6 +59,7 @@ typedef struct DisasContext { /* pc_succ_insn points to the instruction following base.pc_next */ target_ulong pc_succ_insn; target_ulong priv_ver; + RISCVMXL misa_mxl_max; RISCVMXL xl; uint32_t misa_ext; uint32_t opcode; @@ -141,6 +142,13 @@ static inline int get_olen(DisasContext *ctx) return 16 << get_ol(ctx); } +/* The maximum register length */ +#ifdef TARGET_RISCV32 +#define get_xl_max(ctx) MXL_RV32 +#else +#define get_xl_max(ctx) ((ctx)->misa_mxl_max) +#endif + /* * RISC-V requires NaN-boxing of narrower width floating point values. * This applies when a 32-bit value is assigned to a 64-bit FP register. @@ -260,6 +268,7 @@ static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext) } break; case MXL_RV64: + case MXL_RV128: break; default: g_assert_not_reached(); @@ -267,6 +276,15 @@ static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext) return cpu_gpr[reg_num]; } +static TCGv get_gprh(DisasContext *ctx, int reg_num) +{ + assert(get_xl(ctx) == MXL_RV128); + if (reg_num == 0) { + return ctx->zero; + } + return cpu_gprh[reg_num]; +} + static TCGv dest_gpr(DisasContext *ctx, int reg_num) { if (reg_num == 0 || get_olen(ctx) < TARGET_LONG_BITS) { @@ -275,6 +293,14 @@ static TCGv dest_gpr(DisasContext *ctx, int reg_num) return cpu_gpr[reg_num]; } +static TCGv dest_gprh(DisasContext *ctx, int reg_num) +{ + if (reg_num == 0) { + return temp_new(ctx); + } + return cpu_gprh[reg_num]; +} + static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t) { if (reg_num != 0) { @@ -283,11 +309,25 @@ static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t) tcg_gen_ext32s_tl(cpu_gpr[reg_num], t); break; case MXL_RV64: + case MXL_RV128: tcg_gen_mov_tl(cpu_gpr[reg_num], t); break; default: g_assert_not_reached(); } + + if (get_xl_max(ctx) == MXL_RV128) { + tcg_gen_sari_tl(cpu_gprh[reg_num], cpu_gpr[reg_num], 63); + } + } +} + +static void gen_set_gpr128(DisasContext *ctx, int reg_num, TCGv rl, TCGv rh) +{ + assert(get_ol(ctx) == MXL_RV128); + if (reg_num != 0) { + tcg_gen_mov_tl(cpu_gpr[reg_num], rl); + tcg_gen_mov_tl(cpu_gprh[reg_num], rh); } } @@ -754,6 +794,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3); ctx->vstart = env->vstart; ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX); + ctx->misa_mxl_max = env->misa_mxl_max; ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL); ctx->cs = cs; ctx->ntemp = 0; From 568f247f69f9297a7a8816f46ce74a265a96ca8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:01:00 +0100 Subject: [PATCH 308/730] target/riscv: support for 128-bit bitwise instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 128-bit bitwise instructions do not need any function prototype change as the functions can be applied independently on the lower and upper part of the registers. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-11-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/translate.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index d4cf965c9e..b43efc9bc3 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -523,7 +523,15 @@ static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a, func(dest, src1, a->imm); - gen_set_gpr(ctx, a->rd, dest); + if (get_xl(ctx) == MXL_RV128) { + TCGv src1h = get_gprh(ctx, a->rs1); + TCGv desth = dest_gprh(ctx, a->rd); + + func(desth, src1h, -(a->imm < 0)); + gen_set_gpr128(ctx, a->rd, dest, desth); + } else { + gen_set_gpr(ctx, a->rd, dest); + } return true; } @@ -537,7 +545,16 @@ static bool gen_logic(DisasContext *ctx, arg_r *a, func(dest, src1, src2); - gen_set_gpr(ctx, a->rd, dest); + if (get_xl(ctx) == MXL_RV128) { + TCGv src1h = get_gprh(ctx, a->rs1); + TCGv src2h = get_gprh(ctx, a->rs2); + TCGv desth = dest_gprh(ctx, a->rd); + + func(desth, src1h, src2h); + gen_set_gpr128(ctx, a->rd, dest, desth); + } else { + gen_set_gpr(ctx, a->rd, dest); + } return true; } From 57c108b86461a050a58b1ca9d31fd6e4af32205c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:01:01 +0100 Subject: [PATCH 309/730] target/riscv: support for 128-bit U-type instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding the 128-bit version of lui and auipc, and introducing to that end a "set register with immediat" function to handle extension on 128 bits. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-12-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvi.c.inc | 8 ++++---- target/riscv/translate.c | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index e572976e88..6113acc669 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -26,14 +26,14 @@ static bool trans_illegal(DisasContext *ctx, arg_empty *a) static bool trans_c64_illegal(DisasContext *ctx, arg_empty *a) { - REQUIRE_64BIT(ctx); - return trans_illegal(ctx, a); + REQUIRE_64_OR_128BIT(ctx); + return trans_illegal(ctx, a); } static bool trans_lui(DisasContext *ctx, arg_lui *a) { if (a->rd != 0) { - tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm); + gen_set_gpri(ctx, a->rd, a->imm); } return true; } @@ -41,7 +41,7 @@ static bool trans_lui(DisasContext *ctx, arg_lui *a) static bool trans_auipc(DisasContext *ctx, arg_auipc *a) { if (a->rd != 0) { - tcg_gen_movi_tl(cpu_gpr[a->rd], a->imm + ctx->base.pc_next); + gen_set_gpri(ctx, a->rd, a->imm + ctx->base.pc_next); } return true; } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index b43efc9bc3..ba1ad1be5f 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -322,6 +322,27 @@ static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t) } } +static void gen_set_gpri(DisasContext *ctx, int reg_num, target_long imm) +{ + if (reg_num != 0) { + switch (get_ol(ctx)) { + case MXL_RV32: + tcg_gen_movi_tl(cpu_gpr[reg_num], (int32_t)imm); + break; + case MXL_RV64: + case MXL_RV128: + tcg_gen_movi_tl(cpu_gpr[reg_num], imm); + break; + default: + g_assert_not_reached(); + } + + if (get_xl_max(ctx) == MXL_RV128) { + tcg_gen_movi_tl(cpu_gprh[reg_num], -(imm < 0)); + } + } +} + static void gen_set_gpr128(DisasContext *ctx, int reg_num, TCGv rl, TCGv rh) { assert(get_ol(ctx) == MXL_RV128); From 6bf4bbed205127f3805e960a1213c2289db89114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:01:02 +0100 Subject: [PATCH 310/730] target/riscv: support for 128-bit shift instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Handling shifts for 32, 64 and 128 operation length for RV128, following the general framework for handling various olens proposed by Richard. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-13-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 10 ++ target/riscv/insn_trans/trans_rvb.c.inc | 22 +-- target/riscv/insn_trans/trans_rvi.c.inc | 224 ++++++++++++++++++++++-- target/riscv/translate.c | 58 ++++-- 4 files changed, 270 insertions(+), 44 deletions(-) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index ddbf0da03c..a992c6d369 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -22,6 +22,7 @@ %rs1 15:5 %rd 7:5 %sh5 20:5 +%sh6 20:6 %sh7 20:7 %csr 20:12 @@ -91,6 +92,9 @@ # Formats 64: @sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd +# Formats 128: +@sh6 ...... ...... ..... ... ..... ....... &shift shamt=%sh6 %rs1 %rd + # *** Privileged Instructions *** ecall 000000000000 00000 000 00000 1110011 ebreak 000000000001 00000 000 00000 1110011 @@ -166,6 +170,12 @@ sraw 0100000 ..... ..... 101 ..... 0111011 @r ldu ............ ..... 111 ..... 0000011 @i lq ............ ..... 010 ..... 0001111 @i sq ............ ..... 100 ..... 0100011 @s +sllid 000000 ...... ..... 001 ..... 1011011 @sh6 +srlid 000000 ...... ..... 101 ..... 1011011 @sh6 +sraid 010000 ...... ..... 101 ..... 1011011 @sh6 +slld 0000000 ..... ..... 001 ..... 1111011 @r +srld 0000000 ..... ..... 101 ..... 1111011 @r +srad 0100000 ..... ..... 101 ..... 1111011 @r # *** RV32M Standard Extension *** mul 0000001 ..... ..... 000 ..... 0110011 @r diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index de2cd613b1..ad6548320f 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -156,7 +156,7 @@ static void gen_bset(TCGv ret, TCGv arg1, TCGv shamt) static bool trans_bset(DisasContext *ctx, arg_bset *a) { REQUIRE_ZBS(ctx); - return gen_shift(ctx, a, EXT_NONE, gen_bset); + return gen_shift(ctx, a, EXT_NONE, gen_bset, NULL); } static bool trans_bseti(DisasContext *ctx, arg_bseti *a) @@ -178,7 +178,7 @@ static void gen_bclr(TCGv ret, TCGv arg1, TCGv shamt) static bool trans_bclr(DisasContext *ctx, arg_bclr *a) { REQUIRE_ZBS(ctx); - return gen_shift(ctx, a, EXT_NONE, gen_bclr); + return gen_shift(ctx, a, EXT_NONE, gen_bclr, NULL); } static bool trans_bclri(DisasContext *ctx, arg_bclri *a) @@ -200,7 +200,7 @@ static void gen_binv(TCGv ret, TCGv arg1, TCGv shamt) static bool trans_binv(DisasContext *ctx, arg_binv *a) { REQUIRE_ZBS(ctx); - return gen_shift(ctx, a, EXT_NONE, gen_binv); + return gen_shift(ctx, a, EXT_NONE, gen_binv, NULL); } static bool trans_binvi(DisasContext *ctx, arg_binvi *a) @@ -218,7 +218,7 @@ static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt) static bool trans_bext(DisasContext *ctx, arg_bext *a) { REQUIRE_ZBS(ctx); - return gen_shift(ctx, a, EXT_NONE, gen_bext); + return gen_shift(ctx, a, EXT_NONE, gen_bext, NULL); } static bool trans_bexti(DisasContext *ctx, arg_bexti *a) @@ -248,7 +248,7 @@ static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2) static bool trans_ror(DisasContext *ctx, arg_ror *a) { REQUIRE_ZBB(ctx); - return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotr_tl, gen_rorw); + return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotr_tl, gen_rorw, NULL); } static void gen_roriw(TCGv ret, TCGv arg1, target_long shamt) @@ -266,7 +266,7 @@ static bool trans_rori(DisasContext *ctx, arg_rori *a) { REQUIRE_ZBB(ctx); return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE, - tcg_gen_rotri_tl, gen_roriw); + tcg_gen_rotri_tl, gen_roriw, NULL); } static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2) @@ -290,7 +290,7 @@ static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2) static bool trans_rol(DisasContext *ctx, arg_rol *a) { REQUIRE_ZBB(ctx); - return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotl_tl, gen_rolw); + return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotl_tl, gen_rolw, NULL); } static void gen_rev8_32(TCGv ret, TCGv src1) @@ -405,7 +405,7 @@ static bool trans_rorw(DisasContext *ctx, arg_rorw *a) REQUIRE_64BIT(ctx); REQUIRE_ZBB(ctx); ctx->ol = MXL_RV32; - return gen_shift(ctx, a, EXT_NONE, gen_rorw); + return gen_shift(ctx, a, EXT_NONE, gen_rorw, NULL); } static bool trans_roriw(DisasContext *ctx, arg_roriw *a) @@ -413,7 +413,7 @@ static bool trans_roriw(DisasContext *ctx, arg_roriw *a) REQUIRE_64BIT(ctx); REQUIRE_ZBB(ctx); ctx->ol = MXL_RV32; - return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_roriw); + return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_roriw, NULL); } static bool trans_rolw(DisasContext *ctx, arg_rolw *a) @@ -421,7 +421,7 @@ static bool trans_rolw(DisasContext *ctx, arg_rolw *a) REQUIRE_64BIT(ctx); REQUIRE_ZBB(ctx); ctx->ol = MXL_RV32; - return gen_shift(ctx, a, EXT_NONE, gen_rolw); + return gen_shift(ctx, a, EXT_NONE, gen_rolw, NULL); } #define GEN_SHADD_UW(SHAMT) \ @@ -478,7 +478,7 @@ static bool trans_slli_uw(DisasContext *ctx, arg_slli_uw *a) { REQUIRE_64BIT(ctx); REQUIRE_ZBA(ctx); - return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_slli_uw); + return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_slli_uw, NULL); } static bool trans_clmul(DisasContext *ctx, arg_clmul *a) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 6113acc669..2e3a6c6041 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -353,9 +353,22 @@ static bool trans_andi(DisasContext *ctx, arg_andi *a) return gen_logic_imm_fn(ctx, a, tcg_gen_andi_tl); } +static void gen_slli_i128(TCGv retl, TCGv reth, + TCGv src1l, TCGv src1h, + target_long shamt) +{ + if (shamt >= 64) { + tcg_gen_shli_tl(reth, src1l, shamt - 64); + tcg_gen_movi_tl(retl, 0); + } else { + tcg_gen_extract2_tl(reth, src1l, src1h, 64 - shamt); + tcg_gen_shli_tl(retl, src1l, shamt); + } +} + static bool trans_slli(DisasContext *ctx, arg_slli *a) { - return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl); + return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl, gen_slli_i128); } static void gen_srliw(TCGv dst, TCGv src, target_long shamt) @@ -363,10 +376,23 @@ static void gen_srliw(TCGv dst, TCGv src, target_long shamt) tcg_gen_extract_tl(dst, src, shamt, 32 - shamt); } +static void gen_srli_i128(TCGv retl, TCGv reth, + TCGv src1l, TCGv src1h, + target_long shamt) +{ + if (shamt >= 64) { + tcg_gen_shri_tl(retl, src1h, shamt - 64); + tcg_gen_movi_tl(reth, 0); + } else { + tcg_gen_extract2_tl(retl, src1l, src1h, shamt); + tcg_gen_shri_tl(reth, src1h, shamt); + } +} + static bool trans_srli(DisasContext *ctx, arg_srli *a) { return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE, - tcg_gen_shri_tl, gen_srliw); + tcg_gen_shri_tl, gen_srliw, gen_srli_i128); } static void gen_sraiw(TCGv dst, TCGv src, target_long shamt) @@ -374,10 +400,23 @@ static void gen_sraiw(TCGv dst, TCGv src, target_long shamt) tcg_gen_sextract_tl(dst, src, shamt, 32 - shamt); } +static void gen_srai_i128(TCGv retl, TCGv reth, + TCGv src1l, TCGv src1h, + target_long shamt) +{ + if (shamt >= 64) { + tcg_gen_sari_tl(retl, src1h, shamt - 64); + tcg_gen_sari_tl(reth, src1h, 63); + } else { + tcg_gen_extract2_tl(retl, src1l, src1h, shamt); + tcg_gen_sari_tl(reth, src1h, shamt); + } +} + static bool trans_srai(DisasContext *ctx, arg_srai *a) { return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE, - tcg_gen_sari_tl, gen_sraiw); + tcg_gen_sari_tl, gen_sraiw, gen_srai_i128); } static bool trans_add(DisasContext *ctx, arg_add *a) @@ -390,9 +429,44 @@ static bool trans_sub(DisasContext *ctx, arg_sub *a) return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl); } +static void gen_sll_i128(TCGv destl, TCGv desth, + TCGv src1l, TCGv src1h, TCGv shamt) +{ + TCGv ls = tcg_temp_new(); + TCGv rs = tcg_temp_new(); + TCGv hs = tcg_temp_new(); + TCGv ll = tcg_temp_new(); + TCGv lr = tcg_temp_new(); + TCGv h0 = tcg_temp_new(); + TCGv h1 = tcg_temp_new(); + TCGv zero = tcg_constant_tl(0); + + tcg_gen_andi_tl(hs, shamt, 64); + tcg_gen_andi_tl(ls, shamt, 63); + tcg_gen_neg_tl(shamt, shamt); + tcg_gen_andi_tl(rs, shamt, 63); + + tcg_gen_shl_tl(ll, src1l, ls); + tcg_gen_shl_tl(h0, src1h, ls); + tcg_gen_shr_tl(lr, src1l, rs); + tcg_gen_movcond_tl(TCG_COND_NE, lr, shamt, zero, lr, zero); + tcg_gen_or_tl(h1, h0, lr); + + tcg_gen_movcond_tl(TCG_COND_NE, destl, hs, zero, zero, ll); + tcg_gen_movcond_tl(TCG_COND_NE, desth, hs, zero, ll, h1); + + tcg_temp_free(ls); + tcg_temp_free(rs); + tcg_temp_free(hs); + tcg_temp_free(ll); + tcg_temp_free(lr); + tcg_temp_free(h0); + tcg_temp_free(h1); +} + static bool trans_sll(DisasContext *ctx, arg_sll *a) { - return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl); + return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl, gen_sll_i128); } static bool trans_slt(DisasContext *ctx, arg_slt *a) @@ -405,14 +479,85 @@ static bool trans_sltu(DisasContext *ctx, arg_sltu *a) return gen_arith(ctx, a, EXT_SIGN, gen_sltu); } +static void gen_srl_i128(TCGv destl, TCGv desth, + TCGv src1l, TCGv src1h, TCGv shamt) +{ + TCGv ls = tcg_temp_new(); + TCGv rs = tcg_temp_new(); + TCGv hs = tcg_temp_new(); + TCGv ll = tcg_temp_new(); + TCGv lr = tcg_temp_new(); + TCGv h0 = tcg_temp_new(); + TCGv h1 = tcg_temp_new(); + TCGv zero = tcg_constant_tl(0); + + tcg_gen_andi_tl(hs, shamt, 64); + tcg_gen_andi_tl(rs, shamt, 63); + tcg_gen_neg_tl(shamt, shamt); + tcg_gen_andi_tl(ls, shamt, 63); + + tcg_gen_shr_tl(lr, src1l, rs); + tcg_gen_shr_tl(h1, src1h, rs); + tcg_gen_shl_tl(ll, src1h, ls); + tcg_gen_movcond_tl(TCG_COND_NE, ll, shamt, zero, ll, zero); + tcg_gen_or_tl(h0, ll, lr); + + tcg_gen_movcond_tl(TCG_COND_NE, destl, hs, zero, h1, h0); + tcg_gen_movcond_tl(TCG_COND_NE, desth, hs, zero, zero, h1); + + tcg_temp_free(ls); + tcg_temp_free(rs); + tcg_temp_free(hs); + tcg_temp_free(ll); + tcg_temp_free(lr); + tcg_temp_free(h0); + tcg_temp_free(h1); +} + static bool trans_srl(DisasContext *ctx, arg_srl *a) { - return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl); + return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl, gen_srl_i128); +} + +static void gen_sra_i128(TCGv destl, TCGv desth, + TCGv src1l, TCGv src1h, TCGv shamt) +{ + TCGv ls = tcg_temp_new(); + TCGv rs = tcg_temp_new(); + TCGv hs = tcg_temp_new(); + TCGv ll = tcg_temp_new(); + TCGv lr = tcg_temp_new(); + TCGv h0 = tcg_temp_new(); + TCGv h1 = tcg_temp_new(); + TCGv zero = tcg_constant_tl(0); + + tcg_gen_andi_tl(hs, shamt, 64); + tcg_gen_andi_tl(rs, shamt, 63); + tcg_gen_neg_tl(shamt, shamt); + tcg_gen_andi_tl(ls, shamt, 63); + + tcg_gen_shr_tl(lr, src1l, rs); + tcg_gen_sar_tl(h1, src1h, rs); + tcg_gen_shl_tl(ll, src1h, ls); + tcg_gen_movcond_tl(TCG_COND_NE, ll, shamt, zero, ll, zero); + tcg_gen_or_tl(h0, ll, lr); + tcg_gen_sari_tl(lr, src1h, 63); + + tcg_gen_movcond_tl(TCG_COND_NE, destl, hs, zero, h1, h0); + tcg_gen_movcond_tl(TCG_COND_NE, desth, hs, zero, lr, h1); + + tcg_temp_free(ls); + tcg_temp_free(rs); + tcg_temp_free(hs); + tcg_temp_free(ll); + tcg_temp_free(lr); + tcg_temp_free(h0); + tcg_temp_free(h1); } static bool trans_sra(DisasContext *ctx, arg_sra *a) { - return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl); + return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl, gen_sra_i128); } static bool trans_xor(DisasContext *ctx, arg_xor *a) @@ -439,23 +584,44 @@ static bool trans_addiw(DisasContext *ctx, arg_addiw *a) static bool trans_slliw(DisasContext *ctx, arg_slliw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); ctx->ol = MXL_RV32; - return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl); + return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl, NULL); } static bool trans_srliw(DisasContext *ctx, arg_srliw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); ctx->ol = MXL_RV32; - return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_srliw); + return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_srliw, NULL); } static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); ctx->ol = MXL_RV32; - return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_sraiw); + return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_sraiw, NULL); +} + +static bool trans_sllid(DisasContext *ctx, arg_sllid *a) +{ + REQUIRE_128BIT(ctx); + ctx->ol = MXL_RV64; + return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl, NULL); +} + +static bool trans_srlid(DisasContext *ctx, arg_srlid *a) +{ + REQUIRE_128BIT(ctx); + ctx->ol = MXL_RV64; + return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shri_tl, NULL); +} + +static bool trans_sraid(DisasContext *ctx, arg_sraid *a) +{ + REQUIRE_128BIT(ctx); + ctx->ol = MXL_RV64; + return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_sari_tl, NULL); } static bool trans_addw(DisasContext *ctx, arg_addw *a) @@ -474,25 +640,47 @@ static bool trans_subw(DisasContext *ctx, arg_subw *a) static bool trans_sllw(DisasContext *ctx, arg_sllw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); ctx->ol = MXL_RV32; - return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl); + return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl, NULL); } static bool trans_srlw(DisasContext *ctx, arg_srlw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); ctx->ol = MXL_RV32; - return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl); + return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl, NULL); } static bool trans_sraw(DisasContext *ctx, arg_sraw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); ctx->ol = MXL_RV32; - return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl); + return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl, NULL); } +static bool trans_slld(DisasContext *ctx, arg_slld *a) +{ + REQUIRE_128BIT(ctx); + ctx->ol = MXL_RV64; + return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl, NULL); +} + +static bool trans_srld(DisasContext *ctx, arg_srld *a) +{ + REQUIRE_128BIT(ctx); + ctx->ol = MXL_RV64; + return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl, NULL); +} + +static bool trans_srad(DisasContext *ctx, arg_srad *a) +{ + REQUIRE_128BIT(ctx); + ctx->ol = MXL_RV64; + return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl, NULL); +} + + static bool trans_fence(DisasContext *ctx, arg_fence *a) { /* FENCE is a full memory barrier. */ diff --git a/target/riscv/translate.c b/target/riscv/translate.c index ba1ad1be5f..89220a5fae 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -635,7 +635,8 @@ static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext, } static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext, - void (*func)(TCGv, TCGv, target_long)) + void (*func)(TCGv, TCGv, target_long), + void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long)) { TCGv dest, src1; int max_len = get_olen(ctx); @@ -647,26 +648,38 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext, dest = dest_gpr(ctx, a->rd); src1 = get_gpr(ctx, a->rs1, ext); - func(dest, src1, a->shamt); + if (max_len < 128) { + func(dest, src1, a->shamt); + gen_set_gpr(ctx, a->rd, dest); + } else { + TCGv src1h = get_gprh(ctx, a->rs1); + TCGv desth = dest_gprh(ctx, a->rd); - gen_set_gpr(ctx, a->rd, dest); + if (f128 == NULL) { + return false; + } + f128(dest, desth, src1, src1h, a->shamt); + gen_set_gpr128(ctx, a->rd, dest, desth); + } return true; } static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a, DisasExtend ext, void (*f_tl)(TCGv, TCGv, target_long), - void (*f_32)(TCGv, TCGv, target_long)) + void (*f_32)(TCGv, TCGv, target_long), + void (*f_128)(TCGv, TCGv, TCGv, TCGv, + target_long)) { int olen = get_olen(ctx); if (olen != TARGET_LONG_BITS) { if (olen == 32) { f_tl = f_32; - } else { + } else if (olen != 128) { g_assert_not_reached(); } } - return gen_shift_imm_fn(ctx, a, ext, f_tl); + return gen_shift_imm_fn(ctx, a, ext, f_tl, f_128); } static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext, @@ -690,34 +703,49 @@ static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext, } static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext, - void (*func)(TCGv, TCGv, TCGv)) + void (*func)(TCGv, TCGv, TCGv), + void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv)) { - TCGv dest = dest_gpr(ctx, a->rd); - TCGv src1 = get_gpr(ctx, a->rs1, ext); TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); TCGv ext2 = tcg_temp_new(); + int max_len = get_olen(ctx); - tcg_gen_andi_tl(ext2, src2, get_olen(ctx) - 1); - func(dest, src1, ext2); + tcg_gen_andi_tl(ext2, src2, max_len - 1); - gen_set_gpr(ctx, a->rd, dest); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); + + if (max_len < 128) { + func(dest, src1, ext2); + gen_set_gpr(ctx, a->rd, dest); + } else { + TCGv src1h = get_gprh(ctx, a->rs1); + TCGv desth = dest_gprh(ctx, a->rd); + + if (f128 == NULL) { + return false; + } + f128(dest, desth, src1, src1h, ext2); + gen_set_gpr128(ctx, a->rd, dest, desth); + } tcg_temp_free(ext2); return true; } static bool gen_shift_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext, void (*f_tl)(TCGv, TCGv, TCGv), - void (*f_32)(TCGv, TCGv, TCGv)) + void (*f_32)(TCGv, TCGv, TCGv), + void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv)) { int olen = get_olen(ctx); if (olen != TARGET_LONG_BITS) { if (olen == 32) { f_tl = f_32; - } else { + } else if (olen != 128) { g_assert_not_reached(); } } - return gen_shift(ctx, a, ext, f_tl); + return gen_shift(ctx, a, ext, f_tl, f_128); } static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext, From 7fd40f8679ceed388d82902e9be05ae136cf09cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:01:03 +0100 Subject: [PATCH 311/730] target/riscv: support for 128-bit arithmetic instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addition of 128-bit adds and subs in their various sizes, "set if less than"s and branches. Refactored the code to have a comparison function used for both stls and branches. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-14-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 3 + target/riscv/insn_trans/trans_rvb.c.inc | 20 +-- target/riscv/insn_trans/trans_rvi.c.inc | 159 +++++++++++++++++++++--- target/riscv/insn_trans/trans_rvm.c.inc | 26 ++-- target/riscv/translate.c | 63 ++++++++-- 5 files changed, 222 insertions(+), 49 deletions(-) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index a992c6d369..42366d20fb 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -170,9 +170,12 @@ sraw 0100000 ..... ..... 101 ..... 0111011 @r ldu ............ ..... 111 ..... 0000011 @i lq ............ ..... 010 ..... 0001111 @i sq ............ ..... 100 ..... 0100011 @s +addid ............ ..... 000 ..... 1011011 @i sllid 000000 ...... ..... 001 ..... 1011011 @sh6 srlid 000000 ...... ..... 101 ..... 1011011 @sh6 sraid 010000 ...... ..... 101 ..... 1011011 @sh6 +addd 0000000 ..... ..... 000 ..... 1111011 @r +subd 0100000 ..... ..... 000 ..... 1111011 @r slld 0000000 ..... ..... 001 ..... 1111011 @r srld 0000000 ..... ..... 101 ..... 1111011 @r srad 0100000 ..... ..... 101 ..... 1111011 @r diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index ad6548320f..810431a1d6 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -104,25 +104,25 @@ static bool trans_xnor(DisasContext *ctx, arg_xnor *a) static bool trans_min(DisasContext *ctx, arg_min *a) { REQUIRE_ZBB(ctx); - return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smin_tl); + return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smin_tl, NULL); } static bool trans_max(DisasContext *ctx, arg_max *a) { REQUIRE_ZBB(ctx); - return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smax_tl); + return gen_arith(ctx, a, EXT_SIGN, tcg_gen_smax_tl, NULL); } static bool trans_minu(DisasContext *ctx, arg_minu *a) { REQUIRE_ZBB(ctx); - return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umin_tl); + return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umin_tl, NULL); } static bool trans_maxu(DisasContext *ctx, arg_maxu *a) { REQUIRE_ZBB(ctx); - return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umax_tl); + return gen_arith(ctx, a, EXT_SIGN, tcg_gen_umax_tl, NULL); } static bool trans_sext_b(DisasContext *ctx, arg_sext_b *a) @@ -357,7 +357,7 @@ GEN_SHADD(3) static bool trans_sh##SHAMT##add(DisasContext *ctx, arg_sh##SHAMT##add *a) \ { \ REQUIRE_ZBA(ctx); \ - return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add); \ + return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add, NULL); \ } GEN_TRANS_SHADD(1) @@ -447,7 +447,7 @@ static bool trans_sh##SHAMT##add_uw(DisasContext *ctx, \ { \ REQUIRE_64BIT(ctx); \ REQUIRE_ZBA(ctx); \ - return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add_uw); \ + return gen_arith(ctx, a, EXT_NONE, gen_sh##SHAMT##add_uw, NULL); \ } GEN_TRANS_SHADD_UW(1) @@ -466,7 +466,7 @@ static bool trans_add_uw(DisasContext *ctx, arg_add_uw *a) { REQUIRE_64BIT(ctx); REQUIRE_ZBA(ctx); - return gen_arith(ctx, a, EXT_NONE, gen_add_uw); + return gen_arith(ctx, a, EXT_NONE, gen_add_uw, NULL); } static void gen_slli_uw(TCGv dest, TCGv src, target_long shamt) @@ -484,7 +484,7 @@ static bool trans_slli_uw(DisasContext *ctx, arg_slli_uw *a) static bool trans_clmul(DisasContext *ctx, arg_clmul *a) { REQUIRE_ZBC(ctx); - return gen_arith(ctx, a, EXT_NONE, gen_helper_clmul); + return gen_arith(ctx, a, EXT_NONE, gen_helper_clmul, NULL); } static void gen_clmulh(TCGv dst, TCGv src1, TCGv src2) @@ -496,11 +496,11 @@ static void gen_clmulh(TCGv dst, TCGv src1, TCGv src2) static bool trans_clmulh(DisasContext *ctx, arg_clmulr *a) { REQUIRE_ZBC(ctx); - return gen_arith(ctx, a, EXT_NONE, gen_clmulh); + return gen_arith(ctx, a, EXT_NONE, gen_clmulh, NULL); } static bool trans_clmulr(DisasContext *ctx, arg_clmulh *a) { REQUIRE_ZBC(ctx); - return gen_arith(ctx, a, EXT_NONE, gen_helper_clmulr); + return gen_arith(ctx, a, EXT_NONE, gen_helper_clmulr, NULL); } diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 2e3a6c6041..ca354130ec 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -82,13 +82,103 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a) return true; } +static TCGCond gen_compare_i128(bool bz, TCGv rl, + TCGv al, TCGv ah, TCGv bl, TCGv bh, + TCGCond cond) +{ + TCGv rh = tcg_temp_new(); + bool invert = false; + + switch (cond) { + case TCG_COND_EQ: + case TCG_COND_NE: + if (bz) { + tcg_gen_or_tl(rl, al, ah); + } else { + tcg_gen_xor_tl(rl, al, bl); + tcg_gen_xor_tl(rh, ah, bh); + tcg_gen_or_tl(rl, rl, rh); + } + break; + + case TCG_COND_GE: + case TCG_COND_LT: + if (bz) { + tcg_gen_mov_tl(rl, ah); + } else { + TCGv tmp = tcg_temp_new(); + + tcg_gen_sub2_tl(rl, rh, al, ah, bl, bh); + tcg_gen_xor_tl(rl, rh, ah); + tcg_gen_xor_tl(tmp, ah, bh); + tcg_gen_and_tl(rl, rl, tmp); + tcg_gen_xor_tl(rl, rh, rl); + + tcg_temp_free(tmp); + } + break; + + case TCG_COND_LTU: + invert = true; + /* fallthrough */ + case TCG_COND_GEU: + { + TCGv tmp = tcg_temp_new(); + TCGv zero = tcg_constant_tl(0); + TCGv one = tcg_constant_tl(1); + + cond = TCG_COND_NE; + /* borrow in to second word */ + tcg_gen_setcond_tl(TCG_COND_LTU, tmp, al, bl); + /* seed third word with 1, which will be result */ + tcg_gen_sub2_tl(tmp, rh, ah, one, tmp, zero); + tcg_gen_sub2_tl(tmp, rl, tmp, rh, bh, zero); + + tcg_temp_free(tmp); + } + break; + + default: + g_assert_not_reached(); + } + + if (invert) { + cond = tcg_invert_cond(cond); + } + + tcg_temp_free(rh); + return cond; +} + +static void gen_setcond_i128(TCGv rl, TCGv rh, + TCGv src1l, TCGv src1h, + TCGv src2l, TCGv src2h, + TCGCond cond) +{ + cond = gen_compare_i128(false, rl, src1l, src1h, src2l, src2h, cond); + tcg_gen_setcondi_tl(cond, rl, rl, 0); + tcg_gen_movi_tl(rh, 0); +} + static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond) { TCGLabel *l = gen_new_label(); TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN); TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN); - tcg_gen_brcond_tl(cond, src1, src2, l); + if (get_xl(ctx) == MXL_RV128) { + TCGv src1h = get_gprh(ctx, a->rs1); + TCGv src2h = get_gprh(ctx, a->rs2); + TCGv tmp = tcg_temp_new(); + + cond = gen_compare_i128(a->rs2 == 0, + tmp, src1, src1h, src2, src2h, cond); + tcg_gen_brcondi_tl(cond, tmp, 0, l); + + tcg_temp_free(tmp); + } else { + tcg_gen_brcond_tl(cond, src1, src2, l); + } gen_goto_tb(ctx, 1, ctx->pc_succ_insn); gen_set_label(l); /* branch taken */ @@ -313,9 +403,38 @@ static bool trans_sq(DisasContext *ctx, arg_sq *a) return gen_store(ctx, a, MO_TEUO); } +static bool trans_addd(DisasContext *ctx, arg_addd *a) +{ + REQUIRE_128BIT(ctx); + ctx->ol = MXL_RV64; + return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl, NULL); +} + +static bool trans_addid(DisasContext *ctx, arg_addid *a) +{ + REQUIRE_128BIT(ctx); + ctx->ol = MXL_RV64; + return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl, NULL); +} + +static bool trans_subd(DisasContext *ctx, arg_subd *a) +{ + REQUIRE_128BIT(ctx); + ctx->ol = MXL_RV64; + return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl, NULL); +} + +static void gen_addi2_i128(TCGv retl, TCGv reth, + TCGv srcl, TCGv srch, target_long imm) +{ + TCGv imml = tcg_constant_tl(imm); + TCGv immh = tcg_constant_tl(-(imm < 0)); + tcg_gen_add2_tl(retl, reth, srcl, srch, imml, immh); +} + static bool trans_addi(DisasContext *ctx, arg_addi *a) { - return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl); + return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl, gen_addi2_i128); } static void gen_slt(TCGv ret, TCGv s1, TCGv s2) @@ -323,19 +442,31 @@ static void gen_slt(TCGv ret, TCGv s1, TCGv s2) tcg_gen_setcond_tl(TCG_COND_LT, ret, s1, s2); } +static void gen_slt_i128(TCGv retl, TCGv reth, + TCGv s1l, TCGv s1h, TCGv s2l, TCGv s2h) +{ + gen_setcond_i128(retl, reth, s1l, s1h, s2l, s2h, TCG_COND_LT); +} + static void gen_sltu(TCGv ret, TCGv s1, TCGv s2) { tcg_gen_setcond_tl(TCG_COND_LTU, ret, s1, s2); } +static void gen_sltu_i128(TCGv retl, TCGv reth, + TCGv s1l, TCGv s1h, TCGv s2l, TCGv s2h) +{ + gen_setcond_i128(retl, reth, s1l, s1h, s2l, s2h, TCG_COND_LTU); +} + static bool trans_slti(DisasContext *ctx, arg_slti *a) { - return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_slt); + return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_slt, gen_slt_i128); } static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a) { - return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_sltu); + return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_sltu, gen_sltu_i128); } static bool trans_xori(DisasContext *ctx, arg_xori *a) @@ -421,12 +552,12 @@ static bool trans_srai(DisasContext *ctx, arg_srai *a) static bool trans_add(DisasContext *ctx, arg_add *a) { - return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl, tcg_gen_add2_tl); } static bool trans_sub(DisasContext *ctx, arg_sub *a) { - return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl, tcg_gen_sub2_tl); } static void gen_sll_i128(TCGv destl, TCGv desth, @@ -471,12 +602,12 @@ static bool trans_sll(DisasContext *ctx, arg_sll *a) static bool trans_slt(DisasContext *ctx, arg_slt *a) { - return gen_arith(ctx, a, EXT_SIGN, gen_slt); + return gen_arith(ctx, a, EXT_SIGN, gen_slt, gen_slt_i128); } static bool trans_sltu(DisasContext *ctx, arg_sltu *a) { - return gen_arith(ctx, a, EXT_SIGN, gen_sltu); + return gen_arith(ctx, a, EXT_SIGN, gen_sltu, gen_sltu_i128); } static void gen_srl_i128(TCGv destl, TCGv desth, @@ -577,9 +708,9 @@ static bool trans_and(DisasContext *ctx, arg_and *a) static bool trans_addiw(DisasContext *ctx, arg_addiw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); ctx->ol = MXL_RV32; - return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl); + return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl, NULL); } static bool trans_slliw(DisasContext *ctx, arg_slliw *a) @@ -626,16 +757,16 @@ static bool trans_sraid(DisasContext *ctx, arg_sraid *a) static bool trans_addw(DisasContext *ctx, arg_addw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); ctx->ol = MXL_RV32; - return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl, NULL); } static bool trans_subw(DisasContext *ctx, arg_subw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); ctx->ol = MXL_RV32; - return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl, NULL); } static bool trans_sllw(DisasContext *ctx, arg_sllw *a) diff --git a/target/riscv/insn_trans/trans_rvm.c.inc b/target/riscv/insn_trans/trans_rvm.c.inc index 2af0e5c139..efe25dfc11 100644 --- a/target/riscv/insn_trans/trans_rvm.c.inc +++ b/target/riscv/insn_trans/trans_rvm.c.inc @@ -22,7 +22,7 @@ static bool trans_mul(DisasContext *ctx, arg_mul *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl, NULL); } static void gen_mulh(TCGv ret, TCGv s1, TCGv s2) @@ -42,7 +42,7 @@ static void gen_mulh_w(TCGv ret, TCGv s1, TCGv s2) static bool trans_mulh(DisasContext *ctx, arg_mulh *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith_per_ol(ctx, a, EXT_SIGN, gen_mulh, gen_mulh_w); + return gen_arith_per_ol(ctx, a, EXT_SIGN, gen_mulh, gen_mulh_w, NULL); } static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2) @@ -76,7 +76,7 @@ static void gen_mulhsu_w(TCGv ret, TCGv arg1, TCGv arg2) static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith_per_ol(ctx, a, EXT_NONE, gen_mulhsu, gen_mulhsu_w); + return gen_arith_per_ol(ctx, a, EXT_NONE, gen_mulhsu, gen_mulhsu_w, NULL); } static void gen_mulhu(TCGv ret, TCGv s1, TCGv s2) @@ -91,7 +91,7 @@ static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a) { REQUIRE_EXT(ctx, RVM); /* gen_mulh_w works for either sign as input. */ - return gen_arith_per_ol(ctx, a, EXT_ZERO, gen_mulhu, gen_mulh_w); + return gen_arith_per_ol(ctx, a, EXT_ZERO, gen_mulhu, gen_mulh_w, NULL); } static void gen_div(TCGv ret, TCGv source1, TCGv source2) @@ -130,7 +130,7 @@ static void gen_div(TCGv ret, TCGv source1, TCGv source2) static bool trans_div(DisasContext *ctx, arg_div *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_SIGN, gen_div); + return gen_arith(ctx, a, EXT_SIGN, gen_div, NULL); } static void gen_divu(TCGv ret, TCGv source1, TCGv source2) @@ -158,7 +158,7 @@ static void gen_divu(TCGv ret, TCGv source1, TCGv source2) static bool trans_divu(DisasContext *ctx, arg_divu *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_ZERO, gen_divu); + return gen_arith(ctx, a, EXT_ZERO, gen_divu, NULL); } static void gen_rem(TCGv ret, TCGv source1, TCGv source2) @@ -199,7 +199,7 @@ static void gen_rem(TCGv ret, TCGv source1, TCGv source2) static bool trans_rem(DisasContext *ctx, arg_rem *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_SIGN, gen_rem); + return gen_arith(ctx, a, EXT_SIGN, gen_rem, NULL); } static void gen_remu(TCGv ret, TCGv source1, TCGv source2) @@ -227,7 +227,7 @@ static void gen_remu(TCGv ret, TCGv source1, TCGv source2) static bool trans_remu(DisasContext *ctx, arg_remu *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_ZERO, gen_remu); + return gen_arith(ctx, a, EXT_ZERO, gen_remu, NULL); } static bool trans_mulw(DisasContext *ctx, arg_mulw *a) @@ -235,7 +235,7 @@ static bool trans_mulw(DisasContext *ctx, arg_mulw *a) REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); ctx->ol = MXL_RV32; - return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl, NULL); } static bool trans_divw(DisasContext *ctx, arg_divw *a) @@ -243,7 +243,7 @@ static bool trans_divw(DisasContext *ctx, arg_divw *a) REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); ctx->ol = MXL_RV32; - return gen_arith(ctx, a, EXT_SIGN, gen_div); + return gen_arith(ctx, a, EXT_SIGN, gen_div, NULL); } static bool trans_divuw(DisasContext *ctx, arg_divuw *a) @@ -251,7 +251,7 @@ static bool trans_divuw(DisasContext *ctx, arg_divuw *a) REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); ctx->ol = MXL_RV32; - return gen_arith(ctx, a, EXT_ZERO, gen_divu); + return gen_arith(ctx, a, EXT_ZERO, gen_divu, NULL); } static bool trans_remw(DisasContext *ctx, arg_remw *a) @@ -259,7 +259,7 @@ static bool trans_remw(DisasContext *ctx, arg_remw *a) REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); ctx->ol = MXL_RV32; - return gen_arith(ctx, a, EXT_SIGN, gen_rem); + return gen_arith(ctx, a, EXT_SIGN, gen_rem, NULL); } static bool trans_remuw(DisasContext *ctx, arg_remuw *a) @@ -267,5 +267,5 @@ static bool trans_remuw(DisasContext *ctx, arg_remuw *a) REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); ctx->ol = MXL_RV32; - return gen_arith(ctx, a, EXT_ZERO, gen_remu); + return gen_arith(ctx, a, EXT_ZERO, gen_remu, NULL); } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 89220a5fae..4ae4345691 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -581,57 +581,96 @@ static bool gen_logic(DisasContext *ctx, arg_r *a, } static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext, - void (*func)(TCGv, TCGv, target_long)) + void (*func)(TCGv, TCGv, target_long), + void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long)) { TCGv dest = dest_gpr(ctx, a->rd); TCGv src1 = get_gpr(ctx, a->rs1, ext); - func(dest, src1, a->imm); + if (get_ol(ctx) < MXL_RV128) { + func(dest, src1, a->imm); + gen_set_gpr(ctx, a->rd, dest); + } else { + if (f128 == NULL) { + return false; + } - gen_set_gpr(ctx, a->rd, dest); + TCGv src1h = get_gprh(ctx, a->rs1); + TCGv desth = dest_gprh(ctx, a->rd); + + f128(dest, desth, src1, src1h, a->imm); + gen_set_gpr128(ctx, a->rd, dest, desth); + } return true; } static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext, - void (*func)(TCGv, TCGv, TCGv)) + void (*func)(TCGv, TCGv, TCGv), + void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv)) { TCGv dest = dest_gpr(ctx, a->rd); TCGv src1 = get_gpr(ctx, a->rs1, ext); TCGv src2 = tcg_constant_tl(a->imm); - func(dest, src1, src2); + if (get_ol(ctx) < MXL_RV128) { + func(dest, src1, src2); + gen_set_gpr(ctx, a->rd, dest); + } else { + if (f128 == NULL) { + return false; + } - gen_set_gpr(ctx, a->rd, dest); + TCGv src1h = get_gprh(ctx, a->rs1); + TCGv src2h = tcg_constant_tl(-(a->imm < 0)); + TCGv desth = dest_gprh(ctx, a->rd); + + f128(dest, desth, src1, src1h, src2, src2h); + gen_set_gpr128(ctx, a->rd, dest, desth); + } return true; } static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext, - void (*func)(TCGv, TCGv, TCGv)) + void (*func)(TCGv, TCGv, TCGv), + void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv)) { TCGv dest = dest_gpr(ctx, a->rd); TCGv src1 = get_gpr(ctx, a->rs1, ext); TCGv src2 = get_gpr(ctx, a->rs2, ext); - func(dest, src1, src2); + if (get_ol(ctx) < MXL_RV128) { + func(dest, src1, src2); + gen_set_gpr(ctx, a->rd, dest); + } else { + if (f128 == NULL) { + return false; + } - gen_set_gpr(ctx, a->rd, dest); + TCGv src1h = get_gprh(ctx, a->rs1); + TCGv src2h = get_gprh(ctx, a->rs2); + TCGv desth = dest_gprh(ctx, a->rd); + + f128(dest, desth, src1, src1h, src2, src2h); + gen_set_gpr128(ctx, a->rd, dest, desth); + } return true; } static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext, void (*f_tl)(TCGv, TCGv, TCGv), - void (*f_32)(TCGv, TCGv, TCGv)) + void (*f_32)(TCGv, TCGv, TCGv), + void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv)) { int olen = get_olen(ctx); if (olen != TARGET_LONG_BITS) { if (olen == 32) { f_tl = f_32; - } else { + } else if (olen != 128) { g_assert_not_reached(); } } - return gen_arith(ctx, a, ext, f_tl); + return gen_arith(ctx, a, ext, f_tl, f_128); } static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext, From b3a5d1fbebab2098d0c3cdd3732c25f5cfbe5cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:01:04 +0100 Subject: [PATCH 312/730] target/riscv: support for 128-bit M extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mult are generated inline (using a cool trick pointed out by Richard), but for div and rem, given the complexity of the implementation of these instructions, we call helpers to produce their behavior. From an implementation standpoint, the helpers return the low part of the results, while the high part is temporarily stored in a dedicated field of cpu_env that is used to update the architectural register in the generation wrapper. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-15-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 3 + target/riscv/helper.h | 6 + target/riscv/insn32.decode | 7 + target/riscv/insn_trans/trans_rvm.c.inc | 182 ++++++++++++++++++++++-- target/riscv/m128_helper.c | 109 ++++++++++++++ target/riscv/meson.build | 1 + 6 files changed, 295 insertions(+), 13 deletions(-) create mode 100644 target/riscv/m128_helper.c diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index fd583e0f41..b9dee7d147 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -143,6 +143,9 @@ struct CPURISCVState { uint32_t misa_ext; /* current extensions */ uint32_t misa_ext_mask; /* max ext for this cpu */ + /* 128-bit helpers upper part return value */ + target_ulong retxh; + uint32_t features; #ifdef CONFIG_USER_ONLY diff --git a/target/riscv/helper.h b/target/riscv/helper.h index c15497e4a1..a8ee8a362a 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -1101,3 +1101,9 @@ DEF_HELPER_5(vsext_vf2_d, void, ptr, ptr, ptr, env, i32) DEF_HELPER_5(vsext_vf4_w, void, ptr, ptr, ptr, env, i32) DEF_HELPER_5(vsext_vf4_d, void, ptr, ptr, ptr, env, i32) DEF_HELPER_5(vsext_vf8_d, void, ptr, ptr, ptr, env, i32) + +/* 128-bit integer multiplication and division */ +DEF_HELPER_5(divu_i128, tl, env, tl, tl, tl, tl) +DEF_HELPER_5(divs_i128, tl, env, tl, tl, tl, tl) +DEF_HELPER_5(remu_i128, tl, env, tl, tl, tl, tl) +DEF_HELPER_5(rems_i128, tl, env, tl, tl, tl, tl) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 42366d20fb..5bbedc254c 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -197,6 +197,13 @@ divuw 0000001 ..... ..... 101 ..... 0111011 @r remw 0000001 ..... ..... 110 ..... 0111011 @r remuw 0000001 ..... ..... 111 ..... 0111011 @r +# *** RV128M Standard Extension (in addition to RV64M) *** +muld 0000001 ..... ..... 000 ..... 1111011 @r +divd 0000001 ..... ..... 100 ..... 1111011 @r +divud 0000001 ..... ..... 101 ..... 1111011 @r +remd 0000001 ..... ..... 110 ..... 1111011 @r +remud 0000001 ..... ..... 111 ..... 1111011 @r + # *** RV32A Standard Extension *** lr_w 00010 . . 00000 ..... 010 ..... 0101111 @atom_ld sc_w 00011 . . ..... ..... 010 ..... 0101111 @atom_st diff --git a/target/riscv/insn_trans/trans_rvm.c.inc b/target/riscv/insn_trans/trans_rvm.c.inc index efe25dfc11..16b029edf0 100644 --- a/target/riscv/insn_trans/trans_rvm.c.inc +++ b/target/riscv/insn_trans/trans_rvm.c.inc @@ -18,11 +18,79 @@ * this program. If not, see . */ +static void gen_mulhu_i128(TCGv r2, TCGv r3, TCGv al, TCGv ah, TCGv bl, TCGv bh) +{ + TCGv tmpl = tcg_temp_new(); + TCGv tmph = tcg_temp_new(); + TCGv r0 = tcg_temp_new(); + TCGv r1 = tcg_temp_new(); + TCGv zero = tcg_constant_tl(0); + + tcg_gen_mulu2_tl(r0, r1, al, bl); + + tcg_gen_mulu2_tl(tmpl, tmph, al, bh); + tcg_gen_add2_tl(r1, r2, r1, zero, tmpl, tmph); + tcg_gen_mulu2_tl(tmpl, tmph, ah, bl); + tcg_gen_add2_tl(r1, tmph, r1, r2, tmpl, tmph); + /* Overflow detection into r3 */ + tcg_gen_setcond_tl(TCG_COND_LTU, r3, tmph, r2); + + tcg_gen_mov_tl(r2, tmph); + + tcg_gen_mulu2_tl(tmpl, tmph, ah, bh); + tcg_gen_add2_tl(r2, r3, r2, r3, tmpl, tmph); + + tcg_temp_free(tmpl); + tcg_temp_free(tmph); +} + +static void gen_mul_i128(TCGv rl, TCGv rh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + TCGv tmpl = tcg_temp_new(); + TCGv tmph = tcg_temp_new(); + TCGv tmpx = tcg_temp_new(); + TCGv zero = tcg_constant_tl(0); + + tcg_gen_mulu2_tl(rl, rh, rs1l, rs2l); + tcg_gen_mulu2_tl(tmpl, tmph, rs1l, rs2h); + tcg_gen_add2_tl(rh, tmpx, rh, zero, tmpl, tmph); + tcg_gen_mulu2_tl(tmpl, tmph, rs1h, rs2l); + tcg_gen_add2_tl(rh, tmph, rh, tmpx, tmpl, tmph); + + tcg_temp_free(tmpl); + tcg_temp_free(tmph); + tcg_temp_free(tmpx); +} static bool trans_mul(DisasContext *ctx, arg_mul *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl, NULL); + return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl, gen_mul_i128); +} + +static void gen_mulh_i128(TCGv rl, TCGv rh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + TCGv t0l = tcg_temp_new(); + TCGv t0h = tcg_temp_new(); + TCGv t1l = tcg_temp_new(); + TCGv t1h = tcg_temp_new(); + + gen_mulhu_i128(rl, rh, rs1l, rs1h, rs2l, rs2h); + tcg_gen_sari_tl(t0h, rs1h, 63); + tcg_gen_and_tl(t0l, t0h, rs2l); + tcg_gen_and_tl(t0h, t0h, rs2h); + tcg_gen_sari_tl(t1h, rs2h, 63); + tcg_gen_and_tl(t1l, t1h, rs1l); + tcg_gen_and_tl(t1h, t1h, rs1h); + tcg_gen_sub2_tl(t0l, t0h, rl, rh, t0l, t0h); + tcg_gen_sub2_tl(rl, rh, t0l, t0h, t1l, t1h); + + tcg_temp_free(t0l); + tcg_temp_free(t0h); + tcg_temp_free(t1l); + tcg_temp_free(t1h); } static void gen_mulh(TCGv ret, TCGv s1, TCGv s2) @@ -42,7 +110,25 @@ static void gen_mulh_w(TCGv ret, TCGv s1, TCGv s2) static bool trans_mulh(DisasContext *ctx, arg_mulh *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith_per_ol(ctx, a, EXT_SIGN, gen_mulh, gen_mulh_w, NULL); + return gen_arith_per_ol(ctx, a, EXT_SIGN, gen_mulh, gen_mulh_w, + gen_mulh_i128); +} + +static void gen_mulhsu_i128(TCGv rl, TCGv rh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + + TCGv t0l = tcg_temp_new(); + TCGv t0h = tcg_temp_new(); + + gen_mulhu_i128(rl, rh, rs1l, rs1h, rs2l, rs2h); + tcg_gen_sari_tl(t0h, rs1h, 63); + tcg_gen_and_tl(t0l, t0h, rs2l); + tcg_gen_and_tl(t0h, t0h, rs2h); + tcg_gen_sub2_tl(rl, rh, rl, rh, t0l, t0h); + + tcg_temp_free(t0l); + tcg_temp_free(t0h); } static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2) @@ -76,7 +162,8 @@ static void gen_mulhsu_w(TCGv ret, TCGv arg1, TCGv arg2) static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith_per_ol(ctx, a, EXT_NONE, gen_mulhsu, gen_mulhsu_w, NULL); + return gen_arith_per_ol(ctx, a, EXT_NONE, gen_mulhsu, gen_mulhsu_w, + gen_mulhsu_i128); } static void gen_mulhu(TCGv ret, TCGv s1, TCGv s2) @@ -91,7 +178,15 @@ static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a) { REQUIRE_EXT(ctx, RVM); /* gen_mulh_w works for either sign as input. */ - return gen_arith_per_ol(ctx, a, EXT_ZERO, gen_mulhu, gen_mulh_w, NULL); + return gen_arith_per_ol(ctx, a, EXT_ZERO, gen_mulhu, gen_mulh_w, + gen_mulhu_i128); +} + +static void gen_div_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + gen_helper_divs_i128(rdl, cpu_env, rs1l, rs1h, rs2l, rs2h); + tcg_gen_ld_tl(rdh, cpu_env, offsetof(CPURISCVState, retxh)); } static void gen_div(TCGv ret, TCGv source1, TCGv source2) @@ -130,7 +225,14 @@ static void gen_div(TCGv ret, TCGv source1, TCGv source2) static bool trans_div(DisasContext *ctx, arg_div *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_SIGN, gen_div, NULL); + return gen_arith(ctx, a, EXT_SIGN, gen_div, gen_div_i128); +} + +static void gen_divu_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + gen_helper_divu_i128(rdl, cpu_env, rs1l, rs1h, rs2l, rs2h); + tcg_gen_ld_tl(rdh, cpu_env, offsetof(CPURISCVState, retxh)); } static void gen_divu(TCGv ret, TCGv source1, TCGv source2) @@ -158,7 +260,14 @@ static void gen_divu(TCGv ret, TCGv source1, TCGv source2) static bool trans_divu(DisasContext *ctx, arg_divu *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_ZERO, gen_divu, NULL); + return gen_arith(ctx, a, EXT_ZERO, gen_divu, gen_divu_i128); +} + +static void gen_rem_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + gen_helper_rems_i128(rdl, cpu_env, rs1l, rs1h, rs2l, rs2h); + tcg_gen_ld_tl(rdh, cpu_env, offsetof(CPURISCVState, retxh)); } static void gen_rem(TCGv ret, TCGv source1, TCGv source2) @@ -199,7 +308,14 @@ static void gen_rem(TCGv ret, TCGv source1, TCGv source2) static bool trans_rem(DisasContext *ctx, arg_rem *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_SIGN, gen_rem, NULL); + return gen_arith(ctx, a, EXT_SIGN, gen_rem, gen_rem_i128); +} + +static void gen_remu_i128(TCGv rdl, TCGv rdh, + TCGv rs1l, TCGv rs1h, TCGv rs2l, TCGv rs2h) +{ + gen_helper_remu_i128(rdl, cpu_env, rs1l, rs1h, rs2l, rs2h); + tcg_gen_ld_tl(rdh, cpu_env, offsetof(CPURISCVState, retxh)); } static void gen_remu(TCGv ret, TCGv source1, TCGv source2) @@ -227,12 +343,12 @@ static void gen_remu(TCGv ret, TCGv source1, TCGv source2) static bool trans_remu(DisasContext *ctx, arg_remu *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_ZERO, gen_remu, NULL); + return gen_arith(ctx, a, EXT_ZERO, gen_remu, gen_remu_i128); } static bool trans_mulw(DisasContext *ctx, arg_mulw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); REQUIRE_EXT(ctx, RVM); ctx->ol = MXL_RV32; return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl, NULL); @@ -240,7 +356,7 @@ static bool trans_mulw(DisasContext *ctx, arg_mulw *a) static bool trans_divw(DisasContext *ctx, arg_divw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); REQUIRE_EXT(ctx, RVM); ctx->ol = MXL_RV32; return gen_arith(ctx, a, EXT_SIGN, gen_div, NULL); @@ -248,7 +364,7 @@ static bool trans_divw(DisasContext *ctx, arg_divw *a) static bool trans_divuw(DisasContext *ctx, arg_divuw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); REQUIRE_EXT(ctx, RVM); ctx->ol = MXL_RV32; return gen_arith(ctx, a, EXT_ZERO, gen_divu, NULL); @@ -256,7 +372,7 @@ static bool trans_divuw(DisasContext *ctx, arg_divuw *a) static bool trans_remw(DisasContext *ctx, arg_remw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); REQUIRE_EXT(ctx, RVM); ctx->ol = MXL_RV32; return gen_arith(ctx, a, EXT_SIGN, gen_rem, NULL); @@ -264,8 +380,48 @@ static bool trans_remw(DisasContext *ctx, arg_remw *a) static bool trans_remuw(DisasContext *ctx, arg_remuw *a) { - REQUIRE_64BIT(ctx); + REQUIRE_64_OR_128BIT(ctx); REQUIRE_EXT(ctx, RVM); ctx->ol = MXL_RV32; return gen_arith(ctx, a, EXT_ZERO, gen_remu, NULL); } + +static bool trans_muld(DisasContext *ctx, arg_muld *a) +{ + REQUIRE_128BIT(ctx); + REQUIRE_EXT(ctx, RVM); + ctx->ol = MXL_RV64; + return gen_arith(ctx, a, EXT_SIGN, tcg_gen_mul_tl, NULL); +} + +static bool trans_divd(DisasContext *ctx, arg_divd *a) +{ + REQUIRE_128BIT(ctx); + REQUIRE_EXT(ctx, RVM); + ctx->ol = MXL_RV64; + return gen_arith(ctx, a, EXT_SIGN, gen_div, NULL); +} + +static bool trans_divud(DisasContext *ctx, arg_divud *a) +{ + REQUIRE_128BIT(ctx); + REQUIRE_EXT(ctx, RVM); + ctx->ol = MXL_RV64; + return gen_arith(ctx, a, EXT_ZERO, gen_divu, NULL); +} + +static bool trans_remd(DisasContext *ctx, arg_remd *a) +{ + REQUIRE_128BIT(ctx); + REQUIRE_EXT(ctx, RVM); + ctx->ol = MXL_RV64; + return gen_arith(ctx, a, EXT_SIGN, gen_rem, NULL); +} + +static bool trans_remud(DisasContext *ctx, arg_remud *a) +{ + REQUIRE_128BIT(ctx); + REQUIRE_EXT(ctx, RVM); + ctx->ol = MXL_RV64; + return gen_arith(ctx, a, EXT_ZERO, gen_remu, NULL); +} diff --git a/target/riscv/m128_helper.c b/target/riscv/m128_helper.c new file mode 100644 index 0000000000..7bf115b85e --- /dev/null +++ b/target/riscv/m128_helper.c @@ -0,0 +1,109 @@ +/* + * RISC-V Emulation Helpers for QEMU. + * + * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu + * Copyright (c) 2017-2018 SiFive, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "qemu/main-loop.h" +#include "exec/exec-all.h" +#include "exec/helper-proto.h" + +target_ulong HELPER(divu_i128)(CPURISCVState *env, + target_ulong ul, target_ulong uh, + target_ulong vl, target_ulong vh) +{ + target_ulong ql, qh; + Int128 q; + + if (vl == 0 && vh == 0) { /* Handle special behavior on div by zero */ + ql = ~0x0; + qh = ~0x0; + } else { + q = int128_divu(int128_make128(ul, uh), int128_make128(vl, vh)); + ql = int128_getlo(q); + qh = int128_gethi(q); + } + + env->retxh = qh; + return ql; +} + +target_ulong HELPER(remu_i128)(CPURISCVState *env, + target_ulong ul, target_ulong uh, + target_ulong vl, target_ulong vh) +{ + target_ulong rl, rh; + Int128 r; + + if (vl == 0 && vh == 0) { + rl = ul; + rh = uh; + } else { + r = int128_remu(int128_make128(ul, uh), int128_make128(vl, vh)); + rl = int128_getlo(r); + rh = int128_gethi(r); + } + + env->retxh = rh; + return rl; +} + +target_ulong HELPER(divs_i128)(CPURISCVState *env, + target_ulong ul, target_ulong uh, + target_ulong vl, target_ulong vh) +{ + target_ulong qh, ql; + Int128 q; + + if (vl == 0 && vh == 0) { /* Div by zero check */ + ql = ~0x0; + qh = ~0x0; + } else if (uh == (1ULL << (TARGET_LONG_BITS - 1)) && ul == 0 && + vh == ~0x0 && vl == ~0x0) { + /* Signed div overflow check (-2**127 / -1) */ + ql = ul; + qh = uh; + } else { + q = int128_divs(int128_make128(ul, uh), int128_make128(vl, vh)); + ql = int128_getlo(q); + qh = int128_gethi(q); + } + + env->retxh = qh; + return ql; +} + +target_ulong HELPER(rems_i128)(CPURISCVState *env, + target_ulong ul, target_ulong uh, + target_ulong vl, target_ulong vh) +{ + target_ulong rh, rl; + Int128 r; + + if (vl == 0 && vh == 0) { + rl = ul; + rh = uh; + } else { + r = int128_rems(int128_make128(ul, uh), int128_make128(vl, vh)); + rl = int128_getlo(r); + rh = int128_gethi(r); + } + + env->retxh = rh; + return rl; +} diff --git a/target/riscv/meson.build b/target/riscv/meson.build index d5e0bc93ea..a32158da93 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -18,6 +18,7 @@ riscv_ss.add(files( 'vector_helper.c', 'bitmanip_helper.c', 'translate.c', + 'm128_helper.c' )) riscv_softmmu_ss = ss.source_set() From 2c64ab66c1cdb409ead121357b3e92f8f1800c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:01:05 +0100 Subject: [PATCH 313/730] target/riscv: adding high part of some csrs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding the high part of a very minimal set of csr. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-16-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 4 ++++ target/riscv/machine.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index b9dee7d147..e8c664a956 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -195,6 +195,10 @@ struct CPURISCVState { target_ulong hgatp; uint64_t htimedelta; + /* Upper 64-bits of 128-bit CSRs */ + uint64_t mscratchh; + uint64_t sscratchh; + /* Virtual CSRs */ /* * For RV32 this is 32-bit vsstatus and 32-bit vsstatush. diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 8af9caabf5..13b9ab375b 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -179,6 +179,8 @@ static const VMStateDescription vmstate_rv128 = { .needed = rv128_needed, .fields = (VMStateField[]) { VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32), + VMSTATE_UINT64(env.mscratchh, RISCVCPU), + VMSTATE_UINT64(env.sscratchh, RISCVCPU), VMSTATE_END_OF_LIST() } }; From 961738ffea964daad464389b3f06dd5b245fdf3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:01:06 +0100 Subject: [PATCH 314/730] target/riscv: helper functions to wrap calls to 128-bit csr insns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given the side effects they have, the csr instructions are realized as helpers. We extend this existing infrastructure for 128-bit sized csr. We return 128-bit values using the same approach as for div/rem. Theses helpers all call a unique function that is currently a fallback on the 64-bit version. The trans_csrxx functions supporting 128-bit are yet to be implemented. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-17-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 5 +++++ target/riscv/csr.c | 17 ++++++++++++++++ target/riscv/helper.h | 3 +++ target/riscv/op_helper.c | 44 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index e8c664a956..73d3d22f26 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -25,6 +25,7 @@ #include "exec/cpu-defs.h" #include "fpu/softfloat-types.h" #include "qom/object.h" +#include "qemu/int128.h" #include "cpu_bits.h" #define TCG_GUEST_DEFAULT_MO 0 @@ -500,6 +501,10 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno, target_ulong new_value, target_ulong write_mask); +RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno, + Int128 *ret_value, + Int128 new_value, Int128 write_mask); + typedef struct { const char *name; riscv_csr_predicate_fn predicate; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 146447eac5..4c6a44c0b8 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1817,6 +1817,23 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno, + Int128 *ret_value, + Int128 new_value, Int128 write_mask) +{ + /* fall back to 64-bit version for now */ + target_ulong ret_64; + RISCVException ret = riscv_csrrw(env, csrno, &ret_64, + int128_getlo(new_value), + int128_getlo(write_mask)); + + if (ret_value) { + *ret_value = int128_make64(ret_64); + } + + return ret; +} + /* * Debugger support. If not in user mode, set env->debugger before the * riscv_csrrw call and clear it after the call. diff --git a/target/riscv/helper.h b/target/riscv/helper.h index a8ee8a362a..6cf6d6ce98 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -96,6 +96,9 @@ DEF_HELPER_FLAGS_1(fclass_h, TCG_CALL_NO_RWG_SE, tl, i64) DEF_HELPER_2(csrr, tl, env, int) DEF_HELPER_3(csrw, void, env, int, tl) DEF_HELPER_4(csrrw, tl, env, int, tl, tl) +DEF_HELPER_2(csrr_i128, tl, env, int) +DEF_HELPER_4(csrw_i128, void, env, int, tl, tl) +DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl) #ifndef CONFIG_USER_ONLY DEF_HELPER_2(sret, tl, env, tl) DEF_HELPER_2(mret, tl, env, tl) diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 58d992e98a..6f040f2fb9 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -69,6 +69,50 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr, return val; } +target_ulong helper_csrr_i128(CPURISCVState *env, int csr) +{ + Int128 rv = int128_zero(); + RISCVException ret = riscv_csrrw_i128(env, csr, &rv, + int128_zero(), + int128_zero()); + + if (ret != RISCV_EXCP_NONE) { + riscv_raise_exception(env, ret, GETPC()); + } + + env->retxh = int128_gethi(rv); + return int128_getlo(rv); +} + +void helper_csrw_i128(CPURISCVState *env, int csr, + target_ulong srcl, target_ulong srch) +{ + RISCVException ret = riscv_csrrw_i128(env, csr, NULL, + int128_make128(srcl, srch), + UINT128_MAX); + + if (ret != RISCV_EXCP_NONE) { + riscv_raise_exception(env, ret, GETPC()); + } +} + +target_ulong helper_csrrw_i128(CPURISCVState *env, int csr, + target_ulong srcl, target_ulong srch, + target_ulong maskl, target_ulong maskh) +{ + Int128 rv = int128_zero(); + RISCVException ret = riscv_csrrw_i128(env, csr, &rv, + int128_make128(srcl, srch), + int128_make128(maskl, maskh)); + + if (ret != RISCV_EXCP_NONE) { + riscv_raise_exception(env, ret, GETPC()); + } + + env->retxh = int128_gethi(rv); + return int128_getlo(rv); +} + #ifndef CONFIG_USER_ONLY target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) From 7934fdeee75c8d8ca02a396afc549e3f54303859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:01:07 +0100 Subject: [PATCH 315/730] target/riscv: modification of the trans_csrxx for 128-bit support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As opposed to the gen_arith and gen_shift generation helpers, the csr insns do not have a common prototype, so the choice to generate 32/64 or 128-bit helper calls is done in the trans_csrxx functions. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-18-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvi.c.inc | 201 +++++++++++++++++++----- 1 file changed, 158 insertions(+), 43 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index ca354130ec..3a0ae28fef 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -881,20 +881,78 @@ static bool do_csrrw(DisasContext *ctx, int rd, int rc, TCGv src, TCGv mask) return do_csr_post(ctx); } +static bool do_csrr_i128(DisasContext *ctx, int rd, int rc) +{ + TCGv destl = dest_gpr(ctx, rd); + TCGv desth = dest_gprh(ctx, rd); + TCGv_i32 csr = tcg_constant_i32(rc); + + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } + gen_helper_csrr_i128(destl, cpu_env, csr); + tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh)); + gen_set_gpr128(ctx, rd, destl, desth); + return do_csr_post(ctx); +} + +static bool do_csrw_i128(DisasContext *ctx, int rc, TCGv srcl, TCGv srch) +{ + TCGv_i32 csr = tcg_constant_i32(rc); + + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } + gen_helper_csrw_i128(cpu_env, csr, srcl, srch); + return do_csr_post(ctx); +} + +static bool do_csrrw_i128(DisasContext *ctx, int rd, int rc, + TCGv srcl, TCGv srch, TCGv maskl, TCGv maskh) +{ + TCGv destl = dest_gpr(ctx, rd); + TCGv desth = dest_gprh(ctx, rd); + TCGv_i32 csr = tcg_constant_i32(rc); + + if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) { + gen_io_start(); + } + gen_helper_csrrw_i128(destl, cpu_env, csr, srcl, srch, maskl, maskh); + tcg_gen_ld_tl(desth, cpu_env, offsetof(CPURISCVState, retxh)); + gen_set_gpr128(ctx, rd, destl, desth); + return do_csr_post(ctx); +} + static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a) { - TCGv src = get_gpr(ctx, a->rs1, EXT_NONE); + if (get_xl(ctx) < MXL_RV128) { + TCGv src = get_gpr(ctx, a->rs1, EXT_NONE); - /* - * If rd == 0, the insn shall not read the csr, nor cause any of the - * side effects that might occur on a csr read. - */ - if (a->rd == 0) { - return do_csrw(ctx, a->csr, src); + /* + * If rd == 0, the insn shall not read the csr, nor cause any of the + * side effects that might occur on a csr read. + */ + if (a->rd == 0) { + return do_csrw(ctx, a->csr, src); + } + + TCGv mask = tcg_constant_tl(-1); + return do_csrrw(ctx, a->rd, a->csr, src, mask); + } else { + TCGv srcl = get_gpr(ctx, a->rs1, EXT_NONE); + TCGv srch = get_gprh(ctx, a->rs1); + + /* + * If rd == 0, the insn shall not read the csr, nor cause any of the + * side effects that might occur on a csr read. + */ + if (a->rd == 0) { + return do_csrw_i128(ctx, a->csr, srcl, srch); + } + + TCGv mask = tcg_constant_tl(-1); + return do_csrrw_i128(ctx, a->rd, a->csr, srcl, srch, mask, mask); } - - TCGv mask = tcg_constant_tl(-1); - return do_csrrw(ctx, a->rd, a->csr, src, mask); } static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a) @@ -906,13 +964,24 @@ static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a) * a zero value, the instruction will still attempt to write the * unmodified value back to the csr and will cause side effects. */ - if (a->rs1 == 0) { - return do_csrr(ctx, a->rd, a->csr); - } + if (get_xl(ctx) < MXL_RV128) { + if (a->rs1 == 0) { + return do_csrr(ctx, a->rd, a->csr); + } - TCGv ones = tcg_constant_tl(-1); - TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO); - return do_csrrw(ctx, a->rd, a->csr, ones, mask); + TCGv ones = tcg_constant_tl(-1); + TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO); + return do_csrrw(ctx, a->rd, a->csr, ones, mask); + } else { + if (a->rs1 == 0) { + return do_csrr_i128(ctx, a->rd, a->csr); + } + + TCGv ones = tcg_constant_tl(-1); + TCGv maskl = get_gpr(ctx, a->rs1, EXT_ZERO); + TCGv maskh = get_gprh(ctx, a->rs1); + return do_csrrw_i128(ctx, a->rd, a->csr, ones, ones, maskl, maskh); + } } static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a) @@ -924,28 +993,54 @@ static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a) * a zero value, the instruction will still attempt to write the * unmodified value back to the csr and will cause side effects. */ - if (a->rs1 == 0) { - return do_csrr(ctx, a->rd, a->csr); - } + if (get_xl(ctx) < MXL_RV128) { + if (a->rs1 == 0) { + return do_csrr(ctx, a->rd, a->csr); + } - TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO); - return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask); + TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO); + return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask); + } else { + if (a->rs1 == 0) { + return do_csrr_i128(ctx, a->rd, a->csr); + } + + TCGv maskl = get_gpr(ctx, a->rs1, EXT_ZERO); + TCGv maskh = get_gprh(ctx, a->rs1); + return do_csrrw_i128(ctx, a->rd, a->csr, + ctx->zero, ctx->zero, maskl, maskh); + } } static bool trans_csrrwi(DisasContext *ctx, arg_csrrwi *a) { - TCGv src = tcg_constant_tl(a->rs1); + if (get_xl(ctx) < MXL_RV128) { + TCGv src = tcg_constant_tl(a->rs1); - /* - * If rd == 0, the insn shall not read the csr, nor cause any of the - * side effects that might occur on a csr read. - */ - if (a->rd == 0) { - return do_csrw(ctx, a->csr, src); + /* + * If rd == 0, the insn shall not read the csr, nor cause any of the + * side effects that might occur on a csr read. + */ + if (a->rd == 0) { + return do_csrw(ctx, a->csr, src); + } + + TCGv mask = tcg_constant_tl(-1); + return do_csrrw(ctx, a->rd, a->csr, src, mask); + } else { + TCGv src = tcg_constant_tl(a->rs1); + + /* + * If rd == 0, the insn shall not read the csr, nor cause any of the + * side effects that might occur on a csr read. + */ + if (a->rd == 0) { + return do_csrw_i128(ctx, a->csr, src, ctx->zero); + } + + TCGv mask = tcg_constant_tl(-1); + return do_csrrw_i128(ctx, a->rd, a->csr, src, ctx->zero, mask, mask); } - - TCGv mask = tcg_constant_tl(-1); - return do_csrrw(ctx, a->rd, a->csr, src, mask); } static bool trans_csrrsi(DisasContext *ctx, arg_csrrsi *a) @@ -957,16 +1052,26 @@ static bool trans_csrrsi(DisasContext *ctx, arg_csrrsi *a) * a zero value, the instruction will still attempt to write the * unmodified value back to the csr and will cause side effects. */ - if (a->rs1 == 0) { - return do_csrr(ctx, a->rd, a->csr); - } + if (get_xl(ctx) < MXL_RV128) { + if (a->rs1 == 0) { + return do_csrr(ctx, a->rd, a->csr); + } - TCGv ones = tcg_constant_tl(-1); - TCGv mask = tcg_constant_tl(a->rs1); - return do_csrrw(ctx, a->rd, a->csr, ones, mask); + TCGv ones = tcg_constant_tl(-1); + TCGv mask = tcg_constant_tl(a->rs1); + return do_csrrw(ctx, a->rd, a->csr, ones, mask); + } else { + if (a->rs1 == 0) { + return do_csrr_i128(ctx, a->rd, a->csr); + } + + TCGv ones = tcg_constant_tl(-1); + TCGv mask = tcg_constant_tl(a->rs1); + return do_csrrw_i128(ctx, a->rd, a->csr, ones, ones, mask, ctx->zero); + } } -static bool trans_csrrci(DisasContext *ctx, arg_csrrci *a) +static bool trans_csrrci(DisasContext *ctx, arg_csrrci * a) { /* * If rs1 == 0, the insn shall not write to the csr at all, nor @@ -975,10 +1080,20 @@ static bool trans_csrrci(DisasContext *ctx, arg_csrrci *a) * a zero value, the instruction will still attempt to write the * unmodified value back to the csr and will cause side effects. */ - if (a->rs1 == 0) { - return do_csrr(ctx, a->rd, a->csr); - } + if (get_xl(ctx) < MXL_RV128) { + if (a->rs1 == 0) { + return do_csrr(ctx, a->rd, a->csr); + } - TCGv mask = tcg_constant_tl(a->rs1); - return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask); + TCGv mask = tcg_constant_tl(a->rs1); + return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask); + } else { + if (a->rs1 == 0) { + return do_csrr_i128(ctx, a->rd, a->csr); + } + + TCGv mask = tcg_constant_tl(a->rs1); + return do_csrrw_i128(ctx, a->rd, a->csr, + ctx->zero, ctx->zero, mask, ctx->zero); + } } From 457c360f9c72f86ac6dd57f46a016dd361aaf3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Thu, 6 Jan 2022 22:01:08 +0100 Subject: [PATCH 316/730] target/riscv: actual functions to realize crs 128-bit insns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The csrs are accessed through function pointers: we add 128-bit read operations in the table for three csrs (writes fallback to the 64-bit version as the upper 64-bit information is handled elsewhere): - misa, as mxl is needed for proper operation, - mstatus and sstatus, to return sd In addition, we also add read and write accesses to the machine and supervisor scratch registers. Signed-off-by: Frédéric Pétrot Co-authored-by: Fabien Portas Reviewed-by: Alistair Francis Message-id: 20220106210108.138226-19-frederic.petrot@univ-grenoble-alpes.fr Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 7 ++ target/riscv/cpu_bits.h | 3 + target/riscv/csr.c | 197 +++++++++++++++++++++++++++++++++------- 3 files changed, 176 insertions(+), 31 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 73d3d22f26..9ee01f761f 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -505,12 +505,19 @@ RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno, Int128 *ret_value, Int128 new_value, Int128 write_mask); +typedef RISCVException (*riscv_csr_read128_fn)(CPURISCVState *env, int csrno, + Int128 *ret_value); +typedef RISCVException (*riscv_csr_write128_fn)(CPURISCVState *env, int csrno, + Int128 new_value); + typedef struct { const char *name; riscv_csr_predicate_fn predicate; riscv_csr_read_fn read; riscv_csr_write_fn write; riscv_csr_op_fn op; + riscv_csr_read128_fn read128; + riscv_csr_write128_fn write128; } riscv_csr_operations; /* CSR function table constants */ diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 1e31f4d35f..5a6d49aa64 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -401,6 +401,7 @@ #define MSTATUS32_SD 0x80000000 #define MSTATUS64_SD 0x8000000000000000ULL +#define MSTATUSH128_SD 0x8000000000000000ULL #define MISA32_MXL 0xC0000000 #define MISA64_MXL 0xC000000000000000ULL @@ -423,6 +424,8 @@ typedef enum { #define SSTATUS_SUM 0x00040000 /* since: priv-1.10 */ #define SSTATUS_MXR 0x00080000 +#define SSTATUS64_UXL 0x0000000300000000ULL + #define SSTATUS32_SD 0x80000000 #define SSTATUS64_SD 0x8000000000000000ULL diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 4c6a44c0b8..adb3d4381d 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -481,7 +481,7 @@ static const target_ulong vs_delegable_excps = DELEGABLE_EXCPS & (1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT))); static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS | - SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS; + SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS | (target_ulong)SSTATUS64_UXL; static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP; static const target_ulong hip_writable_mask = MIP_VSSIP; static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP; @@ -527,6 +527,8 @@ static uint64_t add_status_sd(RISCVMXL xl, uint64_t status) return status | MSTATUS32_SD; case MXL_RV64: return status | MSTATUS64_SD; + case MXL_RV128: + return MSTATUSH128_SD; default: g_assert_not_reached(); } @@ -576,10 +578,11 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, mstatus = (mstatus & ~mask) | (val & mask); - if (riscv_cpu_mxl(env) == MXL_RV64) { + RISCVMXL xl = riscv_cpu_mxl(env); + if (xl > MXL_RV32) { /* SXL and UXL fields are for now read only */ - mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64); - mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64); + mstatus = set_field(mstatus, MSTATUS64_SXL, xl); + mstatus = set_field(mstatus, MSTATUS64_UXL, xl); } env->mstatus = mstatus; @@ -608,6 +611,20 @@ static RISCVException write_mstatush(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static RISCVException read_mstatus_i128(CPURISCVState *env, int csrno, + Int128 *val) +{ + *val = int128_make128(env->mstatus, add_status_sd(MXL_RV128, env->mstatus)); + return RISCV_EXCP_NONE; +} + +static RISCVException read_misa_i128(CPURISCVState *env, int csrno, + Int128 *val) +{ + *val = int128_make128(env->misa_ext, (uint64_t)MXL_RV128 << 62); + return RISCV_EXCP_NONE; +} + static RISCVException read_misa(CPURISCVState *env, int csrno, target_ulong *val) { @@ -765,6 +782,21 @@ static RISCVException write_mcounteren(CPURISCVState *env, int csrno, } /* Machine Trap Handling */ +static RISCVException read_mscratch_i128(CPURISCVState *env, int csrno, + Int128 *val) +{ + *val = int128_make128(env->mscratch, env->mscratchh); + return RISCV_EXCP_NONE; +} + +static RISCVException write_mscratch_i128(CPURISCVState *env, int csrno, + Int128 val) +{ + env->mscratch = int128_getlo(val); + env->mscratchh = int128_gethi(val); + return RISCV_EXCP_NONE; +} + static RISCVException read_mscratch(CPURISCVState *env, int csrno, target_ulong *val) { @@ -844,6 +876,16 @@ static RISCVException rmw_mip(CPURISCVState *env, int csrno, } /* Supervisor Trap Setup */ +static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno, + Int128 *val) +{ + uint64_t mask = sstatus_v1_10_mask; + uint64_t sstatus = env->mstatus & mask; + + *val = int128_make128(sstatus, add_status_sd(MXL_RV128, sstatus)); + return RISCV_EXCP_NONE; +} + static RISCVException read_sstatus(CPURISCVState *env, int csrno, target_ulong *val) { @@ -937,6 +979,21 @@ static RISCVException write_scounteren(CPURISCVState *env, int csrno, } /* Supervisor Trap Handling */ +static RISCVException read_sscratch_i128(CPURISCVState *env, int csrno, + Int128 *val) +{ + *val = int128_make128(env->sscratch, env->sscratchh); + return RISCV_EXCP_NONE; +} + +static RISCVException write_sscratch_i128(CPURISCVState *env, int csrno, + Int128 val) +{ + env->sscratch = int128_getlo(val); + env->sscratchh = int128_gethi(val); + return RISCV_EXCP_NONE; +} + static RISCVException read_sscratch(CPURISCVState *env, int csrno, target_ulong *val) { @@ -1737,16 +1794,13 @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno, * csrrc <-> riscv_csrrw(env, csrno, ret_value, 0, value); */ -RISCVException riscv_csrrw(CPURISCVState *env, int csrno, - target_ulong *ret_value, - target_ulong new_value, target_ulong write_mask) +static inline RISCVException riscv_csrrw_check(CPURISCVState *env, + int csrno, + bool write_mask, + RISCVCPU *cpu) { - RISCVException ret; - target_ulong old_value; - RISCVCPU *cpu = env_archcpu(env); - int read_only = get_field(csrno, 0xC00) == 3; - /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */ + int read_only = get_field(csrno, 0xC00) == 3; #if !defined(CONFIG_USER_ONLY) int effective_priv = env->priv; @@ -1778,10 +1832,17 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno, if (!csr_ops[csrno].predicate) { return RISCV_EXCP_ILLEGAL_INST; } - ret = csr_ops[csrno].predicate(env, csrno); - if (ret != RISCV_EXCP_NONE) { - return ret; - } + + return csr_ops[csrno].predicate(env, csrno); +} + +static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno, + target_ulong *ret_value, + target_ulong new_value, + target_ulong write_mask) +{ + RISCVException ret; + target_ulong old_value; /* execute combined read/write operation if it exists */ if (csr_ops[csrno].op) { @@ -1817,20 +1878,89 @@ RISCVException riscv_csrrw(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } -RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno, - Int128 *ret_value, - Int128 new_value, Int128 write_mask) +RISCVException riscv_csrrw(CPURISCVState *env, int csrno, + target_ulong *ret_value, + target_ulong new_value, target_ulong write_mask) { - /* fall back to 64-bit version for now */ - target_ulong ret_64; - RISCVException ret = riscv_csrrw(env, csrno, &ret_64, - int128_getlo(new_value), - int128_getlo(write_mask)); + RISCVCPU *cpu = env_archcpu(env); - if (ret_value) { - *ret_value = int128_make64(ret_64); + RISCVException ret = riscv_csrrw_check(env, csrno, write_mask, cpu); + if (ret != RISCV_EXCP_NONE) { + return ret; } + return riscv_csrrw_do64(env, csrno, ret_value, new_value, write_mask); +} + +static RISCVException riscv_csrrw_do128(CPURISCVState *env, int csrno, + Int128 *ret_value, + Int128 new_value, + Int128 write_mask) +{ + RISCVException ret; + Int128 old_value; + + /* read old value */ + ret = csr_ops[csrno].read128(env, csrno, &old_value); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + + /* write value if writable and write mask set, otherwise drop writes */ + if (int128_nz(write_mask)) { + new_value = int128_or(int128_and(old_value, int128_not(write_mask)), + int128_and(new_value, write_mask)); + if (csr_ops[csrno].write128) { + ret = csr_ops[csrno].write128(env, csrno, new_value); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + } else if (csr_ops[csrno].write) { + /* avoids having to write wrappers for all registers */ + ret = csr_ops[csrno].write(env, csrno, int128_getlo(new_value)); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + } + } + + /* return old value */ + if (ret_value) { + *ret_value = old_value; + } + + return RISCV_EXCP_NONE; +} + +RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno, + Int128 *ret_value, + Int128 new_value, Int128 write_mask) +{ + RISCVException ret; + RISCVCPU *cpu = env_archcpu(env); + + ret = riscv_csrrw_check(env, csrno, int128_nz(write_mask), cpu); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + + if (csr_ops[csrno].read128) { + return riscv_csrrw_do128(env, csrno, ret_value, new_value, write_mask); + } + + /* + * Fall back to 64-bit version for now, if the 128-bit alternative isn't + * at all defined. + * Note, some CSRs don't need to extend to MXLEN (64 upper bits non + * significant), for those, this fallback is correctly handling the accesses + */ + target_ulong old_value; + ret = riscv_csrrw_do64(env, csrno, &old_value, + int128_getlo(new_value), + int128_getlo(write_mask)); + if (ret == RISCV_EXCP_NONE && ret_value) { + *ret_value = int128_make64(old_value); + } return ret; } @@ -1895,8 +2025,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MHARTID] = { "mhartid", any, read_mhartid }, /* Machine Trap Setup */ - [CSR_MSTATUS] = { "mstatus", any, read_mstatus, write_mstatus }, - [CSR_MISA] = { "misa", any, read_misa, write_misa }, + [CSR_MSTATUS] = { "mstatus", any, read_mstatus, write_mstatus, NULL, + read_mstatus_i128 }, + [CSR_MISA] = { "misa", any, read_misa, write_misa, NULL, + read_misa_i128 }, [CSR_MIDELEG] = { "mideleg", any, read_mideleg, write_mideleg }, [CSR_MEDELEG] = { "medeleg", any, read_medeleg, write_medeleg }, [CSR_MIE] = { "mie", any, read_mie, write_mie }, @@ -1906,20 +2038,23 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MSTATUSH] = { "mstatush", any32, read_mstatush, write_mstatush }, /* Machine Trap Handling */ - [CSR_MSCRATCH] = { "mscratch", any, read_mscratch, write_mscratch }, + [CSR_MSCRATCH] = { "mscratch", any, read_mscratch, write_mscratch, NULL, + read_mscratch_i128, write_mscratch_i128 }, [CSR_MEPC] = { "mepc", any, read_mepc, write_mepc }, [CSR_MCAUSE] = { "mcause", any, read_mcause, write_mcause }, [CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval }, [CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip }, /* Supervisor Trap Setup */ - [CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus }, + [CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus, NULL, + read_sstatus_i128 }, [CSR_SIE] = { "sie", smode, read_sie, write_sie }, [CSR_STVEC] = { "stvec", smode, read_stvec, write_stvec }, [CSR_SCOUNTEREN] = { "scounteren", smode, read_scounteren, write_scounteren }, /* Supervisor Trap Handling */ - [CSR_SSCRATCH] = { "sscratch", smode, read_sscratch, write_sscratch }, + [CSR_SSCRATCH] = { "sscratch", smode, read_sscratch, write_sscratch, NULL, + read_sscratch_i128, write_sscratch_i128 }, [CSR_SEPC] = { "sepc", smode, read_sepc, write_sepc }, [CSR_SCAUSE] = { "scause", smode, read_scause, write_scause }, [CSR_STVAL] = { "stval", smode, read_stval, write_stval }, From ea7b5d5af6c3f994b10caa80c7f41964678eb2bb Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 20 Dec 2021 16:49:14 +1000 Subject: [PATCH 317/730] target/riscv: Set the opcode in DisasContext Signed-off-by: Alistair Francis Reviewed-by: Richard Henderson Reviewed-by: Bin Meng Message-id: 20211220064916.107241-2-alistair.francis@opensource.wdc.com --- target/riscv/translate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 4ae4345691..9e4f9c3342 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -846,6 +846,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode) if (!has_ext(ctx, RVC)) { gen_exception_illegal(ctx); } else { + ctx->opcode = opcode; ctx->pc_succ_insn = ctx->base.pc_next + 2; if (!decode_insn16(ctx, opcode)) { gen_exception_illegal(ctx); @@ -856,6 +857,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode) opcode32 = deposit32(opcode32, 16, 16, translator_lduw(env, &ctx->base, ctx->base.pc_next + 2)); + ctx->opcode = opcode32; ctx->pc_succ_insn = ctx->base.pc_next + 4; if (!decode_insn32(ctx, opcode32)) { gen_exception_illegal(ctx); From 86d0c457396b1a789fe2740f7bd8d476ea426298 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 20 Dec 2021 16:49:15 +1000 Subject: [PATCH 318/730] target/riscv: Fixup setting GVA In preparation for adding support for the illegal instruction address let's fixup the Hypervisor extension setting GVA logic and improve the variable names. Signed-off-by: Alistair Francis Reviewed-by: Richard Henderson Reviewed-by: Bin Meng Message-id: 20211220064916.107241-3-alistair.francis@opensource.wdc.com --- target/riscv/cpu_helper.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 10f3baba53..ddacb8533a 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -998,6 +998,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; + bool write_gva = false; uint64_t s; /* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide @@ -1006,7 +1007,6 @@ void riscv_cpu_do_interrupt(CPUState *cs) bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG); target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK; target_ulong deleg = async ? env->mideleg : env->medeleg; - bool write_tval = false; target_ulong tval = 0; target_ulong htval = 0; target_ulong mtval2 = 0; @@ -1035,7 +1035,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) case RISCV_EXCP_INST_PAGE_FAULT: case RISCV_EXCP_LOAD_PAGE_FAULT: case RISCV_EXCP_STORE_PAGE_FAULT: - write_tval = true; + write_gva = true; tval = env->badaddr; break; default: @@ -1072,18 +1072,6 @@ void riscv_cpu_do_interrupt(CPUState *cs) if (riscv_has_ext(env, RVH)) { target_ulong hdeleg = async ? env->hideleg : env->hedeleg; - if (env->two_stage_lookup && write_tval) { - /* - * If we are writing a guest virtual address to stval, set - * this to 1. If we are trapping to VS we will set this to 0 - * later. - */ - env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 1); - } else { - /* For other HS-mode traps, we set this to 0. */ - env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 0); - } - if (riscv_cpu_virt_enabled(env) && ((hdeleg >> cause) & 1)) { /* Trap to VS mode */ /* @@ -1094,7 +1082,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) cause == IRQ_VS_EXT) { cause = cause - 1; } - env->hstatus = set_field(env->hstatus, HSTATUS_GVA, 0); + write_gva = false; } else if (riscv_cpu_virt_enabled(env)) { /* Trap into HS mode, from virt */ riscv_cpu_swap_hypervisor_regs(env); @@ -1103,6 +1091,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) env->hstatus = set_field(env->hstatus, HSTATUS_SPV, riscv_cpu_virt_enabled(env)); + htval = env->guest_phys_fault_addr; riscv_cpu_set_virt_enabled(env, 0); @@ -1110,7 +1099,9 @@ void riscv_cpu_do_interrupt(CPUState *cs) /* Trap into HS mode */ env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false); htval = env->guest_phys_fault_addr; + write_gva = false; } + env->hstatus = set_field(env->hstatus, HSTATUS_GVA, write_gva); } s = env->mstatus; From 48eaeb56debf91817dea00a2cd9c1f6c986eb531 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 20 Dec 2021 16:49:16 +1000 Subject: [PATCH 319/730] target/riscv: Implement the stval/mtval illegal instruction The stval and mtval registers can optionally contain the faulting instruction on an illegal instruction exception. This patch adds support for setting the stval and mtval registers. The RISC-V spec states that "The stval register can optionally also be used to return the faulting instruction bits on an illegal instruction exception...". In this case we are always writing the value on an illegal instruction. This doesn't match all CPUs (some CPUs won't write the data), but in QEMU let's just populate the value on illegal instructions. This won't break any guest software, but will provide more information to guests. Signed-off-by: Alistair Francis Reviewed-by: Richard Henderson Reviewed-by: Bin Meng Message-id: 20211220064916.107241-4-alistair.francis@opensource.wdc.com --- target/riscv/cpu.h | 2 ++ target/riscv/cpu_helper.c | 3 +++ target/riscv/translate.c | 3 +++ 3 files changed, 8 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 9ee01f761f..4d63086765 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -132,6 +132,8 @@ struct CPURISCVState { target_ulong frm; target_ulong badaddr; + uint32_t bins; + target_ulong guest_phys_fault_addr; target_ulong priv_ver; diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index ddacb8533a..434a83e66a 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -1038,6 +1038,9 @@ void riscv_cpu_do_interrupt(CPUState *cs) write_gva = true; tval = env->badaddr; break; + case RISCV_EXCP_ILLEGAL_INST: + tval = env->bins; + break; default: break; } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 9e4f9c3342..615048ec87 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -208,6 +208,9 @@ static void generate_exception_mtval(DisasContext *ctx, int excp) static void gen_exception_illegal(DisasContext *ctx) { + tcg_gen_st_i32(tcg_constant_i32(ctx->opcode), cpu_env, + offsetof(CPURISCVState, bins)); + generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST); } From 73d72229fca1950a1ae48843680ba0adcf1518e2 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 4 Nov 2021 16:31:27 -0600 Subject: [PATCH 320/730] bsd-user/mips*: Remove mips support FreeBSD is dropping support for mips starting with FreeBSD 14. mips support has been removed from the bsd-user fork because updating it for new signal requirements will take too much time. Remove it here since it is a distraction. Signed-off-by: Warner Losh Acked-by: Richard Henderson --- bsd-user/mips/target_arch_sysarch.h | 69 --------------------------- bsd-user/mips/target_syscall.h | 52 -------------------- bsd-user/mips64/target_arch_sysarch.h | 69 --------------------------- bsd-user/mips64/target_syscall.h | 53 -------------------- 4 files changed, 243 deletions(-) delete mode 100644 bsd-user/mips/target_arch_sysarch.h delete mode 100644 bsd-user/mips/target_syscall.h delete mode 100644 bsd-user/mips64/target_arch_sysarch.h delete mode 100644 bsd-user/mips64/target_syscall.h diff --git a/bsd-user/mips/target_arch_sysarch.h b/bsd-user/mips/target_arch_sysarch.h deleted file mode 100644 index 6da803a408..0000000000 --- a/bsd-user/mips/target_arch_sysarch.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * mips sysarch() system call emulation - * - * Copyright (c) 2013 Stacey D. Son - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#ifndef BSD_USER_ARCH_SYSARCH_H_ -#define BSD_USER_ARCH_SYSARCH_H_ - -#include "target_syscall.h" -#include "target_arch.h" - -static inline abi_long do_freebsd_arch_sysarch(CPUMIPSState *env, int op, - abi_ulong parms) -{ - int ret = 0; - - switch (op) { - case TARGET_MIPS_SET_TLS: - target_cpu_set_tls(env, parms); - break; - - case TARGET_MIPS_GET_TLS: - if (put_user(target_cpu_get_tls(env), parms, abi_ulong)) { - ret = -TARGET_EFAULT; - } - break; - - default: - ret = -TARGET_EINVAL; - break; - } - - return ret; -} - -static inline void do_freebsd_arch_print_sysarch( - const struct syscallname *name, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) -{ - - switch (arg1) { - case TARGET_MIPS_SET_TLS: - gemu_log("%s(SET_TLS, 0x" TARGET_ABI_FMT_lx ")", name->name, arg2); - break; - - case TARGET_MIPS_GET_TLS: - gemu_log("%s(GET_TLS, 0x" TARGET_ABI_FMT_lx ")", name->name, arg2); - break; - - default: - gemu_log("UNKNOWN OP: %d, " TARGET_ABI_FMT_lx ")", (int)arg1, arg2); - } -} - -#endif /*!BSD_USER_ARCH_SYSARCH_H_ */ diff --git a/bsd-user/mips/target_syscall.h b/bsd-user/mips/target_syscall.h deleted file mode 100644 index aacc6ddf9f..0000000000 --- a/bsd-user/mips/target_syscall.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * mips system call definitions - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ -#ifndef _MIPS_SYSCALL_H_ -#define _MIPS_SYSCALL_H_ - -/* - * struct target_pt_regs defines the way the registers are stored on the stack - * during a system call. - */ - -struct target_pt_regs { - /* Saved main processor registers. */ - abi_ulong regs[32]; - - /* Saved special registers. */ - abi_ulong cp0_status; - abi_ulong lo; - abi_ulong hi; - abi_ulong cp0_badvaddr; - abi_ulong cp0_cause; - abi_ulong cp0_epc; -}; - -#if defined(TARGET_WORDS_BIGENDIAN) -#define UNAME_MACHINE "mips" -#else -#define UNAME_MACHINE "mipsel" -#endif - -#define TARGET_HW_MACHINE "mips" -#define TARGET_HW_MACHINE_ARCH UNAME_MACHINE - -/* sysarch() commands */ -#define TARGET_MIPS_SET_TLS 1 -#define TARGET_MIPS_GET_TLS 2 - -#endif /* !_MIPS_SYSCALL_H_ */ diff --git a/bsd-user/mips64/target_arch_sysarch.h b/bsd-user/mips64/target_arch_sysarch.h deleted file mode 100644 index e6f9c00d5f..0000000000 --- a/bsd-user/mips64/target_arch_sysarch.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * mips64 sysarch() system call emulation - * - * Copyright (c) 2013 Stacey D. Son - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#ifndef BSD_USER_ARCH_SYSARCH_H_ -#define BSD_USER_ARCH_SYSARCH_H_ - -#include "target_syscall.h" -#include "target_arch.h" - -static inline abi_long do_freebsd_arch_sysarch(CPUMIPSState *env, int op, - abi_ulong parms) -{ - int ret = 0; - - switch (op) { - case TARGET_MIPS_SET_TLS: - target_cpu_set_tls(env, parms); - break; - - case TARGET_MIPS_GET_TLS: - if (put_user(target_cpu_get_tls(env), parms, abi_ulong)) { - ret = -TARGET_EFAULT; - } - break; - - default: - ret = -TARGET_EINVAL; - break; - } - - return ret; -} - -static inline void do_freebsd_arch_print_sysarch( - const struct syscallname *name, abi_long arg1, abi_long arg2, - abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) -{ - - switch (arg1) { - case TARGET_MIPS_SET_TLS: - gemu_log("%s(SET_TLS, 0x" TARGET_ABI_FMT_lx ")", name->name, arg2); - break; - - case TARGET_MIPS_GET_TLS: - gemu_log("%s(GET_TLS, 0x" TARGET_ABI_FMT_lx ")", name->name, arg2); - break; - - default: - gemu_log("UNKNOWN OP: %d, " TARGET_ABI_FMT_lx ")", (int)arg1, arg2); - } -} - -#endif /*!BSD_USER_ARCH_SYSARCH_H_ */ diff --git a/bsd-user/mips64/target_syscall.h b/bsd-user/mips64/target_syscall.h deleted file mode 100644 index bf4c598b13..0000000000 --- a/bsd-user/mips64/target_syscall.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * mips64 system call definitions - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ -#ifndef _MIPS64_SYSCALL_H_ -#define _MIPS64_SYSCALL_H_ - -/* - * struct target_pt_regs defines the way the registers are stored on the stack - * during a system call. - */ - -struct target_pt_regs { - /* Saved main processor registers. */ - abi_ulong regs[32]; - - /* Saved special registers. */ - abi_ulong cp0_status; - abi_ulong lo; - abi_ulong hi; - abi_ulong cp0_badvaddr; - abi_ulong cp0_cause; - abi_ulong cp0_epc; -}; - - -#if defined(TARGET_WORDS_BIGENDIAN) -#define UNAME_MACHINE "mips64" -#else -#define UNAME_MACHINE "mips64el" -#endif - -#define TARGET_HW_MACHINE "mips" -#define TARGET_HW_MACHINE_ARCH UNAME_MACHINE - -/* sysarch() commands */ -#define TARGET_MIPS_SET_TLS 1 -#define TARGET_MIPS_GET_TLS 2 - -#endif /* !_MIPS64_SYSCALL_H_ */ From aa3a2428308fe6831ce4b2f9d28ff8572b74f6c4 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 29 Oct 2021 08:39:01 -0600 Subject: [PATCH 321/730] bsd-user/freebsd: Create common target_os_ucontext.h file FreeBSD has a MI ucontext structure that contains the MD mcontext machine state and other things that are machine independent. Create an include file for all the ucontext stuff. It needs to be included in the arch specific files after target_mcontext is defined. This is largely copied from sys/_ucontext.h with the comments about layout removed because we don't support ancient FreeBSD binaries. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/freebsd/target_os_signal.h | 3 --- bsd-user/freebsd/target_os_ucontext.h | 35 +++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 bsd-user/freebsd/target_os_ucontext.h diff --git a/bsd-user/freebsd/target_os_signal.h b/bsd-user/freebsd/target_os_signal.h index 1a4c5faf19..3ed454e086 100644 --- a/bsd-user/freebsd/target_os_signal.h +++ b/bsd-user/freebsd/target_os_signal.h @@ -1,9 +1,6 @@ #ifndef _TARGET_OS_SIGNAL_H_ #define _TARGET_OS_SIGNAL_H_ -/* FreeBSD's sys/ucontext.h defines this */ -#define TARGET_MC_GET_CLEAR_RET 0x0001 - #include "target_os_siginfo.h" #include "target_arch_signal.h" diff --git a/bsd-user/freebsd/target_os_ucontext.h b/bsd-user/freebsd/target_os_ucontext.h new file mode 100644 index 0000000000..1d0c3c4e65 --- /dev/null +++ b/bsd-user/freebsd/target_os_ucontext.h @@ -0,0 +1,35 @@ +/* + * FreeBSD has a common ucontext definition for all architectures. + * + * Copyright 2021 Warner Losh + * + * SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause + */ +#ifndef TARGET_OS_UCONTEXT_H +#define TARGET_OS_UCONTEXT_H + +/* + * Defines the common bits for all of FreeBSD's architectures. Has to be + * included AFTER the MD target_mcontext_t is defined, however, so can't + * be in the grab-bag that is target_os_signal.h. + */ + +/* See FreeBSD's sys/ucontext.h */ +#define TARGET_MC_GET_CLEAR_RET 0x0001 + +/* FreeBSD's sys/_ucontext.h structures */ +typedef struct target_ucontext { + target_sigset_t uc_sigmask; + target_mcontext_t uc_mcontext; + abi_ulong uc_link; + target_stack_t uc_stack; + int32_t uc_flags; + int32_t __spare__[4]; +} target_ucontext_t; + +#ifdef TARGET_MCONTEXT_SIZE +G_STATIC_ASSERT(TARGET_MCONTEXT_SIZE == sizeof(target_mcontext_t)); +G_STATIC_ASSERT(TARGET_UCONTEXT_SIZE == sizeof(target_ucontext_t)); +#endif /* TARGET_MCONTEXT_SIZE */ + +#endif /* TARGET_OS_UCONTEXT_H */ From 19bf129f8245a0f53130cb368ef616a0c362b8f4 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 4 Nov 2021 16:34:48 -0600 Subject: [PATCH 322/730] bsd-user: create a per-arch signal.c file Create a place-holder signal.c file for each of the architectures that are currently built. In the future, some code that's currently inlined in target_arch_signal.h will live here. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/i386/signal.c | 1 + bsd-user/x86_64/signal.c | 1 + meson.build | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 bsd-user/i386/signal.c create mode 100644 bsd-user/x86_64/signal.c diff --git a/bsd-user/i386/signal.c b/bsd-user/i386/signal.c new file mode 100644 index 0000000000..ac90323365 --- /dev/null +++ b/bsd-user/i386/signal.c @@ -0,0 +1 @@ +/* Placeholder for signal.c */ diff --git a/bsd-user/x86_64/signal.c b/bsd-user/x86_64/signal.c new file mode 100644 index 0000000000..ac90323365 --- /dev/null +++ b/bsd-user/x86_64/signal.c @@ -0,0 +1 @@ +/* Placeholder for signal.c */ diff --git a/meson.build b/meson.build index 53065e96ec..c1b1db1e28 100644 --- a/meson.build +++ b/meson.build @@ -2933,7 +2933,7 @@ foreach target : target_dirs base_dir = 'bsd-user' target_inc += include_directories('bsd-user/' / targetos) dir = base_dir / abi - arch_srcs += files(dir / 'target_arch_cpu.c') + arch_srcs += files(dir / 'signal.c', dir / 'target_arch_cpu.c') endif target_inc += include_directories( base_dir, From 4dca396631a10f85065a3c71639f1655a96bcdbe Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 29 Oct 2021 08:25:45 -0600 Subject: [PATCH 323/730] bsd-user/i386/target_arch_signal.h: Remove target_sigcontext In FreeBSD, sigcontext was retired in favor of ucontext/mcontext. Remove vestigial target_sigcontext. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/i386/target_arch_signal.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/bsd-user/i386/target_arch_signal.h b/bsd-user/i386/target_arch_signal.h index a90750d602..e262667bda 100644 --- a/bsd-user/i386/target_arch_signal.h +++ b/bsd-user/i386/target_arch_signal.h @@ -27,10 +27,6 @@ #define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */ #define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */ -struct target_sigcontext { - /* to be added */ -}; - typedef struct target_mcontext { } target_mcontext_t; From c504713f34fb127179496ba3e680689d38e29764 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 29 Oct 2021 09:07:59 -0600 Subject: [PATCH 324/730] bsd-user/i386/target_arch_signal.h: use new target_os_ucontext.h Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/i386/target_arch_signal.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/bsd-user/i386/target_arch_signal.h b/bsd-user/i386/target_arch_signal.h index e262667bda..bf7263c4f8 100644 --- a/bsd-user/i386/target_arch_signal.h +++ b/bsd-user/i386/target_arch_signal.h @@ -30,14 +30,7 @@ typedef struct target_mcontext { } target_mcontext_t; -typedef struct target_ucontext { - target_sigset_t uc_sigmask; - target_mcontext_t uc_mcontext; - abi_ulong uc_link; - target_stack_t uc_stack; - int32_t uc_flags; - int32_t __spare__[4]; -} target_ucontext_t; +#include "target_os_ucontext.h" struct target_sigframe { abi_ulong sf_signum; From 679041b1efc03cb6ff2343024b5d209d1fc231f1 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 4 Nov 2021 16:41:55 -0600 Subject: [PATCH 325/730] bsd-user/i386/target_arch_signal.h: Update mcontext_t to match FreeBSD Fill in target_mcontext_t to match the FreeBSD mcontex_t. Also tag the current size of mcontext and ucontext to enable size checking for i386. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/i386/target_arch_signal.h | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/bsd-user/i386/target_arch_signal.h b/bsd-user/i386/target_arch_signal.h index bf7263c4f8..701c6f964f 100644 --- a/bsd-user/i386/target_arch_signal.h +++ b/bsd-user/i386/target_arch_signal.h @@ -28,8 +28,54 @@ #define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */ typedef struct target_mcontext { + abi_ulong mc_onstack; /* XXX - sigcontext compat. */ + abi_ulong mc_gs; /* machine state (struct trapframe) */ + abi_ulong mc_fs; + abi_ulong mc_es; + abi_ulong mc_ds; + abi_ulong mc_edi; + abi_ulong mc_esi; + abi_ulong mc_ebp; + abi_ulong mc_isp; + abi_ulong mc_ebx; + abi_ulong mc_edx; + abi_ulong mc_ecx; + abi_ulong mc_eax; + abi_ulong mc_trapno; + abi_ulong mc_err; + abi_ulong mc_eip; + abi_ulong mc_cs; + abi_ulong mc_eflags; + abi_ulong mc_esp; + abi_ulong mc_ss; + + int32_t mc_len; /* sizeof(mcontext_t) */ +#define _MC_FPFMT_NODEV 0x10000 /* device not present or configured */ +#define _MC_FPFMT_387 0x10001 +#define _MC_FPFMT_XMM 0x10002 + int32_t mc_fpformat; +#define _MC_FPOWNED_NONE 0x20000 /* FP state not used */ +#define _MC_FPOWNED_FPU 0x20001 /* FP state came from FPU */ +#define _MC_FPOWNED_PCB 0x20002 /* FP state came from PCB */ + int32_t mc_ownedfp; + abi_ulong mc_flags; + /* + * See for the internals of mc_fpstate[]. + */ + int32_t mc_fpstate[128] __aligned(16); + + abi_ulong mc_fsbase; + abi_ulong mc_gsbase; + + abi_ulong mc_xfpustate; + abi_ulong mc_xfpustate_len; + + int32_t mc_spare2[4]; } target_mcontext_t; +#define TARGET_MCONTEXT_SIZE 640 +#define TARGET_UCONTEXT_SIZE 704 + #include "target_os_ucontext.h" struct target_sigframe { From f7d5ed6184ef4fe4cc4ad168d15e2aa6d399b712 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 4 Nov 2021 16:45:26 -0600 Subject: [PATCH 326/730] bsd-user/i386: Move the inlines into signal.c Move the (now stubbed out) inlines into bsd-user/i386/signal.c. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/i386/signal.c | 56 +++++++++++++++++++++++++++++- bsd-user/i386/target_arch_signal.h | 43 +++++------------------ 2 files changed, 63 insertions(+), 36 deletions(-) diff --git a/bsd-user/i386/signal.c b/bsd-user/i386/signal.c index ac90323365..2939d32400 100644 --- a/bsd-user/i386/signal.c +++ b/bsd-user/i386/signal.c @@ -1 +1,55 @@ -/* Placeholder for signal.c */ +/* + * i386 dependent signal definitions + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "qemu.h" + +/* + * Compare to i386/i386/machdep.c sendsig() + * Assumes that target stack frame memory is locked. + */ +abi_long set_sigtramp_args(CPUX86State *env, int sig, + struct target_sigframe *frame, + abi_ulong frame_addr, + struct target_sigaction *ka) +{ + /* XXX return -TARGET_EOPNOTSUPP; */ + return 0; +} + +/* Compare to i386/i386/machdep.c get_mcontext() */ +abi_long get_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int flags) +{ + /* XXX */ + return -TARGET_EOPNOTSUPP; +} + +/* Compare to i386/i386/machdep.c set_mcontext() */ +abi_long set_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int srflag) +{ + /* XXX */ + return -TARGET_EOPNOTSUPP; +} + +abi_long get_ucontext_sigreturn(CPUX86State *regs, abi_ulong target_sf, + abi_ulong *target_uc) +{ + /* XXX */ + *target_uc = 0; + return -TARGET_EOPNOTSUPP; +} diff --git a/bsd-user/i386/target_arch_signal.h b/bsd-user/i386/target_arch_signal.h index 701c6f964f..982c7035c7 100644 --- a/bsd-user/i386/target_arch_signal.h +++ b/bsd-user/i386/target_arch_signal.h @@ -88,40 +88,13 @@ struct target_sigframe { uint32_t __spare__[2]; }; -/* - * Compare to i386/i386/machdep.c sendsig() - * Assumes that target stack frame memory is locked. - */ -static inline abi_long set_sigtramp_args(CPUX86State *regs, - int sig, struct target_sigframe *frame, abi_ulong frame_addr, - struct target_sigaction *ka) -{ - /* XXX return -TARGET_EOPNOTSUPP; */ - return 0; -} - -/* Compare to i386/i386/machdep.c get_mcontext() */ -static inline abi_long get_mcontext(CPUX86State *regs, - target_mcontext_t *mcp, int flags) -{ - /* XXX */ - return -TARGET_EOPNOTSUPP; -} - -/* Compare to i386/i386/machdep.c set_mcontext() */ -static inline abi_long set_mcontext(CPUX86State *regs, - target_mcontext_t *mcp, int srflag) -{ - /* XXX */ - return -TARGET_EOPNOTSUPP; -} - -static inline abi_long get_ucontext_sigreturn(CPUX86State *regs, - abi_ulong target_sf, abi_ulong *target_uc) -{ - /* XXX */ - *target_uc = 0; - return -TARGET_EOPNOTSUPP; -} +abi_long set_sigtramp_args(CPUX86State *env, int sig, + struct target_sigframe *frame, + abi_ulong frame_addr, + struct target_sigaction *ka); +abi_long get_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int flags); +abi_long set_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int srflag); +abi_long get_ucontext_sigreturn(CPUX86State *regs, abi_ulong target_sf, + abi_ulong *target_uc); #endif /* TARGET_ARCH_SIGNAL_H */ From fc1fc2c78e5d1f60faa50e75ecc7b8aefca322c3 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 29 Oct 2021 08:27:50 -0600 Subject: [PATCH 327/730] bsd-user/x86_64/target_arch_signal.h: Remove target_sigcontext In FreeBSD, sigcontext was retired in favor of ucontext/mcontext. Remove vestigial target_sigcontext. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/x86_64/target_arch_signal.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/bsd-user/x86_64/target_arch_signal.h b/bsd-user/x86_64/target_arch_signal.h index 4bb753b08b..55f742b0a8 100644 --- a/bsd-user/x86_64/target_arch_signal.h +++ b/bsd-user/x86_64/target_arch_signal.h @@ -27,10 +27,6 @@ #define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */ #define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */ -struct target_sigcontext { - /* to be added */ -}; - typedef struct target_mcontext { } target_mcontext_t; From c104b7505b890cfbd4af3fc8b891b779496ba274 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 29 Oct 2021 09:07:02 -0600 Subject: [PATCH 328/730] bsd-user/x86_64/target_arch_signal.h: use new target_os_ucontext.h Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/x86_64/target_arch_signal.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/bsd-user/x86_64/target_arch_signal.h b/bsd-user/x86_64/target_arch_signal.h index 55f742b0a8..e84aff948c 100644 --- a/bsd-user/x86_64/target_arch_signal.h +++ b/bsd-user/x86_64/target_arch_signal.h @@ -30,14 +30,7 @@ typedef struct target_mcontext { } target_mcontext_t; -typedef struct target_ucontext { - target_sigset_t uc_sigmask; - target_mcontext_t uc_mcontext; - abi_ulong uc_link; - target_stack_t uc_stack; - int32_t uc_flags; - int32_t __spare__[4]; -} target_ucontext_t; +#include "target_os_ucontext.h" struct target_sigframe { abi_ulong sf_signum; From 164f94bc3033011ea9899988d33659239cacb67e Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 4 Nov 2021 16:51:50 -0600 Subject: [PATCH 329/730] bsd-user/x86_64/target_arch_signal.h: Fill in mcontext_t Fill in target_mcontext match the FreeBSD mcontext_t structure. Also define the size correctly. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/x86_64/target_arch_signal.h | 54 ++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/bsd-user/x86_64/target_arch_signal.h b/bsd-user/x86_64/target_arch_signal.h index e84aff948c..720e3939c3 100644 --- a/bsd-user/x86_64/target_arch_signal.h +++ b/bsd-user/x86_64/target_arch_signal.h @@ -28,8 +28,62 @@ #define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */ typedef struct target_mcontext { + abi_ulong mc_onstack; /* XXX - sigcontext compat. */ + abi_ulong mc_rdi; /* machine state (struct trapframe) */ + abi_ulong mc_rsi; + abi_ulong mc_rdx; + abi_ulong mc_rcx; + abi_ulong mc_r8; + abi_ulong mc_r9; + abi_ulong mc_rax; + abi_ulong mc_rbx; + abi_ulong mc_rbp; + abi_ulong mc_r10; + abi_ulong mc_r11; + abi_ulong mc_r12; + abi_ulong mc_r13; + abi_ulong mc_r14; + abi_ulong mc_r15; + uint32_t mc_trapno; + uint16_t mc_fs; + uint16_t mc_gs; + abi_ulong mc_addr; + uint32_t mc_flags; + uint16_t mc_es; + uint16_t mc_ds; + abi_ulong mc_err; + abi_ulong mc_rip; + abi_ulong mc_cs; + abi_ulong mc_rflags; + abi_ulong mc_rsp; + abi_ulong mc_ss; + + abi_long mc_len; /* sizeof(mcontext_t) */ + +#define _MC_FPFMT_NODEV 0x10000 /* device not present or configured */ +#define _MC_FPFMT_XMM 0x10002 + abi_long mc_fpformat; +#define _MC_FPOWNED_NONE 0x20000 /* FP state not used */ +#define _MC_FPOWNED_FPU 0x20001 /* FP state came from FPU */ +#define _MC_FPOWNED_PCB 0x20002 /* FP state came from PCB */ + abi_long mc_ownedfp; + /* + * See for the internals of mc_fpstate[]. + */ + abi_long mc_fpstate[64] __aligned(16); + + abi_ulong mc_fsbase; + abi_ulong mc_gsbase; + + abi_ulong mc_xfpustate; + abi_ulong mc_xfpustate_len; + + abi_long mc_spare[4]; } target_mcontext_t; +#define TARGET_MCONTEXT_SIZE 800 +#define TARGET_UCONTEXT_SIZE 880 + #include "target_os_ucontext.h" struct target_sigframe { From 1b4e358a614fc6b8f2e1e1b26550f7f3e9509c8f Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 4 Nov 2021 16:53:13 -0600 Subject: [PATCH 330/730] bsd-user/x86_64: Move functions into signal.c Move the current inline functions into sigal.c. This will increate the flexibility of implementation in the future. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/x86_64/signal.c | 56 +++++++++++++++++++++++++++- bsd-user/x86_64/target_arch_signal.h | 43 ++++----------------- 2 files changed, 63 insertions(+), 36 deletions(-) diff --git a/bsd-user/x86_64/signal.c b/bsd-user/x86_64/signal.c index ac90323365..8885152a7d 100644 --- a/bsd-user/x86_64/signal.c +++ b/bsd-user/x86_64/signal.c @@ -1 +1,55 @@ -/* Placeholder for signal.c */ +/* + * x86_64 signal definitions + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "qemu.h" + +/* + * Compare to amd64/amd64/machdep.c sendsig() + * Assumes that target stack frame memory is locked. + */ +abi_long set_sigtramp_args(CPUX86State *regs, + int sig, struct target_sigframe *frame, abi_ulong frame_addr, + struct target_sigaction *ka) +{ + /* XXX return -TARGET_EOPNOTSUPP; */ + return 0; +} + +/* Compare to amd64/amd64/machdep.c get_mcontext() */ +abi_long get_mcontext(CPUX86State *regs, + target_mcontext_t *mcp, int flags) +{ + /* XXX */ + return -TARGET_EOPNOTSUPP; +} + +/* Compare to amd64/amd64/machdep.c set_mcontext() */ +abi_long set_mcontext(CPUX86State *regs, + target_mcontext_t *mcp, int srflag) +{ + /* XXX */ + return -TARGET_EOPNOTSUPP; +} + +abi_long get_ucontext_sigreturn(CPUX86State *regs, + abi_ulong target_sf, abi_ulong *target_uc) +{ + /* XXX */ + *target_uc = 0; + return -TARGET_EOPNOTSUPP; +} diff --git a/bsd-user/x86_64/target_arch_signal.h b/bsd-user/x86_64/target_arch_signal.h index 720e3939c3..b39b70466e 100644 --- a/bsd-user/x86_64/target_arch_signal.h +++ b/bsd-user/x86_64/target_arch_signal.h @@ -96,40 +96,13 @@ struct target_sigframe { uint32_t __spare__[2]; }; -/* - * Compare to amd64/amd64/machdep.c sendsig() - * Assumes that target stack frame memory is locked. - */ -static inline abi_long set_sigtramp_args(CPUX86State *regs, - int sig, struct target_sigframe *frame, abi_ulong frame_addr, - struct target_sigaction *ka) -{ - /* XXX return -TARGET_EOPNOTSUPP; */ - return 0; -} - -/* Compare to amd64/amd64/machdep.c get_mcontext() */ -static inline abi_long get_mcontext(CPUX86State *regs, - target_mcontext_t *mcp, int flags) -{ - /* XXX */ - return -TARGET_EOPNOTSUPP; -} - -/* Compare to amd64/amd64/machdep.c set_mcontext() */ -static inline abi_long set_mcontext(CPUX86State *regs, - target_mcontext_t *mcp, int srflag) -{ - /* XXX */ - return -TARGET_EOPNOTSUPP; -} - -static inline abi_long get_ucontext_sigreturn(CPUX86State *regs, - abi_ulong target_sf, abi_ulong *target_uc) -{ - /* XXX */ - *target_uc = 0; - return -TARGET_EOPNOTSUPP; -} +abi_long set_sigtramp_args(CPUX86State *env, int sig, + struct target_sigframe *frame, + abi_ulong frame_addr, + struct target_sigaction *ka); +abi_long get_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int flags); +abi_long set_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int srflag); +abi_long get_ucontext_sigreturn(CPUX86State *regs, abi_ulong target_sf, + abi_ulong *target_uc); #endif /* !TARGET_ARCH_SIGNAL_H_ */ From 108fffe53601d46c38efd44d4094bbb211cb73e3 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Fri, 5 Nov 2021 10:55:35 -0600 Subject: [PATCH 331/730] bsd-user/target_os_signal.h: Move signal prototypes to target_os_ucontext.h Switch to the CPUArchState typedef and move target-provided prototypes to target_os_ucontext.h. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/freebsd/target_os_ucontext.h | 11 +++++++++++ bsd-user/i386/target_arch_signal.h | 9 --------- bsd-user/x86_64/target_arch_signal.h | 9 --------- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/bsd-user/freebsd/target_os_ucontext.h b/bsd-user/freebsd/target_os_ucontext.h index 1d0c3c4e65..dd61aec7cc 100644 --- a/bsd-user/freebsd/target_os_ucontext.h +++ b/bsd-user/freebsd/target_os_ucontext.h @@ -32,4 +32,15 @@ G_STATIC_ASSERT(TARGET_MCONTEXT_SIZE == sizeof(target_mcontext_t)); G_STATIC_ASSERT(TARGET_UCONTEXT_SIZE == sizeof(target_ucontext_t)); #endif /* TARGET_MCONTEXT_SIZE */ +struct target_sigframe; + +abi_long set_sigtramp_args(CPUArchState *env, int sig, + struct target_sigframe *frame, + abi_ulong frame_addr, + struct target_sigaction *ka); +abi_long get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags); +abi_long set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int srflag); +abi_long get_ucontext_sigreturn(CPUArchState *regs, abi_ulong target_sf, + abi_ulong *target_uc); + #endif /* TARGET_OS_UCONTEXT_H */ diff --git a/bsd-user/i386/target_arch_signal.h b/bsd-user/i386/target_arch_signal.h index 982c7035c7..279dadc22c 100644 --- a/bsd-user/i386/target_arch_signal.h +++ b/bsd-user/i386/target_arch_signal.h @@ -88,13 +88,4 @@ struct target_sigframe { uint32_t __spare__[2]; }; -abi_long set_sigtramp_args(CPUX86State *env, int sig, - struct target_sigframe *frame, - abi_ulong frame_addr, - struct target_sigaction *ka); -abi_long get_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int flags); -abi_long set_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int srflag); -abi_long get_ucontext_sigreturn(CPUX86State *regs, abi_ulong target_sf, - abi_ulong *target_uc); - #endif /* TARGET_ARCH_SIGNAL_H */ diff --git a/bsd-user/x86_64/target_arch_signal.h b/bsd-user/x86_64/target_arch_signal.h index b39b70466e..b4a0ebf2bd 100644 --- a/bsd-user/x86_64/target_arch_signal.h +++ b/bsd-user/x86_64/target_arch_signal.h @@ -96,13 +96,4 @@ struct target_sigframe { uint32_t __spare__[2]; }; -abi_long set_sigtramp_args(CPUX86State *env, int sig, - struct target_sigframe *frame, - abi_ulong frame_addr, - struct target_sigaction *ka); -abi_long get_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int flags); -abi_long set_mcontext(CPUX86State *regs, target_mcontext_t *mcp, int srflag); -abi_long get_ucontext_sigreturn(CPUX86State *regs, abi_ulong target_sf, - abi_ulong *target_uc); - #endif /* !TARGET_ARCH_SIGNAL_H_ */ From c186aa67de050ebde0edb23634e356b4e466a76f Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 08:28:24 -0600 Subject: [PATCH 332/730] bsd-user/arm/target_arch_sysarch.h: Use consistent include guards As part of upstreaming, the include guards have been made more consistent. Update this file to use the new guards. Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_sysarch.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bsd-user/arm/target_arch_sysarch.h b/bsd-user/arm/target_arch_sysarch.h index 632a5cd453..8cc6bff207 100644 --- a/bsd-user/arm/target_arch_sysarch.h +++ b/bsd-user/arm/target_arch_sysarch.h @@ -17,8 +17,8 @@ * along with this program; if not, see . */ -#ifndef BSD_USER_ARCH_SYSARCH_H_ -#define BSD_USER_ARCH_SYSARCH_H_ +#ifndef _TARGET_ARCH_SYSARCH_H_ +#define _TARGET_ARCH_SYSARCH_H_ #include "target_syscall.h" #include "target_arch.h" @@ -75,4 +75,4 @@ static inline void do_freebsd_arch_print_sysarch( } } -#endif /*!BSD_USER_ARCH_SYSARCH_H_ */ +#endif /*!_TARGET_ARCH_SYSARCH_H_ */ From 559d09a6cdcc78fe0f977e516b5479b4c9587b7a Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 08:29:39 -0600 Subject: [PATCH 333/730] bsd-user/arm/target_syscall.h: Add copyright and update name The preferred name for the 32-bit arm is now armv7. Update the name to reflect that. In addition, add Stacey's copyright to this file and update the include guards to the new convention. Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_syscall.h | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/bsd-user/arm/target_syscall.h b/bsd-user/arm/target_syscall.h index ef4b37f017..a5f2bb4e01 100644 --- a/bsd-user/arm/target_syscall.h +++ b/bsd-user/arm/target_syscall.h @@ -1,5 +1,24 @@ -#ifndef BSD_USER_ARCH_SYSCALL_H_ -#define BSD_USER_ARCH_SYSCALL_H_ +/* + * arm cpu system call stubs + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _TARGET_ARCH_SYSCALL_H_ +#define _TARGET_ARCH_SYSCALL_H_ struct target_pt_regs { abi_long uregs[17]; @@ -31,6 +50,6 @@ struct target_pt_regs { #define TARGET_FREEBSD_ARM_GET_TP 3 #define TARGET_HW_MACHINE "arm" -#define TARGET_HW_MACHINE_ARCH "armv6" +#define TARGET_HW_MACHINE_ARCH "armv7" -#endif /* !BSD_USER_ARCH_SYSCALL_H_ */ +#endif /* !_TARGET_ARCH_SYSCALL_H_ */ From 8c98705bb933f58bed743977ee897f67a27d449f Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 08:32:06 -0600 Subject: [PATCH 334/730] bsd-user/arm/target_arch_cpu.c: Target specific TLS routines Target specific TLS routines to get and set the TLS values. Signed-off-by: Kyle Evans Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch.h | 28 ++++++++++++++++++++++++ bsd-user/arm/target_arch_cpu.c | 39 ++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 bsd-user/arm/target_arch.h create mode 100644 bsd-user/arm/target_arch_cpu.c diff --git a/bsd-user/arm/target_arch.h b/bsd-user/arm/target_arch.h new file mode 100644 index 0000000000..93cfaea098 --- /dev/null +++ b/bsd-user/arm/target_arch.h @@ -0,0 +1,28 @@ +/* + * ARM 32-bit specific prototypes for bsd-user + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _TARGET_ARCH_H_ +#define _TARGET_ARCH_H_ + +#include "qemu.h" + +void target_cpu_set_tls(CPUARMState *env, target_ulong newtls); +target_ulong target_cpu_get_tls(CPUARMState *env); + +#endif /* !_TARGET_ARCH_H_ */ diff --git a/bsd-user/arm/target_arch_cpu.c b/bsd-user/arm/target_arch_cpu.c new file mode 100644 index 0000000000..02bf9149d5 --- /dev/null +++ b/bsd-user/arm/target_arch_cpu.c @@ -0,0 +1,39 @@ +/* + * arm cpu related code + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#include "target_arch.h" + +void target_cpu_set_tls(CPUARMState *env, target_ulong newtls) +{ + if (access_secure_reg(env)) { + env->cp15.tpidrurw_s = newtls; + env->cp15.tpidruro_s = newtls; + return; + } + + env->cp15.tpidr_el[0] = newtls; + env->cp15.tpidrro_el[0] = newtls; +} + +target_ulong target_cpu_get_tls(CPUARMState *env) +{ + if (access_secure_reg(env)) { + return env->cp15.tpidruro_s; + } + return env->cp15.tpidrro_el[0]; +} From ca5d32a3f30e4bd01aa36b948e42302f40443501 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 08:41:13 -0600 Subject: [PATCH 335/730] bsd-user/arm/target_arch_cpu.h: CPU Loop definitions target_arch_cpu.h is for CPU loop definitions. Create the file and define target_cpu_init and target_cpu_reset for arm. Signed-off-by: Olivier Houchard Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_cpu.h | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 bsd-user/arm/target_arch_cpu.h diff --git a/bsd-user/arm/target_arch_cpu.h b/bsd-user/arm/target_arch_cpu.h new file mode 100644 index 0000000000..66215684d6 --- /dev/null +++ b/bsd-user/arm/target_arch_cpu.h @@ -0,0 +1,43 @@ +/* + * arm cpu init and loop + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _TARGET_ARCH_CPU_H_ +#define _TARGET_ARCH_CPU_H_ + +#include "target_arch.h" + +#define TARGET_DEFAULT_CPU_MODEL "any" + +static inline void target_cpu_init(CPUARMState *env, + struct target_pt_regs *regs) +{ + int i; + + cpsr_write(env, regs->uregs[16], CPSR_USER | CPSR_EXEC, + CPSRWriteByInstr); + for (i = 0; i < 16; i++) { + env->regs[i] = regs->uregs[i]; + } +} + +static inline void target_cpu_reset(CPUArchState *cpu) +{ +} + +#endif /* !_TARGET_ARCH_CPU_H */ From e17d4c9a3701ca22170cd3bbbd42c9eddad97e84 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 08:44:05 -0600 Subject: [PATCH 336/730] bsd-user/arm/target_arch_cpu.h: Implement target_cpu_clone_regs Implement target_cpu_clone_regs to clone the resister state on a fork. Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_cpu.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bsd-user/arm/target_arch_cpu.h b/bsd-user/arm/target_arch_cpu.h index 66215684d6..fa45d9335d 100644 --- a/bsd-user/arm/target_arch_cpu.h +++ b/bsd-user/arm/target_arch_cpu.h @@ -36,6 +36,14 @@ static inline void target_cpu_init(CPUARMState *env, } } +static inline void target_cpu_clone_regs(CPUARMState *env, target_ulong newsp) +{ + if (newsp) { + env->regs[13] = newsp; + } + env->regs[0] = 0; +} + static inline void target_cpu_reset(CPUArchState *cpu) { } From 06efe3bfce17576a829fcc7de4d271fe84ca8c9d Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 08:47:16 -0600 Subject: [PATCH 337/730] bsd-user/arm/target_arch_cpu.h: Dummy target_cpu_loop implementation Add a boiler plate CPU loop that does nothing except return an error for all traps. Signed-off-by: Sean Bruno Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_cpu.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/bsd-user/arm/target_arch_cpu.h b/bsd-user/arm/target_arch_cpu.h index fa45d9335d..2484bdc2f7 100644 --- a/bsd-user/arm/target_arch_cpu.h +++ b/bsd-user/arm/target_arch_cpu.h @@ -36,6 +36,28 @@ static inline void target_cpu_init(CPUARMState *env, } } +static inline void target_cpu_loop(CPUARMState *env) +{ + int trapnr; + target_siginfo_t info; + CPUState *cs = env_cpu(env); + + for (;;) { + cpu_exec_start(cs); + trapnr = cpu_exec(cs); + cpu_exec_end(cs); + process_queued_cpu_work(cs); + switch (trapnr) { + default: + fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", + trapnr); + cpu_dump_state(cs, stderr, 0); + abort(); + } /* switch() */ + process_pending_signals(env); + } /* for (;;) */ +} + static inline void target_cpu_clone_regs(CPUARMState *env, target_ulong newsp) { if (newsp) { From 70985aec1c29e34e1de1aec684324073d76d5873 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 08:54:17 -0600 Subject: [PATCH 338/730] bsd-user/arm/target_arch_cpu.h: Implement trivial EXCP exceptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement EXCP_UDEF, EXCP_DEBUG, EXCP_INTERRUPT, EXCP_ATOMIC and EXCP_YIELD. The first two generate a signal to the emulated binary. EXCP_ATOMIC handles atomic operations. The remainder are fancy nops. Signed-off-by: Stacey Son Signed-off-by: Mikaël Urankar Signed-off-by: Kyle Evans Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_cpu.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/bsd-user/arm/target_arch_cpu.h b/bsd-user/arm/target_arch_cpu.h index 2484bdc2f7..9f9b380b13 100644 --- a/bsd-user/arm/target_arch_cpu.h +++ b/bsd-user/arm/target_arch_cpu.h @@ -48,6 +48,39 @@ static inline void target_cpu_loop(CPUARMState *env) cpu_exec_end(cs); process_queued_cpu_work(cs); switch (trapnr) { + case EXCP_UDEF: + { + /* See arm/arm/undefined.c undefinedinstruction(); */ + info.si_addr = env->regs[15]; + + /* illegal instruction */ + info.si_signo = TARGET_SIGILL; + info.si_errno = 0; + info.si_code = TARGET_ILL_ILLOPC; + queue_signal(env, info.si_signo, &info); + + /* TODO: What about instruction emulation? */ + } + break; + case EXCP_INTERRUPT: + /* just indicate that signals should be handled asap */ + break; + case EXCP_DEBUG: + { + + info.si_signo = TARGET_SIGTRAP; + info.si_errno = 0; + info.si_code = TARGET_TRAP_BRKPT; + info.si_addr = env->exception.vaddress; + queue_signal(env, info.si_signo, &info); + } + break; + case EXCP_ATOMIC: + cpu_exec_step_atomic(cs); + break; + case EXCP_YIELD: + /* nothing to do here for user-mode, just resume guest code */ + break; default: fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); From ef1412bd84cd384ee4be34139f750e789ad0f12f Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 08:57:14 -0600 Subject: [PATCH 339/730] bsd-user/arm/target_arch_cpu.h: Implement data abort exceptions Implement EXCP_PREFETCH_ABORT AND EXCP_DATA_ABORT. Both of these data exceptions cause a SIGSEGV. Signed-off-by: Kyle Evans Signed-off-by: Olivier Houchard Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_cpu.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/bsd-user/arm/target_arch_cpu.h b/bsd-user/arm/target_arch_cpu.h index 9f9b380b13..905a5ffaff 100644 --- a/bsd-user/arm/target_arch_cpu.h +++ b/bsd-user/arm/target_arch_cpu.h @@ -65,6 +65,17 @@ static inline void target_cpu_loop(CPUARMState *env) case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; + case EXCP_PREFETCH_ABORT: + /* See arm/arm/trap.c prefetch_abort_handler() */ + case EXCP_DATA_ABORT: + /* See arm/arm/trap.c data_abort_handler() */ + info.si_signo = TARGET_SIGSEGV; + info.si_errno = 0; + /* XXX: check env->error_code */ + info.si_code = 0; + info.si_addr = env->exception.vaddress; + queue_signal(env, info.si_signo, &info); + break; case EXCP_DEBUG: { From 8d450c9a309609f6abc75e036c5c67b1317d1dc6 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 09:08:21 -0600 Subject: [PATCH 340/730] bsd-user/arm/target_arch_cpu.h: Implement system call dispatch Implement the system call dispatch. This implements all three kinds of system call: direct and the two indirect variants. It handles all the special cases for thumb as well. Signed-off-by: Stacey Son Signed-off-by: Kyle Evans Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_cpu.h | 94 ++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/bsd-user/arm/target_arch_cpu.h b/bsd-user/arm/target_arch_cpu.h index 905a5ffaff..c675419c30 100644 --- a/bsd-user/arm/target_arch_cpu.h +++ b/bsd-user/arm/target_arch_cpu.h @@ -40,6 +40,7 @@ static inline void target_cpu_loop(CPUARMState *env) { int trapnr; target_siginfo_t info; + unsigned int n; CPUState *cs = env_cpu(env); for (;;) { @@ -62,6 +63,99 @@ static inline void target_cpu_loop(CPUARMState *env) /* TODO: What about instruction emulation? */ } break; + case EXCP_SWI: + case EXCP_BKPT: + { + /* + * system call + * See arm/arm/trap.c cpu_fetch_syscall_args() + */ + if (trapnr == EXCP_BKPT) { + if (env->thumb) { + env->regs[15] += 2; + } else { + env->regs[15] += 4; + } + } + n = env->regs[7]; + if (bsd_type == target_freebsd) { + int ret; + abi_ulong params = get_sp_from_cpustate(env); + int32_t syscall_nr = n; + int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8; + + /* See arm/arm/trap.c cpu_fetch_syscall_args() */ + if (syscall_nr == TARGET_FREEBSD_NR_syscall) { + syscall_nr = env->regs[0]; + arg1 = env->regs[1]; + arg2 = env->regs[2]; + arg3 = env->regs[3]; + get_user_s32(arg4, params); + params += sizeof(int32_t); + get_user_s32(arg5, params); + params += sizeof(int32_t); + get_user_s32(arg6, params); + params += sizeof(int32_t); + get_user_s32(arg7, params); + arg8 = 0; + } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) { + syscall_nr = env->regs[0]; + arg1 = env->regs[2]; + arg2 = env->regs[3]; + get_user_s32(arg3, params); + params += sizeof(int32_t); + get_user_s32(arg4, params); + params += sizeof(int32_t); + get_user_s32(arg5, params); + params += sizeof(int32_t); + get_user_s32(arg6, params); + arg7 = 0; + arg8 = 0; + } else { + arg1 = env->regs[0]; + arg2 = env->regs[1]; + arg3 = env->regs[2]; + arg4 = env->regs[3]; + get_user_s32(arg5, params); + params += sizeof(int32_t); + get_user_s32(arg6, params); + params += sizeof(int32_t); + get_user_s32(arg7, params); + params += sizeof(int32_t); + get_user_s32(arg8, params); + } + ret = do_freebsd_syscall(env, syscall_nr, arg1, arg2, arg3, + arg4, arg5, arg6, arg7, arg8); + /* + * Compare to arm/arm/vm_machdep.c + * cpu_set_syscall_retval() + */ + if (-TARGET_EJUSTRETURN == ret) { + /* + * Returning from a successful sigreturn syscall. + * Avoid clobbering register state. + */ + break; + } + if (-TARGET_ERESTART == ret) { + env->regs[15] -= env->thumb ? 2 : 4; + break; + } + if ((unsigned int)ret >= (unsigned int)(-515)) { + ret = -ret; + cpsr_write(env, CPSR_C, CPSR_C, CPSRWriteByInstr); + env->regs[0] = ret; + } else { + cpsr_write(env, 0, CPSR_C, CPSRWriteByInstr); + env->regs[0] = ret; /* XXX need to handle lseek()? */ + /* env->regs[1] = 0; */ + } + } else { + fprintf(stderr, "qemu: bsd_type (= %d) syscall " + "not supported\n", bsd_type); + } + } + break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; From bcacf30808ee8cd5f2e1c7104bbbee9d64e7ca6c Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 09:10:27 -0600 Subject: [PATCH 341/730] bsd-user/arm/target_arch_reg.h: Implement core dump register copying Implement the register copying routines to extract registers from the cpu for core dump generation. Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_reg.h | 60 ++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 bsd-user/arm/target_arch_reg.h diff --git a/bsd-user/arm/target_arch_reg.h b/bsd-user/arm/target_arch_reg.h new file mode 100644 index 0000000000..ef5ed5154f --- /dev/null +++ b/bsd-user/arm/target_arch_reg.h @@ -0,0 +1,60 @@ +/* + * FreeBSD arm register structures + * + * Copyright (c) 2015 Stacey Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _TARGET_ARCH_REG_H_ +#define _TARGET_ARCH_REG_H_ + +/* See sys/arm/include/reg.h */ +typedef struct target_reg { + uint32_t r[13]; + uint32_t r_sp; + uint32_t r_lr; + uint32_t r_pc; + uint32_t r_cpsr; +} target_reg_t; + +typedef struct target_fp_reg { + uint32_t fp_exponent; + uint32_t fp_mantissa_hi; + u_int32_t fp_mantissa_lo; +} target_fp_reg_t; + +typedef struct target_fpreg { + uint32_t fpr_fpsr; + target_fp_reg_t fpr[8]; +} target_fpreg_t; + +#define tswapreg(ptr) tswapal(ptr) + +static inline void target_copy_regs(target_reg_t *regs, const CPUARMState *env) +{ + int i; + + for (i = 0; i < 13; i++) { + regs->r[i] = tswapreg(env->regs[i + 1]); + } + regs->r_sp = tswapreg(env->regs[13]); + regs->r_lr = tswapreg(env->regs[14]); + regs->r_pc = tswapreg(env->regs[15]); + regs->r_cpsr = tswapreg(cpsr_read((CPUARMState *)env)); +} + +#undef tswapreg + +#endif /* !_TARGET_ARCH_REG_H_ */ From dacfdf3ba4ac0773a92472d5063166b1553dff59 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 09:12:12 -0600 Subject: [PATCH 342/730] bsd-user/arm/target_arch_vmparam.h: Parameters for arm address space Various parameters describing the layout of the ARM address space. In addition, define routines to get the stack pointer and to set the second return value. Signed-off-by: Stacey Son Signed-off-by: Kyle Evans Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_vmparam.h | 48 ++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 bsd-user/arm/target_arch_vmparam.h diff --git a/bsd-user/arm/target_arch_vmparam.h b/bsd-user/arm/target_arch_vmparam.h new file mode 100644 index 0000000000..4bbc04ddf5 --- /dev/null +++ b/bsd-user/arm/target_arch_vmparam.h @@ -0,0 +1,48 @@ +/* + * arm VM parameters definitions + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#ifndef _TARGET_ARCH_VMPARAM_H_ +#define _TARGET_ARCH_VMPARAM_H_ + +#include "cpu.h" + +/* compare to sys/arm/include/vmparam.h */ +#define TARGET_MAXTSIZ (64 * MiB) /* max text size */ +#define TARGET_DFLDSIZ (128 * MiB) /* initial data size limit */ +#define TARGET_MAXDSIZ (512 * MiB) /* max data size */ +#define TARGET_DFLSSIZ (4 * MiB) /* initial stack size limit */ +#define TARGET_MAXSSIZ (64 * MiB) /* max stack size */ +#define TARGET_SGROWSIZ (128 * KiB) /* amount to grow stack */ + +#define TARGET_RESERVED_VA 0xf7000000 + + /* KERNBASE - 512 MB */ +#define TARGET_VM_MAXUSER_ADDRESS (0xc0000000 - (512 * MiB)) +#define TARGET_USRSTACK TARGET_VM_MAXUSER_ADDRESS + +static inline abi_ulong get_sp_from_cpustate(CPUARMState *state) +{ + return state->regs[13]; /* sp */ +} + +static inline void set_second_rval(CPUARMState *state, abi_ulong retval2) +{ + state->regs[1] = retval2; +} + +#endif /* ! _TARGET_ARCH_VMPARAM_H_ */ From eacb50b8d92452251d890f6bfb4ac8eb22acb8d2 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 09:14:08 -0600 Subject: [PATCH 343/730] bsd-user/arm/target_arch_sigtramp.h: Signal Trampoline for arm Copy of the signal trampoline code for arm, as well as setup_sigtramp to write it to the stack. Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_sigtramp.h | 49 +++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 bsd-user/arm/target_arch_sigtramp.h diff --git a/bsd-user/arm/target_arch_sigtramp.h b/bsd-user/arm/target_arch_sigtramp.h new file mode 100644 index 0000000000..5d434a9e7e --- /dev/null +++ b/bsd-user/arm/target_arch_sigtramp.h @@ -0,0 +1,49 @@ +/* + * arm sysarch() system call emulation + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _TARGET_ARCH_SIGTRAMP_H_ +#define _TARGET_ARCH_SIGTRAMP_H_ + +/* Compare to arm/arm/locore.S ENTRY_NP(sigcode) */ +static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc, + unsigned sys_sigreturn) +{ + int i; + uint32_t sys_exit = TARGET_FREEBSD_NR_exit; + uint32_t sigtramp_code[] = { + /* 1 */ 0xE1A0000D, /* mov r0, sp */ + /* 2 */ 0xE2800000 + sigf_uc, /* add r0, r0, #SIGF_UC */ + /* 3 */ 0xE59F700C, /* ldr r7, [pc, #12] */ + /* 4 */ 0xEF000000 + sys_sigreturn, /* swi (SYS_sigreturn) */ + /* 5 */ 0xE59F7008, /* ldr r7, [pc, #8] */ + /* 6 */ 0xEF000000 + sys_exit, /* swi (SYS_exit)*/ + /* 7 */ 0xEAFFFFFA, /* b . -16 */ + /* 8 */ sys_sigreturn, + /* 9 */ sys_exit + }; + + G_STATIC_ASSERT(sizeof(sigtramp_code) == TARGET_SZSIGCODE); + + for (i = 0; i < 9; i++) { + tswap32s(&sigtramp_code[i]); + } + + return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE); +} +#endif /* _TARGET_ARCH_SIGTRAMP_H_ */ From f10521cc22aec74ad259bee03ca15ae5ee561c6c Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 09:16:15 -0600 Subject: [PATCH 344/730] bsd-user/arm/target_arch_thread.h: Routines to create and switch to a thread Implement target_thread_init (to create a thread) and target_set_upcall (to switch to a thread) for arm. Signed-off-by: Stacey Son Signed-off-by: Kyle Evans Signed-off-by: Warner Losh Reviewed-by: Kyle Evans --- bsd-user/arm/target_arch_thread.h | 82 +++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 bsd-user/arm/target_arch_thread.h diff --git a/bsd-user/arm/target_arch_thread.h b/bsd-user/arm/target_arch_thread.h new file mode 100644 index 0000000000..11c7f76583 --- /dev/null +++ b/bsd-user/arm/target_arch_thread.h @@ -0,0 +1,82 @@ +/* + * arm thread support + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#ifndef _TARGET_ARCH_THREAD_H_ +#define _TARGET_ARCH_THREAD_H_ + +/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */ +static inline void target_thread_set_upcall(CPUARMState *env, abi_ulong entry, + abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size) +{ + abi_ulong sp; + + /* + * Make sure the stack is properly aligned. + * arm/include/param.h (STACKLIGN() macro) + */ + sp = (u_int)(stack_base + stack_size) & ~0x7; + + /* sp = stack base */ + env->regs[13] = sp; + /* pc = start function entry */ + env->regs[15] = entry & 0xfffffffe; + /* r0 = arg */ + env->regs[0] = arg; + env->spsr = ARM_CPU_MODE_USR; + /* + * Thumb mode is encoded by the low bit in the entry point (since ARM can't + * execute at odd addresses). When it's set, set the Thumb bit (T) in the + * CPSR. + */ + cpsr_write(env, (entry & 1) * CPSR_T, CPSR_T, CPSRWriteByInstr); +} + +static inline void target_thread_init(struct target_pt_regs *regs, + struct image_info *infop) +{ + abi_long stack = infop->start_stack; + memset(regs, 0, sizeof(*regs)); + regs->ARM_cpsr = ARM_CPU_MODE_USR; + /* + * Thumb mode is encoded by the low bit in the entry point (since ARM can't + * execute at odd addresses). When it's set, set the Thumb bit (T) in the + * CPSR. + */ + if (infop->entry & 1) { + regs->ARM_cpsr |= CPSR_T; + } + regs->ARM_pc = infop->entry & 0xfffffffe; + regs->ARM_sp = stack; + if (bsd_type == target_freebsd) { + regs->ARM_lr = infop->entry & 0xfffffffe; + } + /* + * FreeBSD kernel passes the ps_strings pointer in r0. This is used by some + * programs to set status messages that we see in ps. bsd-user doesn't + * support that functionality, so it's ignored. When set to 0, FreeBSD's csu + * code ignores it. For the static case, r1 and r2 are effectively ignored + * by the csu __startup() routine. For the dynamic case, rtld saves r0 but + * generates r1 and r2 and passes them into the csu _startup. + * + * r0 ps_strings 0 passed since ps arg setting not supported + * r1 obj_main ignored by _start(), so 0 passed + * r2 cleanup generated by rtld or ignored by _start(), so 0 passed + */ +} + +#endif /* !_TARGET_ARCH_THREAD_H_ */ From 082e65314b807c8b5a5a52e15eb0797765029568 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 14:34:56 -0600 Subject: [PATCH 345/730] bsd-user/arm/target_arch_elf.h: arm defines for ELF Basic set of defines needed for arm ELF file activation. Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_elf.h | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 bsd-user/arm/target_arch_elf.h diff --git a/bsd-user/arm/target_arch_elf.h b/bsd-user/arm/target_arch_elf.h new file mode 100644 index 0000000000..15b5c66511 --- /dev/null +++ b/bsd-user/arm/target_arch_elf.h @@ -0,0 +1,36 @@ +/* + * arm ELF definitions + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#ifndef _TARGET_ARCH_ELF_H_ +#define _TARGET_ARCH_ELF_H_ + +#define ELF_START_MMAP 0x80000000 +#define ELF_ET_DYN_LOAD_ADDR 0x500000 + +#define elf_check_arch(x) ((x) == EM_ARM) + +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_ARM + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 + +#define ELF_HWCAP 0 + +#endif /* _TARGET_ARCH_ELF_H_ */ From 6c5d60fa78d90ba7308b021fd0d33d88475410c5 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 14:42:42 -0600 Subject: [PATCH 346/730] bsd-user/arm/target_arch_elf.h: arm get hwcap Implement get_elf_hwcap to get the first word of hardware capabilities. Signed-off-by: Kyle Evans Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_elf.h | 72 +++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/bsd-user/arm/target_arch_elf.h b/bsd-user/arm/target_arch_elf.h index 15b5c66511..02d25b8926 100644 --- a/bsd-user/arm/target_arch_elf.h +++ b/bsd-user/arm/target_arch_elf.h @@ -31,6 +31,76 @@ #define USE_ELF_CORE_DUMP #define ELF_EXEC_PAGESIZE 4096 -#define ELF_HWCAP 0 +#define ELF_HWCAP get_elf_hwcap() + +#define GET_FEATURE(feat, hwcap) \ + do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0) + +#define GET_FEATURE_ID(feat, hwcap) \ + do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0) + +enum { + ARM_HWCAP_ARM_SWP = 1 << 0, + ARM_HWCAP_ARM_HALF = 1 << 1, + ARM_HWCAP_ARM_THUMB = 1 << 2, + ARM_HWCAP_ARM_26BIT = 1 << 3, + ARM_HWCAP_ARM_FAST_MULT = 1 << 4, + ARM_HWCAP_ARM_FPA = 1 << 5, + ARM_HWCAP_ARM_VFP = 1 << 6, + ARM_HWCAP_ARM_EDSP = 1 << 7, + ARM_HWCAP_ARM_JAVA = 1 << 8, + ARM_HWCAP_ARM_IWMMXT = 1 << 9, + ARM_HWCAP_ARM_CRUNCH = 1 << 10, + ARM_HWCAP_ARM_THUMBEE = 1 << 11, + ARM_HWCAP_ARM_NEON = 1 << 12, + ARM_HWCAP_ARM_VFPv3 = 1 << 13, + ARM_HWCAP_ARM_VFPv3D16 = 1 << 14, + ARM_HWCAP_ARM_TLS = 1 << 15, + ARM_HWCAP_ARM_VFPv4 = 1 << 16, + ARM_HWCAP_ARM_IDIVA = 1 << 17, + ARM_HWCAP_ARM_IDIVT = 1 << 18, + ARM_HWCAP_ARM_VFPD32 = 1 << 19, + ARM_HWCAP_ARM_LPAE = 1 << 20, + ARM_HWCAP_ARM_EVTSTRM = 1 << 21, +}; + +static uint32_t get_elf_hwcap(void) +{ + ARMCPU *cpu = ARM_CPU(thread_cpu); + uint32_t hwcaps = 0; + + hwcaps |= ARM_HWCAP_ARM_SWP; + hwcaps |= ARM_HWCAP_ARM_HALF; + hwcaps |= ARM_HWCAP_ARM_THUMB; + hwcaps |= ARM_HWCAP_ARM_FAST_MULT; + + /* probe for the extra features */ + /* EDSP is in v5TE and above */ + GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP); + GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT); + GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE); + GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON); + GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS); + GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE); + GET_FEATURE_ID(aa32_arm_div, ARM_HWCAP_ARM_IDIVA); + GET_FEATURE_ID(aa32_thumb_div, ARM_HWCAP_ARM_IDIVT); + GET_FEATURE_ID(aa32_vfp, ARM_HWCAP_ARM_VFP); + + if (cpu_isar_feature(aa32_fpsp_v3, cpu) || + cpu_isar_feature(aa32_fpdp_v3, cpu)) { + hwcaps |= ARM_HWCAP_ARM_VFPv3; + if (cpu_isar_feature(aa32_simd_r32, cpu)) { + hwcaps |= ARM_HWCAP_ARM_VFPD32; + } else { + hwcaps |= ARM_HWCAP_ARM_VFPv3D16; + } + } + GET_FEATURE_ID(aa32_simdfmac, ARM_HWCAP_ARM_VFPv4); + + return hwcaps; +} + +#undef GET_FEATURE +#undef GET_FEATURE_ID #endif /* _TARGET_ARCH_ELF_H_ */ From 883d19ccf92d66fcfb72bd1b744cc8a61552419a Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 14:48:18 -0600 Subject: [PATCH 347/730] bsd-user/arm/target_arch_elf.h: arm get_hwcap2 impl Implement the extended HW capabilities for HWCAP2. Signed-off-by: Kyle Evans Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_elf.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/bsd-user/arm/target_arch_elf.h b/bsd-user/arm/target_arch_elf.h index 02d25b8926..4a0215d02e 100644 --- a/bsd-user/arm/target_arch_elf.h +++ b/bsd-user/arm/target_arch_elf.h @@ -32,6 +32,7 @@ #define ELF_EXEC_PAGESIZE 4096 #define ELF_HWCAP get_elf_hwcap() +#define ELF_HWCAP2 get_elf_hwcap2() #define GET_FEATURE(feat, hwcap) \ do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0) @@ -64,6 +65,14 @@ enum { ARM_HWCAP_ARM_EVTSTRM = 1 << 21, }; +enum { + ARM_HWCAP2_ARM_AES = 1 << 0, + ARM_HWCAP2_ARM_PMULL = 1 << 1, + ARM_HWCAP2_ARM_SHA1 = 1 << 2, + ARM_HWCAP2_ARM_SHA2 = 1 << 3, + ARM_HWCAP2_ARM_CRC32 = 1 << 4, +}; + static uint32_t get_elf_hwcap(void) { ARMCPU *cpu = ARM_CPU(thread_cpu); @@ -100,6 +109,19 @@ static uint32_t get_elf_hwcap(void) return hwcaps; } +static uint32_t get_elf_hwcap2(void) +{ + ARMCPU *cpu = ARM_CPU(thread_cpu); + uint32_t hwcaps = 0; + + GET_FEATURE_ID(aa32_aes, ARM_HWCAP2_ARM_AES); + GET_FEATURE_ID(aa32_pmull, ARM_HWCAP2_ARM_PMULL); + GET_FEATURE_ID(aa32_sha1, ARM_HWCAP2_ARM_SHA1); + GET_FEATURE_ID(aa32_sha2, ARM_HWCAP2_ARM_SHA2); + GET_FEATURE_ID(aa32_crc32, ARM_HWCAP2_ARM_CRC32); + return hwcaps; +} + #undef GET_FEATURE #undef GET_FEATURE_ID From 156d75579f116e7da27c3c26a0964d43ba3076d2 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 15:15:08 -0600 Subject: [PATCH 348/730] bsd-user/arm/target_arch_signal.h: arm specific signal registers and stack Defines for registers and stack layout related to signals. Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Kyle Evans Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_signal.h | 57 +++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 bsd-user/arm/target_arch_signal.h diff --git a/bsd-user/arm/target_arch_signal.h b/bsd-user/arm/target_arch_signal.h new file mode 100644 index 0000000000..973183d99c --- /dev/null +++ b/bsd-user/arm/target_arch_signal.h @@ -0,0 +1,57 @@ +/* + * arm signal definitions + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#ifndef _TARGET_ARCH_SIGNAL_H_ +#define _TARGET_ARCH_SIGNAL_H_ + +#include "cpu.h" + +#define TARGET_REG_R0 0 +#define TARGET_REG_R1 1 +#define TARGET_REG_R2 2 +#define TARGET_REG_R3 3 +#define TARGET_REG_R4 4 +#define TARGET_REG_R5 5 +#define TARGET_REG_R6 6 +#define TARGET_REG_R7 7 +#define TARGET_REG_R8 8 +#define TARGET_REG_R9 9 +#define TARGET_REG_R10 10 +#define TARGET_REG_R11 11 +#define TARGET_REG_R12 12 +#define TARGET_REG_R13 13 +#define TARGET_REG_R14 14 +#define TARGET_REG_R15 15 +#define TARGET_REG_CPSR 16 +#define TARGET__NGREG 17 +/* Convenience synonyms */ +#define TARGET_REG_FP TARGET_REG_R11 +#define TARGET_REG_SP TARGET_REG_R13 +#define TARGET_REG_LR TARGET_REG_R14 +#define TARGET_REG_PC TARGET_REG_R15 + +#define TARGET_INSN_SIZE 4 /* arm instruction size */ + +/* Size of the signal trampolin code. See _sigtramp(). */ +#define TARGET_SZSIGCODE ((abi_ulong)(9 * TARGET_INSN_SIZE)) + +/* compare to arm/include/_limits.h */ +#define TARGET_MINSIGSTKSZ (1024 * 4) /* min sig stack size */ +#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) /* recommended size */ + +#endif /* !_TARGET_ARCH_SIGNAL_H_ */ From 03fd4028f180af4175e6446bc8c09c4689fb6580 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 15:17:03 -0600 Subject: [PATCH 349/730] bsd-user/arm/target_arch_signal.h: arm machine context and trapframe for signals Signed-off-by: Stacey Son Signed-off-by: Kyle Evans Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_signal.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/bsd-user/arm/target_arch_signal.h b/bsd-user/arm/target_arch_signal.h index 973183d99c..9527335cc9 100644 --- a/bsd-user/arm/target_arch_signal.h +++ b/bsd-user/arm/target_arch_signal.h @@ -54,4 +54,32 @@ #define TARGET_MINSIGSTKSZ (1024 * 4) /* min sig stack size */ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) /* recommended size */ +/* + * Floating point register state + */ +typedef struct target_mcontext_vfp { + abi_ullong mcv_reg[32]; + abi_ulong mcv_fpscr; +} target_mcontext_vfp_t; + +typedef struct target_mcontext { + abi_uint __gregs[TARGET__NGREG]; + + /* + * Originally, rest of this structure was named __fpu, 35 * 4 bytes + * long, never accessed from kernel. + */ + abi_ulong mc_vfp_size; + abi_ptr mc_vfp_ptr; + abi_int mc_spare[33]; +} target_mcontext_t; + +#include "target_os_ucontext.h" + +struct target_sigframe { + target_siginfo_t sf_si; /* saved siginfo */ + target_ucontext_t sf_uc; /* saved ucontext */ + target_mcontext_vfp_t sf_vfp; /* actual saved VFP context */ +}; + #endif /* !_TARGET_ARCH_SIGNAL_H_ */ From 2cb1e6432f917a91c3edd4772b26da3b5d8df791 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 4 Nov 2021 17:08:04 -0600 Subject: [PATCH 350/730] bsd-user/arm/target_arch_signal.h: Define size of *context_t Define the native sizes of mcontext_t and ucontext_t so that the tests in target_os_ucontext.h ensure the size of arm's version of these structures is correct. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/arm/target_arch_signal.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bsd-user/arm/target_arch_signal.h b/bsd-user/arm/target_arch_signal.h index 9527335cc9..f1844dbf22 100644 --- a/bsd-user/arm/target_arch_signal.h +++ b/bsd-user/arm/target_arch_signal.h @@ -74,6 +74,9 @@ typedef struct target_mcontext { abi_int mc_spare[33]; } target_mcontext_t; +#define TARGET_MCONTEXT_SIZE 208 +#define TARGET_UCONTEXT_SIZE 260 + #include "target_os_ucontext.h" struct target_sigframe { From 781be8666c7cc05a9cce6011c9d9c1ba4e15770d Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 15:19:33 -0600 Subject: [PATCH 351/730] bsd-user/arm/signal.c: arm set_sigtramp_args Implement set_sigtramp_args to setup the arguments to the sigtramp calls. Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/arm/signal.c | 60 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 bsd-user/arm/signal.c diff --git a/bsd-user/arm/signal.c b/bsd-user/arm/signal.c new file mode 100644 index 0000000000..3c0db30a85 --- /dev/null +++ b/bsd-user/arm/signal.c @@ -0,0 +1,60 @@ +/* + * arm signal functions + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "qemu.h" + +/* + * Compare to arm/arm/machdep.c sendsig() + * Assumes that target stack frame memory is locked. + */ +abi_long set_sigtramp_args(CPUARMState *env, int sig, + struct target_sigframe *frame, + abi_ulong frame_addr, + struct target_sigaction *ka) +{ + /* + * Arguments to signal handler: + * r0 = signal number + * r1 = siginfo pointer + * r2 = ucontext pointer + * r5 = ucontext pointer + * pc = signal handler pointer + * sp = sigframe struct pointer + * lr = sigtramp at base of user stack + */ + + env->regs[0] = sig; + env->regs[1] = frame_addr + + offsetof(struct target_sigframe, sf_si); + env->regs[2] = frame_addr + + offsetof(struct target_sigframe, sf_uc); + + /* the trampoline uses r5 as the uc address */ + env->regs[5] = frame_addr + + offsetof(struct target_sigframe, sf_uc); + env->regs[TARGET_REG_PC] = ka->_sa_handler & ~1; + env->regs[TARGET_REG_SP] = frame_addr; + env->regs[TARGET_REG_LR] = TARGET_PS_STRINGS - TARGET_SZSIGCODE; + /* + * Low bit indicates whether or not we're entering thumb mode. + */ + cpsr_write(env, (ka->_sa_handler & 1) * CPSR_T, CPSR_T, CPSRWriteByInstr); + + return 0; +} From 38ce1471c97af97ff2bb569c659951a962c2b703 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 15:22:12 -0600 Subject: [PATCH 352/730] bsd-user/arm/signal.c: arm get_mcontext Get the machine context from the CPU state. Signed-off-by: Stacey Son Signed-off-by: Kyle Evans Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/arm/signal.c | 51 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/bsd-user/arm/signal.c b/bsd-user/arm/signal.c index 3c0db30a85..93c9bfc0d3 100644 --- a/bsd-user/arm/signal.c +++ b/bsd-user/arm/signal.c @@ -58,3 +58,54 @@ abi_long set_sigtramp_args(CPUARMState *env, int sig, return 0; } + +/* + * Compare to arm/arm/machdep.c get_mcontext() + * Assumes that the memory is locked if mcp points to user memory. + */ +abi_long get_mcontext(CPUARMState *env, target_mcontext_t *mcp, int flags) +{ + int err = 0; + uint32_t *gr = mcp->__gregs; + + if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_size != sizeof(target_mcontext_vfp_t)) { + return -TARGET_EINVAL; + } + + gr[TARGET_REG_CPSR] = tswap32(cpsr_read(env)); + if (flags & TARGET_MC_GET_CLEAR_RET) { + gr[TARGET_REG_R0] = 0; + gr[TARGET_REG_CPSR] &= ~CPSR_C; + } else { + gr[TARGET_REG_R0] = tswap32(env->regs[0]); + } + + gr[TARGET_REG_R1] = tswap32(env->regs[1]); + gr[TARGET_REG_R2] = tswap32(env->regs[2]); + gr[TARGET_REG_R3] = tswap32(env->regs[3]); + gr[TARGET_REG_R4] = tswap32(env->regs[4]); + gr[TARGET_REG_R5] = tswap32(env->regs[5]); + gr[TARGET_REG_R6] = tswap32(env->regs[6]); + gr[TARGET_REG_R7] = tswap32(env->regs[7]); + gr[TARGET_REG_R8] = tswap32(env->regs[8]); + gr[TARGET_REG_R9] = tswap32(env->regs[9]); + gr[TARGET_REG_R10] = tswap32(env->regs[10]); + gr[TARGET_REG_R11] = tswap32(env->regs[11]); + gr[TARGET_REG_R12] = tswap32(env->regs[12]); + + gr[TARGET_REG_SP] = tswap32(env->regs[13]); + gr[TARGET_REG_LR] = tswap32(env->regs[14]); + gr[TARGET_REG_PC] = tswap32(env->regs[15]); + + if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_ptr != 0) { + /* see get_vfpcontext in sys/arm/arm/exec_machdep.c */ + target_mcontext_vfp_t *vfp; + vfp = lock_user(VERIFY_WRITE, mcp->mc_vfp_ptr, sizeof(*vfp), 0); + for (int i = 0; i < 32; i++) { + vfp->mcv_reg[i] = tswap64(*aa32_vfp_dreg(env, i)); + } + vfp->mcv_fpscr = tswap32(vfp_get_fpscr(env)); + unlock_user(vfp, mcp->mc_vfp_ptr, sizeof(*vfp)); + } + return err; +} From d6d4509a9f326fd90fe47e33fe532c7bc2c8adf2 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 15:23:13 -0600 Subject: [PATCH 353/730] bsd-user/arm/signal.c: arm set_mcontext Move the machine context to the CPU state. Signed-off-by: Stacey Son Signed-off-by: Kyle Evans Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/arm/signal.c | 76 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/bsd-user/arm/signal.c b/bsd-user/arm/signal.c index 93c9bfc0d3..fb6228db6c 100644 --- a/bsd-user/arm/signal.c +++ b/bsd-user/arm/signal.c @@ -109,3 +109,79 @@ abi_long get_mcontext(CPUARMState *env, target_mcontext_t *mcp, int flags) } return err; } + +/* Compare to arm/arm/exec_machdep.c set_mcontext() */ +abi_long set_mcontext(CPUARMState *env, target_mcontext_t *mcp, int srflag) +{ + int err = 0; + const uint32_t *gr = mcp->__gregs; + uint32_t cpsr, ccpsr = cpsr_read(env); + uint32_t fpscr, mask; + + cpsr = tswap32(gr[TARGET_REG_CPSR]); + /* + * Only allow certain bits to change, reject attempted changes to non-user + * bits. In addition, make sure we're headed for user mode and none of the + * interrupt bits are set. + */ + if ((ccpsr & ~CPSR_USER) != (cpsr & ~CPSR_USER)) { + return -TARGET_EINVAL; + } + if ((cpsr & CPSR_M) != ARM_CPU_MODE_USR || + (cpsr & (CPSR_I | CPSR_F)) != 0) { + return -TARGET_EINVAL; + } + + /* + * The movs pc,lr instruction that implements the return to userland masks + * these bits out. + */ + mask = cpsr & CPSR_T ? 0x1 : 0x3; + + /* + * Make sure that we either have no vfp, or it's the correct size. + * FreeBSD just ignores it, though, so maybe we'll need to adjust + * things below instead. + */ + if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_size != sizeof(target_mcontext_vfp_t)) { + return -TARGET_EINVAL; + } + + env->regs[0] = tswap32(gr[TARGET_REG_R0]); + env->regs[1] = tswap32(gr[TARGET_REG_R1]); + env->regs[2] = tswap32(gr[TARGET_REG_R2]); + env->regs[3] = tswap32(gr[TARGET_REG_R3]); + env->regs[4] = tswap32(gr[TARGET_REG_R4]); + env->regs[5] = tswap32(gr[TARGET_REG_R5]); + env->regs[6] = tswap32(gr[TARGET_REG_R6]); + env->regs[7] = tswap32(gr[TARGET_REG_R7]); + env->regs[8] = tswap32(gr[TARGET_REG_R8]); + env->regs[9] = tswap32(gr[TARGET_REG_R9]); + env->regs[10] = tswap32(gr[TARGET_REG_R10]); + env->regs[11] = tswap32(gr[TARGET_REG_R11]); + env->regs[12] = tswap32(gr[TARGET_REG_R12]); + + env->regs[13] = tswap32(gr[TARGET_REG_SP]); + env->regs[14] = tswap32(gr[TARGET_REG_LR]); + env->regs[15] = tswap32(gr[TARGET_REG_PC] & ~mask); + if (mcp->mc_vfp_size != 0 && mcp->mc_vfp_ptr != 0) { + /* see set_vfpcontext in sys/arm/arm/exec_machdep.c */ + target_mcontext_vfp_t *vfp; + + vfp = lock_user(VERIFY_READ, mcp->mc_vfp_ptr, sizeof(*vfp), 1); + for (int i = 0; i < 32; i++) { + __get_user(*aa32_vfp_dreg(env, i), &vfp->mcv_reg[i]); + } + __get_user(fpscr, &vfp->mcv_fpscr); + vfp_set_fpscr(env, fpscr); + unlock_user(vfp, mcp->mc_vfp_ptr, sizeof(target_ucontext_t)); + + /* + * linux-user sets fpexc, fpinst and fpinst2, but these aren't in + * FreeBSD's mcontext, what to do? + */ + } + cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC, CPSRWriteByInstr); + + return err; +} From 3ac34cc98576425a63763b7671decf11fd606ec6 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 15:24:19 -0600 Subject: [PATCH 354/730] bsd-user/arm/signal.c: arm get_ucontext_sigreturn Update ucontext to implement sigreturn. Signed-off-by: Stacey Son Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/arm/signal.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bsd-user/arm/signal.c b/bsd-user/arm/signal.c index fb6228db6c..1478f008d1 100644 --- a/bsd-user/arm/signal.c +++ b/bsd-user/arm/signal.c @@ -185,3 +185,12 @@ abi_long set_mcontext(CPUARMState *env, target_mcontext_t *mcp, int srflag) return err; } + +/* Compare to arm/arm/machdep.c sys_sigreturn() */ +abi_long get_ucontext_sigreturn(CPUARMState *env, abi_ulong target_sf, + abi_ulong *target_uc) +{ + *target_uc = target_sf; + + return 0; +} From ca4fc704a40b5ad36a7ced03331224293888fafb Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 4 Nov 2021 17:21:48 -0600 Subject: [PATCH 355/730] bsd-user/freebsd/target_os_ucontext.h: Require TARGET_*CONTEXT_SIZE Now that all architecutres define TARGET_[MU]CONTEXT_SIZE, enforce requiring them and always check the sizeof target_{u,m}context_t sizes. Signed-off-by: Warner Losh Reviewed-by: Richard Henderson --- bsd-user/freebsd/target_os_ucontext.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/bsd-user/freebsd/target_os_ucontext.h b/bsd-user/freebsd/target_os_ucontext.h index dd61aec7cc..41b28b2c15 100644 --- a/bsd-user/freebsd/target_os_ucontext.h +++ b/bsd-user/freebsd/target_os_ucontext.h @@ -27,10 +27,8 @@ typedef struct target_ucontext { int32_t __spare__[4]; } target_ucontext_t; -#ifdef TARGET_MCONTEXT_SIZE G_STATIC_ASSERT(TARGET_MCONTEXT_SIZE == sizeof(target_mcontext_t)); G_STATIC_ASSERT(TARGET_UCONTEXT_SIZE == sizeof(target_ucontext_t)); -#endif /* TARGET_MCONTEXT_SIZE */ struct target_sigframe; From 18fe5d99f27fa7458724aa367e3c6784c36d5771 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 23 Sep 2021 15:30:45 -0600 Subject: [PATCH 356/730] bsd-user: add arm target build CC: Paolo Bonzini Signed-off-by: Warner Losh Acked-by: Kyle Evans Reviewed-by: Richard Henderson --- configs/targets/arm-bsd-user.mak | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 configs/targets/arm-bsd-user.mak diff --git a/configs/targets/arm-bsd-user.mak b/configs/targets/arm-bsd-user.mak new file mode 100644 index 0000000000..cb143e6426 --- /dev/null +++ b/configs/targets/arm-bsd-user.mak @@ -0,0 +1,2 @@ +TARGET_ARCH=arm +TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml From 214bdf8e7199a34fe6f46ac7a83b61d8cc3f8ad0 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Sat, 18 Dec 2021 12:43:40 +0100 Subject: [PATCH 357/730] hw: m68k: Add virt compat machine type for 7.0 Signed-off-by: Laurent Vivier Reviewed-by: Thomas Huth Reviewed-by: Cornelia Huck Message-Id: <20211218114340.1856757-1-laurent@vivier.eu> --- hw/m68k/virt.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c index 0efa4a45c7..78e926a554 100644 --- a/hw/m68k/virt.c +++ b/hw/m68k/virt.c @@ -304,10 +304,17 @@ type_init(virt_machine_register_types) } \ type_init(machvirt_machine_##major##_##minor##_init); -static void virt_machine_6_2_options(MachineClass *mc) +static void virt_machine_7_0_options(MachineClass *mc) { } -DEFINE_VIRT_MACHINE(6, 2, true) +DEFINE_VIRT_MACHINE(7, 0, true) + +static void virt_machine_6_2_options(MachineClass *mc) +{ + virt_machine_7_0_options(mc); + compat_props_add(mc->compat_props, hw_compat_6_2, hw_compat_6_2_len); +} +DEFINE_VIRT_MACHINE(6, 2, false) static void virt_machine_6_1_options(MachineClass *mc) { From 0969e00b3933a10a481f5bc13c834bf1abbc438d Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Fri, 7 Jan 2022 11:50:49 +0100 Subject: [PATCH 358/730] q800: fix segfault with invalid MacROM "qemu-system-m68k -M q800 -bios /dev/null" crashes with a segfault in q800_init(). This happens because the code doesn't check that rom_ptr() returned a non-NULL pointer . To avoid NULL pointer, don't allow 0 sized file and use bios_size with rom_ptr(). Resolves: https://gitlab.com/qemu-project/qemu/-/issues/756 Reported-by: Peter Maydell Signed-off-by: Laurent Vivier Reviewed-by: Thomas Huth Reviewed-by: Mark Cave-Ayland Message-Id: <20220107105049.961489-1-laurent@vivier.eu> Signed-off-by: Laurent Vivier --- hw/m68k/q800.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index e4c7c9b88a..55dfe5036f 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -672,12 +672,13 @@ static void q800_init(MachineState *machine) /* Remove qtest_enabled() check once firmware files are in the tree */ if (!qtest_enabled()) { - if (bios_size < 0 || bios_size > MACROM_SIZE) { + if (bios_size <= 0 || bios_size > MACROM_SIZE) { error_report("could not load MacROM '%s'", bios_name); exit(1); } - ptr = rom_ptr(MACROM_ADDR, MACROM_SIZE); + ptr = rom_ptr(MACROM_ADDR, bios_size); + assert(ptr != NULL); stl_phys(cs->as, 0, ldl_p(ptr)); /* reset initial SP */ stl_phys(cs->as, 4, MACROM_ADDR + ldl_p(ptr + 4)); /* reset initial PC */ From 4e136629f003d0f5be2985b15176acbec2c5a344 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 8 Jan 2022 16:41:47 +0000 Subject: [PATCH 359/730] macfb: fix VRAM dirty memory region logging The macfb VRAM memory region was configured with coalescing rather than dirty memory logging enabled, causing some areas of the screen not to redraw after a full screen update. Signed-off-by: Mark Cave-Ayland Fixes: 8ac919a065 ("hw/m68k: add Nubus macfb video card") Reviewed-by: Laurent Vivier Message-Id: <20220108164147.30813-1-mark.cave-ayland@ilande.co.uk> Signed-off-by: Laurent Vivier --- hw/display/macfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/display/macfb.c b/hw/display/macfb.c index 277d3e6633..4bd7c3ad6a 100644 --- a/hw/display/macfb.c +++ b/hw/display/macfb.c @@ -661,9 +661,9 @@ static bool macfb_common_realize(DeviceState *dev, MacfbState *s, Error **errp) memory_region_init_ram(&s->mem_vram, OBJECT(dev), "macfb-vram", MACFB_VRAM_SIZE, &error_abort); + memory_region_set_log(&s->mem_vram, true, DIRTY_MEMORY_VGA); s->vram = memory_region_get_ram_ptr(&s->mem_vram); s->vram_bit_mask = MACFB_VRAM_SIZE - 1; - memory_region_set_coalescing(&s->mem_vram); s->vbl_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, macfb_vbl_timer, s); macfb_update_mode(s); From 31144eb6393b66b06a13e8a6ad0e730f9e82d4c6 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 8 Jan 2022 18:04:53 +0000 Subject: [PATCH 360/730] target/m68k: don't word align SP in stack frame if M68K_FEATURE_UNALIGNED_DATA feature enabled Commit a9431a03f7 ("target/m68k: add M68K_FEATURE_UNALIGNED_DATA feature") added a new feature for processors from the 68020 onwards which do not require data accesses to be word aligned. Unfortunately the original commit missed an additional case whereby the SP is still word aligned when setting up an additional format 1 stack frame so add the necessary M68K_FEATURE_UNALIGNED_DATA feature guard. Signed-off-by: Mark Cave-Ayland Fixes: a9431a03f7 ("target/m68k: add M68K_FEATURE_UNALIGNED_DATA feature") Reviewed-by: Laurent Vivier Message-Id: <20220108180453.18680-1-mark.cave-ayland@ilande.co.uk> Signed-off-by: Laurent Vivier --- target/m68k/op_helper.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index c0f4825034..acbd473515 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -415,7 +415,10 @@ static void m68k_interrupt_all(CPUM68KState *env, int is_hw) oldsr = sr; env->aregs[7] = sp; cpu_m68k_set_sr(env, sr &= ~SR_M); - sp = env->aregs[7] & ~1; + sp = env->aregs[7]; + if (!m68k_feature(env, M68K_FEATURE_UNALIGNED_DATA)) { + sp &= ~1; + } do_stack_frame(env, &sp, 1, oldsr, 0, retaddr); } else { do_stack_frame(env, &sp, 0, oldsr, 0, retaddr); From 1c127fa8e2ff2b034ebf8e50faea2bbc5136afd2 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Mon, 10 Jan 2022 15:27:45 +1100 Subject: [PATCH 361/730] pseries: Update SLOF firmware image The only change is that SLOF is compiled with -mcpu=power5 to make it work on PPC970 too. Signed-off-by: Alexey Kardashevskiy --- pc-bios/README | 2 +- pc-bios/slof.bin | Bin 991920 -> 992384 bytes roms/SLOF | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pc-bios/README b/pc-bios/README index c51ae58824..ba6c15e769 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -14,7 +14,7 @@ - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at https://github.com/aik/SLOF, and the image currently in qemu is - built from git tag qemu-slof-20211112. + built from git tag qemu-slof-20220110. - VOF (Virtual Open Firmware) is a minimalistic firmware to work with -machine pseries,x-vof=on. When enabled, the firmware acts as a slim shim and diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin index 046ca63709aacf7f05c9b95a37535ac2c0b52df3..cbbe23e9107575c64c3264badacfad8b0a7ca090 100644 GIT binary patch delta 267695 zcmeFa3v^UPwl`jNI*<+qXtaRCixU+MUj$10i(Mph1WziZm}Fj5=XN?T~Ix zCx8;gnP3JAMueb%;HVQuGBOGpd>}YF7ajG(kw*}ag!qV#kAwi{|J!xCL!!>yx&OPq zweI@X&03w)ryjd@?b>_Su3fvTYu-!`9!akp-#0P1sA$>nar4H`A2)aYg82)^ja$0# z?)y@!;`zX?mIQ9IOm#h7nZ z$4dRLXPs+_#Ws;T!!irc?8M8##Z6-b|_X$=*AW}p8*eKIq=#=h8`g@e_#>b<5R~6?O#939QXQV{?lFKkCN$X{=W(M@o zQd*O%_D@N+QMUd3#ba*PWxa&;B&b)eQ_#Mnb+LU_Yq5QPE8+2Bm1%0AX9yRxvlwZ4 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 ~k;8br+r}fCe9r!X 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 delta 267618 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 y$A8x&J1W!j|L5G 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

    5sR_6e5!(A5f1`q^fbMat8lH~A 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

    (z()M14;O?2FVme>5*sXF(FyQJc zIa@-Jle1$*fN79Z02&3nJb@8MM@zP(kV6O5!7Q0pm|`E~)-kKZQsR*R<<$usolo47 z=w6*rfFdroA~$JCr;798j zTrkRq7)UV_U_1qtna;ICXGA6CC=XrJIs4rwQz|tMA?DE2Yh(igmL(E*I)vAxKL`x*^SC}pHd{KiB?Odw1|KWZx4g)&V@i!aQ{B8NxRXt+uaa+F6HJi;I4 zsy%}266~|+=trrGbCef(YQWi$({-`BSXOMPj#6X$zckaI>fzQ5Qldy`3&j;FW>)6a zD;*Y2d>l2XN9?!=KTe5Zh8OVz?s30S=l^*d*BN1e7T46IS=hvK^3r*vd)>Zxku_J}SWW7P)b z_>Bhp0MMUSpa8`3)HW^1_2Z{%SSUCA6eg0Mf>x+s?j9t?e#B61O%4H6LcesH(76%k zLn55=il5rZ%)U*0J!MSgXZHCSlSsMRp+GK#e%fMNw|iFF@8yw#Fj_Yj_5_xRbi$|O zWQKsbIgwMsD$%DkPEfz$u1QDF>-TQL4QT5q+kmTTQ132lHZUp)OXC>_Q4I8HlN6*B zK8^M*V>C!ih;=ucM-h;~DI4#VL!G-(r>RJ-Jac4Qaw&e=NBDFD3Jz&uRN!*IjG|>k z46Ej#k$~g@P!0;+C|ihGl7vp-^kyj`{7fMKX#R5s9PP6_KUE;#PosYR9u$&V4wZQy zFAJ~(a?=M4*-XAF4GX%NPsbK5OQLD)loHRg2%*YQhy_xC%}vz^R082tJR>-Ap%nub zaZsRIVh57|3FLwW0s09W5O0LbyqLF-`a;!!P$A0ee+7v{?Jav{ny z=8!ml>KWm+pN?WSK~BOs>U<#(^Pl1NqEncVR%f<-kvYuj`S5?7dwnU0;Zo02k=6i- zEiRGV&?j(r*q@C-Q*if168Qg10D<%|1?qW50`@Sr8)DWUyGoqgNXldyJkn)r^2@v=;V3T$2;- ztu;yus~2f$%LD-|M}nl!0#V%I=?Q}bM7rGyGa$eM-IpT+0O^kTSHz0u%1Y9ATnB&+ znkVl7$lalSPdMt!L?#GeeKsT#>02leQ{q$u`mG?}?5Yic4Pr>WMo^G~rO_J`7?(-d zMNle4BH~9Hx2}3lr6sAve5*}pT{6eAAE{$745JZOKWo6VxDI>FBme}S@_kxP4eSwA zR07GNOyB+{g4$88954W1R2YY`$~8+%YZ4Bah`mY+kqF@wxlRJb5|Q#zB6qtM@KH}7 zogpQMX;yv#GrQ3u@@F@fU@*$I4~j&WF(($(En{ye5-Ir9rS!J-T8D<^jFE#WQH{WY zQ3GxYI`;X;G+*ZR;&p3mGCc@$2Y?KPMT`JEK8fFTK#)W_RKqQ%G7&hF-)bsSAUATo z>PCq_#%dIfsApMiZNk(;=7?0%BQrg;o319be0!Y<;I#CoI3%DQj3}oC z@njX!6UYa0ZbzrsqVMEH+A=uz8wfz4=dccSVM~yl&h!C?Ha(nwgAY$;7or#FP@)*%XJRHfy|~{XlNt zr%P7_pE`)bkcfzJi3BtGPbLGfq+hYxz7AX4hI6vm-vUXLN5&H?)DFahB0aW22`BNi z4{p$RJ+|5l3>wq1y#wjoy3dqe9ZU%gVQfN~gY?5sp9T&vE=^g>Vh0eWKzJ+gz^DxD zKGUxCJ_EZg&{P8HG1P}}s2!iD?*iMWonjD%43R2ZS`?X$=03Ae5J~XO-ug4+c~e-# zl)?oBfrtgB0|rf#L7qZ#Y}AWes8%(1lJW_ty3te}wKHy70WcC0vA6$#xxqE~9u%S! zTdD_jFk~X8ZN70k12G_)E<)Tx27i-~9!x~cj>N(&Fkj|fMs4oB&y`;Jj(sr|GEYvB z7qL7WT)NYQY_FL8AASz|XijLW@ZB*s1i*m8(yfqnBbxdlfB_YB)fi^Vh)h6Uq94_y z5j(KLF}Ve5DRXJdLzwK~Bp7HaDrb0t#Sls5$OeIHj+;1-IevP21_98u9^b6@6|@=& z#N|+9qt)NFfVg0B>JoV=xTaSu4bSC@sHqomxne%t2P1P5FIq`|UqE-C zvWt-C!{;)hJ&6^?Q#Kjpdtpd00@wF&ogMpZ^L-EU#A%HHa2ArOQn$^1N~F0YAu6CN zrxE)09Kgdd9OG;|)*td8q#+KTbGaCPanffNdYU3KoXq00OGR@$sV2o00dFNWuZfvR(wZc{dsyiBQ6{ zE5P)k3=aU)%^G3>l63>U!hd{L#dVR&Gq%5g^OQw^U_-5TI(6e7@#oLi1J*J;C7K5+ zMJ3M#sddk0^#p~NH zxL5ow7f{%n2T*{tKko8!mHTm5@qWfwB&8D5?wzTw+J0>8vE}RiP0X7QUvAKEvPl7# zmqs2or|pMXOQqdVmHB4H80F4(R6jf z{i(bZNeq|{Je6F<7lzU1I?c!?4k!SxhIq$NM;iy!Qc`BeC(fB<;%(g>ZQFe&33zdZ z=IKz$RZDeIqAyl64?6{3m<1(G%IS-7{D$MEDntU{{>2(idwxdK;8VkigXCCl-8DwPWffsgf*rcqr1g<%J4r>mdqhC>j zRX-cU1bjyk474yxq5xNfxB}W1E4vt7S}qWv9PM(UD=&~#7uE2&LklJSIWS!;>CYW` zT}fk~V_L*an4jMqWtfu?F>LNB=GfZ(0|%^mfQD&| zBh~g)iVG!n5vD4oveu0d;_9nOc+I7{%+(wi7G@)j53b?!6ANwP0HnHj>#M?7NjiET zdJ=$O4}XysfYd^v$KHbaa5oGz=}Op&*+0?i`zW~@nv;2?EAEqp)%Jw!=UQ|Pl7Pg; z!*>zc1XRgL_{B~77e`YCS-#WLKCc`;jxpl{$MKinQUdLqI{1rYN_fCsNp#!N@d3C+ zIEoCqbp4IE_U?RtB#7P^;o)BhatTa<9$h&I_{*#i5O{>_Wf^uAbHGsRv*46#S+XyI z!L59UM6d7oOY48w(Me}Gstox_E*Kg+UJDC^7?EU*(+8YKrdS+IGn6lEQ1Q5Uub?-^ zVB!mKhytX>2)_Cc`Vs?!ZQWc)Mns2W4vVU>02e>@ayLZrg}s7o@hFRy4$gpZVbDa? z#dC>+hz;kIUc4p`qE#PcP)Em%A`-Yk!<+|;25;1;o2um81ji%Ni6>C^cindjVJgtx zlMSYMSOgWt#}7fq6%Ult`w*B%=N#axNBknJ?!G^mQDQg+C4KM+8p2isSdKLOc0g_F zQm3mXkT`Z9yu1URFX4;XCyAfl(`|Euk6psOmb#h--S5H7JzD_T_4C@9eq z8xfHzKBHobN;OvcYAbDnA(%*jGzp4`-YB0+)F8-3i5MUtC`iJG#Fo-nP|?yBH5II} z#uhCq?MrfV^XPrNb^gD-XU@4NH_`X8{x56o%-oqhd-m+TXV1r(GiO?O;+DY4AuAKA zbd|5(Qu?De{lhq?6(EdC!}^?==aN?}TXgjXNfwV= z;8?6dTHkB-O$A!HCEWfZX1O)f7UT>HGp^|ROv%$X3G8fzE+K_Qb++u*A(F2+_Du%z z22lAVLjL-t$7vZ{`F@GH+-U1~5L`ONQ@&d=`Och*drCOQDQ$uKt#yQa5NYdCw@s{9IvphWb0vH(G!~Aqa6)n`k)iX(mbeVJ;!n`p07H!veGK{WtaKWDnrdUZ6LOcCu33DG%!*L>L1o)U7-qKN-AyNga1Xp{?F-w6#OZ7s z<1$n-<2z-ubeo5dZd!t318}zu8*n?n@XX|&6;B`B@fnL$Y zy#5t0t1F*vJA6f3!zZ@!X}|4Rq@_@{jIz6dT3Bce=WY+2`s3~Cas2JMV{(&{%ypGH zL(4h$O&)UCUTMoqSzCU4t{=~^y}iIkt14W#J#faQ%_Olsu>&$*(JD@4=?AcKhE6ZK zQ@{7KeY3CV!EpQb!0Ds8N672GtN@~{45Hf)vWl3+dzSa+$l^+yyxnJ@JF>!gI|8SU z-XX?FlXq;4*SjODtguAx{bLtMzO5vyg&h;(_3kJQSMNYvJA@ZH#?I8Z+R1C)5jg!T zJIn@-kD+Xaha}}>}al-R#KKTqe$K2Rm$g%u6SKLhlI!Oq>VcZNTZ&e z@adM_IRw$lcRNdG7EZIBaHr2r?u1V*>+*TrSGJVXua&&T$g#AN$uq8!HtzKCymNQB zm9n9is8-te(l}q)-Mlzas&dtboRp*pavy<^F@%;A3ZcV3LbrK%hENqaE}^;{=y>mVk-;D1&P%O? zxXE2vK00+C9&{#wv>zmw(9u!3`j;f%>BLX^TDL13Jeb;5>LYg4!&9bqWyWdk8Wqmp z#X!2N%$CD)UCZA!O3O*3O*yer%fqg@(wMvNoSZXbO8MP!kGM;ABe0NNC*qpgHP^#4 zbYygQ>Fkq*+8yDKcLlx{lCtubjMH(w#;$!jQk(8;&1=^&kSu|w3^%`|OgerNV?~pg zAAkOlya%48(=-Mom(Ijl-^HcgS;UxAQfOUjQw<2%T@xyH?Y(KDxLy~pT3u>Wm5)$u zcy|+{c^gRx;^pjkTbgQ>*B+yJlTWct$9N@bn&QYyk`Ukz3we2jiTdTzbj-t3p}ssA z9NU(c$CMZG9GMyY!`FBgDhXYp*kv4Jd~3tg;jczM3f%N*ur7{YaKdd0mn z3PGZezATy&I+@wUMWtn~G%k?-`|<(J>&L7!eE8+ScY^NbJ-@Sm5xCs{yYv@<3omr@ zy}k8;*K)V$oiodMdU83FOgEqM&A$kY^p`*Ji@>?(yZJ6NG9z*yv%h@QFiP2RzYJXC zFI)4=zzx01icHC}(*v%XJz1Wo!=Qa`VIK{IOLqru@K@8kJAvih z_QpMZo{=fyGcw&Ry%L$a>t)Sn#o$fUncBY0Bwbb)x}sQ4e7<8Q_o>oo=GcQ+m9c_c zki|3j6Lz)1SoX`?OgXz5bcrn_t^MLcyCEi(Ng?Fd`YRrXi>%}FuBe>CkS?qLU)=`t zsX!8GB{TG#{~obgP17lZNy{Tm3}?RCJ@*=yXB%?T^)kJ%=ZUjGHuXuJ2>x2Sch-!V zm045e1GpFYjKeSqek!&;MH{8>$9feY6+yWB>oL|P0(?)%eTnNgOh^qcLO z?jFoAH_9?+zAuUkMd<0062ZxO7{TTJ8viPqkxlWFC-~OBsj^|) z30m+o1TA-i+1r?Fh7Lk9blB5snK&#jG;!C8?-z_b`mzy}A(`eSTl1%)Dx5O5R@K)J&V+ z3LbWKu+`c_FiUI9nmHp&oX1<4njTJm4Oh6^oQ0SDLT}G7v3}bxUhOh;rE`h2Up?pw z$85DMq#dtKQJm;&#c|UR`|~_;s`a{+<~V#v4L0#2blkVMA&UCl&Cmqn*5^>Y%w;po zS>lR6K)+^d_eyjCj9+{)7gy|U)WI#-h3j)de`K?)M|&WQ~(X-RqU zP&$wdfZXBd?cCZloep{PFC;OwrND_cj`xf{+K8yU3TcTu&Cpk+c_`o>*?7&G%YIa; zkFe!VJIyxs_WCiSDy9!7UJs1?aRMEkOYP4vs(QU$Xq3&ohkNtf*R=OfA`g4rUu)@m z*@pi9*&hAH`vW7rn;+y|y`m{4I;Y#e(%?v1MJ2n;b{yJ&G@kzRSqAqFl63r%U1{!l zU%t|aP={Emd1?2eY;P@F2aEv|5 zc2JHG2Qk4OGcc{A)&ej+w3qoN+ZUoewF*L|@m1cO(}z2T0slmHYNn8$Zv@g{822p+ zqHpXFjS5cBBT#S7HMsWpllPDY7acPGGn;~REEz$R2=O;D(H?Ih$jO=g;I(*_V6oUL z+IdsF7hdVVdy)y-_7Pi1))}TnzfJGiA|p{<$^L)6RY>Wc#28x1T~ZgYmkbBgZ0<`? zmqYJGRqnMe(Fai%WB$S4qORXgP$qSp_WT~Im7edOgqOQ_ygX=$i!&=~-YF{Q0t36n za3Iyt`dX>+C{r_UH?K^(Z(99i#L}b(o#+7>U}OR)uZ7CUC6f>lwV8}uHGO)CUhAj5 z>VRwHldAR3xh(79HNxvL4b)H%z-Lr?*4Jh5=U! zA_0{GOvwbp#??Vf{Oua>^@ta?YNanj^6!iqwbHjOO?hcv%U7CkDP_y@v_848Rr5lI zV7ADGr?_{>zGhMR1!fHY-F~0w26(wD6>nZQI6mabgJN!m_0*x#8inoAYGv9ZVI1@C zha}yohG2Szm+MvFH#!v=V(kOB>#dFIe;R(zL{(dFTZ~krzekd;GM=E?NwAgR!a9!xb%Wk^rt!JZ)qG2t}h1Vo$2z~D^b zdraZ+eH50md8TDO$~L%VOHJANeU}wa&etPNrFS*Eg$mD6Zkx4`w74h7U&Qc1xBNY( zyq!??Sw7BmDBj{Wmq4i!cx%)bGoWLT%Qy^iy}+#LWjP{iGiusd?OWp5QJqL>>ONi# z0%X8do4A~KsyMXzgbdlT5gnoL9tE;&Iu$3~uJPy}Hlwb5fF42jjUHTVPd*FIw+z1K z25yBBw12XzotMub?dFRq;1a(;R+la_8fo2!KTO$isg!y)8%YKe~lYe4v5Mc|C+)~D)hyhNb9}3bJV^Dg^)hrke5Wnk_D#zQ;M`oq61K>$+aE}*wq?OS_7?14NXgS|o zM_N`kcfPdnZY>;@+fd{t^-qRCu&rY9)FOH1#EAY-tB={_vHY+iuC(XW2-R*2e%D+*&Js|Llm8`7Fw=f)FQ;fW+mIDk*`et$e25LnqCv#Z=pkLA z_lM=^Dl$R|*sTeiMJ9!WftL7O-0QovUdKmou}DSoXAPE9c+q#6dHNRyf-elX3j;A& zW*o3~$<&2PE=L|aHJgn-+3-PU?yLjoY{8)Hf^%T!`dUPccg9o2iT z6?J9;J!tC*QfZ5bU8H_Y8iP*l+m~kUlTSqg=&}C^tyCqWx`hF6=Q&f}`7!e|v4i); zfB1~D$H~J~>JSFGxVn{PcWbKRMh}VMCP}(`841S)<)RMTt6HtJMKhj@K+>}Ebp_`^F*!7 zjGrE_bQFcNKM0&$BvY8gQRhp@Eo*Yg$us*L&IuRKoMN{gKA6}CEv$=Osk#sBu9Pb; z*UBYSouUKupnm$~3FeWdzv#(O@@ zaX-I%6wCIud{Mk>O;a=D_vHV1<9|UszO2;~;$KQ%KF4J&i!0Tp8SXz!^;+%YSn_ER zD)~}^9=*cS$tBa(%s-rB86HM?8pxPnR5GBjBs4Wg5y40xo`I`98t(#eNwBjchf1uY z_|S|CJqZtFzLsP0zMO8z*SF#ugl(CIW238UZoYY<9kVl;uN9SRtJ-X<6en=qO%t#C zzBWRqPrT2?1(XKQ4!;KP+VNLkf0GZ7gNzX5F^&2BK%1{4tB=M~Wfm$2)ji9{1JZkr zwb@6|lJ4Cokybc))}6%+qK08HY;oPwYLF)OWDe@PCu^$J$lJ^WCHn3TGnZEt5jXhL zxk0#uo$i@4rpUp5yy-{9DxBz)QMuWc9fD z!N;7aRbECbv0JkrS#=u8Uw7N}R`U8gEn5(I8Q0xGl|2=|o#4yGRhl`w?oRjcMIUt; z=4hekA9Qj<*L)8;GDGr)ccdj9gW0qiyx+%5y1M2ciAYEN#ph z0-|u5R5*P~DW5=99P;J@Q^J!zwqGzwQh~@0iEjV;9^o4Y+}|y(Le(=3+NNRFL7!~% zv$)jLZvCGFO>uE%7p6)*!pGLd$$IMJYOS;DF6o5&AUxCQ4zT3?g!jdZWZrHa_s1t- z8aq=v%pzRu;*%a1NOwO>38u`sYeYozE zz!k}d!>ykL&JMY5AfKGpg#7`LY98Xi&Scr(Zf@w51KW9Mu62@=tQ}$oI`eOV&TdgX z3+D#%$d7vleFa?}EmhphUFxCfwg>!e5S5v(7X9RSAB^NfM2s6|+<9;hh7em{49VWH z*k>=sPzmX`CvfL}s79VzRN8M|ls_r1{%^Kxi-DW*3tw@ESev%Kr(?`De(Px9Ed8jH z-9k_YDpGd0nY3qeXSew{PR`T{w?_Ny^ypY4l>cF!`gpTPod~pNol~YymPg++3w5MA zy5H2J?Hb_aN!#=x3_HEx%g4EmoBMRU4?o?_^Ke5TPoFFoTFHvz)7d`cpdg#Pp2Q`M zqgdAUd|K}-Gtey~N4304pd-g$EklQW`02{6WV*=VjL+C@JmMdZ6I%JZ16HfP)_7?N zOnd1GjCtuw!_+TnIC0sY46&QZ`CpW5S5azKpZP`kf6A0kDu%1@*v|uJ7q$8%cZz3< ze)9*x3Mc4yDLiycr*X@zzsDiq%XRRP$GD$Ou)cqUc7^881Lt~&a9Lj-`#f-Z@bgNy z?r`R@z!_KWY3@bAZ)h%o0PwN`9Q$ptzy5C~?yK!F8*?3=V z4UY%s(K>n1CZ2n0=6QTXY`#jTJrS4ICg7I3blZ!K=smiO8Xm5Eq!_~Gx${6mPwmSS zko)TzjH8#;XApw`?V~LHs_+pD|#+c~rkZWw{q8IW=i(H>T_-lROUSe?%Cg6U(58P1} z_XNA7;uJi~Jh>0#OAT@)JAp9$w->{sE$+kw+*A6%y-aaK(MVMS@~M3wkFkU|C*Xdg z58Q8CTrhwKxHJNCL9pTHST+NWeX_4_vFduC@f+v*NfRx9^X%x{DgW9~T>kB6_vX=q?%^ zlR!AD4_vFd=#&K9a}+n^cdz9mt?r_XK|MswrLBofTw=Rjbaw*o&^~aj>Y_&zaEI|o zGlB4I_i;w|paf)Q4?S^vem}B1Pw{niWhUH=EthAJsH?7Md!BjfZ#D@?PGdX?DTYO0 z=#&f5JcPh`r9B9&?3G`h>#ty6@BEAX`R%>)LnD0%9T;2!1Lc?a^T+qjALY+y9*|i6 zQh$D3ul!K?Xg|V%UI^uv`SXwW&L88;?;O@U|J(lj{Dl0p(0Sz-s|<|_I_D-Lkgqbd z`5XJlR}tF$mOk=TgeE_NE%cC3D2)nKh8AH&0)phL3~l~xedMbMZT|c|@>PU3zoBP- z2rDeVSY>DtT6-dBzRJ+#chL)aw1Dy>eG=>%)knThf?WkY@)>`HfKP;7)jbeQzE6Z* zO?~A1B-q7>+KWM-1f#g>c)pDP!hlbN(XoC6o9`20w78Fap9G`J`^fi6Fxu?P|It2E z!6iNsMvwUr+irdsXEHgh@_!@=A^(9S4pA$0W`FN7_pE zswROaqjVB`=6dFX--Cd3^4m!c$lZyyTr%lnfMI~tm6~|Ruf>zP#{;9n*~w|&{Lyar zOXa=3cHW(A#!$U5E0O(_0!YAqGVCY!!G5x^Ki26^nJCqIH?(%A3?>cslZAcntJiM6 z;F6yWWQNmI(uQ8IcH$kj>P{I8hS*OJY1(4DDb@h&kl+44(h8O~W{;O|niFpY4ggKy z=+{&PSFKLM?vyUz7|_Dcbe8;*jdc5E0UYK^X%8PsNjpESUoO7~g){r54ZTIo5Vp+y zJ8^dV84K~)0%5v&8FTN+8YxWLhU&4DCY6t?Y)IH|t0Xo*tO3A}6bc3=* zgw1xWP&M1J-J#T6Tj6|I9A!5@dLFLn`EB1pb|+w*6AjXl+;y?>0#)J}x>M&HnmU!~ zS6*4j(B+GFr!Ka?)20vS1=DgqpY2s_%?BbNak!?tKj-{XTf>=wv@-^ndAU3%85Kwy zdI8>0H)vDA)VA@a;2kq3m-Ce&a|)_P*$IpbR|V3}4Fy&zTit`!2*wg_vtv9l8zAhJ!xa1G-2oca>#Ycs z=*d|dYUCWS^VfllYfQ$atk*bg7$d%HR2e2h@s|X-h0I0Nk4wmt4!Lv9C~4XqQ}DPb zH=br%APvxT?+Hed)16i`t89uqPAM#&Sy41YEVVnW+GhZ+F@+#1*Pq!pj&(mtD-2Y~ zYul7C#O=Fz@%;F!t6I4^b!8;bf0$Mj-HZXLAAzC%HJonX!4~&YmEBuj!edeMs4Kj> ze_DF5zsFj*p?}(~C7faKTFz(OYzbk;NF(vub+?OT_#dIU4<;#=!M@c|tFCmjg=B0q zT$-MCcBonTjcX;5JWqH;xGI;P>_me+4Kac@&qFx|)tzo!LU%eQ%-vQ~N{h-b8ELzA zdY7ro(8|`#8!j1XE;W`Bwmy{({r-%`t?#osNqn zY&3b_mN`(-xS90NoQ_NP5t2SSi?GX-8A~W-E^l)pPu}QsjIA_f zuc$X=Lzf>hg|8?!g|8UlL}~^&9am7GW(8>zoQ@=rYhG|7OCNJO@?cgNz2>+ncg;9M z@S1c}!PN&$`SEkXUk*OZE^K!?t{(41?z@3d9ApwE^nl;wD5*ePUHy~nm{Pb+zP%hbL&czf6Gx*?v~AlnOn*XGvBW@%;dKkCT`II z%;~r#Hw3|X6o%;8NaBgGA$a=`!_e)+oXCnwr{kw{oyfAWPRFFf;JiZ!!MT4TEa3N> zgy7we)NY4?C-xA+!2MSc!hkUNh4gN*1gFrF{~f{1X`EP$JXvI5#fRa8CBd@?xIh0M zKJNedAK|RKg5OQPAzV-qJoWUaf2z8O&D!X6%o!~4EWn98T^_EvCwOYg(+k55cLl$Z z{B*crMld_vephf{V7L=mJ$%Kq;EjRTiM<}qm*@eahr)H!fV|R^3RGKSMkOrgnEVL|-vDb>CUqI4E2&E0~s2H%X%Tl@cu_x?)DK zfAW1q(gRAaZi(c#-_b8M)rr)tmLGNZ2=Wezmdywbmv+~^!!N90`74>n9{jde7^(X+ z>7O`}(@vA$?jJJ7D!`kTbdID++=QnMcX9N0$32)kc#mZY&w_U-oH;Xi#-*=REzJCi zNvi8K;c1si=>EBFJ-tgNmQu9tc(`C@aQK=1%+J%xG~NDl(Zg-if)@;YGVMD~WX;6_ z;lne7Hz%JN&MpfMC&-szRd{w;@VlV_hS2Hh;K_Dxk`t?HaUv@R3Y$)B`bPAy9$TL1 z#6ky&%W4Rm&^RX&J{dUAi9OJcVaWJR`u+2rNbQRzK4+g3S+&o^?*V7kDjOd`{0tNS z>D_dgr=K@JW*vv13c!g~4ss$-eaoa*kR}fuMK~0SwqEa`6lzN$Dcaq)zYw$<&mNuS}{&f>QMM^0rPhBX{whDULwcy+y zuKPJ%_o*q8s&@X=9EoD*{m;AygojO=@0u;4{G|exS!x+&i3{`TjIu|WDC{=9Je-N6fSDbM~q_>GjOVQdy2W`yxDHM4^K0}l(6 z;o4cj8d)hdyvwbRj_{>ghK5!s}rJpD(BqMH869}`Q@)#{%9cZug|d{vrYpr&(E zR-G(SMAkp~oAJaviRMb;M2V@uR{d0>>KIndB#L85OIh`hBx-R{UAXMN;Ly;dc*Ew5 za^uF))Ox?2*uAm@)4vq{WALVTN<4ONrO7eJ{W0_t?r-u&xN)PSRU6&kCS3aKH05Z( zujRKBo4q5PSrN?6$Q;B~WRdlZ*sIpT`ZzVE_Dq}pEt@{hreAB*e`wPu+w=k*QBrD4!g+T~`4Yvu{Fz5xj-A+C?b`C& zNa&etU!Er|E1`0c`+b<~2XUnP>fN{zN9|)ES(B}e`{&wCu6~mDS}xzRT>drOK8Hp} z!|l^y@|pgoG0$Whv}aB;XwQre=T%Dn1R4GaCtJL7i?_()J!|oHDZSI5`Gd=!8=8US znZJeG?&vot)rmag7_qGW2HvvPiIrx#m=YSXtj61|9`3}ZNyqa3j96By1sxn3p$ z!Z6QTU2SMh>tP(G=GE7TC~QYwoi9IfAE5A0h@}gCs*<5E-E`E|I{F1ox)CVY19k}) zFmzkE;ep_{l1B>}?Uc`|lgkX@Wz%LH)urwx+4(yHLV0a>J6U{hAy8%z!Fo)x_C z@-+h(q|S6=WuA2j0aMwUb9Jzb%{(G$?w=9!noEUn=7TWKQ7hB`*ZhoFh7s$UnNDQw z`DTu^<^jR2dN6o4XXiQ=jx+Pdg%ixYap4Iwty_#zWuCZ*VNK?Vi*}fK;-cARp15eN znI}F~Y|1Z|aG%rhbgr4O@^Sje;~zkO*ca0a$;2~};6^Hxnf1nFu)G++TGrM8%Yl`^ zGr(HlIRJ;Tb}ImLYny=GKr_Iwx%N%qAn-2G3j75)3j71;0%A<%*P$Gl?Y>AMsr1GD zW;(t#(}}E0DZfU3cLbGGHq{}Z>H^k%rjzZ8E@3kl3~>F4i$*h-a#5NU4Q2`L-<4J z2tywxnFf4RX43yQ#iakOz@&d#WmZu~rJU&h@B0kG-IOjM=Vm75`GG^uMnOv;d7LI?hN28;5;B3$OQtxB~D}`d22>Gk)v%Lhm?@yveyWvJr93nFB|(^0@(or`YgZ8(u`(rN9`V9k>R#4j6A3 z*mxuHe+5_!OaAINb{(4^?3apUI|KD9xz1G5S^Rbes1%8I4zD)p!%-nB?;PH$D(@VQ z_U=K$u5}N^19Rc(tOj9 zm&Q4f2Bs_0kl#|D^sLS|Y$b0a;&N*NHuQoH!#~!xX3eJc!M~$mdYWoC@H6Cz45v=PYt!2TRG%a@t`q zcCd^zde@xo9=*t%J)~DU;ZK(Y&r1GrIK7&AY+Y)2M0N0rD=`-qS&_MroqH!m#yVXE zv}f*2;_SW^bpfJCO&{fuTSSfPNlW z46Fq34G%CjJg^IZ)B}tM4=@%y@F{=~2qgpfiqO~TexDJdo=`S03b-1$0hk8BP6#Q6 z!a!&Z|6T&%DfBkb3j7Ud2V#gCCaTf^yj;~}pai%ZcmSw&+G}bF*AX5e+~l;cA49m^ zX@3gcSG|HLE7)fn??fJ)rYea%crS745?T))bwaM*A`f;TEaXo{>}?7^)DOrYo{umG z0a-vMX-MOtt;Dl|5ybz(cA)5aFp%N2uWB)N@HUE>mjNJ!c^8oC$OCf}Z9E0PM+ zQR#z(Ff#uRC#H-JAxuRwouq|U@vqs5y!a8}e>jl^=x)Iv^oO_?Ab|y^(V9HM{=ioO z7+7!y1cwo#ng!@~0prYqACP95dAo|=G-Lr|$^z_W!5Ux-z*w?iFM#iWsmOxUQSpKg zhb5i z;IzLti4b*I#v%*b_}%Wr-bqrskUkTNEJ|TSqZcfqC5zC@BKqf|`5+-WF_J~JV)k)k zNG>7izl$~iPXScEXg$!tykk7`dn|nO_xQaX_!aP4oPk9L`Q7To-bWpaJ^_xS|HX)O z@lYprXEliEW$^@@11eZt2*Au@#JRWz*aZBF!jks^(B(uPJ{iaXs90L}@J&jiUFNsq zQ0i#u!_@IGOg_9HK+O*$?MFy|WS|pS5<=vUd;>tVk6aHF1G9i704;xHE#2k>;al-m zJVIYzata_4LvrHLmcYOgELx>Wmve0aFBn;}%<1@N8Q~_UqaREx`GwOF5d1fsj!+7s zSi(FnC6BO$5C)d8tD4eG*w$0*OFp6XS@>lPZVAR(oe6x?t4#W{cHj4Nk%rjDmE`3* zv2JLA>oN8I7=E+KRed%3ufB)KQ)G?-Xi@b#;5`8SJUSeJp-1Pdcw;h1h(mGhz_p!6 z_tNs)03;!5c=WFTVt(}Be7H#JQB)?*K9pS`>Nwpbo3D7>V5}PRI0n8Q){? zFQz=kN!N_3 zHQ;TalldFn@rernjOYp6tn5h6p~X+!O87nm5dD3}eMF8>kud73=!qX0riFQFu`&&F zFcd33=)_8J!6n0lhSfhKccfuCm2AZ|UO~8r5Q0oDWuht18zSp}Vu(IQg`3f{xaeiV zCw8b=@66vhy4`4?t=oKr*10}#rClpyxMFgv5DHba^%tk>A z@pWewvgSWcPgwI?biV@Mfat|2*Pzlh ze*r#b!Mb3!(@~Q_c#sfA#Mssxb7BwfaJmW*t%y_XLd3lGe4{rJ|MTAg@83!5XT~Zv{9L;Ztax-&mL9hqCe5U=x^;L29DIY1X{5LVQMX{ z6r+*K>km-rc0+9Gk4b|O%Vg}Kao`p!Q?74_weEIe4^4C;rz1(Fh5Ce6NQg;cX(fbW z4>g(Ah)CDY1n%=Oa@Z7JhZtQ(d}Sl+zD{{?#OS2_x-$UnX2#35k}gl_gn<=bQyL*{ z%?e!a7qmuayTY9G3@fGBLq}}|7qKxh9zy%52ysfq>n;bd_;oh|g=}Dy5(>;EK8Wxc zV2j%*#4u?-2~<$e2=zfFAq4B`F7n9kyk=a#9=6k}Sv~oReQ(C$HHlE9zNBA>})K;vMip`r%c}E)&*>IAhb4s_- z>$36xt{A1_4?)(I9HQGW*ikpeNPNRJq=jze-z}yB(ai?LB|cqRB)-5M6E>hLvF;66@`h!mugkD3gUtq*c=B;z z9r1c#C9uZF1k<|z;2CU8A1@OYo5^WI9`nE05T`S}p2W?*0<92efK!-YcPzGmwR>up z)0qZwX^HrLk%~w}e1tGY>vi_Lv5mI-O@0JDn$uCoFY3hfw~s`A+Al=}u?T zM5ps>O-|=m`DA71S2LZ?^TpeZbvnV->y=h*jF?u5U)PrPBTO)`joqfTn;6YD#b>mUzAE0t zW7f9Y45R+RXVWQ8?BV&8KO6e;d{&m&B2Kqr5$7fb5aE2&NPt#tx-l-1h6%*SK^(){ zgzao9;`c;|wlZ#rUnn4LFTliP6Jq~vHMCC#E(PfO&ohGtFY^3qo(T)`^K1y+1hMB4 z&+}CN!l?kp_rlFs?_sB_0HSToUZv0rvd>WfOfvoWg}J0vYk8CZl40P5H%aecBGTXK ztiZ-9Xz1p_PG|WD;&TnH&0P4Z+{#39GZk*e`Zxa^cof(I><5^Dh^24&8o)A5D&BGt zz_i+S-B=rjDUw+FRVOm}F!)Tvw&2XR&}$l6SiT=3&Jusig8(YuG7osni9N#ElUQ8_ zKaMKbog3kBeY?}S5sQ5;%jCV7qIr=Q&u8vVB`;P0PXW!q$E zriE@pvMJke2Jx$a_~Iqjwh^Xf{5x2*Sd}2eQSc}rw|^~aC3Oj T+Tie0&&;qN;i(RB7g&ONFmy-8o)_AIsSJgcMPl-`x}CF1r?f_gvAbHQX~!?()-0@BT&>+qHsw z#)}56;-2MlXP4G?PrBS$u31Yy5nHt2-PxkrEZ=P3el^N43{XrdapylcTDX44oJ`u6ggd zMRaMYd*+G=t#Z%z;XVfI`=Ifx3$J<@>w%ur^&SVRgHr;-e7@$S%pDo&tS?j2{Qs#o%1IuM@37P<{@PWCoS=|HI%8l)s`7hrO zFj>W|yENO=AzIL((K4rAi#oJi=Ge93LyN>3?ew9)%52-Q(#qSt#9*!Cp_|0F$6~4? zrP!!BADJz-9jkj}iV!i!S|8mf2G87H{Aj`UN1uX56F$-k9$PwelVjNj1&-8D3LKN( z0`&T`+L_0$kn7sCuE!o7{B~i%m;$9ydHv_wk;fMao02HKT~}6m1uH8`D|_N{VbzX2 zF;`rzwLY;{rqycE)$2vHR#TlNQz6~aF(Md>8xM^n9=!#ouRFR{rZj5-Po~QhyXJgy z9aPc&@LNupj$dKzQ-RD$DPhu* zo(mm1XI_xWv~9s}&tTCYtGxLHRaM9l+B47j%A`u|#B*atJzcnUOu>wYJYH=I(%HV* zrgc8ISKiX1IiH^^Dz*COAD1^@&}_%%iW6GJF$XjlP^XDnt)_0}kTn^Fjxhz!?anx> zj2Wewk1s-;#~hylo#!8aL?)K$Hc5=uZPHmbOy1O~)xU7Fys2FCcd^!UT-VAQ+qDL6 zDm1_P@d(`<{5MgHuU{krw6gl;a&?o|Qols5F4Y2GTnek&Uc6Q&T+nJ?oFbfB%Zn>z zLa`S7(gAq`XumX9*tO1=7Rnn6G|S63iDvTa5hJySUiOA&s$aejfr%;_bUU?#2t~#QbUrB+K8LzCA@m*ToD{EzZnHKQstMa<0V=b>Pl=2#M zPp)7-PDb*qlM7|s8Ljo?d>L1EEa3GaLdH6^kW=F){8qSgQbDZy$EO`%{ZZi9`9*=_ z$iEAaAWc@e{G=0x)NIwGwH>D>z|)SLS}O97wV%4ji?i0>W*`Mt{cVb<&>HdIoMWAT zyG_VtP|BNmFv{sSV@3Rdx5f*|`1ch^RRw>)UM_9b&Tvzr1-*40Yxb=fFj=Q-oLmC^ zq658f2Um&nCcn)lmmOrEhA%6NONj0Syfu;x4K zG1T_XNbT4=q2us_vLkttxpff*RkQEjkO?d)}0if%WVil&)-jTG(6ab}f~8CqAi z-0Vc{{3kcTtD{=81tgfXJXo?%jL{E&G{*MIojz@V?~JOckVjTt=Z1q zCM|_p!?~p*f!f}bqqMP~4H14?*k?;cyO#6WjdDhg*7(_VB2WuxTOzM)(UQ0+*Q(l9 zh&Zhs|Mk`^pIuQ~PS}XhKF^CZJ#a6g_!xuNeQvTwl{RU0KaYUx-IBqtM(+d$>*I9I-MMOvF`5s3sc8z zS-ivKuX8ypSu6W$mJG?)PJi{JoYJD@{L3v`wVd`t!g9>_>m@=4cWCk7+=8&<>^1F`Av)X7SKYi_}ftIq_y8V#B|N_ z-R;Alj&Pci4)u7sSq8^*98s4F?Z|hxh;I*kKSOkAmhVHwSuN@NSg~8H{(jP^w8DHA zT6BSO7!={_So#4b`Cg-)|2{>0tyw!KIo<$=thgZNaQhc8WBihbbtQTCINYQC5fiPL zAC37w`ut1x8*>7-ozC;j*|6U#y2DmZ(aML`v+fxsDa2Ib+ImEbC&Ih$`ItMSF z*M}2)p9g37_DT0KPCn?x^`kdf;qEX6ID+3Ya0h;^Mf@;HyrCui@R|5oi~8{@Ikv@P zFdwb<#}RUDiPrezB8cq$6C;NG%+_E@*}isQ>a3SbqO&1+O)Cg(eMn-)|ud^~a> zZ`_5ChH~J>M4k(1D|}#5LE%fGP%t=X_;o2Za`T1tL$4`(r7fOm6sCORZHf3n0vk-&egAHgEzr3jh z{yrXI6ZLy20wv@3Nn*cN`uo49_c&ihl@jwofzttg#m~1EMWVmcifUDcz@=ki-3NZt z$A0}UPEB6o zSz#upSu7Hj)L<445kt`fM67618^on8R5L)#7KJJ@FD*VeQ2bL2qR)1Ta8)c*;3Z22jT!F-#6@J$R{jS(MU=OU0FPKnHbPDsB+|6zwankOOik!&mGRF|G@~Vvvwt zXI$nX;u6%kn-FWU!y=2Rng2;2GS_&B|?i>4c(Jk1} zR+>!v(Uxt|Hw(@wR`GiQH4PP;#cHw+gGfPCHw?PTpsrzJ*0|nU1aF{Ta})^Pb5#c9 z!;1LLk76zd>O3mGT;Q}qb(f2qWzT8y^A}mNCy|`~;5~x;hJ(583W^>M$r`A9III&$ zCx%1yW{Mgi4he5+86i?2N9}Pr{PI^qm2-1d%JpRAx!?0Cb)=Xp>Rgp0VH)8}O##qi z7=?@ycgPC~R6YunQ>p4BF=nu;W(yBb!n|J_$#1l{MRZWv<}E=;%sQph7|7Pzg?a@a4g=V%^ZOQMOB;W>wo#ei&yJ-!)RfSTRj@Wzdna z5ZX-M<3#SwKQ%;RE8(RhlT8Tp6Z`e$-`TD5JOUmk#ehXsmp+~H$`9l8u@BDT+??;& zg(C2A@T87}?>~oZ=C4jVdVeT2kAn^Z$TD7x89EiC)`%k1{%Z8S-IO$5WY0MYaLC0; z@A)7tn$>0^KJwuMB^Hlx7MYTGn)6|k%_^F{JQxJ4pCn6=7&+>2(FBvt@ybf%bN6XX z_SGl1>?a$B2TTUIiQ@k*{i!TS43a-oP-T$F8yuz9QLOyqECo&wW5h0sm>||qzs6WK z(D@K{_}5H+$Q{0ghbQ`5MN1E;m8eDZnG>jK0v0(AuzqmsOwcQ)PBZ6*D2)#Z-`7#i zMDc|1b0tg?UP5#n914ev7vSdGb}9%K{}SzFn=HN;eiVO&cnvk8-xTo|`AwaxW{P-A z_`IlFwP^r3r-~Vqi}dchZ-bFk&YlscOoDglSaoFDkZR19dkeK5J4b^Q#c54nrRJ@(h`$i)?Y8@~0zc>#2IW3exWB;x2hUl?tvz2$xdR zmB@2nw9$nt#XX|Z<(whj6=Dv>&&23Fs-7v{!LKZZ1g`OYdAbFlM2ES zy}PM99J@gbRnCEm!*s*9wyF)9Gqy{9(oF$#Mda13J6|^WV}CE;ZOY+ws=#r)H-{r< z`(sZ*nJRK3B9h@|*h+cJw2D*1c}ztY<71vxeDD}m&K3U?-+D0Cmk1ugex2)z81k(mxbS7AlB@!2c-W6U5T7(bzL!k%zaSepCS*>wfe( z-6~B<2cuwrGX+J#{z2%BlOHxx68Fxd7wBCy$rKWK?!!{5j1sXv`N$msR`J3b>WqR* zoV`Gn1xU0%P$D<2tZh_b;IBXY*PJzW#+6 z98%0=Uo8GHI1KUO4c>fX-46`MjoPe1O&ziBLla`%r}vQMdN9>gOASjPl~d*6rhKZp zUffQ%EEVD643#Z~y54P|`lZ;S=8z>ugbw9`t^i~M^iZkWMfMnMCKgvm3>;zsDr0pJ ziUvx^_MMNyX3uXhV9ZUJ0n;zj9>m$~L8rxlEu)&{;-;}hj-5Htix0ccZC0Te|+ z*NAC@{#wolV5@lgYD%~U#ZUt^+^PG5De~N3v8`Ss9+YnsQ_{8ATXLx3TJf1UOjXxm zqde6}zVX=M+fX1v+$WK~{S(D?gH6s}r^)%M z6MT=7r}x>d~fxqxm!tb6BK)fKoEOA_;?%So+C zaEKTRxK%{@a0GX5n3pks`x(oU8BHAjRiH9W7+or@8 zY#X?gvrwR(ZJ!)Yfwv*+eMxb*A&>5-DsC1~*KKfu5Q?~6WY7CnKL(ooShLP#lXpal zNtB_rit_jR#yEEVJa(MgZbz!Q|Da8*n>W1=@xO@-?Hl_qBHGVXWdo73)L;`U=I!aj z{4Xln#=f!trm~u%lR;%Q*^QMw~SHq1p_O zJXae|mQ&QB>!b>c3 zb=)Dg4jB7pq>1kYerW}EXVru1{jk*gU zYB+^$!CvR2rY(rS5Q@7C+2sh;-X$gud7w0*SYDZ0>@-6r+U%%az;2+`*ICHu~7!0&3ePt{ikQDbmSO74D*d?Z_(o zsb;(Q16zHy11@kYH9L@a=TJ8{gDKdF264g7E0oX8{Zz@#20G2nGU{+b2t-g38ekSd zLmjU09pWk>4-~lUJE0peJ39|EPvXmg|_mq&m1W_MH)o6VDfD|0-zG=0}N~O&dv>UrYX&Kpfi%_2j z^vKTslB#xN`>W8ZzM3dY1E>vyVhj1+E5?kyl{cP0n>|s#(G)xU)P(!WDC1rcI`#*3 zNJm+y>QI$aZaS_zPu5wg1u>kA&)h4nm-n_&(0w>gnO%wZ;bb6c^s@BLQZWpNxYknS zl|ZuW0Y)cf>_I_%!Iiid))!Xl-iN}+Lh<{t9r^7?4lS;8q2q;eni39(?}qGXn0Kq` z{I;bxAY|8FxF7raJW4$Xzk0>hc2KMk zqKiT*MDLQq*2u%ctVd3ArURns(cHb?*v$RlH3Hs)Lu~E^q>4l?+893)aH~k3Lm3ai z-~*`Q0dcR~+DyTJK_Tz!>ii2Ea<|LB66G1{xP-$9k*}%lFr0cY1w4p3zmfGpahu$n zEf7 zaq(}2UfUDmPMK9jiPfA#4jvVAhhM|e@J3#kh6q>X^s0>%cNBcYk!_%yO`jbVlP20P z6h4I8{@%~0hIyf+*c`|xYCDb)O|GDb7huA0SLF*Z2d+bq-lxgiPmpiDSU31;_7t7^4b9}N zM`G}&>Uz{ir>W#c1g*(+`b8uLpIv%cx!^sjdl|{vk9<#vcYRiGU#h{WqaJphKLH&h z02D`SIuu7#{;D_zTU%d4)=g}p($}ENBv;#Od~I`60d+Kh;Sh>CDQ+BhDPAgbL8J5;@n)9UIYRP#D^FK~Sd z*(9Od)qIM@4X1!NV9o$n%o{Al06lPKt#XC`4Od1!KkGHr%*7Pbh$uWx-fv=~!xb3o z_qrr%dmF^A^P{kLVEy2~i?8H0-7ep^#0Qf1NgiC;#)D`pTm|olXN0u2yF!|T3roA& z-V=CxyeyuTa-A@dUo)~{%xQ{KZ3&e$BOS)+IrGv@RMw1~>38s~m_K4^bFABUgU2;_ z$Fqv@%P9UVR$7`*m1o5|pMavdM)IQP{ZYyJtncFlPfw}kU?wfC9I%MG8QlAl*c zVQsK^JLR+?m07904f#2cB0k5t!9*>eBUI+%=I@`#0^zROe~Pyx3|{yplIuy==`T4a zpV19Jt5siZR;ljB7ygB?h@hZ$97ty3^wo|4$f5RjaZp-X$oVzG%;Kb$uaP)oDE_1z zFb6$^>q`!gB)R; zZHCkS@5C}0+Da|oVgADu_&s!u{QJGQWzM$P-lJEm?9Z>%UUh~zu6T=!SUK4ZK9|jA#)6+{s^J!sIy&+rdNLy<#I|Q zCH#bq;|km`|Adh7#`{;I_@;(cZ=N7Am#^hbJl<(+exbqv68F%%*)ONX~c|ohE z`OPo<+x7n2R>WWFxHrHQ{h+(O>~UPZneaKr)Q|n~ig|qWVRy!i64VIzoJdcMf4oOE z{&Kk-SmWyQ2jAFIaz;SzZB#izUM0=V)I0+0d`>|ly#k1+hHvW<(w)fYglsHQEN>q1=qvd*3J*P*@Tg2zC zpfU1N0inYJp~^QYK2S~^_I(e(A5q^gp#+I_pPx*{f$){DDPXKTIH;!sC5|=LeeMCO zA1h}JEpj?!cx>;6ElQ%^4IAmgSUGD+Pfo1+)3=Q`vH{pr%(1;WtH7GRyPLi>Y`$4&2FPA1C)g6W!zF`gyC07Rm4h(SqNf4=S39OW56}@cmb_ zz$J5-gNQ1OIfV)LZ6=(k%^JpIdw)o#s`1kQTApp}UVgYd^u}!P^TQm^j>f8staNu< zO&`BlwAkeB?19y$&G%m&(y(w<$dYlZLY6PYX*FouRIkVH4|K^Oxr}XPogiPAzm<{i zMET^f3+=dvn`s<(Q)As9Urmh@W%huR0H5dTJs^amm_3n2j68RtaFI=zoZGxAnQ6!F z3#P@duu9f_ONEnUHln9vlAI>-f+Qdqf&3n|2g~{LmwF1GEMFF*sBN;m39b=w1!C)K zD!l?u9Y_sV$dSXdtiv1HSVW!BqenV z$Y=G~-eUsh@QZkeRrUPOWDk*74Ere_wIk#BM-)T(z0beGWx}jsKlvK)0Kk1?dyhYN zpdy6)rph5%KQ_kp))n!k6s84YXeMs3uQ8Si0(pr1{8+$tTPmZ8RrpgIEK^TS$ys(j+)8yO% z5qO-#kF$NMF%pFZe$%^lbfeLIMekbBjX}4FC5T=ohYacLDl39dYakM~ST| zkn5%6F!;%d?X6yoHb0`$1dSctjc4Fgv*ro`gZ7SY!m|_4(A?2X-d=HQT(skyvluYT z_EX1ze{>a}>;caNEZl%Cz`PRlBQQP_&!w@wPkfEG3@|8f;nA_W8GfDvU^y0j17@56 z>CG&$M+4Bx0E|~)5>#CMwJyZ-Z@ZkcAAtTgYM3kMUva)Hw)e5eF8bc%t7F|g z19mQSvU3FU=L505k1lovMaZXw7)xj7sV$(Jn^!1ozPxGjyod)(W%GMXH`JZez78IVHT~JsTT2S~)WI^FwW5C*Ddv@Yx0Xn^e_35}9_XbW*jz>4Z zU{$fbag)h+k&JY_hi(w;_r}gwao^6-(R=8XSobdj${Z$3ge{0|d(?nGhUagA7lg40 z2oW7|*aQt8I*Vtx{a^N=wE_k$9y*EVIKWugc);Mmhn{8yM1C%id4FE5{Hb@^p;fWH zN1kTeN3`OFlm3m^UOQCT7q*69rLT_f+7r&_3d4f>}N$?sbUT=T zrIBiHmmkU#om66z{{}ceS?-W8JLy8Q+V#HbeeZ9y>vGnOJ7y z#bw6cAxGd+G5ijM_pRi+9-b6TaqHon&z-08_3**x;wj7yFjQd&xVF<(XP0*h`D~6W zEKA-ZapW(_ksk{AR07#@;oVQ3rjA^hE}yhxu;`3pi>JHbL ze74_XIj-me`4=zwa0|6=g+U%pq@+T5qpa$7)fLKFLO#^!YTqWu3EVEbydCTrhZ88n zi2|jvkiv>!^Fv)!SA^nx19cb4F+*259p38r0V}}&ec*vRP*7N0&K=m`gukn5r@T_g zidJeWM#!w<+j`z%_b)J=d2WHJ37<8@-1LPNNpV0Ah3|q$)IklqqzgyWg1b?e9!zp2 z+#?4Hc|Uk9fi&gKu9gych1Zb%wGlS6sqp2{g4iB6a#*R195sRWAk>FJR+Hlbz(aX0 zlun&gTMB-P$yutRt*KOAJEV-i>*F06d&9MJ4panD+#We%NZFCto}M>3TgUds&!L<> zsC7fAbq~s>eH|3ASN2ZZi}#v659nci{Vqo3aJHIm{n`j`f0YJ$x~Ed~KJ3D8QpP@% zp&MNn_OUifTPb8ebXl56wfkZA`x?l4KxWDN;;8-r*xXMo2ar7O?F3)H>8q?tGiYn!slkLisun9GP9C=k0bBRBg=6)8!GBK3)3B!Swk|K zE;`%UYv}xOhybh?P+Dgsu~)62XI=6VnSn2sjE?u<6Bqp}c#Yv-mksx3okpHpR~Xy# z!MD1bU9pDZTyQfJ)w|$k>8Gj71vW-eKt0$Gqa*du#8`@Z5e5AwI`JYxHnoQQUy`rk z{YUdld~~LSmr)Uhxk_J#F$UvR#BYY@O!lFw6WHdSrW0t!u2J{VcvXj;cLRJ&owyd` z+uGQkcQ(1YPDm1?KGnVV%voph;0*nar8gwD=gb>)EoF87sCw{p8y7=266E1Cn=r zY|oo%bOyIf!|_5MAH0|>`!Q4orDNeY@dD^1jBlaR*X4uqmNE)EC3j+bt34%g-{MPk zrx8tS3VHJ!MXTSCyM`ooz?)NbZ=Tr0|GY=H&l)pddK<<{tkVxJm4B623`tD7Xf6N! z)bv+5dvG9lxLP;S=m*H}Z&2d`3PUqizhg3m;@!BgSWPkQNIc$=IP}H#oO+v5|As7c zoa+9DJ^jWuT*E@ER%&fT%3a;4bGhkFc>wn*-hY>O3{0qv?HvhC{awzUbKGj0n5i^{ z_v9Bf)$kZHWw6!c^|?CfZd3O?fx4XbRVR9$4lztI*dUb zO>mxTlc>81Y3Z64Dtiwen@NrD!CBx#@5@l1F!dIsryj}VePoBYMyh%r2@$F7ebh5} z<@W)?0{QL(B(m6II{$%OG$izWJSeANAlWp(e+j&l6MPE+1`}YBIi$A-iXuZN!_`82B?pf_d(AMRjttf)zsc9?;W_f6N%$X-Dw{A6i%}^ z9!?XcJI$aMDd!esn#Jejwt>+tu{||->v|5yk}cGEPL7;96`ywS_ie5420x6Bf^hm5 z;cC08S*!~Eo*LxM&*XJu{h{6vUA<3zs+-`cv$~p}dYdXgLn2(%KrNp^cEtZ@P&=Hn zP3|1J+n^h)YUrLPpQHLVILpFf^8XyjxS{*%T4A zuCA}-L@zm~#1-(3{ELvYJE-p8@&nYp>f@jK4mp3|th(5qA2R7e2Ws3|sTB1sjET1b z-^v>Y&Mc4Z`Ee8Zeg{`SOkv+4zCx(rJ2_==5x$8uK{rrmC%zB-4s$Iv)cGBhz8lx& zh`=baeGll23v}drK+jUs_YiMJG48(6P3G=Mx}{TEz)UHFzQsQl8A#@GgWZ!J!<|zE|k+t$p1&+r&08eGX09MuAMj+IZj--vS@+H%>P)1FZY~C zM6o^J4bYWaahT5h2xh`gkl#h4Qek0 z7u|~7X2QSY9H|0mP)H%*NTf8AY`@}w5R&LB`BnbnH6$1pVm&?lsY`6nzQ?Ha51cWA zaYGJkOsb%SZiKub3^HFQ8tF`sdCF9OpqUl2$>e7;ZK#KE-1or306XLE>F&bkvgR512qSKS zneUkMCzwOgtD0b*?Sp?+EBs80hgfLB2=gfVd4hQ~?&JL?n&%Ek0;x8#z2`NYk|&x+ zV4G~J_nJ5`JKo(pAe^cunx`ya6z_{1WS3$n{y$(qoF@rlv{eNduhj-hl!9I0c)If;0hw&#{65Nw~kvJl-e7WZD=6 zUhL1d3W#SwG=)DLqP!YO#TbP zSKg3kL@m&JcK(g&JP)QY>tO^+rX52-s17 zSZ`AmU{Tb`6H-}U<9*;&n>qn4rRb@k)-Q#m*Jbee%JR4dHGNrb`)Efg3EPzB}0nUW5&^SQHIoaWCNu*QFosY1;>{!J@-TA%UU7zn zK^OR{JIuUvKp{pOsHwrrpH76CN5b)&!_26S$#*)C5-57Qj)aTuoEN=D(nHhD0S;!u zS1qX&cvqpjH{?IUPf4{l)2F&AGjCTewD{%V5+5n5vVGcE& z5xW4i{26hpH(=02|H)gS(GX^&AHl8AXb20@9|nzv0Q4sqG&-dVu#18?Ok3>$UicHx zwABe%H(-haS}?e^90bw+304glGZ=^;|1sVPz}VdVVNHOA1J+MlTM-H&;jI4tzzYUq zzl95Z0kZ`fJFmm4o-U8q4(*{bb^6SYM*JICTEz) ze-^?YulZ*IihmQs4RYKpu0gMpjC<4Q}BK?gd4n9;-(v4*&{xZsD^uZ^NhUWW5IjM8h7v9 zGJJcF!4}-Kqv@v9IUv?fRdWznsnjwDi=QU%t3bM&!mmOvky5!=N@Z7pqk8bdT=5^; zortalEp+B8%nl^;Tp*T^Wv+SlfMy^h>B`Hc}hXkAnbFci}=&m1`@2#c6u@rD8V&U@8-^C&1Jem<6n zqQd#+6$9AuOY|)D*?eTF9EyJpTjf0nf>jk16bWJtNW034C2-_bEtC@p)dk~U3}7sR z8Y9h-KHVmhgU5YV0K61u$4OSr-7&n+g}0WAP8a8W(`uI_h3&zH;Eb(BLgWRQ4^b4i(>L zLf1<13!$qcSdX>Ae{hKVqA}D+WeZ_18$j*4u0LG}UE^OwEQAVikGaS^cX$&x+pNBl?jug z&A4Qwx@f4YhR!n(FA5i4J|wR@D$y@7U?98? zxobW0$x^r?E1*z!fqhHi0s&OL)I4`8E7ZdZsFWRX_u5YbhHzGYP(@iiV6EgG0|ntj zr5J>K0p)YAnkr*Jx)YeCI_WQB%>MYWM0wYKc-O{!3R(utN{@FPfOl=I!>a}}{@)xX zs^UR^YFq|=70`ucpj}T<%OPwB%8r@MC>zPG#@J`n{Wy>*?iZyXH65SJ?Bhru5YCZK1<>QNjXlHQ9% z1^m~m5r)w#1qu4+m=eOV+ z^$2%waXVl};qqu4{K3Zl9SRoO<6wk}gDnWyr-zz{`9QqC__}-V?xLh?5V##waSbR( zQNuOx(`sttUL!tj1do3~WR$d#4>}UAwD;^3e;fij`@LEWcXlMh{ z9Zquh?&+c$#weyXU&}2DsWLi<*TrKJvFSt6o2aCo}GfO z$5=gCxv^2s^%%3!k?S#r((ig`B7%HxFi#m|!_uwnj9z;BeQCCNC}+MZc=`h-$^i~$ zRB)3-4L86zU3B3FkimDf322HbJ^^EAsDK+Jq6DlI!p)2Uh`d7?{20mW^UofN?**9}Hpfa6bC|=SBlo3RrYM zJOs?c_2|QWCn_)#%mDBVdO-@Ja_|x4%ZIT)--J`@1%Uh0g?1jnv_76N?Z_Fx!YMG( zJZV)Dh5%B3Kzj@#Jd%MPG}#A(2#*w?*H47UAi^WaBzVz^N1E}<5gP2EdT!#W zjhjaDUIShGQurDi1VgB7jd|%DUO5piVTl{M*s)@WY4O0to)sTQf_()l#= z6i2+f^GS>QryYszPKf-|jyd>U?(RI=h<2>I^NA$)Pmb{h%x1s}-9Obx%(J6E88}X~ zq3+J=ZnT%7twK8rZ7N#OJNg}Py6~KawixYtcW2Fc{HpLy?%s5Bm?MqtCPPxQrxv4B zb$6xN(Z3{Q5dgbXzYu-z5PNoZ&eXekycB((kWdA<2hR+vL^~*TQx3iYQ~g@BLuLVB z&}=~evPBpBY;eEqJJWKDaqwaSZ2%0N#SnebPV|T6WTvdw38bTIx;!;E+aQ?khra(T z1}OaWAoPc4WqKG$x1c{FH`{JE=0~GHGB-QlU@$!%{ebBJI1B_E0Hg9YCwmsiL4Wit z2Ivbo(I2xgcL$hFFT-8H^T%2fc> zZ${rSK?h7QRGEGrz=@$ntd(?*fl1TV^Exx0gQw}wet4d|X&NuOE)dUGY}hnoLv|_? zT^EA>l;pK}hNSBv&=1K{FoFU@EJU`0sUhRl2w zY8k8rYsmVvEsIn?6J68Q+}A@h(+~ZXX$5I1oAT2P|H%vjEH)!8*H|Po9Q`=%Pf$*o z8H4^cso86Dle1DXN=&nulT22{wW-;Qbm(pc%K+@UO9Fmb~eyX=^vF zQ^MVm3fQf|nOQ0JO{r-mO0YZF)VBqvWu;`NrcH-cIMYGkJJ6VJ4^fjjAnrJF&<^?T zr~^1TFCTHG6nn=R^v(F0(zA2(Gp5@yb}yr|+-CPL-br?#<|)6wqss$Zo1AADYP~nZ z@bjCI!rrr<<@Lf(%-F2@EHC%v3_JRcuJtT51I#nB6hd5Izd-eqjK23wrI_`0qc3LZ z{X(NJXY2h^qwh6+rkY>LeK-Cr`gn~oZrZSAdY*5ZJ>77*^(QE312nR}83+Q&JO}L{ zNDu@cPek9Ak>*J^>pS}4`1QxhPRUQUD^1$jtvz(S`{Sf+%FRv7$~V@vhXc+%$VPujB6e)SjQa zDXmzIZ3qNRX)_(ObeGv+p|ULV7)K0-!18*KSmzJYr@?x-(Qm{yP>g;KFBy`Oy&(sV zIXyeezGdoO;BT<~A9Kq<>rZntH*82t&4df80NB9BWi{oyyBw^i4N9i|^q~}9z%VK! zD!eLYB;B68E^iU*bOX!E%-is@U{P;f2o^v&f&={%Jg1L=MI07ctPjk~3Sw6VfRVV( zC}-sUjOa$lO6Z%=wVtJ8e6%|LEk&jsAO>A4W*XoXZ5UJDcdK&WtZHMdw*MHiM7ASe zxn0(29U;>S;*cU!O%Bs1pT9W9l4iAgh^K^ctYl-D7v{OF1vQ?-f~fSV=w}D%I6PnB zp;dxA{B>#A_DYQ)$j>Yx6H2pXZL-^^D@v@oY{Ore2>VJlT7G6fQ8XIBTo=#VtTV^% z?O~2-8*~*D(XhYbwvZ>-^$8~oPU8(u(JD^+Gx{GerlAM|uIQC8y(qOQW*b4zrdkI) zIC8$H+{}sM62NdER=aMqg=@1@wMQ4E+wVlI=Vq=mX4-WeW$YN>bme~f0No9;@C*&=^-bRj5D2)A z+&F!az6n^UZxJYGeeFd;X-d`l0-l9cmc<-qfEiTG^0Q4hX=Vg3o|(P_X3wqF*UF6t zOjo4i|IlPU^r&k-&&Y7B$lN+52@=0C7OxXj#Oyj_|7n$U%+rk!vNmm9X4X_=+sjj4 zfV7G*N?w=TZ@|cKfN#pm&$RbVXfPJDg>25i?$HNt>4WE{<)kI&Pc2cZ&Fkz3*L^S* zg^Sv6^1b!3%u&{hs!E5t+5dE3qOwiqk&a*;&!e%tntnpUeBd!RO{cB%x)1p9zWgL( zZD={K)gY;BT#?U*#dKwQrZa1Lc;uJsb9q;Aq*s9e7EQ;GP0hb_@W_7F=O)2`CE!=A z!&MBS&xF1rgem+3@tRLR091MTAMk>8}4aCH6Ok}IR_Vre%S zdm6hz9vD;#WN8hT$Zz&YtCXbAaq3d4IsZ#TYL0RbWo^aPraFC6A5&fZ7K5a`@c;5Z z&VTF~oESE>UtBofx8MAJ%=Y=Z!)8xQzB4V4Gw+>Yn1}@m;ygCvy93>3cc$t@@66EC z0h=uCJhTA@J?X*|sca@@lG9%QbjQpErB<4v#-7!U*d$TWU6k@|{k7LDqz4 zQ6)K?hEDxDrXe0mM+uO7m6kHyZ;=FkZ?UR-$d z8G|uM?s2;QTJZ>=Grvd?QHvQ`P$q)x;3vSPQ%%refT) zp%(OucMdaNNa2-Xp1*FAyaW*EY+MB!cX%|Etuk{#p-x}z`bK!NrX1`fifeQ@-aXHG zK?X6vJqxNF!Hi|6D-9K#(1~)aGqF7Um;nQ?ATuArIo(}b{0zJrofh%{AI-Y9L~u>R zN3)={X`W-~mU#3TcFEd2g~XoEeeaZHoNCm$a7(@c8*Iyb=!87?YFoOE zMZ!H2&cdCUF8y5r#u&83n&SORcRsWZbkc0I7J6=e?lSy9A>;!AT&qdOWZ>p5CwRfN*_*ObRc75gO#?HHZ~j^+}x1S?w8WVyb>OX%shwHiIz6m1)X>XW|7?ai^(krVtI=ygwb4 zh@i#762{%M!Qr_NEv(j&FWNV6!;IXt4V=Xan+-xxpT`*s!Bl!Zn2*CaqJbUI!>nhK zbxHpN?uR)HFIKHXk4sznhCW6*FLKR`v6rsH0v_TFD+D7P%M8nj))!%$tAzsrcVdpe zz6dkMj>!vdiPCX(2cCu{9jVI8wGp|vq&+W&AL*2fBW4nid!$_BZl86bgr2PnZG{LtwyrJ~X zH}Zu8evqDz496`Pb|f+0=C$eeOjQRsDwt6RfF8B{4=wbm*^q>Zp+?x;N2Gy?^rP`V z%;BNoVOVFxt~26*%ADr^HxUPz{4YX)>BMHFcrN{&hQFvQrXXf^#^%1Ua($ik(a@wm zW_R=r)*6HHeS=wjV`q#pn`bN~In?lMXS+V;tiTvF2o?8@6&Zp#>pWxji(^4*o}!1$ujdkt7wj9$*XJn-6*KmWV`at|3#i7jFlM~gDl)v= zbEq}$qta51bX(MDOoj%whUo+pE}Tl=Y*I3kb3;`wDKa!tRKVIuL1ClAcNlv?(HR8? ze%>w<+kZ!xAuUv>Prv}fV+=U7pu=?y?BHbOg`YWU0dF!p45>4!kQw6`ccBgkIy)!t zA3EHk!z*<-XHN&$d}%gI)B?kvJL)bD?kLg6)FMq6;rfPTiSiU8I}C|E=@|6XF1pj) zZw{DaxM!W6foja5a`+B4xT%kcoe}!PjCv2}n=VdFFvj5hx>TDp^E341vy<}#Bv$)I z7bFK=jvC$rcn!`K`kb|C`J2kS*lO;l*c>EnA=(Ez1Ysv`WWYl9TpG` z(TQ>k9QFEZXWK;_wTC1ci!wf*al^OSQ;HQETFHn8oa34^oztXq=s73=CXheXE(Y7< zW~o>)T5Qo5;zd~9oZ(oytXP-HQvA>lc6TXH=0n91y`N?aR*qC`H<(Gq0$uu6tO#S?UC5MtKc{GWySs{WARseo z%T7->e69F`ai__MY$sh++3GdTF2e^lK!S^7YwgKd>s55@GW=jm0_I_HoS1TPUed>m zh+qvFH@qs{<{9C!}9~w}qibgn`Hl7Qi4fNCMAaxrP*K>X!fm#oNe)FMj zCnQz0N-#hEPxJrGK&LU^!7A}Ezy$F7-vm;U^HVa?bCWlu@!j^_77$=ZGAX!{`tBT^ z==v6DtO~zIy}dghS_m;8`M3^Q50<-gY0Q{_e;kt9-S~DXzd$Ud){-<`j^M><8 z8}pcOw?6MrbYM=!1Tzz?k27sPCo+RM?5MW9%kqL*@Ut%7qK5sUg zE_1unbJNnM+cWd>)$l#|M5@F*;>LRn^Qz+z2%ZoWoLh^3qF)vb?MQo zg2sUHHgJ#47`IW_Zu4lzJ)TU^fH9^A`O%uFy zKAqmvZ5R%8IRI6Fn)O<^s6(e;Vlvj@c<`hKb(s1$tbAS{>@N}LL6r+3p~8n%nQ@QA zJf=2TXkFJJn82c}4K;?At=Hc&3eN$cBAlors8Z3G=rN^ADZcuG3YS%yYV}vCp~SEb91y$sWo3{Gn1O=vhSk z-;3yLlpD-IIMyDke}{$hA=?F=KKsEGta^rf7UiVuQL9Sc@Pq#L|4+%d%21L!AtkiN ze&E6J^c4dRLlqudZ)pZ{a6dJ}?yOdi4|pak#=xkDL6*n^>q|eN<2eB;X1w(X@|c&M z*WvL{_Dqlc`nYGO>oVXNX9+y&=HrQHL62tA!+~St&s6lydv_O1iZ@!BW`^f)$>GaC zXrwe=4^eF54t*DgdOW*#X#$XW^W|8zsjn-h^VEBJVn*M@|C*;3>6@3Ay(u>(ZF**^ zN~EP#n8y{QDRV6sccm?Q-#o-IDRZr{JC|}*hb=~!7WRGgRLaQ&Fq6~?@`-PcANq)z zQZTs3WW>8|MqYkyX4X1m!`&0C<7}yiUqQI^eBHm4U)gf9Q`V>D=VjiNcJBZti2q;L zUVJ&ThtoWBX*Li%#7e1iuX(iGbA){NA!YAr(24IUz+5;NpKVH-@LX*q7-Ip&Y->MU zm`^!6@D;A%^m`1rrx;|K+rxpwa5lRwFDKc!ecJ2IB@Amsq-WyB7FE5TO!gYb6qb;4 z0dMl`J8V{!%0ZC(>_e)ADK{bnKE`#o$A|iSk3%1Gcs|eJpI)bN2@6kFK7t&;6Vhxs zI9=$q&|ae|;Qd6I$ls6}bM_|b&wD&Dv`m;8?yC|3Q^^T1&t9VthI1JRS5 zw&K|%0TWaUq%vc9>oapUt4q1P7j#oFQyxYU3lp(6)%a;n z+3;%q@PvzSRpUV7bP!>i?*J2?P-Y3#2Pzzv=Yhjg*+Po=1wdJ}PF!txQ+47xlS%q` zrLlN_lO^(e$3*opLfHu&q3H!f&`H6Swf>dOfh3(4 zM-pp;ZynUPLI`cotBnKIjKf=Yv*Cb1?n^lT54HU-t??o_>ZGI?{&4^mk|Q^XK|Rhl_#PMd$avr;WSm0~m$_K^h zBMBm-WGFV#D|9FZG>5bosXKK-qB__Rr?GtZJSvjmewIG$-pi(~X^)>%xI*v<%0T>& z1e;aw1paYQPXmm$Q>Jl}Ui?6$ks3}_+f7>L;_<(T5 z_`oe)J)5Ir=C{wV{Ud>ZXn19zItXz9h|C)vxFsL~vI6%xTrIdzUR>*_5nHEe3khx@ z#bOuFCa8btx;GXHMgg=pp~#;F;`E#$i$lkdMCPV%L$7B|q#ij`kpU7)$hp%}z1wAdBtM|cje&`0 zfy0lsz#v^SjW>v`wWh_@zyECm*5pICf0$nEiDDst^v45P48|kpjJOfh2eF*G;Khzh zIx(>udov?{UXjoierr;xbv++Dq+W=XM%lNmqzbNsIf+sKYK&O?!Aw?$!7hkDwAtV; zKyF(oNSe}`bESS5v53h5<=Q1fKZ&$n@u{kSjJ7m;M1uD z8-60Dx~Klf0rxt%$(}xJFz@TsJ-eU4c^%JVpYV&9R{6m)iV=$72)+7*Ftb+vJK4Vvp15$s5J zckJ%zw~pqyoRtM3B;dJWBd8ts^(a4Q&u9VkibTqC(w*a1Bv}iuIRT$Oa-kxlx>Nyy zXAgFliW7NmLXrMh1dw0}K?FY10Wa6zG@Nt0=AM_GkFX7AY~-Y@Nwp~lmCZ`T4-T0A zJUDhOgwLEcq|r)R0>2|5ye3i(_c8+mMg!G%PPQ{W->n=Hh_mSDGo-pF%MtMN1*X) zGAg*yt#rQtNC4bKI*{&E0?eNrK8A=HQc!6k-eHVEww9EG(2 z41~O>J8@7I&mv;vDG?k+tJFTZNfA&jKJJ5B7;8k;^2s^EM_I3yU+xQ(7kG`0zqEOE zOq~WDMmou>Biq^2Bioohc}$Ufa#E%8Nr*3~OC}suNu>+FE0-ma6XqAFu8A?!p9K@AH8Ls->yyDsS%jT1t{7l=&Oo_~_2IWyyZL~LIVEDE zP9?zDfE#@1fF{T#k#^%cPr`>pYDY{ej&K|dB+~dam$sDhp_N(F^^tZ(K!DNVx3yy#jXRVkISWOWg zIja?qyeM2~TEWu5X{r2b85@44TJxx5!jrXzS*Qt2NQ*!kL%W^$9Y5$>MIhdcz#yvC zZiC-v8X~}e>*i2-# z@rIu@10qpG!to-11?1)ND#);G7K?60894G?<_E=8* zp9K;>k};qpOa`#y_=RB!K@cZ>LH7zpOky1jrtJjWE|ix^&dm`Qybm~&0SHW`Gd;Z< zWTnPO1baK%>5$Sx|k!~=Ko{u1_FCi02H7HR;8kIyKd))z0?4T_| zjBzgMH4**R8DJ1aJv&Yo=pIB-N>U$cAQ5sON9S_@^~Ug=f&Yn-QUHn;;Fyn8Vh=@` z0evo^>iL`@7S16t0Zj2Cy|+aG<3I|70YWI%vNDjS5WEWQpOlmVsxyKJ%oU7l8fLs! zauW0NBT5KEE@y018J)}LM-3SWVSw@lz!3FfFe6B7@s2iLq0c11TY%OPio3VgV^u};>TYXalazI49A()g@}(K?Xnz~GaS4Q z$G6Fx{ueH)s5$G+7QoivRzeo6fI!@W*y2E{gsPRbhdKPBE~BQ>5)bq*gF@&^ngztz zoiZSeYB-A_lYO)q5EfS(@v-1Bt7{Y6ew|@d{k?DMwZ#G*Tu(r;LeK0BIE%fY0Q1>= zP*^wv!kq`LX&C{udNE*dPZ-v;WWkGh(vrAGXJ5(ty>?3L$g3?n&z~A{`=^dsw@ILs z4v|Z=3S%UppQ*vK6E!%Y(WaSaj5vu>T|zX<{5t9}Oq0ru?ss%jB|p*E=WPc_O%iR ze$m1@`jjtT1V8}bfJon%T-(>rIdkj6zhsMHM9Pchg}Aah_esm0G+)&li;PPf=y6ez zo{<@DB0>m4TIQT0XMQ@V_ww>Ap8F<&td;2)S8^^Zhmp=mu`t=9n(+)wXgxBaFWz=^ z=I};t6IX?Tj-4{0HF+47WR&G5qgF`>Fgc^ZsE$dfQiglDXIw$UmNclIz*BKPJ3sk1u?O0#UcJ2FGMaPj5Fat^)>-HDAQR6=48m=q(z$qV``_5+}7 z5RMq-b~lb2=-835b&fA@FM}NvJn)7HZ~$_^sUF@7f;w6^!IW0xU^u71E_misXRlp6qO*05aYOv53;``|uCLIX_*BmyyB39na8^e%B2HPXh25ni&X`0m~c-D;9naL<=Er zp>*=wj>m76=Ioku8QdNP{9A;3PKgj0G;B)r29t2TCncd(Yyvl?ZbTO zAxJu+&PFAg^O=I+O(m5I;;j`b#e^DF%DmqNgYLep)$z!I4xI=2JvJElKejSnTx#eU z;lc`3NXHfR9g6`IRkHa4;c=7~BK=%cNeT<*uTh>(647AiAl@H!zUX)zaC2gvhy~ac zB`zLq)_XNnt;Z?D<3~$e96v^&IISw3UGHXOkK4GHp#qng#92bJyyvBkQ>w_kSa96p z6XEKTB6S`VgJ~Svp;Lt~u!)Pm>FP;mbY1EN)8+9OK}bRC(#IUXq(sv9@EJR(oyQX& z^+HPXQ7;g^QQWT5e&|xU?&<5v`8VBV#qI^uAzKh7wiHIjmLu=6ZzG}}oMkeo?$V~C zUYK=+BL_!2K>>2;##gGDz779kX}ra_L9FvD2|Pk2U#Wq((2B%~fdew_Dy2saaE<< zZ$;hN@))@+q685dEkJM!*683Y1xT&7Ft!5P7Dog!-C!!@wtbN_h=8Pu#edalO_nL2 zQ$rqXlvAEv=UG-wU_t#KS(yNZ76AC6X1ck|*QQ+a9K-@tM$X6h$^|upgBKv`m`dxD zjUXOno#?Uu3Y*_@O+58zD2o}pkz(P*R;?$|C5V*iiDk&3ejeEe0LO7(0KjqMxEaVB zgzLfywjyv8t2U`s-_P0Pbc&H)M$?w9lCm-bd^tG(P2dTf_pA690kjmAZYAX@+ z-+)vI5+{d`U|aM@De&c3s&?r?g9Ei(77myfI4}b>hY#ft$s~RmOMZi0nf^V-U>RJP ziqHpDM&RCzL&r)4{`VCISo)%T@~iP%*E&fp5oy9+pza8O^7=Wees-0q5rE;WJ$rWnA*PnM0TjNJCRE7?&(as1r<>mn-VRBx0ib$Y4{BUSS*~}Vt|(#;CTNo zPA^Ekgq3kh^UcJTwNu0kL>h5uvt*Zf0&SD4Z|qWCqa7H;z85K%USR>NtPnxqJUi#ycC*UN^SunIa0h-9%SLWe(4&ZqV z_h8u1htrCZSsY2wq#JH+BhDWH73pGEPDg~W=Gp%vL& z|Dc2Yv5{io57_A$U;=j@jrRhJ+QL1FCJwHTO1T*Pxv0`*Ua(9-)R^Xg0Nv{y|CLB6 zDIoa+R2Hun0Y*D|I;OB3LP2KmD5*by6tPrkAT>h&L%-ZStAPc>Ha0E^GVm*-_{{*^ zf_oqlkcRM!+P;{@HNjkD8TOu0C_?>my?*kJBLh zF@R>9fApf3W9;$BF_zh}H*M=br{X1sPqo2jMGIKOQ&;g|$6$I7UYLA4N@-)I%VOi< zMFRP%Q9AkPklRv!Dxm;5q+#C4dFD%Wi1pi^KAPJpHdsjQujZKEgRuXx^q>$6n>{tI z0NlWf;U*FB_tYV6wG<`eRX-I5weXpHFI=clJd3n#4!I&}k`oTcMEj@A=EWpY|NjBO zPY36Ug%?oqk6IL&AejUZAoR!*`pi5=VQ#~RM?3@08_E%r>p!kn#{PH(@&@osxRgY_ zNxS}+2J%1nlX(3#PR6Hlg!0)VH!jVu_*(p$tNs`*D~55$qs`B}FcPdB7=+*K+@;O! zPtPHb%8XfZ)4))+TO*yRVI;$<|8%ZcnA)eJlHq2xiilyJq^F3_*Y6)N1DZ0G&^5Sn ze;OC_=jhZ9`S`d_oAxM+RU z>7zk708`KzftVL<69AiDhk%pi1h77JEJS!XD{-Qtjz_6Izl)D~PtzYj}STgT5r9`Kb z7|`H!H3Vcb*7*7fEn^!819cp*at@Z=ZbEuSdQ8rNQ1_W*>WQfunU$O^l|=_vj^L~! zpoC}xJ|M1v#KGhv7m+@q63mQQzr!{wOOP;kA}>R_&5+LFHz}ORi0&J$iipnT>o01% z7Z~l_sgArWopcg-fXmD%?6PIhw=+WB3J(QCli6bc6An+Q*LtQdzvY`29cLg3O2C(c z^&^_F6~k3j;f^CN6}6J zBOs8TEY8qz@3c=NL?<#Yxf-n`#KU$XCw%UuLz$j5;!a{f4g%RArol8{IL!8IA2)5j zpG469h@A8G-&hAVLG(C|Qwx3*umm~uOAfyYU@~~NGoioPhuS|5|A?62uJoV_5_T8vj*r}fJ5%tDyX+_mALoYkQt4At3k`r;;~VL)+igtzqMJ@ z$vLM77+Mkzne+WdeM$UKLs06eX4NqDwen_Z3ExU7z`e*DrB0ocY5`=T^rERaz;<0`l0o)T8BfhQxIxTY~s6^chN26+`5K~D?%*Q3fO#x7{6YOMgWB?F@ z*l(M}q^m|b{t}T#4$0B-T{j&RUj#rPpjVX1Gn_)jA;`DqloJ9F&YKmO^ess9@f$d0 z{q8v>jKpcwgl8b8$W`n-X%|xugFs;Rc6t?8qaiLqvPl8;oktrU(|b7q&OZVdt{#vHi28a>2@+D`IF&BXY~#ZVMBoB^+>=Kyi`~sE8@zr-PJPPmB3kABqzb>k0H<-fLbn(OQh)RfWp#eh>O^-V z)mR$q)ZsoUh}r&x_`iUV*kXR|Gz^A1^y}s;w3njO_=|&f56MUeG)F*)4F;O_^w`;U zXW{@PlkAetMlJ}>Y|bD5OT-sv=#Y?q=XB#k?|bmWauEKReTtm+#mh|x(;&U00@3sz zoQiPHst7tss{}!Df`gx`S3{OY0O8PM%jQ)r2mLNb!S;<0emM4H3!`g)XyfJ&ZTxU- zv9e=jfLV6yrj5V2c-aXp`%E3}Yw7mw3jjhrZoo<|d3q@K1-&*;36rx?d6VJHm`X~x zi>vC%A*IG4#F=rOpkbQWFrJ+|U@Lr_yWPYeBq17bP*w;9q^SZq0r-9hh}dySy+-6s zRMe~0dcF+GdpJ|&?jR^af9elZwA{J;mnW4gwvN9%1>i{)CG-9YgEevG$r0(${_0q% ztZ=+Vrvao-p#-|!v;gX!Du$14Hg&T@d;b zKcZZbNJe32@XY#LKdUT556z3^bP?vEX7`TK|8VD0i@1^x-RUz5CRPB(Ovq4ACY8cG zm^9s)8qJetw%}vFERPR>WDz%7%rVm#DZlK_)pvqnysn8u{hNjZcVgVkHbYngLu=Ie z0xU1~WSe@hd<@ZokQws}pP0w`D8x&CGxG{Oy0*&R(ltSjFQ~HeMOz@h%YayL^Vbc8gZLr}he(;@==zs)Yns5+=d)2qYOtegLjj+&G55+ekHW|4(#FE@~!` ze}l_c2KUsTAOQ>+tiV}$-4i%rPvT90QX!p)pV`(M}p{*fCmU6D_IH-7!kQku(q+D+h|o%8j9kCDo8z*}GlY zlNDvTTvS=O#TA|_FYLx}mF4fT@_%2uNO`QORhGZkm2YEtv{%QWAi!KtWrg>+3ImHE zz&6Ut@~y7?#3JRPpZ`1t0M~iUv10cA^7f4!x_EG`l-|O>7EI(J4{~n(|VfjbP@>_lWl;zL* z{6K8ZeNF8j&S?RWfI0+`fXipI_7W)N-|h1gmQM+k@>_geB`q2ALBQ?>-;%n*cAIe#EXT0Xut&` z{vm~H6xUH))41mHBmao+HPAs=@$>Ow;d}$Gc3df3qqvUZn#MIJ{AFcX#JYj+Z&Dg) z_r6sRXglCSoV14$?b)VgsV(uz_eZtvRdn&+KS1}JPy7?s^uIr)85~#0_!G$4hkPf6 z=hNC1a0Pm&!+FS+x zy8CEM*?U$eQCar;^W<0^EhL3cIT{1zY)OF2mu+=CzxAKCD01#JOea4g8-)KUqa1Ub z;5Ke$l4^VIWCn838!I1WeP@%6vXDo6a0Gu1y)W-so`g#84txQ1li-k-$ooxn@hX%7jYL0Hm`vQ?leEAhBZdV+EvR-2Kxi zB-9Ed$MFmMSh6l!_r8U70bA=Lt6G_hGD8?a>|zuM$8{A1ya6Dw6A>6oo0={U1IE5p z2{9?(Eg};gQ`8Xc_x3?_(67XdwWxq}idD*hd#s1ey%c|E+2&&Avu?z&L}hNS^R;0h zO*Y9w?FH+sIW3_3bis3iMBz6cF>a`j_9J*vRtDL1_zoj>k0)~d`QMn2zv(Kj=<$L# zotTf`aMl0eXdUkTg^~Q!JiO~m-R_ydaSq;U-TegLkV^k1(ngAfm*66_4t}dy2H*X| z$zu4DmALMgjz{uqn6G;``?Kj3z3@w9NO0n}*6I(zd44qZbBbU-QlO3nItF(R@k?1* zK`>t%$;Y=EF+3o7t9hUv5zIH|Ctk)3;ry0Jx!C$t-)g0j1FHFQMv>QvPax?bJM-*& z9D&tRFP*lj^!bTMUXA3TpTK8J@lim*eah!!hNhMUdegb?{*+q^n}5+4z=uo}K+kR* z$|;4$L;&-bB4z4XW+jeS%48gjmlKiv6-LC4GzUq8B;w^Z=A*T}FoK%|3*d~E-T{7S zQY83tk_9Zk0V*yDQ1eIf^RGaHFHc0u#nxk|*uZMOK|%?>%oy9jh-)4Rki6MQUbW_7 zDM==QUY?KS)evL}If;Lz2KgLv)UMAz^(sEOzRH!)PrQn+bmOqZSL3%XePtkjPJYLp zE#Pd#SB~db;P=;FIb*eB8@gnp4rY{g!14t0d6)OF=E;#)dSuC~apYAM!{cZ{SeKQm z`o2(BLWfrq`LP195$@BQ7vkEXWIeM=&R!bUN+}D@Z3Nm zJ7zgG0>)pRL>WZgufRLKGK1>^(%NyQa54Xo`e^w0pz!K(9FKCeL@PoZg=LNO)folG z4uNIaAqaqN^c=VcK&Ht(5cqo_boV5{-_JzuIdv`>Ca3|M`!B3er0j25+0SmlnX^xJ z>kD*U)iHHl`*Y?xo5fWoeqirmfH2wF%PIF)#&|;Eehi08un3RS75ZfbwGz;K=e|H9T*D<(2$SB7Do;-Er$H=yBu=5 zc)|kW=tUwpfg{8m_JptG{KgO3Y<|;m&uCjX#qM6edQ_tTE4ksZL227h`h%Pzr%k&_ zmGGigeSh znT!Hv(aD}fU0O<=(#z>F$>W?Ith5Y2$_xHCC-@g668N+#I+!~WkiP3Yqr|9>P-6bM zF(PSb?g#A=;1dS;`Um-yp2UL>pvOvR?X?D*a7nlj@TNrK!Tw;dw<8BS)+PX132<9! zD0Nrxf$ntYuIy0nV&zXTha5i`j&M_^DoP4} zjbh9z??@=2PHoaSw^4oWC$5O?Q*UV$0yz<#GPLdoB{7;~Al70IK`adzy0nyR7%RIHwX} z1jmabyo(3O9s9+Umb8}lFXLMFpI1S04W)xxcuouB+=Vc3sAzf+U)EMI9~(im|1VP| zASGlw8t=OUvU{Rf_+ec0>C+}#(UNds-KB9Y^GA^1p!saU3=j29&>fBTYMty){$aa= zfnSu7a_8aW`sOsvGqQSR1-oMe6ksngp!17lh0xm2eSi!4Lg^q_2fl5c1J=(yF9jfW*$ z`_UZmi|bwifYZ9WQTJd)3SH7NTo)-dwH=LEIJkq$o|h7uPiOSVIc;KYs6tina!k=~ zZa2HS)P{Q8M8I|*f`B(t`8HSCIy_o_Sv^QY-%#JdFa63}cbCk^I6O2|IVJ&w$$srJ z0BAa-)_E+ocI|QQyjKnA(mCZ=ChY-)eUC;fJM=U5oCSqs{q#V2?;+P4C3xx*o% zuGaN-4DO=U6Ume!VMQs6dMvZvzO5++igK@+Kk#4VL>Yc6Qf7CUzqv$g7f1Vh_9-Cw z@}wbqEfXokGDo#c%5?gg1!fd27jbr@xse!rE>n#1HM4k^zX#rs`SKk}hhxTqpgmTZ z=dyY#t&I;SwIbqg$^Nh4pjfNK4Vwh|yVTH%tICNU2604+x+tPjESe`Y!h*uyIw{n% z6Qz1O`s8iNVz&a4HeRdZ=2Q{I?xz%y&OLvaPJBDoNM&D65n%$GGyMpI683s&5;=`) z0C|k$PDOUc$R;9qD1NJqlPGeO!HkL&fZIIaX#)(71So;UE%E^ZiFhDlp9h$a&jRjg zz+@EkB7W^N8aaF-0mHmP}Rp5ln$BQQs@YH5|eu!ZL51Ahb~JgJt0L=3TIA8;5ut@Y>6*{mSw zV@Tj91>2QAroDVt^Sa{L#Q=%>EfjDgbeOz2D0vxDM|m`NWXLf($21z!cU=3>FP9Us zgwg?n6b$1J0;X{IOQ{ND^+*GgoctrPBuLx{7)DySB%y>#SrFLG$vsM25~@8_h4h@I zttfHCa^F6$E0fL{DzV(W&chLKHiD;loc&n1WI~8m#11BiB4LF0GCxMb2XgWX44C%> z>Jfk&-6!1B*PR~3oI*)A&jP{HttypWXH7Lg;?>fvNM1T&IO4#QGAW=OnGU#4DFn15 z(=MUxGK5igFU@Kluet-M3qp0xmeSz#lv$9Dj>Dza=a5h%C|tTt!aeNtLu8H+mFw=| zvhB(diP#T)iE4n9&#sH#xeo|w2OyFY!;B#)LF#>H9e%+jC+wUQ>A}-U5M`4(f@hR? zAZk+N^$is`ak&E+nuZ=fN+PW_d9@t{H;^7ZFIB*hpWfFw$Ea^ubn^-8)(L@L-IN+(ikb-*6659; zF#((tEd^;CvgZT#K%0;&hhNx;-|2vR;R-4xacU#R*^a%rw7ygwR&7%8yTc3#O9((c zfjf?8lSt4s(7o5D48toDQZZaMZ@|a!++eogh)MxSglOv;%IhQyk*h;Std5jFM*`#} zxxlxgD=YxQ7sA3ADva=c=Pg|!**n4{KdscypLqvV2J^~gy8Abk_!lkp69vVdO-VsKeFBhOb zP)E)nAt!(XqN?gGDuFlTEP+_Ob`2!A)jPK^c7|{pabRFNSL!I`?3nOM!f#qqA<}wO z05FQx;sr56iV!Mnz8W6)%Hv8{nU@CQD^GaDq6RimzEs}CNdp~IhgV*dy5Vv(Wtp^z zGZS?|v@g#OAzAsWS}Mw4oeBi#!z>hY6$jHh_oE=}=Bktu2Q`Gt*^&^0IAaxr%TU(W z!?%3X8HTOlRpS+isw5AI4u>(53lRP}>dqiPj$N~pZcam0cQuk3I8{if@N!Hg%e|&l zH#S_l!(qa!>ldlhs`m6PxDc@;*5^A<^3b5b=r6tj>lTBuG(`|OL<(`z+bt}(db1+Z z-d%~5k>i}%&?Xd6TzuDs3)Ps2xyXdy+;86_1NoAcEgi-@7W zd{mnuTZ%{sb;*$Q^0YHYNITMwE{J~vwR9jRA@ft^&60rVHD#!h0jISJ907NDbzH~D z^Ds6+n9*`yXB}L^EeP<>4Vo``fXUx9o9s&`G((zZ!J;!%%>GcN1cg?-bYue|L{#0%AHe*Q=Q5~&xIGE@v#9@$u-6;8Jnk_ zkV&Zbzzp=yLmkZBil?I(*};(7Xa!2>r7;z`NDF#oSs6_Nuxnn-yLevfzTBY5%F;$n z+Nj^nccz)i>m^dQO^r^TA!wVIZ8BnH$$b5F zRkyvjRvngZ$(creLDk}oyslKohXu1pJE7&!S?;^8>ZY4&jWG&HOa|RW?L4HL%pbq5 z>PGj1L8;mRR^dlQN!Mx|R`Q3Cr)$U-MvF@m(@e_BzI0{RYFAdOS8ejIRu{&0bz&|nVm5yh1Wq6B24_!t6aC$I0S*B@V~Q{jSQylh%lHcov;?Z`MN`B z%q9UiBkjDeqbowxdKVkBPR$IaGqhC&aDBBBMNmaEVRag{jzl0= zzT5J$oD3+2tQ;MeIk9p;c>StK9z@QG3VIqH_hZ7SuUzccn@L}D7KFg$qHx_yug+8P z-L-&TW4;Bi=mNL~WCRLs$O(Fe>kdWS9m)`h%$AIRBjs8fw@Kj5uz%)5ol)wf2f2P) zq!3<@_Ga!g2(Lfwtuty+8Ej{8tV!j%q*NBJgwU!^mO&zjO)WxfT!;-xkc{uSZ6lq{ zG8(Dlzyy(RZPIn-jc~>(9qw@4HZo(w+tG^Q54h)ejzeLJw|g^?ql^p+=WyR($mDZi zYEN~vCqY*74#1^7O28=+ZVR&U*;}@j3eVRqPLLmqy-{MYvB*Ag9lm8G0v~D*=`{)Th2-0!vBQ6-0Pbd;E4!tsL?!*x!i;R?oY-d**pg1XCQ&u*}`4I;xE2rJp!G0=oV&P=5@Hmk_rvQ6QM z@m|3)J$=&tue-oX^3~$qJ%hQSj*L2u8=dznSkqi?CJdjkEE#FrEqFcv;E)D=hwp#E zgdmI5yYiAr3sNC7H)sJ;gAdRFuo9Es@>UG=ZiE5H;<)f#51ne2vtpz<)^oUmbw{i> zhBv}i>K|aa$RE<{swF`EutO-PV4lD;?1nQM2!Bd>Ba)`iNLTmFT|`EYb$ImyoWrW_fXtZ)@20;<{>C9u&E@-P-#b~a`A^yE6bWrJ4u)&>xQzUTKEX%dZy1$Ob3 z-|($7k{*ON#h5W7UF=)cvB+Y$_6MD;AThvOF9}C<;asf=-zqk?$LHTCCG@sd_wTz{IqAbA}Rp)+OrR?2|C+6(a^~R9h~) z4wMg9j20h~&Bkt{aPho4D=xrw4EBn>tT-c;#o^&gEZk}!pIc)0ev4PT?mXjZJbdAn z1C3i6@?*DF-TaO=t&Raw58glQz<49aQ$3}K#!yf|e&$xV!CTC%>DaToMy2iDa;Q|l zV`m>uq3G#s;*8OTG0mTp{P3-_R3u;z=9<}%Z!xmzVYpF`gSCHcDHi_uq%X(MDu%br zDSXVS1k#9En8K?ld>0GfT4ROB0AxS`FH*Ke%C;Keuue=}U8cOfp?v27Fw+eLDNjvV z1*IB`#?6ol%=A{13LC%QhlzRe)SW7|Tc-?p5+_&>_Vdh_@YZvh1{b?I5t$G!hmjr1 zA}mcci9)3Vy0ze7@ti4!I3%_hzHPIl%b<={-gR2Lcn(6Ov%A_B92j+>Y0@&;>Dibb z0ZFxXqwGpCVhOK>r((P&kqv+`GVTU2AI&5HWLjUzCK4Hc!<2p8z&dy~coJ>9F*ZYR zj*46ao=yghsostz421eSZMRMMHcB5`g!D}m$!D-2)8q+urRXqTgL!av33WBH&{tf- z#Fhnht*^gBq?n)?uztbnH+3{+_x5!vaM*GQF~XhnAiflduw0LX3lo$16}MI0bX9^z zEwMnp4bMU1Jf7(#XHDeQ@0L@!)7jS_?D#pG8XIF|00%Jw!#PTiQWj4dSCwiXGtiOi zMquA$TR@sR^8ep$Ro4X8COC`fw=2N;`6G(h;K2M+m;e|389L}V6*y7uZ}7}~9&wEO z@a?sR8|}-5qu%+oSy|SD1(4n#QrR;gjKCC5zo-`xink?O zL)DE}R{O`1hN_!C(C8lV+e++mglUg{JrK5n*0*wVq|7>BW}vJL#VVBMFEqe>R*w7U z+ILjluy*B1_l)07gyG*>2v?qs2{8x?&6$XYa}&;kZ7lj|w8Gut`{j3BfR1^ZBNFv}+WGd85w77-M~ z#0(HZJl+UL)E-C#^QaC;Nq}=sh8*&8YQSW4n7Cl-Ftu@ln)!Et84^aOWKm{YsqAlD zL>cP;XA(Nc;teo^j7eM#AS@{p$DGiYA??q=GgD$V{45cjK-uZiDi0-5HxX&RU_{|D z2xIu!)QPRVeZkOx`ubIy6|n0C0Zc^+dyq5|!?aV-Cv5~0lk|8oT(!lF3py_=1A<7D zl!Ln5+9-%~^`UiPH2^;F%3SgsSwLde& zqfd1w$*QBJ=G%1=`oHaY8>M$Zt4 zBf)r(`e$@%Mly!6pg1piGG*jA`5l;^ka( zA=UmK6$AkYv-$T}>>V26((8HgZ?+f_Dv-^9_!T6mPgvqxqN`Xj9oL~XfEo1vEZkUY z7EB$s-~s}dF4kHoZ=$c!R;JCefrMo#N$x7~gf(iJ*Ojca|8WIgYV#F_YY|J6#&lxg z2WEhDLJ`yAo!b@8O^Q?{pI7Ee_9M@S^qCCEk{Uf-)0l=)zFluY8ER063|F-9Gk4T1%4&7xlP+8MTjsuY;KQqN)Ryt z6Nqp%D$hz7J{X_w9KwzK_YmHO(PR%^gHQ7;fpp3&{jLjI5z}n@TB;r_tz;xS zQiB+xWc3pO;oS{VF1)*u!1z*JO5aC;?(eqNqIoS%+>F}PBkzQVcOQ$^!>e?dLUfCo zcWbC_FuMk^omC%hw^K~BCW0ZpoaUS#@B*CstNb9*D zw+9;{gxGuPqItTBrK4A8-nOKMC#uzdb^JY5%a^`o6)G+(hWEB&M37!7Q~Rwr`*uy$4L7wWnTIQeI2T7| zrZ*fA(Y6lf&#kGtb#*Hwt@$finP;entt3S1tn5UL(%WaV!mZQ!Rck>*>x=o#YpZU$ zxAl@Mm&N`s?4rPlyg8eHSyS)w_Mj>E^TpT!jyTt}Y_wrj7+euJ->@Q@pX=Yb zGlQ2bh6d5t#4b0ii{|4yftbB6tG_*(ze7f)(fnY;zGwllLq~xkI9#5Ob*NkuRgWn% zn5=B0*l;RZ#x_<~mN^$KgFS47lj#Xy*2-yHJX*kjh}m0yLs|Y{#~y4!*x4^e*47@) z>)O$jhP$)f32jNq3xD+@{e24G^y*gah(RNkZ=(dz^w%Q<(vy7fjGl(yM`netj-d>W ze}yp`A(RNp-!qR^U5g7gf=j|FMz%}PSL^G&tfN-lc1G$*@3`i?jt|*Wt_fx$4=3e5 zT#s&)v-MKoKqP-6a(~J0lk15^+{*pHLBiGm=FU3&0uhGd;Tpi@`urNy5x8;`E_Z`w zG9P5yy+5TDxsx|Kto|ZI#?Y!Ckqa*nBp2^F_3G1-de671(fzhQP<8LS__-*7Rlhco za>|O_-Iu`ksH9B(&;wPs1^Rg@yi`4y?(N^LUD*95X-`*VN7SOUMd*<8e!0aGFWorb z_1=*RKC4}U;sa&J@Giy}rssCti8F5cBB2Mn_4m#QP%^%+y=twT&7|*p;^|kiQw9i$^Xj6s@h+Bpio)6tfdQv zc6!w^O0AWaTCxPl?dziD@>3hpW3-zEmALdR91UElYe(}bhaYX^R_1tRnQR81;B6Wj z(6-k;TbVDmg;N=K_KUk}UxZOHbnCu0)|CTjZGunCF*;NP8(Wa?{c+ch)+T;Hb1>a$ zjeq0T%6tkk7{n{HojFE68*`Nf=)>;f#wHtZ6o0tcnY@ijcDx{euird;37c!2lm4CLNO%x!MGCS>bc+6 za|>bY0!(=^E`ibD9PS&`r~^=jnV~_2YLq?Lu7KAf>X-S8F{vCn&LarmRZtdU2k>y? zFn(oZK#oPf-U8X+9yG52xM3^Z8&8E5{|0vg{}#5UO44x1P>2#D@bLcb%ao~5g#j1X zUOg3RA-*;Ih#(!SiCqwh69+eISKuP0<2K%f?_{}++f;O|i}-^F3nDq)W{O^dbvcd2 z5hpu^))V?nsq%R(Pa%?dE{gHZmI$#k%@?v~5p~hZxO#9*t%w36(S^8#pPN+`MkTRk z5h(|iVy@(V;~^jvBn!RPrtO9VT-l5OrKVHQagmMgHrbqOT@50XQmj+vrxRa7kuAlqxu}`6`+6U8e-Cp z7tMqQ>6#w$HP4LmLH_Q;1w-XM3^PzYjbOfFRt!WISJ1}7^+!v_6}i_Pxih*2n4A%y zYx9fg$W$b&L~Lfh>;Xt*m~$G|n9=6+Z93oTvf}sOH~R0!v9=UAEHO?p9sG1$Q}iJm z2?3Ug{wI|{AYR8yU}5j|^Eu=GbV=Xla+L_^(mjhG0C%tfwGHU_!A(BD%t1XkfilUi zfUZu(E}nTz0)zLnJ;S%RDpFPyMsfyTx zi{GRNd;gpeRp=U*Iv%O_0p>=X3f9ED0kclT^FhjtLD@CqK-zHgumTnr2aeUFseau( z8oy6x*NJp-3enC4(kbj~hFIYmNraSH5#?5FrBnu8vHzr~AV)hULgzXu_OfSiUiN&# zp3f@M^`}bDobNI?GE2yM5*IIjcV{>D8uh{7;6;p}^i4824lEgk0K)e=t*~w4Lt(r~ zsxxr|0E~PBB+(CE)ZYy-I+wO7X=(WNY15WAQc8Q@7U-WqHcUhkAx24?ilo7KByFyg z_VdG<)>d6gdw`?UY&BeHk@9?19K;*aV)0BlJQ5)5qmYy?-hwc|2hN}j zDLE)F`1(Z2;@Uv0NMJip5g_1#dpU7t1O!1kRtAM4Wk86O;pZr$g-8GakxLQ(6(Vtb z;5Kr4Z4JcSYNC!S*Io+Ucy5S@+{7$|0k%kag@``f1gWO)z%HC@XEyyPPw*LmFPH%b zGM&*s@k~8f5_oWy3A=m>_7!?^!h0$G01RF%$+++J@K!i0~_Z_yF5y zM~#RC0Hw$|$|Ie&V=J=hHZ3TRuD217U z@B=w4xPcRCf)F!j3(C$O;WLoCj*CRemJ<->yeb*F;*v?`y%oqd0ofwBf>@(R=738t z2M%QW0S&AS!C^!2z#BtQ27e!5q6=r7VekX7V1!)aJcNUFhM@f?MxYW>B%(Gip$Pn{ z7Y+VK!iWC7k!)LBL}eVLjDypj17!f|^n}hvA|$N!eP{kn@hl=u)HKpGGs&uifeh^ z$G4*WOFIVOD1{;#RDeXJW&FoU2KtX8jzvTh<>o(3G69TcG0`kr2g2x3e!hZ0q)R)7 z?nt0>N(|emMmVhy@dKN%HfKIVx)k@)^9J+%C78Me4Q>4m097DI4anva5OG=#Mx`^W zQ3FI%4BHxwkfg!*1?qn>V=^H0g1&i10XdH94NzMJG0rG|44e&f=Kq(>7@#db9Uz8m z6!DS+2B)_I4mcJGR}v&k&`#I*rj6$oob|R481#rXOy?rar#3Qs5lLTybg`F#3dCS& zQPrLRyb&%uLMIi|A%c*5T_VWC4O2$IF+=od1){B&N3;*NA~r%?Ee00^fT`g1kvYj^ zE084?N45cWAW||XgKipYE4{Lc;kxM$+APV2BwG*k@4DS3HQJm+j1Z?+1t@mj%$l2q za&N};`d}Ac-^57*2?Sj+J?K}CEpAX)Wd@Aq$>2udKVcs)l z%lX$SR-kp@8SYt)758MqF+c*BP8qx_E8umL87x~70Q4eVtk*f54V#UL&J#q@p;Z)% z7vXA88Q`M3S6B-OXtQz%R?8$b3>=96#7{dlxKPU(9El@9q)S-lUwn-irLP0$0$=aL zH)+19g%VkE+z7gw{eK~1>83LR^dd$F!e=ky#Q-`RfYi$1!Dyq-$C&Z032+0|*NBRG zNxe~qkLi{HYFHFdnVw@WTHTu~>cTcigxJ*0MQLf$%78OH0R6i*ExJAgZuj9jhjHTs zh=PlZf#XHgVN0AUokdjy#J-+NO+x)L72y>G5ibCU5n|FoEgDTt^r!kK2g0qqT#wy4 z+`;gxHoNV&DscypKicu24FCS~2{3@+9rw#~5~OR~9a5#Ix#b^BR@Dao`K*?rd-9tc zAv0;HHGM;wOv2vFQ4b?c;5FS_#;Fq<*pXsCl_L9-CUgphXLeyICDSb&Qbo&QeKCNO z#_?8iT&j}&aJ3OM7a<7#nddTb{4FEXX}obaV>&{}!+W28D3XqQrgPV>7Zn(FJ2PW& z0wVis7pdg81)~BejSz~%W_R}VaUJF1Lqe=4u2jx8#c?yw$594lle(58BUlg=K71H( zc}|a~Ca2=`o7V6WB6rr=DQ2>#aOpPBomiMy83=SeSuC#Y)o*kg0rDEaZ4otyG^hs0 zTu>a=OaY`j?)e27*>{oDVXbssvhg`eY=cNn#7cd0E@pm8Rpfwk?uL2(R4Nck6?%s2 zioYZYtmrG9RlqznUnY1;M9Dsdjs!S@Sqs4hL%OXPc90-^8LhMGhF|HR>EngPM>9;5 z_aybDP~F=lD;yo?6%L(4+p{`X#NC}VP=2w4&C-7lVHF!h{$MATY1z#(-wyQ;J8+N5 zXY3D(q8JmE@2F86EFZfkkrSX$@O zwF%enKLV#k$$HmaZ)L8+-n`y{o=o}gs#js{Y+mB&z-n0# z2-dVW0tKLqhUUIUL$SznN)1o$NA#XB#3*O<86o?B(u5O|5bmheINrTXP0L#BlG!Z~ z31DGoF0#F}*|C}*@4~58PQTg(=&nZnK9FuV5j`cr%xPRFK|>qFI|6-e_HZtCRjvLY z;kYuKQS-v0fX?d1-p3He?Kpt*`V*iliO+$gv6&ZVDGOFx1W&C}yFv>b-dT0)I~{#E z`v7~r26wyST#4^W__C*VT5HvvBoE#G;ZICfUbK+5gj}3*&NR8K(>> z$Mgs;C`fj+Ou+o+L4O13RoP(Y13CwFE$kG!P6EDcpTijER&-Te-9PnJxYUkw8}{LX zp#OC{E)eqC0IqRdFo4%)bol&j zxX$A`i0d#eXyn&nMUNG54d>f;;

    Wn{efd1%4FgGx%j=`wU;R{VWRY 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 delta 35425 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�{HO7HmRoYHbmeNI9tIR&wxda+t3?5tO7i`H|ANKz}P@@ZbOU@ z;o{p=oH%(KO5^JN?T|lB!P~*Ihhn$GWVv72r~(m6-40Fo$@LwCaV!dd2e~0Tw}TSj zfmM_==t9JPzQZ;czeBW^e9|C$A*#OvtqrkIcyw#$BR~u^Y$1(8P^vGEwtEPF-a&c? zPQg2H3P(Ylg5KkhyO-Pq;G`fS4_jRRW)6|?gOx>SZkk-}@I=j&Zbzvw<=atvO4eNFZi0neyDTQJ{O6`3L9MzNW8Ejf*4xvZxgmZMr_@0j3O_c2W!hE_I z!V8=Mc24%w-!AS>FGAe$e*%u<%d>6uM ze7Jy*V(nXtzo?SG3!UCZ#@+nQI{x!C_D#yK>v+vvA>N6%_SD9R684H%ZnH(M>sWKLoRNF&2-W zKz3sGdI-jalTXfVR+)D0T8wz)suz3v3O$9d^gjeY*QKeo+E(d~#;jvJjF@t7Nwyx! z$PRM0rzE?b({fTuaCW35J5|i?eHbQ@BI8GpOjp@&{)qhu_N%KZMe8aCqR+0H+)bVz zgPCl7!Ma=4T!1@|UuTRuIXf~ftImGKQt*72f~!&zTK(81ehf`Jm|IQNgtqu2qOpN# z_|egRb*%{LAS3zu(6-GZM&P=kHtI~GyyS(K4IogLKnV(}==uSqfV?W1?8X)WEVtYSq6cK&ud`yJl-|+XN@EOFb zOeZbs6am&nvJ*2l1~LCJl?gY)x6J8+uMU&31Ae=u3s*0k>d#KR+yy`Aj^7IOuwTGg z;}qf-(u0N{hb%EYOGLoo)?bJQ^@)pOle4XI>=ZIagu1y{0zD!Y9j_N**>ISfSim&4 zY)MONi~Y5*?3Gv_DE6_(q558m-i^8F`Nts&EaP#pxH>8ef&m5bfow>{e24y{y@<{| z0r4VaJSoUtoas0?FGY=Kpq$qG&~JO66hDLop}NskIIA}vLdfIl2(!VXduW!6(oaE- zq%z0CQ*fExG!C zTJVy!6Aaz)l$@D7DGUlsQ2Yt&YzsoM3Y|`&%W;(WG}a{s-ogjKMDa8RZH${TiVk~5 z{Ho-mFWFWfSY$Q$xJkO$Lg96XO!Ta!nKBk`p1)hW4xO2$>mh>DJ zyS@P>v-8`@^Gmo<*FbcOo6`k38a~Bb-?|Y?oLhe>o-SR+ADr-coVEE_;c`U74e&yZ zQ%Q2Z00AAmjvaMGc8ejav7QT3;swmoa$EqV`p$YDD}fi}ZL3hXEF1+;+Yi`Xw-OQC z#AG*WFsQp5&5Xof6tzB;SKPqZORmbGDsy;FL4CQ}`nF4@?Q0l^Q=wASoTRVwaUMT~ z>`fgC-l*ix-jLVnZJSSo)4Cz3uAANzCdaSfA3Zu3&iGe2g3*?2Uf%{#uOH_noshIm2t4_zmBZ!1+yxLjPLKly?NPH%o;TvN!uxO*aRW!@dc# zG2eT=&7k0K;BVS=Hg?#*f$`z6_&3r8@*&dE*_&0X`p+Srm&Bf`o8g`mL0Xm{K=88o ztm>9L-y>qvGUl3NY3nZB{?WWJ!RGG5Yq_~y=r~t7ndWGdrPJua3JSd@#$)3jBU!kS0HJ-Auhtn{ZZ;FY~%SB|ID9t6JvTnvvM4xef^l?g@``mrI$8)!{5N&*S$xbMKjYb>N6acG=uGs8ja893>Y{w;2mI25)YI{aJd$CAGl8|xASaWXe*m8%m<#F%H``EB+UYsbieGgY!u#Y|-pGfF=4_?kt z_}ce@*QUJ?ziB&D5MwJS_dW)}Tki}0vvT;&cZ4MB++H!F>Rt%b3!G2k9`BW8X-1_L z>ZA{VLeT32pb$~}GrWH616-{4mvvkcB*lGPpGxzL?kS`8{Q+oK8M=+p&1L8`qmyN5 z=O4vX@ld`DANnK6eP!qlMz@urbBs=xp}l_s+F6EP8+89K%2L>by~0O;N_bb!&GGITqmBV}ld(Wx@DJBL}r zq0If79K3ZqC33JMi^1{q_Z&>iO~!{ng%xVmhd|-_52Ns20#m)kC|tB+6qX$yAznQ1 zFBlpZ~P0gUHp3*-}7VC-x-x8<0H)EKf;|g#;y7YI3Gnn0$H0vy~QY4`9~1a zNuH09gQ(}n%=2U9bWnm(IfeQ=qr7DN6{x5}t@>AxZzH&FH22Lr5^ zLN*zS{|!SH%bvf<0v7)GE*5c*IVtit%;$be{0-|61V@>wopOJ}mH}fOf5npKd?L2- z=J^v8OfztkFOMolaC|LaVEkCPlOrI&zhz+t!uATzkxUS7obFd zz9;?X^xsvVn!{lWs-zq({~DMBBE_0rLG5+kj@BVpq_slO5EHTv%X3E56Zo!lz;cOhUZNcKd1;>Z~p4?&Vq2W z*;e9r0p}waw|vj-jtNKOuR~lHJo>uei0gtQuM5^(7p(nx(D|d8l!!R0I}h_YPc!}x DbIPB( diff --git a/roms/openbios b/roms/openbios index b9062deaae..04dfc984ac 160000 --- a/roms/openbios +++ b/roms/openbios @@ -1 +1 @@ -Subproject commit b9062deaaea7269369eaa46260d75edcaf276afa +Subproject commit 04dfc984ac0ad70e2d1f58d1121e3b7670901124 From 2df59b73e0864f021f6179f32f7ed364f6d4f38d Mon Sep 17 00:00:00 2001 From: Nico Boehr Date: Thu, 16 Dec 2021 14:16:57 +0100 Subject: [PATCH 510/730] s390x/css: fix PMCW invalid mask Previously, we required bits 5, 6 and 7 to be zero (0x07 == 0b111). But, as per the principles of operation, bit 5 is ignored in MSCH and bits 0, 1, 6 and 7 need to be zero. As both PMCW_FLAGS_MASK_INVALID and ioinst_schib_valid() are only used by ioinst_handle_msch(), adjust the mask accordingly. Fixes: db1c8f53bfb1 ("s390: Channel I/O basic definitions.") Signed-off-by: Nico Boehr Reviewed-by: Pierre Morel Reviewed-by: Halil Pasic Reviewed-by: Janosch Frank Reviewed-by: Cornelia Huck Message-Id: <20211216131657.1057978-1-nrb@linux.ibm.com> Signed-off-by: Thomas Huth --- include/hw/s390x/ioinst.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hw/s390x/ioinst.h b/include/hw/s390x/ioinst.h index 3771fff9d4..ea8d0f2444 100644 --- a/include/hw/s390x/ioinst.h +++ b/include/hw/s390x/ioinst.h @@ -107,7 +107,7 @@ QEMU_BUILD_BUG_MSG(sizeof(PMCW) != 28, "size of PMCW is wrong"); #define PMCW_FLAGS_MASK_MP 0x0004 #define PMCW_FLAGS_MASK_TF 0x0002 #define PMCW_FLAGS_MASK_DNV 0x0001 -#define PMCW_FLAGS_MASK_INVALID 0x0700 +#define PMCW_FLAGS_MASK_INVALID 0xc300 #define PMCW_CHARS_MASK_ST 0x00e00000 #define PMCW_CHARS_MASK_MBFC 0x00000004 From 521130f267240cb1ed8fd4635496493a153281db Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 12 Jan 2022 17:50:12 +0100 Subject: [PATCH 511/730] target/s390x: Fix SLDA sign bit index SLDA operates on 64-bit values, so its sign bit index should be 63, not 31. Fixes: a79ba3398a0a ("target-s390: Convert SHIFT DOUBLE") Reported-by: David Hildenbrand Signed-off-by: Ilya Leoshkevich Reviewed-by: David Hildenbrand Message-Id: <20220112165016.226996-2-iii@linux.ibm.com> Signed-off-by: Thomas Huth --- target/s390x/tcg/insn-data.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/s390x/tcg/insn-data.def b/target/s390x/tcg/insn-data.def index f0af458aee..90c753068c 100644 --- a/target/s390x/tcg/insn-data.def +++ b/target/s390x/tcg/insn-data.def @@ -800,7 +800,7 @@ C(0xebde, SRLK, RSY_a, DO, r3_32u, sh32, new, r1_32, srl, 0) C(0xeb0c, SRLG, RSY_a, Z, r3_o, sh64, r1, 0, srl, 0) /* SHIFT LEFT DOUBLE */ - D(0x8f00, SLDA, RS_a, Z, r1_D32, sh64, new, r1_D32, sla, 0, 31) + D(0x8f00, SLDA, RS_a, Z, r1_D32, sh64, new, r1_D32, sla, 0, 63) /* SHIFT LEFT DOUBLE LOGICAL */ C(0x8d00, SLDL, RS_a, Z, r1_D32, sh64, new, r1_D32, sll, 0) /* SHIFT RIGHT DOUBLE */ From 57556b28afde4b039bb12bfc274bd8df9022d946 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 12 Jan 2022 17:50:13 +0100 Subject: [PATCH 512/730] target/s390x: Fix SRDA CC calculation SRDA uses r1_D32 for binding the first operand and s64 for setting CC. cout_s64() relies on o->out being the shift result, however, wout_r1_D32() clobbers it. Fix by using a temporary. Fixes: a79ba3398a0a ("target-s390: Convert SHIFT DOUBLE") Signed-off-by: Ilya Leoshkevich Reviewed-by: David Hildenbrand Message-Id: <20220112165016.226996-3-iii@linux.ibm.com> Signed-off-by: Thomas Huth --- target/s390x/tcg/translate.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index f180853e7a..766b4c87b2 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -5420,9 +5420,11 @@ static void wout_r1_P32(DisasContext *s, DisasOps *o) static void wout_r1_D32(DisasContext *s, DisasOps *o) { int r1 = get_field(s, r1); + TCGv_i64 t = tcg_temp_new_i64(); store_reg32_i64(r1 + 1, o->out); - tcg_gen_shri_i64(o->out, o->out, 32); - store_reg32_i64(r1, o->out); + tcg_gen_shri_i64(t, o->out, 32); + store_reg32_i64(r1, t); + tcg_temp_free_i64(t); } #define SPEC_wout_r1_D32 SPEC_r1_even From df103c09bc2f549d36ba6313a69c18fc003ef1ee Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 12 Jan 2022 17:50:14 +0100 Subject: [PATCH 513/730] target/s390x: Fix cc_calc_sla_64() missing overflows An overflow occurs for SLAG when at least one shifted bit is not equal to sign bit. Therefore, we need to check that `shift + 1` bits are neither all 0s nor all 1s. The current code checks only `shift` bits, missing some overflows. Fixes: cbe24bfa91d2 ("target-s390: Convert SHIFT, ROTATE SINGLE") Co-developed-by: David Hildenbrand Signed-off-by: Ilya Leoshkevich Reviewed-by: David Hildenbrand Message-Id: <20220112165016.226996-4-iii@linux.ibm.com> Signed-off-by: Thomas Huth --- target/s390x/tcg/cc_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/s390x/tcg/cc_helper.c b/target/s390x/tcg/cc_helper.c index c2c96c3a3c..c9b7b0e8c6 100644 --- a/target/s390x/tcg/cc_helper.c +++ b/target/s390x/tcg/cc_helper.c @@ -297,7 +297,7 @@ static uint32_t cc_calc_sla_32(uint32_t src, int shift) static uint32_t cc_calc_sla_64(uint64_t src, int shift) { - uint64_t mask = ((1ULL << shift) - 1ULL) << (64 - shift); + uint64_t mask = -1ULL << (63 - shift); uint64_t sign = 1ULL << 63; uint64_t match; int64_t r; From 6da170beda33f3e7f1d9242814acd9f428f0f0fb Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 12 Jan 2022 17:50:15 +0100 Subject: [PATCH 514/730] target/s390x: Fix shifting 32-bit values for more than 31 bits According to PoP, both 32- and 64-bit shifts use lowest 6 address bits. The current code special-cases 32-bit shifts to use only 5 bits, which is not correct. For example, shifting by 32 bits currently preserves the initial value, however, it's supposed zero it out instead. Fix by merging sh32 and sh64 and adapting CC calculation to shift values greater than 31. Fixes: cbe24bfa91d2 ("target-s390: Convert SHIFT, ROTATE SINGLE") Signed-off-by: Ilya Leoshkevich Reviewed-by: David Hildenbrand Message-Id: <20220112165016.226996-5-iii@linux.ibm.com> Signed-off-by: Thomas Huth --- target/s390x/cpu-dump.c | 3 +-- target/s390x/s390x-internal.h | 3 +-- target/s390x/tcg/cc_helper.c | 36 +++----------------------- target/s390x/tcg/insn-data.def | 36 +++++++++++++------------- target/s390x/tcg/translate.c | 47 ++++++++++++++++------------------ 5 files changed, 45 insertions(+), 80 deletions(-) diff --git a/target/s390x/cpu-dump.c b/target/s390x/cpu-dump.c index 0f5c062994..ffa9e94d84 100644 --- a/target/s390x/cpu-dump.c +++ b/target/s390x/cpu-dump.c @@ -121,8 +121,7 @@ const char *cc_name(enum cc_op cc_op) [CC_OP_NZ_F64] = "CC_OP_NZ_F64", [CC_OP_NZ_F128] = "CC_OP_NZ_F128", [CC_OP_ICM] = "CC_OP_ICM", - [CC_OP_SLA_32] = "CC_OP_SLA_32", - [CC_OP_SLA_64] = "CC_OP_SLA_64", + [CC_OP_SLA] = "CC_OP_SLA", [CC_OP_FLOGR] = "CC_OP_FLOGR", [CC_OP_LCBB] = "CC_OP_LCBB", [CC_OP_VC] = "CC_OP_VC", diff --git a/target/s390x/s390x-internal.h b/target/s390x/s390x-internal.h index 1a178aed41..6fc8cad2d5 100644 --- a/target/s390x/s390x-internal.h +++ b/target/s390x/s390x-internal.h @@ -193,8 +193,7 @@ enum cc_op { CC_OP_NZ_F128, /* FP dst != 0 (128bit) */ CC_OP_ICM, /* insert characters under mask */ - CC_OP_SLA_32, /* Calculate shift left signed (32bit) */ - CC_OP_SLA_64, /* Calculate shift left signed (64bit) */ + CC_OP_SLA, /* Calculate shift left signed */ CC_OP_FLOGR, /* find leftmost one */ CC_OP_LCBB, /* load count to block boundary */ CC_OP_VC, /* vector compare result */ diff --git a/target/s390x/tcg/cc_helper.c b/target/s390x/tcg/cc_helper.c index c9b7b0e8c6..8d04097f78 100644 --- a/target/s390x/tcg/cc_helper.c +++ b/target/s390x/tcg/cc_helper.c @@ -268,34 +268,7 @@ static uint32_t cc_calc_icm(uint64_t mask, uint64_t val) } } -static uint32_t cc_calc_sla_32(uint32_t src, int shift) -{ - uint32_t mask = ((1U << shift) - 1U) << (32 - shift); - uint32_t sign = 1U << 31; - uint32_t match; - int32_t r; - - /* Check if the sign bit stays the same. */ - if (src & sign) { - match = mask; - } else { - match = 0; - } - if ((src & mask) != match) { - /* Overflow. */ - return 3; - } - - r = ((src << shift) & ~sign) | (src & sign); - if (r == 0) { - return 0; - } else if (r < 0) { - return 1; - } - return 2; -} - -static uint32_t cc_calc_sla_64(uint64_t src, int shift) +static uint32_t cc_calc_sla(uint64_t src, int shift) { uint64_t mask = -1ULL << (63 - shift); uint64_t sign = 1ULL << 63; @@ -459,11 +432,8 @@ static uint32_t do_calc_cc(CPUS390XState *env, uint32_t cc_op, case CC_OP_ICM: r = cc_calc_icm(src, dst); break; - case CC_OP_SLA_32: - r = cc_calc_sla_32(src, dst); - break; - case CC_OP_SLA_64: - r = cc_calc_sla_64(src, dst); + case CC_OP_SLA: + r = cc_calc_sla(src, dst); break; case CC_OP_FLOGR: r = cc_calc_flogr(dst); diff --git a/target/s390x/tcg/insn-data.def b/target/s390x/tcg/insn-data.def index 90c753068c..1c3e115712 100644 --- a/target/s390x/tcg/insn-data.def +++ b/target/s390x/tcg/insn-data.def @@ -747,8 +747,8 @@ C(0xb9e1, POPCNT, RRE, PC, 0, r2_o, r1, 0, popcnt, nz64) /* ROTATE LEFT SINGLE LOGICAL */ - C(0xeb1d, RLL, RSY_a, Z, r3_o, sh32, new, r1_32, rll32, 0) - C(0xeb1c, RLLG, RSY_a, Z, r3_o, sh64, r1, 0, rll64, 0) + C(0xeb1d, RLL, RSY_a, Z, r3_o, sh, new, r1_32, rll32, 0) + C(0xeb1c, RLLG, RSY_a, Z, r3_o, sh, r1, 0, rll64, 0) /* ROTATE THEN INSERT SELECTED BITS */ C(0xec55, RISBG, RIE_f, GIE, 0, r2, r1, 0, risbg, s64) @@ -784,29 +784,29 @@ C(0x0400, SPM, RR_a, Z, r1, 0, 0, 0, spm, 0) /* SHIFT LEFT SINGLE */ - D(0x8b00, SLA, RS_a, Z, r1, sh32, new, r1_32, sla, 0, 31) - D(0xebdd, SLAK, RSY_a, DO, r3, sh32, new, r1_32, sla, 0, 31) - D(0xeb0b, SLAG, RSY_a, Z, r3, sh64, r1, 0, sla, 0, 63) + D(0x8b00, SLA, RS_a, Z, r1, sh, new, r1_32, sla, 0, 31) + D(0xebdd, SLAK, RSY_a, DO, r3, sh, new, r1_32, sla, 0, 31) + D(0xeb0b, SLAG, RSY_a, Z, r3, sh, r1, 0, sla, 0, 63) /* SHIFT LEFT SINGLE LOGICAL */ - C(0x8900, SLL, RS_a, Z, r1_o, sh32, new, r1_32, sll, 0) - C(0xebdf, SLLK, RSY_a, DO, r3_o, sh32, new, r1_32, sll, 0) - C(0xeb0d, SLLG, RSY_a, Z, r3_o, sh64, r1, 0, sll, 0) + C(0x8900, SLL, RS_a, Z, r1_o, sh, new, r1_32, sll, 0) + C(0xebdf, SLLK, RSY_a, DO, r3_o, sh, new, r1_32, sll, 0) + C(0xeb0d, SLLG, RSY_a, Z, r3_o, sh, r1, 0, sll, 0) /* SHIFT RIGHT SINGLE */ - C(0x8a00, SRA, RS_a, Z, r1_32s, sh32, new, r1_32, sra, s32) - C(0xebdc, SRAK, RSY_a, DO, r3_32s, sh32, new, r1_32, sra, s32) - C(0xeb0a, SRAG, RSY_a, Z, r3_o, sh64, r1, 0, sra, s64) + C(0x8a00, SRA, RS_a, Z, r1_32s, sh, new, r1_32, sra, s32) + C(0xebdc, SRAK, RSY_a, DO, r3_32s, sh, new, r1_32, sra, s32) + C(0xeb0a, SRAG, RSY_a, Z, r3_o, sh, r1, 0, sra, s64) /* SHIFT RIGHT SINGLE LOGICAL */ - C(0x8800, SRL, RS_a, Z, r1_32u, sh32, new, r1_32, srl, 0) - C(0xebde, SRLK, RSY_a, DO, r3_32u, sh32, new, r1_32, srl, 0) - C(0xeb0c, SRLG, RSY_a, Z, r3_o, sh64, r1, 0, srl, 0) + C(0x8800, SRL, RS_a, Z, r1_32u, sh, new, r1_32, srl, 0) + C(0xebde, SRLK, RSY_a, DO, r3_32u, sh, new, r1_32, srl, 0) + C(0xeb0c, SRLG, RSY_a, Z, r3_o, sh, r1, 0, srl, 0) /* SHIFT LEFT DOUBLE */ - D(0x8f00, SLDA, RS_a, Z, r1_D32, sh64, new, r1_D32, sla, 0, 63) + D(0x8f00, SLDA, RS_a, Z, r1_D32, sh, new, r1_D32, sla, 0, 63) /* SHIFT LEFT DOUBLE LOGICAL */ - C(0x8d00, SLDL, RS_a, Z, r1_D32, sh64, new, r1_D32, sll, 0) + C(0x8d00, SLDL, RS_a, Z, r1_D32, sh, new, r1_D32, sll, 0) /* SHIFT RIGHT DOUBLE */ - C(0x8e00, SRDA, RS_a, Z, r1_D32, sh64, new, r1_D32, sra, s64) + C(0x8e00, SRDA, RS_a, Z, r1_D32, sh, new, r1_D32, sra, s64) /* SHIFT RIGHT DOUBLE LOGICAL */ - C(0x8c00, SRDL, RS_a, Z, r1_D32, sh64, new, r1_D32, srl, 0) + C(0x8c00, SRDL, RS_a, Z, r1_D32, sh, new, r1_D32, srl, 0) /* SQUARE ROOT */ F(0xb314, SQEBR, RRE, Z, 0, e2, new, e1, sqeb, 0, IF_BFP) diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index 766b4c87b2..46dea73357 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -636,8 +636,7 @@ static void gen_op_calc_cc(DisasContext *s) case CC_OP_LTUGTU_64: case CC_OP_TM_32: case CC_OP_TM_64: - case CC_OP_SLA_32: - case CC_OP_SLA_64: + case CC_OP_SLA: case CC_OP_SUBU: case CC_OP_NZ_F128: case CC_OP_VC: @@ -1178,19 +1177,6 @@ struct DisasInsn { /* ====================================================================== */ /* Miscellaneous helpers, used by several operations. */ -static void help_l2_shift(DisasContext *s, DisasOps *o, int mask) -{ - int b2 = get_field(s, b2); - int d2 = get_field(s, d2); - - if (b2 == 0) { - o->in2 = tcg_const_i64(d2 & mask); - } else { - o->in2 = get_address(s, 0, b2, d2); - tcg_gen_andi_i64(o->in2, o->in2, mask); - } -} - static DisasJumpType help_goto_direct(DisasContext *s, uint64_t dest) { if (dest == s->pc_tmp) { @@ -4113,9 +4099,18 @@ static DisasJumpType op_soc(DisasContext *s, DisasOps *o) static DisasJumpType op_sla(DisasContext *s, DisasOps *o) { + TCGv_i64 t; uint64_t sign = 1ull << s->insn->data; - enum cc_op cco = s->insn->data == 31 ? CC_OP_SLA_32 : CC_OP_SLA_64; - gen_op_update2_cc_i64(s, cco, o->in1, o->in2); + if (s->insn->data == 31) { + t = tcg_temp_new_i64(); + tcg_gen_shli_i64(t, o->in1, 32); + } else { + t = o->in1; + } + gen_op_update2_cc_i64(s, CC_OP_SLA, t, o->in2); + if (s->insn->data == 31) { + tcg_temp_free_i64(t); + } tcg_gen_shl_i64(o->out, o->in1, o->in2); /* The arithmetic left shift is curious in that it does not affect the sign bit. Copy that over from the source unchanged. */ @@ -5924,17 +5919,19 @@ static void in2_ri2(DisasContext *s, DisasOps *o) } #define SPEC_in2_ri2 0 -static void in2_sh32(DisasContext *s, DisasOps *o) +static void in2_sh(DisasContext *s, DisasOps *o) { - help_l2_shift(s, o, 31); -} -#define SPEC_in2_sh32 0 + int b2 = get_field(s, b2); + int d2 = get_field(s, d2); -static void in2_sh64(DisasContext *s, DisasOps *o) -{ - help_l2_shift(s, o, 63); + if (b2 == 0) { + o->in2 = tcg_const_i64(d2 & 0x3f); + } else { + o->in2 = get_address(s, 0, b2, d2); + tcg_gen_andi_i64(o->in2, o->in2, 0x3f); + } } -#define SPEC_in2_sh64 0 +#define SPEC_in2_sh 0 static void in2_m2_8u(DisasContext *s, DisasOps *o) { From f7cff0738d1bc66b530a6c200874eb86575048f4 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 12 Jan 2022 17:50:16 +0100 Subject: [PATCH 515/730] tests/tcg/s390x: Test shift instructions Add a test for each shift instruction in order to to prevent regressions. Signed-off-by: Ilya Leoshkevich Acked-by: David Hildenbrand Message-Id: <20220112165016.226996-6-iii@linux.ibm.com> Signed-off-by: Thomas Huth --- tests/tcg/s390x/Makefile.target | 1 + tests/tcg/s390x/shift.c | 270 ++++++++++++++++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 tests/tcg/s390x/shift.c diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index cc64dd32d2..1a7238b4eb 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -9,6 +9,7 @@ TESTS+=exrl-trtr TESTS+=pack TESTS+=mvo TESTS+=mvc +TESTS+=shift TESTS+=trap TESTS+=signals-s390x diff --git a/tests/tcg/s390x/shift.c b/tests/tcg/s390x/shift.c new file mode 100644 index 0000000000..29594fec5c --- /dev/null +++ b/tests/tcg/s390x/shift.c @@ -0,0 +1,270 @@ +#include +#include +#include + +#define DEFINE_SHIFT_SINGLE_COMMON(_name, _insn_str) \ + static uint64_t _name(uint64_t op1, uint64_t op2, uint64_t *cc) \ + { \ + asm(" sll %[cc],28\n" \ + " spm %[cc]\n" \ + " " _insn_str "\n" \ + " ipm %[cc]\n" \ + " srl %[cc],28" \ + : [op1] "+&r" (op1), \ + [cc] "+&r" (*cc) \ + : [op2] "r" (op2) \ + : "cc"); \ + return op1; \ + } +#define DEFINE_SHIFT_SINGLE_2(_insn, _offset) \ + DEFINE_SHIFT_SINGLE_COMMON(_insn ## _ ## _offset, \ + #_insn " %[op1]," #_offset "(%[op2])") +#define DEFINE_SHIFT_SINGLE_3(_insn, _offset) \ + DEFINE_SHIFT_SINGLE_COMMON(_insn ## _ ## _offset, \ + #_insn " %[op1],%[op1]," #_offset "(%[op2])") +#define DEFINE_SHIFT_DOUBLE(_insn, _offset) \ + static uint64_t _insn ## _ ## _offset(uint64_t op1, uint64_t op2, \ + uint64_t *cc) \ + { \ + uint32_t op1h = op1 >> 32; \ + uint32_t op1l = op1 & 0xffffffff; \ + register uint32_t r2 asm("2") = op1h; \ + register uint32_t r3 asm("3") = op1l; \ + \ + asm(" sll %[cc],28\n" \ + " spm %[cc]\n" \ + " " #_insn " %[r2]," #_offset "(%[op2])\n" \ + " ipm %[cc]\n" \ + " srl %[cc],28" \ + : [r2] "+&r" (r2), \ + [r3] "+&r" (r3), \ + [cc] "+&r" (*cc) \ + : [op2] "r" (op2) \ + : "cc"); \ + op1h = r2; \ + op1l = r3; \ + return (((uint64_t)op1h) << 32) | op1l; \ + } + +DEFINE_SHIFT_SINGLE_3(rll, 0x4cf3b); +DEFINE_SHIFT_SINGLE_3(rllg, 0x697c9); +DEFINE_SHIFT_SINGLE_2(sla, 0x4b0); +DEFINE_SHIFT_SINGLE_2(sla, 0xd54); +DEFINE_SHIFT_SINGLE_3(slak, 0x2832c); +DEFINE_SHIFT_SINGLE_3(slag, 0x66cc4); +DEFINE_SHIFT_SINGLE_3(slag, 0xd54); +DEFINE_SHIFT_SINGLE_2(sll, 0xd04); +DEFINE_SHIFT_SINGLE_3(sllk, 0x2699f); +DEFINE_SHIFT_SINGLE_3(sllg, 0x59df9); +DEFINE_SHIFT_SINGLE_2(sra, 0x67e); +DEFINE_SHIFT_SINGLE_3(srak, 0x60943); +DEFINE_SHIFT_SINGLE_3(srag, 0x6b048); +DEFINE_SHIFT_SINGLE_2(srl, 0x035); +DEFINE_SHIFT_SINGLE_3(srlk, 0x43dfc); +DEFINE_SHIFT_SINGLE_3(srlg, 0x27227); +DEFINE_SHIFT_DOUBLE(slda, 0x38b); +DEFINE_SHIFT_DOUBLE(sldl, 0x031); +DEFINE_SHIFT_DOUBLE(srda, 0x36f); +DEFINE_SHIFT_DOUBLE(srdl, 0x99a); + +struct shift_test { + const char *name; + uint64_t (*insn)(uint64_t, uint64_t, uint64_t *); + uint64_t op1; + uint64_t op2; + uint64_t exp_result; + uint64_t exp_cc; +}; + +static const struct shift_test tests[] = { + { + .name = "rll", + .insn = rll_0x4cf3b, + .op1 = 0xecbd589a45c248f5ull, + .op2 = 0x62e5508ccb4c99fdull, + .exp_result = 0xecbd589af545c248ull, + .exp_cc = 0, + }, + { + .name = "rllg", + .insn = rllg_0x697c9, + .op1 = 0xaa2d54c1b729f7f4ull, + .op2 = 0x5ffcf7465f5cd71full, + .exp_result = 0x29f7f4aa2d54c1b7ull, + .exp_cc = 0, + }, + { + .name = "sla-1", + .insn = sla_0x4b0, + .op1 = 0x8bf21fb67cca0e96ull, + .op2 = 0x3ddf2f53347d3030ull, + .exp_result = 0x8bf21fb600000000ull, + .exp_cc = 3, + }, + { + .name = "sla-2", + .insn = sla_0xd54, + .op1 = 0xe4faaed5def0e926ull, + .op2 = 0x18d586fab239cbeeull, + .exp_result = 0xe4faaed5fbc3a498ull, + .exp_cc = 3, + }, + { + .name = "slak", + .insn = slak_0x2832c, + .op1 = 0x7300bf78707f09f9ull, + .op2 = 0x4d193b85bb5cb39bull, + .exp_result = 0x7300bf783f84fc80ull, + .exp_cc = 3, + }, + { + .name = "slag-1", + .insn = slag_0x66cc4, + .op1 = 0xe805966de1a77762ull, + .op2 = 0x0e92953f6aa91c6bull, + .exp_result = 0xbbb1000000000000ull, + .exp_cc = 3, + }, + { + .name = "slag-2", + .insn = slag_0xd54, + .op1 = 0xdef0e92600000000ull, + .op2 = 0x18d586fab239cbeeull, + .exp_result = 0xfbc3a49800000000ull, + .exp_cc = 3, + }, + { + .name = "sll", + .insn = sll_0xd04, + .op1 = 0xb90281a3105939dfull, + .op2 = 0xb5e4df7e082e4c5eull, + .exp_result = 0xb90281a300000000ull, + .exp_cc = 0, + }, + { + .name = "sllk", + .insn = sllk_0x2699f, + .op1 = 0x777c6cf116f99557ull, + .op2 = 0xe0556cf112e5a458ull, + .exp_result = 0x777c6cf100000000ull, + .exp_cc = 0, + }, + { + .name = "sllg", + .insn = sllg_0x59df9, + .op1 = 0xcdf86cbfbc0f3557ull, + .op2 = 0x325a45acf99c6d3dull, + .exp_result = 0x55c0000000000000ull, + .exp_cc = 0, + }, + { + .name = "sra", + .insn = sra_0x67e, + .op1 = 0xb878f048d5354183ull, + .op2 = 0x9e27d13195931f79ull, + .exp_result = 0xb878f048ffffffffull, + .exp_cc = 1, + }, + { + .name = "srak", + .insn = srak_0x60943, + .op1 = 0xb6ceb5a429cedb35ull, + .op2 = 0x352354900ae34d7aull, + .exp_result = 0xb6ceb5a400000000ull, + .exp_cc = 0, + }, + { + .name = "srag", + .insn = srag_0x6b048, + .op1 = 0xd54dd4468676c63bull, + .op2 = 0x84d026db7b4dca28ull, + .exp_result = 0xffffffffffffd54dull, + .exp_cc = 1, + }, + { + .name = "srl", + .insn = srl_0x035, + .op1 = 0x09be503ef826815full, + .op2 = 0xbba8d1a0e542d5c1ull, + .exp_result = 0x9be503e00000000ull, + .exp_cc = 0, + }, + { + .name = "srlk", + .insn = srlk_0x43dfc, + .op1 = 0x540d6c8de71aee2aull, + .op2 = 0x0000000000000000ull, + .exp_result = 0x540d6c8d00000000ull, + .exp_cc = 0, + }, + { + .name = "srlg", + .insn = srlg_0x27227, + .op1 = 0x26f7123c1c447a34ull, + .op2 = 0x0000000000000000ull, + .exp_result = 0x00000000004dee24ull, + .exp_cc = 0, + }, + { + .name = "slda", + .insn = slda_0x38b, + .op1 = 0x7988f722dd5bbe7cull, + .op2 = 0x9aed3f95b4d78cc2ull, + .exp_result = 0x1ee45bab77cf8000ull, + .exp_cc = 3, + }, + { + .name = "sldl", + .insn = sldl_0x031, + .op1 = 0xaae2918dce2b049aull, + .op2 = 0x0000000000000000ull, + .exp_result = 0x0934000000000000ull, + .exp_cc = 0, + }, + { + .name = "srda", + .insn = srda_0x36f, + .op1 = 0x0cd4ed9228a50978ull, + .op2 = 0x72b046f0848b8cc9ull, + .exp_result = 0x000000000000000cull, + .exp_cc = 2, + }, + { + .name = "srdl", + .insn = srdl_0x99a, + .op1 = 0x1018611c41689a1dull, + .op2 = 0x2907e150c50ba319ull, + .exp_result = 0x0000000000000203ull, + .exp_cc = 0, + }, +}; + +int main(void) +{ + int ret = 0; + size_t i; + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + uint64_t result; + uint64_t cc = 0; + + result = tests[i].insn(tests[i].op1, tests[i].op2, &cc); + if (result != tests[i].exp_result) { + fprintf(stderr, + "bad %s result:\n" + "actual = 0x%" PRIx64 "\n" + "expected = 0x%" PRIx64 "\n", + tests[i].name, result, tests[i].exp_result); + ret = 1; + } + if (cc != tests[i].exp_cc) { + fprintf(stderr, + "bad %s cc:\n" + "actual = %" PRIu64 "\n" + "expected = %" PRIu64 "\n", + tests[i].name, cc, tests[i].exp_cc); + ret = 1; + } + } + return ret; +} From 56e34834029c7c6862cb0095d95ad83c50485f88 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 22 Dec 2021 11:55:48 +0100 Subject: [PATCH 516/730] MAINTAINERS: split out s390x sections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split out some more specialized devices etc., so that we can build smarter lists of people to be put on cc: in the future. Signed-off-by: Cornelia Huck Reviewed-by: Philippe Mathieu-Daudé Acked-by: David Hildenbrand Acked-by: Christian Borntraeger Acked-by: Thomas Huth Acked-by: Halil Pasic Acked-by: Eric Farman Message-Id: <20211222105548.356852-1-cohuck@redhat.com> Signed-off-by: Thomas Huth --- MAINTAINERS | 85 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 74 insertions(+), 11 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 2fd74c4642..793d6edd2d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -297,7 +297,6 @@ M: David Hildenbrand S: Maintained F: target/s390x/ F: target/s390x/tcg -F: target/s390x/cpu_models_*.[ch] F: hw/s390x/ F: disas/s390.c F: tests/tcg/s390x/ @@ -396,16 +395,10 @@ M: Halil Pasic M: Christian Borntraeger S: Supported F: target/s390x/kvm/ -F: target/s390x/ioinst.[ch] F: target/s390x/machine.c F: target/s390x/sigp.c -F: target/s390x/cpu_features*.[ch] -F: target/s390x/cpu_models.[ch] F: hw/s390x/pv.c F: include/hw/s390x/pv.h -F: hw/intc/s390_flic.c -F: hw/intc/s390_flic_kvm.c -F: include/hw/s390x/s390_flic.h F: gdb-xml/s390*.xml T: git https://github.com/borntraeger/qemu.git s390-next L: qemu-s390x@nongnu.org @@ -1533,12 +1526,8 @@ S390 Virtio-ccw M: Halil Pasic M: Christian Borntraeger S: Supported -F: hw/char/sclp*.[hc] -F: hw/char/terminal3270.c F: hw/s390x/ F: include/hw/s390x/ -F: hw/watchdog/wdt_diag288.c -F: include/hw/watchdog/wdt_diag288.h F: configs/devices/s390x-softmmu/default.mak F: tests/avocado/machine_s390_ccw_virtio.py T: git https://github.com/borntraeger/qemu.git s390-next @@ -1563,6 +1552,37 @@ F: hw/s390x/s390-pci* F: include/hw/s390x/s390-pci* L: qemu-s390x@nongnu.org +S390 channel subsystem +M: Halil Pasic +M: Christian Borntraeger +S: Supported +F: hw/s390x/ccw-device.[ch] +F: hw/s390x/css.c +F: hw/s390x/css-bridge.c +F: include/hw/s390x/css.h +F: include/hw/s390x/css-bridge.h +F: include/hw/s390x/ioinst.h +F: target/s390x/ioinst.c +L: qemu-s390x@nongnu.org + +S390 CPU models +M: David Hildenbrand +S: Maintained +F: target/s390x/cpu_features*.[ch] +F: target/s390x/cpu_models.[ch] +L: qemu-s390x@nongnu.org + +S390 SCLP-backed devices +M: Halil Pasic +M: Christian Borntraeger +S: Supported +F: include/hw/s390x/event-facility.h +F: include/hw/s390x/sclp.h +F: hw/char/sclp*.[hc] +F: hw/s390x/event-facility.c +F: hw/s390x/sclp*.c +L: qemu-s390x@nongnu.org + X86 Machines ------------ PC @@ -1970,6 +1990,7 @@ M: Halil Pasic S: Supported F: hw/s390x/virtio-ccw*.[hc] F: hw/s390x/vhost-vsock-ccw.c +F: hw/s390x/vhost-user-fs-ccw.c T: git https://gitlab.com/cohuck/qemu.git s390-next T: git https://github.com/borntraeger/qemu.git s390-next L: qemu-s390x@nongnu.org @@ -2308,6 +2329,48 @@ F: hw/timer/mips_gictimer.c F: include/hw/intc/mips_gic.h F: include/hw/timer/mips_gictimer.h +S390 3270 device +M: Halil Pasic +M: Christian Borntraeger +S: Odd fixes +F: include/hw/s390x/3270-ccw.h +F: hw/char/terminal3270.c +F: hw/s390x/3270-ccw.c +L: qemu-s390x@nongnu.org + +S390 diag 288 watchdog +M: Halil Pasic +M: Christian Borntraeger +S: Supported +F: hw/watchdog/wdt_diag288.c +F: include/hw/watchdog/wdt_diag288.h +L: qemu-s390x@nongnu.org + +S390 storage key device +M: Halil Pasic +M: Christian Borntraeger +S: Supported +F: hw/s390x/storage-keys.h +F: hw/390x/s390-skeys*.c +L: qemu-s390x@nongnu.org + +S390 storage attribute device +M: Halil Pasic +M: Christian Borntraeger +S: Supported +F: hw/s390x/storage-attributes.h +F: hw/s390/s390-stattrib*.c +L: qemu-s390x@nongnu.org + +S390 floating interrupt controller +M: Halil Pasic +M: Christian Borntraeger +M: David Hildenbrand +S: Supported +F: hw/intc/s390_flic*.c +F: include/hw/s390x/s390_flic.h +L: qemu-s390x@nongnu.org + Subsystems ---------- Overall Audio backends From 6a6d3dfd6ed57d624dbbef116c8328d70d49130f Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Wed, 12 Jan 2022 17:40:44 +0100 Subject: [PATCH 517/730] MAINTAINERS: Add myself to s390 I/O areas After the recent restructuring, I'd like to volunteer to help in some of the s390 I/O areas. Built on "[PATCH RFC v2] MAINTAINERS: split out s390x sections" Signed-off-by: Eric Farman Acked-by: Christian Borntraeger Acked-by: Halil Pasic Message-Id: <20220112164044.2210508-1-farman@linux.ibm.com> Signed-off-by: Thomas Huth --- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 793d6edd2d..893a556710 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1525,6 +1525,7 @@ S390 Machines S390 Virtio-ccw M: Halil Pasic M: Christian Borntraeger +M: Eric Farman S: Supported F: hw/s390x/ F: include/hw/s390x/ @@ -1555,6 +1556,7 @@ L: qemu-s390x@nongnu.org S390 channel subsystem M: Halil Pasic M: Christian Borntraeger +M: Eric Farman S: Supported F: hw/s390x/ccw-device.[ch] F: hw/s390x/css.c @@ -1987,6 +1989,7 @@ T: git https://github.com/stefanha/qemu.git block virtio-ccw M: Cornelia Huck M: Halil Pasic +M: Eric Farman S: Supported F: hw/s390x/virtio-ccw*.[hc] F: hw/s390x/vhost-vsock-ccw.c From 1a59bdba4bf476c242fbf88283a71427c0160f06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 16 Aug 2020 19:07:11 +0200 Subject: [PATCH 518/730] memory: Directly dispatch alias accesses on origin memory region MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 2cdfcf272d ("memory: assign MemoryRegionOps to all regions"), all newly created regions are assigned with unassigned_mem_ops (which might be then overwritten). When using aliased container regions, and there is no region mapped at address 0 in the container, the memory_region_dispatch_read() and memory_region_dispatch_write() calls incorrectly return the container unassigned_mem_ops, because the alias offset is not used. Consider the following setup: +--------------------+ < - - - - - - - - - - - + | Container | mr | (unassigned_mem) | | | | | | | | | alias_offset + + <- - - - - - +----------+---------+ | +----------------+ | | | | | MemoryRegion0 | | | | | +----------------+ | | Alias | addr1 | | MemoryRegion1 | | <~ ~ ~ ~ ~ | | <~~~~~~ | +----------------+ | | | | | +--------------------+ | | | | | | | | | +----------------+ | | | MemoryRegionX | | | +----------------+ | | | MemoryRegionY | | | +----------------+ | | | MemoryRegionZ | | | +----------------+ | +--------------------+ The memory_region_init_alias() flow is: memory_region_init_alias() -> memory_region_init() -> object_initialize(TYPE_MEMORY_REGION) -> memory_region_initfn() -> mr->ops = &unassigned_mem_ops; Later when accessing offset=addr1 via the alias, we expect to hit MemoryRegion1. The memory_region_dispatch_read() flow is: memory_region_dispatch_read(addr1) -> memory_region_access_valid(mr) <- addr1 offset is ignored -> mr->ops->valid.accepts() -> unassigned_mem_accepts() <- false <- false <- MEMTX_DECODE_ERROR The caller gets a MEMTX_DECODE_ERROR while the access is OK. Fix by dispatching aliases recursively, accessing its origin region after adding the alias offset. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Peter Xu Message-Id: <20210418055708.820980-1-f4bug@amsat.org> --- softmmu/memory.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/softmmu/memory.c b/softmmu/memory.c index 7340e19ff5..0c463e0fe5 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -1444,6 +1444,11 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr, unsigned size = memop_size(op); MemTxResult r; + if (mr->alias) { + return memory_region_dispatch_read(mr->alias, + mr->alias_offset + addr, + pval, op, attrs); + } if (!memory_region_access_valid(mr, addr, size, false, attrs)) { *pval = unassigned_mem_read(mr, addr, size); return MEMTX_DECODE_ERROR; @@ -1488,6 +1493,11 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr, { unsigned size = memop_size(op); + if (mr->alias) { + return memory_region_dispatch_write(mr->alias, + mr->alias_offset + addr, + data, op, attrs); + } if (!memory_region_access_valid(mr, addr, size, true, attrs)) { unassigned_mem_write(mr, addr, data, size); return MEMTX_DECODE_ERROR; From 670c0780e7a12013f06b7702e37d8434274cc018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 1 Sep 2021 17:45:48 +0200 Subject: [PATCH 519/730] memory: Split mtree_info() as mtree_info_flatview() + mtree_info_as() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While mtree_info() handles both ASes and flatviews cases, the two cases share basically no code. Split mtree_info() as mtree_info_flatview() + mtree_info_as() to simplify. Suggested-by: Peter Maydell Reviewed-by: David Hildenbrand Reviewed-by: Peter Xu Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20210904231101.1071929-2-philmd@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- softmmu/memory.c | 87 ++++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/softmmu/memory.c b/softmmu/memory.c index 0c463e0fe5..2cb823c642 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -3284,50 +3284,50 @@ static gboolean mtree_info_flatview_free(gpointer key, gpointer value, return true; } -void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled) +static void mtree_info_flatview(bool dispatch_tree, bool owner) +{ + struct FlatViewInfo fvi = { + .counter = 0, + .dispatch_tree = dispatch_tree, + .owner = owner, + }; + AddressSpace *as; + FlatView *view; + GArray *fv_address_spaces; + GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal); + AccelClass *ac = ACCEL_GET_CLASS(current_accel()); + + if (ac->has_memory) { + fvi.ac = ac; + } + + /* Gather all FVs in one table */ + QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { + view = address_space_get_flatview(as); + + fv_address_spaces = g_hash_table_lookup(views, view); + if (!fv_address_spaces) { + fv_address_spaces = g_array_new(false, false, sizeof(as)); + g_hash_table_insert(views, view, fv_address_spaces); + } + + g_array_append_val(fv_address_spaces, as); + } + + /* Print */ + g_hash_table_foreach(views, mtree_print_flatview, &fvi); + + /* Free */ + g_hash_table_foreach_remove(views, mtree_info_flatview_free, 0); + g_hash_table_unref(views); +} + +static void mtree_info_as(bool dispatch_tree, bool owner, bool disabled) { MemoryRegionListHead ml_head; MemoryRegionList *ml, *ml2; AddressSpace *as; - if (flatview) { - FlatView *view; - struct FlatViewInfo fvi = { - .counter = 0, - .dispatch_tree = dispatch_tree, - .owner = owner, - }; - GArray *fv_address_spaces; - GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal); - AccelClass *ac = ACCEL_GET_CLASS(current_accel()); - - if (ac->has_memory) { - fvi.ac = ac; - } - - /* Gather all FVs in one table */ - QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - view = address_space_get_flatview(as); - - fv_address_spaces = g_hash_table_lookup(views, view); - if (!fv_address_spaces) { - fv_address_spaces = g_array_new(false, false, sizeof(as)); - g_hash_table_insert(views, view, fv_address_spaces); - } - - g_array_append_val(fv_address_spaces, as); - } - - /* Print */ - g_hash_table_foreach(views, mtree_print_flatview, &fvi); - - /* Free */ - g_hash_table_foreach_remove(views, mtree_info_flatview_free, 0); - g_hash_table_unref(views); - - return; - } - QTAILQ_INIT(&ml_head); QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { @@ -3348,6 +3348,15 @@ void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled) } } +void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled) +{ + if (flatview) { + mtree_info_flatview(dispatch_tree, owner); + } else { + mtree_info_as(dispatch_tree, owner, disabled); + } +} + void memory_region_init_ram(MemoryRegion *mr, Object *owner, const char *name, From 7bdbf99aa2aac3bf483db6a08d1cea5bf1053c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 20 Aug 2021 12:34:14 +0200 Subject: [PATCH 520/730] memory: Have 'info mtree' remove duplicated Address Space information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Peter Maydell [*]: 'info mtree' monitor command was designed on the assumption that there's really only one or two interesting address spaces, and with more recent developments that's just not the case any more. Similarly about how the FlatView are sorted using a GHashTable, sort the AddressSpace objects to remove the duplications (AS using the same root MemoryRegion). This drastically reduces the output of 'info mtree' on some boards. Before: $ (echo info mtree; echo q) \ | qemu-system-aarch64 -S -monitor stdio -M raspi3b \ | wc -l 423 After: $ (echo info mtree; echo q) \ | qemu-system-aarch64 -S -monitor stdio -M raspi3b \ | wc -l 106 (qemu) info mtree address-space: I/O 0000000000000000-000000000000ffff (prio 0, i/o): io address-space: cpu-memory-0 address-space: cpu-memory-1 address-space: cpu-memory-2 address-space: cpu-memory-3 address-space: cpu-secure-memory-0 address-space: cpu-secure-memory-1 address-space: cpu-secure-memory-2 address-space: cpu-secure-memory-3 address-space: memory 0000000000000000-ffffffffffffffff (prio 0, i/o): system 0000000000000000-000000003fffffff (prio 0, ram): ram 000000003f000000-000000003fffffff (prio 1, i/o): bcm2835-peripherals 000000003f003000-000000003f00301f (prio 0, i/o): bcm2835-sys-timer 000000003f004000-000000003f004fff (prio -1000, i/o): bcm2835-txp 000000003f006000-000000003f006fff (prio 0, i/o): mphi 000000003f007000-000000003f007fff (prio 0, i/o): bcm2835-dma 000000003f00b200-000000003f00b3ff (prio 0, i/o): bcm2835-ic 000000003f00b400-000000003f00b43f (prio -1000, i/o): bcm2835-sp804 000000003f00b800-000000003f00bbff (prio 0, i/o): bcm2835-mbox 000000003f100000-000000003f1001ff (prio 0, i/o): bcm2835-powermgt 000000003f101000-000000003f102fff (prio 0, i/o): bcm2835-cprman 000000003f104000-000000003f10400f (prio 0, i/o): bcm2835-rng 000000003f200000-000000003f200fff (prio 0, i/o): bcm2835_gpio 000000003f201000-000000003f201fff (prio 0, i/o): pl011 000000003f202000-000000003f202fff (prio 0, i/o): bcm2835-sdhost 000000003f203000-000000003f2030ff (prio -1000, i/o): bcm2835-i2s 000000003f204000-000000003f20401f (prio -1000, i/o): bcm2835-spi0 000000003f205000-000000003f20501f (prio -1000, i/o): bcm2835-i2c0 000000003f20f000-000000003f20f07f (prio -1000, i/o): bcm2835-otp 000000003f212000-000000003f212007 (prio 0, i/o): bcm2835-thermal 000000003f214000-000000003f2140ff (prio -1000, i/o): bcm2835-spis 000000003f215000-000000003f2150ff (prio 0, i/o): bcm2835-aux 000000003f300000-000000003f3000ff (prio 0, i/o): sdhci 000000003f600000-000000003f6000ff (prio -1000, i/o): bcm2835-smi 000000003f804000-000000003f80401f (prio -1000, i/o): bcm2835-i2c1 000000003f805000-000000003f80501f (prio -1000, i/o): bcm2835-i2c2 000000003f900000-000000003f907fff (prio -1000, i/o): bcm2835-dbus 000000003f910000-000000003f917fff (prio -1000, i/o): bcm2835-ave0 000000003f980000-000000003f990fff (prio 0, i/o): dwc2 000000003f980000-000000003f980fff (prio 0, i/o): dwc2-io 000000003f981000-000000003f990fff (prio 0, i/o): dwc2-fifo 000000003fc00000-000000003fc00fff (prio -1000, i/o): bcm2835-v3d 000000003fe00000-000000003fe000ff (prio -1000, i/o): bcm2835-sdramc 000000003fe05000-000000003fe050ff (prio 0, i/o): bcm2835-dma-chan15 0000000040000000-00000000400000ff (prio 0, i/o): bcm2836-control address-space: bcm2835-dma-memory address-space: bcm2835-fb-memory address-space: bcm2835-property-memory address-space: dwc2 0000000000000000-00000000ffffffff (prio 0, i/o): bcm2835-gpu 0000000000000000-000000003fffffff (prio 0, ram): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff 0000000040000000-000000007fffffff (prio 0, ram): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff 000000007e000000-000000007effffff (prio 1, i/o): alias bcm2835-peripherals @bcm2835-peripherals 0000000000000000-0000000000ffffff 0000000080000000-00000000bfffffff (prio 0, ram): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff 00000000c0000000-00000000ffffffff (prio 0, ram): alias bcm2835-gpu-ram-alias[*] @ram 0000000000000000-000000003fffffff address-space: bcm2835-mbox-memory 0000000000000000-000000000000008f (prio 0, i/o): bcm2835-mbox 0000000000000010-000000000000001f (prio 0, i/o): bcm2835-fb 0000000000000080-000000000000008f (prio 0, i/o): bcm2835-property memory-region: ram 0000000000000000-000000003fffffff (prio 0, ram): ram memory-region: bcm2835-peripherals 000000003f000000-000000003fffffff (prio 1, i/o): bcm2835-peripherals 000000003f003000-000000003f00301f (prio 0, i/o): bcm2835-sys-timer 000000003f004000-000000003f004fff (prio -1000, i/o): bcm2835-txp 000000003f006000-000000003f006fff (prio 0, i/o): mphi 000000003f007000-000000003f007fff (prio 0, i/o): bcm2835-dma 000000003f00b200-000000003f00b3ff (prio 0, i/o): bcm2835-ic 000000003f00b400-000000003f00b43f (prio -1000, i/o): bcm2835-sp804 000000003f00b800-000000003f00bbff (prio 0, i/o): bcm2835-mbox 000000003f100000-000000003f1001ff (prio 0, i/o): bcm2835-powermgt 000000003f101000-000000003f102fff (prio 0, i/o): bcm2835-cprman 000000003f104000-000000003f10400f (prio 0, i/o): bcm2835-rng 000000003f200000-000000003f200fff (prio 0, i/o): bcm2835_gpio 000000003f201000-000000003f201fff (prio 0, i/o): pl011 000000003f202000-000000003f202fff (prio 0, i/o): bcm2835-sdhost 000000003f203000-000000003f2030ff (prio -1000, i/o): bcm2835-i2s 000000003f204000-000000003f20401f (prio -1000, i/o): bcm2835-spi0 000000003f205000-000000003f20501f (prio -1000, i/o): bcm2835-i2c0 000000003f20f000-000000003f20f07f (prio -1000, i/o): bcm2835-otp 000000003f212000-000000003f212007 (prio 0, i/o): bcm2835-thermal 000000003f214000-000000003f2140ff (prio -1000, i/o): bcm2835-spis 000000003f215000-000000003f2150ff (prio 0, i/o): bcm2835-aux 000000003f300000-000000003f3000ff (prio 0, i/o): sdhci 000000003f600000-000000003f6000ff (prio -1000, i/o): bcm2835-smi 000000003f804000-000000003f80401f (prio -1000, i/o): bcm2835-i2c1 000000003f805000-000000003f80501f (prio -1000, i/o): bcm2835-i2c2 000000003f900000-000000003f907fff (prio -1000, i/o): bcm2835-dbus 000000003f910000-000000003f917fff (prio -1000, i/o): bcm2835-ave0 000000003f980000-000000003f990fff (prio 0, i/o): dwc2 000000003f980000-000000003f980fff (prio 0, i/o): dwc2-io 000000003f981000-000000003f990fff (prio 0, i/o): dwc2-fifo 000000003fc00000-000000003fc00fff (prio -1000, i/o): bcm2835-v3d 000000003fe00000-000000003fe000ff (prio -1000, i/o): bcm2835-sdramc 000000003fe05000-000000003fe050ff (prio 0, i/o): bcm2835-dma-chan15 (qemu) q [*] https://www.mail-archive.com/qemu-devel@nongnu.org/msg829821.html Suggested-by: Peter Maydell Reviewed-by: Peter Maydell Reviewed-by: David Hildenbrand Reviewed-by: Peter Xu Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20210904231101.1071929-2-philmd@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- softmmu/memory.c | 63 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/softmmu/memory.c b/softmmu/memory.c index 2cb823c642..5e69624f7f 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -3322,20 +3322,77 @@ static void mtree_info_flatview(bool dispatch_tree, bool owner) g_hash_table_unref(views); } +struct AddressSpaceInfo { + MemoryRegionListHead *ml_head; + bool owner; + bool disabled; +}; + +/* Returns negative value if a < b; zero if a = b; positive value if a > b. */ +static gint address_space_compare_name(gconstpointer a, gconstpointer b) +{ + const AddressSpace *as_a = a; + const AddressSpace *as_b = b; + + return g_strcmp0(as_a->name, as_b->name); +} + +static void mtree_print_as_name(gpointer data, gpointer user_data) +{ + AddressSpace *as = data; + + qemu_printf("address-space: %s\n", as->name); +} + +static void mtree_print_as(gpointer key, gpointer value, gpointer user_data) +{ + MemoryRegion *mr = key; + GSList *as_same_root_mr_list = value; + struct AddressSpaceInfo *asi = user_data; + + g_slist_foreach(as_same_root_mr_list, mtree_print_as_name, NULL); + mtree_print_mr(mr, 1, 0, asi->ml_head, asi->owner, asi->disabled); + qemu_printf("\n"); +} + +static gboolean mtree_info_as_free(gpointer key, gpointer value, + gpointer user_data) +{ + GSList *as_same_root_mr_list = value; + + g_slist_free(as_same_root_mr_list); + + return true; +} + static void mtree_info_as(bool dispatch_tree, bool owner, bool disabled) { MemoryRegionListHead ml_head; MemoryRegionList *ml, *ml2; AddressSpace *as; + GHashTable *views = g_hash_table_new(g_direct_hash, g_direct_equal); + GSList *as_same_root_mr_list; + struct AddressSpaceInfo asi = { + .ml_head = &ml_head, + .owner = owner, + .disabled = disabled, + }; QTAILQ_INIT(&ml_head); QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - qemu_printf("address-space: %s\n", as->name); - mtree_print_mr(as->root, 1, 0, &ml_head, owner, disabled); - qemu_printf("\n"); + /* Create hashtable, key=AS root MR, value = list of AS */ + as_same_root_mr_list = g_hash_table_lookup(views, as->root); + as_same_root_mr_list = g_slist_insert_sorted(as_same_root_mr_list, as, + address_space_compare_name); + g_hash_table_insert(views, as->root, as_same_root_mr_list); } + /* print address spaces */ + g_hash_table_foreach(views, mtree_print_as, &asi); + g_hash_table_foreach_remove(views, mtree_info_as_free, 0); + g_hash_table_unref(views); + /* print aliased regions */ QTAILQ_FOREACH(ml, &ml_head, mrqueue) { qemu_printf("memory-region: %s\n", memory_region_name(ml->mr)); From eef3a7abff8a5eab840868fffd6195d8a2a555d0 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Tue, 2 Nov 2021 17:43:15 +0100 Subject: [PATCH 521/730] machine: Use host_memory_backend_is_mapped() in machine_consume_memdev() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit memory_region_is_mapped() is the wrong check, we actually want to check whether the backend is already marked mapped. For example, memory regions mapped via an alias, such as NVDIMMs, currently don't make memory_region_is_mapped() return "true". As the machine is initialized before any memory devices (and thereby before NVDIMMs are initialized), this isn't a fix but merely a cleanup. Reviewed-by: Richard Henderson Reviewed-by: Igor Mammedov Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Xu Signed-off-by: David Hildenbrand Message-Id: <20211102164317.45658-2-david@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- hw/core/machine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/core/machine.c b/hw/core/machine.c index debcdc0e70..d856485cb4 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -1091,7 +1091,7 @@ MemoryRegion *machine_consume_memdev(MachineState *machine, { MemoryRegion *ret = host_memory_backend_get_memory(backend); - if (memory_region_is_mapped(ret)) { + if (host_memory_backend_is_mapped(backend)) { error_report("memory backend %s can't be used multiple times.", object_get_canonical_path_component(OBJECT(backend))); exit(EXIT_FAILURE); From 5ead62185d23caad41ef2afc80773fb384e40229 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Tue, 2 Nov 2021 17:43:16 +0100 Subject: [PATCH 522/730] memory: Make memory_region_is_mapped() succeed when mapped via an alias MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit memory_region_is_mapped() currently does not return "true" when a memory region is mapped via an alias. Assuming we have: alias (A0) -> alias (A1) -> region (R0) Mapping A0 would currently only make memory_region_is_mapped() succeed on A0, but not on A1 and R0. Let's fix that by adding a "mapped_via_alias" counter to memory regions and updating it accordingly when an alias gets (un)mapped. I am not aware of actual issues, this is rather a cleanup to make it consistent. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Xu Signed-off-by: David Hildenbrand Message-Id: <20211102164317.45658-3-david@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- include/exec/memory.h | 1 + softmmu/memory.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 20f1b27377..fea1a493b9 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -738,6 +738,7 @@ struct MemoryRegion { const MemoryRegionOps *ops; void *opaque; MemoryRegion *container; + int mapped_via_alias; /* Mapped via an alias, container might be NULL */ Int128 size; hwaddr addr; void (*destructor)(MemoryRegion *mr); diff --git a/softmmu/memory.c b/softmmu/memory.c index 5e69624f7f..e37a4b8ae3 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -2545,8 +2545,13 @@ static void memory_region_add_subregion_common(MemoryRegion *mr, hwaddr offset, MemoryRegion *subregion) { + MemoryRegion *alias; + assert(!subregion->container); subregion->container = mr; + for (alias = subregion->alias; alias; alias = alias->alias) { + alias->mapped_via_alias++; + } subregion->addr = offset; memory_region_update_container_subregions(subregion); } @@ -2571,9 +2576,15 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr, void memory_region_del_subregion(MemoryRegion *mr, MemoryRegion *subregion) { + MemoryRegion *alias; + memory_region_transaction_begin(); assert(subregion->container == mr); subregion->container = NULL; + for (alias = subregion->alias; alias; alias = alias->alias) { + alias->mapped_via_alias--; + assert(alias->mapped_via_alias >= 0); + } QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link); memory_region_unref(subregion); memory_region_update_pending |= mr->enabled && subregion->enabled; @@ -2670,7 +2681,7 @@ static FlatRange *flatview_lookup(FlatView *view, AddrRange addr) bool memory_region_is_mapped(MemoryRegion *mr) { - return mr->container ? true : false; + return !!mr->container || mr->mapped_via_alias; } /* Same as memory_region_find, but it does not add a reference to the From 455faf03df1a9beff236e3b194cad93e4b014076 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Tue, 2 Nov 2021 17:43:17 +0100 Subject: [PATCH 523/730] memory: Update description of memory_region_is_mapped() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's update the documentation, making it clearer what the semantics of memory_region_is_mapped() actually are. Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Xu Signed-off-by: David Hildenbrand Message-Id: <20211102164317.45658-4-david@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- include/exec/memory.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index fea1a493b9..63be794a06 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -2297,7 +2297,8 @@ bool memory_region_present(MemoryRegion *container, hwaddr addr); /** * memory_region_is_mapped: returns true if #MemoryRegion is mapped - * into any address space. + * into another memory region, which does not necessarily imply that it is + * mapped into an address space. * * @mr: a #MemoryRegion which should be checked if it's mapped */ From 7b0538ed3a22ce30817f818449d10701fb0821f9 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Tue, 30 Nov 2021 16:00:28 +0800 Subject: [PATCH 524/730] memory: Fix incorrect calls of log_global_start/stop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should only call the log_global_start/stop when the global dirty track bitmask changes from zero<->non-zero. No real issue reported for this yet probably because no immediate user to enable both dirty rate measurement and migration at the same time. However it'll be good to be prepared for it. Fixes: 63b41db4bc ("memory: make global_dirty_tracking a bitmask") Cc: qemu-stable@nongnu.org Cc: Hyman Huang Cc: Paolo Bonzini Cc: Dr. David Alan Gilbert Cc: Juan Quintela Cc: David Hildenbrand Signed-off-by: Peter Xu Reviewed-by: David Hildenbrand Message-Id: <20211130080028.6474-1-peterx@redhat.com> Signed-off-by: Philippe Mathieu-Daudé --- softmmu/memory.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/softmmu/memory.c b/softmmu/memory.c index e37a4b8ae3..678dc62f06 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -2794,6 +2794,8 @@ static VMChangeStateEntry *vmstate_change; void memory_global_dirty_log_start(unsigned int flags) { + unsigned int old_flags = global_dirty_tracking; + if (vmstate_change) { qemu_del_vm_change_state_handler(vmstate_change); vmstate_change = NULL; @@ -2802,15 +2804,14 @@ void memory_global_dirty_log_start(unsigned int flags) assert(flags && !(flags & (~GLOBAL_DIRTY_MASK))); assert(!(global_dirty_tracking & flags)); global_dirty_tracking |= flags; - trace_global_dirty_changed(global_dirty_tracking); - MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward); - - /* Refresh DIRTY_MEMORY_MIGRATION bit. */ - memory_region_transaction_begin(); - memory_region_update_pending = true; - memory_region_transaction_commit(); + if (!old_flags) { + MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward); + memory_region_transaction_begin(); + memory_region_update_pending = true; + memory_region_transaction_commit(); + } } static void memory_global_dirty_log_do_stop(unsigned int flags) @@ -2821,12 +2822,12 @@ static void memory_global_dirty_log_do_stop(unsigned int flags) trace_global_dirty_changed(global_dirty_tracking); - /* Refresh DIRTY_MEMORY_MIGRATION bit. */ - memory_region_transaction_begin(); - memory_region_update_pending = true; - memory_region_transaction_commit(); - - MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse); + if (!global_dirty_tracking) { + memory_region_transaction_begin(); + memory_region_update_pending = true; + memory_region_transaction_commit(); + MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse); + } } static void memory_vm_change_state_handler(void *opaque, bool running, From e3ae2bbfcac6400c1eff72b5e89d093dd5758f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 11 Jan 2022 11:44:18 +0100 Subject: [PATCH 525/730] stubs: Restrict fw_cfg to system emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fw_cfg_arch_key_name() stub is only required for sysemu. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: David Hildenbrand Message-Id: <20220111184309.28637-2-f4bug@amsat.org> --- stubs/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/meson.build b/stubs/meson.build index 71469c1d50..363f6fa785 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -11,7 +11,6 @@ stub_ss.add(files('icount.c')) stub_ss.add(files('dump.c')) stub_ss.add(files('error-printf.c')) stub_ss.add(files('fdset.c')) -stub_ss.add(files('fw_cfg.c')) stub_ss.add(files('gdbstub.c')) stub_ss.add(files('get-vm-name.c')) if linux_io_uring.found() @@ -51,6 +50,7 @@ if have_block stub_ss.add(files('replay-tools.c')) endif if have_system + stub_ss.add(files('fw_cfg.c')) stub_ss.add(files('semihost.c')) stub_ss.add(files('usb-dev-stub.c')) stub_ss.add(files('xen-hw-stub.c')) From 33cda58f0064fdeffe0c13bf340c63878e321f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 12:13:57 +0100 Subject: [PATCH 526/730] hw/nvram: Restrict fw_cfg QOM interface to sysemu and tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fw_cfg QOM interface is required by system emulation and qemu-storage-daemon. User-mode emulation doesn't need it. Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: David Hildenbrand Message-Id: <20220111184309.28637-3-f4bug@amsat.org> --- hw/nvram/meson.build | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index 202a5466e6..f5ee9f6b88 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -1,5 +1,7 @@ -# QOM interfaces must be available anytime QOM is used. -qom_ss.add(files('fw_cfg-interface.c')) +if have_system or have_tools + # QOM interfaces must be available anytime QOM is used. + qom_ss.add(files('fw_cfg-interface.c')) +endif softmmu_ss.add(files('fw_cfg.c')) softmmu_ss.add(when: 'CONFIG_CHRP_NVRAM', if_true: files('chrp_nvram.c')) From e0431aafc48ed0bea934148fb7266dbe36ef7685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 11:10:27 +0100 Subject: [PATCH 527/730] hw/pci: Restrict pci-bus stub to sysemu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neither tools nor user-mode emulation require the PCI bus stub. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Michael S. Tsirkin Reviewed-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20220111184309.28637-4-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- stubs/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/meson.build b/stubs/meson.build index 363f6fa785..d359cbe1ad 100644 --- a/stubs/meson.build +++ b/stubs/meson.build @@ -26,7 +26,6 @@ stub_ss.add(files('migr-blocker.c')) stub_ss.add(files('module-opts.c')) stub_ss.add(files('monitor.c')) stub_ss.add(files('monitor-core.c')) -stub_ss.add(files('pci-bus.c')) stub_ss.add(files('qemu-timer-notify-cb.c')) stub_ss.add(files('qmp_memory_device.c')) stub_ss.add(files('qmp-command-available.c')) @@ -51,6 +50,7 @@ if have_block endif if have_system stub_ss.add(files('fw_cfg.c')) + stub_ss.add(files('pci-bus.c')) stub_ss.add(files('semihost.c')) stub_ss.add(files('usb-dev-stub.c')) stub_ss.add(files('xen-hw-stub.c')) From 1efc6b319cfab73176412d86fa8f3702ed30c867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 11:51:52 +0100 Subject: [PATCH 528/730] hw/pci: Document pci_dma_map() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Michael S. Tsirkin Reviewed-by: Richard Henderson Message-Id: <20220111184309.28637-5-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- include/hw/pci/pci.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 483d5c7c72..023abc0f79 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -881,6 +881,18 @@ PCI_DMA_DEFINE_LDST(q_be, q_be, 64); #undef PCI_DMA_DEFINE_LDST +/** + * pci_dma_map: Map device PCI address space range into host virtual address + * @dev: #PCIDevice to be accessed + * @addr: address within that device's address space + * @plen: pointer to length of buffer; updated on return to indicate + * if only a subset of the requested range has been mapped + * @dir: indicates the transfer direction + * + * Return: A host pointer, or %NULL if the resources needed to + * perform the mapping are exhausted (in that case *@plen + * is set to zero). + */ static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t *plen, DMADirection dir) { From fd5e451edbebecaa65d2e6fef09b9afd7eefc951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 11:18:15 +0100 Subject: [PATCH 529/730] hw/dma: Remove CONFIG_USER_ONLY check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DMA API should not be included in user-mode emulation. If so, build should fail. Remove the CONFIG_USER_ONLY check. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20220111184309.28637-6-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- include/sysemu/dma.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index b3faef41b2..0db2478a50 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -31,8 +31,6 @@ struct QEMUSGList { AddressSpace *as; }; -#ifndef CONFIG_USER_ONLY - /* * When an IOMMU is present, bus addresses become distinct from * CPU/memory physical addresses and may be a different size. Because @@ -288,7 +286,6 @@ void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint, AddressSpace *as); void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len); void qemu_sglist_destroy(QEMUSGList *qsg); -#endif typedef BlockAIOCB *DMAIOFunc(int64_t offset, QEMUIOVector *iov, BlockCompletionFunc *cb, void *cb_opaque, From 6a094d62ffccad7e2411cc96d6400145e38da13e Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 18 Jan 2022 11:56:16 +0100 Subject: [PATCH 530/730] seabios: update submodule to snapshot Most important update is smbios3 support being added, this update should help getting the qemu side of things (flip to smbios3 by default for new machine types) merged and tested. Not fully clear yet when the next 1.16 seabios version will be released, but it should be no later than end of February so we can pick it up for qemu 7.0. full shortlog ============= Andy Pei (3): virtio-blk: add feature VIRTIO_BLK_F_SIZE_MAX and VIRTIO_BLK_F_SEG_MAX virtio-blk: abstract a function named virtio_blk_op_one_segment to handle r/w request virtio-blk: split large IO according to size_max Eduardo Habkost (19): biostables: copy_fseg_table() function util.h: Delete unused get_smbios_entry_point() prototype smbios: Rename code specific for SMBIOS 2.1 entry points smbios: Generic smbios_next() function smbios: smbios_get_tables() function smbios: Use smbios_get_tables()/smbios_next() at display_uuid() smbios: smbios_major_version()/smbios_minor_version() helpers tpm: Use smbios_get_tables() csm: Don't check SMBios21Addr before calling copy_smbios_21() smbios: Make SMBios21Addr variable static smbios: Use smbios_next() at smbios_romfile_setup() smbios: Extract SMBIOS table building code to separate function smbios: Make smbios_build_tables() more generic smbios: smbios_21_setup_entry_point() function smbios: Make some smbios_build_tables() arguments optional smbios: Make smbios_build_tables() ready for 64-bit tables smbios: copy_smbios_30() function smbios: Support SMBIOS 3.0 entry point at copy_table() smbios: Support SMBIOS 3.0 entry point at smbios_romfile_setup() Gerd Hoffmann (1): svgamodes: add standard 4k modes Igor Mammedov (2): pci: reserve resources for pcie-pci-bridge to fix regressed hotplug on q35 pci: let firmware reserve IO for pcie-pci-bridge Kevin O'Connor (4): vgasrc: Don't use VAR16 in header files to fix gcc warning memmap: Fix gcc out-of-bounds warning readserial: Improve Python3 compatibility scripts: Remove python23compat.py Signed-off-by: Gerd Hoffmann --- roms/seabios | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roms/seabios b/roms/seabios index 2dd4b9b3f8..6a62e0cb0d 160000 --- a/roms/seabios +++ b/roms/seabios @@ -1 +1 @@ -Subproject commit 2dd4b9b3f84019668719344b40dba79d681be41c +Subproject commit 6a62e0cb0dfe9cd28b70547dbea5caf76847c3a9 From 11bb4e968432fce4b140e2d272301d1fb025a77f Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 18 Jan 2022 12:15:49 +0100 Subject: [PATCH 531/730] seabios: update binaries to snapshot Signed-off-by: Gerd Hoffmann --- pc-bios/bios-256k.bin | Bin 262144 -> 262144 bytes pc-bios/bios-microvm.bin | Bin 131072 -> 131072 bytes pc-bios/bios.bin | Bin 131072 -> 131072 bytes pc-bios/vgabios-ati.bin | Bin 39424 -> 39936 bytes pc-bios/vgabios-bochs-display.bin | Bin 28672 -> 28672 bytes pc-bios/vgabios-cirrus.bin | Bin 39424 -> 39424 bytes pc-bios/vgabios-qxl.bin | Bin 39424 -> 39424 bytes pc-bios/vgabios-ramfb.bin | Bin 28672 -> 28672 bytes pc-bios/vgabios-stdvga.bin | Bin 39424 -> 39424 bytes pc-bios/vgabios-virtio.bin | Bin 39424 -> 39424 bytes pc-bios/vgabios-vmware.bin | Bin 39424 -> 39424 bytes pc-bios/vgabios.bin | Bin 38912 -> 38912 bytes 12 files changed, 0 insertions(+), 0 deletions(-) diff --git a/pc-bios/bios-256k.bin b/pc-bios/bios-256k.bin index 26f863b60926cb5dc768cff39fe944c9d297de80..e0796344dfa58d4d77f742e8640cc848c01c9e87 100644 GIT binary patch delta 56234 zcmZ^s37k#k|M<^yXT@*_gTY{MF_tt_w#m{kV+%D5V_z!iTE5?u8IdxhJ5!F^lnRfw zZwaMRw9RrWW(+fEvm~NIrOvq2glysd-=A|)eZRlISMPhyd6v(!eV)&=oaaorxzV}& z_kk+ypr>?Jy>dPYH;jEyJHjw}!a%qk#>2m19y|(zR@to!X%gmZ{3(< z7?TqX<5_5!WEkyWF+2xV(Ca1=zu7SI;4J7ahOrHnbv2C8ZiewDbnk8$1#q#4VMHby zMm99Lg<6D3@HjN-iCowPM_^?y!}u9)&AFATf|ucY_zCKy7)Cs_f!km){MMIiKdL{? zFzy~;7()jd#*)F5_%_3M4LS`qj3np|DKH<_!w>N0aKrd&gkjXppf;fwJPL~;=NomGv2%)p6Lg)aAFb3{}2VpbZ@^6$1 z_JU`&VHDnv4nXGz3}Yh{K{bqQ`WfL(A2R31$Wji58! z23K+x(=MiABrHKt0YaWcf#8{?RME2}w!$#hz@M;XrC~(9Xc#Bqsh136Efhlfe+=V+ zm#HPFggag_j8~utTCJkm;Q^?GF0azV;A8j=;Kj9uu?}{_AFmlk$m`@7 z;-DLhS%IPm9DyEtDJ`6UUSAnTUw9rO_8}MU%i-rk_!54B9$(W9 zp$sDTQ{`|!T!IG=7{cXgV>YY|B9kQt>0)4=vi$T ztvjPDI){6{Gx%b|=uAIk_ zkPVp~lra&WgVN5*FmB8t!i~z91Lg25T!tly%6K$M8DGJft_bd?jCRlidc!~%1{&7G zyza_)3f971J(Tef?1r!5JNN-!PgX|zTa@93Suh*2a`>4C4?`~G!D4s=&6iQh=eGJh8T#2 zIEV)qBtR!fgf7qndO-@L!5|n4=`a$;zyz2AQ^5_hV0KU1KZ~2{G!pKQKuCkxkOwPa zJ(R*%V8JDb9zaH*2MmQNuxlWtgL#9gDOdyRVIzD1#qcqt-9`psD5T#;`;X)%4;I5x zSOzQM6<7o7U?XH3hOsaNQw-B;VK<@-V=#<`X<)*CU<>SrUm>hEHUVyh(J%)*Py##Q z=Nx{{L9IHNSxAI2@BlnopK(0~BLPo?4}OA+FtIW2@B;WCwh5CMSO;TTFl0mRc*A%X zw!(Mt2c)(%j18~@rnRE~KgZ7-umxJRHjJAf72NOwtbw=TJ{Ki~7vX&RcnF>Zql;nGhZ~@OmmCHVZr+7U zklocVyzn1*7wUAQbkG?dhL_+2xV1ax7>ZzI4}(6>91z}tk6{-Cpk6Y~3cX+$Oof?{ z1CPOTa8yK7gE){0zPoI}Q)PQaAv8Qz#Y8hG$?uB=<$RU+m5|!hW~_HT$7Q zkPHJM9VWp%cm`gE4`C~O)sOc7k(-cIrbW;Wy1`KJz_CK@mRCV>fC;Rv)EN^Qa?uou3AhlVj4g7bFbLUIm2x5Ffu4)b8$9cX7d zo-hsO!E$&DK7rj3HXKERfg@PJz$|zKPQr)`nhrjLDi}7BZaa$Jl!;!!9q<|)f*duP zDuoF!1LDUp34#7F0wzQGSV}XFh;Rf>L$~ofLl!&(??E|y3yujGF1Q8u!)2&9kwQT~ zm;%|bWFqbVIyc+k1gJ^0F(knqFcs#*64(gmp~hquCvXbdPNDn3qcG-9su$jb1K@`i zcVTwnK6nw{g1vC_-DCpZzMJ;{g_|Z*Xy>kJ5dMIu0x|+qo}@2>hLESo4D^Exco3GtyRZfJ!wGm~ zDcuS_fQY9VqG3KPfp=gJ`~sJt`7`*z-8s)Ph(I}w!tAxw29!ehYmAWa1ssOR*J+~H zY5(EeJO>wH);a>gCTR8sLp9{X_wcVb857_QSn(E01m8f)dNdsJ;5pdzHkNb)HTod~ zR3Qoq-HPZf@B(au3nh$*J_`I%4psIMV=}CTH$KL^!tap$32h4Jpy4K_X7DcDRK|)H zzJ~Ez5DLx9=~}QK{BpmQT7XBlF=d0n6_{dhRMH$!1d-cm+8lm{!Nc$dyt{*C6WsVI z)%h8Teohzqg02QrU?wd5lJ!5_x{KizRzt!bOf|d;Ti`gnu$NN8g0JYFFn=F|7nDK2 zuZase_wthq%b?zVtQ~ZNE%3kr#)WU_r?42#!svtaZODd4;aPYcw!l8vb_fOimga(? z-%}`vKFl*Lgc?V%EifFK9i{y{9;KZj0JVQ$iUps;acKP`Rt%QI2KW)KK>SZ+0G@FV4;bC|IhE`Dm`1m+g z@5dURV6=o`Fa_p=39U|22B6pUbbJ{4xe1_)u99s~D40FuL4 zlEWS0toh&`cohzS9|p0U9|upustDG9JGuD|&Ok&YYd}baA~*xJY7hYyL(Q7X7yvV1 zJzRlE_5m{BGC0`}=m1$z2v4v#@G*3$s|+u^0EJM4{eo5SS$)=jljD^!7v6<|Y#JV$kLl-tRhQcZ+hc6)KJAVFz7D==njD?48qH5p>9D|6P@rTaP3+{u3@Dgl?1K{Yw zvK$g28**S7d+!7fTi=mlBuH57JJ^^J3EnP|309^Avm!fOsA@{^+P2dM5f9QO__ zYLu=9I@Ah1d4w8MV?`Y!D{|3=c`J132z5ih>yLGe>?qIq#JOP}E79*rDjh$mJj2^y z3jPI8I06w&XO0@@0|84m0+P2s(A3-PtC3El*jTA=%uuuH937+#voilsb`x*22`ls) z8S1TCiJHjcl-Vp%>&YWkQmszc96D+J!bml^@w0UdGt`w->MZ;qVhRu5PA=z$PWdU% z>dPZlC$(I67^QaSOi)|$cVxB8C>R@>RGNJ7fo{&izN#QiIg)qHNyw$UWrd{pPv_3N zVq~B5hbQlPppn0A!JyFOopWnC3kNAxmb~*pDN*@u^+t=-0-nj*hu$dha;3+0nC~UN&CEw>U9S8NPlb z;|+CrwuV-H%d@k{SRFOoX;jr1toM#rEgQwrcB3;(LJ8)Jm#}HBXe(l{t~Eimn)D+r zc+E5Fn&%fd&M;=EV4TRHbF5W_b5dY*M$q|c=y>ZDoIP9P{S7^(38O~@JtZ;g@j==< zLA4n0#ci0v=L;k^ehqCMWy5MV8TW4@zT%L5&-`-icx1axH-l42-orQmz7x6oQ z-z{mbkgP@pqZQBFZ`0KiRF@nnaWIK!5puu^8G;H{j2Y*@D|cQuBWnox4hBftV{N`3 zSn@;QuaRn2TrXPE9^9V)??CSo$g?%tU%wzF!A=TEFWC{3O7-fADn9N*YSeQiWSZxE zNLGWSQhzgNQHZaP6#1LMMTaMdCZP52qMsVbr#;75dgGs!?6>>Ed;6$SN?zIbuc8y;Ia+NBt*J!mNg# z-Y!(r@JHnKUiG9dze{y+%uLq5-KEw!R;B6Z?pA#r-TLZp?^f}Sn7;bT-Kw3#pQ77M zRSAx=6g_;ZigD~s)%Q+SE!2pj$ET`?lzOblF-^5_sK<0Gw|XsRV;@F@YG=`QTYo2w zpHx+Gi~iP4Le2Z@$myz?Bao)sO;-~n!TjlJextkD%FRESRkt7`)L9g6UKl@V^2Dm! zlZzV6Q2$biKU;x-ndSq=SYOJFn9J+{q?`q6i4!{y2pJgrPVp|yLuh9V>VmE@9K^G zREB*Z)y2Qcu=P*s=kHTP)l&V-eX47Nj+lP36J43+iorkB+-1eysFP-^Mong7_{WXS zFU_u(+{Kk$+nXBh*&0Xrf9b66nyrR9%6jXKv(*g8XT5dY{VKLe{f^2gn5V>0VqOkq z#ZUp}1yp;GzWsjXadfy{@4a6ob(}kb!Tw}=tu&z@I{BQUi;15Ze8Tr`)nS;^Y>&$kU+{vz3~Cn+VT2uz3%~) z6f<`yg(|1^wsJ!OBCNZH>n3wlsblx8`rA1w_Lc=~XiuZeZBrZ-X|5K^JZP0@%j90XdHp*v@xM9oI%(OIfZms?Y?PvdquF-m(dQC1g(jIC;r zF3D!aTC2Vb1h{efstf8E#f;!aRdt5mn57yej%Fxbr?R7b)lcB{90~dxdyZT(%L`Hh zy{|COnp;2U^&h;fH!}3OEY-1R|AT19c58Yd5LncE)}2m6$gbtSAwUY&)G zUe3AEzQs!s&AiVTUsal+CuXZAO~#TVvpm1l8|BKb>suz-dS4QFB11o&t!}Qp1c%lV zV^Y=7481#Bwaba49-`CviApaR>WV5D>543twz8h1K-k*YHu0FMNt1ia#hL#tekIHo z4d+eH!t+kwkw~X!J8t;_XI?4Sq&-PHiUa7pl}RbC>Yc$gmN5B0Vb;TB^OZ3?PD|&5-P8MT|jg&}6^an#K9N}R`3X7WF zMoLZNZ$ie1kiAy|0Xs)yQ28d1Dc9J#)5nGFK22Quaes^6m%1By(Ys zIsdiHp^rI;8Q>|8T=b_wfwPMXX1St96=b=hGOt%4Y2;etnA?pV|B;J_MZH{1Msnvi z9rafj#-&`Vn@j?og%eznW5y+&E$Gy(Am1Qwl4mQHbPDp-wZ|HgZ1TCBgWd)*Mtf_^ zU|cMrtzR!Q0QZ*XI~ITA*&Z;rIM;63d*p0cd{(HrC8_k>E_3&}-L37h-Q3dhLhcu| zu|)jva+5&77tUCCt<}~b$~FX(C+gp`Rfl?*7F%UJTcd1Kw>MqiFc-V{z}cdqbJf$z zaruls{Ghtg@!1(2Jx|RD$2?ed{?NJeR7?}OKXWD!7)Lj)?>jI0ID+c1M%=F7nWrW@ za?WVyeAUQN_O(u!ui7)+8!=xc)&6=fYJA@O-8}Bjou`-1R}C6vUZ99~Uz%9H=(1Zn zMSVLni}lCzRa2rJn6H}mCpDQx{7yxUV}?{BLu~P4T&upv>6$~XID9S+WyN`NU-mc8 zycN3VL#mm&sK-8}5*zN?L$D*(S5%5vN_t6*_4Xe9@vd=RQ=y{yZ)A1pobCzQd8 z#U%NgmBf)U!|o)kfEjDfjx@IvzjG_WJCf7@|0kXWv0@r;W9asurXWGHxX-FOt=le8 zE|=6(U#X|Jm>u{NFtc0C>cEP{IOUhluYu{SaZdkxflBT#A?wqU?J59qlQNX22V3N4jsfKCwXcpc30WtZwNnCgN?1 z67+mpCJyB#%Yx|yLG|Cs)@7deYK5MGA@`Qrc9&@A699xA}At+ zLj1{e!=F=<5R}nZ*Ly@g;Mn)2e(VvIkRvrG6HRNNOiDft_`_B|F@;PY7+)?!MWy+5 zu}rtDTQ1QOST@YsVo}M@M1AXv!E=-X* zn}K>VgFA1%)`@(lhT0C+bM`}I@ZkwvnWG+x`)&Y@P)Uxan%|XOj#_-+=cz0ywk?dY z$_MC)xvFzaMsJpb*(ZJJQk^oqS@#dnFXyWE4IAR~)083EeqW;a4HUnd2I%i|)xCE- zg~KLs*w|kgRgGzMyUUO%%lf^8GAjFvf#VW6J?BWkR%)`lA0P9+(8>t$Gbcv{-K(w5 zdf6g1ylI-u*ii1-jGg}K60v^vSQ}|&tawz#pk@soRbB50BS~)vqh}p&v{~O{MOlrj z0|EaD&%>@zBl{+AModyE(*etJ;4EYB#ouU`YU{LI&RZwsa=^2-lU<+R|E8aNRCVYr zZ^~Jkc?ZUL)7FKqi_S`vnBU<_Ld|?xQs5y{;8tk_JVig+^eN_UXTTq4O>`Gv8 ziuz!M{w|L>?X&%KL_Vf>_(|P1UkynKC2{iN*_vqA!XF5`dM|y)b0VJZv)BBhBsii_ z+Kmk9B{C6|;of>xzniZ*q&rjDqHtH|mz6Iyd3&`Qg_QINu}A=dH^GXQrA}*Y|;RCVGQm z^%eDsu*{xZ3W>q0NeV`!L?Vf3X(=AN@W}9kp3RL+HxJT|P8oB@hz(#eZ5SA*PA1$Mr7uGo~p}TY5y*bg8U1bRGXzq*OAu<6lV{KemN5TI-P}tD5)pDpU1$ zq-kxLs(qV1KmW7$B(X~;y~mpxZ>9yi&YBgv+Y;3^CY!YWZf?@8^S|hvC8}B5fe4Wf zz55s2uMGc?KKw;*S)wK+ER%V7dsNPz43$sw^zOk}m6F|7X5~et>F%`> zAhM?(;8iVEm3Dj8t*yqzlBgI?o;fSbv zi|+k|>YLhiYfwL!7Kh5nC&N8k(S~)es8fV_(Yo_TLi~PR*76wK>;BClPnSKRVsmbY zK_E^^u;$J@ILg1k43L}V!5Yxr)71F zE7{KCnIdC7)v;P!R>{w~U1e4ad%&+S_ghUUldP>TS`RdoWmHy_?_23oZ&PxAFSC4I zXjWXoXjy(+!wEoAwcWEt=#xEkX@P3gQUd#=npUx%W`m;IE9~@P+I&(q%lQzA(|UJnnmyAeF(}V!aq*m2S@rpiBCSr5#9N4+8}A>G zbjVrwsjo&buVGtHpyYoP{XMJtC$% zV#bYSYpIs|d3he%4u>&|uTN1tCn8zv?oW4r%zVndRf2>O!aPuRByte#7=?*@1gT~P zI+=fVUSDU?uRa-&Fi3uV|5K`AyT0|PgdM&nLC2eUvdv(3JC^?=^Pp&C`-b|Rr%;sT zXy&xuq2bQ_=joH9g2^6`WM_3lXT@GSi?&(o2}U7E6XO@3k?uYrK?W1V{N{Qf*={F< zzjlVZb`88c;5~Md99gnuxRJ3q)U_lcWpTtUp)PicTv?e3QZ*yoZ6*AlT_q9cVwR=X zBi(&X<_Py-3A3LtW5(HqlYBK0nQ5+w5*a_QyLQ$uELGi9qTaJqwT_r7@kVsjmzJs~ z5liGDsjF`Gv}!#319_;6#3gC2dW$0@@AaI8jEw2-Z^Y{?Mr`aPXW>v+_;uNnqV4*$ zs=Cm_JzFE~?&3Zx!7IDy$DdYadv;j^S*}Q7bms7Mx2qcz zwNEEMqi##-@3h;?HV<@EtGW)|jakh|HsjXsiYz*LR;=4yei@vQ1FBK;pSqRWm)v*+cLnW8Nt32*a)Pp0Vh^AEL25}V`ebj@WK zE(NLa))ysW7_C#^>-=Zc4eTku|175NjNbRGYTIY36l~~CQn2746Wr|arXsY& z6L(I6FAJf__`VUl{;4%G-H%DM1~=*CWvbbLW)<`yhOLqwgu?nCu#OWh_hDBZ!Dto;DGM1T*ax6^uXn+pPHwaELRCbUL^dLo!J9q7DuPu{jHdz()?0q z9~$q>K-dpoAEc)BE)f)R~4z<)Z~f&j+ySU;v_4siqu5IXU}G;t=hr7n5hY}cbCkl<;jv)MrOEy_?s!61UDhu@r`pFp%^a=+J;FOa)Z-8JA9E**sDF3T zM@V;qtbku3XP&K7>>4>u604#nI*o!sYUYlFq&>mDhe38vlz1)0-%iPWX}st1C1+j- zhM;MS9*GGJ&vrTs`!}9hn&4%x$eb0TM?bIbk4vsW{V~;H)f5w+-JwL@#9+^~iJtP%tA6)H60E|r<67*Me?_}Zyeip@2})V0 zD_>B(8Y01EWHl-du$7%$T}=BKjn6-z8^6fbd3>bq|Dx)glQ8o@LI~Lwo-Ga%%HdU#B?WU9?JBz%x_Gzes5AFML{^OFhuXOp zL!HaENTMxwG2-~+2v2ZQk@rH@KvKvnbuMT3pj4HTewU<^n`Obya!mGiFhXgr9=N-_ zb6mU)i1N8`^jvmiMff}TBm_M?#~y^tku=7zP{~C&x*uiLBS*;2+d$ir=^lnNPv$BV z#^t%Jvbuwr6uZJ?8^i zv&>MJKL=+P!bpkyo0M4F<*c-?^hR59obC1lZW#S2Gs>3kxe~~#m6F}4Z*~mn`CHP8 zp@HmHo?fm%b{x}{`$c8tl>JyXmdJ+G4K2*sh0mkZH*90)Oe;hiNrWnhPJY-b&jQjl|K& zl5&epiAGc~eyA&%Tby&^Ni1|uMxe{vFaB)^cE2te??=WNrD(gE-r(5kDGhk`1kk>y z`iSGzSCsc*SM<5>J^PJwht1zxmQgP)_mlHbe~)Xvo{E5He}J^&$U?lTu6yyC5AkyB zh-EE*mkQn0@;o^V^)8^19a+2*_D^*dMc8U%%|biO3i?GNP9@cW>Ojz4E76*(fd<-v zctl5~x~=*6dVY4^p8Y=S9gh|7Ie#RpmS-M2i?4c9;{7L!u??tIhAVxP-u$v^n3HC` z&FJCT8Y^Sf5Sq%H9vA4c{O@(+MX^&Fr@OzEDyrL7swk%aX2XcTuK1qIA#q==t-KGyfzCO;to%ie1xx_>5&tT6OzX8)}FB7cTDKYLm+PHhh;+^@%)>ti$t* zJWHEe-9HEf#+C$b#lDo4h+Z|`J;&v({R)=Y+icBpz4jH=yHA9OxQQq;3^#A9uLQcv zE_k4;m~VFr@oa#nXKR9;u@;Dw!f&Ex{1NV+I)0UEnX~473^@7rl*Y=)U@g1)Z0+NQ zLAIuQoCw;~oG~oTHOLx@Gi@1zw#MQx(&`y>u+`5F;S>i}GPbWn9ztD&4z-8T1tKi- za~#Xf-K(N?IOS;&qjkk9HL!O1q8}+~srkLR-<+VEyvp3K{RY%-$a?*Pd5Z z%QSgtu%6!$EX>@`ip0A(mO}O?P?9)n`LDb>80m7`4~u!A9sRt?-$)es$1B6-+Im&B zXgoqfW=Lm@v@M84ex`cS-Nrlhw#P5NIHW z0c1|vD;S_7?}w6hmu-`mX7Oq<*>QXXRCGWw!sc{8S+a&w;9^_|Oa&Kx%NxYXr`yJ-!I9)UOg@UY<7fuHAV5?Hf_-rL(OgGmIlvseeFwiHVxOE=fwTBlODc2QX-LOb>}x#lZNyD;kPX4cekGOrfSx( z|3CcJ1pN~A({HMnUQO|d-Sy4%QMx+OQQ-Z!n^wBp} z+lD0s`YTs5$dIcwy4hQ*Nh9+ge$p54%Q~kgzo{BDOAJ0{{v%A6pkrU1`<9BS*9pI1 zl{OE$r|Q?$BN7y+R*)OSNuy$u^H@V~j6W`b2XY!zyk<>)u5H zONJtXuK1^JvtG@QI4$)%x3ONkUfmsWqmzfI#@hL|x*>eFJRH#d-c|{9mdO2^vKM#2 z`fRJ7_cq<*UHzZ8nXmp@g%)$$XN+L<*-2No ze*Tk#xOpVbnE_0;DRGy|=3FETl`-SXWs{sYBvv+awEWU}_02Lu6-cNV66$=0lVcs8 z-g4;7$exlZf*19eoH1;2_8qoyv>xLKD)Rdl%!w|M8t`c%GYlMlQ3Pglcq(T|Si$gW znI%9ZSDeaD`Qy4FV3DdR&4_7e-%Nt69!te3Z6t?GupsZ!OqQ36{T zSXb0~J9L!0O5$uJ4mJL(cc?4+^cr(PXmHVfz#5^KY*fv2JSU=9N5#0jvzX;( zv2@6lj^9%`^N*s`=BL)aO47n&+IrtbQoDkObqcvvGG*~TB@viuhMMOCdNKFTqQ}LF zNRbSHoPny>1R!{ECCmW@Yg!Eby)E+^fpsF?G5B znEQgXh&WbC-kz*yIUsx?d8hNSVWc`@xVx5w@$qKCvo$Iy;0@_5hb!hrSc}Q9Kg^mc z`4)9-=CgC{lHS^zT-*71YcrEY%wso0Og5YQq2$<@CI?2oH1ZHHd_zPjNy^DtE# zN)tq$USlW!_9ouYQ4GW1kx6$ub@c^NSv5UJoZh(nQr1c4sp7iz z$aC8J6AEduhUI*swK=9Q?W=5uU*mia1cc=VG zd+Zkp*08H?%$vpSbxAP!svBisu(n!d3m3HdA-pqS&h>Ka4hgU~$GIIj4Ho8{0> zygk8dgr%@wG;zdjUPCf!FDR_(I^Cxl)E!zZ+pyL0CA8>y?_xdIr+U}DQWSKK3p)Q+ zq__H1pB%UQeM#poH0ZDMegmvAyxf)%)@{Ueiz##;4khRtoNK_R2XbWI+Qa&8 zB`s3HCO{8t>qYBd@>q^)=O1$B-A`-eis{ajn+2+o^Rc1a5nuMz1c;e^gmtx)T~8@3jQJiP#l^T9>h$wrbElup{hcpwS{I z4g+<>s`IX`iZj`xGI;4-?!Jq-{-z`lZnehG9;Ak`uM}zU8t-8dJPg5O{JmxvnI$xc z(b0E5zibZoB_C$_*fD$@5MMl;kj(kRipO%3?$#2qL4scJiE7&aU49km>f}S+LB-j-b(g%ZPMqp6!cv zf2NykQk^32c{UJ8cb7HLw{KFe*c~D&SJZ2QD>}o9kiZA5Q5*G=O=?IaFJiqhfBeK* zkxeSmaj1cIZsx4W(WiCi&8kH$StCs*sx>b{kJ+pq>`U+(5*&9a_@b>(@M|}WJt>MZ z%SX8VBsilcM;q&8S|;YitdvFnq3pWeW{Jymbg63WXi=a$ma3Z^zctX4OH~uKOg~hr z;_JTigtSDKlWpUREFWKfLcdk2nr5CCfswRFbh=f@BA*_?+|(+hR*=jhk=?7B9KU2D zxM{V$;-tUP#KDPLG^@Up1kd^C>{jkh6v%xAah4-Y$CasejUTIH%;WXEQ8ke% zNWlojl48_qJ)ulBi>%j>S?77ns~452zIApl7i}nr3CHQ^t9nNHk{-l8IkxnoP&0nW;m$MsmHK zP7ssn#?Tuxq6<>Hq+2hax7C1iI3(VVNo^Bc@ zL!-4>)TzuDy%GmGm1+&eB&}M!LLb|%+Ql{ek%g_nnv1idazxdtjj#36OO`Kl9DY)lV8#h|2lXWX=A$zuA2Y6&H z`Wh#b6C>lVfW>&W*OuGCvh<-HD!$fh zY_NDL92xFY4R!cV)pFWTWZzjNDK{o%`%YD)%0A?4K?y1-p`mp@Q8$TD&QcJeVRE^% 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 delta 55527 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 Y6y<5V%C~dfWXxb^^xt0mfU#E|0EF;D`~Uy| delta 27963 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 Yx_XuR>ya%4!NEZ2@`x1C+ee4~5BB~uaR2}S delta 36570 zcmZ_13t&vg`~QD-vymWd5ClQ62!cdILlZ*c(z-1n;;yZxTUFKCpdXiwZqhndTJ317 zdR5wLwMrGSR6`|tEUM~OTKjuFXG8n>eE14>r^^9jpKY8fjV~I0yp3(pb~#gBGAGcm`}~ta-F!1X{&v+CuOq zSP!m&9!)fD0eBQF0iS|JO*L&Z7}ZSE6bO&gv^C%mXw*W}9N;N1xh1^7R&akjf5E&q z202pm4pq-}q6ErQaqoz#@kfFN5!rHSLien)b@An${#$)0Ts$(=_cIXq=9a;Nji~>B)e&9}F|8DOd`Y zf%icPI0-I;AQ+gXX`TC1>j9cp1!V`DV!ja*IhtmEez@Q&5A&p-g=j6*{32Dk=X;}Hz-UxTy<=rZs)SPwn`t!HT34B!SIgD)P`v>`J!t@}gh1*ig- zLH~zog@@_?>jY-bqQBjmHVc%1Z^6%?Wj@UaHiAz;+-yzD2ZuqQIhr;Mi~`fZOkkM{ z9?`Us;AhZfo~Hc(q8DgdC-CJ$Mi*tS1baaVmOg3HS*-xJ1*AfLtHL7aRj;LHDJU2RzU4^CtKR z^m+n?dJ-L2rfKVxruALU_K*jKHUg)? z(;uNgU=R2LoB%(A0O(#yzkvq35CUX?zd^&@bOm?_%moWTzcQK{*vd665=4P$5Cfe1 z5gIH5Yrr87KRl;Q zG3eifOyDc7x)Uaji=V&EO?_8lNa~}#I!~c zK{0p@YyiK34sGBAmV#}-bDWU=KJ7E`n}tX$^2Ucm%u()`L=T2%HCD?Whgt z1~S0yU<`N&_`nLV9()Ks2491}Ky-Urtv&tUl|X+mAG{7Kz%Rg(!0-Y|;1KB2LDPDJ ziQoaS9BcyLg1m8(69?F-^D}01eSm|!71=) zS4}GeUw~VaXd>`F*a4!Gks73dQNRQI;5eAmjRHZ`EzI$t2N(>-gFKKA-brDC>P}_A zc<_LSpC#Z`@IEL97l5w^h25%Y37|U|07}4h&?XfZ3cL*71Lr~Qp0pGg24(;cSOInd z16%^C7kv&s0af5S@WkE5FaiU>-Cz+|3qAzLz!^|Gjaq~5U;vm7Hh|;cZ%{KGr3IaO z)0!Zy50wJ1fQz7h210`&U_Mw5UIrU8=>P2m4uf0z!lWOQ1~>w$z&S8DlRgK(f! z0Cs~TAONm_dc&zXxC0z@QX>#M0%1Tlm;si8a`4GWx({gC{0CkJyTH%jDzJ~D@4+k( zH(GoFe&&IXz!{+BVE@5b@IE*OZqKEb;8hSgmh|zo0C*g%0)B7_q)xyW0879Ia2`yV zi0K6{fcL>k@EeGpM7hB8K0l@47tm-j^Yj#I1IFBm^8pkn0mr~8(EKj!JeUi<0KM;~ zd%zRm46se5=3os-z6XK8z2HA!B`5(OgHxbK9{qoN9tw3Y&DOL`FcF*p6CNQQTmuXLLkoe_c?bhegX3=7~tC?1b+;n zL6gTZ(_j+#4g`R8F;)|F_3&fUvELwk3DYeo0AGVs;4-lJa6CX;&>IW~KY)%)>1&Wy z%=3Z_3p(*hrO8H{m=%F_1H%n80pEf1VE9HBBVeV6pS|FY_pxT+O>hBNH&Hv# z4s-&&K>i0PAUFno0PQ!Uj9_;OU9=7T@YCEN56lKXfWJWMc6>(gI;aFk!1v%1@TBaZ zCg4Tz8EEz)J{uSTrhpk>71#hi1y@0>owNYx2j+o7@G{s3j)VFiv1S0HN)c=q))jQy zjR9(I(Oy4pp&2Y%-ZJyw=Q`YFX{b*AZrk)z(<8O4A6!r+ZO7C+c%iQ5j$HKTUKQJ} z^S_>kwQC%+fwbbK)?fs@zt^q=gT}6p)g$d5x4v^hS=(pUPP<6@IE&sq?V@tFPp+MM z<2m)BTH1cf=+W7}L9zC&xs5CbijKJ372jb?F70{X;WYb}ewN}PR%_3%W_2leB&fN= z`Ud_ec;vd4e>qSClCNepDIOuTM`uUdw~Vk@_7ke1?+sX!OUJ802?^HJ^XlP*#G$F@ z>uP~o-XFs3TOO70__9?=$dIlvvgbrqhR>w}5)RapsM0wxH={}`!{>(*waV~ZLTx&! zK!Urr<7zPIi*e}3j1FpAhxcm<2mMeph*i6eX_gXocgMk&l1=Y*Y;I}!**?r&KN$OL z4sW@ws+?#0R&Dj#Np`L3_x&o+sa0d!0fto0HXBs_cp=SlL>s^DS8Wnodk*aXCk?MW zl(vP)Y1%YPC`)80I@WlF=;Yv->`-(yb-b~dXm5FZppmyUVa&)-qLgJkNW!?Wx#K5I zE*m{2Cp%j|uy~Xs%)a%UzXr+rIb+MgSiFzud|UE~!0m-6^6UFkLJ40VR9`1HtzUYO zk&xvGb2ly?V}X9dK^56KrGeBrR7|vxA2R|6)$q9&3LfoVO zOY}TM-ty=`gW`+?lWX!3qv)X8+_|0gr331l&au{A2h`=xw^|SFQAu5fTDKoio-TbI z&b|1P{mm(wzNF29_TtY=6yt~dCtCdui5#N#!sr+yGI@G+ObvNk6F>}_U;W99?9=q zFwbt8-OM*Drsw5{9l27QzB&m#^(JPDxNhqFc@il)3Wh*-2jv>4LCvASOn$XQ_ z{pq0kzFTthx`&z1&Xi>v4@k?FQT7}HMWy)>#vg}N*IT}CV;72+{^)S*(r@}+<8hvS zs*ox(`Xb=>@ga3fN*n9`PgQP8cWa&f>dBNwsT*j_yvi&`y9{eZmZPObKW?->g2j@U z{5Jk}WG~KgSdGOu=rk)N!NcmCl=dAwpHk#gw2rqtVf>`BqEdIPvF%(iNWktNbhfTm z(vEhoy7!3c+`Vz_;~1v3mi#FH;xlS^_a;$`&p_}p1sL&1l)HN;%TMan?v2}&cd~0n z8N%n5W$R`3E!H&q>}Y?&If$=7JihAIBkFkfrcEEBAe}OOQI7n2{?oz?)2$g{M^xP& z-Ref2CZdgGm{e7ESPkoOdxNPWkwnq|X5ZX8ehz zPM%LtD~XZ9g5R5cuJ1Ovmq?LS4T8boNZsZzejz|jVjTJPL&;LE7?t0zQ*_ylOvfbC zw?y5DI3y7tOT?~{&m_F-Ux}Zot-Wq(xYi)`q;c+VDIvc;of%^ksbH_>xlU}QaW6Wn zXGSMq>UrIrUJ@r&6R9Ar=imDqwf%`6H1?uvfo6U)*-AI+vHHwNeRs*yGFaSBnF9hJ zdFRDy?g(T3Ugf?mB`QH$s;{t{cu;+C+lc-fq=On*=?}B%uVESCGB;A6X)8LDAO2xf zqFvKnQND)DsYj*FA%BXFoCFf8*g zmm(LGqO}>eZ3R4#*|?^v(wf@>3W?+GANoz*c zM`}j;LzYeIWO~BX6wy4HK#afXPVa$WAbjR*(It{4;kqNPztT5h@2 z{vee#_K_#h#Z)FEjG5Xu(4l8KmW)YQoSk6bk`ZYswQm`dpr-e39`}Z5OC|ZI>fh}8 zJ8JQ zjF2>aa#Se(oH74Hb)t{6^AHqAy828Rbvx&GK!jRF8ucaH1V=RH#6jIP{zjfwxfwmI zM=I5_jQgS|;P&`qLgZ1#upO#q-wv5=h+I6xQG=Gr^Cji^a;@Gn>xNqT@w565A`4>c zyJ(db_N^7h)EiIHevKk1Hp&>jPv!Sba10W4{u2?fJ~93^(gTB}W2aTnYkPx%dd8i* z)vmrRJa37ZmA(Oy+n572tl7gzpznUGUMaQeM!ffjvm=QfB+*xlV#u)z?t1-uI#I`!jN;qx7E2F;ln>*jN& z_%a;EBu1PsGr@T7y!=fxo;3d^smJ?GPDqsw{2t~;ODS}KFEiGsc~5@q-D~w_$LiLS ztCBWOIj8452^xA$)uktS62cdG~cCt9tas+agPW~VyP|Ms@EaKQD7Z5WWC zKM6UQoNY!buKYhwziw1L2c%mA>($%=w?ssDhSjH~>iq%zTg>>5@wUetZzrW^0x&Sb zq)Yl4bv{%L2X^wDl-@uK1D`Un*3c{Uul`uWeDM!=jpak2!GA@aVReywMmMS_3DbcZ zp;tOx^Q7!EjNw%ow5B*3zRqhgC*vnEOl^*ZeSD*eH2wOL7E5a3QAHR0*;RcsuxIRP zJk#s>_L3EneI7MkEitQ3tLQ<^vj3p2Yc1|5zgucR$yy*yFI#JK#}$teC&D-a0XnP+rD9FSjm2-Q?V2Ue2|VX67LUekD(~q?+>m{M60fl~S*U891G+Gpc z#068mf(9sfy-k;^c?pt8O4(rq>JTW$*ydTPOwIh0zP zYy#W$<38rlm<{UW?XjK$cnAx7(Mr^PbV!ViBE|y@WWNk~`_?_ibC6LdWaxR!9iQ!V z?GchY#58<$lW5gCQ?mngvR%JOawjnblT4|EM>aeb+Z;9q@Z#7sv^D5U-KIse3nGLM*K?&Ou|iu$c$-#= z_$TzCnm*B{f1-cqtq6L*3|cDceTi>A!ZiUxqc{AgX)YF!*Mr^XU+~Zx-DO?qa!YC} zQt^IKUON&MmD&sUqIMX{1SyQavaZsK`$rXza>N^}j^pe1k0qRFJVTgl$N0klujN`M z?B2tLWm1bbhD$1|MSYYbhKNL?cPJv(Lrk1WQeR>!^e@fi@KACjsZq&ClJ}Kt6m~Oy zgv93153fqVWceB<^4sq=B91mWFe{u-|!@{GEQy zm*!}7S-;|&@36J{PQMx+40?inyhre~7X3)QO7%FC9!@^8A#gm|9rRi>&oN=BL<0o! zmIl2?f?+lX4?<+tiaw6?O>jhA{>pn)yL^HoqFa4x78O%nRH&rNMZcOQ9o6SM67^9Y zM^bfZt7p;+dPBGLd6pxV0^^X+%w)MjRc>TVcbRn4`5ie1Eshen_DTEXZKb(KIa26{ zmDlK+QH~6PPZIQ&$LN9NOMym};ZltJQyDHrIVBkQsb}{g)9l*(HW(tqm@Ij-qX>;Q zL$QPg6B^(xO9*`KEl)K^m8`@^>J_ru!VYhr0w4R9b;s0CLt9(hzpf&Owe9`02=&Ys zQK@J%4=cnn{R>}40xA-2)c%R?oR#2rla&=iSbdMBxw>%y-n)?1cx>O#7DUj=II8*$b#)3})m(Y9Ewlvp>GvOe_sLil&}Y2ZzO4 zAALjpGAu2kgYbTJv+6Lsb@V0%;^Kjk#iJu7d!0Ab_~Fg0=U!KHhxfI<`?}gby#0{o zkYC@QKY-qdWcu*_5DeP4mddy|g*+BRk0@yhNuX^t!QhLbQFHJ{YC}nl(7TqjPF7u< zE#mHy@@Ib_O@f6T;;2i}{+du5OTJPrXWQ}Xg`hhG6`4IOlP3l`<+zSZRBJOTsoLE= zXMFU%DTYj!wupXCY?+Lx$Zl|b z>08xkM2q{Dp$R>kiwfAE=tRq9R?lz8jnnLc>J>$o?2E&RFNqgPd$YbXJ^Lp97iFFo zk9kpfj7=7&6!Zmy-ft4trz{pO43Q|>$7b}wTN=@?{^P6RIWXEENj~v{=d4!0k7(NT zk2TUAvEGxOL1~sbU8|><3gg5Y)pleD>*+PhIWol)Ct~-;(OOgxHL^l;S=Wt)=*>(?-iSU zc`36p39;mKFfRlHW{3q_&?8KR*$t-NeK(5!xFJ>QXrxl8f6v3C5e zw#R|GH;67D(<_qMZK!$9J(7as)cn!SJ+Tom0(vs5c^O=GYBcvF#{WUoF`a57) zGdP5nK9dmm*}gSNKc{=#j_ABy2DYK}AMJ?$FYSoOixcfYv}ohi&rC~Y&KAZ8^a{2p z2~*_|{_ghnEzBg|-B#8VMt|DNzV*%}w{X{5a* z#fFKgGAxJy@4_O+1wtli_CgGdIrDh0Tihw$>mIASf3Z^rLbQ>F*0Q{#pkil~8Pic> zm@Qf1WY~*zvStQc#m;Cmu?~seD?xXjZgWU%j2U}b6sDR_mg}jMsuYvsHL;R1s zpnuw`QtJI(t1lTSwm_0^h$rMv{Nv30Z+~d_rO?euy&hl&OyeN zZ|T3#men!YFqtE@xd+yP-l3Ykq7o;KN>oBtNw?^!MZx?SfB7kBGpLbq3WimOFbV$n zjbFU;mN!)7WQTR^O4Vg@oaJsccyh}I&1k7@jG)j$OnjJ^)Pl*4 z+cz;s+PS=y8Fx@MW(+$9@SIj$DO8NJl@$sO$bUSzX=x4WgQr^H#+ zACq6Sws=uJHO0~B&WSrA}W%u@?<=|VZ}R;WAgjI&0rP@X&6Hu|1p*?*2EL`@($sQh;} zZM5;flBCy2dQqLavw7OW|4K>;CEXW_w1gT?CM)Pi5gCeT5sJ89W!}}+)12tB<8cxK z4d{)!pQA`NM_tVynuidJQYU8*ot*DBjk8gg&L}L+&nsRS zy)7IPe+~@|w^?Q8#_%xvmPz5o+2@G)iLQV$4S8D00;J5tyinhNNOo0w&`cCp<-=)o z=C~$EXZ`kunBZaI`geb<(VL4DEK(sVtM*6|OCA%lMTg;4QSyp}^9f^93j4xNRMlR1 zDD-p~qK-UlYe^X2y^em)6MS|t4?eFX+qaH#wCQ=sUQ`1jBke1gGVYNu#$O^5 zek9Rn5UJ{C$>Wne;&$oBg39CqH96WQA7P1A$9S~@2D@<`YZmm<@=vok2;T_@Esx>b zCJ(||c}1Q}ZdXZ($ep@d+M^_6GT}tRma>vkiH|2-oD~+wVN)K3)w+DdzV%4Y!wVaX z80k771Rvu-(kifTk;l|qt2ibi4};t$4{O|TR=5<@FprtLgMF)%o1SZ(9buFm!>0*1 zUdiFFIiOpHs`#T+F^Vc8qs<6ADi)!tEs;_$Mw`8m11?<7SRE}1(_-;hP3hO^c4JQIc9l`4shrn#$6pTYcmZP4`{Pn%3qKRy7v?eBg`GHs}etzczOV(p8Z1gc5|B=XU2c_=D9cr4ZX>z~k&4z5q zHtfUxpJYq>yfA%_jDb6iw=g(?N-5o%_O=xMba%Dc)wzo_#hujeg4E^1& zm7!r;h8;2wzQK$ZI#zm~a`fH4I`P=5;=Y#E@fX#m`%-hY9+c>(I~l@pCEsoqLl$o? z=8j^oWTh`hmvb8-oj*;a-}4lF_FS%{)|$I>=m_SR(e`6mlb$orL{PUzAFIr1>Gi&( zlbRN^qY)-JY?kBV@fNeBks5JeI6xh~KP@uz z!(hItD^_No!n@2IKKK)#rZwu@@b^rSns+$6p4^|rm?bP5|%`6+#y|X%c9KMVc z=9?QQa6V3GtCq^}AVxps-5)&?9kdy{iK~vOFENqE24YHTiCTPzj_Z}V>NgXAfN zT)E?_u8QcaMK(y?O_S5W_<0+4*%b5vD5>v!2KSBn#!%lcu7>KnZBAU9UF@2Ot63x^ zRupIUWl9R=>MFS^*(y_4=CqDkLnOoQD#Ih&b&g(ltxZ*3<~H`^i3huz1zJ(*BQ<;t z*D%$L(SJ8x7vtSM!C>x5?M^mE^~{*!%mm%$ap>m_9gnE)T^pGX_l`Z`zROd5|A1|g5TVM3(ZGwWnNfOnG^@wRyvod`nl<1Et({^Z zg5=zz_|bZ1)4X)e>aNKSlCw&dXrTp;IEc_34AHa*-Q}tuirgBCjQi(;7nHAc3&qBN zB!UJOd?ck5XF5$H{i@+5d2v?Sg@N8+O8&1>fl-@P(tl!FFw)JARvX6F8gZ?kVX0=Fn{d5YOzZD?UB z=uY{Y=`hyF49He!x)T@;?V-lv)$>P+ z0V{yJvEm6@r+rDdgdb&m1U7m12RV-JZ0>}U+1+NBQPX=eOy3=7lH+<`E ztA6vFSud|tljk>XJ^dZ3gY}ooSW*5%Qi9Ctfq^|MxO;Zqcx& zzf_m*PBgN%tELMEcKTg(^-gPw&1kU&9y4UQ{~Qs_%C7BXoR#4#E~wu<8TC&8 z{;xcZO8S|38ki+k=P^sW_@R2BAYr!7i z_bvXCTE8)yy`9iveV0+oDRYwRZ{fR+na1?IYF=^Qo9FEvoqs0>tS^?C%_k*>x&rBo5fE zw^3Se_0gi{9uCMLW15`rLMbCg)^4CAPquFrCe8aEb0S9hnFA1*W2s$!Pb zc3Ot!4Bi$`$UMd=k$ZZ^hm@|Dt#;rShYok1#ka_Dx*n7gKX{yuKIYwP!9f0QPx94q zTvQVu?NXyy5@)EV9&O}VC&AY-C$0}9G>9DjD_DgRiYfT*%;a?Wn?LfOqp9fkrN9d0 zm*w4j6!MR~?1!JoPjwv?4mIFlB(TmgZ%MC~Gwgq^L5B{1a{rnXXzTh7>MBn$)n>6e zpE|e%Qu|0>-D(=HJW{;;~ zE-hf+ve#UoK`@LSHY*hWI~DSrdz~8wVU+DhQeklY-C*!iW~{|sFElOn4n_Y;bg1T4 z56ME{oRP#Jxgno4Q)_J9p>{f6Q)F9!XOTNDFt57FzWO(LOx~h-F`6fgz4K6m z28vGP*KsW~TR`#!`e(b=$x|v%vQLeH3Q1{ZAei7Q} z4ppE6CC?R2cZ#Mv>DnP7|76ocqUq|uqrGecsfn^Y-@xW;m~>Iadpp>|ZpPFhW~w(S zt^~C+m2j*T)^GE)y_7pMS zTH#^*%Hx2Zmp#XQ4MjhFb>y0UiTK9GL6Usw+{9m881IopeRr!r3qFY~k<5l7)n9|* z!9i_MA|55e6zih2!8U5FAC{vEcNF(ldr2!yxj|7U9g63KqHOgV*{@qzAnjV(vusv) zDB>@?twrgQ79^+ranDk8VyE_pj3D`SIBy^6CzEJrC-f{Kyd|;T^g*1WY55cETbtM5 zInR5o*=)7uSxItzsWy`FL8B zeh=e7$&IJI`VdE=Ie_F`y3@nziN}Xp=jE$!9`Dt-pNKu|ZRD!Jc^B=2YsY-mWwEbe zF=H*Ee*_cs{Lo&=Ib(@ieX_WfXN;s2I%GuONXa6K#`4&=_O~&ia3h#aPu{$-J6)rs zj7bY+O&pkP+)a;GH|1$*$}DMwL!<^Woxu+rg*@iC7E6{+M4ApLJJGKfXGSxJW!j{? zdql|3W+6jnE#C(YykI%!js9beIU5;;3}d4at89EfmS*-MdGk8d1FK}Uf&XasL80_P zBtjY^DXHoZRDS6vW{^muXqI}%cT24STsaUnJx@JuEM(K1+LBCi2_N zy7O)I!qV2B=HHoqQt1324ZDlhugI(wSv^j`u#Vf8*0Ua8~GcBqBq@)Zp6}|vA?lIhm~?T(WiJwt(Bze6_Y0x zm8xfo<1KB~mf~BjXTDLt6{ob?`i%@X4&Y~pTgnFL=NFHWc{hUmA*1q~%6g*p1UFQs zKTz$`Z=1=4J3Q9Ba2KK*8KSUN42%^9O>Q#i`F{#%LVDAi=}pw`Cx+LGfl9BGMU!gw zWW41SmG)$6)4Z?EQfY&5i~hU$3QUQZOk=2e;>nhl&T2isb<`(M##>LHQ0JbE?SACM zjU2VYiU-#=*E^vsB{x%QlM-bfJcm+VR_V){q!xzKBPuiNPy%gR&tFeuG|Rj9X6AaN zggWo0B+HsuZc%HOjgCoxYNEVv(1xAzT+>_(R`s505iKt_B?rU0%U!Mp>4_IrpQpOk z*vcwz{AA^RD!$nOf@GtfHu^f;A1(z;OB;#my{DR3>Z^TE4YMx1OVwW9G%=Xs!1j+4 z+dm51Kcz&(G`{`{H&ot&Xv@(g7;Rnhf;-bAEW?>CEnO z!>o3=Na&vRe~K_OwIY+bs?EN6DNQv{Q|hii77R|7Y7aG;E#j{KKg{ww{2ylVB0&n7 z#!r%gScjRqYAbQcmp&5rQ$;LqV`bt=T;AMz>`OIxxhLk%Y0@FJ%-g0R19|le_3iSG zo&T3Nqcp~_G0Hh+;V#gk`Hm>rZp;7Dn;r$nXC}2iguBCe%P;)V%P}WI1M($b<*V;3rgyT}eL5x6^m9$;#1l#ryVBW%I!9bd_n3O+AY)h43K7Z*Q$DwOglg0sbIman!Tui zN7mGDy@;?;j^enlu#_TKG(3FE3P~+GVlTAv#QG)}Ju5tP_x+sl_G+Z5Kp49}LBt*d zY1IsDqA$}H+Vs`W2bbaKvmIpXsdhY9t8JrKXx2LVtVo~D5!9;ILLACFRq`&EybETE zQ=zUuSEKRK=cIt*{;9J2SHT092U2C^ueh~#l$5wga>c2ME4qx3;|AZvRNsO$Uw#Jk z)TpQAD0MgYIc<1^jeMG~Kx)IRUrYbf^83R!wxaF+bF%ZYLKw+$iREaqtrzRr)I4=+ zMd#*!twe&dY6*5d%fs%X6ZXPkP$Eal^D7(3ODFW(GMSE65p6v2p!)v#W@8pT$aKDC z^xUyMcjwP35j$(leyzH_>iG{zp}Qrr0=mFGXvuuvaz_C%dJR3twrIOFo5{O@f3EPB zlSm`(L6yC-ea}CZ(2DjDlaHY@ewaabpDCys_ZNN0Cd6>*OF4fVK!Afr*}=6LJzrFt zR<^Sqe^#AX8SlA+trJe;?fx~w{+h6v3>(u?^%^#rxVYgFh4UQ`rMYVuRWe1E0=GRu zJ+d6pv~5ioNBJ^rfscij4W|n-T{4}s&9w?Do5P>MLy7ztQ4+(O9_||4Sc%s1Tl+6a zC(e_!yJn~*FEoqu-OZ&HZ9w15?8*$AWHPTpN|heETkU$GQIl6ifaS$_?ox;!N~ffD zLhWBj&78y z`(NyFi|Kv#?^@ZvXE6BD^;I(&D?alcs_9^MtLUF;(fbe8N00Dzm%FFF^ywGWXD_yo zI3{efo>SJB?u@mO@W<<18@ysO?s$^RPyK4(d1O4P=DpOs{#giF3`gNNRY{&!PpY?H z>KKkAvUrgC>ZK(eHsA(sYflw1)3Kq$RAJPIrk9w-18ruPc6~xEeK|Jn4|w1=oPW%$ zklp{aR6bcW=DlgE^yS1he?u@WKD38+MG8Df6Lv5-Gsw=)8pT+NQp)~HhxS8Xq5)-_ zhy8hWB@YRo7m&hu9@DCyt-31Vqm$L-SEh&DKlk!rkh>b~LO1-+8P3V-hgW)8VpQ{2 zyIJ=?rAEA((ndoGtG%{zVJKo4PBuFOx0;t&jU|)R+E-gA4}S`}W5qKp0h@j?xm3^k zU_PBSq{P}Afu{=-E-0DZS5IQby{N9en$~I93uXc)3j zpZKV}MRV)NcF3Plk|r%VW(BEYL7Vv3isZK;ukq$Ra&hZLmdLcwEuquJuf`FVkx0yj z%8VpU<*jL${xV&tyI-82Nev@QT1%6p6%u8-sP35|V`uy%Hk6YPj%_p<=yRorlzUXk znp-?Sup|nE>!aY|y%v+NhbSHsik~pZj8e^=%kc8fP0;d(mvqO2F!F?-tV5zg)K5Yk z7_oC*AG@|q2=q#pF1yKO6vExSWQ2O17>heD$^I<#&Dgw@`7kl*B?lEEwSn-IqopPx zo-f05QMqi^m|Lr3kwrgctQf0SzTUL{J(3r{Da87mF@3Bmf4x&~S4!Y+!4%eHciNfC z2eQ*i`>*qbSkJxH7%k>I^g7Yk(h{bX+Ks^pG~@b8g0!E5C;c~hiAe7(Y`o=Bs_h$x z+V*~ita2?cde=#tkt9#FvVChAe`4+L5pOhmMm2r2<-jR&^qnFK=)DVGSB&`#eKJNG zvqFIwV;X_v6IFNGXpJ~&fGfsJOr6D(qx9cp;yPyBw{TOzn=LKYK?~HXwGHa!=8&3u zGu5#`?O9vd_89iXcuIzh+#p1-8VD1&Ekii&4((9QdP;44E5 zGV)NqjlKGI{wR@Gu7(>YIF6O25zPxfn{j}Eex+*k-}K@HVS3ECKFSsarkliu#Mm|bUiNtQWJS>EZ=<0Y|v3`h3@-`vR11-c!= zD5Nxlgo$ZXADoENj166&duyb+=bcU|Ltw+1>jmMvlIEhd+&WoLl|0a&e%g$^K$)ty zk@_Q(lv(~x7tild*|%QFD+<~Rmr{w4-+D>xix`G_{uia#>!cWO!8dTfKVHH=j-ZU( z$cl_;OP)SAW=ys#W&}mc$7?A15H*v1BMn#2Un=z1Z>Q^WVoDfUygeQ|5vW7A#rlTD zB$x6z23{%O56+j=>W94F6f6B*hjm$@dhgvvb?0JMxTSHQixgF?j=p)5v(4K3`FRjc)l8-+s}I%NHOBwvLaRNcD6);F_0;aB&sZ_;!YJG)*!3efDI4aQe_ z1IgI%ANBJ3wh{mFhT3NT`nH~p^gVsJcs)HA8tzw&ed3YPGWNn1#FoTJE+_T`795!@ROkqA{+Gz^7ywkl>e9 zMTz_vUzst9|B9(JW0HKs5{mY@Yk3zYYHpdt>V=B9TQa>f)5mV`)&h@z%M zJVHe7I27UAZS;zD-xBrGhNck{rI}96Q9CzeC7P!S&G13ZekhU`$o++K!qZXOO1_0@ z6q*y8=y;cnow`3?D*gBfd!tI&e1f$bJ2}9Mf+Z~;p^VcEf$E*m_YB9)oKI}*G`Q!@ zoE4ID207VPm7H(xAm`G5DmmN83 z{`)QZ6fYF5VaK@Sis;Ki9xXf`EiqW?7!UsQD5+CIk6X)}uDT=PF*!$l^?oPooX1s- zO)Wgv-!c`o@B${Pc%H37OVVwQoG~t!6nAknQ)yY*l2pX0wDG zWA|1W7qUCPhxsLRq->tI$w5+fXpGgR(I-|tK`FuTxVt!7T0DcD{1q)T_)^rO(=m~B z;I7bJqm#zy!8~!|W0XFic5k|++3mQ&sMi55a>r=-<^B~^1DCg<@n&BY{Xs&D8lm*X z#HBg8Sp>%K0G4b4RvWf#zl;f+js`4rO1%S24mxXAtyMw*F^m!^6M? z{d1bP==5}2QQu?kQ&K{P(d!PLr#q%{oDs&7o~=JQ>Xeyu7`9JF{aU&KVZ$s9H=nJFz-wqXMVQD=$nMF(=8mnF}q z(>A!TSYt$>vXfmotLTyw=|6m zJq*&-Q(M}29`OF!a@$CnHP0IicZY8qOHewE4AYHCGm)yII)7uM^?y(c(njPs?OQSv zoSZVt2L_z3DWPt8d%KW3U61l;bin$0%N@ejUNn^vYElp8OjRW1)taAa&#I~g8?LbE`&m|qhOuPAY0UH#ozWot9rynyYqI1TKZyaGh1Ef6^WE7a^LtlGnaT%1ld`livuSq`~aoM`0di7xZbILR!a6MYdzD|ONzZ{0Uf zS+~#i497o}>lzt1JK1}Bh>WIBM7mW&Wl841zA~Ms@?-c5ZeHD4DtkFwi1d~ZG35+n zGUht(d7~cdnu2*fG`ACr@#n*wE^+~fJ2Y|uCy->`xiPPTz4K6eI=40~pzH1yNsP<0 z*m{sCPNN%#uH6{ThN}1-v7U$7M`1dJk%4f5&u?5uA=l63NAPTf-bzolzKjxuTusG`#CWhTd%U zrtXGLSHpj$=7m!I6ZfmbJK8sY3>gq*|0Af4d^s!BDBF1?tQvmUy3w(|6zp~kDW30` z7&-&GVwCq)LqF_j-G8@w#H z{B*DS=EEKlEfL0OHCQ#>d0X~45zJ|fkmIu57_>MH__d1|xEIiO6hxFj5rq37!*aLu z6b6fn&iTUR4XV%mvWFqKA=rHxYVFRpG48uUr1qljBx1yxav}NqosB%pBwsrD@b5(d z<*iVX8yV+rCC4t#OiC^CLiK5focjFddHu|?1& zp)PE1%3`eVgYQlkwI3HrcXqHzxQm+oQJnR?JJs@!?rgLVj?{hQ`~RwY;zCusG(F;k z6n1)$8eZBsZRb6tSF-hlO%shI}+8cO&R^^P9xbhU&7?H)JAmJcK09b=3P5hfTp)r8EBB%)ERt_6c~xtX_Xi7-x4=nqArRt z#0h}yqg9Lq_Gk#sQR8=~xB0Ml$QTXc04KB*Ym0FReCnGR>78ejFYm;w?YmPuefzCtn zSBmi(V_HVV2gGN}%LEO3md*cG0%OXRM|Gdo&%R3`>Nc^_;KYP5iLLYW~Mj3CDU{>le?L#hmgM17u!P1w8f?2#x#}C z0!?@p7bg&1{l;b>f&lUdLw(36(~eZO_Z*^bzW$NyiIYhS{Aj*^z?UIP%psV>j6vb` z{4-?$z5s>s3S|Xm$?9f!qVK^3pC|N59OL62G7<||4Re!JpXXRSI8i^hIJ2{UKc3;a zoDpMOLlG4l((i5QbNiOTo$Xt)J&EF){4AqumwpvBe&Pbb3S>`3Fd09W+_i}AC{Lf@ zN&jmSP2v)3w1^~$Y;+U_-480lMW^LXJC_H)FecN9i_3fi9Ntew zpX%7R=49zr#`U#QGv5ID;zIk;63NBo1;}y3yu^<&UYC=KE50@%^h~eJa_EB-7)y~{&K6_o;S#fqEh}C#yzU=BYscK2pEDDkM%An4 zjDg=sonmfI&XV*=D2eZ{{DSzD^~QN~bV+v&n@%=)=Rlh5UoChDxs$o+S@Z$RI$ynB zc#mQF9kvYbmGJyi+oteB$)c*#=G=OdpORAcQjO)z*DO7wuhh{(8*r~+a8?~tU+?eY z2~S}dXUOa3yG!H@(ilgYaoa?GK7ZcS+^FPIe|C^@cp95C&C1MF7ZFP8<nOHo=iPEA)OrahAv7G@cI8IE};5FfWdJ>^yHsI+ORoVS*7&iJ4;q`%5yV z_g|$9G5M7g5GpDR!63{qro)Eq>Bh144M7hGJF8wB|%|Q=`OonjHe|gw2 zEs`vcnC$FDYgurXJR>ppR>wRmF_PWL$81(_L`I9T7ljDKS87)nI3>%3B3mdzd!c{H z>T`iaUPPKICtUm{O=1#~RDV9v-^DC^Z4Q%?w-90}r_w84*8^Q>m`zIwt@_tj6pBx~S4aEv?6^Vl|?y`j$19IFf^hx^EqafIk|PkZ5JX_)Ygi>lL+jzi=Napq^@cAc~uYpDC` zweVsVZtX9XX0MH$#wb|<95aSal?&XGL;eX2c2x-HH<{ihCtq5%_JUe? zf#ee`O|97!8Zm%lsiQ*r0Hib{w?ubWh8N;gJbRQEqGXAS^!}`uEK}KI)N_?J5@PB&h%U%5U~KnKBxf zhxfSbQ`V^DFB^H@65_LKSnih^hn;LurEfq1MKBp_HUyTic|q13;2UW(y(~{wRO?BS zH*j3<3y<~5@>C~-Nc~g$)`tBg@P&S8*U9Lbd*zMp=tcX8IyZ4*&%JKmNw4JNcOQ@K zK+b$}=IQAlpn`dN_bvRX2){%>TF})%J6G5^XhtNf-@febxk7YtcG!lnv&Grg4VJU6 zPLgPY!Hq8vk1`In3oUPFhMB9}xti7JOB4HlIBY5aYBtK~j1C(wprtN(@7^_3xIEvN zX{5V+Yru5Z<3>nD&EaA%lx@X=+bsR;Ma?8M&(hfbSUo~$w^UeW>MZkiHLI(2#hIbc zdZOeR#ydmInWyj%s0tR=u&P>LO|8qTEw$%F=JzOA7!f`@Np1Kl(dNt!bRp1KUHz(# zCtKcdm@07HEuu}L5N~-_Alkg-_rq|Jtg4&=VBFH&RR3Cr?Fdib(8b2btI>936Jun$ zK3$2G{#r?#_lh;Y-KyoLjd3^krfT`It}RkTd{-LdX9@k@$0LI-@E{str?=T6x`-J& zGM=;x*fkvSYVL+a9T`hhg?>!#Gkq5!Yi!x`H{QW>MK8z6&?~QL3iGRQUk$lYGM+1Z zTo0Waw(Ck{&k9Z~nedEwHudt?Zp(Sq;F|@O z%j&6b`t~?IhMh0@##AJ`c`^QFEG ztRlZ1QNt>=@1Z7tyVH`cT6~w`8HMVUWFUxff3CUk;$^|_ZznV$x@t8GeHu|3&iI%( z!eTUxU4#qLC8y>dW=xtQ%{{k&=*;+n+4yphC-2GT3;Ep`<3PLBB~&zYY`g+vQlVwY zCb|0NySDX4HWJHgz7(Y&@37m*RSiz|j#x~~`nn%dxhLDjpKgJgvo@R=6`UEF9W-A< za-~aM{t`p@ zFYVpAtXsy&j=K5fypc>hF9>Be9QeXr3_Iz8b(P@;EhKgKb4!jxO%006XmLU~=7|k% z)-a3850P%}fhG?^bxMtx(IGu_?GT3F;P@CG=C)PKEf>_w-#5>28nx&^JEX8;BN5QjuIbj88rdYWp?YCB|-=fzNK3XLPTOQrEsut!rxktz-&} z5gqIML(JX6t>=Ds%?#h{Xz$tRzz?jM^w2N~GAS1ih{l76GU76snFmB7wC0zwg+4|7 zzpAbTE~+ExPYuH%$8ZS9?TEvGHy|1`pu{WQ!QgF_#OPzZ2}jg;0E=cBCJ@|N(}^25 zcC*gY*6CjcnZc{ocISRn_&n`}I*>U0p4Q z0ywXA_5)Pv6R0<>-SE`lhQYa2YIAMkFzwl1p8Dd1ZZ^f z42!cR%saZLB9@2A&s%z24G*~x3z-ycTUEQNCg9DJsN1j%ID3z zNhI+Vo zU*>tF0(@Gb0c-+r8@HB6+3q+-dHMX0|oW0kDT1J#SdLOfPpp)s}q*c(h3@LfEli_}dR>Eu;V>|H4x4=B) zMCSWc1mheLys4)u-@TR*Np;RMtcik$08;}TVXzP7S)9U#9+t-IsX?4|MH^uA{))@2 z=9DEu?j3M`IO^pY{9%nmmQM_~OqG`veS`8)a=lPuvoq8n4RmQ<1;P}pckKw=`ji4D zQUxW8)uu+S1YD@{C5-soQS|1OQ_#zKzmc*+t}qbqnfDY1M?!r#EJugG1Uoxg1U zq80fn<@vSOa~Eaj#5# zc`%(u)|{wBs@#6sO%x(BUn7l0*A~#t)W=0r_YBRxMZeL!+7?hWFUv&}@WyX^I$_W9 zUb*Bc9V$IxVB~jNFjeF<1S0OUFvjt(6Lxo?Ruvq8VTBWkewT4mQxsSc0{;tShFzaY zOu$&zOA?>S!~wi`2^e-`hKSD$jbO+yG?V{*6zgjpe($ zhOXQXuyG#iy13e-86cKE4~F8YxcIjcbskPj0(IEw>dL8;& z=ePIwk2kC7lqLE}Z_D~8pN;PF(CKu8>H8gMbOTEd!z5~?R?fxX<_i0ASkY9-a~NoS zHw;3H3x^HLBeiG;t;Lo%oG~7!!D;4f%RT2T+O;{8dRewOyALvd;RSht=M5TayO-fh z1yDI=?IziRAeR5G0O`^~H_82&dXZMXJwoF>TOet z*HeDsuIVDSgA*ZjgT}(+is1qCAeswq9TA=>_XMXxzaR8 zEYnad9T8O;3X7k~XRBa7>~!t8;uDJ zac@0}FccKP@^72#GdlS*Ztk&hZ8j0T*8K@x_BuQC%t@W3`Q z!rwZ@+yC>!2j-)fvDFGT*^8lG6j6lfo(}Ws$X}IF1Rk9gvyi_#oKDI79#>QI z+X48O%o%D4n>jq?Fl5u#f+%kHk&7mI3T|v`bgwDAuC&>=^hjScm3qmP$u=;tsy0lj zS@~l+eduRRuj2>G-i1(k0B@^Z*oKcTPIRH}lqg!ekfc2VJ)+E_XFX=wLd^B1_^>u~ zMl~ytVw@b%_}lS6--{2use9sHFv4DtW+r+OM6wB~<9X2>W^s|fFw{>xK5|&wSJ=EM zy32Ybc>+!vsS<%clrS%dGtyxCQMxG&IaY{O7P%`R7#M?Ui;<$5A`}-lf2_;$W30dVr^d(423uE@~r(qZ>?n*sud?zOK7;X^U8{W;oEIUcu8xG{v>8y+!(Ft&wTYanKK$lAsJ>XluzAWK zi*#R#Q5QSJTwj#vJ+aQ0hH9{qtQQA;=_k^QKlxF)pWd9AXwL0xHUg6(lC|{8EIyV4 zNeD2n@ycY$1B&lA0Gi2$l5`*yuVJV>7ciG?>pORm#-of^_Ci4nGM_0rUwajs~q# zeyh0r_H(K2M-$<%-c$Y*OOdwINp<%RVZ*ShAZUtlrWhAQGrO(4i5dEO4>*jD+kFG} zk~g{{-saoZnjrd=ydMG!o|9{riWR{$fbzvh!4&NkkIdNqVB99)0&5yMMMMZy(?oGF zgeq_w7fM<5x!4*?-9mTU6b94H`Cpos95+v>Gr{C0O`Hs+7^)Giq0~FH@iv&5?jOrQ zVHU*CFt+hADG}mUD20g^y3yK@30R?5bTZIe!~)0MUblQCPEzB}Y;NnT zvN#t;v1zTB8HMTip=M7k#fFO(jd33_!?$8nkPGJ{UaynY3vek46b{gp5 z@>!&WQ*Vz1n;Snb2&X~nAt~ZdxQC7e*V(g_{U)AJ8vCgWBaH8+h-=~Wwub>Y`7@Ch zLH#2};zOFCXdsm-U4wt;Al|Z{WvodNwGpIC9uL}D?vTtFOVSZwrRkp9SD!-q0HRF5 zRC|mU206N~xki_^jn)6~)eMgelUN~k9(~>{TgU;{IDBybVWx3D zLk|H8?_|+Tj1p@XOCu@arN5(6*v=cPm|`6$;9!`S5-{gK`3rK<^Qz*Gwe&^;6s+GL z!X`U-H#`iV7O*OA9D+E@F}!vvM78o@(Gp2RbQ}KD+1~tH!IFm$#bK#d9>GliCDNiO zCOCg6;CYMuy8kyh#ob0WlOpcZDH_re_KO zN~V5Mz+jaz0yh>!*6K$$vB2;<>yFx<3Zi?VIDpUvE z6y`XJGzM{Wsnjn(gF|GCAF2y*gppf8C>ZO2A%9zN=VOqqOXs7$!95n(muztj?#!V0 ziF+a9OXiLBXj{?_j#|F)D4w@7U726tO`$bVK7A*CXP{)?{ageK&`Fy^z7%x^ilkO? z$v|P@#DO+IXka&tmSNd8!>8V}39Zx#7+YGTQp5{`7 z@JOHx8Yo^&p#CFQokKHd`wo8tFf?uB^Qq7aVtxZXTq6MNHnS5jo&kJo%|Y{8MSga08Vwl0EbVhsB)?S%i*zJRA=?o7r%kYYn^ z8i+CW)OVE&POWA+cCot~mRiB^e!CsDL}vMxP6UA#OHv%;Ne6c^FS9$s8J`RNK)fUCDS zl}2xhgXy$h*GYse#p84@XN`jR?t1l8QtOCew5EGxRpC9YY5}e+TqAHL;nLyqzbAg2 zOIJL5dHbt!$fZ0G>r9KCxd;@`42^^M}kID5a((_RGy%IKObw(t`ePEL>LDe??vn zCjZtI*|gQ4E?fOp(3@T6j_r7-*|1|o$2+oN$Ec1R$)8{Vl!NB3Htd*)FrG99X~*Oa zNvV?(Z?|w(HW;=K>v*Tpup^`6YHr!#4QK^Y>G5J-h6k=JG`+)67L(Q?npe>;ahL59 zWDcp{zCY_OnG_LOkvYhe{y_;cEZOAFx(kyPTrfup}hxo%=)YGGf!%!XT5C`9) zaJ9}M&b>tqzGv+@QbnfIAelnXid}1HlRD5Lo?lBVyaOGOYa$HQK@RJ_wRDoEq;*J1 zb%yP(8`5Z~9@YWBFI@nY9x9?gYkZVcjvy4-S+RHn zWkZ>8asx$&H`%3nDQnM}Ya_2_pg0<@W>g-+xD?a$-bU(0P1fEU>A0qgUUkRWKc{?4 zf_Q8qQ<2^w;Rr*6DaPQ)ft7&=N#PeI>`{@hVu1oqaP0jSw_c7M%nCgX+j~3q62g5P zQqo1-`#SK~&tWhP?yo>hF^P`7fq*4Dq_6c3bgCfBDff`5UK%6S3}gsgVBe@bB;Duu z1IZyYX3A3Q9b%T5UQ0{`#hb~Jd2ov3ogXBVA;p3EvHsV}^EqbeLFG@9^K|9K${!>% z5RwT*)?dstm}r3LQ9=Fbd240`&FP|!vRglW4?5vMyFK-=|AuCjG+oM)rWm%{#fR_H zV|2mqe?T$XyY|$^!k;UTN~Q;f?RUhH4`>#(iI^?avrAuBDQ)a0#&4liO0br0q1WB0 zQC#0j!>G|}_%od%1n+)C-^DiCrIN>}WxUU#wD~7gQ?(71wYdXNy2`_b?Tyx!YWhm! zn*gr1F8z_EV!im}FLaUmTFd^AE)jGd3wKcx9kGgCboIX<>HP%jhEFMlNN+vx83n2_ z@B4NSokg(v3tGlO?LHdP`AN+Q*35nM710E%c0c{o9mOCnAB04L`=f&tH7p8g#M!{w zoQ9E6I1hZ!X;QVGR!QU0I;vc_9RJNDqi|CAd0?y{DgH^NLI!fmi&3Ogza*U|Isjkj zogXVN-rZUGV@~m^C}g^_9!(BS5{+e39R>TKv79IvY$(^Fwd|>b=tU32ih5-p`))mk z(|f}02rUV4prxV--L)IGx8t%~*B_xgwFjQdV(yB24KyM0o*iw@jZ^_%kmal#wjuB1ex*P3nwT!<+8o_k^jnTXcXGZ zcI38%`vhqOl8oNsMcY4dBGKx~dP8-yJuR|eA)d;$&0_dTnhrb?PzC>FTOJ)z$?@~EY1fGRD<-4==QLq~7kJjOj zlg?D0k-p@?Q>r~@E%_JS@lO4$H&8>{q-oL&rJ|SK&`YMHPv2690`f&GLhlotQ$E@& z2clybx&>{p!@9efrmB10u^Xz}>@X?PDV?ai{2x#k`R}inl@l_6M+>~Efnf`*Is#y(VwH@o8EPqTlzAOtG%-dp}`_MH;3Lh572eX;QRF{}4>X>HH%mh65wNJ@DEb%4h zo^$T`z27R1sxTH0sXev*=W57sna>;(D3Zph*Hs`yR$*=zB}-m&Z|Nk<`#549oW&SV~uBjhOYg=nR92X@m# zR&%8{YD)&Ul5mQIeRNu5trkZ^emowwE%xuYb!Kt>YU5k8M6 zV}&i^BWp3%Y!3)ztT9tTW~&2YiS2z{Wb~8xUxyGnyBsXx&y{ZR)45&yc5JxSO1Ept zU_Oce0YKs=zDrV#zda=Fq=P3H-E^zn~6B5pAEn4)q*^5 z#cg}%u-fQ9n+SUN81(P%J{#MK;@2MM!?3k33!HnUbHH^N>~CESaK7m7fb)!drpXk5 zRcIro1nb(xeni4aaxQm`dI)q}AInOA0 zQ_R!JvFV(bjmd_lEmdMhEARZPR)I~EB@Z3kM1j*jZx#zrd ze(!hAJ?D6Xg7+)I-1J%fPwP!r$?j+Wm*$_Tu;f>CLbXPCA}ckzC4&9Em4g1;jW z9N@aG*7)lNybCQNOq*C z*jg*P@8z<&>YTcGn-{>c=;^@nr=WkHH}#eTzTP!a8Ve3>r}z`?kt=9RzWN_=FbkqI zI>C|BNK=&Cqs(lrraq;~D$sqrF5~d2O(g-SzAM!Kn7V#V>bJt!61-H zZeDLR;0nIncw0dA#i=E{tkU~Vm5!cN?zEI^nbnz}2^0T+CzLj4%S-H@l-U=!L`Vo* zH`0aeL*0eC8RaAjZ|MPICfZ~ZA;B&3BCLQ|#~#=dao(aGyqf>8%0fi2>UGj(B%GdWOOQA$u!5zDjg#umk~rX5(LiakrIJ~c-rP87kx zGf4bLCm~Uk5;lE4{omp2j6UE|M5n1#QKZ7*V2Oz)a_nPdnnT=F9Q$eecmn{dS1~><|7=ZXg-Idk<l)`k(4O6l!9swgS$md~|&&Ubwvy3bwoh?itsJV86zQ1TC*OTga% diff --git a/pc-bios/vgabios-bochs-display.bin b/pc-bios/vgabios-bochs-display.bin index 7ca04402e97fc844b7628175839c712acc2634ad..afea4c930ded4384faed3a543b66dbcb0d9ec327 100644 GIT binary patch delta 727 zcmZ9JUr19?9LLW+UP5KL8>C1N<0kHke|EO1*xVmAQSVieB$7r!f2{qc(Qaz(En-DJ ztce)srLtnuTM!`^B1GtJK}_hO@*yb*g$QfZqNfUz&Y4>eotN|b{Jy{6Iln)#bs@Gc zC?gL&p9lQ?=>OBDb5DQw5F&}HZ;Q$n#-e7_mdx+R@;RESB{mrl%I=$4fz*ZsOLCBr z@iCsEn9v1u;9|e5bym6)24NL0~1J8wCZ$7$!bVtA9g_i z2?#~skt9;Dn^Bb{1$Enuc9I)a9u=%l-jJkMh19wTc4TDJAF5a>G&IEnvS+CmRm&E8WnDJvz-bRCBScaX`SO8Xak> z$1Eq-@h!ND*3~o;vo(3*>DAnlH2UGdIF^Gn;;FV&u&ov%fH@Q_ zYus-<@*Kff){PS1YQDEM|1+yc|Gi~{VKQs;>+p1qzW2N7+rSWO)=)b7MB%Uz>Gp}i z+rln{tP`bDsf1ASPJ!e+&2y59+T8-}X!khnEo%1*w4=cs%o&S17L2sIqS%|;9pSdq kZOtLqnNinS2stLELZi{~^OwkEC=w+Xrosq|EM5}+0_WT9MgRZ+ delta 667 zcmZuuUr19?96tAW2^4dCQAQ8L#9i^v&Ne4Bb!v{h*R+ujiBwQ9+;1CnS6X|ESdkC6 z4Jpn`(95K^pdv0rNYLGqnBarvLsAe|h**u-3LlnD>6~G`)Hx65_kF+r-$|N6(iEiW zN4_r;{Xg{C?%lnN8ePay| zalRp)Uo<4p>^mw%#SvcQeg)1GSSqU#(8fN&f?-+M#spGLJ1PxI#c@Ms4UfYR5)ewf zCmBP&Z6p+u$;$giVuajjsmNe?{+48RWyqQ$IFN-U)USi~nq+=)pTUCmWSZ?y<9fXCn(EL}&S z z`eWZ2j7?Rq8{Dkzw&j0isi?bEJ4}&9dsT%OTl9n9L*ESr*|NGcEQ`V^T@4J1Hn{u$ ztACGULC52(lEdwc^v=%qh5AEY@b$T!SLVZ^MC{TvG8a}8y82mq*P6^#G@ delta 61 zcmZqJ!ql*Zi9K|c@5_)t&W-FYGgJ+9(~VM6Op+{MQjy82mp;Y6pa7? diff --git a/pc-bios/vgabios-qxl.bin b/pc-bios/vgabios-qxl.bin index 0cc20678a3faf187c6f5e3a83560e9f1a64dc986..056b6657b350ccbea2436f07de76a4f8a3971246 100644 GIT binary patch delta 1481 zcmb7EZA@EL7(VB=;4J}K)(yoFf^4g>xel7FgHl|F64VT6QFMlBGg!}ofdi`5IAz=l zm{x9<&Z7yNVD99PnZ{Hv(dw3XsXr*hm~DyKj}gOkCK#rfCPw3Q_@3J~5`HYP$$Q?f z=RWVpIjJ-&NV9^i<6O&6KX=&C#@~fW9(lB}1=%Nxk9}-&8}OLgZFp~c!Kb|lz0^vg zUy+6i$~IMv;3@UZsy>Vrc6&#EQ8`73m_NHr>Mn&ul2bv|S9V^=E#TqNzmBFu>|sYe z_NbDh#sFV^vS%lp-|Z3L)=G;uqp42T9K| zJLKGr<4krsu*SZ0-fd1!)+IxEa_XdJBhj*1_M`LVqWC0<&XaM?JpQ&|CliIUY+&y- zJjQ&r+lu8NNqAsD+l&Mj<`$WWs1vmTY?X$fVlxS^A&9Ro*~!^BGq~E_C_9;HQ7=>c zK9Uzn^isN8&9Bd`5mV}9637sxWWH%d;o}n(#I|&aKfsRIz^2ib>#)oPJAEU@ku=irJ-2sIcFW}ws;IiRUcjZiGxPZ4w@J?6tjr9%F;1`(4Q?D)&o}&rafE%euM*4b%D!^~phi71mY8M# zbqM{we;6+N`Nlj0memtYt%6A!8q-4Ub|uWdZFXTvwLEew7w#;-%?am2`gy$V5ZG7R z8sWUx+X?53-s#6q1!08;NsY!gcJ@_7qDeBhVp(mHQ{)T%y6bf-2C$l}6;2}K>Q>$3 zpO5x2w3b+1Pp- z=fZ9VMT=-bNI8@7%60D@?pd=K^HurAEV~zeQ98<&o&b!!EvgK*d074o( zp2~i>8_@Zn|LjBP1_*ytm8b+6O;9?vW*z%1#$sWaPMmFm zgJ%Hz7HA3NBAe^6j%1g;KHJZ;AVoUWGEng+@!!R8><_@?1?|pYH)XKKJ7BZCR%Fyi z7ez7Mq6c0Be2;2@jL%aFS_Ju<4fR?}*0;#ZF2nz-PNh!w9^1X$QMZda4?7)!>h7-U eBP6hEFc|0x_4dDD9|}AdvJV6)5{xYDkNpepKDwg- delta 1428 zcmaJ>eN0}}xIK`E{vglfuY+0Z3S+b}qf4wO>q)Hy~O zVpeIE&KnaPBN0dP#S6t&4Xu+8YR+!TI_xFnjXe!-`?}13`q5>^|1B>kh4B zu8Jq~9e#+~u)*R98+w#`FkzQRDmtji){7Y%U~rjWd}&sMGd`xVG+UKaXZjg6P5wC& zo`KNKM72S;+P4Dw_{m8mQ$T{L`b7s1Uk$QTmO@8zG}BNy6KKcU#$a%29!XD25bFO~ zlt!Wpi4=dJf8s~LEcp*(2cw@!|>h*P+0}-mimOQQL|DwVp8ey>5IlbF%1<T9DIa<9T`g8lTN|`&%w3cR zk^lc9a?IVjjy*2r4Uir}6ube8T{vL0*U?5%K1Sg;V>2lrTD=j2%j8j50kO_Cu;-Gz z;T61^|FG;+DNRiAu7%ZN6*d|tf=;K_p!6_H=Z4(0HNz$87!C??LLZ_N-PtkwLCji; zc0Ecab9I^qg1*El&x@Cc+&e_bEXoa(ETU2KYB|&RGEtIqx{ha@=`*xrC=rxw#PY1G zvEd}vw*qTWv9D07%Pv%jQ$=v_1QPENP!F&&tzMeu|Q#Qq3V1t_Mp@jge!& zMj~_3cpk*=ljeh~5y|eEC diff --git a/pc-bios/vgabios-ramfb.bin b/pc-bios/vgabios-ramfb.bin index a7c5ae7c8f5e99a172c4639d4ec37df7d884e856..02662006f238eaa481cba4716d07f593ef6ae052 100644 GIT binary patch delta 500 zcmZp8z}WDBkv(*k#mmDsb(0yL#V5+KGxlv%`@_U|WV15!Bt^ytleekp%RWeBV0bOn zb29DVLxHqi4hXr7b?Q`JkEyvsgkt14CLy zz5@e8z>5W+)8f)1(lQwGC(CPjFn*Yvp*5B9$K-!nwm{NGTSxj!UYg;7z5{A$opK5c zJtz7Or0rm2U;vr+VRN&#CnMvD$!B%67|(3}p<~U+cwn-L-WA3(lR5R9fzIvKf6fHt zlp4L{JmB7PpwvTe!NJMt#s-WBHqS6FVPU*Dnb$%_7wmSco)bV{fc#_tV>KRPV0oW!{$KM6h@vFkF*^O3CA$?{qrj2k9rXia6@G5MdCEs(U)){)+lmu7gN?|@obrW6$OvI@XMg4Uwf%28<1xXBd~TFixDzYaycxcDq&237{`Pelmcu8V@nByjBA9 zJb>a7Al8J*VHR1y5IAU|%(NhFGM}ZyB5F@JWM)LjaRB&UL^uk5;zTfoDke;rMS*h7wb z>`^60jRC&;WbZCGzuQ}CR$fDBHD6vJbJr{+p)iy4fi0dhz}K_%6hhvW#4p584w9Z_ zcF4I0$C>POV2yq0yxW|dtV@RS__LzMe#`zohRd(dHgNGP9_Rx*}%SQ zc#QdKw-?JnlJLNQwiyX5%q=n#Q738x*eVS{#by#-Ll9qGvXirMW^lE;QFb!ZqF$!> zeIzfE=%sYGnqQw=Bc{~JB#T#f#u4_>{z@#fEBnt0fExA4SYnm~ z*CF)#fnm7p=Nt13SXNIowF)L_XiN*W+m$f;w%LUx)$;JIT)4CRHYc19>gVycLttNN zYlQP2Zzr5DdZ!;f6@(QYBsCh}*x6SRi6+V1ie#oRyc`_tJ`#s ze_q0^7<4NR#XfAV!BZdY+l899fthO)ioLyq@$^C&_~AQwRj0n6)c#C{Dqj*YLwnsw~67>k8vI&roM z4xRzh^S>GZryA1!UI+Z%zdu-1RN8N7fJnVD?s=K?Y ekC4Fb!C;^()Z71peJJo;$UYFHNHDUnKlU$i7P^f9 delta 1428 zcmaJ>eN0}}xIK`E{vglfuY+0Z3S+b}qf4wO>q)Hy~O zVpeIE&Kna>o4?(J)c7m>7-I;kmEvBuMs}^YPC8 zz2Et|Y4DN|yd)I2oNv7QOUqYe^>cKTN1m^3B;rWEc%j&;p>^^>&Dl*^hrNWnu?Iq5 zLiIeb+>!xmm)|exqSV74Jl&l$2ZVs(@-3*m8PGx6Jjicvxt5;A!$W@^N`zQlc@-sc zu)IuzUtQd}1@(73HyS+030cYvPebgE5uzTZH$R(4K19CG*_Q}$E=GR^H|&SbadyDG zjrv&FTuy`R3-e=!X_4W~-9wOh2Qh$v;QJ zGZ4C&s5aU^ZPyC3!6lz?+VNQ$Edl8P5PPEK(|0iJgEf(P}$h)cpx{+6A7~cB;%5Ei^ zk)W&bUa2&6We!-2^(pF^=(ke(COcMbr9Sy;^>38g*(bXtuCBXE^&$u>OL>EnM7va^zVXis zxaVXqyV{UcaTN)k2#dMavwvI}g2&HY`HAL`Kt1wD`@Y65o2LX1F9B!$BcV=tFd(J3D4Sh*?X~ zu1Cpau1?cH(3d#ndGQjFdxr>_MY(~JMKo$&EoT~ECQ5Qn*YS)qeTH@nC4!QTSe|t? zHk`!zR$vV(_7zHX*@Y@`st69AK;nI9Z72~&y{3ojS$SH@Pf>DIsyU>>^>tp z$YezOH~wF7Y;F>(eFQeeYa&{;b)8O^D3Np{n}(1-k&O2~i#CpOja~4X3Rb5b#}k!G x{?_~2woTi&O6BeCJK8GSo`H%T+qe4s9c=+`cc0kX@oGTq@#Ccvv@GVn@h>PNv)KRu diff --git a/pc-bios/vgabios-virtio.bin b/pc-bios/vgabios-virtio.bin index 806647a009fb64645adc7054f21cbd200d4d6f1a..f4178f70de41a682f7cfc7e227376e114bb45e38 100644 GIT binary patch delta 1481 zcmb7EZA@EL7(VB=;4J}K=!RklLAF)cTnA0oK`E|732Fpd6rEw(4AygC;DBm1P8qiX zrj?te^Ju~p%$@u()0pZdTHO*a^#_F*vn?_EF=Cj`1j97b#Auuj-*ekW!jC03dC&Xx z+~@r`Cza*|X-=?po^Ac<=gwlZ`FDPbM;>l!MfS;(V;|ex20X6z7~b1a@M#}HFSe2B zSER9$vf}DdJgvS_-H)-tZtWZ>s-OrF^JkYx{l$<-aw@6%@~-o_1w1_V*U@x{J?Ln_ z9#wMG8sMu>_U?l7yS-&*19gZ zNAePhUQBnZ`SrOqVoIG%0vV!|EHtkwJbX@Lr(ETaW>&LE>X$-CptorfUZ@1p8A_rf z*X?vNu{~Yl53nOPuxYgQ8Z2|sPG664B#m@_&+VO*-E_HxYO3yQ5O5jq%slbfEmC_a zJq#uNtvBwYW1m-0*6F?%E3+eRj1%lcqZ`N7bB(`Y9AO{rufj6By#K5Ks4C1yEr z4MM*k7=g=vt|`xeW%WdJn_!ZL$F)$0T?w;qTU=ODEf3wyg*(e{cf$FAejaZ>1oq|j zCOGf*cES0Acjl2(L0I8IQmgTeop}Y3Xp+pYTGpE76!}8G?grh80jxG_g_Fp*woUi= z=cU|=v8R3AK&tt+2}+F3`|e`@`0@lL$W8U0j;MeY^@GR1fhpDFPrPQt9V+f>F}9t? zxv-ld(IQ$9Qr^yZ6}tBh_bl1mbjC~PX1KQ{n|n9ou_k{tj;UdP*B$H%+4_`c5Frg7 zPt^e24d{H(fA%AE9fUusDpZP$Ca9cPN4LWYfc0*~vR{ccM`vP(sTF&;KbmDW0=EaJ zkRXaWGa5>Fk%Fo{!1N*LDG(VX=YL>x0V@e9gg5a<(!A^nEnr)EEu&hd-YUci)T;qq z24VpzKnA@xBj-@oQMR{y$noB897Sjuu9*kRqLG1*rIw`0rvk_6K0{f_7)H#Tl&eHrOn$6&dx> zMNv$*=z-S&-=jJpin3$M)=S)bFOw!%jz_rl-5+ e2np;S3I@7EeFM+ihXc=s?1Mpy1S1RkWB&q9uDXW+ delta 1428 zcmaJ>Z%kWN6u}}xIK`E{vglfuY+0Z3S+b}qf4wO>q)Hy~O zVpeIE&KnacKTN1m^3B;rWEc%j&;p>^^>&Dl*^hrNWnu?Iq5 zLG?Va+>!xmm)|exqSV74Jl&l$2ZVs(@-3*m8PGx6Jjicvxt5;A!$W@^N`zQlc@-sc zu)IuzUtQd}1@(73HyS+030cYvPebgE5uzTZH$R(4K19CG*_Q}$E=GR^H|&SbadyDG zjrv&FTuy`ROY>ufX_4W~-9wOh2Qh$v;QJ zGZ4C&s5aU^ZPyC3!6lz?+VNQ$Edl8P5PPEK(|0iJgEf(P}$h)cpx{+6A7~cB;%5Ei^ zk)W&bUa2&6We!-2^(pF^=(ke(COcMbr9Sy;^>38g*(bXtuCBXE^&$u>OL>EnM7va^zVXis zxaVXqyV{UcaTN)k2#dMavwvI}g2&HY`HAL`Kt1wD`@Y65o2LX1F9B!$BcV=tFd(J3D4Sh*?X~ zu1Cpau1?cH(3d#ndGQjFdxr>_MY(~JMKo$&EoT~ECQ5Qn*YS)qeTH@nC4!QTSe|t? zHk`!zR$vV(_7zHX*@Y@`st69AK;nI9Z72~&y{3ojS$SH@Pf>DIsyU>>^>tp z$YezOH~wF7Y;F>(eFQeeYa&{;b)8O^D3Np{n}(1-k&O2~i#CpOja~4X3Rb5b#}k!G x{?_~2woTi&O6BeCJK8GSo`H%T+qe4s9c=+`cc0kX@oGTq@#Ccvv@GVn@h=AXv(o?o diff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin index 39e3093667d608a34891ded7745af9ab266c38d1..8fae88af2823279a042090b92a20f006dfc98663 100644 GIT binary patch delta 1481 zcmb7EZA@EL7(VB=;4J}K)(yoFf^4g>xel7FgHl|F64VH^C_2Nm8La2PzyZ~2oHA|& zOe;4_x1$MDFn99DOk=7SwYnu<>JJJrW?N$RW5h6>35IE=iP1P6zUQ`$gda<6@}BqW zxzGD?PAbg`(yUVrc56p}Q8`73m_NHj>Mn*vl2bv|mv^4eE#TqNzmB9s>_JC8 z_NbDh#sFV^yk{qz-|Z5+UzO;uqp42T0E{ zJLuev<4krsu*SZ0-f2!w)+IxEa_WR;Bhj*1_M`KqqWC0<&XaM?JpQI&CliIUY+&zI zJjQ&r+lu8NNqAsD+l&Mj<`$WWs1vmTY?X$fVlxS^A&9Ro*~ytWGq~E_C_9;HQ7=>c z9+DSH^kTYO&9Bd`5mV|!637sxWWH%d;o)-{JLxKWG_#roQnwg7482W}@O%Z3PE!&c zzHX-ziEZf;e}EmaflZ?=*I=0ocKUjZBWa}Ldv5Qb?54{lR8e(ry?{%3XXf$8ZjqWx z>0v18Yq@bB9sRtVvJUsXSeY4iW1L{e8{9aqo@@9G;|Tk3UnQ2=<$Y%bK#h82EHTUe zYY_T<|1ezkbB%chEUU+xS_P9dG^T~x?Mj$^+w8)UYI*2pF5Fpun-k6l^z&HTL9j2k zHNttfw-e46ywi`I48jTzkQ$9|?93~OM3ZE0#j@HYr^pxjb=T`w3}7``E1X2e)vdb6 zKQG}{j6Ln^0#ePlRZwDV&UY94$CoE4L2jz|v_}Q3sP8}i4NR#Xd*U@CZdY+E7!fZxo64drZQeSH_g4x+1xuBk2U(Ma7+#RJMUmu$d;!(0|;sG zcq;qhZb0XQ{<9CE>mdA5RiYAPG(qLW8oC`;0IYXCmiYV;Rvh^;RHGpk6iT zQVl899fthO)ioLyq@$;|M}aAQwOi0n6)c#C{Dqj*YLwnsw|m7>k8vI&roM z4xRz<8=xhS3v8~(I+9)X`fNYXf)wdg%Rt4S#D5pVu|EKl7qmNr-IT!^Z-dS9T9Hv7 zT@=N1iyn9l@I9&pGCof!Xc6RZHq>h^S>GZryA1!UI+Z%zdvy19N8K*!Jmho)s=K?Y e50k*I!C;^()Z72OeJJp3$UYFHNHDUnKlU&6kGm=W delta 1428 zcmaJ>ZA@EL7(VB=U`v1&8gR^o#Nco^b~kYApcGdSLS4#eap)4Jtqk5v2TG}Q>KvmC zG3#iS>WK+USibvDM_#CHB;rWEc)r-Gp>^^B&Bq(F4tWWAYY&9J zf$Di+xg`VCE`M0kMX859c&0mN4hR9mS2v*YdO!zh^B}*w`AT{g4-fryFcD&PcVZ|`~ks!iIb|356d5hLD zSH)BL4nIU~*kJL54L!;|n6S$u6&=)M>&1)>Ft|)GzBDVs86VSFnypHzGyRO3CjTr6 z&p_yUqS~Na?OOqT{NyB(DImdA{i1`1F9+ENmO@8zG}BNy6KKcU#$a%29!XD25bFO` zlt!Wpi4=FyKmIfNQmAnOhdC`uCn6jv9dDWE{x87pTP(tDkat!IbOW!=tru5$vShHPPKW5${V z4Ecerkq^`S4^&$u>OL>EnM7va^zVXis zxaVZAxZ03ZaTN)k2#dMav430{g2&HY`N`&xKt1v&d%wjl<-;$%uf@t~YlD`Jxr_23 z^8a5%j=5VOV^2tV1Ehx#1#iG&7Y-QhRkTr*Pf_^I*hC75R&T`MGIxPN)uDOYhkrmg^k9Epwp=}C_T*5xjr{-&2ULNhJ!+!(1++mcXrHv0JD~& zU5Ap%T%D$Ypf7RC^Wr5UcMcLVi*gMmi)hrmTFx}SOqArDuHqSI`U343N(3bvu{`T) zY&ePat-u;o?5mXOvI|w>R1q9Jfy8^!+E5~ldQA`4v+}f*pQ7ZbRC7p$>%kIJW8~N$ zk;#bmZ~VXF*xV#m`v`1`*F>~x>pGn-Q6lL^HVq;7kc{^}i#CpOg`M}B3Rb5b#}k!G x{@(k>){Wb?NagMA+uJJJo`s6-+qU@p9c=+`cc0kX@p?e)@#Ccvv@GVn_Adm`vvvRg diff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin index c3a66af50e40448ec2100b2306bf9eaaf03ee8c1..e5f45f0c9e4483626680fdbab34996bdef6c514f 100644 GIT binary patch delta 1418 zcmb7EacC1~6o234Y!j)?X{WB(jY6@ctBq~J*tBU4bIM>%3|$-s+uEkR@7kzqRu(2> z((7Eo+uG9ZgO#b3Vqpx~A8t3cOc5?lXj;lxWq%AAa$_e7=y3e_k1IkgIBsf6p!h*i#N$x5meXVsT> z1_;Tq;fA*6pxv`;VO&FW)2A@HK$WF@C(vo$NTaUo_!X22iV~gMb4%~Q?Mu+f1pjld zSht?1{)JR8Rp!pn;kh`fPGkM!cfHaF>E3*eWsFZ!j3p)XE6!=&E4@EqFr}0GZyIre z9rHJle)UT~N46M^xksXpY27uNCfL424~KHwq!ZtCv86^2(Ptku67rC(GzCabZ3x^a zB+IH>JYXQQC-;`=3Lsqds?c^JCk8;dmD+S zj_qA3z{gNRKJ=RDmqYCsN5e0op9&vD{~$a~me}OJvKsTjnnttqqCSpKS7%4VSAf4$ zVP;9(FEyg?+4X&KJl!0rK;Ipy;PfPGi9D;GjVK(^RnM#6;YHNtXg5#V)L3jgAO4sW z;O&!6!6^XDoU*cVGdpc$f{mTAvOG3zWY5^xSu11jc2toGHPdmhkZln+#^j>_8cwt? zfm6k`71su|ZD_`%Jx~g~3oEBr;lH>XawAW2S)Eu?YAZROh7Q>%kClQX3!Kww)(O6z z@5zZh^x(<6{Qy6rEuyXYAKU`u%3K!6KXkLGgSzaVxQ<1s5QBkyJrCBSSTBiqJ6Z&7 z9XQP1ctc}m73|(x^BPc#YZ;n=R*YPu-d|icNlS)o)NP`jggA>$CA(@7o}9(1KlEW2 zXoiwtae0etPyR{nXBKz8$<75zz|Fz@g0l2!6NfdC!1VbxCD6f>Q3wG zGL8q2!!gvt@j*MTFQWy}5(tz#4sie0#ipIwr{QX*GRr@U%gn{6R+*1 cVoh>TjHmjKyy<;IJeu+j3`)T9_}@+b2{pK(1poj5 delta 1367 zcmaKse@s(X6vxkfeL`zGS~R*Dndv~AB2odBQ7G8V=^qYi!|DP-Fd{t<5l2VX>_=ky zh>-NTLST2%f7HB;#4P^R?HSi?F?qT__z`2oKaDXpGYboDBkm6tS;X@mZN?^==G=37 z&*y&6x#u>OQ-Yil@(*8W{H-TE$63egV_WiB@LRXv!UnbDman(juSo!(1X1}J>x+3| zsmv1Em!&5eQ~9&)y-rsI03F}oMc+)!iff9s&&#go*^S*ZPkYQAzOTy90-9V^X`wUU z?J1-6!JZKqQ~ zj-ft=X#mK$aeOd}>9rK2^5joc?){E8GENDV{qvMdQZ7I__qZH&qf(I2-hJE8Sc(tS zG}l9}XWR6MPT7s$Kyn(DndMIOcJoF$+9pSCk`zQFoY+5`G`4@z+qu*C=6l&&PoZx* z)`iN%1ss?tCe@2n|MX+8^hJ8>a*YLw6K;wnrRi6i)09^_J8Fjm8{9;b&NR7t@T|m+)lM{0`~N4=z4a>tX8n(^|%^^2ItoOKCO!CyXU{S%Zfq zdAQ*UbMd8yVJ7q8y^m<8KX96!a6Yis!jjtJzMx=}`v&z`vsWG9%?E0ktPLMn%%jIp znyP8l&2^#a2*u&xJG7n;w$b`m@FE-IV~2{$%?GPXPU4U12t8e8E*iKA;#`UOElT^F zjA)eKJJd<1>q8~99t)KSYLqvG-q0?E6oILl=l$Ds5p5xSOk|B(YwJ#t-)}G3fTJ&d zMm5&ame1QF8{&ae06LAu(?g>nZzuov34q6B#<)DN2}GL{AiV^yVg+JDtFW`AW9Z%@ zpVPJc%U1nIcr{q0HUexC1gq6#fq#aZ3)if+Tbf6^vM>oO$9}kcxdatIPDOjkw~#gR zF Date: Sat, 6 Nov 2021 11:56:23 +0100 Subject: [PATCH 532/730] hw/timer/etraxfs_timer: Add vmstate for ETRAX timers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the vmstate for the ETRAX timers. This is in theory a migration compatibility break for the 'AXIS devboard 88' CRIS machine. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-Id: <20211106105623.510868-1-f4bug@amsat.org> Signed-off-by: Laurent Vivier --- hw/timer/etraxfs_timer.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c index 4ba662190d..139e5b86a4 100644 --- a/hw/timer/etraxfs_timer.c +++ b/hw/timer/etraxfs_timer.c @@ -26,6 +26,7 @@ #include "hw/sysbus.h" #include "sysemu/reset.h" #include "sysemu/runstate.h" +#include "migration/vmstate.h" #include "qemu/module.h" #include "qemu/timer.h" #include "hw/irq.h" @@ -64,7 +65,7 @@ struct ETRAXTimerState { ptimer_state *ptimer_t1; ptimer_state *ptimer_wd; - int wd_hits; + uint32_t wd_hits; /* Control registers. */ uint32_t rw_tmr0_div; @@ -83,6 +84,36 @@ struct ETRAXTimerState { uint32_t r_masked_intr; }; +static const VMStateDescription vmstate_etraxfs = { + .name = "etraxfs", + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_PTIMER(ptimer_t0, ETRAXTimerState), + VMSTATE_PTIMER(ptimer_t1, ETRAXTimerState), + VMSTATE_PTIMER(ptimer_wd, ETRAXTimerState), + + VMSTATE_UINT32(wd_hits, ETRAXTimerState), + + VMSTATE_UINT32(rw_tmr0_div, ETRAXTimerState), + VMSTATE_UINT32(r_tmr0_data, ETRAXTimerState), + VMSTATE_UINT32(rw_tmr0_ctrl, ETRAXTimerState), + + VMSTATE_UINT32(rw_tmr1_div, ETRAXTimerState), + VMSTATE_UINT32(r_tmr1_data, ETRAXTimerState), + VMSTATE_UINT32(rw_tmr1_ctrl, ETRAXTimerState), + + VMSTATE_UINT32(rw_wd_ctrl, ETRAXTimerState), + + VMSTATE_UINT32(rw_intr_mask, ETRAXTimerState), + VMSTATE_UINT32(rw_ack_intr, ETRAXTimerState), + VMSTATE_UINT32(r_intr, ETRAXTimerState), + VMSTATE_UINT32(r_masked_intr, ETRAXTimerState), + + VMSTATE_END_OF_LIST() + } +}; + static uint64_t timer_read(void *opaque, hwaddr addr, unsigned int size) { @@ -357,6 +388,7 @@ static void etraxfs_timer_class_init(ObjectClass *klass, void *data) ResettableClass *rc = RESETTABLE_CLASS(klass); dc->realize = etraxfs_timer_realize; + dc->vmsd = &vmstate_etraxfs; rc->phases.enter = etraxfs_timer_reset_enter; rc->phases.hold = etraxfs_timer_reset_hold; } From 2a0c51366985890e3bf6f41a48f3cb2dfe2f153e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 18 Dec 2021 12:19:12 +0100 Subject: [PATCH 533/730] hw/scsi/megasas: Simplify using the ldst API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This code is easier to review using the load/store API. Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211218111912.1499377-1-philmd@redhat.com> Signed-off-by: Laurent Vivier --- hw/scsi/megasas.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index dc9bbdb740..83c321ec20 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -383,8 +383,7 @@ static int megasas_setup_inquiry(uint8_t *cdb, int pg, int len) cdb[1] = 0x1; cdb[2] = pg; } - cdb[3] = (len >> 8) & 0xff; - cdb[4] = (len & 0xff); + stw_be_p(&cdb[3], len); return len; } @@ -400,18 +399,8 @@ static void megasas_encode_lba(uint8_t *cdb, uint64_t lba, } else { cdb[0] = READ_16; } - cdb[2] = (lba >> 56) & 0xff; - cdb[3] = (lba >> 48) & 0xff; - cdb[4] = (lba >> 40) & 0xff; - cdb[5] = (lba >> 32) & 0xff; - cdb[6] = (lba >> 24) & 0xff; - cdb[7] = (lba >> 16) & 0xff; - cdb[8] = (lba >> 8) & 0xff; - cdb[9] = (lba) & 0xff; - cdb[10] = (len >> 24) & 0xff; - cdb[11] = (len >> 16) & 0xff; - cdb[12] = (len >> 8) & 0xff; - cdb[13] = (len) & 0xff; + stq_be_p(&cdb[2], lba); + stl_be_p(&cdb[2 + 8], len); } /* From 5df69ab89527618744661d5a45ed85ca3cc7bceb Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:26:55 +0000 Subject: [PATCH 534/730] qdev-core.h: Fix wrongly named reference to TYPE_SPLIT_IRQ Fix a comment in qdev-core.h where we incorrectly referred to TYPE_IRQ_SPLIT when we meant TYPE_SPLIT_IRQ. Signed-off-by: Peter Maydell Message-Id: <20220111172655.3546766-1-peter.maydell@linaro.org> Signed-off-by: Laurent Vivier --- include/hw/qdev-core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index d19c941752..92c3d65208 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -493,7 +493,7 @@ qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n); * qemu_irqs at once, or to connect multiple outbound GPIOs to the * same qemu_irq. (Warning: there is no assertion or other guard to * catch this error: the model will just not do the right thing.) - * Instead, for fan-out you can use the TYPE_IRQ_SPLIT device: connect + * Instead, for fan-out you can use the TYPE_SPLIT_IRQ device: connect * a device's outbound GPIO to the splitter's input, and connect each * of the splitter's outputs to a different device. For fan-in you * can use the TYPE_OR_IRQ device, which is a model of a logical OR From 6d4c8af321e5d0da919fd946d44abbd61a10b708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 11 Jan 2022 18:55:28 +0100 Subject: [PATCH 535/730] tests: Fix typo in check-help output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix typo in 'make check-help' output. Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20220111175528.22294-1-f4bug@amsat.org> Signed-off-by: Laurent Vivier --- tests/Makefile.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile.include b/tests/Makefile.include index 4c564cf789..3aba622400 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -23,7 +23,7 @@ endif @echo " $(MAKE) check-clean Clean the tests and related data" @echo @echo "The following are useful for CI builds" - @echo " $(MAKE) check-build Build most test binaris" + @echo " $(MAKE) check-build Build most test binaries" @echo " $(MAKE) get-vm-images Downloads all images used by avocado tests, according to configured targets (~350 MB each, 1.5 GB max)" @echo @echo From d4fae97d8fb50d7e3387458af24c85bac965957d Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sun, 16 Jan 2022 12:46:49 +0100 Subject: [PATCH 536/730] softmmu: Provide a clue as to why device tree loading failed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fdt_open_into() obligingly returns an error code in case the operation failed. So be obliging as well and use it in the error message. Signed-off-by: Bernhard Beschow Reviewed-by: David Gibson Reviewed-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220116114649.40859-1-shentey@gmail.com> Signed-off-by: Laurent Vivier --- softmmu/device_tree.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c index 3965c834ca..31d1066940 100644 --- a/softmmu/device_tree.c +++ b/softmmu/device_tree.c @@ -60,7 +60,8 @@ void *create_device_tree(int *sizep) } ret = fdt_open_into(fdt, fdt, *sizep); if (ret) { - error_report("Unable to copy device tree in memory"); + error_report("%s: Unable to copy device tree into memory: %s", + __func__, fdt_strerror(ret)); exit(1); } @@ -104,7 +105,8 @@ void *load_device_tree(const char *filename_path, int *sizep) ret = fdt_open_into(fdt, fdt, dt_size); if (ret) { - error_report("Unable to copy device tree in memory"); + error_report("%s: Unable to copy device tree into memory: %s", + __func__, fdt_strerror(ret)); goto fail; } From 5b602fc4ed1e621d892e6d17879a882512e3b553 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 14 Jan 2022 18:25:35 +0000 Subject: [PATCH 537/730] linux-user: Fix comment typo in arm cpu_loop code Fix a typo in a comment in the arm cpu_loop code. Signed-off-by: Peter Maydell Reviewed-by: Warner Losh Message-Id: <20220114182535.3804783-1-peter.maydell@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/arm/cpu_loop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c index f153ab503a..032e1ffddf 100644 --- a/linux-user/arm/cpu_loop.c +++ b/linux-user/arm/cpu_loop.c @@ -434,8 +434,8 @@ void cpu_loop(CPUARMState *env) case 0x6: /* Access flag fault, level 2 */ case 0x9: /* Domain fault, level 1 */ case 0xb: /* Domain fault, level 2 */ - case 0xd: /* Permision fault, level 1 */ - case 0xf: /* Permision fault, level 2 */ + case 0xd: /* Permission fault, level 1 */ + case 0xf: /* Permission fault, level 2 */ si_signo = TARGET_SIGSEGV; si_code = TARGET_SEGV_ACCERR; break; From b5f9536643faa8a6a7b9e78d0944503a49a90fe3 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 14 Jan 2022 15:37:31 +0000 Subject: [PATCH 538/730] linux-user: Rename user_force_sig tracepoint to match function name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit c599d4d6d6e9bfdb64 in 2016 we renamed the old force_sig() function to dump_core_and_abort(), but we forgot to rename the associated tracepoint. Rename the tracepoint to to match the function it's called from. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220114153732.3767229-3-peter.maydell@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/signal.c | 2 +- linux-user/trace-events | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index f813b4f18e..bfbbeab9ad 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -734,7 +734,7 @@ static void QEMU_NORETURN dump_core_and_abort(int target_sig) struct sigaction act; host_sig = target_to_host_signal(target_sig); - trace_user_force_sig(env, target_sig, host_sig); + trace_user_dump_core_and_abort(env, target_sig, host_sig); gdb_signalled(env, target_sig); /* dump core if supported by target binary format */ diff --git a/linux-user/trace-events b/linux-user/trace-events index e7d2f54e94..f33717f248 100644 --- a/linux-user/trace-events +++ b/linux-user/trace-events @@ -9,7 +9,7 @@ user_setup_frame(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64 user_setup_rt_frame(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64 user_do_rt_sigreturn(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64 user_do_sigreturn(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64 -user_force_sig(void *env, int target_sig, int host_sig) "env=%p signal %d (host %d)" +user_dump_core_and_abort(void *env, int target_sig, int host_sig) "env=%p signal %d (host %d)" user_handle_signal(void *env, int target_sig) "env=%p signal %d" user_host_signal(void *env, int host_sig, int target_sig) "env=%p signal %d (target %d)" user_queue_signal(void *env, int target_sig) "env=%p signal %d" From 337e88d8909b1442956acfa351d48e30a272251c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 14 Jan 2022 15:37:32 +0000 Subject: [PATCH 539/730] linux-user: Return void from queue_signal() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The linux-user queue_signal() function always returns 1, and none of its callers check the return value. Give it a void return type instead. The return value is a leftover from the old pre-2016 linux-user signal handling code, which really did have a queue of signals and so might return a failure indication if too many signals were queued at once. The current design avoids having to ever have more than one signal queued via queue_signal() at once, so it can never fail. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220114153732.3767229-4-peter.maydell@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/signal-common.h | 4 ++-- linux-user/signal.c | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h index 42aa479080..2113165a75 100644 --- a/linux-user/signal-common.h +++ b/linux-user/signal-common.h @@ -59,8 +59,8 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, void process_pending_signals(CPUArchState *cpu_env); void signal_init(void); -int queue_signal(CPUArchState *env, int sig, int si_type, - target_siginfo_t *info); +void queue_signal(CPUArchState *env, int sig, int si_type, + target_siginfo_t *info); void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info); void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo); int target_to_host_signal(int sig); diff --git a/linux-user/signal.c b/linux-user/signal.c index bfbbeab9ad..32854bb375 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -780,8 +780,8 @@ static void QEMU_NORETURN dump_core_and_abort(int target_sig) /* queue a signal so that it will be send to the virtual CPU as soon as possible */ -int queue_signal(CPUArchState *env, int sig, int si_type, - target_siginfo_t *info) +void queue_signal(CPUArchState *env, int sig, int si_type, + target_siginfo_t *info) { CPUState *cpu = env_cpu(env); TaskState *ts = cpu->opaque; @@ -794,7 +794,6 @@ int queue_signal(CPUArchState *env, int sig, int si_type, ts->sync_signal.pending = sig; /* signal that a new signal is pending */ qatomic_set(&ts->signal_pending, 1); - return 1; /* indicates that the signal was queued */ } From bfadf13f63d63d099bf2be14c9b1863f25a091a2 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Sun, 16 Jan 2022 13:44:22 -0700 Subject: [PATCH 540/730] linux-user: Remove MAX_SIGQUEUE_SIZE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's been unused for 7 years since 907f5fddaa67 when linux-user stopped queueing any signals. Signed-off-by: Warner Losh Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220116204423.16133-2-imp@bsdimp.com> Signed-off-by: Laurent Vivier --- linux-user/qemu.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 5c713fa8ab..7910ce59cc 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -89,8 +89,6 @@ struct vm86_saved_state { #include "nwfpe/fpa11.h" #endif -#define MAX_SIGQUEUE_SIZE 1024 - struct emulated_sigtable { int pending; /* true if signal is pending */ target_siginfo_t info; From ce0a7982855afd873600a4180161adbfaef24cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 11:19:08 +0100 Subject: [PATCH 541/730] hw/rdma/rdma_utils: Rename rdma_pci_dma_map 'len' argument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Various APIs use 'pval' naming for 'pointer to val'. rdma_pci_dma_map() uses 'plen' for 'PCI length', but since 'PCI' is already explicit in the function name, simplify and rename the argument 'len'. No logical change. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: David Hildenbrand Reviewed-by: Yuval Shaia Tested-by: Yuval Shaia Message-Id: <20220111184309.28637-7-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- hw/rdma/rdma_utils.c | 14 +++++++------- hw/rdma/rdma_utils.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hw/rdma/rdma_utils.c b/hw/rdma/rdma_utils.c index 98df58f689..61cb8ede0f 100644 --- a/hw/rdma/rdma_utils.c +++ b/hw/rdma/rdma_utils.c @@ -17,29 +17,29 @@ #include "trace.h" #include "rdma_utils.h" -void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t plen) +void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t len) { void *p; - hwaddr len = plen; + hwaddr pci_len = len; if (!addr) { rdma_error_report("addr is NULL"); return NULL; } - p = pci_dma_map(dev, addr, &len, DMA_DIRECTION_TO_DEVICE); + p = pci_dma_map(dev, addr, &pci_len, DMA_DIRECTION_TO_DEVICE); if (!p) { rdma_error_report("pci_dma_map fail, addr=0x%"PRIx64", len=%"PRId64, - addr, len); + addr, pci_len); return NULL; } - if (len != plen) { - rdma_pci_dma_unmap(dev, p, len); + if (pci_len != len) { + rdma_pci_dma_unmap(dev, p, pci_len); return NULL; } - trace_rdma_pci_dma_map(addr, p, len); + trace_rdma_pci_dma_map(addr, p, pci_len); return p; } diff --git a/hw/rdma/rdma_utils.h b/hw/rdma/rdma_utils.h index 9fd0efd940..0c6414e7e0 100644 --- a/hw/rdma/rdma_utils.h +++ b/hw/rdma/rdma_utils.h @@ -38,7 +38,7 @@ typedef struct RdmaProtectedGSList { GSList *list; } RdmaProtectedGSList; -void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t plen); +void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t len); void rdma_pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len); void rdma_protected_gqueue_init(RdmaProtectedGQueue *list); void rdma_protected_gqueue_destroy(RdmaProtectedGQueue *list); From 5f412602ded57bbdce614685eba915f6042dda1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 11:13:34 +0100 Subject: [PATCH 542/730] hw/scsi: Rename SCSIRequest::resid as 'residual' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'resid' field is slightly confusing and could be interpreted as some ID. Rename it as 'residual' which is clearer to review. No logical change. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20220111184309.28637-8-f4bug@amsat.org> Signed-off-by: Philippe Mathieu-Daudé --- hw/scsi/megasas.c | 42 +++++++++++++++++++++++++----------------- hw/scsi/scsi-bus.c | 10 +++++----- hw/scsi/scsi-disk.c | 4 ++-- include/hw/scsi/scsi.h | 4 ++-- softmmu/dma-helpers.c | 26 +++++++++++++------------- 5 files changed, 47 insertions(+), 39 deletions(-) diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index dc9bbdb740..cb01954937 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -1045,7 +1045,8 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, uint64_t pd_size; uint16_t pd_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); uint8_t cmdbuf[6]; - size_t len, resid; + size_t len; + size_t residual; if (!cmd->iov_buf) { cmd->iov_buf = g_malloc0(dcmd_size); @@ -1112,9 +1113,10 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, info->connected_port_bitmap = 0x1; info->device_speed = 1; info->link_speed = 1; - resid = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + residual = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); g_free(cmd->iov_buf); - cmd->iov_size = dcmd_size - resid; + cmd->iov_size = dcmd_size - residual; cmd->iov_buf = NULL; return MFI_STAT_OK; } @@ -1149,7 +1151,8 @@ static int megasas_dcmd_pd_get_info(MegasasState *s, MegasasCmd *cmd) static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) { struct mfi_ld_list info; - size_t dcmd_size = sizeof(info), resid; + size_t dcmd_size = sizeof(info); + size_t residual; uint32_t num_ld_disks = 0, max_ld_disks; uint64_t ld_size; BusChild *kid; @@ -1184,8 +1187,9 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) info.ld_count = cpu_to_le32(num_ld_disks); trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); - resid = dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); - cmd->iov_size = dcmd_size - resid; + residual = dma_buf_read(&info, dcmd_size, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size = dcmd_size - residual; return MFI_STAT_OK; } @@ -1193,7 +1197,8 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd) { uint16_t flags; struct mfi_ld_targetid_list info; - size_t dcmd_size = sizeof(info), resid; + size_t dcmd_size = sizeof(info); + size_t residual; uint32_t num_ld_disks = 0, max_ld_disks = s->fw_luns; BusChild *kid; @@ -1233,8 +1238,9 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd) info.size = dcmd_size; trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); - resid = dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); - cmd->iov_size = dcmd_size - resid; + residual = dma_buf_read(&info, dcmd_size, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size = dcmd_size - residual; return MFI_STAT_OK; } @@ -1244,7 +1250,8 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, struct mfi_ld_info *info = cmd->iov_buf; size_t dcmd_size = sizeof(struct mfi_ld_info); uint8_t cdb[6]; - ssize_t len, resid; + ssize_t len; + size_t residual; uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); uint64_t ld_size; @@ -1283,9 +1290,10 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, info->ld_config.span[0].num_blocks = info->size; info->ld_config.span[0].array_ref = cpu_to_le16(sdev_id); - resid = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + residual = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); g_free(cmd->iov_buf); - cmd->iov_size = dcmd_size - resid; + cmd->iov_size = dcmd_size - residual; cmd->iov_buf = NULL; return MFI_STAT_OK; } @@ -1617,13 +1625,13 @@ static int megasas_handle_dcmd(MegasasState *s, MegasasCmd *cmd) } static int megasas_finish_internal_dcmd(MegasasCmd *cmd, - SCSIRequest *req, size_t resid) + SCSIRequest *req, size_t residual) { int retval = MFI_STAT_OK; int lun = req->lun; trace_megasas_dcmd_internal_finish(cmd->index, cmd->dcmd_opcode, lun); - cmd->iov_size -= resid; + cmd->iov_size -= residual; switch (cmd->dcmd_opcode) { case MFI_DCMD_PD_GET_INFO: retval = megasas_pd_get_info_submit(req->dev, lun, cmd); @@ -1865,12 +1873,12 @@ static void megasas_xfer_complete(SCSIRequest *req, uint32_t len) } } -static void megasas_command_complete(SCSIRequest *req, size_t resid) +static void megasas_command_complete(SCSIRequest *req, size_t residual) { MegasasCmd *cmd = req->hba_private; uint8_t cmd_status = MFI_STAT_OK; - trace_megasas_command_complete(cmd->index, req->status, resid); + trace_megasas_command_complete(cmd->index, req->status, residual); if (req->io_canceled) { return; @@ -1880,7 +1888,7 @@ static void megasas_command_complete(SCSIRequest *req, size_t resid) /* * Internal command complete */ - cmd_status = megasas_finish_internal_dcmd(cmd, req, resid); + cmd_status = megasas_finish_internal_dcmd(cmd, req, residual); if (cmd_status == MFI_STAT_INVALID_STATUS) { return; } diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 2b5e9dca31..3466e680ac 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -760,7 +760,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, } req->cmd = cmd; - req->resid = req->cmd.xfer; + req->residual = req->cmd.xfer; switch (buf[0]) { case INQUIRY: @@ -1408,7 +1408,7 @@ void scsi_req_data(SCSIRequest *req, int len) trace_scsi_req_data(req->dev->id, req->lun, req->tag, len); assert(req->cmd.mode != SCSI_XFER_NONE); if (!req->sg) { - req->resid -= len; + req->residual -= len; req->bus->info->transfer_data(req, len); return; } @@ -1421,9 +1421,9 @@ void scsi_req_data(SCSIRequest *req, int len) buf = scsi_req_get_buf(req); if (req->cmd.mode == SCSI_XFER_FROM_DEV) { - req->resid = dma_buf_read(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); + req->residual = dma_buf_read(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); } else { - req->resid = dma_buf_write(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); + req->residual = dma_buf_write(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); } scsi_req_continue(req); } @@ -1512,7 +1512,7 @@ void scsi_req_complete(SCSIRequest *req, int status) scsi_req_ref(req); scsi_req_dequeue(req); - req->bus->info->complete(req, req->resid); + req->bus->info->complete(req, req->residual); /* Cancelled requests might end up being completed instead of cancelled */ notifier_list_notify(&req->cancel_notifiers, req); diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index d4914178ea..9c0dc7b946 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -420,7 +420,7 @@ static void scsi_do_read(SCSIDiskReq *r, int ret) if (r->req.sg) { dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BLOCK_ACCT_READ); - r->req.resid -= r->req.sg->size; + r->req.residual -= r->req.sg->size; r->req.aiocb = dma_blk_io(blk_get_aio_context(s->qdev.conf.blk), r->req.sg, r->sector << BDRV_SECTOR_BITS, BDRV_SECTOR_SIZE, @@ -580,7 +580,7 @@ static void scsi_write_data(SCSIRequest *req) if (r->req.sg) { dma_acct_start(s->qdev.conf.blk, &r->acct, r->req.sg, BLOCK_ACCT_WRITE); - r->req.resid -= r->req.sg->size; + r->req.residual -= r->req.sg->size; r->req.aiocb = dma_blk_io(blk_get_aio_context(s->qdev.conf.blk), r->req.sg, r->sector << BDRV_SECTOR_BITS, BDRV_SECTOR_SIZE, diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 2ef80af6dc..b27d133b11 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -30,7 +30,7 @@ struct SCSIRequest { int16_t status; int16_t host_status; void *hba_private; - size_t resid; + size_t residual; SCSICommand cmd; NotifierList cancel_notifiers; @@ -125,7 +125,7 @@ struct SCSIBusInfo { void *hba_private); void (*transfer_data)(SCSIRequest *req, uint32_t arg); void (*fail)(SCSIRequest *req); - void (*complete)(SCSIRequest *req, size_t resid); + void (*complete)(SCSIRequest *req, size_t residual); void (*cancel)(SCSIRequest *req); void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense); QEMUSGList *(*get_sg_list)(SCSIRequest *req); diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index b0be156479..4563a775aa 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -294,49 +294,49 @@ BlockAIOCB *dma_blk_write(BlockBackend *blk, } -static MemTxResult dma_buf_rw(void *buf, int32_t len, uint64_t *residp, +static MemTxResult dma_buf_rw(void *buf, int32_t len, uint64_t *residual, QEMUSGList *sg, DMADirection dir, MemTxAttrs attrs) { uint8_t *ptr = buf; - uint64_t resid; + uint64_t xresidual; int sg_cur_index; MemTxResult res = MEMTX_OK; - resid = sg->size; + xresidual = sg->size; sg_cur_index = 0; - len = MIN(len, resid); + len = MIN(len, xresidual); while (len > 0) { ScatterGatherEntry entry = sg->sg[sg_cur_index++]; int32_t xfer = MIN(len, entry.len); res |= dma_memory_rw(sg->as, entry.base, ptr, xfer, dir, attrs); ptr += xfer; len -= xfer; - resid -= xfer; + xresidual -= xfer; } - if (residp) { - *residp = resid; + if (residual) { + *residual = xresidual; } return res; } uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) { - uint64_t resid; + uint64_t residual; - dma_buf_rw(ptr, len, &resid, sg, DMA_DIRECTION_FROM_DEVICE, attrs); + dma_buf_rw(ptr, len, &residual, sg, DMA_DIRECTION_FROM_DEVICE, attrs); - return resid; + return residual; } uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) { - uint64_t resid; + uint64_t residual; - dma_buf_rw(ptr, len, &resid, sg, DMA_DIRECTION_TO_DEVICE, attrs); + dma_buf_rw(ptr, len, &residual, sg, DMA_DIRECTION_TO_DEVICE, attrs); - return resid; + return residual; } void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, From 60791a2c27e1b8f82ff035a474b2f96f0fafa66c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 4 Jan 2022 09:42:21 +0100 Subject: [PATCH 543/730] hw/dma: Fix format string issues using dma_addr_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Richard Henderson Reviewed-by: David Hildenbrand Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20220111184309.28637-10-f4bug@amsat.org> --- hw/ide/ahci.c | 2 +- hw/rdma/trace-events | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 205dfdc662..6c727dd0c0 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1159,7 +1159,7 @@ static void process_ncq_command(AHCIState *s, int port, const uint8_t *cmd_fis, ahci_populate_sglist(ad, &ncq_tfs->sglist, ncq_tfs->cmdh, size, 0); if (ncq_tfs->sglist.size < size) { - error_report("ahci: PRDT length for NCQ command (0x%zx) " + error_report("ahci: PRDT length for NCQ command (0x" DMA_ADDR_FMT ") " "is smaller than the requested size (0x%zx)", ncq_tfs->sglist.size, size); ncq_err(ncq_tfs); diff --git a/hw/rdma/trace-events b/hw/rdma/trace-events index 9accb14973..c23175120e 100644 --- a/hw/rdma/trace-events +++ b/hw/rdma/trace-events @@ -27,5 +27,5 @@ rdma_rm_alloc_qp(uint32_t rm_qpn, uint32_t backend_qpn, uint8_t qp_type) "rm_qpn rdma_rm_modify_qp(uint32_t qpn, uint32_t attr_mask, int qp_state, uint8_t sgid_idx) "qpn=0x%x, attr_mask=0x%x, qp_state=%d, sgid_idx=%d" # rdma_utils.c -rdma_pci_dma_map(uint64_t addr, void *vaddr, uint64_t len) "0x%"PRIx64" -> %p (len=%" PRId64")" +rdma_pci_dma_map(uint64_t addr, void *vaddr, uint64_t len) "0x%"PRIx64" -> %p (len=%" PRIu64")" rdma_pci_dma_unmap(void *vaddr) "%p" From 026644cf5f9fd8c27ea7f4f2fd4fea8102b30001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 11 Jan 2022 11:32:22 +0100 Subject: [PATCH 544/730] hw/dma: Move ScatterGatherEntry / QEMUSGList declarations around MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the next commit we will use the dma_addr_t type in the QEMUSGList structure. Since currently dma_addr_t is defined after QEMUSGList, move the declarations to have dma_addr_t defined first. This is a pure code-movement patch. Suggested-by: David Hildenbrand Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: David Hildenbrand Message-Id: <20220111184309.28637-10-f4bug@amsat.org> --- include/sysemu/dma.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 0db2478a50..c992d9d5d6 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -15,22 +15,11 @@ #include "block/block.h" #include "block/accounting.h" -typedef struct ScatterGatherEntry ScatterGatherEntry; - typedef enum { DMA_DIRECTION_TO_DEVICE = 0, DMA_DIRECTION_FROM_DEVICE = 1, } DMADirection; -struct QEMUSGList { - ScatterGatherEntry *sg; - int nsg; - int nalloc; - size_t size; - DeviceState *dev; - AddressSpace *as; -}; - /* * When an IOMMU is present, bus addresses become distinct from * CPU/memory physical addresses and may be a different size. Because @@ -43,6 +32,17 @@ typedef uint64_t dma_addr_t; #define DMA_ADDR_BITS 64 #define DMA_ADDR_FMT "%" PRIx64 +typedef struct ScatterGatherEntry ScatterGatherEntry; + +struct QEMUSGList { + ScatterGatherEntry *sg; + int nsg; + int nalloc; + size_t size; + DeviceState *dev; + AddressSpace *as; +}; + static inline void dma_barrier(AddressSpace *as, DMADirection dir) { /* From bfa30f3903e0542611196b21f5832a4be5775a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 31 Dec 2021 11:33:29 +0100 Subject: [PATCH 545/730] hw/dma: Use dma_addr_t type definition when relevant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the obvious places where dma_addr_t should be used (instead of uint64_t, hwaddr, size_t, int32_t types). This allows to have &dma_addr_t type portable on 32/64-bit hosts. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: David Hildenbrand Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20220111184309.28637-11-f4bug@amsat.org> --- hw/nvme/ctrl.c | 2 +- hw/rdma/rdma_utils.c | 2 +- hw/scsi/megasas.c | 10 +++++----- include/sysemu/dma.h | 8 +++++--- softmmu/dma-helpers.c | 16 +++++++++------- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 462f79a1f6..c3c4917611 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -1147,7 +1147,7 @@ static uint16_t nvme_tx(NvmeCtrl *n, NvmeSg *sg, uint8_t *ptr, uint32_t len, if (sg->flags & NVME_SG_DMA) { const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; - uint64_t residual; + dma_addr_t residual; if (dir == NVME_TX_DIRECTION_TO_DEVICE) { residual = dma_buf_write(ptr, len, &sg->qsg, attrs); diff --git a/hw/rdma/rdma_utils.c b/hw/rdma/rdma_utils.c index 61cb8ede0f..5a7ef63ad2 100644 --- a/hw/rdma/rdma_utils.c +++ b/hw/rdma/rdma_utils.c @@ -20,7 +20,7 @@ void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t len) { void *p; - hwaddr pci_len = len; + dma_addr_t pci_len = len; if (!addr) { rdma_error_report("addr is NULL"); diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index cb01954937..6c1ae6b980 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -1046,7 +1046,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, uint16_t pd_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); uint8_t cmdbuf[6]; size_t len; - size_t residual; + dma_addr_t residual; if (!cmd->iov_buf) { cmd->iov_buf = g_malloc0(dcmd_size); @@ -1152,7 +1152,7 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) { struct mfi_ld_list info; size_t dcmd_size = sizeof(info); - size_t residual; + dma_addr_t residual; uint32_t num_ld_disks = 0, max_ld_disks; uint64_t ld_size; BusChild *kid; @@ -1198,7 +1198,7 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd) uint16_t flags; struct mfi_ld_targetid_list info; size_t dcmd_size = sizeof(info); - size_t residual; + dma_addr_t residual; uint32_t num_ld_disks = 0, max_ld_disks = s->fw_luns; BusChild *kid; @@ -1251,7 +1251,7 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, size_t dcmd_size = sizeof(struct mfi_ld_info); uint8_t cdb[6]; ssize_t len; - size_t residual; + dma_addr_t residual; uint16_t sdev_id = ((sdev->id & 0xFF) << 8) | (lun & 0xFF); uint64_t ld_size; @@ -1625,7 +1625,7 @@ static int megasas_handle_dcmd(MegasasState *s, MegasasCmd *cmd) } static int megasas_finish_internal_dcmd(MegasasCmd *cmd, - SCSIRequest *req, size_t residual) + SCSIRequest *req, dma_addr_t residual) { int retval = MFI_STAT_OK; int lun = req->lun; diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index c992d9d5d6..36039c5e68 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -38,7 +38,7 @@ struct QEMUSGList { ScatterGatherEntry *sg; int nsg; int nalloc; - size_t size; + dma_addr_t size; DeviceState *dev; AddressSpace *as; }; @@ -301,8 +301,10 @@ BlockAIOCB *dma_blk_read(BlockBackend *blk, BlockAIOCB *dma_blk_write(BlockBackend *blk, QEMUSGList *sg, uint64_t offset, uint32_t align, BlockCompletionFunc *cb, void *opaque); -uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs); -uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs); +dma_addr_t dma_buf_read(void *ptr, dma_addr_t len, + QEMUSGList *sg, MemTxAttrs attrs); +dma_addr_t dma_buf_write(void *ptr, dma_addr_t len, + QEMUSGList *sg, MemTxAttrs attrs); void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, QEMUSGList *sg, enum BlockAcctType type); diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 4563a775aa..916cf12ed4 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -294,12 +294,12 @@ BlockAIOCB *dma_blk_write(BlockBackend *blk, } -static MemTxResult dma_buf_rw(void *buf, int32_t len, uint64_t *residual, +static MemTxResult dma_buf_rw(void *buf, dma_addr_t len, dma_addr_t *residual, QEMUSGList *sg, DMADirection dir, MemTxAttrs attrs) { uint8_t *ptr = buf; - uint64_t xresidual; + dma_addr_t xresidual; int sg_cur_index; MemTxResult res = MEMTX_OK; @@ -308,7 +308,7 @@ static MemTxResult dma_buf_rw(void *buf, int32_t len, uint64_t *residual, len = MIN(len, xresidual); while (len > 0) { ScatterGatherEntry entry = sg->sg[sg_cur_index++]; - int32_t xfer = MIN(len, entry.len); + dma_addr_t xfer = MIN(len, entry.len); res |= dma_memory_rw(sg->as, entry.base, ptr, xfer, dir, attrs); ptr += xfer; len -= xfer; @@ -321,18 +321,20 @@ static MemTxResult dma_buf_rw(void *buf, int32_t len, uint64_t *residual, return res; } -uint64_t dma_buf_read(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) +dma_addr_t dma_buf_read(void *ptr, dma_addr_t len, + QEMUSGList *sg, MemTxAttrs attrs) { - uint64_t residual; + dma_addr_t residual; dma_buf_rw(ptr, len, &residual, sg, DMA_DIRECTION_FROM_DEVICE, attrs); return residual; } -uint64_t dma_buf_write(void *ptr, int32_t len, QEMUSGList *sg, MemTxAttrs attrs) +dma_addr_t dma_buf_write(void *ptr, dma_addr_t len, + QEMUSGList *sg, MemTxAttrs attrs) { - uint64_t residual; + dma_addr_t residual; dma_buf_rw(ptr, len, &residual, sg, DMA_DIRECTION_TO_DEVICE, attrs); From f02b664aad8f1aaafbcdf45285f6fcab0a4bd5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 16 Dec 2021 09:36:38 +0100 Subject: [PATCH 546/730] hw/dma: Let dma_buf_read() / dma_buf_write() propagate MemTxResult MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 292e13142d2, dma_buf_rw() returns a MemTxResult type. Do not discard it, return it to the caller. Pass the previously returned value (the QEMUSGList residual size, which was rarely used) as an optional argument. With this new API, SCSIRequest::residual might now be accessed via a pointer. Since the size_t type does not have the same size on 32 and 64-bit host architectures, convert it to a uint64_t, which is big enough to hold the residual size, and the type is constant on both 32/64-bit hosts. Update the few dma_buf_read() / dma_buf_write() callers to the new API. Reviewed-by: Klaus Jensen Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé Acked-by: Peter Xu Message-Id: <20220117125130.131828-1-f4bug@amsat.org> --- hw/ide/ahci.c | 8 +++--- hw/nvme/ctrl.c | 4 +-- hw/scsi/megasas.c | 59 ++++++++++++++++++++++++++++++------------ hw/scsi/scsi-bus.c | 6 +++-- include/hw/scsi/scsi.h | 2 +- include/sysemu/dma.h | 4 +-- softmmu/dma-helpers.c | 16 +++--------- 7 files changed, 59 insertions(+), 40 deletions(-) diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 6c727dd0c0..7ce001cacd 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1384,9 +1384,9 @@ static void ahci_pio_transfer(const IDEDMA *dma) const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; if (is_write) { - dma_buf_write(s->data_ptr, size, &s->sg, attrs); + dma_buf_write(s->data_ptr, size, NULL, &s->sg, attrs); } else { - dma_buf_read(s->data_ptr, size, &s->sg, attrs); + dma_buf_read(s->data_ptr, size, NULL, &s->sg, attrs); } } @@ -1479,9 +1479,9 @@ static int ahci_dma_rw_buf(const IDEDMA *dma, bool is_write) } if (is_write) { - dma_buf_read(p, l, &s->sg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(p, l, NULL, &s->sg, MEMTXATTRS_UNSPECIFIED); } else { - dma_buf_write(p, l, &s->sg, MEMTXATTRS_UNSPECIFIED); + dma_buf_write(p, l, NULL, &s->sg, MEMTXATTRS_UNSPECIFIED); } /* free sglist, update byte count */ diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index c3c4917611..1f62116af9 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -1150,9 +1150,9 @@ static uint16_t nvme_tx(NvmeCtrl *n, NvmeSg *sg, uint8_t *ptr, uint32_t len, dma_addr_t residual; if (dir == NVME_TX_DIRECTION_TO_DEVICE) { - residual = dma_buf_write(ptr, len, &sg->qsg, attrs); + dma_buf_write(ptr, len, &residual, &sg->qsg, attrs); } else { - residual = dma_buf_read(ptr, len, &sg->qsg, attrs); + dma_buf_read(ptr, len, &residual, &sg->qsg, attrs); } if (unlikely(residual)) { diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 6c1ae6b980..de613c8b35 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -750,6 +750,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) size_t dcmd_size = sizeof(info); BusChild *kid; int num_pd_disks = 0; + dma_addr_t residual; memset(&info, 0x0, dcmd_size); if (cmd->iov_size < dcmd_size) { @@ -860,7 +861,9 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) MFI_INFO_PDMIX_SATA | MFI_INFO_PDMIX_LD); - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -868,6 +871,7 @@ static int megasas_mfc_get_defaults(MegasasState *s, MegasasCmd *cmd) { struct mfi_defaults info; size_t dcmd_size = sizeof(struct mfi_defaults); + dma_addr_t residual; memset(&info, 0x0, dcmd_size); if (cmd->iov_size < dcmd_size) { @@ -890,7 +894,9 @@ static int megasas_mfc_get_defaults(MegasasState *s, MegasasCmd *cmd) info.disable_preboot_cli = 1; info.cluster_disable = 1; - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -898,6 +904,7 @@ static int megasas_dcmd_get_bios_info(MegasasState *s, MegasasCmd *cmd) { struct mfi_bios_data info; size_t dcmd_size = sizeof(info); + dma_addr_t residual; memset(&info, 0x0, dcmd_size); if (cmd->iov_size < dcmd_size) { @@ -911,7 +918,9 @@ static int megasas_dcmd_get_bios_info(MegasasState *s, MegasasCmd *cmd) info.expose_all_drives = 1; } - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -919,10 +928,13 @@ static int megasas_dcmd_get_fw_time(MegasasState *s, MegasasCmd *cmd) { uint64_t fw_time; size_t dcmd_size = sizeof(fw_time); + dma_addr_t residual; fw_time = cpu_to_le64(megasas_fw_time()); - cmd->iov_size -= dma_buf_read(&fw_time, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&fw_time, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -942,6 +954,7 @@ static int megasas_event_info(MegasasState *s, MegasasCmd *cmd) { struct mfi_evt_log_state info; size_t dcmd_size = sizeof(info); + dma_addr_t residual; memset(&info, 0, dcmd_size); @@ -949,7 +962,9 @@ static int megasas_event_info(MegasasState *s, MegasasCmd *cmd) info.shutdown_seq_num = cpu_to_le32(s->shutdown_event); info.boot_seq_num = cpu_to_le32(s->boot_event); - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -979,6 +994,7 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd) size_t dcmd_size = sizeof(info); BusChild *kid; uint32_t offset, dcmd_limit, num_pd_disks = 0, max_pd_disks; + dma_addr_t residual; memset(&info, 0, dcmd_size); offset = 8; @@ -1018,7 +1034,9 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd) info.size = cpu_to_le32(offset); info.count = cpu_to_le32(num_pd_disks); - cmd->iov_size -= dma_buf_read(&info, offset, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, offset, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -1113,8 +1131,9 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, info->connected_port_bitmap = 0x1; info->device_speed = 1; info->link_speed = 1; - residual = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, - MEMTXATTRS_UNSPECIFIED); + dma_buf_read(cmd->iov_buf, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; g_free(cmd->iov_buf); cmd->iov_size = dcmd_size - residual; cmd->iov_buf = NULL; @@ -1187,8 +1206,8 @@ static int megasas_dcmd_ld_get_list(MegasasState *s, MegasasCmd *cmd) info.ld_count = cpu_to_le32(num_ld_disks); trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); - residual = dma_buf_read(&info, dcmd_size, &cmd->qsg, - MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); cmd->iov_size = dcmd_size - residual; return MFI_STAT_OK; } @@ -1238,8 +1257,8 @@ static int megasas_dcmd_ld_list_query(MegasasState *s, MegasasCmd *cmd) info.size = dcmd_size; trace_megasas_dcmd_ld_get_list(cmd->index, num_ld_disks, max_ld_disks); - residual = dma_buf_read(&info, dcmd_size, &cmd->qsg, - MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); cmd->iov_size = dcmd_size - residual; return MFI_STAT_OK; } @@ -1290,8 +1309,8 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, info->ld_config.span[0].num_blocks = info->size; info->ld_config.span[0].array_ref = cpu_to_le16(sdev_id); - residual = dma_buf_read(cmd->iov_buf, dcmd_size, &cmd->qsg, - MEMTXATTRS_UNSPECIFIED); + dma_buf_read(cmd->iov_buf, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); g_free(cmd->iov_buf); cmd->iov_size = dcmd_size - residual; cmd->iov_buf = NULL; @@ -1336,6 +1355,7 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd) struct mfi_config_data *info; int num_pd_disks = 0, array_offset, ld_offset; BusChild *kid; + dma_addr_t residual; if (cmd->iov_size > 4096) { return MFI_STAT_INVALID_PARAMETER; @@ -1410,7 +1430,9 @@ static int megasas_dcmd_cfg_read(MegasasState *s, MegasasCmd *cmd) ld_offset += sizeof(struct mfi_ld_config); } - cmd->iov_size -= dma_buf_read(data, info->size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(data, info->size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -1418,6 +1440,7 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd) { struct mfi_ctrl_props info; size_t dcmd_size = sizeof(info); + dma_addr_t residual; memset(&info, 0x0, dcmd_size); if (cmd->iov_size < dcmd_size) { @@ -1440,7 +1463,9 @@ static int megasas_dcmd_get_properties(MegasasState *s, MegasasCmd *cmd) info.ecc_bucket_leak_rate = cpu_to_le16(1440); info.expose_encl_devices = 1; - cmd->iov_size -= dma_buf_read(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(&info, dcmd_size, &residual, &cmd->qsg, + MEMTXATTRS_UNSPECIFIED); + cmd->iov_size -= residual; return MFI_STAT_OK; } @@ -1485,7 +1510,7 @@ static int megasas_dcmd_set_properties(MegasasState *s, MegasasCmd *cmd) dcmd_size); return MFI_STAT_INVALID_PARAMETER; } - dma_buf_write(&info, dcmd_size, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); + dma_buf_write(&info, dcmd_size, NULL, &cmd->qsg, MEMTXATTRS_UNSPECIFIED); trace_megasas_dcmd_unsupported(cmd->index, cmd->iov_size); return MFI_STAT_OK; } diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 3466e680ac..4057e04ce8 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -1421,9 +1421,11 @@ void scsi_req_data(SCSIRequest *req, int len) buf = scsi_req_get_buf(req); if (req->cmd.mode == SCSI_XFER_FROM_DEV) { - req->residual = dma_buf_read(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); + dma_buf_read(buf, len, &req->residual, req->sg, + MEMTXATTRS_UNSPECIFIED); } else { - req->residual = dma_buf_write(buf, len, req->sg, MEMTXATTRS_UNSPECIFIED); + dma_buf_write(buf, len, &req->residual, req->sg, + MEMTXATTRS_UNSPECIFIED); } scsi_req_continue(req); } diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index b27d133b11..1ffb367f94 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -30,7 +30,7 @@ struct SCSIRequest { int16_t status; int16_t host_status; void *hba_private; - size_t residual; + uint64_t residual; SCSICommand cmd; NotifierList cancel_notifiers; diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 36039c5e68..a1ac5bc1b5 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -301,9 +301,9 @@ BlockAIOCB *dma_blk_read(BlockBackend *blk, BlockAIOCB *dma_blk_write(BlockBackend *blk, QEMUSGList *sg, uint64_t offset, uint32_t align, BlockCompletionFunc *cb, void *opaque); -dma_addr_t dma_buf_read(void *ptr, dma_addr_t len, +MemTxResult dma_buf_read(void *ptr, dma_addr_t len, dma_addr_t *residual, QEMUSGList *sg, MemTxAttrs attrs); -dma_addr_t dma_buf_write(void *ptr, dma_addr_t len, +MemTxResult dma_buf_write(void *ptr, dma_addr_t len, dma_addr_t *residual, QEMUSGList *sg, MemTxAttrs attrs); void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 916cf12ed4..1c6fba6a11 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -321,24 +321,16 @@ static MemTxResult dma_buf_rw(void *buf, dma_addr_t len, dma_addr_t *residual, return res; } -dma_addr_t dma_buf_read(void *ptr, dma_addr_t len, +MemTxResult dma_buf_read(void *ptr, dma_addr_t len, dma_addr_t *residual, QEMUSGList *sg, MemTxAttrs attrs) { - dma_addr_t residual; - - dma_buf_rw(ptr, len, &residual, sg, DMA_DIRECTION_FROM_DEVICE, attrs); - - return residual; + return dma_buf_rw(ptr, len, residual, sg, DMA_DIRECTION_FROM_DEVICE, attrs); } -dma_addr_t dma_buf_write(void *ptr, dma_addr_t len, +MemTxResult dma_buf_write(void *ptr, dma_addr_t len, dma_addr_t *residual, QEMUSGList *sg, MemTxAttrs attrs) { - dma_addr_t residual; - - dma_buf_rw(ptr, len, &residual, sg, DMA_DIRECTION_TO_DEVICE, attrs); - - return residual; + return dma_buf_rw(ptr, len, residual, sg, DMA_DIRECTION_TO_DEVICE, attrs); } void dma_acct_start(BlockBackend *blk, BlockAcctCookie *cookie, From 9d696cd50442327fd71ec7309e7b0c6fee693b1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 10 Jan 2022 17:51:04 +0000 Subject: [PATCH 547/730] docs/devel: add some clarifying text for aliases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We do mention the limitation of single parenthood for memory_region_add_subregion but lets also make it clear how aliases help solve that conundrum. Signed-off-by: Alex Bennée Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220110175104.2908956-7-alex.bennee@linaro.org> Signed-off-by: Philippe Mathieu-Daudé --- docs/devel/memory.rst | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/devel/memory.rst b/docs/devel/memory.rst index 5dc8a12682..69c5e3f914 100644 --- a/docs/devel/memory.rst +++ b/docs/devel/memory.rst @@ -67,11 +67,15 @@ MemoryRegion): You initialize a pure container with memory_region_init(). -- alias: a subsection of another region. Aliases allow a region to be - split apart into discontiguous regions. Examples of uses are memory banks - used when the guest address space is smaller than the amount of RAM - addressed, or a memory controller that splits main memory to expose a "PCI - hole". Aliases may point to any type of region, including other aliases, +- alias: a subsection of another region. Aliases allow a region to be + split apart into discontiguous regions. Examples of uses are memory + banks used when the guest address space is smaller than the amount + of RAM addressed, or a memory controller that splits main memory to + expose a "PCI hole". You can also create aliases to avoid trying to + add the original region to multiple parents via + `memory_region_add_subregion`. + + Aliases may point to any type of region, including other aliases, but an alias may not point back to itself, directly or indirectly. You initialize these with memory_region_init_alias(). From 8915106c6950e43f0cf0dd5d3092450f22ce5418 Mon Sep 17 00:00:00 2001 From: Leonardo Garcia Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 548/730] docs: rSTify ppc-spapr-hotplug.txt. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While working on this file, also removed and unused reference in the end of the file. The reference in the text was removed by commit 9f992cca93d (spapr: update spapr hotplug documentation), but the link in the end of the document was not removed then. Signed-off-by: Leonardo Garcia Reviewed-by: Daniel Henrique Barboza Message-Id: <50ed30232e0e6eafb580c17adec3fba17b873014.1641995058.git.lagarcia@br.ibm.com> Signed-off-by: Cédric Le Goater --- docs/specs/ppc-spapr-hotplug.txt | 685 ++++++++++++++++++------------- 1 file changed, 393 insertions(+), 292 deletions(-) diff --git a/docs/specs/ppc-spapr-hotplug.txt b/docs/specs/ppc-spapr-hotplug.txt index d4fb2d46d9..f84dc55ad9 100644 --- a/docs/specs/ppc-spapr-hotplug.txt +++ b/docs/specs/ppc-spapr-hotplug.txt @@ -1,224 +1,316 @@ -= sPAPR Dynamic Reconfiguration = +============================= +sPAPR Dynamic Reconfiguration +============================= -sPAPR/"pseries" guests make use of a facility called dynamic-reconfiguration -to handle hotplugging of dynamic "physical" resources like PCI cards, or -"logical"/paravirtual resources like memory, CPUs, and "physical" +sPAPR or pSeries guests make use of a facility called dynamic reconfiguration +to handle hot plugging of dynamic "physical" resources like PCI cards, or +"logical"/para-virtual resources like memory, CPUs, and "physical" host-bridges, which are generally managed by the host/hypervisor and provided -to guests as virtualized resources. The specifics of dynamic-reconfiguration -are documented extensively in PAPR+ v2.7, Section 13.1. This document -provides a summary of that information as it applies to the implementation -within QEMU. +to guests as virtualized resources. The specifics of dynamic reconfiguration +are documented extensively in section 13 of the Linux on Power Architecture +Reference document ([LoPAR]_). This document provides a summary of that +information as it applies to the implementation within QEMU. -== Dynamic-reconfiguration Connectors == +Dynamic-reconfiguration Connectors +================================== -To manage hotplug/unplug of these resources, a firmware abstraction known as +To manage hot plug/unplug of these resources, a firmware abstraction known as a Dynamic Resource Connector (DRC) is used to assign a particular dynamic resource to the guest, and provide an interface for the guest to manage configuration/removal of the resource associated with it. -== Device-tree description of DRCs == +Device tree description of DRCs +=============================== -A set of 4 Open Firmware device tree array properties are used to describe +A set of four Open Firmware device tree array properties are used to describe the name/index/power-domain/type of each DRC allocated to a guest at -boot-time. There may be multiple sets of these arrays, rooted at different +boot time. There may be multiple sets of these arrays, rooted at different paths in the device tree depending on the type of resource the DRCs manage. In some cases, the DRCs themselves may be provided by a dynamic resource, -such as the DRCs managing PCI slots on a hotplugged PHB. In this case the +such as the DRCs managing PCI slots on a hot plugged PHB. In this case the arrays would be fetched as part of the device tree retrieval interfaces -for hotplugged resources described under "Guest->Host interface". +for hot plugged resources described under :ref:`guest-host-interface`. The array properties are described below. Each entry/element in an array describes the DRC identified by the element in the corresponding position -of ibm,drc-indexes: +of ``ibm,drc-indexes``: -ibm,drc-names: - first 4-bytes: BE-encoded integer denoting the number of entries - each entry: a NULL-terminated string encoded as a byte array +``ibm,drc-names`` +----------------- - values for logical/virtual resources are defined in PAPR+ v2.7, - Section 13.5.2.4, and basically consist of the type of the resource - followed by a space and a numerical value that's unique across resources - of that type. + First 4-bytes: big-endian (BE) encoded integer denoting the number of entries. - values for "physical" resources such as PCI or VIO devices are - defined as being "location codes", which are the "location labels" of - each encapsulating device, starting from the chassis down to the - individual slot for the device, concatenated by a hyphen. This provides - a mapping of resources to a physical location in a chassis for debugging - purposes. For QEMU, this mapping is less important, so we assign a - location code that conforms to naming specifications, but is simply a - location label for the slot by itself to simplify the implementation. - The naming convention for location labels is documented in detail in - PAPR+ v2.7, Section 12.3.1.5, and in our case amounts to using "C" - for PCI/VIO device slots, where is unique across all PCI/VIO - device slots. + Each entry: a NULL-terminated ```` string encoded as a byte array. -ibm,drc-indexes: - first 4-bytes: BE-encoded integer denoting the number of entries - each 4-byte entry: BE-encoded integer that is unique across all DRCs - in the machine + ```` values for logical/virtual resources are defined in the Linux on + Power Architecture Reference ([LoPAR]_) section 13.5.2.4, and basically + consist of the type of the resource followed by a space and a numerical + value that's unique across resources of that type. - is arbitrary, but in the case of QEMU we try to maintain the - convention used to assign them to pSeries guests on pHyp: + ```` values for "physical" resources such as PCI or VIO devices are + defined as being "location codes", which are the "location labels" of each + encapsulating device, starting from the chassis down to the individual slot + for the device, concatenated by a hyphen. This provides a mapping of + resources to a physical location in a chassis for debugging purposes. For + QEMU, this mapping is less important, so we assign a location code that + conforms to naming specifications, but is simply a location label for the + slot by itself to simplify the implementation. The naming convention for + location labels is documented in detail in the [LoPAR]_ section 12.3.1.5, + and in our case amounts to using ``C`` for PCI/VIO device slots, where + ```` is unique across all PCI/VIO device slots. - bit[31:28]: integer encoding of , where is: - 1 for CPU resource - 2 for PHB resource - 3 for VIO resource - 4 for PCI resource - 8 for Memory resource - bit[27:0]: integer encoding of , where is unique across - all resources of specified type +``ibm,drc-indexes`` +------------------- -ibm,drc-power-domains: - first 4-bytes: BE-encoded integer denoting the number of entries - each 4-byte entry: 32-bit, BE-encoded integer that specifies the - power domain the resource will be assigned to. In the case of QEMU - we associated all resources with a "live insertion" domain, where the - power is assumed to be managed automatically. The integer value for - this domain is a special value of -1. + First 4-bytes: BE-encoded integer denoting the number of entries. + + Each 4-byte entry: BE-encoded ```` integer that is unique across all + DRCs in the machine. + + ```` is arbitrary, but in the case of QEMU we try to maintain the + convention used to assign them to pSeries guests on pHyp (the hypervisor + portion of PowerVM): + + ``bit[31:28]``: integer encoding of ````, where ```` is: + + ``1`` for CPU resource. + + ``2`` for PHB resource. + + ``3`` for VIO resource. + + ``4`` for PCI resource. + + ``8`` for memory resource. + + ``bit[27:0]``: integer encoding of ````, where ```` is unique + across all resources of specified type. + +``ibm,drc-power-domains`` +------------------------- + + First 4-bytes: BE-encoded integer denoting the number of entries. + + Each 4-byte entry: 32-bit, BE-encoded ```` integer that specifies the + power domain the resource will be assigned to. In the case of QEMU we + associated all resources with a "live insertion" domain, where the power is + assumed to be managed automatically. The integer value for this domain is a + special value of ``-1``. -ibm,drc-types: - first 4-bytes: BE-encoded integer denoting the number of entries - each entry: a NULL-terminated string encoded as a byte array +``ibm,drc-types`` +----------------- - is assigned as follows: - "CPU" for a CPU - "PHB" for a physical host-bridge - "SLOT" for a VIO slot - "28" for a PCI slot - "MEM" for memory resource + First 4-bytes: BE-encoded integer denoting the number of entries. -== Guest->Host interface to manage dynamic resources == + Each entry: a NULL-terminated ```` string encoded as a byte array. + ```` is assigned as follows: -Each DRC is given a globally unique DRC Index, and resources associated with -a particular DRC are configured/managed by the guest via a number of RTAS -calls which reference individual DRCs based on the DRC index. This can be -considered the guest->host interface. + "CPU" for a CPU. -rtas-set-power-level: - arg[0]: integer identifying power domain - arg[1]: new power level for the domain, 0-100 - output[0]: status, 0 on success - output[1]: power level after command + "PHB" for a physical host-bridge. - Set the power level for a specified power domain + "SLOT" for a VIO slot. -rtas-get-power-level: - arg[0]: integer identifying power domain - output[0]: status, 0 on success - output[1]: current power level + "28" for a PCI slot. - Get the power level for a specified power domain + "MEM" for memory resource. -rtas-set-indicator: - arg[0]: integer identifying sensor/indicator type - arg[1]: index of sensor, for DR-related sensors this is generally the - DRC index - arg[2]: desired sensor value - output[0]: status, 0 on success +.. _guest-host-interface: - Set the state of an indicator or sensor. For the purpose of this document we - focus on the indicator/sensor types associated with a DRC. The types are: +Guest->Host interface to manage dynamic resources +================================================= - 9001: isolation-state, controls/indicates whether a device has been made - accessible to a guest +Each DRC is given a globally unique DRC index, and resources associated with a +particular DRC are configured/managed by the guest via a number of RTAS calls +which reference individual DRCs based on the DRC index. This can be considered +the guest->host interface. - supported sensor values: - 0: isolate, device is made unaccessible by guest OS - 1: unisolate, device is made available to guest OS +``rtas-set-power-level`` +------------------------ - 9002: dr-indicator, controls "visual" indicator associated with device +Set the power level for a specified power domain. - supported sensor values: - 0: inactive, resource may be safely removed - 1: active, resource is in use and cannot be safely removed - 2: identify, used to visually identify slot for interactive hotplug - 3: action, in most cases, used in the same manner as identify + ``arg[0]``: integer identifying power domain. - 9003: allocation-state, generally only used for "logical" DR resources to - request the allocation/deallocation of a resource prior to acquiring - it via isolation-state->unisolate, or after releasing it via - isolation-state->isolate, respectively. for "physical" DR (like PCI - hotplug/unplug) the pre-allocation of the resource is implied and - this sensor is unused. + ``arg[1]``: new power level for the domain, ``0-100``. - supported sensor values: - 0: unusable, tell firmware/system the resource can be - unallocated/reclaimed and added back to the system resource pool - 1: usable, request the resource be allocated/reserved for use by - guest OS - 2: exchange, used to allocate a spare resource to use for fail-over - in certain situations. unused in QEMU - 3: recover, used to reclaim a previously allocated resource that's - not currently allocated to the guest OS. unused in QEMU + ``output[0]``: status, ``0`` on success. -rtas-get-sensor-state: - arg[0]: integer identifying sensor/indicator type - arg[1]: index of sensor, for DR-related sensors this is generally the - DRC index - output[0]: status, 0 on success + ``output[1]``: power level after command. - Used to read an indicator or sensor value. +``rtas-get-power-level`` +------------------------ - For DR-related operations, the only noteworthy sensor is dr-entity-sense, - which has a type value of 9003, as allocation-state does in the case of - rtas-set-indicator. The semantics/encodings of the sensor values are distinct - however: +Get the power level for a specified power domain. - supported sensor values for dr-entity-sense (9003) sensor: - 0: empty, - for physical resources: DRC/slot is empty - for logical resources: unused - 1: present, - for physical resources: DRC/slot is populated with a device/resource - for logical resources: resource has been allocated to the DRC - 2: unusable, - for physical resources: unused - for logical resources: DRC has no resource allocated to it - 3: exchange, - for physical resources: unused - for logical resources: resource available for exchange (see - allocation-state sensor semantics above) - 4: recovery, - for physical resources: unused - for logical resources: resource available for recovery (see - allocation-state sensor semantics above) + ``arg[0]``: integer identifying power domain. -rtas-ibm-configure-connector: - arg[0]: guest physical address of 4096-byte work area buffer - arg[1]: 0, or address of additional 4096-byte work area buffer. only non-zero - if a prior RTAS response indicated a need for additional memory - output[0]: status: - 0: completed transmittal of device-tree node - 1: instruct guest to prepare for next DT sibling node - 2: instruct guest to prepare for next DT child node - 3: instruct guest to prepare for next DT property - 4: instruct guest to ascend to parent DT node - 5: instruct guest to provide additional work-area buffer - via arg[1] - 990x: instruct guest that operation took too long and to try - again later + ``output[0]``: status, ``0`` on success. - Used to fetch an OF device-tree description of the resource associated with - a particular DRC. The DRC index is encoded in the first 4-bytes of the first - work area buffer. + ``output[1]``: current power level. - Work area layout, using 4-byte offsets: - wa[0]: DRC index of the DRC to fetch device-tree nodes from - wa[1]: 0 (hard-coded) - wa[2]: for next-sibling/next-child response: - wa offset of null-terminated string denoting the new node's name - for next-property response: - wa offset of null-terminated string denoting new property's name - wa[3]: for next-property response (unused otherwise): - byte-length of new property's value - wa[4]: for next-property response (unused otherwise): - new property's value, encoded as an OFDT-compatible byte array +``rtas-set-indicator`` +---------------------- -== hotplug/unplug events == +Set the state of an indicator or sensor. + + ``arg[0]``: integer identifying sensor/indicator type. + + ``arg[1]``: index of sensor, for DR-related sensors this is generally the DRC + index. + + ``arg[2]``: desired sensor value. + + ``output[0]``: status, ``0`` on success. + +For the purpose of this document we focus on the indicator/sensor types +associated with a DRC. The types are: + +* ``9001``: ``isolation-state``, controls/indicates whether a device has been + made accessible to a guest. Supported sensor values: + + ``0``: ``isolate``, device is made inaccessible by guest OS. + + ``1``: ``unisolate``, device is made available to guest OS. + +* ``9002``: ``dr-indicator``, controls "visual" indicator associated with + device. Supported sensor values: + + ``0``: ``inactive``, resource may be safely removed. + + ``1``: ``active``, resource is in use and cannot be safely removed. + + ``2``: ``identify``, used to visually identify slot for interactive hot plug. + + ``3``: ``action``, in most cases, used in the same manner as identify. + +* ``9003``: ``allocation-state``, generally only used for "logical" DR resources + to request the allocation/deallocation of a resource prior to acquiring it via + ``isolation-state->unisolate``, or after releasing it via + ``isolation-state->isolate``, respectively. For "physical" DR (like PCI + hot plug/unplug) the pre-allocation of the resource is implied and this sensor + is unused. Supported sensor values: + + ``0``: ``unusable``, tell firmware/system the resource can be + unallocated/reclaimed and added back to the system resource pool. + + ``1``: ``usable``, request the resource be allocated/reserved for use by + guest OS. + + ``2``: ``exchange``, used to allocate a spare resource to use for fail-over + in certain situations. Unused in QEMU. + + ``3``: ``recover``, used to reclaim a previously allocated resource that's + not currently allocated to the guest OS. Unused in QEMU. + +``rtas-get-sensor-state:`` +-------------------------- + +Used to read an indicator or sensor value. + + ``arg[0]``: integer identifying sensor/indicator type. + + ``arg[1]``: index of sensor, for DR-related sensors this is generally the DRC + index + + ``output[0]``: status, 0 on success + +For DR-related operations, the only noteworthy sensor is ``dr-entity-sense``, +which has a type value of ``9003``, as ``allocation-state`` does in the case of +``rtas-set-indicator``. The semantics/encodings of the sensor values are +distinct however. + +Supported sensor values for ``dr-entity-sense`` (``9003``) sensor: + + ``0``: empty. + + For physical resources: DRC/slot is empty. + + For logical resources: unused. + + ``1``: present. + + For physical resources: DRC/slot is populated with a device/resource. + + For logical resources: resource has been allocated to the DRC. + + ``2``: unusable. + + For physical resources: unused. + + For logical resources: DRC has no resource allocated to it. + + ``3``: exchange. + + For physical resources: unused. + + For logical resources: resource available for exchange (see + ``allocation-state`` sensor semantics above). + + ``4``: recovery. + + For physical resources: unused. + + For logical resources: resource available for recovery (see + ``allocation-state`` sensor semantics above). + +``rtas-ibm-configure-connector`` +-------------------------------- + +Used to fetch an OpenFirmware device tree description of the resource associated +with a particular DRC. + + ``arg[0]``: guest physical address of 4096-byte work area buffer. + + ``arg[1]``: 0, or address of additional 4096-byte work area buffer; only + non-zero if a prior RTAS response indicated a need for additional memory. + + ``output[0]``: status: + + ``0``: completed transmittal of device tree node. + + ``1``: instruct guest to prepare for next device tree sibling node. + + ``2``: instruct guest to prepare for next device tree child node. + + ``3``: instruct guest to prepare for next device tree property. + + ``4``: instruct guest to ascend to parent device tree node. + + ``5``: instruct guest to provide additional work-area buffer via ``arg[1]``. + + ``990x``: instruct guest that operation took too long and to try again + later. + +The DRC index is encoded in the first 4-bytes of the first work area buffer. +Work area (``wa``) layout, using 4-byte offsets: + + ``wa[0]``: DRC index of the DRC to fetch device tree nodes from. + + ``wa[1]``: ``0`` (hard-coded). + + ``wa[2]``: + + For next-sibling/next-child response: + + ``wa`` offset of null-terminated string denoting the new node's name. + + For next-property response: + + ``wa`` offset of null-terminated string denoting new property's name. + + ``wa[3]``: for next-property response (unused otherwise): + + Byte-length of new property's value. + + ``wa[4]``: for next-property response (unused otherwise): + + New property's value, encoded as an OFDT-compatible byte array. + +Hot plug/unplug events +====================== For most DR operations, the hypervisor will issue host->guest add/remove events using the EPOW/check-exception notification framework, where the host issues a @@ -230,130 +322,140 @@ requests via EPOW events. For DR, this framework has been extended to include hotplug events, which were previously unneeded due to direct manipulation of DR-related guest userspace tools by host-level management such as an HMC. This level of management is not -applicable to PowerKVM, hence the reason for extending the notification +applicable to KVM on Power, hence the reason for extending the notification framework to support hotplug events. The format for these EPOW-signalled events is described below under -"hotplug/unplug event structure". Note that these events are not -formally part of the PAPR+ specification, and have been superseded by a -newer format, also described below under "hotplug/unplug event structure", -and so are now deemed a "legacy" format. The formats are similar, but the -"modern" format contains additional fields/flags, which are denoted for the -purposes of this documentation with "#ifdef GUEST_SUPPORTS_MODERN" guards. +:ref:`hot-plug-unplug-event-structure`. Note that these events are not formally +part of the PAPR+ specification, and have been superseded by a newer format, +also described below under :ref:`hot-plug-unplug-event-structure`, and so are +now deemed a "legacy" format. The formats are similar, but the "modern" format +contains additional fields/flags, which are denoted for the purposes of this +documentation with ``#ifdef GUEST_SUPPORTS_MODERN`` guards. QEMU should assume support only for "legacy" fields/flags unless the guest -advertises support for the "modern" format via ibm,client-architecture-support -hcall by setting byte 5, bit 6 of it's ibm,architecture-vec-5 option vector -structure (as described by LoPAPR v11, B.6.2.3). As with "legacy" format events, -"modern" format events are surfaced to the guest via check-exception RTAS calls, -but use a dedicated event source to signal the guest. This event source is -advertised to the guest by the addition of a "hot-plug-events" node under -"/event-sources" node of the guest's device tree using the standard format -described in LoPAPR v11, B.6.12.1. +advertises support for the "modern" format via +``ibm,client-architecture-support`` hcall by setting byte 5, bit 6 of it's +``ibm,architecture-vec-5`` option vector structure (as described by [LoPAR]_, +section B.5.2.3). As with "legacy" format events, "modern" format events are +surfaced to the guest via check-exception RTAS calls, but use a dedicated event +source to signal the guest. This event source is advertised to the guest by the +addition of a ``hot-plug-events`` node under ``/event-sources`` node of the +guest's device tree using the standard format described in [LoPAR]_, +section B.5.12.2. -== hotplug/unplug event structure == +.. _hot-plug-unplug-event-structure: -The hotplug-specific payload in QEMU is implemented as follows (with all values +Hot plug/unplug event structure +=============================== + +The hot plug specific payload in QEMU is implemented as follows (with all values encoded in big-endian format): -struct rtas_event_log_v6_hp { -#define SECTION_ID_HOTPLUG 0x4850 /* HP */ - struct section_header { - uint16_t section_id; /* set to SECTION_ID_HOTPLUG */ - uint16_t section_length; /* sizeof(rtas_event_log_v6_hp), - * plus the length of the DRC name - * if a DRC name identifier is - * specified for hotplug_identifier - */ - uint8_t section_version; /* version 1 */ - uint8_t section_subtype; /* unused */ - uint16_t creator_component_id; /* unused */ - } hdr; -#define RTAS_LOG_V6_HP_TYPE_CPU 1 -#define RTAS_LOG_V6_HP_TYPE_MEMORY 2 -#define RTAS_LOG_V6_HP_TYPE_SLOT 3 -#define RTAS_LOG_V6_HP_TYPE_PHB 4 -#define RTAS_LOG_V6_HP_TYPE_PCI 5 - uint8_t hotplug_type; /* type of resource/device */ -#define RTAS_LOG_V6_HP_ACTION_ADD 1 -#define RTAS_LOG_V6_HP_ACTION_REMOVE 2 - uint8_t hotplug_action; /* action (add/remove) */ -#define RTAS_LOG_V6_HP_ID_DRC_NAME 1 -#define RTAS_LOG_V6_HP_ID_DRC_INDEX 2 -#define RTAS_LOG_V6_HP_ID_DRC_COUNT 3 -#ifdef GUEST_SUPPORTS_MODERN -#define RTAS_LOG_V6_HP_ID_DRC_COUNT_INDEXED 4 -#endif - uint8_t hotplug_identifier; /* type of the resource identifier, - * which serves as the discriminator - * for the 'drc' union field below - */ -#ifdef GUEST_SUPPORTS_MODERN - uint8_t capabilities; /* capability flags, currently unused - * by QEMU - */ -#else - uint8_t reserved; -#endif - union { - uint32_t index; /* DRC index of resource to take action - * on - */ - uint32_t count; /* number of DR resources to take - * action on (guest chooses which) - */ -#ifdef GUEST_SUPPORTS_MODERN - struct { - uint32_t count; /* number of DR resources to take - * action on - */ - uint32_t index; /* DRC index of first resource to take - * action on. guest will take action - * on DRC index through - * DRC index in - * sequential order - */ - } count_indexed; -#endif - char name[1]; /* string representing the name of the - * DRC to take action on - */ - } drc; -} QEMU_PACKED; +.. code-block:: c -== ibm,lrdr-capacity == + struct rtas_event_log_v6_hp { + #define SECTION_ID_HOTPLUG 0x4850 /* HP */ + struct section_header { + uint16_t section_id; /* set to SECTION_ID_HOTPLUG */ + uint16_t section_length; /* sizeof(rtas_event_log_v6_hp), + * plus the length of the DRC name + * if a DRC name identifier is + * specified for hotplug_identifier + */ + uint8_t section_version; /* version 1 */ + uint8_t section_subtype; /* unused */ + uint16_t creator_component_id; /* unused */ + } hdr; + #define RTAS_LOG_V6_HP_TYPE_CPU 1 + #define RTAS_LOG_V6_HP_TYPE_MEMORY 2 + #define RTAS_LOG_V6_HP_TYPE_SLOT 3 + #define RTAS_LOG_V6_HP_TYPE_PHB 4 + #define RTAS_LOG_V6_HP_TYPE_PCI 5 + uint8_t hotplug_type; /* type of resource/device */ + #define RTAS_LOG_V6_HP_ACTION_ADD 1 + #define RTAS_LOG_V6_HP_ACTION_REMOVE 2 + uint8_t hotplug_action; /* action (add/remove) */ + #define RTAS_LOG_V6_HP_ID_DRC_NAME 1 + #define RTAS_LOG_V6_HP_ID_DRC_INDEX 2 + #define RTAS_LOG_V6_HP_ID_DRC_COUNT 3 + #ifdef GUEST_SUPPORTS_MODERN + #define RTAS_LOG_V6_HP_ID_DRC_COUNT_INDEXED 4 + #endif + uint8_t hotplug_identifier; /* type of the resource identifier, + * which serves as the discriminator + * for the 'drc' union field below + */ + #ifdef GUEST_SUPPORTS_MODERN + uint8_t capabilities; /* capability flags, currently unused + * by QEMU + */ + #else + uint8_t reserved; + #endif + union { + uint32_t index; /* DRC index of resource to take action + * on + */ + uint32_t count; /* number of DR resources to take + * action on (guest chooses which) + */ + #ifdef GUEST_SUPPORTS_MODERN + struct { + uint32_t count; /* number of DR resources to take + * action on + */ + uint32_t index; /* DRC index of first resource to take + * action on. guest will take action + * on DRC index through + * DRC index in + * sequential order + */ + } count_indexed; + #endif + char name[1]; /* string representing the name of the + * DRC to take action on + */ + } drc; + } QEMU_PACKED; -ibm,lrdr-capacity is a property in the /rtas device tree node that identifies -the dynamic reconfiguration capabilities of the guest. It consists of a triple -consisting of , and . +``ibm,lrdr-capacity`` +===================== - , encoded in BE format represents the maximum address in bytes and +``ibm,lrdr-capacity`` is a property in the /rtas device tree node that +identifies the dynamic reconfiguration capabilities of the guest. It consists +of a triple consisting of ````, ```` and ````. + + ````, encoded in BE format represents the maximum address in bytes and hence the maximum memory that can be allocated to the guest. - , encoded in BE format represents the size increments in which + ````, encoded in BE format represents the size increments in which memory can be hot-plugged to the guest. - , a BE-encoded integer, represents the maximum number of + ````, a BE-encoded integer, represents the maximum number of processors that the guest can have. -pseries guests use this property to note the maximum allowed CPUs for the +``pseries`` guests use this property to note the maximum allowed CPUs for the guest. -== ibm,dynamic-reconfiguration-memory == +``ibm,dynamic-reconfiguration-memory`` +====================================== -ibm,dynamic-reconfiguration-memory is a device tree node that represents -dynamically reconfigurable logical memory blocks (LMB). This node -is generated only when the guest advertises the support for it via -ibm,client-architecture-support call. Memory that is not dynamically -reconfigurable is represented by /memory nodes. The properties of this -node that are of interest to the sPAPR memory hotplug implementation -in QEMU are described here. +``ibm,dynamic-reconfiguration-memory`` is a device tree node that represents +dynamically reconfigurable logical memory blocks (LMB). This node is generated +only when the guest advertises the support for it via +``ibm,client-architecture-support`` call. Memory that is not dynamically +reconfigurable is represented by ``/memory`` nodes. The properties of this node +that are of interest to the sPAPR memory hotplug implementation in QEMU are +described here. -ibm,lmb-size +``ibm,lmb-size`` +---------------- -This 64bit integer defines the size of each dynamically reconfigurable LMB. +This 64-bit integer defines the size of each dynamically reconfigurable LMB. -ibm,associativity-lookup-arrays +``ibm,associativity-lookup-arrays`` +----------------------------------- This property defines a lookup array in which the NUMA associativity information for each LMB can be found. It is a property encoded array @@ -361,13 +463,14 @@ that begins with an integer M, the number of associativity lists followed by an integer N, the number of entries per associativity list and terminated by M associativity lists each of length N integers. -This property provides the same information as given by ibm,associativity -property in a /memory node. Each assigned LMB has an index value between +This property provides the same information as given by ``ibm,associativity`` +property in a ``/memory`` node. Each assigned LMB has an index value between 0 and M-1 which is used as an index into this table to select which -associativity list to use for the LMB. This index value for each LMB -is defined in ibm,dynamic-memory property. +associativity list to use for the LMB. This index value for each LMB is defined +in ``ibm,dynamic-memory`` property. -ibm,dynamic-memory +``ibm,dynamic-memory`` +---------------------- This property describes the dynamically reconfigurable memory. It is a property encoded array that has an integer N, the number of LMBs followed @@ -375,19 +478,19 @@ by N LMB list entries. Each LMB list entry consists of the following elements: -- Logical address of the start of the LMB encoded as a 64bit integer. This - corresponds to reg property in /memory node. -- DRC index of the LMB that corresponds to ibm,my-drc-index property - in a /memory node. +- Logical address of the start of the LMB encoded as a 64-bit integer. This + corresponds to ``reg`` property in ``/memory`` node. +- DRC index of the LMB that corresponds to ``ibm,my-drc-index`` property + in a ``/memory`` node. - Four bytes reserved for expansion. - Associativity list index for the LMB that is used as an index into - ibm,associativity-lookup-arrays property described earlier. This - is used to retrieve the right associativity list to be used for this - LMB. -- A 32bit flags word. The bit at bit position 0x00000008 defines whether + ``ibm,associativity-lookup-arrays`` property described earlier. This is used + to retrieve the right associativity list to be used for this LMB. +- A 32-bit flags word. The bit at bit position ``0x00000008`` defines whether the LMB is assigned to the partition as of boot time. -ibm,dynamic-memory-v2 +``ibm,dynamic-memory-v2`` +------------------------- This property describes the dynamically reconfigurable memory. This is an alternate and newer way to describe dynamically reconfigurable memory. @@ -397,13 +500,11 @@ for each sequential group of LMBs that share common attributes. Each LMB set entry consists of the following elements: -- Number of sequential LMBs in the entry represented by a 32bit integer. -- Logical address of the first LMB in the set encoded as a 64bit integer. +- Number of sequential LMBs in the entry represented by a 32-bit integer. +- Logical address of the first LMB in the set encoded as a 64-bit integer. - DRC index of the first LMB in the set. - Associativity list index that is used as an index into - ibm,associativity-lookup-arrays property described earlier. This + ``ibm,associativity-lookup-arrays`` property described earlier. This is used to retrieve the right associativity list to be used for all the LMBs in this set. -- A 32bit flags word that applies to all the LMBs in the set. - -[1] http://thread.gmane.org/gmane.linux.ports.ppc.embedded/75350/focus=106867 +- A 32-bit flags word that applies to all the LMBs in the set. From 55ff468f7816ff40e4058153127c9d19ffd36261 Mon Sep 17 00:00:00 2001 From: Leonardo Garcia Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 549/730] docs: Rename ppc-spapr-hotplug.txt to ppc-spapr-hotplug.rst. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Leonardo Garcia Reviewed-by: Daniel Henrique Barboza Message-Id: <1f5860217273f272fddadc68b5d205b4090f6b04.1641995058.git.lagarcia@br.ibm.com> Signed-off-by: Cédric Le Goater --- docs/specs/{ppc-spapr-hotplug.txt => ppc-spapr-hotplug.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/specs/{ppc-spapr-hotplug.txt => ppc-spapr-hotplug.rst} (100%) diff --git a/docs/specs/ppc-spapr-hotplug.txt b/docs/specs/ppc-spapr-hotplug.rst similarity index 100% rename from docs/specs/ppc-spapr-hotplug.txt rename to docs/specs/ppc-spapr-hotplug.rst From 22beb38b78b80e17d70b4562625557cafaedda11 Mon Sep 17 00:00:00 2001 From: Leonardo Garcia Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 550/730] Link new ppc-spapr-hotplug.rst file to pseries.rst. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Leonardo Garcia Reviewed-by: Daniel Henrique Barboza Message-Id: Signed-off-by: Cédric Le Goater --- docs/system/ppc/pseries.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/system/ppc/pseries.rst b/docs/system/ppc/pseries.rst index 1689324815..d0aade3a31 100644 --- a/docs/system/ppc/pseries.rst +++ b/docs/system/ppc/pseries.rst @@ -110,13 +110,13 @@ can also be found in QEMU documentation: .. toctree:: :maxdepth: 1 + ../../specs/ppc-spapr-hotplug.rst ../../specs/ppc-spapr-hcalls.rst ../../specs/ppc-spapr-numa.rst ../../specs/ppc-spapr-xive.rst Other documentation available in QEMU docs directory: -* Hot plug (``/docs/specs/ppc-spapr-hotplug.txt``). * Hypervisor calls needed by the Ultravisor (``/docs/specs/ppc-spapr-uv-hcalls.txt``). From 2084b44d7afa2e604c52a31ee89f46a01835131b Mon Sep 17 00:00:00 2001 From: Leonardo Garcia Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 551/730] rSTify ppc-spapr-uv-hcalls.txt. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Leonardo Garcia Reviewed-by: Daniel Henrique Barboza Message-Id: <243a714d3861f7539d29b02a899ffc376757d668.1642446876.git.lagarcia@br.ibm.com> Signed-off-by: Cédric Le Goater --- docs/specs/ppc-spapr-uv-hcalls.txt | 139 ++++++++++++++++------------- 1 file changed, 76 insertions(+), 63 deletions(-) diff --git a/docs/specs/ppc-spapr-uv-hcalls.txt b/docs/specs/ppc-spapr-uv-hcalls.txt index 389c2740d7..a00288deb3 100644 --- a/docs/specs/ppc-spapr-uv-hcalls.txt +++ b/docs/specs/ppc-spapr-uv-hcalls.txt @@ -1,76 +1,89 @@ -On PPC64 systems supporting Protected Execution Facility (PEF), system -memory can be placed in a secured region where only an "ultravisor" -running in firmware can provide to access it. pseries guests on such -systems can communicate with the ultravisor (via ultracalls) to switch to a -secure VM mode (SVM) where the guest's memory is relocated to this secured -region, making its memory inaccessible to normal processes/guests running on -the host. +=================================== +Hypervisor calls and the Ultravisor +=================================== -The various ultracalls/hypercalls relating to SVM mode are currently -only documented internally, but are planned for direct inclusion into the -public OpenPOWER version of the PAPR specification (LoPAPR/LoPAR). An internal -ACR has been filed to reserve a hypercall number range specific to this -use-case to avoid any future conflicts with the internally-maintained PAPR -specification. This document summarizes some of these details as they relate -to QEMU. +On PPC64 systems supporting Protected Execution Facility (PEF), system memory +can be placed in a secured region where only an ultravisor running in firmware +can provide access to. pSeries guests on such systems can communicate with +the ultravisor (via ultracalls) to switch to a secure virtual machine (SVM) mode +where the guest's memory is relocated to this secured region, making its memory +inaccessible to normal processes/guests running on the host. -== hypercalls needed by the ultravisor == +The various ultracalls/hypercalls relating to SVM mode are currently only +documented internally, but are planned for direct inclusion into the Linux on +Power Architecture Reference document ([LoPAR]_). An internal ACR has been filed +to reserve a hypercall number range specific to this use case to avoid any +future conflicts with the IBM internally maintained Power Architecture Platform +Reference (PAPR+) documentation specification. This document summarizes some of +these details as they relate to QEMU. -Switching to SVM mode involves a number of hcalls issued by the ultravisor -to the hypervisor to orchestrate the movement of guest memory to secure -memory and various other aspects SVM mode. Numbers are assigned for these -hcalls within the reserved range 0xEF00-0xEF80. The below documents the -hcalls relevant to QEMU. +Hypercalls needed by the ultravisor +=================================== -- H_TPM_COMM (0xef10) +Switching to SVM mode involves a number of hcalls issued by the ultravisor to +the hypervisor to orchestrate the movement of guest memory to secure memory and +various other aspects of the SVM mode. Numbers are assigned for these hcalls +within the reserved range ``0xEF00-0xEF80``. The below documents the hcalls +relevant to QEMU. - For TPM_COMM_OP_EXECUTE operation: - Send a request to a TPM and receive a response, opening a new TPM session - if one has not already been opened. +``H_TPM_COMM`` (``0xef10``) +--------------------------- - For TPM_COMM_OP_CLOSE_SESSION operation: - Close the existing TPM session, if any. +SVM file systems are encrypted using a symmetric key. This key is then +wrapped/encrypted using the public key of a trusted system which has the private +key stored in the system's TPM. An Ultravisor will use this hcall to +unwrap/unseal the symmetric key using the system's TPM device or a TPM Resource +Manager associated with the device. - Arguments: +The Ultravisor sets up a separate session key with the TPM in advance during +host system boot. All sensitive in and out values will be encrypted using the +session key. Though the hypervisor will see the in and out buffers in raw form, +any sensitive contents will generally be encrypted using this session key. - r3 : H_TPM_COMM (0xef10) - r4 : TPM operation, one of: - TPM_COMM_OP_EXECUTE (0x1) - TPM_COMM_OP_CLOSE_SESSION (0x2) - r5 : in_buffer, guest physical address of buffer containing the request - - Caller may use the same address for both request and response - r6 : in_size, size of the in buffer - - Must be less than or equal to 4KB - r7 : out_buffer, guest physical address of buffer to store the response - - Caller may use the same address for both request and response - r8 : out_size, size of the out buffer - - Must be at least 4KB, as this is the maximum request/response size - supported by most TPM implementations, including the TPM Resource - Manager in the linux kernel. +Arguments: - Return values: + ``r3``: ``H_TPM_COMM`` (``0xef10``) - r3 : H_Success request processed successfully - H_PARAMETER invalid TPM operation - H_P2 in_buffer is invalid - H_P3 in_size is invalid - H_P4 out_buffer is invalid - H_P5 out_size is invalid - H_RESOURCE problem communicating with TPM - H_FUNCTION TPM access is not currently allowed/configured - r4 : For TPM_COMM_OP_EXECUTE, the size of the response will be stored here - upon success. + ``r4``: ``TPM`` operation, one of: - Use-case/notes: + ``TPM_COMM_OP_EXECUTE`` (``0x1``): send a request to a TPM and receive a + response, opening a new TPM session if one has not already been opened. - SVM filesystems are encrypted using a symmetric key. This key is then - wrapped/encrypted using the public key of a trusted system which has the - private key stored in the system's TPM. An Ultravisor will use this - hcall to unwrap/unseal the symmetric key using the system's TPM device - or a TPM Resource Manager associated with the device. + ``TPM_COMM_OP_CLOSE_SESSION`` (``0x2``): close the existing TPM session, if + any. - The Ultravisor sets up a separate session key with the TPM in advance - during host system boot. All sensitive in and out values will be - encrypted using the session key. Though the hypervisor will see the 'in' - and 'out' buffers in raw form, any sensitive contents will generally be - encrypted using this session key. + ``r5``: ``in_buffer``, guest physical address of buffer containing the + request. Caller may use the same address for both request and response. + + ``r6``: ``in_size``, size of the in buffer. Must be less than or equal to + 4 KB. + + ``r7``: ``out_buffer``, guest physical address of buffer to store the + response. Caller may use the same address for both request and response. + + ``r8``: ``out_size``, size of the out buffer. Must be at least 4 KB, as this + is the maximum request/response size supported by most TPM implementations, + including the TPM Resource Manager in the linux kernel. + +Return values: + + ``r3``: one of the following values: + + ``H_Success``: request processed successfully. + + ``H_PARAMETER``: invalid TPM operation. + + ``H_P2``: ``in_buffer`` is invalid. + + ``H_P3``: ``in_size`` is invalid. + + ``H_P4``: ``out_buffer`` is invalid. + + ``H_P5``: ``out_size`` is invalid. + + ``H_RESOURCE``: problem communicating with TPM. + + ``H_FUNCTION``: TPM access is not currently allowed/configured. + + ``r4``: For ``TPM_COMM_OP_EXECUTE``, the size of the response will be stored + here upon success. From dedc5d79dae59562b2311301d27ecbf2234acf8a Mon Sep 17 00:00:00 2001 From: Leonardo Garcia Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 552/730] Rename ppc-spapr-uv-hcalls.txt to ppc-spapr-uv-hcalls.rst. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Leonardo Garcia Reviewed-by: Daniel Henrique Barboza Message-Id: Signed-off-by: Cédric Le Goater --- docs/specs/{ppc-spapr-uv-hcalls.txt => ppc-spapr-uv-hcalls.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/specs/{ppc-spapr-uv-hcalls.txt => ppc-spapr-uv-hcalls.rst} (100%) diff --git a/docs/specs/ppc-spapr-uv-hcalls.txt b/docs/specs/ppc-spapr-uv-hcalls.rst similarity index 100% rename from docs/specs/ppc-spapr-uv-hcalls.txt rename to docs/specs/ppc-spapr-uv-hcalls.rst From 8e12c012a79320041d49ea6162e944b2f7306b71 Mon Sep 17 00:00:00 2001 From: Leonardo Garcia Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 553/730] Link new ppc-spapr-uv-hcalls.rst to pseries.rst. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Leonardo Garcia Reviewed-by: Daniel Henrique Barboza Message-Id: Signed-off-by: Cédric Le Goater --- docs/system/ppc/pseries.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/system/ppc/pseries.rst b/docs/system/ppc/pseries.rst index d0aade3a31..569237dc0c 100644 --- a/docs/system/ppc/pseries.rst +++ b/docs/system/ppc/pseries.rst @@ -113,13 +113,9 @@ can also be found in QEMU documentation: ../../specs/ppc-spapr-hotplug.rst ../../specs/ppc-spapr-hcalls.rst ../../specs/ppc-spapr-numa.rst + ../../specs/ppc-spapr-uv-hcalls.rst ../../specs/ppc-spapr-xive.rst -Other documentation available in QEMU docs directory: - -* Hypervisor calls needed by the Ultravisor - (``/docs/specs/ppc-spapr-uv-hcalls.txt``). - Switching between the KVM-PR and KVM-HV kernel module ===================================================== From 8f91aca7ff0044b77f04c745ab1572f1e40e2b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 554/730] target/ppc: Remove last user of .load_state_old MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This breaks migration compatibility from (very) old versions of QEMU. This should not be a problem for the pseries machine for which migration is only supported on recent QEMUs ( > 2.x). There is no clear status on what is supported or not for the other machines. Let's move forward and remove the .load_state_old handler. Signed-off-by: Cédric Le Goater Reviewed-by: David Gibson Message-Id: <20220118104150.1899661-2-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/machine.c | 112 ------------------------------------------- 1 file changed, 112 deletions(-) diff --git a/target/ppc/machine.c b/target/ppc/machine.c index 756d8de5d8..df547385ff 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -23,117 +23,6 @@ static void post_load_update_msr(CPUPPCState *env) pmu_update_summaries(env); } -static int cpu_load_old(QEMUFile *f, void *opaque, int version_id) -{ - PowerPCCPU *cpu = opaque; - CPUPPCState *env = &cpu->env; - unsigned int i, j; - target_ulong sdr1; - uint32_t fpscr, vscr; -#if defined(TARGET_PPC64) - int32_t slb_nr; -#endif - target_ulong xer; - - for (i = 0; i < 32; i++) { - qemu_get_betls(f, &env->gpr[i]); - } -#if !defined(TARGET_PPC64) - for (i = 0; i < 32; i++) { - qemu_get_betls(f, &env->gprh[i]); - } -#endif - qemu_get_betls(f, &env->lr); - qemu_get_betls(f, &env->ctr); - for (i = 0; i < 8; i++) { - qemu_get_be32s(f, &env->crf[i]); - } - qemu_get_betls(f, &xer); - cpu_write_xer(env, xer); - qemu_get_betls(f, &env->reserve_addr); - qemu_get_betls(f, &env->msr); - for (i = 0; i < 4; i++) { - qemu_get_betls(f, &env->tgpr[i]); - } - for (i = 0; i < 32; i++) { - union { - float64 d; - uint64_t l; - } u; - u.l = qemu_get_be64(f); - *cpu_fpr_ptr(env, i) = u.d; - } - qemu_get_be32s(f, &fpscr); - env->fpscr = fpscr; - qemu_get_sbe32s(f, &env->access_type); -#if defined(TARGET_PPC64) - qemu_get_betls(f, &env->spr[SPR_ASR]); - qemu_get_sbe32s(f, &slb_nr); -#endif - qemu_get_betls(f, &sdr1); - for (i = 0; i < 32; i++) { - qemu_get_betls(f, &env->sr[i]); - } - for (i = 0; i < 2; i++) { - for (j = 0; j < 8; j++) { - qemu_get_betls(f, &env->DBAT[i][j]); - } - } - for (i = 0; i < 2; i++) { - for (j = 0; j < 8; j++) { - qemu_get_betls(f, &env->IBAT[i][j]); - } - } - qemu_get_sbe32s(f, &env->nb_tlb); - qemu_get_sbe32s(f, &env->tlb_per_way); - qemu_get_sbe32s(f, &env->nb_ways); - qemu_get_sbe32s(f, &env->last_way); - qemu_get_sbe32s(f, &env->id_tlbs); - qemu_get_sbe32s(f, &env->nb_pids); - if (env->tlb.tlb6) { - /* XXX assumes 6xx */ - for (i = 0; i < env->nb_tlb; i++) { - qemu_get_betls(f, &env->tlb.tlb6[i].pte0); - qemu_get_betls(f, &env->tlb.tlb6[i].pte1); - qemu_get_betls(f, &env->tlb.tlb6[i].EPN); - } - } - for (i = 0; i < 4; i++) { - qemu_get_betls(f, &env->pb[i]); - } - for (i = 0; i < 1024; i++) { - qemu_get_betls(f, &env->spr[i]); - } - if (!cpu->vhyp) { - ppc_store_sdr1(env, sdr1); - } - qemu_get_be32s(f, &vscr); - ppc_store_vscr(env, vscr); - qemu_get_be64s(f, &env->spe_acc); - qemu_get_be32s(f, &env->spe_fscr); - qemu_get_betls(f, &env->msr_mask); - qemu_get_be32s(f, &env->flags); - qemu_get_sbe32s(f, &env->error_code); - qemu_get_be32s(f, &env->pending_interrupts); - qemu_get_be32s(f, &env->irq_input_state); - for (i = 0; i < POWERPC_EXCP_NB; i++) { - qemu_get_betls(f, &env->excp_vectors[i]); - } - qemu_get_betls(f, &env->excp_prefix); - qemu_get_betls(f, &env->ivor_mask); - qemu_get_betls(f, &env->ivpr_mask); - qemu_get_betls(f, &env->hreset_vector); - qemu_get_betls(f, &env->nip); - qemu_get_sbetl(f); /* Discard unused hflags */ - qemu_get_sbetl(f); /* Discard unused hflags_nmsr */ - qemu_get_sbe32(f); /* Discard unused mmu_idx */ - qemu_get_sbe32(f); /* Discard unused power_mode */ - - post_load_update_msr(env); - - return 0; -} - static int get_avr(QEMUFile *f, void *pv, size_t size, const VMStateField *field) { @@ -808,7 +697,6 @@ const VMStateDescription vmstate_ppc_cpu = { .version_id = 5, .minimum_version_id = 5, .minimum_version_id_old = 4, - .load_state_old = cpu_load_old, .pre_save = cpu_pre_save, .post_load = cpu_post_load, .fields = (VMStateField[]) { From 328c95fc7d005380e970383a79e30bb4d4acddd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 555/730] target/ppc: Finish removal of 401/403 CPUs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit c8f49e6b938e ("target/ppc: remove 401/403 CPUs") left a few things behind. Reviewed-by: Fabiano Rosas Reviewed-by: David Gibson Message-Id: <20220117091541.1615807-1-clg@kaod.org> Signed-off-by: Cédric Le Goater Message-Id: <20220118104150.1899661-3-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/cpu-models.c | 1 - target/ppc/cpu.h | 1 - target/ppc/helper.h | 1 - target/ppc/machine.c | 24 ------------------------ target/ppc/misc_helper.c | 9 --------- target/ppc/translate.c | 16 +--------------- 6 files changed, 1 insertion(+), 51 deletions(-) diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c index c9fcb6119f..96fec9c2e5 100644 --- a/target/ppc/cpu-models.c +++ b/target/ppc/cpu-models.c @@ -750,7 +750,6 @@ /* PowerPC CPU aliases */ PowerPCCPUAlias ppc_cpu_aliases[] = { - { "403", "403gc" }, { "405", "405d4" }, { "405cr", "405crc" }, { "405gp", "405gpd" }, diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index f99cd0ea92..2560b70c5f 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1133,7 +1133,6 @@ struct CPUPPCState { int nb_pids; /* Number of available PID registers */ int tlb_type; /* Type of TLB we're dealing with */ ppc_tlb_t tlb; /* TLB is optional. Allocate them only if needed */ - target_ulong pb[4]; /* 403 dedicated access protection registers */ bool tlb_dirty; /* Set to non-zero when modifying TLB */ bool kvm_sw_tlb; /* non-zero if KVM SW TLB API is active */ uint32_t tlb_need_flush; /* Delayed flush needed */ diff --git a/target/ppc/helper.h b/target/ppc/helper.h index f9c72dcd50..d318837ea5 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -703,7 +703,6 @@ DEF_HELPER_FLAGS_2(store_hdecr, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_2(store_vtb, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_2(store_tbu40, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_2(store_hid0_601, void, env, tl) -DEF_HELPER_3(store_403_pbr, void, env, i32, tl) DEF_HELPER_FLAGS_1(load_40x_pit, TCG_CALL_NO_RWG, tl, env) DEF_HELPER_FLAGS_2(store_40x_pit, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_2(store_40x_tcr, TCG_CALL_NO_RWG, void, env, tl) diff --git a/target/ppc/machine.c b/target/ppc/machine.c index df547385ff..733a22d744 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -598,25 +598,6 @@ static bool tlbemb_needed(void *opaque) return env->nb_tlb && (env->tlb_type == TLB_EMB); } -static bool pbr403_needed(void *opaque) -{ - PowerPCCPU *cpu = opaque; - uint32_t pvr = cpu->env.spr[SPR_PVR]; - - return (pvr & 0xffff0000) == 0x00200000; -} - -static const VMStateDescription vmstate_pbr403 = { - .name = "cpu/pbr403", - .version_id = 1, - .minimum_version_id = 1, - .needed = pbr403_needed, - .fields = (VMStateField[]) { - VMSTATE_UINTTL_ARRAY(env.pb, PowerPCCPU, 4), - VMSTATE_END_OF_LIST() - }, -}; - static const VMStateDescription vmstate_tlbemb = { .name = "cpu/tlb6xx", .version_id = 1, @@ -628,13 +609,8 @@ static const VMStateDescription vmstate_tlbemb = { env.nb_tlb, vmstate_tlbemb_entry, ppcemb_tlb_t), - /* 403 protection registers */ VMSTATE_END_OF_LIST() }, - .subsections = (const VMStateDescription*[]) { - &vmstate_pbr403, - NULL - } }; static const VMStateDescription vmstate_tlbmas_entry = { diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c index c33f5f39b9..1bcefa7c84 100644 --- a/target/ppc/misc_helper.c +++ b/target/ppc/misc_helper.c @@ -226,15 +226,6 @@ void helper_store_hid0_601(CPUPPCState *env, target_ulong val) } } -void helper_store_403_pbr(CPUPPCState *env, uint32_t num, target_ulong value) -{ - if (likely(env->pb[num] != value)) { - env->pb[num] = value; - /* Should be optimized */ - tlb_flush(env_cpu(env)); - } -} - void helper_store_40x_dbcr0(CPUPPCState *env, target_ulong val) { /* Bits 26 & 27 affect single-stepping. */ diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 40232201bb..9d2adc0cae 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -911,22 +911,8 @@ void spr_write_booke_tsr(DisasContext *ctx, int sprn, int gprn) } #endif -/* PowerPC 403 specific registers */ -/* PBL1 / PBU1 / PBL2 / PBU2 */ +/* PIR */ #if !defined(CONFIG_USER_ONLY) -void spr_read_403_pbr(DisasContext *ctx, int gprn, int sprn) -{ - tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, - offsetof(CPUPPCState, pb[sprn - SPR_403_PBL1])); -} - -void spr_write_403_pbr(DisasContext *ctx, int sprn, int gprn) -{ - TCGv_i32 t0 = tcg_const_i32(sprn - SPR_403_PBL1); - gen_helper_store_403_pbr(cpu_env, t0, cpu_gpr[gprn]); - tcg_temp_free_i32(t0); -} - void spr_write_pir(DisasContext *ctx, int sprn, int gprn) { TCGv t0 = tcg_temp_new(); From fe072a9914cc26c0f0a70dbbe0c27a61ff0170bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 556/730] target/ppc: Fix 7448 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 7448 CPU is an evolution of the PowerPC 7447A and the last of the G4 family. Change its family to reflect correctly its features. This fixes Linux boot. Cc: Fabiano Rosas Reviewed-by: Fabiano Rosas Signed-off-by: Cédric Le Goater Message-Id: <20220117092555.1616512-1-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/cpu-models.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c index 96fec9c2e5..764afe5a2a 100644 --- a/target/ppc/cpu-models.c +++ b/target/ppc/cpu-models.c @@ -636,13 +636,13 @@ "PowerPC 7410 v1.3 (G4)") POWERPC_DEF("7410_v1.4", CPU_POWERPC_7410_v14, 7410, "PowerPC 7410 v1.4 (G4)") - POWERPC_DEF("7448_v1.0", CPU_POWERPC_7448_v10, 7400, + POWERPC_DEF("7448_v1.0", CPU_POWERPC_7448_v10, 7445, "PowerPC 7448 v1.0 (G4)") - POWERPC_DEF("7448_v1.1", CPU_POWERPC_7448_v11, 7400, + POWERPC_DEF("7448_v1.1", CPU_POWERPC_7448_v11, 7445, "PowerPC 7448 v1.1 (G4)") - POWERPC_DEF("7448_v2.0", CPU_POWERPC_7448_v20, 7400, + POWERPC_DEF("7448_v2.0", CPU_POWERPC_7448_v20, 7445, "PowerPC 7448 v2.0 (G4)") - POWERPC_DEF("7448_v2.1", CPU_POWERPC_7448_v21, 7400, + POWERPC_DEF("7448_v2.1", CPU_POWERPC_7448_v21, 7445, "PowerPC 7448 v2.1 (G4)") POWERPC_DEF("7450_v1.0", CPU_POWERPC_7450_v10, 7450, "PowerPC 7450 v1.0 (G4)") From 390a1299973a2f124fccd91c9110f094f1bee29d Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 557/730] tests/avocado: ppc: Add smoke tests for MPC7400 and MPC7450 families MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These tests ensure that our emulation for these cpus is not completely broken and we can at least run OpenBIOS on them. $ make check-avocado AVOCADO_TESTS=../tests/avocado/ppc_74xx.py Signed-off-by: Fabiano Rosas Reviewed-by: Willian Rampazzo Reviewed-by: Daniel Henrique Barboza Message-Id: <20220117144757.782441-1-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- tests/avocado/ppc_74xx.py | 123 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 tests/avocado/ppc_74xx.py diff --git a/tests/avocado/ppc_74xx.py b/tests/avocado/ppc_74xx.py new file mode 100644 index 0000000000..556a9a7da9 --- /dev/null +++ b/tests/avocado/ppc_74xx.py @@ -0,0 +1,123 @@ +# Smoke tests for 74xx cpus (aka G4). +# +# Copyright (c) 2021, IBM Corp. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado_qemu import QemuSystemTest +from avocado_qemu import wait_for_console_pattern + +class ppc74xxCpu(QemuSystemTest): + """ + :avocado: tags=arch:ppc + """ + timeout = 5 + + def test_ppc_7400(self): + """ + :avocado: tags=cpu:7400 + """ + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7410(self): + """ + :avocado: tags=cpu:7410 + """ + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,74xx') + + def test_ppc_7441(self): + """ + :avocado: tags=cpu:7441 + """ + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7445(self): + """ + :avocado: tags=cpu:7445 + """ + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7447(self): + """ + :avocado: tags=cpu:7447 + """ + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7447a(self): + """ + :avocado: tags=cpu:7447a + """ + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7448(self): + """ + :avocado: tags=cpu:7448 + """ + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,MPC86xx') + + def test_ppc_7450(self): + """ + :avocado: tags=cpu:7450 + """ + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7451(self): + """ + :avocado: tags=cpu:7451 + """ + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7455(self): + """ + :avocado: tags=cpu:7455 + """ + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7457(self): + """ + :avocado: tags=cpu:7457 + """ + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') + + def test_ppc_7457a(self): + """ + :avocado: tags=cpu:7457a + """ + self.vm.set_console() + self.vm.launch() + wait_for_console_pattern(self, '>> OpenBIOS') + wait_for_console_pattern(self, '>> CPU type PowerPC,G4') From 5d4ec103410f18490b5d61703af9c586bfca8b6c Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 558/730] ppc/pnv: use PHB4 obj in pnv_pec_stk_pci_xscom_ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current relationship between PnvPhb4PecStack and PnvPHB4 objects is overly complex. Recent work done in pnv_phb4.c and pnv_phb4_pec.c shows that the stack obj role in the overall design is more of a placeholder for its 'phb' object, having no atributes that stand on its own. This became clearer after pnv-phb4 user creatable devices were implemented. What remains now are a lot of stack->phb and phb->stack pointers throughout .read and .write callbacks of MemoryRegionOps that are being initialized in phb4_realize() time. stk_realize() is a no-op if the machine is being run with -nodefaults. The first step of trying to decouple the stack and phb relationship is to move the MemoryRegionOps that belongs to PnvPhb4PecStack to PhbPHB4. Unfortunately this can't be done without some preliminary steps to change the usage of 'stack' and replace it with 'phb' in these read/write callbacks. This patch starts this process by using a PnvPHB4 opaque in pnv_pec_stk_pci_xscom_ops instead of PnvPhb4PecStack. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220113192952.911188-2-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index a7b638831e..e010572376 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1071,7 +1071,7 @@ static const MemoryRegionOps pnv_pec_stk_nest_xscom_ops = { static uint64_t pnv_pec_stk_pci_xscom_read(void *opaque, hwaddr addr, unsigned size) { - PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); + PnvPhb4PecStack *stack = PNV_PHB4(opaque)->stack; uint32_t reg = addr >> 3; /* TODO: add list of allowed registers and error out if not */ @@ -1081,7 +1081,7 @@ static uint64_t pnv_pec_stk_pci_xscom_read(void *opaque, hwaddr addr, static void pnv_pec_stk_pci_xscom_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); + PnvPhb4PecStack *stack = PNV_PHB4(opaque)->stack; uint32_t reg = addr >> 3; switch (reg) { @@ -1475,10 +1475,10 @@ static void pnv_phb4_xscom_realize(PnvPHB4 *phb) &pnv_pec_stk_nest_xscom_ops, stack, name, PHB4_PEC_NEST_STK_REGS_COUNT); - snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d", + snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-phb-%d", pec->chip_id, pec->index, stack->stack_no); - pnv_xscom_region_init(&stack->pci_regs_mr, OBJECT(stack), - &pnv_pec_stk_pci_xscom_ops, stack, name, + pnv_xscom_region_init(&stack->pci_regs_mr, OBJECT(phb), + &pnv_pec_stk_pci_xscom_ops, phb, name, PHB4_PEC_PCI_STK_REGS_COUNT); /* PHB pass-through */ From df462784104b6aa39badcc327dd1ce41769b0011 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 559/730] ppc/pnv: move PCI registers to PnvPHB4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous patch changed pnv_pec_stk_pci_xscom_read() and pnv_pec_stk_pci_xscom_write() to use a PnvPHB4 opaque, making it easier to move both pci_regs[] and the pci_regs_mr MemoryRegion to the PnvHB4 object. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220113192952.911188-3-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 30 +++++++++++++++--------------- include/hw/pci-host/pnv_phb4.h | 10 +++++----- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index e010572376..fd9f6af4b3 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1071,54 +1071,54 @@ static const MemoryRegionOps pnv_pec_stk_nest_xscom_ops = { static uint64_t pnv_pec_stk_pci_xscom_read(void *opaque, hwaddr addr, unsigned size) { - PnvPhb4PecStack *stack = PNV_PHB4(opaque)->stack; + PnvPHB4 *phb = PNV_PHB4(opaque); uint32_t reg = addr >> 3; /* TODO: add list of allowed registers and error out if not */ - return stack->pci_regs[reg]; + return phb->pci_regs[reg]; } static void pnv_pec_stk_pci_xscom_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - PnvPhb4PecStack *stack = PNV_PHB4(opaque)->stack; + PnvPHB4 *phb = PNV_PHB4(opaque); uint32_t reg = addr >> 3; switch (reg) { case PEC_PCI_STK_PCI_FIR: - stack->pci_regs[reg] = val; + phb->pci_regs[reg] = val; break; case PEC_PCI_STK_PCI_FIR_CLR: - stack->pci_regs[PEC_PCI_STK_PCI_FIR] &= val; + phb->pci_regs[PEC_PCI_STK_PCI_FIR] &= val; break; case PEC_PCI_STK_PCI_FIR_SET: - stack->pci_regs[PEC_PCI_STK_PCI_FIR] |= val; + phb->pci_regs[PEC_PCI_STK_PCI_FIR] |= val; break; case PEC_PCI_STK_PCI_FIR_MSK: - stack->pci_regs[reg] = val; + phb->pci_regs[reg] = val; break; case PEC_PCI_STK_PCI_FIR_MSKC: - stack->pci_regs[PEC_PCI_STK_PCI_FIR_MSK] &= val; + phb->pci_regs[PEC_PCI_STK_PCI_FIR_MSK] &= val; break; case PEC_PCI_STK_PCI_FIR_MSKS: - stack->pci_regs[PEC_PCI_STK_PCI_FIR_MSK] |= val; + phb->pci_regs[PEC_PCI_STK_PCI_FIR_MSK] |= val; break; case PEC_PCI_STK_PCI_FIR_ACT0: case PEC_PCI_STK_PCI_FIR_ACT1: - stack->pci_regs[reg] = val; + phb->pci_regs[reg] = val; break; case PEC_PCI_STK_PCI_FIR_WOF: - stack->pci_regs[reg] = 0; + phb->pci_regs[reg] = 0; break; case PEC_PCI_STK_ETU_RESET: - stack->pci_regs[reg] = val & 0x8000000000000000ull; + phb->pci_regs[reg] = val & 0x8000000000000000ull; /* TODO: Implement reset */ break; case PEC_PCI_STK_PBAIB_ERR_REPORT: break; case PEC_PCI_STK_PBAIB_TX_CMD_CRED: case PEC_PCI_STK_PBAIB_TX_DAT_CRED: - stack->pci_regs[reg] = val; + phb->pci_regs[reg] = val; break; default: qemu_log_mask(LOG_UNIMP, "phb4_pec_stk: pci_xscom_write 0x%"HWADDR_PRIx @@ -1477,7 +1477,7 @@ static void pnv_phb4_xscom_realize(PnvPHB4 *phb) snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-phb-%d", pec->chip_id, pec->index, stack->stack_no); - pnv_xscom_region_init(&stack->pci_regs_mr, OBJECT(phb), + pnv_xscom_region_init(&phb->pci_regs_mr, OBJECT(phb), &pnv_pec_stk_pci_xscom_ops, phb, name, PHB4_PEC_PCI_STK_REGS_COUNT); @@ -1496,7 +1496,7 @@ static void pnv_phb4_xscom_realize(PnvPHB4 *phb) &stack->nest_regs_mr); pnv_xscom_add_subregion(pec->chip, pec_pci_base + 0x40 * (stack->stack_no + 1), - &stack->pci_regs_mr); + &phb->pci_regs_mr); pnv_xscom_add_subregion(pec->chip, pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 + 0x40 * stack->stack_no, diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 4b7ce8a723..4487c3a6e2 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -107,6 +107,11 @@ struct PnvPHB4 { MemoryRegion pci_mmio; MemoryRegion pci_io; + /* PCI registers (excluding pass-through) */ +#define PHB4_PEC_PCI_STK_REGS_COUNT 0xf + uint64_t pci_regs[PHB4_PEC_PCI_STK_REGS_COUNT]; + MemoryRegion pci_regs_mr; + /* On-chip IODA tables */ uint64_t ioda_LIST[PNV_PHB4_MAX_LSIs]; uint64_t ioda_MIST[PNV_PHB4_MAX_MIST]; @@ -155,11 +160,6 @@ struct PnvPhb4PecStack { uint64_t nest_regs[PHB4_PEC_NEST_STK_REGS_COUNT]; MemoryRegion nest_regs_mr; - /* PCI registers (excluding pass-through) */ -#define PHB4_PEC_PCI_STK_REGS_COUNT 0xf - uint64_t pci_regs[PHB4_PEC_PCI_STK_REGS_COUNT]; - MemoryRegion pci_regs_mr; - /* PHB pass-through XSCOM */ MemoryRegion phb_regs_mr; From e0d2379fa7cd46e94401dcc5aa1cf525db89d176 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 560/730] ppc/pnv: move phbbar to PnvPHB4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This MemoryRegion is simple enough to be moved in a single step. A 'stack->phb' pointer had to be introduced in pnv_pec_stk_update_map() because this function isn't ready to be fully converted to use a PnvPHB4 pointer instead. This will be dealt with in the following patches. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220113192952.911188-4-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 19 ++++++++++--------- include/hw/pci-host/pnv_phb4.h | 4 +++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index fd9f6af4b3..00eaf91fca 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -874,15 +874,15 @@ static void pnv_phb4_update_regions(PnvPhb4PecStack *stack) /* Unmap first always */ if (memory_region_is_mapped(&phb->mr_regs)) { - memory_region_del_subregion(&stack->phbbar, &phb->mr_regs); + memory_region_del_subregion(&phb->phbbar, &phb->mr_regs); } if (memory_region_is_mapped(&phb->xsrc.esb_mmio)) { memory_region_del_subregion(&stack->intbar, &phb->xsrc.esb_mmio); } /* Map registers if enabled */ - if (memory_region_is_mapped(&stack->phbbar)) { - memory_region_add_subregion(&stack->phbbar, 0, &phb->mr_regs); + if (memory_region_is_mapped(&phb->phbbar)) { + memory_region_add_subregion(&phb->phbbar, 0, &phb->mr_regs); } /* Map ESB if enabled */ @@ -897,6 +897,7 @@ static void pnv_phb4_update_regions(PnvPhb4PecStack *stack) static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) { PnvPhb4PecState *pec = stack->pec; + PnvPHB4 *phb = stack->phb; MemoryRegion *sysmem = get_system_memory(); uint64_t bar_en = stack->nest_regs[PEC_NEST_STK_BAR_EN]; uint64_t bar, mask, size; @@ -919,9 +920,9 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) !(bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) { memory_region_del_subregion(sysmem, &stack->mmbar1); } - if (memory_region_is_mapped(&stack->phbbar) && + if (memory_region_is_mapped(&phb->phbbar) && !(bar_en & PEC_NEST_STK_BAR_EN_PHB)) { - memory_region_del_subregion(sysmem, &stack->phbbar); + memory_region_del_subregion(sysmem, &phb->phbbar); } if (memory_region_is_mapped(&stack->intbar) && !(bar_en & PEC_NEST_STK_BAR_EN_INT)) { @@ -956,14 +957,14 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) stack->mmio1_base = bar; stack->mmio1_size = size; } - if (!memory_region_is_mapped(&stack->phbbar) && + if (!memory_region_is_mapped(&phb->phbbar) && (bar_en & PEC_NEST_STK_BAR_EN_PHB)) { bar = stack->nest_regs[PEC_NEST_STK_PHB_REGS_BAR] >> 8; size = PNV_PHB4_NUM_REGS << 3; - snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-phb", + snprintf(name, sizeof(name), "pec-%d.%d-phb-%d", pec->chip_id, pec->index, stack->stack_no); - memory_region_init(&stack->phbbar, OBJECT(stack), name, size); - memory_region_add_subregion(sysmem, bar, &stack->phbbar); + memory_region_init(&phb->phbbar, OBJECT(phb), name, size); + memory_region_add_subregion(sysmem, bar, &phb->phbbar); } if (!memory_region_is_mapped(&stack->intbar) && (bar_en & PEC_NEST_STK_BAR_EN_INT)) { diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 4487c3a6e2..b11fa80e81 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -112,6 +112,9 @@ struct PnvPHB4 { uint64_t pci_regs[PHB4_PEC_PCI_STK_REGS_COUNT]; MemoryRegion pci_regs_mr; + /* Memory windows from PowerBus to PHB */ + MemoryRegion phbbar; + /* On-chip IODA tables */ uint64_t ioda_LIST[PNV_PHB4_MAX_LSIs]; uint64_t ioda_MIST[PNV_PHB4_MAX_MIST]; @@ -166,7 +169,6 @@ struct PnvPhb4PecStack { /* Memory windows from PowerBus to PHB */ MemoryRegion mmbar0; MemoryRegion mmbar1; - MemoryRegion phbbar; MemoryRegion intbar; uint64_t mmio0_base; uint64_t mmio0_size; From db16c02ea7e399613ea74c32b02fb2737d6937e7 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:30 +0100 Subject: [PATCH 561/730] ppc/pnv: move intbar to PnvPHB4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This MemoryRegion can also be moved in a single step. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220113192952.911188-5-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 18 +++++++++--------- include/hw/pci-host/pnv_phb4.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 00eaf91fca..fbc475f27a 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -877,7 +877,7 @@ static void pnv_phb4_update_regions(PnvPhb4PecStack *stack) memory_region_del_subregion(&phb->phbbar, &phb->mr_regs); } if (memory_region_is_mapped(&phb->xsrc.esb_mmio)) { - memory_region_del_subregion(&stack->intbar, &phb->xsrc.esb_mmio); + memory_region_del_subregion(&phb->intbar, &phb->xsrc.esb_mmio); } /* Map registers if enabled */ @@ -886,8 +886,8 @@ static void pnv_phb4_update_regions(PnvPhb4PecStack *stack) } /* Map ESB if enabled */ - if (memory_region_is_mapped(&stack->intbar)) { - memory_region_add_subregion(&stack->intbar, 0, &phb->xsrc.esb_mmio); + if (memory_region_is_mapped(&phb->intbar)) { + memory_region_add_subregion(&phb->intbar, 0, &phb->xsrc.esb_mmio); } /* Check/update m32 */ @@ -924,9 +924,9 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) !(bar_en & PEC_NEST_STK_BAR_EN_PHB)) { memory_region_del_subregion(sysmem, &phb->phbbar); } - if (memory_region_is_mapped(&stack->intbar) && + if (memory_region_is_mapped(&phb->intbar) && !(bar_en & PEC_NEST_STK_BAR_EN_INT)) { - memory_region_del_subregion(sysmem, &stack->intbar); + memory_region_del_subregion(sysmem, &phb->intbar); } /* Update PHB */ @@ -966,14 +966,14 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) memory_region_init(&phb->phbbar, OBJECT(phb), name, size); memory_region_add_subregion(sysmem, bar, &phb->phbbar); } - if (!memory_region_is_mapped(&stack->intbar) && + if (!memory_region_is_mapped(&phb->intbar) && (bar_en & PEC_NEST_STK_BAR_EN_INT)) { bar = stack->nest_regs[PEC_NEST_STK_INT_BAR] >> 8; size = PNV_PHB4_MAX_INTs << 16; - snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-int", + snprintf(name, sizeof(name), "pec-%d.%d-phb-%d-int", stack->pec->chip_id, stack->pec->index, stack->stack_no); - memory_region_init(&stack->intbar, OBJECT(stack), name, size); - memory_region_add_subregion(sysmem, bar, &stack->intbar); + memory_region_init(&phb->intbar, OBJECT(phb), name, size); + memory_region_add_subregion(sysmem, bar, &phb->intbar); } /* Update PHB */ diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index b11fa80e81..cf5dd4009c 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -114,6 +114,7 @@ struct PnvPHB4 { /* Memory windows from PowerBus to PHB */ MemoryRegion phbbar; + MemoryRegion intbar; /* On-chip IODA tables */ uint64_t ioda_LIST[PNV_PHB4_MAX_LSIs]; @@ -169,7 +170,6 @@ struct PnvPhb4PecStack { /* Memory windows from PowerBus to PHB */ MemoryRegion mmbar0; MemoryRegion mmbar1; - MemoryRegion intbar; uint64_t mmio0_base; uint64_t mmio0_size; uint64_t mmio1_base; From 7edb9514bff1552309a51cdea4f3f2afc47fe8c0 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 562/730] ppc/pnv: change pnv_phb4_update_regions() to use PnvPHB4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function does not rely on stack for anything it does anymore. This is also one less instance of 'stack->phb' that we need to worry about. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220113192952.911188-6-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index fbc475f27a..034721f159 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -868,10 +868,8 @@ static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr, return stack->nest_regs[reg]; } -static void pnv_phb4_update_regions(PnvPhb4PecStack *stack) +static void pnv_phb4_update_regions(PnvPHB4 *phb) { - PnvPHB4 *phb = stack->phb; - /* Unmap first always */ if (memory_region_is_mapped(&phb->mr_regs)) { memory_region_del_subregion(&phb->phbbar, &phb->mr_regs); @@ -930,7 +928,7 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) } /* Update PHB */ - pnv_phb4_update_regions(stack); + pnv_phb4_update_regions(phb); /* Handle maps */ if (!memory_region_is_mapped(&stack->mmbar0) && @@ -977,7 +975,7 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) } /* Update PHB */ - pnv_phb4_update_regions(stack); + pnv_phb4_update_regions(phb); } static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr, From 1293d7352150c3f186ffe09d2024df3969df61c3 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 563/730] ppc/pnv: move mmbar0/mmbar1 and friends to PnvPHB4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These 2 MemoryRegions, together with mmio(0|1)_base and mmio(0|1)_size variables, are used together in the same functions. We're better of moving them all in a single step. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220113192952.911188-7-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 52 +++++++++++++++++----------------- include/hw/pci-host/pnv_phb4.h | 14 ++++----- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 034721f159..dc4db091e4 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -228,16 +228,16 @@ static void pnv_phb4_check_mbt(PnvPHB4 *phb, uint32_t index) /* TODO: Figure out how to implemet/decode AOMASK */ /* Check if it matches an enabled MMIO region in the PEC stack */ - if (memory_region_is_mapped(&phb->stack->mmbar0) && - base >= phb->stack->mmio0_base && - (base + size) <= (phb->stack->mmio0_base + phb->stack->mmio0_size)) { - parent = &phb->stack->mmbar0; - base -= phb->stack->mmio0_base; - } else if (memory_region_is_mapped(&phb->stack->mmbar1) && - base >= phb->stack->mmio1_base && - (base + size) <= (phb->stack->mmio1_base + phb->stack->mmio1_size)) { - parent = &phb->stack->mmbar1; - base -= phb->stack->mmio1_base; + if (memory_region_is_mapped(&phb->mmbar0) && + base >= phb->mmio0_base && + (base + size) <= (phb->mmio0_base + phb->mmio0_size)) { + parent = &phb->mmbar0; + base -= phb->mmio0_base; + } else if (memory_region_is_mapped(&phb->mmbar1) && + base >= phb->mmio1_base && + (base + size) <= (phb->mmio1_base + phb->mmio1_size)) { + parent = &phb->mmbar1; + base -= phb->mmio1_base; } else { phb_error(phb, "PHB MBAR %d out of parent bounds", index); return; @@ -910,13 +910,13 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) */ /* Handle unmaps */ - if (memory_region_is_mapped(&stack->mmbar0) && + if (memory_region_is_mapped(&phb->mmbar0) && !(bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) { - memory_region_del_subregion(sysmem, &stack->mmbar0); + memory_region_del_subregion(sysmem, &phb->mmbar0); } - if (memory_region_is_mapped(&stack->mmbar1) && + if (memory_region_is_mapped(&phb->mmbar1) && !(bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) { - memory_region_del_subregion(sysmem, &stack->mmbar1); + memory_region_del_subregion(sysmem, &phb->mmbar1); } if (memory_region_is_mapped(&phb->phbbar) && !(bar_en & PEC_NEST_STK_BAR_EN_PHB)) { @@ -931,29 +931,29 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) pnv_phb4_update_regions(phb); /* Handle maps */ - if (!memory_region_is_mapped(&stack->mmbar0) && + if (!memory_region_is_mapped(&phb->mmbar0) && (bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) { bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0] >> 8; mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0_MASK]; size = ((~mask) >> 8) + 1; - snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio0", + snprintf(name, sizeof(name), "pec-%d.%d-phb-%d-mmio0", pec->chip_id, pec->index, stack->stack_no); - memory_region_init(&stack->mmbar0, OBJECT(stack), name, size); - memory_region_add_subregion(sysmem, bar, &stack->mmbar0); - stack->mmio0_base = bar; - stack->mmio0_size = size; + memory_region_init(&phb->mmbar0, OBJECT(phb), name, size); + memory_region_add_subregion(sysmem, bar, &phb->mmbar0); + phb->mmio0_base = bar; + phb->mmio0_size = size; } - if (!memory_region_is_mapped(&stack->mmbar1) && + if (!memory_region_is_mapped(&phb->mmbar1) && (bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) { bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1] >> 8; mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1_MASK]; size = ((~mask) >> 8) + 1; - snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio1", + snprintf(name, sizeof(name), "pec-%d.%d-phb-%d-mmio1", pec->chip_id, pec->index, stack->stack_no); - memory_region_init(&stack->mmbar1, OBJECT(stack), name, size); - memory_region_add_subregion(sysmem, bar, &stack->mmbar1); - stack->mmio1_base = bar; - stack->mmio1_size = size; + memory_region_init(&phb->mmbar1, OBJECT(phb), name, size); + memory_region_add_subregion(sysmem, bar, &phb->mmbar1); + phb->mmio1_base = bar; + phb->mmio1_size = size; } if (!memory_region_is_mapped(&phb->phbbar) && (bar_en & PEC_NEST_STK_BAR_EN_PHB)) { diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index cf5dd4009c..4a8f510f6d 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -115,6 +115,12 @@ struct PnvPHB4 { /* Memory windows from PowerBus to PHB */ MemoryRegion phbbar; MemoryRegion intbar; + MemoryRegion mmbar0; + MemoryRegion mmbar1; + uint64_t mmio0_base; + uint64_t mmio0_size; + uint64_t mmio1_base; + uint64_t mmio1_size; /* On-chip IODA tables */ uint64_t ioda_LIST[PNV_PHB4_MAX_LSIs]; @@ -167,14 +173,6 @@ struct PnvPhb4PecStack { /* PHB pass-through XSCOM */ MemoryRegion phb_regs_mr; - /* Memory windows from PowerBus to PHB */ - MemoryRegion mmbar0; - MemoryRegion mmbar1; - uint64_t mmio0_base; - uint64_t mmio0_size; - uint64_t mmio1_base; - uint64_t mmio1_size; - /* The owner PEC */ PnvPhb4PecState *pec; From 98f08333431ef453d1dbfc91d2ebe9bab8cb6d4f Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 564/730] ppc/pnv: move nest_regs[] to PnvPHB4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit stack->nest_regs[] is used in several XSCOM functions and it's one of the main culprits of having to deal with stack->phb pointers around the code. Sure, we're having to add 2 extra stack->phb pointers to ease nest_regs[] migration to PnvPHB4. They'll be dealt with shortly. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220113192952.911188-8-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 52 ++++++++++++++++++---------------- include/hw/pci-host/pnv_phb4.h | 7 +++-- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index dc4db091e4..916a7a3cf0 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -862,10 +862,11 @@ static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr, unsigned size) { PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); + PnvPHB4 *phb = stack->phb; uint32_t reg = addr >> 3; /* TODO: add list of allowed registers and error out if not */ - return stack->nest_regs[reg]; + return phb->nest_regs[reg]; } static void pnv_phb4_update_regions(PnvPHB4 *phb) @@ -897,7 +898,7 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) PnvPhb4PecState *pec = stack->pec; PnvPHB4 *phb = stack->phb; MemoryRegion *sysmem = get_system_memory(); - uint64_t bar_en = stack->nest_regs[PEC_NEST_STK_BAR_EN]; + uint64_t bar_en = phb->nest_regs[PEC_NEST_STK_BAR_EN]; uint64_t bar, mask, size; char name[64]; @@ -933,8 +934,8 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) /* Handle maps */ if (!memory_region_is_mapped(&phb->mmbar0) && (bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) { - bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0] >> 8; - mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0_MASK]; + bar = phb->nest_regs[PEC_NEST_STK_MMIO_BAR0] >> 8; + mask = phb->nest_regs[PEC_NEST_STK_MMIO_BAR0_MASK]; size = ((~mask) >> 8) + 1; snprintf(name, sizeof(name), "pec-%d.%d-phb-%d-mmio0", pec->chip_id, pec->index, stack->stack_no); @@ -945,8 +946,8 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) } if (!memory_region_is_mapped(&phb->mmbar1) && (bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) { - bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1] >> 8; - mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1_MASK]; + bar = phb->nest_regs[PEC_NEST_STK_MMIO_BAR1] >> 8; + mask = phb->nest_regs[PEC_NEST_STK_MMIO_BAR1_MASK]; size = ((~mask) >> 8) + 1; snprintf(name, sizeof(name), "pec-%d.%d-phb-%d-mmio1", pec->chip_id, pec->index, stack->stack_no); @@ -957,7 +958,7 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) } if (!memory_region_is_mapped(&phb->phbbar) && (bar_en & PEC_NEST_STK_BAR_EN_PHB)) { - bar = stack->nest_regs[PEC_NEST_STK_PHB_REGS_BAR] >> 8; + bar = phb->nest_regs[PEC_NEST_STK_PHB_REGS_BAR] >> 8; size = PNV_PHB4_NUM_REGS << 3; snprintf(name, sizeof(name), "pec-%d.%d-phb-%d", pec->chip_id, pec->index, stack->stack_no); @@ -966,7 +967,7 @@ static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) } if (!memory_region_is_mapped(&phb->intbar) && (bar_en & PEC_NEST_STK_BAR_EN_INT)) { - bar = stack->nest_regs[PEC_NEST_STK_INT_BAR] >> 8; + bar = phb->nest_regs[PEC_NEST_STK_INT_BAR] >> 8; size = PNV_PHB4_MAX_INTs << 16; snprintf(name, sizeof(name), "pec-%d.%d-phb-%d-int", stack->pec->chip_id, stack->pec->index, stack->stack_no); @@ -982,34 +983,35 @@ static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); + PnvPHB4 *phb = stack->phb; PnvPhb4PecState *pec = stack->pec; uint32_t reg = addr >> 3; switch (reg) { case PEC_NEST_STK_PCI_NEST_FIR: - stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] = val; + phb->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] = val; break; case PEC_NEST_STK_PCI_NEST_FIR_CLR: - stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] &= val; + phb->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] &= val; break; case PEC_NEST_STK_PCI_NEST_FIR_SET: - stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] |= val; + phb->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] |= val; break; case PEC_NEST_STK_PCI_NEST_FIR_MSK: - stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] = val; + phb->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] = val; break; case PEC_NEST_STK_PCI_NEST_FIR_MSKC: - stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] &= val; + phb->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] &= val; break; case PEC_NEST_STK_PCI_NEST_FIR_MSKS: - stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] |= val; + phb->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] |= val; break; case PEC_NEST_STK_PCI_NEST_FIR_ACT0: case PEC_NEST_STK_PCI_NEST_FIR_ACT1: - stack->nest_regs[reg] = val; + phb->nest_regs[reg] = val; break; case PEC_NEST_STK_PCI_NEST_FIR_WOF: - stack->nest_regs[reg] = 0; + phb->nest_regs[reg] = 0; break; case PEC_NEST_STK_ERR_REPORT_0: case PEC_NEST_STK_ERR_REPORT_1: @@ -1017,39 +1019,39 @@ static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr, /* Flag error ? */ break; case PEC_NEST_STK_PBCQ_MODE: - stack->nest_regs[reg] = val & 0xff00000000000000ull; + phb->nest_regs[reg] = val & 0xff00000000000000ull; break; case PEC_NEST_STK_MMIO_BAR0: case PEC_NEST_STK_MMIO_BAR0_MASK: case PEC_NEST_STK_MMIO_BAR1: case PEC_NEST_STK_MMIO_BAR1_MASK: - if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & + if (phb->nest_regs[PEC_NEST_STK_BAR_EN] & (PEC_NEST_STK_BAR_EN_MMIO0 | PEC_NEST_STK_BAR_EN_MMIO1)) { phb_pec_error(pec, "Changing enabled BAR unsupported\n"); } - stack->nest_regs[reg] = val & 0xffffffffff000000ull; + phb->nest_regs[reg] = val & 0xffffffffff000000ull; break; case PEC_NEST_STK_PHB_REGS_BAR: - if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_PHB) { + if (phb->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_PHB) { phb_pec_error(pec, "Changing enabled BAR unsupported\n"); } - stack->nest_regs[reg] = val & 0xffffffffffc00000ull; + phb->nest_regs[reg] = val & 0xffffffffffc00000ull; break; case PEC_NEST_STK_INT_BAR: - if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_INT) { + if (phb->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_INT) { phb_pec_error(pec, "Changing enabled BAR unsupported\n"); } - stack->nest_regs[reg] = val & 0xfffffff000000000ull; + phb->nest_regs[reg] = val & 0xfffffff000000000ull; break; case PEC_NEST_STK_BAR_EN: - stack->nest_regs[reg] = val & 0xf000000000000000ull; + phb->nest_regs[reg] = val & 0xf000000000000000ull; pnv_pec_stk_update_map(stack); break; case PEC_NEST_STK_DATA_FRZ_TYPE: case PEC_NEST_STK_PBCQ_TUN_BAR: /* Not used for now */ - stack->nest_regs[reg] = val; + phb->nest_regs[reg] = val; break; default: qemu_log_mask(LOG_UNIMP, "phb4_pec: nest_xscom_write 0x%"HWADDR_PRIx diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 4a8f510f6d..a7e08772c1 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -112,6 +112,10 @@ struct PnvPHB4 { uint64_t pci_regs[PHB4_PEC_PCI_STK_REGS_COUNT]; MemoryRegion pci_regs_mr; + /* Nest registers */ +#define PHB4_PEC_NEST_STK_REGS_COUNT 0x17 + uint64_t nest_regs[PHB4_PEC_NEST_STK_REGS_COUNT]; + /* Memory windows from PowerBus to PHB */ MemoryRegion phbbar; MemoryRegion intbar; @@ -165,9 +169,6 @@ struct PnvPhb4PecStack { /* My own stack number */ uint32_t stack_no; - /* Nest registers */ -#define PHB4_PEC_NEST_STK_REGS_COUNT 0x17 - uint64_t nest_regs[PHB4_PEC_NEST_STK_REGS_COUNT]; MemoryRegion nest_regs_mr; /* PHB pass-through XSCOM */ From e19e998ce29c31eaf635ebada3133fc7db4e8a93 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 565/730] ppc/pnv: change pnv_pec_stk_update_map() to use PnvPHB4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit stack->nest_regs_mr wasn't migrated to PnvPHB4 together with phb->nest_regs[] in the previous patch. We were unable to cleanly convert its write MemoryRegionOps, pnv_pec_stk_nest_xscom_write(), to use PnvPHB4 instead of PnvPhb4PecStack due to pnv_pec_stk_update_map() using a stack. Thing is, we're now able to convert pnv_pec_stk_update_map() because of what the did in previous patch. The need for this intermediate step is a good example of the interconnected relationship between stack and phb that we aim to cleanup. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220113192952.911188-9-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 916a7a3cf0..0f4464ec67 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -893,10 +893,10 @@ static void pnv_phb4_update_regions(PnvPHB4 *phb) pnv_phb4_check_all_mbt(phb); } -static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) +static void pnv_pec_stk_update_map(PnvPHB4 *phb) { + PnvPhb4PecStack *stack = phb->stack; PnvPhb4PecState *pec = stack->pec; - PnvPHB4 *phb = stack->phb; MemoryRegion *sysmem = get_system_memory(); uint64_t bar_en = phb->nest_regs[PEC_NEST_STK_BAR_EN]; uint64_t bar, mask, size; @@ -1046,7 +1046,7 @@ static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr, break; case PEC_NEST_STK_BAR_EN: phb->nest_regs[reg] = val & 0xf000000000000000ull; - pnv_pec_stk_update_map(stack); + pnv_pec_stk_update_map(phb); break; case PEC_NEST_STK_DATA_FRZ_TYPE: case PEC_NEST_STK_PBCQ_TUN_BAR: From 867683d86e3c88b07034d891937a3535ace5ff38 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 566/730] ppc/pnv: move nest_regs_mr to PnvPHB4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We're now able to cleanly move nest_regs_mr to the PnvPHB4 device. One thing of notice here is the need to use a phb->stack->pec pointer because pnv_pec_stk_nest_xscom_write requires a PEC object. Another thing that can be noticed in the use of 'stack->stack_no' that still remains throughout the XSCOM code. After moving all MemoryRegions to the PnvPHB4 object, this illustrates what is the remaining role of the stack: provide a PEC pointer and the 'stack_no' information. If we can provide these in the PnvPHB4 object instead (spoiler: we can, and we will), the PnvPhb4PecStack device will be deprecated and can be removed. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220113192952.911188-10-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 16 +++++++--------- include/hw/pci-host/pnv_phb4.h | 3 +-- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 0f4464ec67..37bab10fcb 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -861,8 +861,7 @@ const MemoryRegionOps pnv_phb4_xscom_ops = { static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr, unsigned size) { - PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); - PnvPHB4 *phb = stack->phb; + PnvPHB4 *phb = PNV_PHB4(opaque); uint32_t reg = addr >> 3; /* TODO: add list of allowed registers and error out if not */ @@ -982,9 +981,8 @@ static void pnv_pec_stk_update_map(PnvPHB4 *phb) static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); - PnvPHB4 *phb = stack->phb; - PnvPhb4PecState *pec = stack->pec; + PnvPHB4 *phb = PNV_PHB4(opaque); + PnvPhb4PecState *pec = phb->stack->pec; uint32_t reg = addr >> 3; switch (reg) { @@ -1470,10 +1468,10 @@ static void pnv_phb4_xscom_realize(PnvPHB4 *phb) assert(pec); /* Initialize the XSCOM regions for the stack registers */ - snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest-stack-%d", + snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest-phb-%d", pec->chip_id, pec->index, stack->stack_no); - pnv_xscom_region_init(&stack->nest_regs_mr, OBJECT(stack), - &pnv_pec_stk_nest_xscom_ops, stack, name, + pnv_xscom_region_init(&phb->nest_regs_mr, OBJECT(phb), + &pnv_pec_stk_nest_xscom_ops, phb, name, PHB4_PEC_NEST_STK_REGS_COUNT); snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-phb-%d", @@ -1494,7 +1492,7 @@ static void pnv_phb4_xscom_realize(PnvPHB4 *phb) /* Populate the XSCOM address space. */ pnv_xscom_add_subregion(pec->chip, pec_nest_base + 0x40 * (stack->stack_no + 1), - &stack->nest_regs_mr); + &phb->nest_regs_mr); pnv_xscom_add_subregion(pec->chip, pec_pci_base + 0x40 * (stack->stack_no + 1), &phb->pci_regs_mr); diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index a7e08772c1..1d53dda0ed 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -115,6 +115,7 @@ struct PnvPHB4 { /* Nest registers */ #define PHB4_PEC_NEST_STK_REGS_COUNT 0x17 uint64_t nest_regs[PHB4_PEC_NEST_STK_REGS_COUNT]; + MemoryRegion nest_regs_mr; /* Memory windows from PowerBus to PHB */ MemoryRegion phbbar; @@ -169,8 +170,6 @@ struct PnvPhb4PecStack { /* My own stack number */ uint32_t stack_no; - MemoryRegion nest_regs_mr; - /* PHB pass-through XSCOM */ MemoryRegion phb_regs_mr; From 293a1d27e34810dfa70193b480d0ac265801f1f3 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 567/730] ppc/pnv: move phb_regs_mr to PnvPHB4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After recent changes, this MemoryRegion can be migrated to PnvPHB4 without too much trouble. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220113192952.911188-11-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 6 +++--- include/hw/pci-host/pnv_phb4.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 37bab10fcb..b5045fca64 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1481,9 +1481,9 @@ static void pnv_phb4_xscom_realize(PnvPHB4 *phb) PHB4_PEC_PCI_STK_REGS_COUNT); /* PHB pass-through */ - snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d-phb", + snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-phb-%d", pec->chip_id, pec->index, stack->stack_no); - pnv_xscom_region_init(&stack->phb_regs_mr, OBJECT(phb), + pnv_xscom_region_init(&phb->phb_regs_mr, OBJECT(phb), &pnv_phb4_xscom_ops, phb, name, 0x40); pec_nest_base = pecc->xscom_nest_base(pec); @@ -1499,7 +1499,7 @@ static void pnv_phb4_xscom_realize(PnvPHB4 *phb) pnv_xscom_add_subregion(pec->chip, pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 + 0x40 * stack->stack_no, - &stack->phb_regs_mr); + &phb->phb_regs_mr); } static void pnv_phb4_instance_init(Object *obj) diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 1d53dda0ed..6968efaba8 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -117,6 +117,9 @@ struct PnvPHB4 { uint64_t nest_regs[PHB4_PEC_NEST_STK_REGS_COUNT]; MemoryRegion nest_regs_mr; + /* PHB pass-through XSCOM */ + MemoryRegion phb_regs_mr; + /* Memory windows from PowerBus to PHB */ MemoryRegion phbbar; MemoryRegion intbar; @@ -170,9 +173,6 @@ struct PnvPhb4PecStack { /* My own stack number */ uint32_t stack_no; - /* PHB pass-through XSCOM */ - MemoryRegion phb_regs_mr; - /* The owner PEC */ PnvPhb4PecState *pec; From d2704eb3fd5093224fb14ecbfdc916d42d42416b Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 568/730] ppc/pnv: introduce PnvPHB4 'pec' property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This property will track the owner PEC of this PHB. For now it's redundant since we can retrieve the PEC via phb->stack->pec but it will not be redundant when we get rid of the stack device. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220114180719.52117-2-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 19 +++++++++++++------ hw/pci-host/pnv_phb4_pec.c | 2 ++ include/hw/pci-host/pnv_phb4.h | 3 +++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index b5045fca64..2658ef2d84 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -895,7 +895,7 @@ static void pnv_phb4_update_regions(PnvPHB4 *phb) static void pnv_pec_stk_update_map(PnvPHB4 *phb) { PnvPhb4PecStack *stack = phb->stack; - PnvPhb4PecState *pec = stack->pec; + PnvPhb4PecState *pec = phb->pec; MemoryRegion *sysmem = get_system_memory(); uint64_t bar_en = phb->nest_regs[PEC_NEST_STK_BAR_EN]; uint64_t bar, mask, size; @@ -969,7 +969,7 @@ static void pnv_pec_stk_update_map(PnvPHB4 *phb) bar = phb->nest_regs[PEC_NEST_STK_INT_BAR] >> 8; size = PNV_PHB4_MAX_INTs << 16; snprintf(name, sizeof(name), "pec-%d.%d-phb-%d-int", - stack->pec->chip_id, stack->pec->index, stack->stack_no); + phb->pec->chip_id, phb->pec->index, stack->stack_no); memory_region_init(&phb->intbar, OBJECT(phb), name, size); memory_region_add_subregion(sysmem, bar, &phb->intbar); } @@ -982,7 +982,7 @@ static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PnvPHB4 *phb = PNV_PHB4(opaque); - PnvPhb4PecState *pec = phb->stack->pec; + PnvPhb4PecState *pec = phb->pec; uint32_t reg = addr >> 3; switch (reg) { @@ -1459,7 +1459,7 @@ static AddressSpace *pnv_phb4_dma_iommu(PCIBus *bus, void *opaque, int devfn) static void pnv_phb4_xscom_realize(PnvPHB4 *phb) { PnvPhb4PecStack *stack = phb->stack; - PnvPhb4PecState *pec = stack->pec; + PnvPhb4PecState *pec = phb->pec; PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); uint32_t pec_nest_base; uint32_t pec_pci_base; @@ -1568,8 +1568,13 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) return; } - /* All other phb properties but 'version' are already set */ - pecc = PNV_PHB4_PEC_GET_CLASS(phb->stack->pec); + /* + * All other phb properties but 'pec' ad 'version' are + * already set. + */ + object_property_set_link(OBJECT(phb), "pec", OBJECT(phb->stack->pec), + &error_abort); + pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec); object_property_set_int(OBJECT(phb), "version", pecc->version, &error_fatal); @@ -1682,6 +1687,8 @@ static Property pnv_phb4_properties[] = { DEFINE_PROP_UINT64("version", PnvPHB4, version, 0), DEFINE_PROP_LINK("stack", PnvPHB4, stack, TYPE_PNV_PHB4_PEC_STACK, PnvPhb4PecStack *), + DEFINE_PROP_LINK("pec", PnvPHB4, pec, TYPE_PNV_PHB4_PEC, + PnvPhb4PecState *), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 7fe7f1f007..22194b8de2 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -285,6 +285,8 @@ static void pnv_pec_stk_default_phb_realize(PnvPhb4PecStack *stack, stack->phb = PNV_PHB4(qdev_new(TYPE_PNV_PHB4)); + object_property_set_link(OBJECT(stack->phb), "pec", OBJECT(pec), + &error_abort); object_property_set_int(OBJECT(stack->phb), "chip-id", pec->chip_id, &error_fatal); object_property_set_int(OBJECT(stack->phb), "index", phb_id, diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 6968efaba8..1d27e4c0cb 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -84,6 +84,9 @@ struct PnvPHB4 { uint64_t version; + /* The owner PEC */ + PnvPhb4PecState *pec; + char bus_path[8]; /* Main register images */ From 6f506c90c3e1814a4a7df5be8d08782c06226820 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 569/730] ppc/pnv: reduce stack->stack_no usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'stack->stack_no' represents the order that a stack appears in its PEC. Its primary use is in XSCOM address space calculation in pnv_phb4_xscom_realize() when calculating the memory region offset. This attribute is redundant with phb->phb_id, which is calculated via pnv_phb4_pec_get_phb_id() using stack->stack_no information. It'll also be awkward to assign it when dealing with PECs and PHBs only in a future patch. A new pnv_phb4_get_phb_stack_no() helper is introduced to eliminate most of the stack->stack_no uses we have. The only use left after this patch is during pnv_pec_stk_default_phb_realize() when calculating phb_id, which will also handled in the next patches. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220114180719.52117-3-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 46 +++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 2658ef2d84..4933fe57fe 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -868,6 +868,28 @@ static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr, return phb->nest_regs[reg]; } +/* + * Return the 'stack_no' of a PHB4. 'stack_no' is the order + * the PHB4 occupies in the PEC. This is the reverse of what + * pnv_phb4_pec_get_phb_id() does. + * + * E.g. a phb with phb_id = 4 and pec->index = 1 (PEC1) will + * be the second phb (stack_no = 1) of the PEC. + */ +static int pnv_phb4_get_phb_stack_no(PnvPHB4 *phb) +{ + PnvPhb4PecState *pec = phb->pec; + PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); + int index = pec->index; + int stack_no = phb->phb_id; + + while (index--) { + stack_no -= pecc->num_stacks[index]; + } + + return stack_no; +} + static void pnv_phb4_update_regions(PnvPHB4 *phb) { /* Unmap first always */ @@ -894,10 +916,10 @@ static void pnv_phb4_update_regions(PnvPHB4 *phb) static void pnv_pec_stk_update_map(PnvPHB4 *phb) { - PnvPhb4PecStack *stack = phb->stack; PnvPhb4PecState *pec = phb->pec; MemoryRegion *sysmem = get_system_memory(); uint64_t bar_en = phb->nest_regs[PEC_NEST_STK_BAR_EN]; + int stack_no = pnv_phb4_get_phb_stack_no(phb); uint64_t bar, mask, size; char name[64]; @@ -937,7 +959,7 @@ static void pnv_pec_stk_update_map(PnvPHB4 *phb) mask = phb->nest_regs[PEC_NEST_STK_MMIO_BAR0_MASK]; size = ((~mask) >> 8) + 1; snprintf(name, sizeof(name), "pec-%d.%d-phb-%d-mmio0", - pec->chip_id, pec->index, stack->stack_no); + pec->chip_id, pec->index, stack_no); memory_region_init(&phb->mmbar0, OBJECT(phb), name, size); memory_region_add_subregion(sysmem, bar, &phb->mmbar0); phb->mmio0_base = bar; @@ -949,7 +971,7 @@ static void pnv_pec_stk_update_map(PnvPHB4 *phb) mask = phb->nest_regs[PEC_NEST_STK_MMIO_BAR1_MASK]; size = ((~mask) >> 8) + 1; snprintf(name, sizeof(name), "pec-%d.%d-phb-%d-mmio1", - pec->chip_id, pec->index, stack->stack_no); + pec->chip_id, pec->index, stack_no); memory_region_init(&phb->mmbar1, OBJECT(phb), name, size); memory_region_add_subregion(sysmem, bar, &phb->mmbar1); phb->mmio1_base = bar; @@ -960,7 +982,7 @@ static void pnv_pec_stk_update_map(PnvPHB4 *phb) bar = phb->nest_regs[PEC_NEST_STK_PHB_REGS_BAR] >> 8; size = PNV_PHB4_NUM_REGS << 3; snprintf(name, sizeof(name), "pec-%d.%d-phb-%d", - pec->chip_id, pec->index, stack->stack_no); + pec->chip_id, pec->index, stack_no); memory_region_init(&phb->phbbar, OBJECT(phb), name, size); memory_region_add_subregion(sysmem, bar, &phb->phbbar); } @@ -969,7 +991,7 @@ static void pnv_pec_stk_update_map(PnvPHB4 *phb) bar = phb->nest_regs[PEC_NEST_STK_INT_BAR] >> 8; size = PNV_PHB4_MAX_INTs << 16; snprintf(name, sizeof(name), "pec-%d.%d-phb-%d-int", - phb->pec->chip_id, phb->pec->index, stack->stack_no); + phb->pec->chip_id, phb->pec->index, stack_no); memory_region_init(&phb->intbar, OBJECT(phb), name, size); memory_region_add_subregion(sysmem, bar, &phb->intbar); } @@ -1458,9 +1480,9 @@ static AddressSpace *pnv_phb4_dma_iommu(PCIBus *bus, void *opaque, int devfn) static void pnv_phb4_xscom_realize(PnvPHB4 *phb) { - PnvPhb4PecStack *stack = phb->stack; PnvPhb4PecState *pec = phb->pec; PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); + int stack_no = pnv_phb4_get_phb_stack_no(phb); uint32_t pec_nest_base; uint32_t pec_pci_base; char name[64]; @@ -1469,20 +1491,20 @@ static void pnv_phb4_xscom_realize(PnvPHB4 *phb) /* Initialize the XSCOM regions for the stack registers */ snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest-phb-%d", - pec->chip_id, pec->index, stack->stack_no); + pec->chip_id, pec->index, stack_no); pnv_xscom_region_init(&phb->nest_regs_mr, OBJECT(phb), &pnv_pec_stk_nest_xscom_ops, phb, name, PHB4_PEC_NEST_STK_REGS_COUNT); snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-phb-%d", - pec->chip_id, pec->index, stack->stack_no); + pec->chip_id, pec->index, stack_no); pnv_xscom_region_init(&phb->pci_regs_mr, OBJECT(phb), &pnv_pec_stk_pci_xscom_ops, phb, name, PHB4_PEC_PCI_STK_REGS_COUNT); /* PHB pass-through */ snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-phb-%d", - pec->chip_id, pec->index, stack->stack_no); + pec->chip_id, pec->index, stack_no); pnv_xscom_region_init(&phb->phb_regs_mr, OBJECT(phb), &pnv_phb4_xscom_ops, phb, name, 0x40); @@ -1491,14 +1513,14 @@ static void pnv_phb4_xscom_realize(PnvPHB4 *phb) /* Populate the XSCOM address space. */ pnv_xscom_add_subregion(pec->chip, - pec_nest_base + 0x40 * (stack->stack_no + 1), + pec_nest_base + 0x40 * (stack_no + 1), &phb->nest_regs_mr); pnv_xscom_add_subregion(pec->chip, - pec_pci_base + 0x40 * (stack->stack_no + 1), + pec_pci_base + 0x40 * (stack_no + 1), &phb->pci_regs_mr); pnv_xscom_add_subregion(pec->chip, pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 + - 0x40 * stack->stack_no, + 0x40 * stack_no, &phb->phb_regs_mr); } From 7e67e0a9f00072f31c5279f711441ddfa96ee0e2 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 570/730] ppc/pnv: remove stack pointer from PnvPHB4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pointer was being used for two reasons: pnv_phb4_update_regions() was using it to access the PHB and phb4_realize() was using it as a way to determine if the PHB was user created. We can determine if the PHB is user created via phb->pec, introduced in the previous patch, and pnv_phb4_update_regions() is no longer using stack->phb. Remove the pointer from the PnvPHB4 device. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220114180719.52117-4-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 15 ++++----------- hw/pci-host/pnv_phb4_pec.c | 2 -- include/hw/pci-host/pnv_phb4.h | 2 -- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 4933fe57fe..2efd34518e 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1573,9 +1573,10 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) char name[32]; /* User created PHB */ - if (!phb->stack) { + if (!phb->pec) { PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); PnvChip *chip = pnv_get_chip(pnv, phb->chip_id); + PnvPhb4PecStack *stack; PnvPhb4PecClass *pecc; BusState *s; @@ -1584,7 +1585,7 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) return; } - phb->stack = pnv_phb4_get_stack(chip, phb, &local_err); + stack = pnv_phb4_get_stack(chip, phb, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -1594,18 +1595,12 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) * All other phb properties but 'pec' ad 'version' are * already set. */ - object_property_set_link(OBJECT(phb), "pec", OBJECT(phb->stack->pec), + object_property_set_link(OBJECT(phb), "pec", OBJECT(stack->pec), &error_abort); pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec); object_property_set_int(OBJECT(phb), "version", pecc->version, &error_fatal); - /* - * Assign stack->phb since pnv_phb4_update_regions() uses it - * to access the phb. - */ - phb->stack->phb = phb; - /* * Reparent user created devices to the chip to build * correctly the device tree. @@ -1707,8 +1702,6 @@ static Property pnv_phb4_properties[] = { DEFINE_PROP_UINT32("index", PnvPHB4, phb_id, 0), DEFINE_PROP_UINT32("chip-id", PnvPHB4, chip_id, 0), DEFINE_PROP_UINT64("version", PnvPHB4, version, 0), - DEFINE_PROP_LINK("stack", PnvPHB4, stack, TYPE_PNV_PHB4_PEC_STACK, - PnvPhb4PecStack *), DEFINE_PROP_LINK("pec", PnvPHB4, pec, TYPE_PNV_PHB4_PEC, PnvPhb4PecState *), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 22194b8de2..ed1d644182 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -293,8 +293,6 @@ static void pnv_pec_stk_default_phb_realize(PnvPhb4PecStack *stack, &error_fatal); object_property_set_int(OBJECT(stack->phb), "version", pecc->version, &error_fatal); - object_property_set_link(OBJECT(stack->phb), "stack", OBJECT(stack), - &error_abort); if (!sysbus_realize(SYS_BUS_DEVICE(stack->phb), errp)) { return; diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 1d27e4c0cb..a9059b7279 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -151,8 +151,6 @@ struct PnvPHB4 { XiveSource xsrc; qemu_irq *qirqs; - PnvPhb4PecStack *stack; - QLIST_HEAD(, PnvPhb4DMASpace) dma_spaces; }; From a479f0dcc0e46562768b238c2d53b50401aebfcf Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 571/730] ppc/pnv: move default_phb_realize() to pec_realize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the current pnv_pec_stk_default_phb_realize() call to pec_realize(), renaming the function to pnv_pec_default_phb_realize(), and set the PHB attributes using the PEC object directly. This will be important to allow for PECs devices to handle PHB4s directly later on. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220114180719.52117-5-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4_pec.c | 63 ++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index ed1d644182..a80a21db77 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -112,6 +112,30 @@ static const MemoryRegionOps pnv_pec_pci_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; +static void pnv_pec_default_phb_realize(PnvPhb4PecStack *stack, + int stack_no, + Error **errp) +{ + PnvPhb4PecState *pec = stack->pec; + PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); + int phb_id = pnv_phb4_pec_get_phb_id(pec, stack_no); + + stack->phb = PNV_PHB4(qdev_new(TYPE_PNV_PHB4)); + + object_property_set_link(OBJECT(stack->phb), "pec", OBJECT(pec), + &error_abort); + object_property_set_int(OBJECT(stack->phb), "chip-id", pec->chip_id, + &error_fatal); + object_property_set_int(OBJECT(stack->phb), "index", phb_id, + &error_fatal); + object_property_set_int(OBJECT(stack->phb), "version", pecc->version, + &error_fatal); + + if (!sysbus_realize(SYS_BUS_DEVICE(stack->phb), errp)) { + return; + } +} + static void pnv_pec_instance_init(Object *obj) { PnvPhb4PecState *pec = PNV_PHB4_PEC(obj); @@ -144,6 +168,15 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp) object_property_set_int(stk_obj, "stack-no", i, &error_abort); object_property_set_link(stk_obj, "pec", OBJECT(pec), &error_abort); + + if (defaults_enabled()) { + pnv_pec_default_phb_realize(stack, i, errp); + } + + /* + * qdev gets angry if we don't realize 'stack' here, even + * if stk_realize() is now empty. + */ if (!qdev_realize(DEVICE(stk_obj), NULL, errp)) { return; } @@ -276,38 +309,8 @@ static const TypeInfo pnv_pec_type_info = { } }; -static void pnv_pec_stk_default_phb_realize(PnvPhb4PecStack *stack, - Error **errp) -{ - PnvPhb4PecState *pec = stack->pec; - PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); - int phb_id = pnv_phb4_pec_get_phb_id(pec, stack->stack_no); - - stack->phb = PNV_PHB4(qdev_new(TYPE_PNV_PHB4)); - - object_property_set_link(OBJECT(stack->phb), "pec", OBJECT(pec), - &error_abort); - object_property_set_int(OBJECT(stack->phb), "chip-id", pec->chip_id, - &error_fatal); - object_property_set_int(OBJECT(stack->phb), "index", phb_id, - &error_fatal); - object_property_set_int(OBJECT(stack->phb), "version", pecc->version, - &error_fatal); - - if (!sysbus_realize(SYS_BUS_DEVICE(stack->phb), errp)) { - return; - } -} - static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) { - PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev); - - if (!defaults_enabled()) { - return; - } - - pnv_pec_stk_default_phb_realize(stack, errp); } static Property pnv_pec_stk_properties[] = { From 5c9ecb2e44790dc6b8ee799433130dc5eedde19b Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 572/730] ppc/pnv: remove PnvPhb4PecStack::stack_no MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pnv_pec_default_phb_realize() stopped using it after the previous patch and no one else is using it. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220114180719.52117-6-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4_pec.c | 2 -- include/hw/pci-host/pnv_phb4.h | 3 --- 2 files changed, 5 deletions(-) diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index a80a21db77..d6405d6ca3 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -166,7 +166,6 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp) PnvPhb4PecStack *stack = &pec->stacks[i]; Object *stk_obj = OBJECT(stack); - object_property_set_int(stk_obj, "stack-no", i, &error_abort); object_property_set_link(stk_obj, "pec", OBJECT(pec), &error_abort); if (defaults_enabled()) { @@ -314,7 +313,6 @@ static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) } static Property pnv_pec_stk_properties[] = { - DEFINE_PROP_UINT32("stack-no", PnvPhb4PecStack, stack_no, 0), DEFINE_PROP_LINK("pec", PnvPhb4PecStack, pec, TYPE_PNV_PHB4_PEC, PnvPhb4PecState *), DEFINE_PROP_END_OF_LIST(), diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index a9059b7279..2be56b7afd 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -171,9 +171,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(PnvPhb4PecStack, PNV_PHB4_PEC_STACK) struct PnvPhb4PecStack { DeviceState parent; - /* My own stack number */ - uint32_t stack_no; - /* The owner PEC */ PnvPhb4PecState *pec; From 3f4c369ea63e846f1dd3a83229b9300350b44025 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 573/730] ppc/pnv: make PECs create and realize PHB4s MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch changes the design of the PEC device to create and realize PHB4s instead of PecStacks. After all the recent changes, PHB4s now contain all the information needed for their proper functioning, not relying on PecStack in any capacity. All changes are being made in a single patch to avoid renaming parts of the PecState and leaving the code in a strange way. E.g. rename PecClass->num_stacks to num_phbs, which would then read a pnv_pec_num_stacks[] array. To avoid mixing the old and new design more than necessary it's clearer to do these changes in a single step. The name changes made are: - in PnvPhb4PecState: * rename 'num_stacks' to 'num_phbs' * remove the pec->stacks[] array. Current code relies on the pec->stacks[] obj acting as a simple container, without ever accessing pec->stacks[] for any other purpose. Instead of converting this into a pec->phbs[] array, remove it - in PnvPhb4PecClass, rename *num_stacks to *num_phbs; - pnv_pec_num_stacks[] is renamed to pnv_pec_num_phbs[]. The logical changes: - pnv_pec_default_phb_realize(): * init and set the properties of the PnvPHB4 qdev * do not use stack->phb anymore; - pnv_pec_realize(): * use the new default_phb_realize() to init/realize each PHB if running with defaults; - pnv_pec_instance_init(): removed since we're creating the PHBs during pec_realize(); - pnv_phb4_get_stack(): * renamed to pnv_phb4_get_pec() and returns a PnvPhb4PecState*; - pnv_phb4_realize(): use 'phb->pec' instead of 'stack'. This design change shouldn't caused any behavioral change in the runtime of the machine. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Message-Id: <20220114180719.52117-7-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 26 ++++++-------- hw/pci-host/pnv_phb4_pec.c | 66 ++++++++++------------------------ include/hw/pci-host/pnv_phb4.h | 8 ++--- 3 files changed, 31 insertions(+), 69 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 2efd34518e..3dc3c70cb2 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -884,7 +884,7 @@ static int pnv_phb4_get_phb_stack_no(PnvPHB4 *phb) int stack_no = phb->phb_id; while (index--) { - stack_no -= pecc->num_stacks[index]; + stack_no -= pecc->num_phbs[index]; } return stack_no; @@ -1383,7 +1383,7 @@ int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index) int offset = 0; while (index--) { - offset += pecc->num_stacks[index]; + offset += pecc->num_phbs[index]; } return offset + stack_index; @@ -1534,8 +1534,8 @@ static void pnv_phb4_instance_init(Object *obj) object_initialize_child(obj, "source", &phb->xsrc, TYPE_XIVE_SOURCE); } -static PnvPhb4PecStack *pnv_phb4_get_stack(PnvChip *chip, PnvPHB4 *phb, - Error **errp) +static PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB4 *phb, + Error **errp) { Pnv9Chip *chip9 = PNV9_CHIP(chip); int chip_id = phb->chip_id; @@ -1544,14 +1544,14 @@ static PnvPhb4PecStack *pnv_phb4_get_stack(PnvChip *chip, PnvPHB4 *phb, for (i = 0; i < chip->num_pecs; i++) { /* - * For each PEC, check the amount of stacks it supports - * and see if the given phb4 index matches a stack. + * For each PEC, check the amount of phbs it supports + * and see if the given phb4 index matches an index. */ PnvPhb4PecState *pec = &chip9->pecs[i]; - for (j = 0; j < pec->num_stacks; j++) { + for (j = 0; j < pec->num_phbs; j++) { if (index == pnv_phb4_pec_get_phb_id(pec, j)) { - return &pec->stacks[j]; + return pec; } } } @@ -1576,7 +1576,6 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) if (!phb->pec) { PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); PnvChip *chip = pnv_get_chip(pnv, phb->chip_id); - PnvPhb4PecStack *stack; PnvPhb4PecClass *pecc; BusState *s; @@ -1585,18 +1584,13 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) return; } - stack = pnv_phb4_get_stack(chip, phb, &local_err); + phb->pec = pnv_phb4_get_pec(chip, phb, &local_err); if (local_err) { error_propagate(errp, local_err); return; } - /* - * All other phb properties but 'pec' ad 'version' are - * already set. - */ - object_property_set_link(OBJECT(phb), "pec", OBJECT(stack->pec), - &error_abort); + /* All other phb properties are already set */ pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec); object_property_set_int(OBJECT(phb), "version", pecc->version, &error_fatal); diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index d6405d6ca3..852816b9f8 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -112,41 +112,28 @@ static const MemoryRegionOps pnv_pec_pci_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static void pnv_pec_default_phb_realize(PnvPhb4PecStack *stack, +static void pnv_pec_default_phb_realize(PnvPhb4PecState *pec, int stack_no, Error **errp) { - PnvPhb4PecState *pec = stack->pec; + PnvPHB4 *phb = PNV_PHB4(qdev_new(TYPE_PNV_PHB4)); PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); int phb_id = pnv_phb4_pec_get_phb_id(pec, stack_no); - stack->phb = PNV_PHB4(qdev_new(TYPE_PNV_PHB4)); - - object_property_set_link(OBJECT(stack->phb), "pec", OBJECT(pec), + object_property_set_link(OBJECT(phb), "pec", OBJECT(pec), &error_abort); - object_property_set_int(OBJECT(stack->phb), "chip-id", pec->chip_id, + object_property_set_int(OBJECT(phb), "chip-id", pec->chip_id, &error_fatal); - object_property_set_int(OBJECT(stack->phb), "index", phb_id, + object_property_set_int(OBJECT(phb), "index", phb_id, &error_fatal); - object_property_set_int(OBJECT(stack->phb), "version", pecc->version, + object_property_set_int(OBJECT(phb), "version", pecc->version, &error_fatal); - if (!sysbus_realize(SYS_BUS_DEVICE(stack->phb), errp)) { + if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) { return; } } -static void pnv_pec_instance_init(Object *obj) -{ - PnvPhb4PecState *pec = PNV_PHB4_PEC(obj); - int i; - - for (i = 0; i < PHB4_PEC_MAX_STACKS; i++) { - object_initialize_child(obj, "stack[*]", &pec->stacks[i], - TYPE_PNV_PHB4_PEC_STACK); - } -} - static void pnv_pec_realize(DeviceState *dev, Error **errp) { PnvPhb4PecState *pec = PNV_PHB4_PEC(dev); @@ -159,29 +146,13 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp) return; } - pec->num_stacks = pecc->num_stacks[pec->index]; + pec->num_phbs = pecc->num_phbs[pec->index]; - /* Create stacks */ - for (i = 0; i < pec->num_stacks; i++) { - PnvPhb4PecStack *stack = &pec->stacks[i]; - Object *stk_obj = OBJECT(stack); - - object_property_set_link(stk_obj, "pec", OBJECT(pec), &error_abort); - - if (defaults_enabled()) { - pnv_pec_default_phb_realize(stack, i, errp); + /* Create PHBs if running with defaults */ + if (defaults_enabled()) { + for (i = 0; i < pec->num_phbs; i++) { + pnv_pec_default_phb_realize(pec, i, errp); } - - /* - * qdev gets angry if we don't realize 'stack' here, even - * if stk_realize() is now empty. - */ - if (!qdev_realize(DEVICE(stk_obj), NULL, errp)) { - return; - } - } - for (; i < PHB4_PEC_MAX_STACKS; i++) { - object_unparent(OBJECT(&pec->stacks[i])); } /* Initialize the XSCOM regions for the PEC registers */ @@ -227,7 +198,7 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt, _FDT((fdt_setprop(fdt, offset, "compatible", pecc->compat, pecc->compat_size))); - for (i = 0; i < pec->num_stacks; i++) { + for (i = 0; i < pec->num_phbs; i++) { int phb_id = pnv_phb4_pec_get_phb_id(pec, i); int stk_offset; @@ -263,11 +234,11 @@ static uint32_t pnv_pec_xscom_nest_base(PnvPhb4PecState *pec) } /* - * PEC0 -> 1 stack - * PEC1 -> 2 stacks - * PEC2 -> 3 stacks + * PEC0 -> 1 phb + * PEC1 -> 2 phb + * PEC2 -> 3 phbs */ -static const uint32_t pnv_pec_num_stacks[] = { 1, 2, 3 }; +static const uint32_t pnv_pec_num_phbs[] = { 1, 2, 3 }; static void pnv_pec_class_init(ObjectClass *klass, void *data) { @@ -292,14 +263,13 @@ static void pnv_pec_class_init(ObjectClass *klass, void *data) pecc->stk_compat = stk_compat; pecc->stk_compat_size = sizeof(stk_compat); pecc->version = PNV_PHB4_VERSION; - pecc->num_stacks = pnv_pec_num_stacks; + pecc->num_phbs = pnv_pec_num_phbs; } static const TypeInfo pnv_pec_type_info = { .name = TYPE_PNV_PHB4_PEC, .parent = TYPE_DEVICE, .instance_size = sizeof(PnvPhb4PecState), - .instance_init = pnv_pec_instance_init, .class_init = pnv_pec_class_init, .class_size = sizeof(PnvPhb4PecClass), .interfaces = (InterfaceInfo[]) { diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 2be56b7afd..e750165e77 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -200,10 +200,8 @@ struct PnvPhb4PecState { uint64_t pci_regs[PHB4_PEC_PCI_REGS_COUNT]; MemoryRegion pci_regs_mr; - /* Stacks */ - #define PHB4_PEC_MAX_STACKS 3 - uint32_t num_stacks; - PnvPhb4PecStack stacks[PHB4_PEC_MAX_STACKS]; + /* PHBs */ + uint32_t num_phbs; PnvChip *chip; }; @@ -221,7 +219,7 @@ struct PnvPhb4PecClass { const char *stk_compat; int stk_compat_size; uint64_t version; - const uint32_t *num_stacks; + const uint32_t *num_phbs; }; #endif /* PCI_HOST_PNV_PHB4_H */ From 33fa43e0538d34b9fd3bcf63e150c14c68f74a8d Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 574/730] ppc/pnv: remove PnvPhb4PecStack object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the complexity that was scattered between PnvPhb4PecStack and PnvPHB4 are now centered in the PnvPHB4 device. PnvPhb4PecStack does not serve any purpose in the current code base. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220114180719.52117-8-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4_pec.c | 33 --------------------------------- include/hw/pci-host/pnv_phb4.h | 17 ----------------- 2 files changed, 50 deletions(-) diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 852816b9f8..12aa459628 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -278,42 +278,9 @@ static const TypeInfo pnv_pec_type_info = { } }; -static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) -{ -} - -static Property pnv_pec_stk_properties[] = { - DEFINE_PROP_LINK("pec", PnvPhb4PecStack, pec, TYPE_PNV_PHB4_PEC, - PnvPhb4PecState *), - DEFINE_PROP_END_OF_LIST(), -}; - -static void pnv_pec_stk_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - device_class_set_props(dc, pnv_pec_stk_properties); - dc->realize = pnv_pec_stk_realize; - dc->user_creatable = false; - - /* TODO: reset regs ? */ -} - -static const TypeInfo pnv_pec_stk_type_info = { - .name = TYPE_PNV_PHB4_PEC_STACK, - .parent = TYPE_DEVICE, - .instance_size = sizeof(PnvPhb4PecStack), - .class_init = pnv_pec_stk_class_init, - .interfaces = (InterfaceInfo[]) { - { TYPE_PNV_XSCOM_INTERFACE }, - { } - } -}; - static void pnv_pec_register_types(void) { type_register_static(&pnv_pec_type_info); - type_register_static(&pnv_pec_stk_type_info); } type_init(pnv_pec_register_types); diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index e750165e77..74fdec2b47 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -164,23 +164,6 @@ extern const MemoryRegionOps pnv_phb4_xscom_ops; #define TYPE_PNV_PHB4_PEC "pnv-phb4-pec" OBJECT_DECLARE_TYPE(PnvPhb4PecState, PnvPhb4PecClass, PNV_PHB4_PEC) -#define TYPE_PNV_PHB4_PEC_STACK "pnv-phb4-pec-stack" -OBJECT_DECLARE_SIMPLE_TYPE(PnvPhb4PecStack, PNV_PHB4_PEC_STACK) - -/* Per-stack data */ -struct PnvPhb4PecStack { - DeviceState parent; - - /* The owner PEC */ - PnvPhb4PecState *pec; - - /* - * PHB4 pointer. pnv_phb4_update_regions() needs to access - * the PHB4 via a PnvPhb4PecStack pointer. - */ - PnvPHB4 *phb; -}; - struct PnvPhb4PecState { DeviceState parent; From b4cda949b7adba4101ad313c34f9a2866d95e83f Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 575/730] ppc/pnv: rename pnv_pec_stk_update_map() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function does not use 'stack' anymore. Rename it to pnv_pec_phb_update_map(). Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220114180719.52117-9-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 3dc3c70cb2..1db815b1ab 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -914,7 +914,7 @@ static void pnv_phb4_update_regions(PnvPHB4 *phb) pnv_phb4_check_all_mbt(phb); } -static void pnv_pec_stk_update_map(PnvPHB4 *phb) +static void pnv_pec_phb_update_map(PnvPHB4 *phb) { PnvPhb4PecState *pec = phb->pec; MemoryRegion *sysmem = get_system_memory(); @@ -1066,7 +1066,7 @@ static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr, break; case PEC_NEST_STK_BAR_EN: phb->nest_regs[reg] = val & 0xf000000000000000ull; - pnv_pec_stk_update_map(phb); + pnv_pec_phb_update_map(phb); break; case PEC_NEST_STK_DATA_FRZ_TYPE: case PEC_NEST_STK_PBCQ_TUN_BAR: From 45d22dcf2d409b1a0d89f172ade65ee1f5519db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 576/730] ppc/pnv: Move root port allocation under pnv_pec_default_phb_realize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The root port device is currently created and attached to the PHB early in pnv_phb4_realize(). Do it under pnv_pec_default_phb_realize() after the PHB is fully realized. It's cleaner and avoids an extra test on defaults_enabled(). Signed-off-by: Cédric Le Goater Reviewed-by: Daniel Henrique Barboza Message-Id: <20220117122753.1655504-2-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 7 ------- hw/pci-host/pnv_phb4_pec.c | 3 +++ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 1db815b1ab..c688976cae 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -22,7 +22,6 @@ #include "hw/irq.h" #include "hw/qdev-properties.h" #include "qom/object.h" -#include "sysemu/sysemu.h" #include "trace.h" #define phb_error(phb, fmt, ...) \ @@ -1639,12 +1638,6 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb); pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; - /* Add a single Root port if running with defaults */ - if (defaults_enabled()) { - pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb), - TYPE_PNV_PHB4_ROOT_PORT); - } - /* Setup XIVE Source */ if (phb->big_phb) { nr_irqs = PNV_PHB4_MAX_INTs; diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 12aa459628..b19e89236a 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -132,6 +132,9 @@ static void pnv_pec_default_phb_realize(PnvPhb4PecState *pec, if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) { return; } + + /* Add a single Root port if running with defaults */ + pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb), TYPE_PNV_PHB4_ROOT_PORT); } static void pnv_pec_realize(DeviceState *dev, Error **errp) From 32a07887be0e4c51ae33e3efaf3368e916ca9af7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 577/730] ppc/pnv: Add a 'rp_model' class attribute for the PHB4 PEC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PHB5 will introduce its own root port model. Prepare ground for it. Signed-off-by: Cédric Le Goater Reviewed-by: Daniel Henrique Barboza Message-Id: <20220117122753.1655504-3-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4_pec.c | 5 ++++- include/hw/pci-host/pnv_phb4.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index b19e89236a..a3c4b4ef85 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -134,7 +134,9 @@ static void pnv_pec_default_phb_realize(PnvPhb4PecState *pec, } /* Add a single Root port if running with defaults */ - pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb), TYPE_PNV_PHB4_ROOT_PORT); + pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb), + PNV_PHB4_PEC_GET_CLASS(pec)->rp_model); + } static void pnv_pec_realize(DeviceState *dev, Error **errp) @@ -267,6 +269,7 @@ static void pnv_pec_class_init(ObjectClass *klass, void *data) pecc->stk_compat_size = sizeof(stk_compat); pecc->version = PNV_PHB4_VERSION; pecc->num_phbs = pnv_pec_num_phbs; + pecc->rp_model = TYPE_PNV_PHB4_ROOT_PORT; } static const TypeInfo pnv_pec_type_info = { diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 74fdec2b47..0c7635dec5 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -203,6 +203,7 @@ struct PnvPhb4PecClass { int stk_compat_size; uint64_t version; const uint32_t *num_phbs; + const char *rp_model; }; #endif /* PCI_HOST_PNV_PHB4_H */ From ba49190107ee9803fb2f336b15283b457384b178 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 18 Jan 2022 12:56:31 +0100 Subject: [PATCH 578/730] ppc/pnv: Remove PHB4 version property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Grab the PHB version from the PEC class directly when needed. Signed-off-by: Cédric Le Goater Reviewed-by: Daniel Henrique Barboza Message-Id: <20220117122753.1655504-4-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 9 +-------- hw/pci-host/pnv_phb4_pec.c | 3 --- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index c688976cae..a78add75b0 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -672,7 +672,7 @@ static uint64_t pnv_phb4_reg_read(void *opaque, hwaddr off, unsigned size) switch (off) { case PHB_VERSION: - return phb->version; + return PNV_PHB4_PEC_GET_CLASS(phb->pec)->version; /* Read-only */ case PHB_PHB4_GEN_CAP: @@ -1575,7 +1575,6 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) if (!phb->pec) { PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); PnvChip *chip = pnv_get_chip(pnv, phb->chip_id); - PnvPhb4PecClass *pecc; BusState *s; if (!chip) { @@ -1589,11 +1588,6 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) return; } - /* All other phb properties are already set */ - pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec); - object_property_set_int(OBJECT(phb), "version", pecc->version, - &error_fatal); - /* * Reparent user created devices to the chip to build * correctly the device tree. @@ -1688,7 +1682,6 @@ static void pnv_phb4_xive_notify(XiveNotifier *xf, uint32_t srcno) static Property pnv_phb4_properties[] = { DEFINE_PROP_UINT32("index", PnvPHB4, phb_id, 0), DEFINE_PROP_UINT32("chip-id", PnvPHB4, chip_id, 0), - DEFINE_PROP_UINT64("version", PnvPHB4, version, 0), DEFINE_PROP_LINK("pec", PnvPHB4, pec, TYPE_PNV_PHB4_PEC, PnvPhb4PecState *), DEFINE_PROP_END_OF_LIST(), diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index a3c4b4ef85..40d89fda56 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -117,7 +117,6 @@ static void pnv_pec_default_phb_realize(PnvPhb4PecState *pec, Error **errp) { PnvPHB4 *phb = PNV_PHB4(qdev_new(TYPE_PNV_PHB4)); - PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); int phb_id = pnv_phb4_pec_get_phb_id(pec, stack_no); object_property_set_link(OBJECT(phb), "pec", OBJECT(pec), @@ -126,8 +125,6 @@ static void pnv_pec_default_phb_realize(PnvPhb4PecState *pec, &error_fatal); object_property_set_int(OBJECT(phb), "index", phb_id, &error_fatal); - object_property_set_int(OBJECT(phb), "version", pecc->version, - &error_fatal); if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) { return; From b2173046a64beed76715f310f98538f159276af1 Mon Sep 17 00:00:00 2001 From: Marc Hartmayer Date: Mon, 22 Nov 2021 12:29:09 +0100 Subject: [PATCH 579/730] s390x/ipl: support extended kernel command line size In the past s390 used a fixed command line length of 896 bytes. This has changed with the Linux commit 5ecb2da660ab ("s390: support command lines longer than 896 bytes"). There is now a parm area indicating the maximum command line size. This parm area has always been initialized to zero, so with older kernels this field would read zero and we must then assume that only 896 bytes are available. Signed-off-by: Marc Hartmayer Reviewed-by: David Hildenbrand Reviewed-by: Christian Borntraeger Acked-by: Viktor Mihajlovski Message-Id: <20211122112909.18138-1-mhartmay@linux.ibm.com> [thuth: Cosmetic fixes, and use PRIu64 instead of %lu] Signed-off-by: Thomas Huth --- hw/s390x/ipl.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 7ddca0127f..eb7fc4c4ae 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -37,8 +37,9 @@ #define KERN_IMAGE_START 0x010000UL #define LINUX_MAGIC_ADDR 0x010008UL +#define KERN_PARM_AREA_SIZE_ADDR 0x010430UL #define KERN_PARM_AREA 0x010480UL -#define KERN_PARM_AREA_SIZE 0x000380UL +#define LEGACY_KERN_PARM_AREA_SIZE 0x000380UL #define INITRD_START 0x800000UL #define INITRD_PARM_START 0x010408UL #define PARMFILE_START 0x001000UL @@ -110,6 +111,21 @@ static uint64_t bios_translate_addr(void *opaque, uint64_t srcaddr) return srcaddr + dstaddr; } +static uint64_t get_max_kernel_cmdline_size(void) +{ + uint64_t *size_ptr = rom_ptr(KERN_PARM_AREA_SIZE_ADDR, sizeof(*size_ptr)); + + if (size_ptr) { + uint64_t size; + + size = be64_to_cpu(*size_ptr); + if (size) { + return size; + } + } + return LEGACY_KERN_PARM_AREA_SIZE; +} + static void s390_ipl_realize(DeviceState *dev, Error **errp) { MachineState *ms = MACHINE(qdev_get_machine()); @@ -197,10 +213,13 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) ipl->start_addr = KERN_IMAGE_START; /* Overwrite parameters in the kernel image, which are "rom" */ if (parm_area) { - if (cmdline_size > KERN_PARM_AREA_SIZE) { + uint64_t max_cmdline_size = get_max_kernel_cmdline_size(); + + if (cmdline_size > max_cmdline_size) { error_setg(errp, - "kernel command line exceeds maximum size: %zu > %lu", - cmdline_size, KERN_PARM_AREA_SIZE); + "kernel command line exceeds maximum size:" + " %zu > %" PRIu64, + cmdline_size, max_cmdline_size); return; } From 59b9b5186e44a90088a91ed7a7493b03027e4f1f Mon Sep 17 00:00:00 2001 From: Eric Farman Date: Mon, 13 Dec 2021 22:09:19 +0100 Subject: [PATCH 580/730] s390x: sigp: Reorder the SIGP STOP code Let's wait to mark the VCPU STOPPED until the possible STORE STATUS operation is completed, so that we know the CPU is fully stopped and done doing anything. (When we also clear the possible sigp_order field for STOP orders.) Suggested-by: David Hildenbrand Signed-off-by: Eric Farman Message-Id: <20211213210919.856693-2-farman@linux.ibm.com> Reviewed-by: David Hildenbrand Signed-off-by: Thomas Huth --- target/s390x/sigp.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c index 51c727834c..9dd977349a 100644 --- a/target/s390x/sigp.c +++ b/target/s390x/sigp.c @@ -139,7 +139,7 @@ static void sigp_stop_and_store_status(CPUState *cs, run_on_cpu_data arg) case S390_CPU_STATE_OPERATING: cpu->env.sigp_order = SIGP_STOP_STORE_STATUS; cpu_inject_stop(cpu); - /* store will be performed in do_stop_interrup() */ + /* store will be performed in do_stop_interrupt() */ break; case S390_CPU_STATE_STOPPED: /* already stopped, just store the status */ @@ -479,13 +479,17 @@ void do_stop_interrupt(CPUS390XState *env) { S390CPU *cpu = env_archcpu(env); - if (s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu) == 0) { - qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); - } + /* + * Complete the STOP operation before exposing the CPU as + * STOPPED to the system. + */ if (cpu->env.sigp_order == SIGP_STOP_STORE_STATUS) { s390_store_status(cpu, S390_STORE_STATUS_DEF_ADDR, true); } env->sigp_order = 0; + if (s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu) == 0) { + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + } env->pending_int &= ~INTERRUPT_STOP; } From 70a54b01693eda3c61814b05d699aba41015ac48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:36 +0000 Subject: [PATCH 581/730] ui: avoid compiler warnings from unused clipboard info variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With latest clang 13.0.0 we get ../ui/clipboard.c:47:34: error: variable 'old' set but not used [-Werror,-Wunused-but-set-variable] g_autoptr(QemuClipboardInfo) old = NULL; ^ The compiler can't tell that we only declared this variable in order to get the side effect of free'ing it when out of scope. This pattern is a little dubious for a use of g_autoptr, so rewrite the code to avoid it. Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé [AJB: fix merge conflict] Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-2-berrange@redhat.com> Message-Id: <20220105135009.1584676-2-alex.bennee@linaro.org> --- ui/clipboard.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/clipboard.c b/ui/clipboard.c index 82572ea116..5f15cf853d 100644 --- a/ui/clipboard.c +++ b/ui/clipboard.c @@ -62,13 +62,11 @@ void qemu_clipboard_update(QemuClipboardInfo *info) .type = QEMU_CLIPBOARD_UPDATE_INFO, .info = info, }; - g_autoptr(QemuClipboardInfo) old = NULL; - assert(info->selection < QEMU_CLIPBOARD_SELECTION__COUNT); notifier_list_notify(&clipboard_notifiers, ¬ify); - old = cbinfo[info->selection]; + qemu_clipboard_info_unref(cbinfo[info->selection]); cbinfo[info->selection] = qemu_clipboard_info_ref(info); } From 9dcafa400e57d75f77c67151ff57508065651dd8 Mon Sep 17 00:00:00 2001 From: John Snow Date: Wed, 5 Jan 2022 13:49:37 +0000 Subject: [PATCH 582/730] spice: Update QXLInterface for spice >= 0.15.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit spice updated the spelling (and arguments) of "attache_worker" in 0.15.0. Update QEMU to match, preventing -Wdeprecated-declarations compilations from reporting build errors. See also: https://gitlab.freedesktop.org/spice/spice/-/commit/974692bda1e77af92b71ed43b022439448492cb9 Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Signed-off-by: John Snow Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-3-berrange@redhat.com> Message-Id: <20220105135009.1584676-3-alex.bennee@linaro.org> --- hw/display/qxl.c | 14 +++++++++++++- include/ui/qemu-spice.h | 6 ++++++ ui/spice-display.c | 11 +++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/hw/display/qxl.c b/hw/display/qxl.c index e2d6e317da..1f9ad31943 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -517,13 +517,20 @@ static int qxl_track_command(PCIQXLDevice *qxl, struct QXLCommandExt *ext) /* spice display interface callbacks */ -static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker) +static void interface_attached_worker(QXLInstance *sin) { PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); trace_qxl_interface_attach_worker(qxl->id); } +#if !(SPICE_HAS_ATTACHED_WORKER) +static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker) +{ + interface_attached_worker(sin); +} +#endif + static void interface_set_compression_level(QXLInstance *sin, int level) { PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl); @@ -1131,7 +1138,12 @@ static const QXLInterface qxl_interface = { .base.major_version = SPICE_INTERFACE_QXL_MAJOR, .base.minor_version = SPICE_INTERFACE_QXL_MINOR, +#if SPICE_HAS_ATTACHED_WORKER + .attached_worker = interface_attached_worker, +#else .attache_worker = interface_attach_worker, +#endif + .set_compression_level = interface_set_compression_level, #if SPICE_NEEDS_SET_MM_TIME .set_mm_time = interface_set_mm_time, diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h index 71ecd6cfd1..21fe195e18 100644 --- a/include/ui/qemu-spice.h +++ b/include/ui/qemu-spice.h @@ -40,6 +40,12 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port, #define SPICE_NEEDS_SET_MM_TIME 0 #endif +#if defined(SPICE_SERVER_VERSION) && (SPICE_SERVER_VERSION >= 0x000f00) +#define SPICE_HAS_ATTACHED_WORKER 1 +#else +#define SPICE_HAS_ATTACHED_WORKER 0 +#endif + #else /* CONFIG_SPICE */ #include "qemu/error-report.h" diff --git a/ui/spice-display.c b/ui/spice-display.c index 1043f47f94..a3078adf91 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -500,10 +500,17 @@ void qemu_spice_display_refresh(SimpleSpiceDisplay *ssd) /* spice display interface callbacks */ +#if SPICE_HAS_ATTACHED_WORKER +static void interface_attached_worker(QXLInstance *sin) +{ + /* nothing to do */ +} +#else static void interface_attach_worker(QXLInstance *sin, QXLWorker *qxl_worker) { /* nothing to do */ } +#endif static void interface_set_compression_level(QXLInstance *sin, int level) { @@ -702,7 +709,11 @@ static const QXLInterface dpy_interface = { .base.major_version = SPICE_INTERFACE_QXL_MAJOR, .base.minor_version = SPICE_INTERFACE_QXL_MINOR, +#if SPICE_HAS_ATTACHED_WORKER + .attached_worker = interface_attached_worker, +#else .attache_worker = interface_attach_worker, +#endif .set_compression_level = interface_set_compression_level, #if SPICE_NEEDS_SET_MM_TIME .set_mm_time = interface_set_mm_time, From a41b4fdc445f1aad5f8bdbb36b351415647f91fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:38 +0000 Subject: [PATCH 583/730] meson: require liburing >= 0.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit openSUSE Leap 15.2 ships with liburing == 0.2 against which QEMU fails to build. ../util/fdmon-io_uring.c: In function ‘fdmon_io_uring_need_wait’: ../util/fdmon-io_uring.c:305:9: error: implicit declaration of function ‘io_uring_sq_ready’; did you mean ‘io_uring_cq_ready’? [-Werror=implicit-function-declaration] if (io_uring_sq_ready(&ctx->fdmon_io_uring)) { ^~~~~~~~~~~~~~~~~ io_uring_cq_ready This method was introduced in liburing 0.3, so set that as a minimum requirement. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-4-berrange@redhat.com> Message-Id: <20220105135009.1584676-4-alex.bennee@linaro.org> --- meson.build | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 762d7cee85..333c61deba 100644 --- a/meson.build +++ b/meson.build @@ -445,7 +445,8 @@ if not get_option('linux_aio').auto() or have_block endif linux_io_uring = not_found if not get_option('linux_io_uring').auto() or have_block - linux_io_uring = dependency('liburing', required: get_option('linux_io_uring'), + linux_io_uring = dependency('liburing', version: '>=0.3', + required: get_option('linux_io_uring'), method: 'pkg-config', kwargs: static_kwargs) endif libxml2 = not_found From 021e3fa33b57612fd0e1a6b7ced23d3480cfbdca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:39 +0000 Subject: [PATCH 584/730] ui: avoid warnings about directdb on Alpine / musl libc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Alpine, SDL is built with directfb support and this triggers warnings during QEMU build In file included from /usr/include/directfb/direct/thread.h:38, from /usr/include/directfb/direct/debug.h:43, from /usr/include/directfb/direct/interface.h:36, from /usr/include/directfb/directfb.h:49, from /usr/include/SDL2/SDL_syswm.h:80, from /builds/berrange/qemu/include/ui/sdl2.h:8, from ../ui/sdl2-gl.c:31: /usr/include/directfb/direct/os/waitqueue.h:41:25: error: redundant redeclaration of 'direct_waitqueue_init' [-Werror=redundant-decls] 41 | DirectResult DIRECT_API direct_waitqueue_init ( DirectWaitQueue *queue ); | ^~~~~~~~~~~~~~~~~~~~~ Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-5-berrange@redhat.com> Message-Id: <20220105135009.1584676-5-alex.bennee@linaro.org> --- include/ui/sdl2.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h index 71bcf7ebda..8fb7e08262 100644 --- a/include/ui/sdl2.h +++ b/include/ui/sdl2.h @@ -5,7 +5,18 @@ #undef WIN32_LEAN_AND_MEAN #include + +/* with Alpine / muslc SDL headers pull in directfb headers + * which in turn trigger warning about redundant decls for + * direct_waitqueue_deinit. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" + #include + +#pragma GCC diagnostic pop + #ifdef CONFIG_SDL_IMAGE # include #endif From f178c62afc9cb1c6ef25601c584006e21149036e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:40 +0000 Subject: [PATCH 585/730] ci: explicitly skip I/O tests on alpine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The block I/O tests don't work on Alpine because their alternative libc impl emits different strings for errnos, which breaks the expected output matching. e.g. === IO: pattern 102 wrote 512/512 bytes at offset 512 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) -qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error +qemu-img: Error while reading offset 0 of blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: I/O error 4 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 Formatting 'TEST_DIR/t.IMGFMT.2', fmt=IMGFMT size=0 Currently the I/O tests are skipped as a side effect of the Alpine image containing a minimal busybox 'sed' binary, rather than GNU sed. This is a fragile assumption that will be invalidated when the dockerfile is changed to be autogenerated from a standardized package list that includes GNU sed. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-6-berrange@redhat.com> Reviewed-by: Thomas Huth Message-Id: <20220105135009.1584676-6-alex.bennee@linaro.org> --- .gitlab-ci.d/buildtest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index 12fb1130fe..8f2a3c8f5b 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -24,7 +24,7 @@ check-system-alpine: artifacts: true variables: IMAGE: alpine - MAKE_CHECK_ARGS: check + MAKE_CHECK_ARGS: check-unit check-qtest avocado-system-alpine: extends: .avocado_test_job_template From 3f4a7a7cfb8216d0435de3e7d6d2a5a18b46f7bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:41 +0000 Subject: [PATCH 586/730] tests/docker: switch fedora image to release 35 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Fedora 33 release is shortly end of life. Switch to the newest Fedora 35 to maximise lifespan until we need to update again. Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-7-berrange@redhat.com> Message-Id: <20220105135009.1584676-7-alex.bennee@linaro.org> --- tests/docker/dockerfiles/fedora.docker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker index c6fd7e1113..855aefaac5 100644 --- a/tests/docker/dockerfiles/fedora.docker +++ b/tests/docker/dockerfiles/fedora.docker @@ -1,4 +1,4 @@ -FROM registry.fedoraproject.org/fedora:33 +FROM registry.fedoraproject.org/fedora:35 # Please keep this list sorted alphabetically ENV PACKAGES \ From 4ebb040f1fd6985df191b63321493d1b6fb504f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:42 +0000 Subject: [PATCH 587/730] tests: integrate lcitool for generating build env manifests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This introduces https://gitlab.com/libvirt/libvirt-ci as a git submodule at tests/lcitool/libvirt-ci The 'lcitool' program within this submodule will be used to automatically generate build environment manifests from a definition of requirements in tests/lcitool/projects/qemu.yml It will ultimately be capable of generating - Dockerfiles - Package lists for installation in VMs - Variables for configuring Cirrus CI environments When a new build pre-requisite is needed for QEMU, if this package is not currently known to libvirt-ci, it must first be added to the 'mappings.yml' file in the above git repo. Then the submodule can be updated and the build pre-requisite added to the tests/lcitool/projects/qemu.yml file. Now all the build env manifests can be re-generated using 'make lcitool-refresh' This ensures that when a new build pre-requisite is introduced, it is added to all the different OS containers, VMs and Cirrus CI environments consistently. It also facilitates the addition of containers targetting new distros or updating existing containers to new versions of the same distro, where packages might have been renamed. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-8-berrange@redhat.com> Message-Id: <20220105135009.1584676-8-alex.bennee@linaro.org> --- .gitmodules | 3 + Makefile | 2 + docs/devel/testing.rst | 104 ++++++++++++++++++++++++++++- tests/lcitool/Makefile.include | 17 +++++ tests/lcitool/libvirt-ci | 1 + tests/lcitool/projects/qemu.yml | 115 ++++++++++++++++++++++++++++++++ tests/lcitool/refresh | 67 +++++++++++++++++++ 7 files changed, 306 insertions(+), 3 deletions(-) create mode 100644 tests/lcitool/Makefile.include create mode 160000 tests/lcitool/libvirt-ci create mode 100644 tests/lcitool/projects/qemu.yml create mode 100755 tests/lcitool/refresh diff --git a/.gitmodules b/.gitmodules index 08b1b48a09..84425d87e2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -64,3 +64,6 @@ [submodule "roms/vbootrom"] path = roms/vbootrom url = https://gitlab.com/qemu-project/vbootrom.git +[submodule "tests/lcitool/libvirt-ci"] + path = tests/lcitool/libvirt-ci + url = http://gitlab.com/libvirt/libvirt-ci diff --git a/Makefile b/Makefile index 9e2e3bf004..db9a788601 100644 --- a/Makefile +++ b/Makefile @@ -285,6 +285,7 @@ cscope: # Needed by "meson install" export DESTDIR +include $(SRC_PATH)/tests/lcitool/Makefile.include include $(SRC_PATH)/tests/docker/Makefile.include include $(SRC_PATH)/tests/vm/Makefile.include @@ -314,6 +315,7 @@ endif @echo 'Test targets:' $(call print-help,check,Run all tests (check-help for details)) $(call print-help,bench,Run all benchmarks) + $(call print-help,lcitool-help,Help about targets for managing build environment manifests) $(call print-help,docker-help,Help about targets running tests inside containers) $(call print-help,vm-help,Help about targets running tests inside VM) @echo '' diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index 755343c7dd..d744b5909c 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -382,14 +382,112 @@ Along with many other images, the ``centos8`` image is defined in a Dockerfile in ``tests/docker/dockerfiles/``, called ``centos8.docker``. ``make docker-help`` command will list all the available images. -To add a new image, simply create a new ``.docker`` file under the -``tests/docker/dockerfiles/`` directory. - A ``.pre`` script can be added beside the ``.docker`` file, which will be executed before building the image under the build context directory. This is mainly used to do necessary host side setup. One such setup is ``binfmt_misc``, for example, to make qemu-user powered cross build containers work. +Most of the existing Dockerfiles were written by hand, simply by creating a +a new ``.docker`` file under the ``tests/docker/dockerfiles/`` directory. +This has led to an inconsistent set of packages being present across the +different containers. + +Thus going forward, QEMU is aiming to automatically generate the Dockerfiles +using the ``lcitool`` program provided by the ``libvirt-ci`` project: + + https://gitlab.com/libvirt/libvirt-ci + +In that project, there is a ``mappings.yml`` file defining the distro native +package names for a wide variety of third party projects. This is processed +in combination with a project defined list of build pre-requisites to determine +the list of native packages to install on each distribution. This can be used +to generate dockerfiles, VM package lists and Cirrus CI variables needed to +setup build environments across OS distributions with a consistent set of +packages present. + +When preparing a patch series that adds a new build pre-requisite to QEMU, +updates to various lcitool data files may be required. + + +Adding new build pre-requisites +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the simple case where the pre-requisite is already known to ``libvirt-ci`` +the following steps are needed + + * Edit ``tests/lcitool/projects/qemu.yml`` and add the pre-requisite + + * Run ``make lcitool-refresh`` to re-generate all relevant build environment + manifests + +In some cases ``libvirt-ci`` will not know about the build pre-requisite and +thus some extra preparation steps will be required first + + * Fork the ``libvirt-ci`` project on gitlab + + * Edit the ``mappings.yml`` change to add an entry for the new build + prerequisite, listing its native package name on as many OS distros + as practical. + + * Commit the ``mappings.yml`` change and submit a merge request to + the ``libvirt-ci`` project, noting in the description that this + is a new build pre-requisite desired for use with QEMU + + * CI pipeline will run to validate that the changes to ``mappings.yml`` + are correct, by attempting to install the newly listed package on + all OS distributions supported by ``libvirt-ci``. + + * Once the merge request is accepted, go back to QEMU and update + the ``libvirt-ci`` submodule to point to a commit that contains + the ``mappings.yml`` update. + + +Adding new OS distros +^^^^^^^^^^^^^^^^^^^^^ + +In some cases ``libvirt-ci`` will not know about the OS distro that is +desired to be tested. Before adding a new OS distro, discuss the proposed +addition: + + * Send a mail to qemu-devel, copying people listed in the + MAINTAINERS file for ``Build and test automation``. + + There are limited CI compute resources available to QEMU, so the + cost/benefit tradeoff of adding new OS distros needs to be considered. + + * File an issue at https://gitlab.com/libvirt/libvirt-ci/-/issues + pointing to the qemu-devel mail thread in the archives. + + This alerts other people who might be interested in the work + to avoid duplication, as well as to get feedback from libvirt-ci + maintainers on any tips to ease the addition + +Assuming there is agreement to add a new OS distro then + + * Fork the ``libvirt-ci`` project on gitlab + + * Add metadata under ``guests/lcitool/lcitool/ansible/group_vars/`` + for the new OS distro. There might be code changes required if + the OS distro uses a package format not currently known. The + ``libvirt-ci`` maintainers can advise on this when the issue + is file. + + * Edit the ``mappings.yml`` change to update all the existing package + entries, providing details of the new OS distro + + * Commit the ``mappings.yml`` change and submit a merge request to + the ``libvirt-ci`` project, noting in the description that this + is a new build pre-requisite desired for use with QEMU + + * CI pipeline will run to validate that the changes to ``mappings.yml`` + are correct, by attempting to install the newly listed package on + all OS distributions supported by ``libvirt-ci``. + + * Once the merge request is accepted, go back to QEMU and update + the ``libvirt-ci`` submodule to point to a commit that contains + the ``mappings.yml`` update. + + Tests ~~~~~ diff --git a/tests/lcitool/Makefile.include b/tests/lcitool/Makefile.include new file mode 100644 index 0000000000..cff7c0b814 --- /dev/null +++ b/tests/lcitool/Makefile.include @@ -0,0 +1,17 @@ + +LCITOOL_REFRESH = $(SRC_PATH)/tests/lcitool/refresh + +lcitool: + @echo 'Manage build environment manifests' + @echo + @echo 'Available targets:' + @echo + @echo ' lcitool: Print this help.' + @echo ' lcitool-refresh: Re-generate all build environment manifests.' + @echo + +lcitool-help: lcitool + +lcitool-refresh: + $(call quiet-command, git submodule update --init $(SRC_PATH)/tests/lcitool/libvirt-ci) + $(call quiet-command, $(LCITOOL_REFRESH)) diff --git a/tests/lcitool/libvirt-ci b/tests/lcitool/libvirt-ci new file mode 160000 index 0000000000..29cec2153b --- /dev/null +++ b/tests/lcitool/libvirt-ci @@ -0,0 +1 @@ +Subproject commit 29cec2153b9a4dbb2e66f1cbc9866a4eff519cfd diff --git a/tests/lcitool/projects/qemu.yml b/tests/lcitool/projects/qemu.yml new file mode 100644 index 0000000000..2e2271510e --- /dev/null +++ b/tests/lcitool/projects/qemu.yml @@ -0,0 +1,115 @@ +--- +packages: + - alsa + - bash + - bc + - brlapi + - bzip2 + - bzip2-libs + - capstone + - ccache + - clang + - column + - ctags + - cyrus-sasl + - daxctl + - dbus-daemon + - device-mapper-multipath + - diffutils + - dtrace + - findutils + - g++ + - gcc + - gcovr + - gettext + - genisoimage + - glib2 + - glib2-static + - glibc-static + - glusterfs + - gnutls + - gtk3 + - hostname + - libaio + - libattr + - libasan + - libbpf + - libcacard + - libcap-ng + - libcurl + - libdrm + - libepoxy + - libfdt + - libffi + - libgcrypt + - libibverbs + - libiscsi + - libjemalloc + - libjpeg + - libnfs + - libnuma + - libpmem + - libpng + - librbd + - librdmacm + - libseccomp + - libselinux + - libslirp + - libssh + - libtasn1 + - libubsan + - libudev + - liburing + - libusbx + - libvdeplug + - libxml2 + - libzstd + - llvm + - lttng-ust + - lzo + - netcat + - nettle + - ninja + - nsis + - make + - mesa-libgbm + - meson + - ncursesw + - pam + - pcre-static + - perl + - perl-Test-Harness + - pixman + - pkg-config + - pulseaudio + - python3 + - python3-PyYAML + - python3-numpy + - python3-opencv + - python3-pillow + - python3-pip + - python3-sphinx + - python3-sphinx-rtd-theme + - python3-virtualenv + - rpm2cpio + - sdl2 + - sdl2-image + - sed + - snappy + - sparse + - spice-protocol + - spice-server + - ssh-client + - systemd + - tar + - tesseract + - tesseract-eng + - texinfo + - usbredir + - virglrenderer + - vte + - which + - xen + - xfsprogs + - zlib + - zlib-static diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh new file mode 100755 index 0000000000..b47e25f64b --- /dev/null +++ b/tests/lcitool/refresh @@ -0,0 +1,67 @@ +#!/usr/bin/python3 +# +# Re-generate container recipes +# +# This script uses the "lcitool" available from +# +# https://gitlab.com/libvirt/libvirt-ci +# +# Copyright (c) 2020 Red Hat Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 +# or (at your option) any later version. See the COPYING file in +# the top-level directory. + +import sys +import os +import subprocess + +from pathlib import Path + +if len(sys.argv) != 1: + print("syntax: %s" % sys.argv[0], file=sys.stderr) + sys.exit(1) + +self_dir = Path(__file__).parent +src_dir = self_dir.parent.parent +dockerfiles_dir = Path(src_dir, "tests", "docker", "dockerfiles") + +lcitool_path = Path(self_dir, "libvirt-ci", "lcitool") + +lcitool_cmd = [lcitool_path, "--data-dir", self_dir] + +def atomic_write(filename, content): + tmp = filename.with_suffix(filename.suffix + ".tmp") + try: + with tmp.open("w") as fp: + print(content, file=fp, end="") + tmp.rename(filename) + except Exception as ex: + tmp.unlink() + raise + +def generate(filename, cmd, trailer): + print("Generate %s" % filename) + lcitool=subprocess.run(cmd, capture_output=True) + + if lcitool.returncode != 0: + raise Exception("Failed to generate %s: %s" % (filename, lcitool.stderr)) + + content = lcitool.stdout.decode("utf8") + if trailer is not None: + content += trailer + atomic_write(filename, content) + +def generate_dockerfile(host, target, cross=None, trailer=None): + filename = Path(src_dir, "tests", "docker", "dockerfiles", host + ".docker") + cmd = lcitool_cmd + ["dockerfile"] + if cross is not None: + cmd.extend(["--cross", cross]) + cmd.extend([target, "qemu"]) + generate(filename, cmd, trailer) + +try: + sys.exit(0) +except Exception as ex: + print(str(ex), file=sys.stderr) + sys.exit(1) From 21ea888fc2bb3bdbd79fd122a201348f1738982c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:43 +0000 Subject: [PATCH 588/730] tests/docker: auto-generate centos8.docker with lcitool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is best examined using the "-b" option to diff. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-9-berrange@redhat.com> Message-Id: <20220105135009.1584676-9-alex.bennee@linaro.org> --- tests/docker/dockerfiles/centos8.docker | 243 +++++++++++++----------- tests/lcitool/refresh | 2 + 2 files changed, 135 insertions(+), 110 deletions(-) diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker index 7f135f8e8c..3c62b62a99 100644 --- a/tests/docker/dockerfiles/centos8.docker +++ b/tests/docker/dockerfiles/centos8.docker @@ -1,112 +1,135 @@ -FROM docker.io/centos:8 +# THIS FILE WAS AUTO-GENERATED +# +# $ lcitool dockerfile centos-8 qemu +# +# https://gitlab.com/libvirt/libvirt-ci -RUN dnf -y update -ENV PACKAGES \ - SDL2-devel \ - alsa-lib-devel \ - bc \ - brlapi-devel \ - bzip2 \ - bzip2-devel \ - ca-certificates \ - capstone-devel \ - ccache \ - clang \ - ctags \ - cyrus-sasl-devel \ - daxctl-devel \ - dbus-daemon \ - device-mapper-multipath-devel \ - diffutils \ - findutils \ - gcc \ - gcc-c++ \ - genisoimage \ - gettext \ - git \ - glib2-devel \ - glibc-langpack-en \ - glibc-static \ - glusterfs-api-devel \ - gnutls-devel \ - gtk3-devel \ - hostname \ - jemalloc-devel \ - libaio-devel \ - libasan \ - libattr-devel \ - libbpf-devel \ - libcacard-devel \ - libcap-ng-devel \ - libcurl-devel \ - libdrm-devel \ - libepoxy-devel \ - libfdt-devel \ - libffi-devel \ - libgcrypt-devel \ - libiscsi-devel \ - libjpeg-devel \ - libnfs-devel \ - libpmem-devel \ - libpng-devel \ - librbd-devel \ - libseccomp-devel \ - libselinux-devel \ - libslirp-devel \ - libssh-devel \ - libtasn1-devel \ - libubsan \ - libudev-devel \ - libusbx-devel \ - libxml2-devel \ - libzstd-devel \ - llvm \ - lzo-devel \ - make \ - mesa-libgbm-devel \ - ncurses-devel \ - nettle-devel \ - ninja-build \ - nmap-ncat \ - numactl-devel \ - openssh-clients \ - pam-devel \ - perl \ - perl-Test-Harness \ - pixman-devel \ - pkgconfig \ - pulseaudio-libs-devel \ - python3 \ - python3-PyYAML \ - python3-numpy \ - python3-pillow \ - python3-pip \ - python3-setuptools \ - python3-sphinx \ - python3-sphinx_rtd_theme \ - python3-virtualenv \ - python3-wheel \ - rdma-core-devel \ - rpm \ - sed \ - snappy-devel \ - spice-protocol \ - spice-server-devel \ - systemd-devel \ - systemtap-sdt-devel \ - tar \ - texinfo \ - usbredir-devel \ - util-linux \ - virglrenderer-devel \ - vte291-devel \ - which \ - xfsprogs-devel \ - zlib-devel +FROM docker.io/library/centos:8 -RUN dnf install -y dnf-plugins-core && \ - dnf config-manager --set-enabled powertools && \ - dnf install -y centos-release-advanced-virtualization && \ - dnf install -y epel-release && \ - dnf install -y $PACKAGES -RUN rpm -q $PACKAGES | sort > /packages.txt +RUN dnf update -y && \ + dnf install 'dnf-command(config-manager)' -y && \ + dnf config-manager --set-enabled -y powertools && \ + dnf install -y centos-release-advanced-virtualization && \ + dnf install -y epel-release && \ + dnf install -y \ + SDL2-devel \ + alsa-lib-devel \ + bash \ + bc \ + brlapi-devel \ + bzip2 \ + bzip2-devel \ + ca-certificates \ + capstone-devel \ + ccache \ + clang \ + ctags \ + cyrus-sasl-devel \ + daxctl-devel \ + dbus-daemon \ + device-mapper-multipath-devel \ + diffutils \ + findutils \ + gcc \ + gcc-c++ \ + genisoimage \ + gettext \ + git \ + glib2-devel \ + glib2-static \ + glibc-langpack-en \ + glibc-static \ + glusterfs-api-devel \ + gnutls-devel \ + gtk3-devel \ + hostname \ + jemalloc-devel \ + libaio-devel \ + libasan \ + libattr-devel \ + libbpf-devel \ + libcacard-devel \ + libcap-ng-devel \ + libcurl-devel \ + libdrm-devel \ + libepoxy-devel \ + libfdt-devel \ + libffi-devel \ + libgcrypt-devel \ + libiscsi-devel \ + libjpeg-devel \ + libnfs-devel \ + libpmem-devel \ + libpng-devel \ + librbd-devel \ + libseccomp-devel \ + libselinux-devel \ + libslirp-devel \ + libssh-devel \ + libtasn1-devel \ + libubsan \ + libudev-devel \ + liburing-devel \ + libusbx-devel \ + libxml2-devel \ + libzstd-devel \ + llvm \ + lttng-ust-devel \ + lzo-devel \ + make \ + mesa-libgbm-devel \ + meson \ + ncurses-devel \ + nettle-devel \ + ninja-build \ + nmap-ncat \ + numactl-devel \ + openssh-clients \ + pam-devel \ + pcre-static \ + perl \ + perl-Test-Harness \ + pixman-devel \ + pkgconfig \ + pulseaudio-libs-devel \ + python3 \ + python3-PyYAML \ + python3-numpy \ + python3-pillow \ + python3-pip \ + python3-sphinx \ + python3-sphinx_rtd_theme \ + python3-virtualenv \ + rdma-core-devel \ + rpm \ + sed \ + snappy-devel \ + spice-protocol \ + spice-server-devel \ + systemd-devel \ + systemtap-sdt-devel \ + tar \ + texinfo \ + usbredir-devel \ + util-linux \ + virglrenderer-devel \ + vte291-devel \ + which \ + xfsprogs-devel \ + zlib-devel \ + zlib-static && \ + dnf autoremove -y && \ + dnf clean all -y && \ + rpm -qa | sort > /packages.txt && \ + mkdir -p /usr/libexec/ccache-wrappers && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/cc && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/clang && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc + +ENV LANG "en_US.UTF-8" +ENV MAKE "/usr/bin/make" +ENV NINJA "/usr/bin/ninja" +ENV PYTHON "/usr/bin/python3" +ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers" diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh index b47e25f64b..824b1c0ef2 100755 --- a/tests/lcitool/refresh +++ b/tests/lcitool/refresh @@ -61,6 +61,8 @@ def generate_dockerfile(host, target, cross=None, trailer=None): generate(filename, cmd, trailer) try: + generate_dockerfile("centos8", "centos-8") + sys.exit(0) except Exception as ex: print(str(ex), file=sys.stderr) From 05e47b75cb0310210321028eee98116a0006f93e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:44 +0000 Subject: [PATCH 589/730] tests/docker: auto-generate fedora.docker with lcitool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is best examined using the "-b" option to diff. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-10-berrange@redhat.com> Message-Id: <20220105135009.1584676-10-alex.bennee@linaro.org> --- tests/docker/dockerfiles/fedora.docker | 260 ++++++++++++++----------- tests/lcitool/refresh | 1 + 2 files changed, 146 insertions(+), 115 deletions(-) diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker index 855aefaac5..6784878b56 100644 --- a/tests/docker/dockerfiles/fedora.docker +++ b/tests/docker/dockerfiles/fedora.docker @@ -1,118 +1,148 @@ +# THIS FILE WAS AUTO-GENERATED +# +# $ lcitool dockerfile fedora-35 qemu +# +# https://gitlab.com/libvirt/libvirt-ci + FROM registry.fedoraproject.org/fedora:35 -# Please keep this list sorted alphabetically -ENV PACKAGES \ - SDL2-devel \ - SDL2_image-devel \ - alsa-lib-devel \ - bc \ - brlapi-devel \ - bzip2 \ - bzip2-devel \ - ca-certificates \ - capstone-devel \ - ccache \ - clang \ - ctags \ - cyrus-sasl-devel \ - daxctl-devel \ - dbus-daemon \ - device-mapper-multipath-devel \ - diffutils \ - findutils \ - gcc \ - gcc-c++ \ - gcovr \ - genisoimage \ - gettext \ - git \ - glib2-devel \ - glibc-langpack-en \ - glibc-static \ - glusterfs-api-devel \ - gnutls-devel \ - gtk3-devel \ - hostname \ - jemalloc-devel \ - libaio-devel \ - libasan \ - libattr-devel \ - libbpf-devel \ - libcacard-devel \ - libcap-ng-devel \ - libcurl-devel \ - libdrm-devel \ - libepoxy-devel \ - libfdt-devel \ - libffi-devel \ - libgcrypt-devel \ - libiscsi-devel \ - libjpeg-devel \ - libnfs-devel \ - libpmem-devel \ - libpng-devel \ - librbd-devel \ - libseccomp-devel \ - libselinux-devel \ - libslirp-devel \ - libssh-devel \ - libtasn1-devel \ - libubsan \ - libudev-devel \ - liburing-devel \ - libusbx-devel \ - libxml2-devel \ - libzstd-devel \ - llvm \ - lttng-ust-devel \ - lzo-devel \ - make \ - mesa-libgbm-devel \ - meson \ - ncurses-devel \ - nettle-devel \ - ninja-build \ - nmap-ncat \ - numactl-devel \ - openssh-clients \ - pam-devel \ - perl-Test-Harness \ - perl-base \ - pixman-devel \ - pkgconfig \ - pulseaudio-libs-devel \ - python3 \ - python3-PyYAML \ - python3-numpy \ - python3-opencv \ - python3-pillow \ - python3-pip \ - python3-sphinx \ - python3-sphinx_rtd_theme \ - python3-virtualenv \ - rdma-core-devel \ - rpm \ - sed \ - snappy-devel \ - sparse \ - spice-protocol \ - spice-server-devel \ - systemd-devel \ - systemtap-sdt-devel \ - tar \ - tesseract \ - tesseract-langpack-eng \ - texinfo \ - usbredir-devel \ - util-linux \ - virglrenderer-devel \ - vte291-devel \ - which \ - xen-devel \ - xfsprogs-devel \ - zlib-devel -ENV QEMU_CONFIGURE_OPTS --python=/usr/bin/python3 +RUN dnf install -y nosync && \ + echo -e '#!/bin/sh\n\ +if test -d /usr/lib64\n\ +then\n\ + export LD_PRELOAD=/usr/lib64/nosync/nosync.so\n\ +else\n\ + export LD_PRELOAD=/usr/lib/nosync/nosync.so\n\ +fi\n\ +exec "$@"' > /usr/bin/nosync && \ + chmod +x /usr/bin/nosync && \ + nosync dnf update -y && \ + nosync dnf install -y \ + SDL2-devel \ + SDL2_image-devel \ + alsa-lib-devel \ + bash \ + bc \ + brlapi-devel \ + bzip2 \ + bzip2-devel \ + ca-certificates \ + capstone-devel \ + ccache \ + clang \ + ctags \ + cyrus-sasl-devel \ + daxctl-devel \ + dbus-daemon \ + device-mapper-multipath-devel \ + diffutils \ + findutils \ + gcc \ + gcc-c++ \ + gcovr \ + genisoimage \ + gettext \ + git \ + glib2-devel \ + glib2-static \ + glibc-langpack-en \ + glibc-static \ + glusterfs-api-devel \ + gnutls-devel \ + gtk3-devel \ + hostname \ + jemalloc-devel \ + libaio-devel \ + libasan \ + libattr-devel \ + libbpf-devel \ + libcacard-devel \ + libcap-ng-devel \ + libcurl-devel \ + libdrm-devel \ + libepoxy-devel \ + libfdt-devel \ + libffi-devel \ + libgcrypt-devel \ + libiscsi-devel \ + libjpeg-devel \ + libnfs-devel \ + libpmem-devel \ + libpng-devel \ + librbd-devel \ + libseccomp-devel \ + libselinux-devel \ + libslirp-devel \ + libssh-devel \ + libtasn1-devel \ + libubsan \ + libudev-devel \ + liburing-devel \ + libusbx-devel \ + libxml2-devel \ + libzstd-devel \ + llvm \ + lttng-ust-devel \ + lzo-devel \ + make \ + mesa-libgbm-devel \ + meson \ + ncurses-devel \ + nettle-devel \ + ninja-build \ + nmap-ncat \ + numactl-devel \ + openssh-clients \ + pam-devel \ + pcre-static \ + perl-Test-Harness \ + perl-base \ + pixman-devel \ + pkgconfig \ + pulseaudio-libs-devel \ + python3 \ + python3-PyYAML \ + python3-numpy \ + python3-opencv \ + python3-pillow \ + python3-pip \ + python3-sphinx \ + python3-sphinx_rtd_theme \ + python3-virtualenv \ + rdma-core-devel \ + rpm \ + sed \ + snappy-devel \ + sparse \ + spice-protocol \ + spice-server-devel \ + systemd-devel \ + systemtap-sdt-devel \ + tar \ + tesseract \ + tesseract-langpack-eng \ + texinfo \ + usbredir-devel \ + util-linux \ + virglrenderer-devel \ + vte291-devel \ + which \ + xen-devel \ + xfsprogs-devel \ + zlib-devel \ + zlib-static && \ + nosync dnf autoremove -y && \ + nosync dnf clean all -y && \ + rpm -qa | sort > /packages.txt && \ + mkdir -p /usr/libexec/ccache-wrappers && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/cc && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/clang && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc -RUN dnf install -y $PACKAGES -RUN rpm -q $PACKAGES | sort > /packages.txt -ENV PATH $PATH:/usr/libexec/python3-sphinx/ +ENV LANG "en_US.UTF-8" +ENV MAKE "/usr/bin/make" +ENV NINJA "/usr/bin/ninja" +ENV PYTHON "/usr/bin/python3" +ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers" diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh index 824b1c0ef2..d79d2b8c06 100755 --- a/tests/lcitool/refresh +++ b/tests/lcitool/refresh @@ -62,6 +62,7 @@ def generate_dockerfile(host, target, cross=None, trailer=None): try: generate_dockerfile("centos8", "centos-8") + generate_dockerfile("fedora", "fedora-35") sys.exit(0) except Exception as ex: From e482191643256aca6d6e84568f510da1abda219d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:45 +0000 Subject: [PATCH 590/730] tests/docker: auto-generate ubuntu1804.docker with lcitool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is best examined using the "-b" option to diff. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-11-berrange@redhat.com> Message-Id: <20220105135009.1584676-11-alex.bennee@linaro.org> --- tests/docker/dockerfiles/ubuntu1804.docker | 257 ++++++++++++--------- tests/lcitool/refresh | 7 + 2 files changed, 150 insertions(+), 114 deletions(-) diff --git a/tests/docker/dockerfiles/ubuntu1804.docker b/tests/docker/dockerfiles/ubuntu1804.docker index 450fd06d0d..0ffa3c4d4b 100644 --- a/tests/docker/dockerfiles/ubuntu1804.docker +++ b/tests/docker/dockerfiles/ubuntu1804.docker @@ -1,117 +1,146 @@ -FROM docker.io/library/ubuntu:18.04 -ENV PACKAGES \ - bc \ - bsdmainutils \ - bzip2 \ - ca-certificates \ - ccache \ - clang \ - dbus \ - debianutils \ - diffutils \ - exuberant-ctags \ - findutils \ - g++ \ - gcc \ - gcovr \ - genisoimage \ - gettext \ - git \ - glusterfs-common \ - hostname \ - libaio-dev \ - libasan5 \ - libasound2-dev \ - libattr1-dev \ - libbrlapi-dev \ - libbz2-dev \ - libc6-dev \ - libcacard-dev \ - libcap-ng-dev \ - libcapstone-dev \ - libcurl4-gnutls-dev \ - libdaxctl-dev \ - libdrm-dev \ - libepoxy-dev \ - libfdt-dev \ - libffi-dev \ - libgbm-dev \ - libgcrypt20-dev \ - libglib2.0-dev \ - libgnutls28-dev \ - libgtk-3-dev \ - libibverbs-dev \ - libiscsi-dev \ - libjemalloc-dev \ - libjpeg-turbo8-dev \ - liblttng-ust-dev \ - liblzo2-dev \ - libncursesw5-dev \ - libnfs-dev \ - libnuma-dev \ - libpam0g-dev \ - libpixman-1-dev \ - libpmem-dev \ - libpng-dev \ - libpulse-dev \ - librbd-dev \ - librdmacm-dev \ - libsasl2-dev \ - libsdl2-dev \ - libsdl2-image-dev \ - libseccomp-dev \ - libselinux-dev \ - libsnappy-dev \ - libspice-protocol-dev \ - libspice-server-dev \ - libssh-dev \ - libsystemd-dev \ - libtasn1-6-dev \ - libtest-harness-perl \ - libubsan1 \ - libudev-dev \ - libusb-1.0-0-dev \ - libusbredirhost-dev \ - libvdeplug-dev \ - libvirglrenderer-dev \ - libvte-2.91-dev \ - libxen-dev \ - libxml2-dev \ - libzstd-dev \ - llvm \ - locales \ - make \ - multipath-tools \ - netcat-openbsd \ - nettle-dev \ - ninja-build \ - openssh-client \ - perl-base \ - pkgconf \ - python3 \ - python3-numpy \ - python3-opencv \ - python3-pillow \ - python3-pip \ - python3-setuptools \ - python3-sphinx \ - python3-sphinx-rtd-theme \ - python3-venv \ - python3-wheel \ - python3-yaml \ - rpm2cpio \ - sed \ - sparse \ - systemtap-sdt-dev \ - tar \ - tesseract-ocr \ - tesseract-ocr-eng \ - texinfo \ - xfslibs-dev \ - zlib1g-dev -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get -y install $PACKAGES -RUN dpkg -l $PACKAGES | sort > /packages.txt +# THIS FILE WAS AUTO-GENERATED +# +# $ lcitool dockerfile ubuntu-1804 qemu +# +# https://gitlab.com/libvirt/libvirt-ci +FROM docker.io/library/ubuntu:18.04 + +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ + bash \ + bc \ + bsdmainutils \ + bzip2 \ + ca-certificates \ + ccache \ + clang \ + dbus \ + debianutils \ + diffutils \ + exuberant-ctags \ + findutils \ + g++ \ + gcc \ + gcovr \ + genisoimage \ + gettext \ + git \ + glusterfs-common \ + hostname \ + libaio-dev \ + libasan5 \ + libasound2-dev \ + libattr1-dev \ + libbrlapi-dev \ + libbz2-dev \ + libc6-dev \ + libcacard-dev \ + libcap-ng-dev \ + libcapstone-dev \ + libcurl4-gnutls-dev \ + libdaxctl-dev \ + libdrm-dev \ + libepoxy-dev \ + libfdt-dev \ + libffi-dev \ + libgbm-dev \ + libgcrypt20-dev \ + libglib2.0-dev \ + libgnutls28-dev \ + libgtk-3-dev \ + libibverbs-dev \ + libiscsi-dev \ + libjemalloc-dev \ + libjpeg-turbo8-dev \ + liblttng-ust-dev \ + liblzo2-dev \ + libncursesw5-dev \ + libnfs-dev \ + libnuma-dev \ + libpam0g-dev \ + libpcre2-dev \ + libpixman-1-dev \ + libpmem-dev \ + libpng-dev \ + libpulse-dev \ + librbd-dev \ + librdmacm-dev \ + libsasl2-dev \ + libsdl2-dev \ + libsdl2-image-dev \ + libseccomp-dev \ + libselinux1-dev \ + libsnappy-dev \ + libspice-protocol-dev \ + libspice-server-dev \ + libssh-dev \ + libsystemd-dev \ + libtasn1-6-dev \ + libtest-harness-perl \ + libubsan1 \ + libudev-dev \ + libusb-1.0-0-dev \ + libusbredirhost-dev \ + libvdeplug-dev \ + libvirglrenderer-dev \ + libvte-2.91-dev \ + libxen-dev \ + libxml2-dev \ + libzstd-dev \ + llvm \ + locales \ + make \ + multipath-tools \ + netcat-openbsd \ + nettle-dev \ + ninja-build \ + openssh-client \ + perl-base \ + pkgconf \ + python3 \ + python3-numpy \ + python3-opencv \ + python3-pillow \ + python3-pip \ + python3-setuptools \ + python3-sphinx \ + python3-sphinx-rtd-theme \ + python3-venv \ + python3-wheel \ + python3-yaml \ + rpm2cpio \ + sed \ + sparse \ + systemtap-sdt-dev \ + tar \ + tesseract-ocr \ + tesseract-ocr-eng \ + texinfo \ + xfslibs-dev \ + zlib1g-dev && \ + eatmydata apt-get autoremove -y && \ + eatmydata apt-get autoclean -y && \ + sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \ + dpkg-reconfigure locales && \ + dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt && \ + mkdir -p /usr/libexec/ccache-wrappers && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/cc && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/clang && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc + +RUN pip3 install \ + meson==0.56.0 + +ENV LANG "en_US.UTF-8" +ENV MAKE "/usr/bin/make" +ENV NINJA "/usr/bin/ninja" +ENV PYTHON "/usr/bin/python3" +ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers" # https://bugs.launchpad.net/qemu/+bug/1838763 ENV QEMU_CONFIGURE_OPTS --disable-libssh diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh index d79d2b8c06..1e30674d67 100755 --- a/tests/lcitool/refresh +++ b/tests/lcitool/refresh @@ -60,9 +60,16 @@ def generate_dockerfile(host, target, cross=None, trailer=None): cmd.extend([target, "qemu"]) generate(filename, cmd, trailer) +ubuntu1804_skipssh = [ + "# https://bugs.launchpad.net/qemu/+bug/1838763\n", + "ENV QEMU_CONFIGURE_OPTS --disable-libssh\n" +] + try: generate_dockerfile("centos8", "centos-8") generate_dockerfile("fedora", "fedora-35") + generate_dockerfile("ubuntu1804", "ubuntu-1804", + trailer="".join(ubuntu1804_skipssh)) sys.exit(0) except Exception as ex: From bb317c325830ac7c9e1f4b6fef23146ad85bc1be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:46 +0000 Subject: [PATCH 591/730] tests/docker: auto-generate ubuntu2004.docker with lcitool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is best examined using the "-b" option to diff. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-12-berrange@redhat.com> Message-Id: <20220105135009.1584676-12-alex.bennee@linaro.org> --- tests/docker/dockerfiles/ubuntu2004.docker | 259 ++++++++++++--------- tests/lcitool/refresh | 9 +- 2 files changed, 152 insertions(+), 116 deletions(-) diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker index 15a026be09..40402b91fe 100644 --- a/tests/docker/dockerfiles/ubuntu2004.docker +++ b/tests/docker/dockerfiles/ubuntu2004.docker @@ -1,119 +1,148 @@ -FROM docker.io/library/ubuntu:20.04 -ENV PACKAGES \ - bc \ - bsdmainutils \ - bzip2 \ - ca-certificates \ - ccache \ - clang \ - dbus \ - debianutils \ - diffutils \ - exuberant-ctags \ - findutils \ - g++ \ - gcc \ - gcovr \ - genisoimage \ - gettext \ - git \ - hostname \ - libaio-dev \ - libasan5 \ - libasound2-dev \ - libattr1-dev \ - libbrlapi-dev \ - libbz2-dev \ - libc6-dev \ - libcacard-dev \ - libcap-ng-dev \ - libcapstone-dev \ - libcurl4-gnutls-dev \ - libdaxctl-dev \ - libdrm-dev \ - libepoxy-dev \ - libfdt-dev \ - libffi-dev \ - libgbm-dev \ - libgcrypt20-dev \ - libglib2.0-dev \ - libglusterfs-dev \ - libgnutls28-dev \ - libgtk-3-dev \ - libibverbs-dev \ - libiscsi-dev \ - libjemalloc-dev \ - libjpeg-turbo8-dev \ - liblttng-ust-dev \ - liblzo2-dev \ - libncursesw5-dev \ - libnfs-dev \ - libnuma-dev \ - libpam0g-dev \ - libpixman-1-dev \ - libpmem-dev \ - libpng-dev \ - libpulse-dev \ - librbd-dev \ - librdmacm-dev \ - libsasl2-dev \ - libsdl2-dev \ - libsdl2-image-dev \ - libseccomp-dev \ - libselinux-dev \ - libslirp-dev \ - libsnappy-dev \ - libspice-protocol-dev \ - libspice-server-dev \ - libssh-dev \ - libsystemd-dev \ - libtasn1-6-dev \ - libtest-harness-perl \ - libubsan1 \ - libudev-dev \ - libusb-1.0-0-dev \ - libusbredirhost-dev \ - libvdeplug-dev \ - libvirglrenderer-dev \ - libvte-2.91-dev \ - libxen-dev \ - libxml2-dev \ - libzstd-dev \ - llvm \ - locales \ - make \ - multipath-tools \ - ncat \ - nettle-dev \ - ninja-build \ - openssh-client \ - perl-base \ - pkgconf \ - python3 \ - python3-numpy \ - python3-opencv \ - python3-pillow \ - python3-pip \ - python3-setuptools \ - python3-sphinx \ - python3-sphinx-rtd-theme \ - python3-venv \ - python3-wheel \ - python3-yaml \ - rpm2cpio \ - sed \ - sparse \ - systemtap-sdt-dev \ - tar \ - tesseract-ocr \ - tesseract-ocr-eng \ - texinfo \ - xfslibs-dev \ - zlib1g-dev -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get -y install $PACKAGES -RUN dpkg -l $PACKAGES | sort > /packages.txt +# THIS FILE WAS AUTO-GENERATED +# +# $ lcitool dockerfile ubuntu-2004 qemu +# +# https://gitlab.com/libvirt/libvirt-ci +FROM docker.io/library/ubuntu:20.04 + +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ + bash \ + bc \ + bsdmainutils \ + bzip2 \ + ca-certificates \ + ccache \ + clang \ + dbus \ + debianutils \ + diffutils \ + exuberant-ctags \ + findutils \ + g++ \ + gcc \ + gcovr \ + genisoimage \ + gettext \ + git \ + hostname \ + libaio-dev \ + libasan5 \ + libasound2-dev \ + libattr1-dev \ + libbrlapi-dev \ + libbz2-dev \ + libc6-dev \ + libcacard-dev \ + libcap-ng-dev \ + libcapstone-dev \ + libcurl4-gnutls-dev \ + libdaxctl-dev \ + libdrm-dev \ + libepoxy-dev \ + libfdt-dev \ + libffi-dev \ + libgbm-dev \ + libgcrypt20-dev \ + libglib2.0-dev \ + libglusterfs-dev \ + libgnutls28-dev \ + libgtk-3-dev \ + libibverbs-dev \ + libiscsi-dev \ + libjemalloc-dev \ + libjpeg-turbo8-dev \ + liblttng-ust-dev \ + liblzo2-dev \ + libncursesw5-dev \ + libnfs-dev \ + libnuma-dev \ + libpam0g-dev \ + libpcre2-dev \ + libpixman-1-dev \ + libpmem-dev \ + libpng-dev \ + libpulse-dev \ + librbd-dev \ + librdmacm-dev \ + libsasl2-dev \ + libsdl2-dev \ + libsdl2-image-dev \ + libseccomp-dev \ + libselinux1-dev \ + libslirp-dev \ + libsnappy-dev \ + libspice-protocol-dev \ + libspice-server-dev \ + libssh-dev \ + libsystemd-dev \ + libtasn1-6-dev \ + libtest-harness-perl \ + libubsan1 \ + libudev-dev \ + libusb-1.0-0-dev \ + libusbredirhost-dev \ + libvdeplug-dev \ + libvirglrenderer-dev \ + libvte-2.91-dev \ + libxen-dev \ + libxml2-dev \ + libzstd-dev \ + llvm \ + locales \ + make \ + multipath-tools \ + ncat \ + nettle-dev \ + ninja-build \ + openssh-client \ + perl-base \ + pkgconf \ + python3 \ + python3-numpy \ + python3-opencv \ + python3-pillow \ + python3-pip \ + python3-setuptools \ + python3-sphinx \ + python3-sphinx-rtd-theme \ + python3-venv \ + python3-wheel \ + python3-yaml \ + rpm2cpio \ + sed \ + sparse \ + systemtap-sdt-dev \ + tar \ + tesseract-ocr \ + tesseract-ocr-eng \ + texinfo \ + xfslibs-dev \ + zlib1g-dev && \ + eatmydata apt-get autoremove -y && \ + eatmydata apt-get autoclean -y && \ + sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \ + dpkg-reconfigure locales && \ + dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt && \ + mkdir -p /usr/libexec/ccache-wrappers && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/cc && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/clang && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc + +RUN pip3 install \ + meson==0.56.0 + +ENV LANG "en_US.UTF-8" +ENV MAKE "/usr/bin/make" +ENV NINJA "/usr/bin/ninja" +ENV PYTHON "/usr/bin/python3" +ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers" # Apply patch https://reviews.llvm.org/D75820 # This is required for TSan in clang-10 to compile with QEMU. RUN sed -i 's/^const/static const/g' /usr/lib/llvm-10/lib/clang/10.0.0/include/sanitizer/tsan_interface.h diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh index 1e30674d67..310bad1315 100755 --- a/tests/lcitool/refresh +++ b/tests/lcitool/refresh @@ -65,12 +65,19 @@ ubuntu1804_skipssh = [ "ENV QEMU_CONFIGURE_OPTS --disable-libssh\n" ] +ubuntu2004_tsanhack = [ + "# Apply patch https://reviews.llvm.org/D75820\n", + "# This is required for TSan in clang-10 to compile with QEMU.\n", + "RUN sed -i 's/^const/static const/g' /usr/lib/llvm-10/lib/clang/10.0.0/include/sanitizer/tsan_interface.h\n" +] + try: generate_dockerfile("centos8", "centos-8") generate_dockerfile("fedora", "fedora-35") generate_dockerfile("ubuntu1804", "ubuntu-1804", trailer="".join(ubuntu1804_skipssh)) - + generate_dockerfile("ubuntu2004", "ubuntu-2004", + trailer="".join(ubuntu2004_tsanhack)) sys.exit(0) except Exception as ex: print(str(ex), file=sys.stderr) From 122198393df0386bbae234f376187359f3210d62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:47 +0000 Subject: [PATCH 592/730] tests/docker: auto-generate opensuse-leap.docker with lcitool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is best examined using the "-b" option to diff. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-13-berrange@redhat.com> Message-Id: <20220105135009.1584676-13-alex.bennee@linaro.org> --- tests/docker/dockerfiles/opensuse-leap.docker | 245 ++++++++++-------- tests/lcitool/refresh | 1 + 2 files changed, 135 insertions(+), 111 deletions(-) diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker index 3bbdb67f4f..5510bdf19c 100644 --- a/tests/docker/dockerfiles/opensuse-leap.docker +++ b/tests/docker/dockerfiles/opensuse-leap.docker @@ -1,114 +1,137 @@ +# THIS FILE WAS AUTO-GENERATED +# +# $ lcitool dockerfile opensuse-leap-152 qemu +# +# https://gitlab.com/libvirt/libvirt-ci + FROM registry.opensuse.org/opensuse/leap:15.2 -# Please keep this list sorted alphabetically -ENV PACKAGES \ - Mesa-devel \ - alsa-lib-devel \ - bc \ - brlapi-devel \ - bzip2 \ - ca-certificates \ - ccache \ - clang \ - ctags \ - cyrus-sasl-devel \ - dbus-1 \ - diffutils \ - findutils \ - gcc \ - gcc-c++ \ - gcovr \ - gettext-runtime \ - git \ - glib2-devel \ - glibc-locale \ - glibc-static \ - glusterfs-devel \ - gtk3-devel \ - hostname \ - jemalloc-devel \ - libSDL2-devel \ - libSDL2_image-devel \ - libaio-devel \ - libasan6 \ - libattr-devel \ - libbpf-devel \ - libbz2-devel \ - libcacard-devel \ - libcap-ng-devel \ - libcurl-devel \ - libdrm-devel \ - libepoxy-devel \ - libfdt-devel \ - libffi-devel \ - libgcrypt-devel \ - libgnutls-devel \ - libiscsi-devel \ - libjpeg8-devel \ - libndctl-devel \ - libnettle-devel \ - libnfs-devel \ - libnuma-devel \ - libpixman-1-0-devel \ - libpmem-devel \ - libpng16-devel \ - libpulse-devel \ - librbd-devel \ - libseccomp-devel \ - libselinux-devel \ - libspice-server-devel \ - libssh-devel \ - libtasn1-devel \ - libubsan1 \ - libudev-devel \ - libusb-1_0-devel \ - libxml2-devel \ - libzstd-devel \ - llvm \ - lttng-ust-devel \ - lzo-devel \ - make \ - mkisofs \ - ncat \ - ncurses-devel \ - ninja \ - openssh \ - pam-devel \ - perl-Test-Harness \ - perl-base \ - pkgconfig \ - python3-Pillow \ - python3-PyYAML \ - python3-Sphinx \ - python3-base \ - python3-numpy \ - python3-opencv \ - python3-pip \ - python3-setuptools \ - python3-sphinx_rtd_theme \ - python3-virtualenv \ - python3-wheel \ - rdma-core-devel \ - rpm \ - sed \ - snappy-devel \ - sparse \ - spice-protocol-devel \ - systemd-devel \ - systemtap-sdt-devel \ - tar \ - tesseract-ocr \ - tesseract-ocr-traineddata-english \ - texinfo \ - usbredir-devel \ - util-linux \ - virglrenderer-devel \ - vte-devel \ - which \ - xen-devel \ - xfsprogs-devel \ - zlib-devel -ENV QEMU_CONFIGURE_OPTS --python=/usr/bin/python3.6 +RUN zypper update -y && \ + zypper install -y \ + Mesa-devel \ + alsa-lib-devel \ + bash \ + bc \ + brlapi-devel \ + bzip2 \ + ca-certificates \ + ccache \ + clang \ + ctags \ + cyrus-sasl-devel \ + dbus-1 \ + diffutils \ + findutils \ + gcc \ + gcc-c++ \ + gcovr \ + gettext-runtime \ + git \ + glib2-devel \ + glibc-locale \ + glibc-static \ + glusterfs-devel \ + gtk3-devel \ + hostname \ + jemalloc-devel \ + libSDL2-devel \ + libSDL2_image-devel \ + libaio-devel \ + libasan6 \ + libattr-devel \ + libbpf-devel \ + libbz2-devel \ + libcacard-devel \ + libcap-ng-devel \ + libcurl-devel \ + libdrm-devel \ + libepoxy-devel \ + libfdt-devel \ + libffi-devel \ + libgcrypt-devel \ + libgnutls-devel \ + libiscsi-devel \ + libjpeg8-devel \ + libndctl-devel \ + libnettle-devel \ + libnfs-devel \ + libnuma-devel \ + libpixman-1-0-devel \ + libpmem-devel \ + libpng16-devel \ + libpulse-devel \ + librbd-devel \ + libseccomp-devel \ + libselinux-devel \ + libspice-server-devel \ + libssh-devel \ + libtasn1-devel \ + libubsan1 \ + libudev-devel \ + liburing-devel \ + libusb-1_0-devel \ + libxml2-devel \ + libzstd-devel \ + llvm \ + lttng-ust-devel \ + lzo-devel \ + make \ + mkisofs \ + ncat \ + ncurses-devel \ + ninja \ + openssh \ + pam-devel \ + pcre-devel-static \ + perl-Test-Harness \ + perl-base \ + pkgconfig \ + python3-Pillow \ + python3-PyYAML \ + python3-Sphinx \ + python3-base \ + python3-numpy \ + python3-opencv \ + python3-pip \ + python3-setuptools \ + python3-sphinx_rtd_theme \ + python3-virtualenv \ + python3-wheel \ + rdma-core-devel \ + rpm \ + sed \ + snappy-devel \ + sparse \ + spice-protocol-devel \ + systemd-devel \ + systemtap-sdt-devel \ + tar \ + tesseract-ocr \ + tesseract-ocr-traineddata-english \ + texinfo \ + usbredir-devel \ + util-linux \ + virglrenderer-devel \ + vte-devel \ + which \ + xen-devel \ + xfsprogs-devel \ + zlib-devel \ + zlib-devel-static && \ + zypper clean --all && \ + rpm -qa | sort > /packages.txt && \ + mkdir -p /usr/libexec/ccache-wrappers && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/cc && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/clang && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc -RUN zypper update -y && zypper --non-interactive install -y $PACKAGES -RUN rpm -q $PACKAGES | sort > /packages.txt +RUN pip3 install \ + meson==0.56.0 + +ENV LANG "en_US.UTF-8" +ENV MAKE "/usr/bin/make" +ENV NINJA "/usr/bin/ninja" +ENV PYTHON "/usr/bin/python3" +ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers" diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh index 310bad1315..b8a69cee59 100755 --- a/tests/lcitool/refresh +++ b/tests/lcitool/refresh @@ -78,6 +78,7 @@ try: trailer="".join(ubuntu1804_skipssh)) generate_dockerfile("ubuntu2004", "ubuntu-2004", trailer="".join(ubuntu2004_tsanhack)) + generate_dockerfile("opensuse-leap", "opensuse-leap-152") sys.exit(0) except Exception as ex: print(str(ex), file=sys.stderr) From 6815e63f31fc83b8f5062e3167765a9fa74660e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:48 +0000 Subject: [PATCH 593/730] tests/docker: remove ubuntu.docker container MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This duplicates the ubuntu2004 container but with an inconsistent set of packages. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-14-berrange@redhat.com> Message-Id: <20220105135009.1584676-14-alex.bennee@linaro.org> --- .gitlab-ci.d/containers.yml | 5 -- tests/docker/dockerfiles/ubuntu.docker | 71 -------------------------- 2 files changed, 76 deletions(-) delete mode 100644 tests/docker/dockerfiles/ubuntu.docker diff --git a/.gitlab-ci.d/containers.yml b/.gitlab-ci.d/containers.yml index cd06d3f5f4..b9b675fdcb 100644 --- a/.gitlab-ci.d/containers.yml +++ b/.gitlab-ci.d/containers.yml @@ -29,11 +29,6 @@ amd64-ubuntu2004-container: variables: NAME: ubuntu2004 -amd64-ubuntu-container: - extends: .container_job_template - variables: - NAME: ubuntu - amd64-opensuse-leap-container: extends: .container_job_template variables: diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker deleted file mode 100644 index f0e0180d21..0000000000 --- a/tests/docker/dockerfiles/ubuntu.docker +++ /dev/null @@ -1,71 +0,0 @@ -# -# Latest Ubuntu Release -# -# Useful for testing against relatively bleeding edge libraries and -# compilers. We also have seperate recipe for the most recent LTS -# release. -# -# When updating use the full tag not :latest otherwise the build -# system won't pick up that it has changed. -# - -FROM docker.io/library/ubuntu:20.04 -ENV PACKAGES \ - ccache \ - clang \ - dbus \ - gcc \ - gettext \ - git \ - glusterfs-common \ - libaio-dev \ - libattr1-dev \ - libbrlapi-dev \ - libbz2-dev \ - libcacard-dev \ - libcap-ng-dev \ - libcurl4-gnutls-dev \ - libdrm-dev \ - libepoxy-dev \ - libfdt-dev \ - libffi-dev \ - libgbm-dev \ - libgnutls28-dev \ - libgtk-3-dev \ - libibverbs-dev \ - libiscsi-dev \ - libjemalloc-dev \ - libjpeg-turbo8-dev \ - liblzo2-dev \ - libncurses5-dev \ - libncursesw5-dev \ - libnfs-dev \ - libnuma-dev \ - libpixman-1-dev \ - libpng-dev \ - librados-dev \ - librbd-dev \ - librdmacm-dev \ - libsasl2-dev \ - libsdl2-dev \ - libseccomp-dev \ - libsnappy-dev \ - libspice-protocol-dev \ - libspice-server-dev \ - libssh-dev \ - libusb-1.0-0-dev \ - libusbredirhost-dev \ - libvdeplug-dev \ - libvte-2.91-dev \ - libxen-dev \ - libzstd-dev \ - make \ - ninja-build \ - python3-yaml \ - python3-sphinx \ - python3-sphinx-rtd-theme \ - sparse \ - xfslibs-dev -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get -y install $PACKAGES -RUN dpkg -l $PACKAGES | sort > /packages.txt From c45a540f4bd47b2947edf585c89bbfdc338eaef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:49 +0000 Subject: [PATCH 594/730] .gitlab-ci.d/cirrus: auto-generate variables with lcitool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current Cirrus CI variables files were previously generated by using lcitool. This change wires them up to the refresh script to make that link explicit. This changes the package list because libvirt-ci now knows about the mapping for dtc on FreeBSD and macOS platforms. The variables are also now emit in sorted order for stability across runs. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-15-berrange@redhat.com> Message-Id: <20220105135009.1584676-15-alex.bennee@linaro.org> --- .gitlab-ci.d/cirrus/freebsd-12.vars | 11 +++++++---- .gitlab-ci.d/cirrus/freebsd-13.vars | 11 +++++++---- .gitlab-ci.d/cirrus/macos-11.vars | 11 ++++++----- tests/lcitool/refresh | 10 ++++++++++ 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/.gitlab-ci.d/cirrus/freebsd-12.vars b/.gitlab-ci.d/cirrus/freebsd-12.vars index 2099b21354..9c52266811 100644 --- a/.gitlab-ci.d/cirrus/freebsd-12.vars +++ b/.gitlab-ci.d/cirrus/freebsd-12.vars @@ -2,12 +2,15 @@ # # $ lcitool variables freebsd-12 qemu # -# https://gitlab.com/libvirt/libvirt-ci/-/commit/c7e275ab27ac0dcd09da290817b9adeea1fd1eb1 +# https://gitlab.com/libvirt/libvirt-ci -PACKAGING_COMMAND='pkg' CCACHE='/usr/local/bin/ccache' +CPAN_PKGS='' +CROSS_PKGS='' MAKE='/usr/local/bin/gmake' NINJA='/usr/local/bin/ninja' -PYTHON='/usr/local/bin/python3' +PACKAGING_COMMAND='pkg' PIP3='/usr/local/bin/pip-3.8' -PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 libxml2 llvm lttng-ust lzo2 meson ncurses nettle ninja opencv p5-Test-Harness perl5 pixman pkgconf png py38-numpy py38-pillow py38-pip py38-sphinx py38-sphinx_rtd_theme py38-virtualenv py38-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' +PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils dtc gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 libxml2 llvm lttng-ust lzo2 meson ncurses nettle ninja opencv p5-Test-Harness perl5 pixman pkgconf png py38-numpy py38-pillow py38-pip py38-sphinx py38-sphinx_rtd_theme py38-virtualenv py38-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' +PYPI_PKGS='' +PYTHON='/usr/local/bin/python3' diff --git a/.gitlab-ci.d/cirrus/freebsd-13.vars b/.gitlab-ci.d/cirrus/freebsd-13.vars index 323fe806d5..7b44dba324 100644 --- a/.gitlab-ci.d/cirrus/freebsd-13.vars +++ b/.gitlab-ci.d/cirrus/freebsd-13.vars @@ -2,12 +2,15 @@ # # $ lcitool variables freebsd-13 qemu # -# https://gitlab.com/libvirt/libvirt-ci/-/commit/c7e275ab27ac0dcd09da290817b9adeea1fd1eb1 +# https://gitlab.com/libvirt/libvirt-ci -PACKAGING_COMMAND='pkg' CCACHE='/usr/local/bin/ccache' +CPAN_PKGS='' +CROSS_PKGS='' MAKE='/usr/local/bin/gmake' NINJA='/usr/local/bin/ninja' -PYTHON='/usr/local/bin/python3' +PACKAGING_COMMAND='pkg' PIP3='/usr/local/bin/pip-3.8' -PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 libxml2 llvm lttng-ust lzo2 meson ncurses nettle ninja opencv p5-Test-Harness perl5 pixman pkgconf png py38-numpy py38-pillow py38-pip py38-sphinx py38-sphinx_rtd_theme py38-virtualenv py38-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' +PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils dtc gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 libxml2 llvm lttng-ust lzo2 meson ncurses nettle ninja opencv p5-Test-Harness perl5 pixman pkgconf png py38-numpy py38-pillow py38-pip py38-sphinx py38-sphinx_rtd_theme py38-virtualenv py38-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' +PYPI_PKGS='' +PYTHON='/usr/local/bin/python3' diff --git a/.gitlab-ci.d/cirrus/macos-11.vars b/.gitlab-ci.d/cirrus/macos-11.vars index cbec8a44a3..613d1373c2 100644 --- a/.gitlab-ci.d/cirrus/macos-11.vars +++ b/.gitlab-ci.d/cirrus/macos-11.vars @@ -2,14 +2,15 @@ # # $ lcitool variables macos-11 qemu # -# https://gitlab.com/libvirt/libvirt-ci/-/commit/c7e275ab27ac0dcd09da290817b9adeea1fd1eb1 +# https://gitlab.com/libvirt/libvirt-ci -PACKAGING_COMMAND='brew' CCACHE='/usr/local/bin/ccache' +CPAN_PKGS='Test::Harness' +CROSS_PKGS='' MAKE='/usr/local/bin/gmake' NINJA='/usr/local/bin/ninja' -PYTHON='/usr/local/bin/python3' +PACKAGING_COMMAND='brew' PIP3='/usr/local/bin/pip3' -PKGS='bash bc bzip2 capstone ccache cpanminus ctags curl dbus diffutils gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb libxml2 llvm lzo make meson ncurses nettle ninja perl pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy sparse spice-protocol tesseract texinfo usbredir vde vte3 zlib zstd' +PKGS='bash bc bzip2 capstone ccache cpanminus ctags curl dbus diffutils dtc gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb libxml2 llvm lzo make meson ncurses nettle ninja perl pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy sparse spice-protocol tesseract texinfo usbredir vde vte3 zlib zstd' PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme virtualenv' -CPAN_PKGS='Test::Harness' +PYTHON='/usr/local/bin/python3' diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh index b8a69cee59..b8cf0a7386 100755 --- a/tests/lcitool/refresh +++ b/tests/lcitool/refresh @@ -60,6 +60,11 @@ def generate_dockerfile(host, target, cross=None, trailer=None): cmd.extend([target, "qemu"]) generate(filename, cmd, trailer) +def generate_cirrus(target, trailer=None): + filename = Path(src_dir, ".gitlab-ci.d", "cirrus", target + ".vars") + cmd = [lcitool_path, "variables", target, "qemu"] + generate(filename, cmd, trailer) + ubuntu1804_skipssh = [ "# https://bugs.launchpad.net/qemu/+bug/1838763\n", "ENV QEMU_CONFIGURE_OPTS --disable-libssh\n" @@ -79,6 +84,11 @@ try: generate_dockerfile("ubuntu2004", "ubuntu-2004", trailer="".join(ubuntu2004_tsanhack)) generate_dockerfile("opensuse-leap", "opensuse-leap-152") + + generate_cirrus("freebsd-12") + generate_cirrus("freebsd-13") + generate_cirrus("macos-11") + sys.exit(0) except Exception as ex: print(str(ex), file=sys.stderr) From 8d5528016028c0df124c2af428094ca1a61be61c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:50 +0000 Subject: [PATCH 595/730] tests/docker: updates to alpine package list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup the package lists by removing some entries that we don't need to directly reference binutils: implied by the compiler toolchain coreutils: not required by QEMU build mesa-egl mesa-gbm: implied by mesa-dev ninja: alias for samurai package shadow: not required by QEMU build util-linux-dev: not directly required by QEMU build Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-16-berrange@redhat.com> Message-Id: <20220105135009.1584676-16-alex.bennee@linaro.org> --- tests/docker/dockerfiles/alpine.docker | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfiles/alpine.docker index 7e6997e301..5a1808726e 100644 --- a/tests/docker/dockerfiles/alpine.docker +++ b/tests/docker/dockerfiles/alpine.docker @@ -8,9 +8,7 @@ RUN apk upgrade ENV PACKAGES \ alsa-lib-dev \ bash \ - binutils \ ccache \ - coreutils \ curl-dev \ g++ \ gcc \ @@ -33,22 +31,18 @@ ENV PACKAGES \ lzo-dev \ make \ mesa-dev \ - mesa-egl \ - mesa-gbm \ meson \ ncurses-dev \ - ninja \ perl \ pulseaudio-dev \ python3 \ py3-sphinx \ py3-sphinx_rtd_theme \ - shadow \ + samurai \ snappy-dev \ spice-dev \ texinfo \ usbredir-dev \ - util-linux-dev \ vde2-dev \ virglrenderer-dev \ vte3-dev \ From 46b1c19beceaea6295cddd56d87c0a21e984cb64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:51 +0000 Subject: [PATCH 596/730] tests/docker: fix sorting of alpine image package lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "python" sorts alphabetically after "py3-xxxx" Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-17-berrange@redhat.com> Message-Id: <20220105135009.1584676-17-alex.bennee@linaro.org> --- tests/docker/dockerfiles/alpine.docker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfiles/alpine.docker index 5a1808726e..ca4b3b58d2 100644 --- a/tests/docker/dockerfiles/alpine.docker +++ b/tests/docker/dockerfiles/alpine.docker @@ -35,9 +35,9 @@ ENV PACKAGES \ ncurses-dev \ perl \ pulseaudio-dev \ - python3 \ py3-sphinx \ py3-sphinx_rtd_theme \ + python3 \ samurai \ snappy-dev \ spice-dev \ From e6302780086d8453524e63d1fe8053ca80cc09a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:52 +0000 Subject: [PATCH 597/730] tests/docker: fully expand the alpine package list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add many extra alpine packages to cover the various optional QEMU build dependencies pulled in by other dockerfiles. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-18-berrange@redhat.com> Message-Id: <20220105135009.1584676-18-alex.bennee@linaro.org> --- tests/docker/dockerfiles/alpine.docker | 58 +++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfiles/alpine.docker index ca4b3b58d2..0ac30c8014 100644 --- a/tests/docker/dockerfiles/alpine.docker +++ b/tests/docker/dockerfiles/alpine.docker @@ -7,11 +7,29 @@ RUN apk upgrade # Please keep this list sorted alphabetically ENV PACKAGES \ alsa-lib-dev \ + attr-dev \ bash \ + bc \ + bzip2 \ + bzip2-dev \ + ca-certificates \ + capstone-dev \ ccache \ + cdrkit \ + ceph-dev \ + clang \ + ctags \ curl-dev \ + cyrus-sasl-dev \ + dbus \ + diffutils \ + dtc-dev \ + eudev-dev \ + findutils \ g++ \ gcc \ + gcovr \ + gettext \ git \ glib-dev \ glib-static \ @@ -20,34 +38,72 @@ ENV PACKAGES \ libaio-dev \ libbpf-dev \ libcap-ng-dev \ + libdrm-dev \ + libepoxy-dev \ libffi-dev \ + libgcrypt-dev \ libjpeg-turbo-dev \ libnfs-dev \ libpng-dev \ libseccomp-dev \ + libselinux-dev \ + libslirp-dev \ libssh-dev \ + libtasn1-dev \ + liburing-dev \ libusb-dev \ libxml2-dev \ + linux-pam-dev \ + llvm11 \ + lttng-ust-dev \ lzo-dev \ make \ mesa-dev \ meson \ + multipath-tools \ ncurses-dev \ + ndctl-dev \ + net-tools \ + nettle-dev \ + nmap-ncat \ + numactl-dev \ + openssh-client \ + pcre-dev \ perl \ + perl-test-harness \ + pixman-dev \ + pkgconf \ pulseaudio-dev \ + py3-numpy \ + py3-pillow \ + py3-pip \ py3-sphinx \ py3-sphinx_rtd_theme \ + py3-virtualenv \ + py3-yaml \ python3 \ + rpm2cpio \ samurai \ + sdl2-dev \ + sdl2_image-dev \ + sed \ snappy-dev \ + sparse \ spice-dev \ + spice-protocol \ + tar \ + tesseract-ocr \ texinfo \ usbredir-dev \ + util-linux \ vde2-dev \ virglrenderer-dev \ vte3-dev \ + which \ + xen-dev \ xfsprogs-dev \ zlib-dev \ - zlib-static + zlib-static \ + zstd-dev RUN apk add $PACKAGES From e1cb5c7550804ea61971366598431aa7c0cadfd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 13:49:53 +0000 Subject: [PATCH 598/730] tests/docker: auto-generate alpine.docker with lcitool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit is best examined using the "-b" option to diff. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Daniel P. Berrangé Signed-off-by: Alex Bennée Message-Id: <20211215141949.3512719-19-berrange@redhat.com> Message-Id: <20220105135009.1584676-19-alex.bennee@linaro.org> --- tests/docker/dockerfiles/alpine.docker | 225 +++++++++++++------------ tests/lcitool/refresh | 1 + 2 files changed, 120 insertions(+), 106 deletions(-) diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfiles/alpine.docker index 0ac30c8014..97c7a88d1f 100644 --- a/tests/docker/dockerfiles/alpine.docker +++ b/tests/docker/dockerfiles/alpine.docker @@ -1,109 +1,122 @@ +# THIS FILE WAS AUTO-GENERATED +# +# $ lcitool dockerfile alpine-edge qemu +# +# https://gitlab.com/libvirt/libvirt-ci -FROM alpine:edge +FROM docker.io/library/alpine:edge -RUN apk update -RUN apk upgrade +RUN apk update && \ + apk upgrade && \ + apk add \ + alsa-lib-dev \ + attr-dev \ + bash \ + bc \ + bzip2 \ + bzip2-dev \ + ca-certificates \ + capstone-dev \ + ccache \ + cdrkit \ + ceph-dev \ + clang \ + ctags \ + curl-dev \ + cyrus-sasl-dev \ + dbus \ + diffutils \ + dtc-dev \ + eudev-dev \ + findutils \ + g++ \ + gcc \ + gcovr \ + gettext \ + git \ + glib-dev \ + glib-static \ + gnutls-dev \ + gtk+3.0-dev \ + libaio-dev \ + libbpf-dev \ + libcap-ng-dev \ + libdrm-dev \ + libepoxy-dev \ + libffi-dev \ + libgcrypt-dev \ + libjpeg-turbo-dev \ + libnfs-dev \ + libpng-dev \ + libseccomp-dev \ + libselinux-dev \ + libslirp-dev \ + libssh-dev \ + libtasn1-dev \ + liburing-dev \ + libusb-dev \ + libxml2-dev \ + linux-pam-dev \ + llvm11 \ + lttng-ust-dev \ + lzo-dev \ + make \ + mesa-dev \ + meson \ + multipath-tools \ + ncurses-dev \ + ndctl-dev \ + net-tools \ + nettle-dev \ + nmap-ncat \ + numactl-dev \ + openssh-client \ + pcre-dev \ + perl \ + perl-test-harness \ + pixman-dev \ + pkgconf \ + pulseaudio-dev \ + py3-numpy \ + py3-pillow \ + py3-pip \ + py3-sphinx \ + py3-sphinx_rtd_theme \ + py3-virtualenv \ + py3-yaml \ + python3 \ + rpm2cpio \ + samurai \ + sdl2-dev \ + sdl2_image-dev \ + sed \ + snappy-dev \ + sparse \ + spice-dev \ + spice-protocol \ + tar \ + tesseract-ocr \ + texinfo \ + usbredir-dev \ + util-linux \ + vde2-dev \ + virglrenderer-dev \ + vte3-dev \ + which \ + xen-dev \ + xfsprogs-dev \ + zlib-dev \ + zlib-static \ + zstd-dev && \ + mkdir -p /usr/libexec/ccache-wrappers && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/cc && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/clang && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc -# Please keep this list sorted alphabetically -ENV PACKAGES \ - alsa-lib-dev \ - attr-dev \ - bash \ - bc \ - bzip2 \ - bzip2-dev \ - ca-certificates \ - capstone-dev \ - ccache \ - cdrkit \ - ceph-dev \ - clang \ - ctags \ - curl-dev \ - cyrus-sasl-dev \ - dbus \ - diffutils \ - dtc-dev \ - eudev-dev \ - findutils \ - g++ \ - gcc \ - gcovr \ - gettext \ - git \ - glib-dev \ - glib-static \ - gnutls-dev \ - gtk+3.0-dev \ - libaio-dev \ - libbpf-dev \ - libcap-ng-dev \ - libdrm-dev \ - libepoxy-dev \ - libffi-dev \ - libgcrypt-dev \ - libjpeg-turbo-dev \ - libnfs-dev \ - libpng-dev \ - libseccomp-dev \ - libselinux-dev \ - libslirp-dev \ - libssh-dev \ - libtasn1-dev \ - liburing-dev \ - libusb-dev \ - libxml2-dev \ - linux-pam-dev \ - llvm11 \ - lttng-ust-dev \ - lzo-dev \ - make \ - mesa-dev \ - meson \ - multipath-tools \ - ncurses-dev \ - ndctl-dev \ - net-tools \ - nettle-dev \ - nmap-ncat \ - numactl-dev \ - openssh-client \ - pcre-dev \ - perl \ - perl-test-harness \ - pixman-dev \ - pkgconf \ - pulseaudio-dev \ - py3-numpy \ - py3-pillow \ - py3-pip \ - py3-sphinx \ - py3-sphinx_rtd_theme \ - py3-virtualenv \ - py3-yaml \ - python3 \ - rpm2cpio \ - samurai \ - sdl2-dev \ - sdl2_image-dev \ - sed \ - snappy-dev \ - sparse \ - spice-dev \ - spice-protocol \ - tar \ - tesseract-ocr \ - texinfo \ - usbredir-dev \ - util-linux \ - vde2-dev \ - virglrenderer-dev \ - vte3-dev \ - which \ - xen-dev \ - xfsprogs-dev \ - zlib-dev \ - zlib-static \ - zstd-dev - -RUN apk add $PACKAGES +ENV LANG "en_US.UTF-8" +ENV MAKE "/usr/bin/make" +ENV NINJA "/usr/bin/ninja" +ENV PYTHON "/usr/bin/python3" +ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers" diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh index b8cf0a7386..033120e223 100755 --- a/tests/lcitool/refresh +++ b/tests/lcitool/refresh @@ -84,6 +84,7 @@ try: generate_dockerfile("ubuntu2004", "ubuntu-2004", trailer="".join(ubuntu2004_tsanhack)) generate_dockerfile("opensuse-leap", "opensuse-leap-152") + generate_dockerfile("alpine", "alpine-edge") generate_cirrus("freebsd-12") generate_cirrus("freebsd-13") From 91ad2244b73ce2b98129bc4ac7ea45fa280ccf62 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Jan 2022 13:49:54 +0000 Subject: [PATCH 599/730] tests/tcg: use CONFIG_LINUX_USER, not CONFIG_LINUX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two more or less overlap, because CONFIG_LINUX is a requirement for Linux user-mode emulation. However, CONFIG_LINUX is technically a host symbol that applies even to system emulation. Defining CONFIG_LINUX_USER, and CONFIG_BSD_USER for eventual future use, is cleaner. Signed-off-by: Paolo Bonzini Signed-off-by: Alex Bennée Message-Id: <20211210084836.25202-1-pbonzini@redhat.com> Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220105135009.1584676-20-alex.bennee@linaro.org> --- tests/tcg/configure.sh | 8 +++++++- tests/tcg/multiarch/Makefile.target | 2 +- tests/tcg/x86_64/Makefile.target | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh index 8eb4287c84..309335a2bd 100755 --- a/tests/tcg/configure.sh +++ b/tests/tcg/configure.sh @@ -225,8 +225,14 @@ for target in $target_list; do echo "TARGET_NAME=$arch" >> $config_target_mak echo "target=$target" >> $config_target_mak case $target in - *-linux-user | *-bsd-user) + *-linux-user) echo "CONFIG_USER_ONLY=y" >> $config_target_mak + echo "CONFIG_LINUX_USER=y" >> $config_target_mak + echo "QEMU=$PWD/qemu-$arch" >> $config_target_mak + ;; + *-bsd-user) + echo "CONFIG_USER_ONLY=y" >> $config_target_mak + echo "CONFIG_BSD_USER=y" >> $config_target_mak echo "QEMU=$PWD/qemu-$arch" >> $config_target_mak ;; *-softmmu) diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index a83efb4a9d..dec401e67f 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -10,7 +10,7 @@ MULTIARCH_SRC=$(SRC_PATH)/tests/tcg/multiarch # Set search path for all sources VPATH += $(MULTIARCH_SRC) MULTIARCH_SRCS = $(notdir $(wildcard $(MULTIARCH_SRC)/*.c)) -ifneq ($(CONFIG_LINUX),) +ifneq ($(CONFIG_LINUX_USER),) VPATH += $(MULTIARCH_SRC)/linux MULTIARCH_SRCS += $(notdir $(wildcard $(MULTIARCH_SRC)/linux/*.c)) endif diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target index d7a7385583..4a8a464c57 100644 --- a/tests/tcg/x86_64/Makefile.target +++ b/tests/tcg/x86_64/Makefile.target @@ -8,7 +8,7 @@ include $(SRC_PATH)/tests/tcg/i386/Makefile.target -ifneq ($(CONFIG_LINUX),) +ifneq ($(CONFIG_LINUX_USER),) X86_64_TESTS += vsyscall TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64 else From 7bef20d72985c5da4082d198ad175715272cd50c Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 5 Jan 2022 13:49:55 +0000 Subject: [PATCH 600/730] tests/docker: add libfuse3 development headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FUSE exports feature is not built because most container images do not have libfuse3 development headers installed. Add the necessary packages to the Dockerfiles. Cc: Hanna Reitz Cc: Richard W.M. Jones Signed-off-by: Stefan Hajnoczi Acked-by: Richard W.M. Jones Reviewed-by: Beraldo Leal Tested-by: Beraldo Leal Message-Id: <20211207160025.52466-1-stefanha@redhat.com> [AJB: migrate to lcitool qemu.yml and regenerate] Signed-off-by: Alex Bennée Reviewed-by: Richard W.M. Jones Message-Id: <20220105135009.1584676-21-alex.bennee@linaro.org> --- tests/docker/dockerfiles/alpine.docker | 1 + tests/docker/dockerfiles/centos8.docker | 1 + tests/docker/dockerfiles/fedora.docker | 1 + tests/docker/dockerfiles/opensuse-leap.docker | 1 + tests/docker/dockerfiles/ubuntu2004.docker | 1 + tests/lcitool/projects/qemu.yml | 1 + 6 files changed, 6 insertions(+) diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfiles/alpine.docker index 97c7a88d1f..eb2251c81c 100644 --- a/tests/docker/dockerfiles/alpine.docker +++ b/tests/docker/dockerfiles/alpine.docker @@ -29,6 +29,7 @@ RUN apk update && \ dtc-dev \ eudev-dev \ findutils \ + fuse3-dev \ g++ \ gcc \ gcovr \ diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker index 3c62b62a99..cbb909d02b 100644 --- a/tests/docker/dockerfiles/centos8.docker +++ b/tests/docker/dockerfiles/centos8.docker @@ -30,6 +30,7 @@ RUN dnf update -y && \ device-mapper-multipath-devel \ diffutils \ findutils \ + fuse3-devel \ gcc \ gcc-c++ \ genisoimage \ diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker index 6784878b56..60207f3da3 100644 --- a/tests/docker/dockerfiles/fedora.docker +++ b/tests/docker/dockerfiles/fedora.docker @@ -37,6 +37,7 @@ exec "$@"' > /usr/bin/nosync && \ device-mapper-multipath-devel \ diffutils \ findutils \ + fuse3-devel \ gcc \ gcc-c++ \ gcovr \ diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker index 5510bdf19c..f57d8cfb29 100644 --- a/tests/docker/dockerfiles/opensuse-leap.docker +++ b/tests/docker/dockerfiles/opensuse-leap.docker @@ -22,6 +22,7 @@ RUN zypper update -y && \ dbus-1 \ diffutils \ findutils \ + fuse3-devel \ gcc \ gcc-c++ \ gcovr \ diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker index 40402b91fe..4e562dfdcd 100644 --- a/tests/docker/dockerfiles/ubuntu2004.docker +++ b/tests/docker/dockerfiles/ubuntu2004.docker @@ -46,6 +46,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libepoxy-dev \ libfdt-dev \ libffi-dev \ + libfuse3-dev \ libgbm-dev \ libgcrypt20-dev \ libglib2.0-dev \ diff --git a/tests/lcitool/projects/qemu.yml b/tests/lcitool/projects/qemu.yml index 2e2271510e..ed5ab1407a 100644 --- a/tests/lcitool/projects/qemu.yml +++ b/tests/lcitool/projects/qemu.yml @@ -18,6 +18,7 @@ packages: - diffutils - dtrace - findutils + - fuse3 - g++ - gcc - gcovr From 33973e1e1f88b7588fe9629645e279ff2c6ca1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 5 Jan 2022 13:49:56 +0000 Subject: [PATCH 601/730] hw/arm: add control knob to disable kaslr_seed via DTB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generally a guest needs an external source of randomness to properly enable things like address space randomisation. However in a trusted boot environment where the firmware will cryptographically verify components having random data in the DTB will cause verification to fail. Add a control knob so we can prevent this being added to the system DTB. Signed-off-by: Alex Bennée Tested-by: Heinrich Schuchardt Acked-by: Ilias Apalodimas Acked-by: Jerome Forissier Reviewed-by: Andrew Jones Message-Id: <20220105135009.1584676-22-alex.bennee@linaro.org> --- docs/system/arm/virt.rst | 8 ++++++++ hw/arm/virt.c | 32 ++++++++++++++++++++++++++++++-- include/hw/arm/virt.h | 1 + 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst index 850787495b..1544632b67 100644 --- a/docs/system/arm/virt.rst +++ b/docs/system/arm/virt.rst @@ -121,6 +121,14 @@ ras Set ``on``/``off`` to enable/disable reporting host memory errors to a guest using ACPI and guest external abort exceptions. The default is off. +dtb-kaslr-seed + Set ``on``/``off`` to pass a random seed via the guest dtb + kaslr-seed node (in both "/chosen" and /secure-chosen) to use + for features like address space randomisation. The default is + ``on``. You will want to disable it if your trusted boot chain will + verify the DTB it is passed. It would be the responsibility of the + firmware to come up with a seed and pass it on if it wants to. + Linux guest kernel configuration """""""""""""""""""""""""""""""" diff --git a/hw/arm/virt.c b/hw/arm/virt.c index b45b52c90e..84c2444fff 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -247,11 +247,15 @@ static void create_fdt(VirtMachineState *vms) /* /chosen must exist for load_dtb to fill in necessary properties later */ qemu_fdt_add_subnode(fdt, "/chosen"); - create_kaslr_seed(ms, "/chosen"); + if (vms->dtb_kaslr_seed) { + create_kaslr_seed(ms, "/chosen"); + } if (vms->secure) { qemu_fdt_add_subnode(fdt, "/secure-chosen"); - create_kaslr_seed(ms, "/secure-chosen"); + if (vms->dtb_kaslr_seed) { + create_kaslr_seed(ms, "/secure-chosen"); + } } /* Clock node, for the benefit of the UART. The kernel device tree @@ -2235,6 +2239,20 @@ static void virt_set_its(Object *obj, bool value, Error **errp) vms->its = value; } +static bool virt_get_dtb_kaslr_seed(Object *obj, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + return vms->dtb_kaslr_seed; +} + +static void virt_set_dtb_kaslr_seed(Object *obj, bool value, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(obj); + + vms->dtb_kaslr_seed = value; +} + static char *virt_get_oem_id(Object *obj, Error **errp) { VirtMachineState *vms = VIRT_MACHINE(obj); @@ -2764,6 +2782,13 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) "Set on/off to enable/disable " "ITS instantiation"); + object_class_property_add_bool(oc, "dtb-kaslr-seed", + virt_get_dtb_kaslr_seed, + virt_set_dtb_kaslr_seed); + object_class_property_set_description(oc, "dtb-kaslr-seed", + "Set off to disable passing of kaslr-seed " + "dtb node to guest"); + object_class_property_add_str(oc, "x-oem-id", virt_get_oem_id, virt_set_oem_id); @@ -2828,6 +2853,9 @@ static void virt_instance_init(Object *obj) /* MTE is disabled by default. */ vms->mte = false; + /* Supply a kaslr-seed by default */ + vms->dtb_kaslr_seed = true; + vms->irqmap = a15irqmap; virt_flash_create(vms); diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index dc6b66ffc8..be0534608f 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -148,6 +148,7 @@ struct VirtMachineState { bool virt; bool ras; bool mte; + bool dtb_kaslr_seed; OnOffAuto acpi; VirtGICType gic_version; VirtIOMMUType iommu; From 92e28c03d6162d55b40f7052962067c021c90e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 5 Jan 2022 13:49:57 +0000 Subject: [PATCH 602/730] monitor: move x-query-profile into accel/tcg to fix build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As --enable-profiler isn't defended in CI we missed this breakage. Move the qmp handler into accel/tcg so we have access to the helpers we need. While we are at it ensure we gate the feature on CONFIG_TCG. Signed-off-by: Alex Bennée Suggested-by: Daniel P. Berrangé Reported-by: Mark Cave-Ayland Fixes: 37087fde0e ("qapi: introduce x-query-profile QMP command") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/773 Reviewed-by: Daniel P. Berrangé Tested-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220105135009.1584676-23-alex.bennee@linaro.org> --- accel/tcg/cpu-exec.c | 31 +++++++++++++++++++++++++++++++ hmp-commands-info.hx | 2 ++ monitor/qmp-cmds.c | 31 ------------------------------- qapi/machine.json | 1 + 4 files changed, 34 insertions(+), 31 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 409ec8c38c..8b4cd6c59d 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -1090,4 +1090,35 @@ HumanReadableText *qmp_x_query_opcount(Error **errp) return human_readable_text_from_str(buf); } +#ifdef CONFIG_PROFILER + +int64_t dev_time; + +HumanReadableText *qmp_x_query_profile(Error **errp) +{ + g_autoptr(GString) buf = g_string_new(""); + static int64_t last_cpu_exec_time; + int64_t cpu_exec_time; + int64_t delta; + + cpu_exec_time = tcg_cpu_exec_time(); + delta = cpu_exec_time - last_cpu_exec_time; + + g_string_append_printf(buf, "async time %" PRId64 " (%0.3f)\n", + dev_time, dev_time / (double)NANOSECONDS_PER_SECOND); + g_string_append_printf(buf, "qemu time %" PRId64 " (%0.3f)\n", + delta, delta / (double)NANOSECONDS_PER_SECOND); + last_cpu_exec_time = cpu_exec_time; + dev_time = 0; + + return human_readable_text_from_str(buf); +} +#else +HumanReadableText *qmp_x_query_profile(Error **errp) +{ + error_setg(errp, "Internal profiler not compiled"); + return NULL; +} +#endif + #endif /* !CONFIG_USER_ONLY */ diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index 407a1da800..e90f20a107 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -358,6 +358,7 @@ SRST Show host USB devices. ERST +#if defined(CONFIG_TCG) { .name = "profile", .args_type = "", @@ -365,6 +366,7 @@ ERST .help = "show profiling information", .cmd_info_hrt = qmp_x_query_profile, }, +#endif SRST ``info profile`` diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index 14e3beeaaf..db4d186448 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -368,37 +368,6 @@ void qmp_display_reload(DisplayReloadOptions *arg, Error **errp) } } -#ifdef CONFIG_PROFILER - -int64_t dev_time; - -HumanReadableText *qmp_x_query_profile(Error **errp) -{ - g_autoptr(GString) buf = g_string_new(""); - static int64_t last_cpu_exec_time; - int64_t cpu_exec_time; - int64_t delta; - - cpu_exec_time = tcg_cpu_exec_time(); - delta = cpu_exec_time - last_cpu_exec_time; - - g_string_append_printf(buf, "async time %" PRId64 " (%0.3f)\n", - dev_time, dev_time / (double)NANOSECONDS_PER_SECOND); - g_string_append_printf(buf, "qemu time %" PRId64 " (%0.3f)\n", - delta, delta / (double)NANOSECONDS_PER_SECOND); - last_cpu_exec_time = cpu_exec_time; - dev_time = 0; - - return human_readable_text_from_str(buf); -} -#else -HumanReadableText *qmp_x_query_profile(Error **errp) -{ - error_setg(errp, "Internal profiler not compiled"); - return NULL; -} -#endif - static int qmp_x_query_rdma_foreach(Object *obj, void *opaque) { RdmaProvider *rdma; diff --git a/qapi/machine.json b/qapi/machine.json index b6a37e17c4..c87c81b803 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1503,6 +1503,7 @@ ## { 'command': 'x-query-profile', 'returns': 'HumanReadableText', + 'if': 'CONFIG_TCG', 'features': [ 'unstable' ] } ## From a68e025bf5103280be6cfeab19452491b793e679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 5 Jan 2022 13:49:58 +0000 Subject: [PATCH 603/730] docs/devel: update C standard to C11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since 8a9d3d5640 (configure: Use -std=gnu11) we have allowed C11 code so lets reflect that in the style guide. Signed-off-by: Alex Bennée Reviewed-by: Daniel P. Berrangé Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220105135009.1584676-24-alex.bennee@linaro.org> --- docs/devel/style.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/devel/style.rst b/docs/devel/style.rst index 9c5c0fffd9..4f770002a7 100644 --- a/docs/devel/style.rst +++ b/docs/devel/style.rst @@ -483,11 +483,11 @@ of arguments. C standard, implementation defined and undefined behaviors ========================================================== -C code in QEMU should be written to the C99 language specification. A copy -of the final version of the C99 standard with corrigenda TC1, TC2, and TC3 -included, formatted as a draft, can be downloaded from: +C code in QEMU should be written to the C11 language specification. A +copy of the final version of the C11 standard formatted as a draft, +can be downloaded from: - ``_ + ``_ The C language specification defines regions of undefined behavior and implementation defined behavior (to give compiler authors enough leeway to From 3918fe16b0f8c6657928a14f41b7ff50061e33e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 5 Jan 2022 13:49:59 +0000 Subject: [PATCH 604/730] docs/devel: more documentation on the use of suffixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using _qemu is a little confusing. Let's use _compat for these sorts of things. We should also mention _impl which is another common suffix in the code base. Signed-off-by: Alex Bennée Reviewed-by: Daniel P. Berrangé Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220105135009.1584676-25-alex.bennee@linaro.org> --- docs/devel/style.rst | 6 ++++++ include/glib-compat.h | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/devel/style.rst b/docs/devel/style.rst index 4f770002a7..793a8d4280 100644 --- a/docs/devel/style.rst +++ b/docs/devel/style.rst @@ -151,6 +151,12 @@ If there are two versions of a function to be called with or without a lock held, the function that expects the lock to be already held usually uses the suffix ``_locked``. +If a function is a shim designed to deal with compatibility +workarounds we use the suffix ``_compat``. These are generally not +called directly and aliased to the plain function name via the +pre-processor. Another common suffix is ``_impl``; it is used for the +concrete implementation of a function that will not be called +directly, but rather through a macro or an inline function. Block structure =============== diff --git a/include/glib-compat.h b/include/glib-compat.h index 8d01a8c01f..3113a7d2af 100644 --- a/include/glib-compat.h +++ b/include/glib-compat.h @@ -46,9 +46,9 @@ * int g_foo(const char *wibble) * * We must define a static inline function with the same signature that does - * what we need, but with a "_qemu" suffix e.g. + * what we need, but with a "_compat" suffix e.g. * - * static inline void g_foo_qemu(const char *wibble) + * static inline void g_foo_compat(const char *wibble) * { * #if GLIB_CHECK_VERSION(X, Y, 0) * g_foo(wibble) @@ -61,7 +61,7 @@ * ensuring this wrapper function impl doesn't trigger the compiler warning * about using too new glib APIs. Finally we can do * - * #define g_foo(a) g_foo_qemu(a) + * #define g_foo(a) g_foo_compat(a) * * So now the code elsewhere in QEMU, which *does* have the * -Wdeprecated-declarations warning active, can call g_foo(...) as normal, From 11d3672788b48548811810bdc0f3f7969662572d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 13 Jan 2022 16:55:50 +0000 Subject: [PATCH 605/730] linux-user: expand reserved brk space for 64bit guests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A recent change to fix commpage allocation issues on 32bit hosts revealed another intermittent issue on s390x. The root cause was the headroom we give for the brk space wasn't enough causing the guest to attempt to map something on top of QEMUs own pages. We do not currently do anything to protect from this (see #555). By inspection the brk mmap moves around and top of the address range has been measured as far as 19Mb away from the top of the binary. As we chose a smallish number to keep 32bit on 32 bit feasible we only increase the gap for 64 bit guests. This does mean that 64-on-32 static binaries are more likely to fail to find a hole in the address space but that is hopefully a fairly rare situation. Signed-off-by: Alex Bennée Reviewed-by: Thomas Huth Message-Id: <20220113165550.4184455-1-alex.bennee@linaro.org> --- linux-user/elfload.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index d3274edfdb..fc23a6dcf6 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -2783,11 +2783,17 @@ static void load_elf_image(const char *image_name, int image_fd, * and the stack, lest they be placed immediately after * the data segment and block allocation from the brk. * - * 16MB is chosen as "large enough" without being so large - * as to allow the result to not fit with a 32-bit guest on - * a 32-bit host. + * 16MB is chosen as "large enough" without being so large as + * to allow the result to not fit with a 32-bit guest on a + * 32-bit host. However some 64 bit guests (e.g. s390x) + * attempt to place their heap further ahead and currently + * nothing stops them smashing into QEMUs address space. */ +#if TARGET_LONG_BITS == 64 + info->reserve_brk = 32 * MiB; +#else info->reserve_brk = 16 * MiB; +#endif hiaddr += info->reserve_brk; if (ehdr->e_type == ET_EXEC) { From e7588237ce8f8115b5ad9a3ecdd46f60d95a461a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 5 Jan 2022 13:50:00 +0000 Subject: [PATCH 606/730] linux-user/elfload: add extra logging for hole finding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The various approaches to finding memory holes are quite complicated to follow especially at a distance. Improve the logging so we can see exactly what method found the space for the guest memory. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Warner Losh Message-Id: <20220105135009.1584676-26-alex.bennee@linaro.org> --- linux-user/elfload.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index fc23a6dcf6..30dbb005c2 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -2267,6 +2267,9 @@ static void pgb_have_guest_base(const char *image_name, abi_ulong guest_loaddr, if (test != addr) { pgb_fail_in_use(image_name); } + qemu_log_mask(CPU_LOG_PAGE, + "%s: base @ %p for " TARGET_ABI_FMT_ld " bytes\n", + __func__, addr, guest_hiaddr - guest_loaddr); } /** @@ -2309,6 +2312,9 @@ static uintptr_t pgd_find_hole_fallback(uintptr_t guest_size, uintptr_t brk, if (mmap_start != MAP_FAILED) { munmap(mmap_start, guest_size); if (mmap_start == (void *) align_start) { + qemu_log_mask(CPU_LOG_PAGE, + "%s: base @ %p for %" PRIdPTR" bytes\n", + __func__, mmap_start + offset, guest_size); return (uintptr_t) mmap_start + offset; } } @@ -2388,6 +2394,12 @@ static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, } free_self_maps(maps); + if (ret != -1) { + qemu_log_mask(CPU_LOG_PAGE, "%s: base @ %" PRIxPTR + " for %" PRIuPTR " bytes\n", + __func__, ret, guest_size); + } + return ret; } @@ -2439,6 +2451,9 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr, } guest_base = addr; + + qemu_log_mask(CPU_LOG_PAGE, "%s: base @ %"PRIxPTR" for %" PRIuPTR" bytes\n", + __func__, addr, hiaddr - loaddr); } static void pgb_dynamic(const char *image_name, long align) @@ -2495,6 +2510,9 @@ static void pgb_reserved_va(const char *image_name, abi_ulong guest_loaddr, "using -R option)", reserved_va, test, strerror(errno)); exit(EXIT_FAILURE); } + + qemu_log_mask(CPU_LOG_PAGE, "%s: base @ %p for %lu bytes\n", + __func__, addr, reserved_va); } void probe_guest_base(const char *image_name, abi_ulong guest_loaddr, From 190674f3719d7a26387715952312f6397cddfaaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 5 Jan 2022 13:50:01 +0000 Subject: [PATCH 607/730] linux-user: don't adjust base of found hole MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pgb_find_hole function goes to the trouble of taking account of both mmap_min_addr and any offset we've applied to decide the starting address of a potential hole. This is especially important for emulating 32bit ARM in a 32bit build as we have applied the offset to ensure there will be space to map the ARM_COMMPAGE bellow the main guest map (using wrapped arithmetic). Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Resolves: https://gitlab.com/qemu-project/qemu/-/issues/690 Message-Id: <20220105135009.1584676-27-alex.bennee@linaro.org> --- linux-user/elfload.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 30dbb005c2..99829faf89 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -2339,8 +2339,7 @@ static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, brk = (uintptr_t)sbrk(0); if (!maps) { - ret = pgd_find_hole_fallback(guest_size, brk, align, offset); - return ret == -1 ? -1 : ret - guest_loaddr; + return pgd_find_hole_fallback(guest_size, brk, align, offset); } /* The first hole is before the first map entry. */ @@ -2380,7 +2379,7 @@ static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, /* Record the lowest successful match. */ if (ret < 0) { - ret = align_start - guest_loaddr; + ret = align_start; } /* If this hole contains the identity map, select it. */ if (align_start <= guest_loaddr && From 603bd9c25eba3c994a1ba681a641372d23eca5f0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 5 Jan 2022 13:50:03 +0000 Subject: [PATCH 608/730] tests/tcg/multiarch: Read fp flags before printf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to read the floating-point flags before printf may do other floating-point operations which may affect the flags. Hexagon reference files regenerated by Taylor Simpson. Signed-off-by: Taylor Simpson Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Alex Bennée Reviewed-by: Taylor Simpson Message-Id: <1639510781-3790-1-git-send-email-tsimpson@quicinc.com> Message-Id: <20211224035541.2159966-2-richard.henderson@linaro.org> Message-Id: <20220105135009.1584676-29-alex.bennee@linaro.org> --- tests/tcg/hexagon/float_convs.ref | 152 +++++++++++++++--------------- tests/tcg/hexagon/float_madds.ref | 48 +++++----- tests/tcg/multiarch/float_convs.c | 2 +- tests/tcg/multiarch/float_madds.c | 2 +- 4 files changed, 102 insertions(+), 102 deletions(-) diff --git a/tests/tcg/hexagon/float_convs.ref b/tests/tcg/hexagon/float_convs.ref index 9ec9ffc08d..a5505c337b 100644 --- a/tests/tcg/hexagon/float_convs.ref +++ b/tests/tcg/hexagon/float_convs.ref @@ -18,31 +18,31 @@ from single: f32(-inf:0xff800000) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) - to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (INEXACT ) + to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (OK) to int32: -2147483648 (INVALID) to int64: -9223372036854775808 (INVALID) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) - to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (INEXACT ) + to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (OK) to int32: -2147483648 (INVALID) to int64: -9223372036854775808 (INVALID) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) - to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (INEXACT ) + to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (OK) to int32: -2147483648 (INVALID) to int64: -9223372036854775808 (INVALID) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.31f75000000000000000p-40:0xab98fba8) - to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (INEXACT ) + to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.50544400000000000000p-66:0x9ea82a22) - to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (INEXACT ) + to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INVALID) @@ -72,19 +72,19 @@ from single: f32(0x1.00000000000000000000p-25:0x33000000) to uint32: 0 (INEXACT ) to uint64: 0 (INEXACT ) from single: f32(0x1.ffffe600000000000000p-25:0x337ffff3) - to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (INEXACT ) + to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INEXACT ) to uint64: 0 (INEXACT ) from single: f32(0x1.ff801a00000000000000p-15:0x387fc00d) - to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (INEXACT ) + to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INEXACT ) to uint64: 0 (INEXACT ) from single: f32(0x1.00000c00000000000000p-14:0x38800006) - to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (INEXACT ) + to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INEXACT ) @@ -96,7 +96,7 @@ from single: f32(0x1.00000000000000000000p+0:0x3f800000) to uint32: 1 (OK) to uint64: 1 (OK) from single: f32(0x1.00400000000000000000p+0:0x3f802000) - to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (INEXACT ) + to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (OK) to int32: 1 (INEXACT ) to int64: 1 (INEXACT ) to uint32: 1 (INEXACT ) @@ -108,61 +108,61 @@ from single: f32(0x1.00000000000000000000p+1:0x40000000) to uint32: 2 (OK) to uint64: 2 (OK) from single: f32(0x1.5bf0a800000000000000p+1:0x402df854) - to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (INEXACT ) + to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (OK) to int32: 2 (INEXACT ) to int64: 2 (INEXACT ) to uint32: 2 (INEXACT ) to uint64: 2 (INEXACT ) from single: f32(0x1.921fb600000000000000p+1:0x40490fdb) - to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (INEXACT ) + to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (OK) to int32: 3 (INEXACT ) to int64: 3 (INEXACT ) to uint32: 3 (INEXACT ) to uint64: 3 (INEXACT ) from single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00) - to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (INEXACT ) + to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (OK) to int32: 65503 (OK) to int64: 65503 (OK) to uint32: 65503 (OK) to uint64: 65503 (OK) from single: f32(0x1.ffc00000000000000000p+15:0x477fe000) - to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (INEXACT ) + to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (OK) to int32: 65504 (OK) to int64: 65504 (OK) to uint32: 65504 (OK) to uint64: 65504 (OK) from single: f32(0x1.ffc20000000000000000p+15:0x477fe100) - to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (INEXACT ) + to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (OK) to int32: 65505 (OK) to int64: 65505 (OK) to uint32: 65505 (OK) to uint64: 65505 (OK) from single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) - to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (INEXACT ) + to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (OK) to int32: 131007 (OK) to int64: 131007 (OK) to uint32: 131007 (OK) to uint64: 131007 (OK) from single: f32(0x1.ffc00000000000000000p+16:0x47ffe000) - to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (INEXACT ) + to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (OK) to int32: 131008 (OK) to int64: 131008 (OK) to uint32: 131008 (OK) to uint64: 131008 (OK) from single: f32(0x1.ffc10000000000000000p+16:0x47ffe080) - to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (INEXACT ) + to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (OK) to int32: 131009 (OK) to int64: 131009 (OK) to uint32: 131009 (OK) to uint64: 131009 (OK) from single: f32(0x1.c0bab600000000000000p+99:0x71605d5b) - to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (INEXACT ) + to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (OK) to int32: 2147483647 (INVALID) to int64: 9223372036854775807 (INVALID) to uint32: -1 (INVALID) to uint64: -1 (INVALID) from single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) - to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (INEXACT ) + to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (OK) to int32: 2147483647 (INVALID) to int64: 9223372036854775807 (INVALID) to uint32: -1 (INVALID) @@ -205,31 +205,31 @@ from single: f32(-inf:0xff800000) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) - to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (INEXACT ) + to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (OK) to int32: -2147483648 (INVALID) to int64: -9223372036854775808 (INVALID) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) - to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (INEXACT ) + to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (OK) to int32: -2147483648 (INVALID) to int64: -9223372036854775808 (INVALID) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) - to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (INEXACT ) + to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (OK) to int32: -2147483648 (INVALID) to int64: -9223372036854775808 (INVALID) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.31f75000000000000000p-40:0xab98fba8) - to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (INEXACT ) + to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.50544400000000000000p-66:0x9ea82a22) - to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (INEXACT ) + to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INVALID) @@ -259,19 +259,19 @@ from single: f32(0x1.00000000000000000000p-25:0x33000000) to uint32: 0 (INEXACT ) to uint64: 0 (INEXACT ) from single: f32(0x1.ffffe600000000000000p-25:0x337ffff3) - to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (INEXACT ) + to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INEXACT ) to uint64: 0 (INEXACT ) from single: f32(0x1.ff801a00000000000000p-15:0x387fc00d) - to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (INEXACT ) + to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INEXACT ) to uint64: 0 (INEXACT ) from single: f32(0x1.00000c00000000000000p-14:0x38800006) - to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (INEXACT ) + to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INEXACT ) @@ -283,7 +283,7 @@ from single: f32(0x1.00000000000000000000p+0:0x3f800000) to uint32: 1 (OK) to uint64: 1 (OK) from single: f32(0x1.00400000000000000000p+0:0x3f802000) - to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (INEXACT ) + to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (OK) to int32: 1 (INEXACT ) to int64: 1 (INEXACT ) to uint32: 1 (INEXACT ) @@ -295,61 +295,61 @@ from single: f32(0x1.00000000000000000000p+1:0x40000000) to uint32: 2 (OK) to uint64: 2 (OK) from single: f32(0x1.5bf0a800000000000000p+1:0x402df854) - to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (INEXACT ) + to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (OK) to int32: 2 (INEXACT ) to int64: 2 (INEXACT ) to uint32: 2 (INEXACT ) to uint64: 2 (INEXACT ) from single: f32(0x1.921fb600000000000000p+1:0x40490fdb) - to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (INEXACT ) + to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (OK) to int32: 3 (INEXACT ) to int64: 3 (INEXACT ) to uint32: 3 (INEXACT ) to uint64: 3 (INEXACT ) from single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00) - to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (INEXACT ) + to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (OK) to int32: 65503 (OK) to int64: 65503 (OK) to uint32: 65503 (OK) to uint64: 65503 (OK) from single: f32(0x1.ffc00000000000000000p+15:0x477fe000) - to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (INEXACT ) + to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (OK) to int32: 65504 (OK) to int64: 65504 (OK) to uint32: 65504 (OK) to uint64: 65504 (OK) from single: f32(0x1.ffc20000000000000000p+15:0x477fe100) - to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (INEXACT ) + to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (OK) to int32: 65505 (OK) to int64: 65505 (OK) to uint32: 65505 (OK) to uint64: 65505 (OK) from single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) - to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (INEXACT ) + to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (OK) to int32: 131007 (OK) to int64: 131007 (OK) to uint32: 131007 (OK) to uint64: 131007 (OK) from single: f32(0x1.ffc00000000000000000p+16:0x47ffe000) - to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (INEXACT ) + to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (OK) to int32: 131008 (OK) to int64: 131008 (OK) to uint32: 131008 (OK) to uint64: 131008 (OK) from single: f32(0x1.ffc10000000000000000p+16:0x47ffe080) - to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (INEXACT ) + to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (OK) to int32: 131009 (OK) to int64: 131009 (OK) to uint32: 131009 (OK) to uint64: 131009 (OK) from single: f32(0x1.c0bab600000000000000p+99:0x71605d5b) - to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (INEXACT ) + to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (OK) to int32: 2147483647 (INVALID) to int64: 9223372036854775807 (INVALID) to uint32: -1 (INVALID) to uint64: -1 (INVALID) from single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) - to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (INEXACT ) + to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (OK) to int32: 2147483647 (INVALID) to int64: 9223372036854775807 (INVALID) to uint32: -1 (INVALID) @@ -392,31 +392,31 @@ from single: f32(-inf:0xff800000) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) - to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (INEXACT ) + to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (OK) to int32: -2147483648 (INVALID) to int64: -9223372036854775808 (INVALID) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) - to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (INEXACT ) + to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (OK) to int32: -2147483648 (INVALID) to int64: -9223372036854775808 (INVALID) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) - to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (INEXACT ) + to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (OK) to int32: -2147483648 (INVALID) to int64: -9223372036854775808 (INVALID) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.31f75000000000000000p-40:0xab98fba8) - to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (INEXACT ) + to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.50544400000000000000p-66:0x9ea82a22) - to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (INEXACT ) + to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INVALID) @@ -446,19 +446,19 @@ from single: f32(0x1.00000000000000000000p-25:0x33000000) to uint32: 0 (INEXACT ) to uint64: 0 (INEXACT ) from single: f32(0x1.ffffe600000000000000p-25:0x337ffff3) - to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (INEXACT ) + to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INEXACT ) to uint64: 0 (INEXACT ) from single: f32(0x1.ff801a00000000000000p-15:0x387fc00d) - to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (INEXACT ) + to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INEXACT ) to uint64: 0 (INEXACT ) from single: f32(0x1.00000c00000000000000p-14:0x38800006) - to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (INEXACT ) + to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INEXACT ) @@ -470,7 +470,7 @@ from single: f32(0x1.00000000000000000000p+0:0x3f800000) to uint32: 1 (OK) to uint64: 1 (OK) from single: f32(0x1.00400000000000000000p+0:0x3f802000) - to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (INEXACT ) + to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (OK) to int32: 1 (INEXACT ) to int64: 1 (INEXACT ) to uint32: 1 (INEXACT ) @@ -482,61 +482,61 @@ from single: f32(0x1.00000000000000000000p+1:0x40000000) to uint32: 2 (OK) to uint64: 2 (OK) from single: f32(0x1.5bf0a800000000000000p+1:0x402df854) - to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (INEXACT ) + to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (OK) to int32: 2 (INEXACT ) to int64: 2 (INEXACT ) to uint32: 2 (INEXACT ) to uint64: 2 (INEXACT ) from single: f32(0x1.921fb600000000000000p+1:0x40490fdb) - to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (INEXACT ) + to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (OK) to int32: 3 (INEXACT ) to int64: 3 (INEXACT ) to uint32: 3 (INEXACT ) to uint64: 3 (INEXACT ) from single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00) - to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (INEXACT ) + to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (OK) to int32: 65503 (OK) to int64: 65503 (OK) to uint32: 65503 (OK) to uint64: 65503 (OK) from single: f32(0x1.ffc00000000000000000p+15:0x477fe000) - to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (INEXACT ) + to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (OK) to int32: 65504 (OK) to int64: 65504 (OK) to uint32: 65504 (OK) to uint64: 65504 (OK) from single: f32(0x1.ffc20000000000000000p+15:0x477fe100) - to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (INEXACT ) + to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (OK) to int32: 65505 (OK) to int64: 65505 (OK) to uint32: 65505 (OK) to uint64: 65505 (OK) from single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) - to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (INEXACT ) + to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (OK) to int32: 131007 (OK) to int64: 131007 (OK) to uint32: 131007 (OK) to uint64: 131007 (OK) from single: f32(0x1.ffc00000000000000000p+16:0x47ffe000) - to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (INEXACT ) + to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (OK) to int32: 131008 (OK) to int64: 131008 (OK) to uint32: 131008 (OK) to uint64: 131008 (OK) from single: f32(0x1.ffc10000000000000000p+16:0x47ffe080) - to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (INEXACT ) + to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (OK) to int32: 131009 (OK) to int64: 131009 (OK) to uint32: 131009 (OK) to uint64: 131009 (OK) from single: f32(0x1.c0bab600000000000000p+99:0x71605d5b) - to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (INEXACT ) + to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (OK) to int32: 2147483647 (INVALID) to int64: 9223372036854775807 (INVALID) to uint32: -1 (INVALID) to uint64: -1 (INVALID) from single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) - to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (INEXACT ) + to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (OK) to int32: 2147483647 (INVALID) to int64: 9223372036854775807 (INVALID) to uint32: -1 (INVALID) @@ -579,31 +579,31 @@ from single: f32(-inf:0xff800000) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) - to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (INEXACT ) + to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (OK) to int32: -2147483648 (INVALID) to int64: -9223372036854775808 (INVALID) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) - to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (INEXACT ) + to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (OK) to int32: -2147483648 (INVALID) to int64: -9223372036854775808 (INVALID) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) - to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (INEXACT ) + to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (OK) to int32: -2147483648 (INVALID) to int64: -9223372036854775808 (INVALID) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.31f75000000000000000p-40:0xab98fba8) - to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (INEXACT ) + to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INVALID) to uint64: 0 (INVALID) from single: f32(-0x1.50544400000000000000p-66:0x9ea82a22) - to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (INEXACT ) + to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INVALID) @@ -633,19 +633,19 @@ from single: f32(0x1.00000000000000000000p-25:0x33000000) to uint32: 0 (INEXACT ) to uint64: 0 (INEXACT ) from single: f32(0x1.ffffe600000000000000p-25:0x337ffff3) - to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (INEXACT ) + to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INEXACT ) to uint64: 0 (INEXACT ) from single: f32(0x1.ff801a00000000000000p-15:0x387fc00d) - to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (INEXACT ) + to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INEXACT ) to uint64: 0 (INEXACT ) from single: f32(0x1.00000c00000000000000p-14:0x38800006) - to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (INEXACT ) + to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (OK) to int32: 0 (INEXACT ) to int64: 0 (INEXACT ) to uint32: 0 (INEXACT ) @@ -657,7 +657,7 @@ from single: f32(0x1.00000000000000000000p+0:0x3f800000) to uint32: 1 (OK) to uint64: 1 (OK) from single: f32(0x1.00400000000000000000p+0:0x3f802000) - to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (INEXACT ) + to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (OK) to int32: 1 (INEXACT ) to int64: 1 (INEXACT ) to uint32: 1 (INEXACT ) @@ -669,61 +669,61 @@ from single: f32(0x1.00000000000000000000p+1:0x40000000) to uint32: 2 (OK) to uint64: 2 (OK) from single: f32(0x1.5bf0a800000000000000p+1:0x402df854) - to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (INEXACT ) + to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (OK) to int32: 2 (INEXACT ) to int64: 2 (INEXACT ) to uint32: 2 (INEXACT ) to uint64: 2 (INEXACT ) from single: f32(0x1.921fb600000000000000p+1:0x40490fdb) - to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (INEXACT ) + to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (OK) to int32: 3 (INEXACT ) to int64: 3 (INEXACT ) to uint32: 3 (INEXACT ) to uint64: 3 (INEXACT ) from single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00) - to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (INEXACT ) + to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (OK) to int32: 65503 (OK) to int64: 65503 (OK) to uint32: 65503 (OK) to uint64: 65503 (OK) from single: f32(0x1.ffc00000000000000000p+15:0x477fe000) - to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (INEXACT ) + to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (OK) to int32: 65504 (OK) to int64: 65504 (OK) to uint32: 65504 (OK) to uint64: 65504 (OK) from single: f32(0x1.ffc20000000000000000p+15:0x477fe100) - to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (INEXACT ) + to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (OK) to int32: 65505 (OK) to int64: 65505 (OK) to uint32: 65505 (OK) to uint64: 65505 (OK) from single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) - to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (INEXACT ) + to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (OK) to int32: 131007 (OK) to int64: 131007 (OK) to uint32: 131007 (OK) to uint64: 131007 (OK) from single: f32(0x1.ffc00000000000000000p+16:0x47ffe000) - to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (INEXACT ) + to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (OK) to int32: 131008 (OK) to int64: 131008 (OK) to uint32: 131008 (OK) to uint64: 131008 (OK) from single: f32(0x1.ffc10000000000000000p+16:0x47ffe080) - to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (INEXACT ) + to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (OK) to int32: 131009 (OK) to int64: 131009 (OK) to uint32: 131009 (OK) to uint64: 131009 (OK) from single: f32(0x1.c0bab600000000000000p+99:0x71605d5b) - to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (INEXACT ) + to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (OK) to int32: 2147483647 (INVALID) to int64: 9223372036854775807 (INVALID) to uint32: -1 (INVALID) to uint64: -1 (INVALID) from single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) - to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (INEXACT ) + to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (OK) to int32: 2147483647 (INVALID) to int64: 9223372036854775807 (INVALID) to uint32: -1 (INVALID) diff --git a/tests/tcg/hexagon/float_madds.ref b/tests/tcg/hexagon/float_madds.ref index ceed3bbbfb..a08c616057 100644 --- a/tests/tcg/hexagon/float_madds.ref +++ b/tests/tcg/hexagon/float_madds.ref @@ -44,7 +44,7 @@ res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (6/2) op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000) res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (7/0) op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) -res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (7/1) +res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=OK (7/1) op : f32(0x0.00000000000000000000p+0:0000000000) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000) res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (7/2) op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000) @@ -90,15 +90,15 @@ res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/1) op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000) res: f32(0x1.00040200000000000000p+0:0x3f800201) flags=INEXACT (14/2) op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) -res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/0) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/0) op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.00000000000000000000p+0:0x3f800000) -res: f32(0x1.80400000000000000000p+1:0x40402000) flags=INEXACT (15/1) +res: f32(0x1.80400000000000000000p+1:0x40402000) flags=OK (15/1) op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000) -res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/2) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/2) op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854) -res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=INEXACT (16/0) +res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=OK (16/0) op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.00400000000000000000p+0:0x3f802000) -res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=INEXACT (16/1) +res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=OK (16/1) op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) res: f32(0x1.2e23d200000000000000p+2:0x409711e9) flags=INEXACT (16/2) op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb) @@ -236,7 +236,7 @@ res: f32(-0x1.50544200000000000000p-66:0x9ea82a21) flags=INEXACT (6/2) op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000) res: f32(0x1.00000000000000000000p-149:0x00000001) flags=UNDERFLOW INEXACT (7/0) op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) -res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (7/1) +res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=OK (7/1) op : f32(0x0.00000000000000000000p+0:0000000000) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000) res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (7/2) op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000) @@ -282,15 +282,15 @@ res: f32(0x1.00440200000000000000p+0:0x3f802201) flags=INEXACT (14/1) op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000) res: f32(0x1.00040200000000000000p+0:0x3f800201) flags=INEXACT (14/2) op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) -res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/0) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/0) op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.00000000000000000000p+0:0x3f800000) -res: f32(0x1.80400000000000000000p+1:0x40402000) flags=INEXACT (15/1) +res: f32(0x1.80400000000000000000p+1:0x40402000) flags=OK (15/1) op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000) -res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/2) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/2) op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854) -res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=INEXACT (16/0) +res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=OK (16/0) op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.00400000000000000000p+0:0x3f802000) -res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=INEXACT (16/1) +res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=OK (16/1) op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) res: f32(0x1.2e23d400000000000000p+2:0x409711ea) flags=INEXACT (16/2) op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb) @@ -428,7 +428,7 @@ res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (6/2) op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000) res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (7/0) op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) -res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (7/1) +res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=OK (7/1) op : f32(0x0.00000000000000000000p+0:0000000000) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000) res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (7/2) op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000) @@ -474,15 +474,15 @@ res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/1) op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000) res: f32(0x1.00040000000000000000p+0:0x3f800200) flags=INEXACT (14/2) op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) -res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/0) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/0) op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.00000000000000000000p+0:0x3f800000) -res: f32(0x1.80400000000000000000p+1:0x40402000) flags=INEXACT (15/1) +res: f32(0x1.80400000000000000000p+1:0x40402000) flags=OK (15/1) op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000) -res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/2) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/2) op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854) -res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=INEXACT (16/0) +res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=OK (16/0) op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.00400000000000000000p+0:0x3f802000) -res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=INEXACT (16/1) +res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=OK (16/1) op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) res: f32(0x1.2e23d200000000000000p+2:0x409711e9) flags=INEXACT (16/2) op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb) @@ -620,7 +620,7 @@ res: f32(-0x1.50544200000000000000p-66:0x9ea82a21) flags=INEXACT (6/2) op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000) res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (7/0) op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) -res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (7/1) +res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=OK (7/1) op : f32(0x0.00000000000000000000p+0:0000000000) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000) res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (7/2) op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000) @@ -666,15 +666,15 @@ res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/1) op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000) res: f32(0x1.00040000000000000000p+0:0x3f800200) flags=INEXACT (14/2) op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) -res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/0) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/0) op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.00000000000000000000p+0:0x3f800000) -res: f32(0x1.80400000000000000000p+1:0x40402000) flags=INEXACT (15/1) +res: f32(0x1.80400000000000000000p+1:0x40402000) flags=OK (15/1) op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000) -res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/2) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/2) op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854) -res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=INEXACT (16/0) +res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=OK (16/0) op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.00400000000000000000p+0:0x3f802000) -res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=INEXACT (16/1) +res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=OK (16/1) op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) res: f32(0x1.2e23d200000000000000p+2:0x409711e9) flags=INEXACT (16/2) op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb) diff --git a/tests/tcg/multiarch/float_convs.c b/tests/tcg/multiarch/float_convs.c index e9be75c2d5..2e4fa55324 100644 --- a/tests/tcg/multiarch/float_convs.c +++ b/tests/tcg/multiarch/float_convs.c @@ -51,8 +51,8 @@ static void convert_single_to_double(float input) output = input; - out_fmt = fmt_f64(output); flag_fmt = fmt_flags(); + out_fmt = fmt_f64(output); printf(" to double: %s (%s)\n", out_fmt, flag_fmt); free(out_fmt); free(flag_fmt); diff --git a/tests/tcg/multiarch/float_madds.c b/tests/tcg/multiarch/float_madds.c index e422608ccd..4888f8641f 100644 --- a/tests/tcg/multiarch/float_madds.c +++ b/tests/tcg/multiarch/float_madds.c @@ -54,8 +54,8 @@ static void print_result(float r, int j, int k) { char *r_fmt, *flag_fmt; - r_fmt = fmt_f32(r); flag_fmt = fmt_flags(); + r_fmt = fmt_f32(r); printf("res: %s flags=%s (%d/%d)\n", r_fmt, flag_fmt, j, k); From 3118bfbf07068c6488ce30e3ac6d2a639d2e1312 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 5 Jan 2022 13:50:04 +0000 Subject: [PATCH 609/730] test/tcg/ppc64le: Add float reference files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated on Power9, PowerNV 9006-22P. Signed-off-by: Richard Henderson Signed-off-by: Alex Bennée Message-Id: <20211224035541.2159966-3-richard.henderson@linaro.org> Message-Id: <20220105135009.1584676-30-alex.bennee@linaro.org> --- tests/tcg/ppc64le/float_convs.ref | 748 +++++++++++++++++++++++++++++ tests/tcg/ppc64le/float_madds.ref | 768 ++++++++++++++++++++++++++++++ 2 files changed, 1516 insertions(+) create mode 100644 tests/tcg/ppc64le/float_convs.ref create mode 100644 tests/tcg/ppc64le/float_madds.ref diff --git a/tests/tcg/ppc64le/float_convs.ref b/tests/tcg/ppc64le/float_convs.ref new file mode 100644 index 0000000000..6e6f636834 --- /dev/null +++ b/tests/tcg/ppc64le/float_convs.ref @@ -0,0 +1,748 @@ +### Rounding to nearest +from single: f32(-nan:0xffa00000) + to double: f64(-nan:0x00fff4000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-nan:0xffc00000) + to double: f64(-nan:0x00fff8000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-inf:0xff800000) + to double: f64(-inf:0x00fff0000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.31f75000000000000000p-40:0xab98fba8) + to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(-0x1.50544400000000000000p-66:0x9ea82a22) + to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(-0x1.00000000000000000000p-126:0x80800000) + to double: f64(-0x1.00000000000000000000p-126:0x00b810000000000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x0.00000000000000000000p+0:0000000000) + to double: f64(0x0.00000000000000000000p+0:00000000000000000000) (OK) + to int32: 0 (OK) + to int64: 0 (OK) + to uint32: 0 (OK) + to uint64: 0 (OK) +from single: f32(0x1.00000000000000000000p-126:0x00800000) + to double: f64(0x1.00000000000000000000p-126:0x003810000000000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.00000000000000000000p-25:0x33000000) + to double: f64(0x1.00000000000000000000p-25:0x003e60000000000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.ffffe600000000000000p-25:0x337ffff3) + to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.ff801a00000000000000p-15:0x387fc00d) + to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.00000c00000000000000p-14:0x38800006) + to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.00000000000000000000p+0:0x3f800000) + to double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) (OK) + to int32: 1 (OK) + to int64: 1 (OK) + to uint32: 1 (OK) + to uint64: 1 (OK) +from single: f32(0x1.00400000000000000000p+0:0x3f802000) + to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (OK) + to int32: 1 (INEXACT ) + to int64: 1 (INEXACT ) + to uint32: 1 (INEXACT ) + to uint64: 1 (INEXACT ) +from single: f32(0x1.00000000000000000000p+1:0x40000000) + to double: f64(0x1.00000000000000000000p+1:0x004000000000000000) (OK) + to int32: 2 (OK) + to int64: 2 (OK) + to uint32: 2 (OK) + to uint64: 2 (OK) +from single: f32(0x1.5bf0a800000000000000p+1:0x402df854) + to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (OK) + to int32: 2 (INEXACT ) + to int64: 2 (INEXACT ) + to uint32: 2 (INEXACT ) + to uint64: 2 (INEXACT ) +from single: f32(0x1.921fb600000000000000p+1:0x40490fdb) + to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (OK) + to int32: 3 (INEXACT ) + to int64: 3 (INEXACT ) + to uint32: 3 (INEXACT ) + to uint64: 3 (INEXACT ) +from single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (OK) + to int32: 65503 (OK) + to int64: 65503 (OK) + to uint32: 65503 (OK) + to uint64: 65503 (OK) +from single: f32(0x1.ffc00000000000000000p+15:0x477fe000) + to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (OK) + to int32: 65504 (OK) + to int64: 65504 (OK) + to uint32: 65504 (OK) + to uint64: 65504 (OK) +from single: f32(0x1.ffc20000000000000000p+15:0x477fe100) + to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (OK) + to int32: 65505 (OK) + to int64: 65505 (OK) + to uint32: 65505 (OK) + to uint64: 65505 (OK) +from single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (OK) + to int32: 131007 (OK) + to int64: 131007 (OK) + to uint32: 131007 (OK) + to uint64: 131007 (OK) +from single: f32(0x1.ffc00000000000000000p+16:0x47ffe000) + to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (OK) + to int32: 131008 (OK) + to int64: 131008 (OK) + to uint32: 131008 (OK) + to uint64: 131008 (OK) +from single: f32(0x1.ffc10000000000000000p+16:0x47ffe080) + to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (OK) + to int32: 131009 (OK) + to int64: 131009 (OK) + to uint32: 131009 (OK) + to uint64: 131009 (OK) +from single: f32(0x1.c0bab600000000000000p+99:0x71605d5b) + to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from single: f32(inf:0x7f800000) + to double: f64(inf:0x007ff0000000000000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from single: f32(nan:0x7fc00000) + to double: f64(nan:0x007ff8000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(nan:0x7fa00000) + to double: f64(nan:0x007ff4000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +### Rounding upwards +from single: f32(-nan:0xffa00000) + to double: f64(-nan:0x00fff4000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-nan:0xffc00000) + to double: f64(-nan:0x00fff8000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-inf:0xff800000) + to double: f64(-inf:0x00fff0000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.31f75000000000000000p-40:0xab98fba8) + to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(-0x1.50544400000000000000p-66:0x9ea82a22) + to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(-0x1.00000000000000000000p-126:0x80800000) + to double: f64(-0x1.00000000000000000000p-126:0x00b810000000000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x0.00000000000000000000p+0:0000000000) + to double: f64(0x0.00000000000000000000p+0:00000000000000000000) (OK) + to int32: 0 (OK) + to int64: 0 (OK) + to uint32: 0 (OK) + to uint64: 0 (OK) +from single: f32(0x1.00000000000000000000p-126:0x00800000) + to double: f64(0x1.00000000000000000000p-126:0x003810000000000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.00000000000000000000p-25:0x33000000) + to double: f64(0x1.00000000000000000000p-25:0x003e60000000000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.ffffe600000000000000p-25:0x337ffff3) + to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.ff801a00000000000000p-15:0x387fc00d) + to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.00000c00000000000000p-14:0x38800006) + to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.00000000000000000000p+0:0x3f800000) + to double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) (OK) + to int32: 1 (OK) + to int64: 1 (OK) + to uint32: 1 (OK) + to uint64: 1 (OK) +from single: f32(0x1.00400000000000000000p+0:0x3f802000) + to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (OK) + to int32: 1 (INEXACT ) + to int64: 1 (INEXACT ) + to uint32: 1 (INEXACT ) + to uint64: 1 (INEXACT ) +from single: f32(0x1.00000000000000000000p+1:0x40000000) + to double: f64(0x1.00000000000000000000p+1:0x004000000000000000) (OK) + to int32: 2 (OK) + to int64: 2 (OK) + to uint32: 2 (OK) + to uint64: 2 (OK) +from single: f32(0x1.5bf0a800000000000000p+1:0x402df854) + to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (OK) + to int32: 2 (INEXACT ) + to int64: 2 (INEXACT ) + to uint32: 2 (INEXACT ) + to uint64: 2 (INEXACT ) +from single: f32(0x1.921fb600000000000000p+1:0x40490fdb) + to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (OK) + to int32: 3 (INEXACT ) + to int64: 3 (INEXACT ) + to uint32: 3 (INEXACT ) + to uint64: 3 (INEXACT ) +from single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (OK) + to int32: 65503 (OK) + to int64: 65503 (OK) + to uint32: 65503 (OK) + to uint64: 65503 (OK) +from single: f32(0x1.ffc00000000000000000p+15:0x477fe000) + to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (OK) + to int32: 65504 (OK) + to int64: 65504 (OK) + to uint32: 65504 (OK) + to uint64: 65504 (OK) +from single: f32(0x1.ffc20000000000000000p+15:0x477fe100) + to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (OK) + to int32: 65505 (OK) + to int64: 65505 (OK) + to uint32: 65505 (OK) + to uint64: 65505 (OK) +from single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (OK) + to int32: 131007 (OK) + to int64: 131007 (OK) + to uint32: 131007 (OK) + to uint64: 131007 (OK) +from single: f32(0x1.ffc00000000000000000p+16:0x47ffe000) + to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (OK) + to int32: 131008 (OK) + to int64: 131008 (OK) + to uint32: 131008 (OK) + to uint64: 131008 (OK) +from single: f32(0x1.ffc10000000000000000p+16:0x47ffe080) + to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (OK) + to int32: 131009 (OK) + to int64: 131009 (OK) + to uint32: 131009 (OK) + to uint64: 131009 (OK) +from single: f32(0x1.c0bab600000000000000p+99:0x71605d5b) + to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from single: f32(inf:0x7f800000) + to double: f64(inf:0x007ff0000000000000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from single: f32(nan:0x7fc00000) + to double: f64(nan:0x007ff8000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(nan:0x7fa00000) + to double: f64(nan:0x007ff4000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +### Rounding downwards +from single: f32(-nan:0xffa00000) + to double: f64(-nan:0x00fff4000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-nan:0xffc00000) + to double: f64(-nan:0x00fff8000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-inf:0xff800000) + to double: f64(-inf:0x00fff0000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.31f75000000000000000p-40:0xab98fba8) + to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(-0x1.50544400000000000000p-66:0x9ea82a22) + to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(-0x1.00000000000000000000p-126:0x80800000) + to double: f64(-0x1.00000000000000000000p-126:0x00b810000000000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x0.00000000000000000000p+0:0000000000) + to double: f64(0x0.00000000000000000000p+0:00000000000000000000) (OK) + to int32: 0 (OK) + to int64: 0 (OK) + to uint32: 0 (OK) + to uint64: 0 (OK) +from single: f32(0x1.00000000000000000000p-126:0x00800000) + to double: f64(0x1.00000000000000000000p-126:0x003810000000000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.00000000000000000000p-25:0x33000000) + to double: f64(0x1.00000000000000000000p-25:0x003e60000000000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.ffffe600000000000000p-25:0x337ffff3) + to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.ff801a00000000000000p-15:0x387fc00d) + to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.00000c00000000000000p-14:0x38800006) + to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.00000000000000000000p+0:0x3f800000) + to double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) (OK) + to int32: 1 (OK) + to int64: 1 (OK) + to uint32: 1 (OK) + to uint64: 1 (OK) +from single: f32(0x1.00400000000000000000p+0:0x3f802000) + to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (OK) + to int32: 1 (INEXACT ) + to int64: 1 (INEXACT ) + to uint32: 1 (INEXACT ) + to uint64: 1 (INEXACT ) +from single: f32(0x1.00000000000000000000p+1:0x40000000) + to double: f64(0x1.00000000000000000000p+1:0x004000000000000000) (OK) + to int32: 2 (OK) + to int64: 2 (OK) + to uint32: 2 (OK) + to uint64: 2 (OK) +from single: f32(0x1.5bf0a800000000000000p+1:0x402df854) + to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (OK) + to int32: 2 (INEXACT ) + to int64: 2 (INEXACT ) + to uint32: 2 (INEXACT ) + to uint64: 2 (INEXACT ) +from single: f32(0x1.921fb600000000000000p+1:0x40490fdb) + to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (OK) + to int32: 3 (INEXACT ) + to int64: 3 (INEXACT ) + to uint32: 3 (INEXACT ) + to uint64: 3 (INEXACT ) +from single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (OK) + to int32: 65503 (OK) + to int64: 65503 (OK) + to uint32: 65503 (OK) + to uint64: 65503 (OK) +from single: f32(0x1.ffc00000000000000000p+15:0x477fe000) + to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (OK) + to int32: 65504 (OK) + to int64: 65504 (OK) + to uint32: 65504 (OK) + to uint64: 65504 (OK) +from single: f32(0x1.ffc20000000000000000p+15:0x477fe100) + to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (OK) + to int32: 65505 (OK) + to int64: 65505 (OK) + to uint32: 65505 (OK) + to uint64: 65505 (OK) +from single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (OK) + to int32: 131007 (OK) + to int64: 131007 (OK) + to uint32: 131007 (OK) + to uint64: 131007 (OK) +from single: f32(0x1.ffc00000000000000000p+16:0x47ffe000) + to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (OK) + to int32: 131008 (OK) + to int64: 131008 (OK) + to uint32: 131008 (OK) + to uint64: 131008 (OK) +from single: f32(0x1.ffc10000000000000000p+16:0x47ffe080) + to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (OK) + to int32: 131009 (OK) + to int64: 131009 (OK) + to uint32: 131009 (OK) + to uint64: 131009 (OK) +from single: f32(0x1.c0bab600000000000000p+99:0x71605d5b) + to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from single: f32(inf:0x7f800000) + to double: f64(inf:0x007ff0000000000000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from single: f32(nan:0x7fc00000) + to double: f64(nan:0x007ff8000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(nan:0x7fa00000) + to double: f64(nan:0x007ff4000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +### Rounding to zero +from single: f32(-nan:0xffa00000) + to double: f64(-nan:0x00fff4000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-nan:0xffc00000) + to double: f64(-nan:0x00fff8000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-inf:0xff800000) + to double: f64(-inf:0x00fff0000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(-0x1.31f75000000000000000p-40:0xab98fba8) + to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(-0x1.50544400000000000000p-66:0x9ea82a22) + to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(-0x1.00000000000000000000p-126:0x80800000) + to double: f64(-0x1.00000000000000000000p-126:0x00b810000000000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x0.00000000000000000000p+0:0000000000) + to double: f64(0x0.00000000000000000000p+0:00000000000000000000) (OK) + to int32: 0 (OK) + to int64: 0 (OK) + to uint32: 0 (OK) + to uint64: 0 (OK) +from single: f32(0x1.00000000000000000000p-126:0x00800000) + to double: f64(0x1.00000000000000000000p-126:0x003810000000000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.00000000000000000000p-25:0x33000000) + to double: f64(0x1.00000000000000000000p-25:0x003e60000000000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.ffffe600000000000000p-25:0x337ffff3) + to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.ff801a00000000000000p-15:0x387fc00d) + to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.00000c00000000000000p-14:0x38800006) + to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from single: f32(0x1.00000000000000000000p+0:0x3f800000) + to double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) (OK) + to int32: 1 (OK) + to int64: 1 (OK) + to uint32: 1 (OK) + to uint64: 1 (OK) +from single: f32(0x1.00400000000000000000p+0:0x3f802000) + to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (OK) + to int32: 1 (INEXACT ) + to int64: 1 (INEXACT ) + to uint32: 1 (INEXACT ) + to uint64: 1 (INEXACT ) +from single: f32(0x1.00000000000000000000p+1:0x40000000) + to double: f64(0x1.00000000000000000000p+1:0x004000000000000000) (OK) + to int32: 2 (OK) + to int64: 2 (OK) + to uint32: 2 (OK) + to uint64: 2 (OK) +from single: f32(0x1.5bf0a800000000000000p+1:0x402df854) + to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (OK) + to int32: 2 (INEXACT ) + to int64: 2 (INEXACT ) + to uint32: 2 (INEXACT ) + to uint64: 2 (INEXACT ) +from single: f32(0x1.921fb600000000000000p+1:0x40490fdb) + to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (OK) + to int32: 3 (INEXACT ) + to int64: 3 (INEXACT ) + to uint32: 3 (INEXACT ) + to uint64: 3 (INEXACT ) +from single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (OK) + to int32: 65503 (OK) + to int64: 65503 (OK) + to uint32: 65503 (OK) + to uint64: 65503 (OK) +from single: f32(0x1.ffc00000000000000000p+15:0x477fe000) + to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (OK) + to int32: 65504 (OK) + to int64: 65504 (OK) + to uint32: 65504 (OK) + to uint64: 65504 (OK) +from single: f32(0x1.ffc20000000000000000p+15:0x477fe100) + to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (OK) + to int32: 65505 (OK) + to int64: 65505 (OK) + to uint32: 65505 (OK) + to uint64: 65505 (OK) +from single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (OK) + to int32: 131007 (OK) + to int64: 131007 (OK) + to uint32: 131007 (OK) + to uint64: 131007 (OK) +from single: f32(0x1.ffc00000000000000000p+16:0x47ffe000) + to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (OK) + to int32: 131008 (OK) + to int64: 131008 (OK) + to uint32: 131008 (OK) + to uint64: 131008 (OK) +from single: f32(0x1.ffc10000000000000000p+16:0x47ffe080) + to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (OK) + to int32: 131009 (OK) + to int64: 131009 (OK) + to uint32: 131009 (OK) + to uint64: 131009 (OK) +from single: f32(0x1.c0bab600000000000000p+99:0x71605d5b) + to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from single: f32(inf:0x7f800000) + to double: f64(inf:0x007ff0000000000000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from single: f32(nan:0x7fc00000) + to double: f64(nan:0x007ff8000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from single: f32(nan:0x7fa00000) + to double: f64(nan:0x007ff4000000000000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) diff --git a/tests/tcg/ppc64le/float_madds.ref b/tests/tcg/ppc64le/float_madds.ref new file mode 100644 index 0000000000..e66917cb80 --- /dev/null +++ b/tests/tcg/ppc64le/float_madds.ref @@ -0,0 +1,768 @@ +### Rounding to nearest +op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(-inf:0xff800000) +res: f32(-nan:0xffe00000) flags=INVALID (0/0) +op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-nan:0xffa00000) +res: f32(-nan:0xffc00000) flags=INVALID (0/1) +op : f32(-inf:0xff800000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000) +res: f32(-nan:0xffc00000) flags=INVALID (0/2) +op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff) +res: f32(-nan:0xffc00000) flags=OK (1/0) +op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-nan:0xffc00000) +res: f32(-nan:0xffc00000) flags=OK (1/1) +op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-nan:0xffc00000) + f32(-inf:0xff800000) +res: f32(-nan:0xffc00000) flags=OK (1/2) +op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59) +res: f32(inf:0x7f800000) flags=OK (2/0) +op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-inf:0xff800000) +res: f32(-inf:0xff800000) flags=OK (2/1) +op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff) +res: f32(inf:0x7f800000) flags=OK (2/2) +op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (3/0) +op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (3/1) +op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (3/2) +op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (4/0) +op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59) +res: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) flags=INEXACT (4/1) +op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) +res: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) flags=INEXACT (4/2) +op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) +res: f32(0x1.0c27fa00000000000000p+60:0x5d8613fd) flags=INEXACT (5/0) +op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) +res: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) flags=INEXACT (5/1) +op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8) +res: f32(0x1.26c46200000000000000p+34:0x50936231) flags=INEXACT (5/2) +op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000) +res: f32(0x1.91f94000000000000000p-106:0x0ac8fca0) flags=INEXACT (6/0) +op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(-0x1.31f75000000000000000p-40:0xab98fba8) +res: f32(-0x1.31f75000000000000000p-40:0xab98fba8) flags=INEXACT (6/1) +op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) +res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (6/2) +op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (7/0) +op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) +res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=OK (7/1) +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000) +res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (7/2) +op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000) +res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (8/0) +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(-0x1.00000000000000000000p-126:0x80800000) +res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (8/1) +op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(-0x0.00000000000000000000p+0:0x80000000) flags=UNDERFLOW INEXACT (8/2) +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000) +res: f32(0x1.00000000000000000000p-25:0x33000000) flags=OK (9/0) +op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (9/1) +op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000) +res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (9/2) +op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3) +res: f32(0x1.ffffe600000000000000p-25:0x337ffff3) flags=INEXACT (10/0) +op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.00000000000000000000p-126:0x00800000) +res: f32(0x1.ffffe600000000000000p-50:0x26fffff3) flags=INEXACT (10/1) +op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000) +res: f32(0x1.00000000000000000000p-25:0x33000000) flags=INEXACT (10/2) +op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d) +res: f32(0x1.ff801a00000000000000p-15:0x387fc00d) flags=INEXACT (11/0) +op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000000000000000000p-25:0x33000000) +res: f32(0x1.0007fe00000000000000p-25:0x330003ff) flags=INEXACT (11/1) +op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3) +res: f32(0x1.0001f200000000000000p-24:0x338000f9) flags=INEXACT (11/2) +op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006) +res: f32(0x1.00000c00000000000000p-14:0x38800006) flags=INEXACT (12/0) +op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.ffffe600000000000000p-25:0x337ffff3) +res: f32(0x1.0ffbf400000000000000p-24:0x3387fdfa) flags=INEXACT (12/1) +op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d) +res: f32(0x1.ff801c00000000000000p-15:0x387fc00e) flags=INEXACT (12/2) +op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000) +res: f32(0x1.00000000000000000000p+0:0x3f800000) flags=INEXACT (13/0) +op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.ff801a00000000000000p-15:0x387fc00d) +res: f32(0x1.ffc01800000000000000p-14:0x38ffe00c) flags=INEXACT (13/1) +op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006) +res: f32(0x1.ffc01800000000000000p-14:0x38ffe00c) flags=INEXACT (13/2) +op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000) +res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/0) +op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000c00000000000000p-14:0x38800006) +res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/1) +op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000) +res: f32(0x1.00040200000000000000p+0:0x3f800201) flags=INEXACT (14/2) +op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/0) +op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.00000000000000000000p+0:0x3f800000) +res: f32(0x1.80400000000000000000p+1:0x40402000) flags=OK (15/1) +op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/2) +op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854) +res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=OK (16/0) +op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.00400000000000000000p+0:0x3f802000) +res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=OK (16/1) +op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) +res: f32(0x1.2e23d200000000000000p+2:0x409711e9) flags=INEXACT (16/2) +op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb) +res: f32(0x1.12804200000000000000p+3:0x41094021) flags=INEXACT (17/0) +op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.00000000000000000000p+1:0x40000000) +res: f32(0x1.51458000000000000000p+3:0x4128a2c0) flags=INEXACT (17/1) +op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854) +res: f32(0x1.200c0400000000000000p+3:0x41100602) flags=INEXACT (17/2) +op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00) +res: f32(0x1.ffcf1400000000000000p+15:0x477fe78a) flags=INEXACT (18/0) +op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.5bf0a800000000000000p+1:0x402df854) +res: f32(0x1.91ed3c00000000000000p+17:0x4848f69e) flags=INEXACT (18/1) +op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb) +res: f32(0x1.5bc56000000000000000p+17:0x482de2b0) flags=INEXACT (18/2) +op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000) +res: f32(0x1.08edf000000000000000p+18:0x488476f8) flags=INEXACT (19/0) +op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.921fb600000000000000p+1:0x40490fdb) +res: f32(0x1.ff7e0800000000000000p+31:0x4f7fbf04) flags=INEXACT (19/1) +op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00) +res: f32(0x1.08ee7a00000000000000p+18:0x4884773d) flags=INEXACT (19/2) +op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100) +res: f32(0x1.ff800800000000000000p+31:0x4f7fc004) flags=INEXACT (20/0) +op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00) +res: f32(0x1.ff840800000000000000p+31:0x4f7fc204) flags=INEXACT (20/1) +op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000) +res: f32(0x1.ff820800000000000000p+31:0x4f7fc104) flags=INEXACT (20/2) +op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) +res: f32(0x1.ff860800000000000000p+31:0x4f7fc304) flags=INEXACT (21/0) +op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+15:0x477fe000) +res: f32(0x1.ff820800000000000000p+32:0x4fffc104) flags=INEXACT (21/1) +op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100) +res: f32(0x1.ff800800000000000000p+32:0x4fffc004) flags=INEXACT (21/2) +op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000) +res: f32(0x1.ff830800000000000000p+32:0x4fffc184) flags=INEXACT (22/0) +op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100) +res: f32(0x1.ff7f8800000000000000p+33:0x507fbfc4) flags=INEXACT (22/1) +op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) +res: f32(0x1.ff840800000000000000p+32:0x4fffc204) flags=INEXACT (22/2) +op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080) +res: f32(0x1.ff800800000000000000p+33:0x507fc004) flags=INEXACT (23/0) +op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) +res: f32(0x1.ff820800000000000000p+33:0x507fc104) flags=INEXACT (23/1) +op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000) +res: f32(0x1.ff810800000000000000p+33:0x507fc084) flags=INEXACT (23/2) +op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b) +res: f32(0x1.c0bab600000000000000p+99:0x71605d5b) flags=INEXACT (24/0) +op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.ffc00000000000000000p+16:0x47ffe000) +res: f32(0x1.c0838000000000000000p+116:0x79e041c0) flags=INEXACT (24/1) +op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080) +res: f32(0x1.c0829e00000000000000p+116:0x79e0414f) flags=INEXACT (24/2) +op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (25/0) +op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(0x1.ffc10000000000000000p+16:0x47ffe080) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (25/1) +op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (25/2) +op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000) +res: f32(inf:0x7f800000) flags=OK (26/0) +op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(0x1.c0bab600000000000000p+99:0x71605d5b) +res: f32(inf:0x7f800000) flags=OK (26/1) +op : f32(inf:0x7f800000) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff) +res: f32(inf:0x7f800000) flags=OK (26/2) +op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(nan:0x7fc00000) +res: f32(nan:0x7fc00000) flags=OK (27/0) +op : f32(inf:0x7f800000) * f32(nan:0x7fc00000) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff) +res: f32(nan:0x7fc00000) flags=OK (27/1) +op : f32(nan:0x7fc00000) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000) +res: f32(nan:0x7fc00000) flags=OK (27/2) +op : f32(inf:0x7f800000) * f32(nan:0x7fc00000) + f32(nan:0x7fa00000) +res: f32(nan:0x7fe00000) flags=INVALID (28/0) +op : f32(nan:0x7fc00000) * f32(nan:0x7fa00000) + f32(inf:0x7f800000) +res: f32(nan:0x7fc00000) flags=INVALID (28/1) +op : f32(nan:0x7fa00000) * f32(inf:0x7f800000) + f32(nan:0x7fc00000) +res: f32(nan:0x7fe00000) flags=INVALID (28/2) +op : f32(nan:0x7fc00000) * f32(nan:0x7fa00000) + f32(-nan:0xffa00000) +res: f32(nan:0x7fc00000) flags=INVALID (29/0) +op : f32(nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(nan:0x7fc00000) +res: f32(nan:0x7fe00000) flags=INVALID (29/1) +op : f32(-nan:0xffa00000) * f32(nan:0x7fc00000) + f32(nan:0x7fa00000) +res: f32(-nan:0xffe00000) flags=INVALID (29/2) +op : f32(nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000) +res: f32(nan:0x7fe00000) flags=INVALID (30/0) +op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(nan:0x7fa00000) +res: f32(-nan:0xffe00000) flags=INVALID (30/1) +op : f32(-nan:0xffc00000) * f32(nan:0x7fa00000) + f32(-nan:0xffa00000) +res: f32(-nan:0xffc00000) flags=INVALID (30/2) +# LP184149 +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-1:0x3f000000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(0x0.00000000000000000000p+0:0000000000) flags=OK (31/0) +op : f32(0x1.00000000000000000000p-149:0x00000001) * f32(0x1.00000000000000000000p-149:0x00000001) + f32(0x1.00000000000000000000p-149:0x00000001) +res: f32(0x1.00000000000000000000p-149:0x00000001) flags=UNDERFLOW INEXACT (32/0) +### Rounding upwards +op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(-inf:0xff800000) +res: f32(-nan:0xffe00000) flags=INVALID (0/0) +op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-nan:0xffa00000) +res: f32(-nan:0xffc00000) flags=INVALID (0/1) +op : f32(-inf:0xff800000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000) +res: f32(-nan:0xffc00000) flags=INVALID (0/2) +op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff) +res: f32(-nan:0xffc00000) flags=OK (1/0) +op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-nan:0xffc00000) +res: f32(-nan:0xffc00000) flags=OK (1/1) +op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-nan:0xffc00000) + f32(-inf:0xff800000) +res: f32(-nan:0xffc00000) flags=OK (1/2) +op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59) +res: f32(inf:0x7f800000) flags=OK (2/0) +op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-inf:0xff800000) +res: f32(-inf:0xff800000) flags=OK (2/1) +op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff) +res: f32(inf:0x7f800000) flags=OK (2/2) +op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (3/0) +op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (3/1) +op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (3/2) +op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (4/0) +op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59) +res: f32(-0x1.1874b000000000000000p+103:0xf30c3a58) flags=INEXACT (4/1) +op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) +res: f32(-0x1.c0bab400000000000000p+99:0xf1605d5a) flags=INEXACT (4/2) +op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) +res: f32(0x1.0c27fa00000000000000p+60:0x5d8613fd) flags=INEXACT (5/0) +op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) +res: f32(-0x1.c0bab400000000000000p+99:0xf1605d5a) flags=INEXACT (5/1) +op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8) +res: f32(0x1.26c46200000000000000p+34:0x50936231) flags=INEXACT (5/2) +op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000) +res: f32(0x1.91f94000000000000000p-106:0x0ac8fca0) flags=INEXACT (6/0) +op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(-0x1.31f75000000000000000p-40:0xab98fba8) +res: f32(-0x1.31f74e00000000000000p-40:0xab98fba7) flags=INEXACT (6/1) +op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) +res: f32(-0x1.50544200000000000000p-66:0x9ea82a21) flags=INEXACT (6/2) +op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(0x1.00000000000000000000p-149:0x00000001) flags=UNDERFLOW INEXACT (7/0) +op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) +res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=OK (7/1) +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000) +res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (7/2) +op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000) +res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (8/0) +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(-0x1.00000000000000000000p-126:0x80800000) +res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (8/1) +op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(-0x0.00000000000000000000p+0:0x80000000) flags=UNDERFLOW INEXACT (8/2) +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000) +res: f32(0x1.00000000000000000000p-25:0x33000000) flags=OK (9/0) +op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(0x1.00000000000000000000p-149:0x00000001) flags=UNDERFLOW INEXACT (9/1) +op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000) +res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (9/2) +op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3) +res: f32(0x1.ffffe800000000000000p-25:0x337ffff4) flags=INEXACT (10/0) +op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.00000000000000000000p-126:0x00800000) +res: f32(0x1.ffffe800000000000000p-50:0x26fffff4) flags=INEXACT (10/1) +op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000) +res: f32(0x1.00000200000000000000p-25:0x33000001) flags=INEXACT (10/2) +op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d) +res: f32(0x1.ff801c00000000000000p-15:0x387fc00e) flags=INEXACT (11/0) +op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000000000000000000p-25:0x33000000) +res: f32(0x1.00080000000000000000p-25:0x33000400) flags=INEXACT (11/1) +op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3) +res: f32(0x1.0001f400000000000000p-24:0x338000fa) flags=INEXACT (11/2) +op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006) +res: f32(0x1.00000e00000000000000p-14:0x38800007) flags=INEXACT (12/0) +op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.ffffe600000000000000p-25:0x337ffff3) +res: f32(0x1.0ffbf600000000000000p-24:0x3387fdfb) flags=INEXACT (12/1) +op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d) +res: f32(0x1.ff801c00000000000000p-15:0x387fc00e) flags=INEXACT (12/2) +op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000) +res: f32(0x1.00000200000000000000p+0:0x3f800001) flags=INEXACT (13/0) +op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.ff801a00000000000000p-15:0x387fc00d) +res: f32(0x1.ffc01a00000000000000p-14:0x38ffe00d) flags=INEXACT (13/1) +op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006) +res: f32(0x1.ffc01a00000000000000p-14:0x38ffe00d) flags=INEXACT (13/2) +op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000) +res: f32(0x1.00440200000000000000p+0:0x3f802201) flags=INEXACT (14/0) +op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000c00000000000000p-14:0x38800006) +res: f32(0x1.00440200000000000000p+0:0x3f802201) flags=INEXACT (14/1) +op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000) +res: f32(0x1.00040200000000000000p+0:0x3f800201) flags=INEXACT (14/2) +op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/0) +op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.00000000000000000000p+0:0x3f800000) +res: f32(0x1.80400000000000000000p+1:0x40402000) flags=OK (15/1) +op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/2) +op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854) +res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=OK (16/0) +op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.00400000000000000000p+0:0x3f802000) +res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=OK (16/1) +op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) +res: f32(0x1.2e23d400000000000000p+2:0x409711ea) flags=INEXACT (16/2) +op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb) +res: f32(0x1.12804200000000000000p+3:0x41094021) flags=INEXACT (17/0) +op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.00000000000000000000p+1:0x40000000) +res: f32(0x1.51458200000000000000p+3:0x4128a2c1) flags=INEXACT (17/1) +op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854) +res: f32(0x1.200c0600000000000000p+3:0x41100603) flags=INEXACT (17/2) +op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00) +res: f32(0x1.ffcf1600000000000000p+15:0x477fe78b) flags=INEXACT (18/0) +op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.5bf0a800000000000000p+1:0x402df854) +res: f32(0x1.91ed3c00000000000000p+17:0x4848f69e) flags=INEXACT (18/1) +op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb) +res: f32(0x1.5bc56200000000000000p+17:0x482de2b1) flags=INEXACT (18/2) +op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000) +res: f32(0x1.08edf000000000000000p+18:0x488476f8) flags=INEXACT (19/0) +op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.921fb600000000000000p+1:0x40490fdb) +res: f32(0x1.ff7e0a00000000000000p+31:0x4f7fbf05) flags=INEXACT (19/1) +op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00) +res: f32(0x1.08ee7a00000000000000p+18:0x4884773d) flags=INEXACT (19/2) +op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100) +res: f32(0x1.ff800a00000000000000p+31:0x4f7fc005) flags=INEXACT (20/0) +op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00) +res: f32(0x1.ff840800000000000000p+31:0x4f7fc204) flags=INEXACT (20/1) +op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000) +res: f32(0x1.ff820800000000000000p+31:0x4f7fc104) flags=INEXACT (20/2) +op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) +res: f32(0x1.ff860800000000000000p+31:0x4f7fc304) flags=INEXACT (21/0) +op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+15:0x477fe000) +res: f32(0x1.ff820800000000000000p+32:0x4fffc104) flags=INEXACT (21/1) +op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100) +res: f32(0x1.ff800a00000000000000p+32:0x4fffc005) flags=INEXACT (21/2) +op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000) +res: f32(0x1.ff830800000000000000p+32:0x4fffc184) flags=INEXACT (22/0) +op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100) +res: f32(0x1.ff7f8a00000000000000p+33:0x507fbfc5) flags=INEXACT (22/1) +op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) +res: f32(0x1.ff840800000000000000p+32:0x4fffc204) flags=INEXACT (22/2) +op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080) +res: f32(0x1.ff800a00000000000000p+33:0x507fc005) flags=INEXACT (23/0) +op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) +res: f32(0x1.ff820800000000000000p+33:0x507fc104) flags=INEXACT (23/1) +op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000) +res: f32(0x1.ff810800000000000000p+33:0x507fc084) flags=INEXACT (23/2) +op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b) +res: f32(0x1.c0bab800000000000000p+99:0x71605d5c) flags=INEXACT (24/0) +op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.ffc00000000000000000p+16:0x47ffe000) +res: f32(0x1.c0838000000000000000p+116:0x79e041c0) flags=INEXACT (24/1) +op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080) +res: f32(0x1.c082a000000000000000p+116:0x79e04150) flags=INEXACT (24/2) +op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (25/0) +op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(0x1.ffc10000000000000000p+16:0x47ffe080) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (25/1) +op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b) +res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (25/2) +op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000) +res: f32(inf:0x7f800000) flags=OK (26/0) +op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(0x1.c0bab600000000000000p+99:0x71605d5b) +res: f32(inf:0x7f800000) flags=OK (26/1) +op : f32(inf:0x7f800000) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff) +res: f32(inf:0x7f800000) flags=OK (26/2) +op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(nan:0x7fc00000) +res: f32(nan:0x7fc00000) flags=OK (27/0) +op : f32(inf:0x7f800000) * f32(nan:0x7fc00000) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff) +res: f32(nan:0x7fc00000) flags=OK (27/1) +op : f32(nan:0x7fc00000) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000) +res: f32(nan:0x7fc00000) flags=OK (27/2) +op : f32(inf:0x7f800000) * f32(nan:0x7fc00000) + f32(nan:0x7fa00000) +res: f32(nan:0x7fe00000) flags=INVALID (28/0) +op : f32(nan:0x7fc00000) * f32(nan:0x7fa00000) + f32(inf:0x7f800000) +res: f32(nan:0x7fc00000) flags=INVALID (28/1) +op : f32(nan:0x7fa00000) * f32(inf:0x7f800000) + f32(nan:0x7fc00000) +res: f32(nan:0x7fe00000) flags=INVALID (28/2) +op : f32(nan:0x7fc00000) * f32(nan:0x7fa00000) + f32(-nan:0xffa00000) +res: f32(nan:0x7fc00000) flags=INVALID (29/0) +op : f32(nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(nan:0x7fc00000) +res: f32(nan:0x7fe00000) flags=INVALID (29/1) +op : f32(-nan:0xffa00000) * f32(nan:0x7fc00000) + f32(nan:0x7fa00000) +res: f32(-nan:0xffe00000) flags=INVALID (29/2) +op : f32(nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000) +res: f32(nan:0x7fe00000) flags=INVALID (30/0) +op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(nan:0x7fa00000) +res: f32(-nan:0xffe00000) flags=INVALID (30/1) +op : f32(-nan:0xffc00000) * f32(nan:0x7fa00000) + f32(-nan:0xffa00000) +res: f32(-nan:0xffc00000) flags=INVALID (30/2) +# LP184149 +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-1:0x3f000000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(0x0.00000000000000000000p+0:0000000000) flags=OK (31/0) +op : f32(0x1.00000000000000000000p-149:0x00000001) * f32(0x1.00000000000000000000p-149:0x00000001) + f32(0x1.00000000000000000000p-149:0x00000001) +res: f32(0x1.00000000000000000000p-148:0x00000002) flags=UNDERFLOW INEXACT (32/0) +### Rounding downwards +op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(-inf:0xff800000) +res: f32(-nan:0xffe00000) flags=INVALID (0/0) +op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-nan:0xffa00000) +res: f32(-nan:0xffc00000) flags=INVALID (0/1) +op : f32(-inf:0xff800000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000) +res: f32(-nan:0xffc00000) flags=INVALID (0/2) +op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff) +res: f32(-nan:0xffc00000) flags=OK (1/0) +op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-nan:0xffc00000) +res: f32(-nan:0xffc00000) flags=OK (1/1) +op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-nan:0xffc00000) + f32(-inf:0xff800000) +res: f32(-nan:0xffc00000) flags=OK (1/2) +op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59) +res: f32(inf:0x7f800000) flags=OK (2/0) +op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-inf:0xff800000) +res: f32(-inf:0xff800000) flags=OK (2/1) +op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff) +res: f32(inf:0x7f800000) flags=OK (2/2) +op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (3/0) +op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (3/1) +op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (3/2) +op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (4/0) +op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59) +res: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) flags=INEXACT (4/1) +op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) +res: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) flags=INEXACT (4/2) +op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) +res: f32(0x1.0c27f800000000000000p+60:0x5d8613fc) flags=INEXACT (5/0) +op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) +res: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) flags=INEXACT (5/1) +op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8) +res: f32(0x1.26c46000000000000000p+34:0x50936230) flags=INEXACT (5/2) +op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000) +res: f32(0x1.91f93e00000000000000p-106:0x0ac8fc9f) flags=INEXACT (6/0) +op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(-0x1.31f75000000000000000p-40:0xab98fba8) +res: f32(-0x1.31f75000000000000000p-40:0xab98fba8) flags=INEXACT (6/1) +op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) +res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (6/2) +op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (7/0) +op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) +res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=OK (7/1) +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000) +res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (7/2) +op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000) +res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (8/0) +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(-0x1.00000000000000000000p-126:0x80800000) +res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (8/1) +op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(-0x1.00000000000000000000p-149:0x80000001) flags=UNDERFLOW INEXACT (8/2) +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000) +res: f32(0x1.00000000000000000000p-25:0x33000000) flags=OK (9/0) +op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (9/1) +op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000) +res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (9/2) +op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3) +res: f32(0x1.ffffe600000000000000p-25:0x337ffff3) flags=INEXACT (10/0) +op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.00000000000000000000p-126:0x00800000) +res: f32(0x1.ffffe600000000000000p-50:0x26fffff3) flags=INEXACT (10/1) +op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000) +res: f32(0x1.00000000000000000000p-25:0x33000000) flags=INEXACT (10/2) +op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d) +res: f32(0x1.ff801a00000000000000p-15:0x387fc00d) flags=INEXACT (11/0) +op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000000000000000000p-25:0x33000000) +res: f32(0x1.0007fe00000000000000p-25:0x330003ff) flags=INEXACT (11/1) +op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3) +res: f32(0x1.0001f200000000000000p-24:0x338000f9) flags=INEXACT (11/2) +op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006) +res: f32(0x1.00000c00000000000000p-14:0x38800006) flags=INEXACT (12/0) +op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.ffffe600000000000000p-25:0x337ffff3) +res: f32(0x1.0ffbf400000000000000p-24:0x3387fdfa) flags=INEXACT (12/1) +op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d) +res: f32(0x1.ff801a00000000000000p-15:0x387fc00d) flags=INEXACT (12/2) +op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000) +res: f32(0x1.00000000000000000000p+0:0x3f800000) flags=INEXACT (13/0) +op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.ff801a00000000000000p-15:0x387fc00d) +res: f32(0x1.ffc01800000000000000p-14:0x38ffe00c) flags=INEXACT (13/1) +op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006) +res: f32(0x1.ffc01800000000000000p-14:0x38ffe00c) flags=INEXACT (13/2) +op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000) +res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/0) +op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000c00000000000000p-14:0x38800006) +res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/1) +op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000) +res: f32(0x1.00040000000000000000p+0:0x3f800200) flags=INEXACT (14/2) +op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/0) +op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.00000000000000000000p+0:0x3f800000) +res: f32(0x1.80400000000000000000p+1:0x40402000) flags=OK (15/1) +op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/2) +op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854) +res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=OK (16/0) +op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.00400000000000000000p+0:0x3f802000) +res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=OK (16/1) +op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) +res: f32(0x1.2e23d200000000000000p+2:0x409711e9) flags=INEXACT (16/2) +op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb) +res: f32(0x1.12804000000000000000p+3:0x41094020) flags=INEXACT (17/0) +op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.00000000000000000000p+1:0x40000000) +res: f32(0x1.51458000000000000000p+3:0x4128a2c0) flags=INEXACT (17/1) +op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854) +res: f32(0x1.200c0400000000000000p+3:0x41100602) flags=INEXACT (17/2) +op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00) +res: f32(0x1.ffcf1400000000000000p+15:0x477fe78a) flags=INEXACT (18/0) +op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.5bf0a800000000000000p+1:0x402df854) +res: f32(0x1.91ed3a00000000000000p+17:0x4848f69d) flags=INEXACT (18/1) +op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb) +res: f32(0x1.5bc56000000000000000p+17:0x482de2b0) flags=INEXACT (18/2) +op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000) +res: f32(0x1.08edee00000000000000p+18:0x488476f7) flags=INEXACT (19/0) +op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.921fb600000000000000p+1:0x40490fdb) +res: f32(0x1.ff7e0800000000000000p+31:0x4f7fbf04) flags=INEXACT (19/1) +op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00) +res: f32(0x1.08ee7800000000000000p+18:0x4884773c) flags=INEXACT (19/2) +op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100) +res: f32(0x1.ff800800000000000000p+31:0x4f7fc004) flags=INEXACT (20/0) +op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00) +res: f32(0x1.ff840600000000000000p+31:0x4f7fc203) flags=INEXACT (20/1) +op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000) +res: f32(0x1.ff820600000000000000p+31:0x4f7fc103) flags=INEXACT (20/2) +op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) +res: f32(0x1.ff860600000000000000p+31:0x4f7fc303) flags=INEXACT (21/0) +op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+15:0x477fe000) +res: f32(0x1.ff820600000000000000p+32:0x4fffc103) flags=INEXACT (21/1) +op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100) +res: f32(0x1.ff800800000000000000p+32:0x4fffc004) flags=INEXACT (21/2) +op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000) +res: f32(0x1.ff830600000000000000p+32:0x4fffc183) flags=INEXACT (22/0) +op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100) +res: f32(0x1.ff7f8800000000000000p+33:0x507fbfc4) flags=INEXACT (22/1) +op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) +res: f32(0x1.ff840600000000000000p+32:0x4fffc203) flags=INEXACT (22/2) +op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080) +res: f32(0x1.ff800800000000000000p+33:0x507fc004) flags=INEXACT (23/0) +op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) +res: f32(0x1.ff820600000000000000p+33:0x507fc103) flags=INEXACT (23/1) +op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000) +res: f32(0x1.ff810600000000000000p+33:0x507fc083) flags=INEXACT (23/2) +op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b) +res: f32(0x1.c0bab600000000000000p+99:0x71605d5b) flags=INEXACT (24/0) +op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.ffc00000000000000000p+16:0x47ffe000) +res: f32(0x1.c0837e00000000000000p+116:0x79e041bf) flags=INEXACT (24/1) +op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080) +res: f32(0x1.c0829e00000000000000p+116:0x79e0414f) flags=INEXACT (24/2) +op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (25/0) +op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(0x1.ffc10000000000000000p+16:0x47ffe080) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (25/1) +op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (25/2) +op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000) +res: f32(inf:0x7f800000) flags=OK (26/0) +op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(0x1.c0bab600000000000000p+99:0x71605d5b) +res: f32(inf:0x7f800000) flags=OK (26/1) +op : f32(inf:0x7f800000) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff) +res: f32(inf:0x7f800000) flags=OK (26/2) +op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(nan:0x7fc00000) +res: f32(nan:0x7fc00000) flags=OK (27/0) +op : f32(inf:0x7f800000) * f32(nan:0x7fc00000) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff) +res: f32(nan:0x7fc00000) flags=OK (27/1) +op : f32(nan:0x7fc00000) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000) +res: f32(nan:0x7fc00000) flags=OK (27/2) +op : f32(inf:0x7f800000) * f32(nan:0x7fc00000) + f32(nan:0x7fa00000) +res: f32(nan:0x7fe00000) flags=INVALID (28/0) +op : f32(nan:0x7fc00000) * f32(nan:0x7fa00000) + f32(inf:0x7f800000) +res: f32(nan:0x7fc00000) flags=INVALID (28/1) +op : f32(nan:0x7fa00000) * f32(inf:0x7f800000) + f32(nan:0x7fc00000) +res: f32(nan:0x7fe00000) flags=INVALID (28/2) +op : f32(nan:0x7fc00000) * f32(nan:0x7fa00000) + f32(-nan:0xffa00000) +res: f32(nan:0x7fc00000) flags=INVALID (29/0) +op : f32(nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(nan:0x7fc00000) +res: f32(nan:0x7fe00000) flags=INVALID (29/1) +op : f32(-nan:0xffa00000) * f32(nan:0x7fc00000) + f32(nan:0x7fa00000) +res: f32(-nan:0xffe00000) flags=INVALID (29/2) +op : f32(nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000) +res: f32(nan:0x7fe00000) flags=INVALID (30/0) +op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(nan:0x7fa00000) +res: f32(-nan:0xffe00000) flags=INVALID (30/1) +op : f32(-nan:0xffc00000) * f32(nan:0x7fa00000) + f32(-nan:0xffa00000) +res: f32(-nan:0xffc00000) flags=INVALID (30/2) +# LP184149 +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-1:0x3f000000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(0x0.00000000000000000000p+0:0000000000) flags=OK (31/0) +op : f32(0x1.00000000000000000000p-149:0x00000001) * f32(0x1.00000000000000000000p-149:0x00000001) + f32(0x1.00000000000000000000p-149:0x00000001) +res: f32(0x1.00000000000000000000p-149:0x00000001) flags=UNDERFLOW INEXACT (32/0) +### Rounding to zero +op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(-inf:0xff800000) +res: f32(-nan:0xffe00000) flags=INVALID (0/0) +op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-nan:0xffa00000) +res: f32(-nan:0xffc00000) flags=INVALID (0/1) +op : f32(-inf:0xff800000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000) +res: f32(-nan:0xffc00000) flags=INVALID (0/2) +op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff) +res: f32(-nan:0xffc00000) flags=OK (1/0) +op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-nan:0xffc00000) +res: f32(-nan:0xffc00000) flags=OK (1/1) +op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-nan:0xffc00000) + f32(-inf:0xff800000) +res: f32(-nan:0xffc00000) flags=OK (1/2) +op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59) +res: f32(inf:0x7f800000) flags=OK (2/0) +op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-inf:0xff800000) +res: f32(-inf:0xff800000) flags=OK (2/1) +op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff) +res: f32(inf:0x7f800000) flags=OK (2/2) +op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (3/0) +op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (3/1) +op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (3/2) +op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (4/0) +op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59) +res: f32(-0x1.1874b000000000000000p+103:0xf30c3a58) flags=INEXACT (4/1) +op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) +res: f32(-0x1.c0bab400000000000000p+99:0xf1605d5a) flags=INEXACT (4/2) +op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) +res: f32(0x1.0c27f800000000000000p+60:0x5d8613fc) flags=INEXACT (5/0) +op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) +res: f32(-0x1.c0bab400000000000000p+99:0xf1605d5a) flags=INEXACT (5/1) +op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8) +res: f32(0x1.26c46000000000000000p+34:0x50936230) flags=INEXACT (5/2) +op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000) +res: f32(0x1.91f93e00000000000000p-106:0x0ac8fc9f) flags=INEXACT (6/0) +op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(-0x1.31f75000000000000000p-40:0xab98fba8) +res: f32(-0x1.31f74e00000000000000p-40:0xab98fba7) flags=INEXACT (6/1) +op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) +res: f32(-0x1.50544200000000000000p-66:0x9ea82a21) flags=INEXACT (6/2) +op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (7/0) +op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(-0x1.50544400000000000000p-66:0x9ea82a22) +res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=OK (7/1) +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000) +res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (7/2) +op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000) +res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (8/0) +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(-0x1.00000000000000000000p-126:0x80800000) +res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (8/1) +op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(-0x0.00000000000000000000p+0:0x80000000) flags=UNDERFLOW INEXACT (8/2) +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000) +res: f32(0x1.00000000000000000000p-25:0x33000000) flags=OK (9/0) +op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (9/1) +op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000) +res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (9/2) +op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3) +res: f32(0x1.ffffe600000000000000p-25:0x337ffff3) flags=INEXACT (10/0) +op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.00000000000000000000p-126:0x00800000) +res: f32(0x1.ffffe600000000000000p-50:0x26fffff3) flags=INEXACT (10/1) +op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000) +res: f32(0x1.00000000000000000000p-25:0x33000000) flags=INEXACT (10/2) +op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d) +res: f32(0x1.ff801a00000000000000p-15:0x387fc00d) flags=INEXACT (11/0) +op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000000000000000000p-25:0x33000000) +res: f32(0x1.0007fe00000000000000p-25:0x330003ff) flags=INEXACT (11/1) +op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3) +res: f32(0x1.0001f200000000000000p-24:0x338000f9) flags=INEXACT (11/2) +op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006) +res: f32(0x1.00000c00000000000000p-14:0x38800006) flags=INEXACT (12/0) +op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.ffffe600000000000000p-25:0x337ffff3) +res: f32(0x1.0ffbf400000000000000p-24:0x3387fdfa) flags=INEXACT (12/1) +op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d) +res: f32(0x1.ff801a00000000000000p-15:0x387fc00d) flags=INEXACT (12/2) +op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000) +res: f32(0x1.00000000000000000000p+0:0x3f800000) flags=INEXACT (13/0) +op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.ff801a00000000000000p-15:0x387fc00d) +res: f32(0x1.ffc01800000000000000p-14:0x38ffe00c) flags=INEXACT (13/1) +op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006) +res: f32(0x1.ffc01800000000000000p-14:0x38ffe00c) flags=INEXACT (13/2) +op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000) +res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/0) +op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000c00000000000000p-14:0x38800006) +res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/1) +op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000) +res: f32(0x1.00040000000000000000p+0:0x3f800200) flags=INEXACT (14/2) +op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/0) +op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.00000000000000000000p+0:0x3f800000) +res: f32(0x1.80400000000000000000p+1:0x40402000) flags=OK (15/1) +op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000) +res: f32(0x1.80200000000000000000p+1:0x40401000) flags=OK (15/2) +op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854) +res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=OK (16/0) +op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.00400000000000000000p+0:0x3f802000) +res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=OK (16/1) +op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000) +res: f32(0x1.2e23d200000000000000p+2:0x409711e9) flags=INEXACT (16/2) +op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb) +res: f32(0x1.12804000000000000000p+3:0x41094020) flags=INEXACT (17/0) +op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.00000000000000000000p+1:0x40000000) +res: f32(0x1.51458000000000000000p+3:0x4128a2c0) flags=INEXACT (17/1) +op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854) +res: f32(0x1.200c0400000000000000p+3:0x41100602) flags=INEXACT (17/2) +op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00) +res: f32(0x1.ffcf1400000000000000p+15:0x477fe78a) flags=INEXACT (18/0) +op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.5bf0a800000000000000p+1:0x402df854) +res: f32(0x1.91ed3a00000000000000p+17:0x4848f69d) flags=INEXACT (18/1) +op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb) +res: f32(0x1.5bc56000000000000000p+17:0x482de2b0) flags=INEXACT (18/2) +op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000) +res: f32(0x1.08edee00000000000000p+18:0x488476f7) flags=INEXACT (19/0) +op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.921fb600000000000000p+1:0x40490fdb) +res: f32(0x1.ff7e0800000000000000p+31:0x4f7fbf04) flags=INEXACT (19/1) +op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00) +res: f32(0x1.08ee7800000000000000p+18:0x4884773c) flags=INEXACT (19/2) +op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100) +res: f32(0x1.ff800800000000000000p+31:0x4f7fc004) flags=INEXACT (20/0) +op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00) +res: f32(0x1.ff840600000000000000p+31:0x4f7fc203) flags=INEXACT (20/1) +op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000) +res: f32(0x1.ff820600000000000000p+31:0x4f7fc103) flags=INEXACT (20/2) +op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) +res: f32(0x1.ff860600000000000000p+31:0x4f7fc303) flags=INEXACT (21/0) +op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+15:0x477fe000) +res: f32(0x1.ff820600000000000000p+32:0x4fffc103) flags=INEXACT (21/1) +op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100) +res: f32(0x1.ff800800000000000000p+32:0x4fffc004) flags=INEXACT (21/2) +op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000) +res: f32(0x1.ff830600000000000000p+32:0x4fffc183) flags=INEXACT (22/0) +op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100) +res: f32(0x1.ff7f8800000000000000p+33:0x507fbfc4) flags=INEXACT (22/1) +op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) +res: f32(0x1.ff840600000000000000p+32:0x4fffc203) flags=INEXACT (22/2) +op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080) +res: f32(0x1.ff800800000000000000p+33:0x507fc004) flags=INEXACT (23/0) +op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) +res: f32(0x1.ff820600000000000000p+33:0x507fc103) flags=INEXACT (23/1) +op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000) +res: f32(0x1.ff810600000000000000p+33:0x507fc083) flags=INEXACT (23/2) +op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b) +res: f32(0x1.c0bab600000000000000p+99:0x71605d5b) flags=INEXACT (24/0) +op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.ffc00000000000000000p+16:0x47ffe000) +res: f32(0x1.c0837e00000000000000p+116:0x79e041bf) flags=INEXACT (24/1) +op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080) +res: f32(0x1.c0829e00000000000000p+116:0x79e0414f) flags=INEXACT (24/2) +op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (25/0) +op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(0x1.ffc10000000000000000p+16:0x47ffe080) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (25/1) +op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b) +res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (25/2) +op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000) +res: f32(inf:0x7f800000) flags=OK (26/0) +op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(0x1.c0bab600000000000000p+99:0x71605d5b) +res: f32(inf:0x7f800000) flags=OK (26/1) +op : f32(inf:0x7f800000) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff) +res: f32(inf:0x7f800000) flags=OK (26/2) +op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(nan:0x7fc00000) +res: f32(nan:0x7fc00000) flags=OK (27/0) +op : f32(inf:0x7f800000) * f32(nan:0x7fc00000) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff) +res: f32(nan:0x7fc00000) flags=OK (27/1) +op : f32(nan:0x7fc00000) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000) +res: f32(nan:0x7fc00000) flags=OK (27/2) +op : f32(inf:0x7f800000) * f32(nan:0x7fc00000) + f32(nan:0x7fa00000) +res: f32(nan:0x7fe00000) flags=INVALID (28/0) +op : f32(nan:0x7fc00000) * f32(nan:0x7fa00000) + f32(inf:0x7f800000) +res: f32(nan:0x7fc00000) flags=INVALID (28/1) +op : f32(nan:0x7fa00000) * f32(inf:0x7f800000) + f32(nan:0x7fc00000) +res: f32(nan:0x7fe00000) flags=INVALID (28/2) +op : f32(nan:0x7fc00000) * f32(nan:0x7fa00000) + f32(-nan:0xffa00000) +res: f32(nan:0x7fc00000) flags=INVALID (29/0) +op : f32(nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(nan:0x7fc00000) +res: f32(nan:0x7fe00000) flags=INVALID (29/1) +op : f32(-nan:0xffa00000) * f32(nan:0x7fc00000) + f32(nan:0x7fa00000) +res: f32(-nan:0xffe00000) flags=INVALID (29/2) +op : f32(nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000) +res: f32(nan:0x7fe00000) flags=INVALID (30/0) +op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(nan:0x7fa00000) +res: f32(-nan:0xffe00000) flags=INVALID (30/1) +op : f32(-nan:0xffc00000) * f32(nan:0x7fa00000) + f32(-nan:0xffa00000) +res: f32(-nan:0xffc00000) flags=INVALID (30/2) +# LP184149 +op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-1:0x3f000000) + f32(0x0.00000000000000000000p+0:0000000000) +res: f32(0x0.00000000000000000000p+0:0000000000) flags=OK (31/0) +op : f32(0x1.00000000000000000000p-149:0x00000001) * f32(0x1.00000000000000000000p-149:0x00000001) + f32(0x1.00000000000000000000p-149:0x00000001) +res: f32(0x1.00000000000000000000p-149:0x00000001) flags=UNDERFLOW INEXACT (32/0) From e850897e67026fa235bd34c56adf1c26e6aa1110 Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Wed, 5 Jan 2022 13:50:05 +0000 Subject: [PATCH 610/730] FreeBSD: Upgrade to 12.3 release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note, since libtasn1 was fixed in 12.3 [*], this commit re-enables GnuTLS. [*] https://gitlab.com/gnutls/libtasn1/-/merge_requests/71 Signed-off-by: Brad Smith Tested-by: Thomas Huth Reviewed-by: Warner Losh Signed-off-by: Alex Bennée Reviewed-by: Daniel P. Berrangé Reviewed-by: Philippe Mathieu-Daudé Message-Id: Message-Id: <20220105135009.1584676-31-alex.bennee@linaro.org> --- .gitlab-ci.d/cirrus.yml | 5 +---- tests/vm/freebsd | 8 +++----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/.gitlab-ci.d/cirrus.yml b/.gitlab-ci.d/cirrus.yml index 19e6c21401..b96b22e269 100644 --- a/.gitlab-ci.d/cirrus.yml +++ b/.gitlab-ci.d/cirrus.yml @@ -52,14 +52,11 @@ x64-freebsd-12-build: NAME: freebsd-12 CIRRUS_VM_INSTANCE_TYPE: freebsd_instance CIRRUS_VM_IMAGE_SELECTOR: image_family - CIRRUS_VM_IMAGE_NAME: freebsd-12-2 + CIRRUS_VM_IMAGE_NAME: freebsd-12-3 CIRRUS_VM_CPUS: 8 CIRRUS_VM_RAM: 8G UPDATE_COMMAND: pkg update INSTALL_COMMAND: pkg install -y - # TODO: Enable gnutls again once FreeBSD's libtasn1 got fixed - # See: https://gitlab.com/gnutls/libtasn1/-/merge_requests/71 - CONFIGURE_ARGS: --disable-gnutls TEST_TARGETS: check x64-freebsd-13-build: diff --git a/tests/vm/freebsd b/tests/vm/freebsd index 6e20e84322..805db759d6 100755 --- a/tests/vm/freebsd +++ b/tests/vm/freebsd @@ -28,8 +28,8 @@ class FreeBSDVM(basevm.BaseVM): name = "freebsd" arch = "x86_64" - link = "https://download.freebsd.org/ftp/releases/ISO-IMAGES/12.2/FreeBSD-12.2-RELEASE-amd64-disc1.iso.xz" - csum = "a4530246cafbf1dd42a9bd3ea441ca9a78a6a0cd070278cbdf63f3a6f803ecae" + link = "https://download.freebsd.org/ftp/releases/ISO-IMAGES/12.3/FreeBSD-12.3-RELEASE-amd64-disc1.iso.xz" + csum = "36dd0de50f1fe5f0a88e181e94657656de26fb64254412f74e80e128e8b938b4" size = "20G" pkgs = [ # build tools @@ -65,8 +65,6 @@ class FreeBSDVM(basevm.BaseVM): "zstd", ] - # TODO: Enable gnutls again once FreeBSD's libtasn1 got fixed - # See: https://gitlab.com/gnutls/libtasn1/-/merge_requests/71 BUILD_SCRIPT = """ set -e; rm -rf /home/qemu/qemu-test.* @@ -74,7 +72,7 @@ class FreeBSDVM(basevm.BaseVM): mkdir src build; cd src; tar -xf /dev/vtbd1; cd ../build - ../src/configure --python=python3.7 --disable-gnutls {configure_opts}; + ../src/configure --python=python3.7 {configure_opts}; gmake --output-sync -j{jobs} {target} {verbose}; """ From 3265d1fc77eb5da522accb37e50053dfdfda7e8f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 5 Jan 2022 13:50:08 +0000 Subject: [PATCH 611/730] docker: include bison in debian-tricore-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Binutils sometimes fail to build if bison is not installed: /bin/sh ./ylwrap `test -f arparse.y || echo ./`arparse.y y.tab.c arparse.c y.tab.h arparse.h y.output arparse.output -- -d ./ylwrap: 109: ./ylwrap: -d: not found (the correct invocation of ylwrap would have "bison -d" after the double dash). Work around by installing it in the container. Signed-off-by: Paolo Bonzini Reviewed-by: Philippe Mathieu-Daudé Resolves: https://gitlab.com/qemu-project/qemu/-/issues/596 Reviewed-by: Richard Henderson Message-Id: <20211221111624.352804-1-pbonzini@redhat.com> Signed-off-by: Alex Bennée Message-Id: <20220105135009.1584676-34-alex.bennee@linaro.org> --- tests/docker/dockerfiles/debian-tricore-cross.docker | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/docker/dockerfiles/debian-tricore-cross.docker b/tests/docker/dockerfiles/debian-tricore-cross.docker index d8df2c6117..3f6b55562c 100644 --- a/tests/docker/dockerfiles/debian-tricore-cross.docker +++ b/tests/docker/dockerfiles/debian-tricore-cross.docker @@ -16,6 +16,7 @@ MAINTAINER Philippe Mathieu-Daudé RUN apt update && \ DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \ DEBIAN_FRONTEND=noninteractive eatmydata apt install -yy \ + bison \ bzip2 \ ca-certificates \ ccache \ From 75f01c68b5c630a9a6b21b93febf3a871a9111ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sat, 15 Jan 2022 21:37:23 +0100 Subject: [PATCH 612/730] exec/memory: Extract address_space_set() from dma_memory_set() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dma_memory_set() does a DMA barrier, set the address space with a constant value. The constant value filling code is not specific to DMA and can be used for AddressSpace. Extract it as a new helper: address_space_set(). Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Laurent Vivier Reviewed-by: Stefano Garzarella Reviewed-by: Richard Henderson [lv: rebase] Signed-off-by: Laurent Vivier Reviewed-by: David Hildenbrand Reviewed-by: Peter Xu Message-Id: <20220115203725.3834712-2-laurent@vivier.eu> --- include/exec/memory.h | 16 ++++++++++++++++ softmmu/dma-helpers.c | 15 +-------------- softmmu/physmem.c | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 63be794a06..4d5997e6bb 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -2908,6 +2908,22 @@ address_space_write_cached(MemoryRegionCache *cache, hwaddr addr, } } +/** + * address_space_set: Fill address space with a constant byte. + * + * Return a MemTxResult indicating whether the operation succeeded + * or failed (eg unassigned memory, device rejected the transaction, + * IOMMU fault). + * + * @as: #AddressSpace to be accessed + * @addr: address within that address space + * @c: constant byte to fill the memory + * @len: the number of bytes to fill with the constant byte + * @attrs: memory transaction attributes + */ +MemTxResult address_space_set(AddressSpace *as, hwaddr addr, + uint8_t c, hwaddr len, MemTxAttrs attrs); + #ifdef NEED_CPU_H /* enum device_endian to MemOp. */ static inline MemOp devend_memop(enum device_endian end) diff --git a/softmmu/dma-helpers.c b/softmmu/dma-helpers.c index 1c6fba6a11..160095e4ba 100644 --- a/softmmu/dma-helpers.c +++ b/softmmu/dma-helpers.c @@ -23,20 +23,7 @@ MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr, { dma_barrier(as, DMA_DIRECTION_FROM_DEVICE); -#define FILLBUF_SIZE 512 - uint8_t fillbuf[FILLBUF_SIZE]; - int l; - MemTxResult error = MEMTX_OK; - - memset(fillbuf, c, FILLBUF_SIZE); - while (len > 0) { - l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE; - error |= address_space_write(as, addr, attrs, fillbuf, l); - len -= l; - addr += l; - } - - return error; + return address_space_set(as, addr, c, len, attrs); } void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint, diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 3524c04c2a..dddf70edf5 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -2927,6 +2927,25 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs, } } +MemTxResult address_space_set(AddressSpace *as, hwaddr addr, + uint8_t c, hwaddr len, MemTxAttrs attrs) +{ +#define FILLBUF_SIZE 512 + uint8_t fillbuf[FILLBUF_SIZE]; + int l; + MemTxResult error = MEMTX_OK; + + memset(fillbuf, c, FILLBUF_SIZE); + while (len > 0) { + l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE; + error |= address_space_write(as, addr, attrs, fillbuf, l); + len -= l; + addr += l; + } + + return error; +} + void cpu_physical_memory_rw(hwaddr addr, void *buf, hwaddr len, bool is_write) { From b4c4c1f1129a5d9dcbcbff46b58998f6fb1410bb Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Sat, 15 Jan 2022 21:37:24 +0100 Subject: [PATCH 613/730] hw/elf_ops: clear uninitialized segment space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the mem_size of the segment is bigger than the file_size, and if this space doesn't overlap another segment, it needs to be cleared. This bug is very similar to the one we had for linux-user, 22d113b52f41 ("linux-user: Fix loading of BSS segments"), where .bss section is encoded as an extension of the the data one by setting the segment p_memsz > p_filesz. Signed-off-by: Laurent Vivier [PMD: Use recently added address_space_set()] Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Stefano Garzarella Reviewed-by: Richard Henderson Message-Id: <20220115203725.3834712-3-laurent@vivier.eu> --- hw/core/loader.c | 4 ++++ include/hw/elf_ops.h | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/hw/core/loader.c b/hw/core/loader.c index 052a0fd719..19edb928e9 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -1164,9 +1164,13 @@ static void rom_reset(void *unused) if (rom->mr) { void *host = memory_region_get_ram_ptr(rom->mr); memcpy(host, rom->data, rom->datasize); + memset(host + rom->datasize, 0, rom->romsize - rom->datasize); } else { address_space_write_rom(rom->as, rom->addr, MEMTXATTRS_UNSPECIFIED, rom->data, rom->datasize); + address_space_set(rom->as, rom->addr + rom->datasize, 0, + rom->romsize - rom->datasize, + MEMTXATTRS_UNSPECIFIED); } if (rom->isrom) { /* rom needs to be written only once */ diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h index 995de8495c..7c3b1d0f6c 100644 --- a/include/hw/elf_ops.h +++ b/include/hw/elf_ops.h @@ -555,6 +555,19 @@ static ssize_t glue(load_elf, SZ)(const char *name, int fd, if (res != MEMTX_OK) { goto fail; } + /* + * We need to zero'ify the space that is not copied + * from file + */ + if (file_size < mem_size) { + res = address_space_set(as ? as : &address_space_memory, + addr + file_size, 0, + mem_size - file_size, + MEMTXATTRS_UNSPECIFIED); + if (res != MEMTX_OK) { + goto fail; + } + } } } From e48b140eef9775986cc18038c7bc68f8d2b7fe1d Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Sat, 15 Jan 2022 21:37:25 +0100 Subject: [PATCH 614/730] m68k: virt: correctly set the initial PC According to QEMU parameter, set initial PC to the entry of the loaded kernel. Signed-off-by: Laurent Vivier Message-Id: <20220115203725.3834712-4-laurent@vivier.eu> --- hw/m68k/virt.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c index 78e926a554..bbaf630bbf 100644 --- a/hw/m68k/virt.c +++ b/hw/m68k/virt.c @@ -85,14 +85,21 @@ #define VIRT_VIRTIO_MMIO_BASE 0xff010000 /* MMIO: 0xff010000 - 0xff01ffff */ #define VIRT_VIRTIO_IRQ_BASE PIC_IRQ(2, 1) /* PIC: 2, 3, 4, 5, IRQ: ALL */ +typedef struct { + M68kCPU *cpu; + hwaddr initial_pc; + hwaddr initial_stack; +} ResetInfo; + static void main_cpu_reset(void *opaque) { - M68kCPU *cpu = opaque; + ResetInfo *reset_info = opaque; + M68kCPU *cpu = reset_info->cpu; CPUState *cs = CPU(cpu); cpu_reset(cs); - cpu->env.aregs[7] = ldl_phys(cs->as, 0); - cpu->env.pc = ldl_phys(cs->as, 4); + cpu->env.aregs[7] = reset_info->initial_stack; + cpu->env.pc = reset_info->initial_pc; } static void virt_init(MachineState *machine) @@ -113,6 +120,7 @@ static void virt_init(MachineState *machine) SysBusDevice *sysbus; hwaddr io_base; int i; + ResetInfo *reset_info; if (ram_size > 3399672 * KiB) { /* @@ -124,9 +132,13 @@ static void virt_init(MachineState *machine) exit(1); } + reset_info = g_malloc0(sizeof(ResetInfo)); + /* init CPUs */ cpu = M68K_CPU(cpu_create(machine->cpu_type)); - qemu_register_reset(main_cpu_reset, cpu); + + reset_info->cpu = cpu; + qemu_register_reset(main_cpu_reset, reset_info); /* RAM */ memory_region_add_subregion(get_system_memory(), 0, machine->ram); @@ -206,7 +218,7 @@ static void virt_init(MachineState *machine) error_report("could not load kernel '%s'", kernel_filename); exit(1); } - stl_phys(cs->as, 4, elf_entry); /* reset initial PC */ + reset_info->initial_pc = elf_entry; parameters_base = (high + 1) & ~1; BOOTINFO1(cs->as, parameters_base, BI_MACHTYPE, MACH_VIRT); From 95ea96e8b1610f2d1bfa2abd0d12c40d647e563d Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 7 Jan 2022 15:01:54 +0000 Subject: [PATCH 615/730] hw/arm/virt: KVM: Enable PAuth when supported by the host Add basic support for Pointer Authentication when running a KVM guest and that the host supports it, loosely based on the SVE support. Although the feature is enabled by default when the host advertises it, it is possible to disable it by setting the 'pauth=off' CPU property. The 'pauth' comment is removed from cpu-features.rst, as it is now common to both TCG and KVM. Tested on an Apple M1 running 5.16-rc6. Cc: Eric Auger Cc: Richard Henderson Cc: Peter Maydell Reviewed-by: Andrew Jones Signed-off-by: Marc Zyngier Reviewed-by: Richard Henderson Message-id: 20220107150154.2490308-1-maz@kernel.org [PMM: fixed indentation] Signed-off-by: Peter Maydell --- docs/system/arm/cpu-features.rst | 4 ---- target/arm/cpu.c | 16 +++++----------- target/arm/cpu.h | 1 + target/arm/cpu64.c | 31 +++++++++++++++++++++++++++---- target/arm/kvm64.c | 21 +++++++++++++++++++++ 5 files changed, 54 insertions(+), 19 deletions(-) diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst index 584eb17097..3e626c4b68 100644 --- a/docs/system/arm/cpu-features.rst +++ b/docs/system/arm/cpu-features.rst @@ -217,10 +217,6 @@ TCG VCPU Features TCG VCPU features are CPU features that are specific to TCG. Below is the list of TCG VCPU features and their descriptions. - pauth Enable or disable ``FEAT_Pauth``, pointer - authentication. By default, the feature is - enabled with ``-cpu max``. - pauth-impdef When ``FEAT_Pauth`` is enabled, either the *impdef* (Implementation Defined) algorithm is enabled or the *architected* QARMA algorithm diff --git a/target/arm/cpu.c b/target/arm/cpu.c index a211804fd3..cdbc4cdd01 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1380,17 +1380,10 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp) return; } - /* - * KVM does not support modifications to this feature. - * We have not registered the cpu properties when KVM - * is in use, so the user will not be able to set them. - */ - if (!kvm_enabled()) { - arm_cpu_pauth_finalize(cpu, &local_err); - if (local_err != NULL) { - error_propagate(errp, local_err); - return; - } + arm_cpu_pauth_finalize(cpu, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; } } @@ -2091,6 +2084,7 @@ static void arm_host_initfn(Object *obj) kvm_arm_set_cpu_features_from_host(cpu); if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { aarch64_add_sve_properties(obj); + aarch64_add_pauth_properties(obj); } #else hvf_arm_set_cpu_features_from_host(cpu); diff --git a/target/arm/cpu.h b/target/arm/cpu.h index e33f37b70a..c6a4d50e82 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1076,6 +1076,7 @@ void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq); void aarch64_sve_change_el(CPUARMState *env, int old_el, int new_el, bool el0_a64); void aarch64_add_sve_properties(Object *obj); +void aarch64_add_pauth_properties(Object *obj); /* * SVE registers are encoded in KVM's memory in an endianness-invariant format. diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 15245a60a8..8786be7783 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -630,6 +630,15 @@ void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) int arch_val = 0, impdef_val = 0; uint64_t t; + /* Exit early if PAuth is enabled, and fall through to disable it */ + if (kvm_enabled() && cpu->prop_pauth) { + if (!cpu_isar_feature(aa64_pauth, cpu)) { + error_setg(errp, "'pauth' feature not supported by KVM on this host"); + } + + return; + } + /* TODO: Handle HaveEnhancedPAC, HaveEnhancedPAC2, HaveFPAC. */ if (cpu->prop_pauth) { if (cpu->prop_pauth_impdef) { @@ -655,6 +664,23 @@ static Property arm_cpu_pauth_property = static Property arm_cpu_pauth_impdef_property = DEFINE_PROP_BOOL("pauth-impdef", ARMCPU, prop_pauth_impdef, false); +void aarch64_add_pauth_properties(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + /* Default to PAUTH on, with the architected algorithm on TCG. */ + qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_property); + if (kvm_enabled()) { + /* + * Mirror PAuth support from the probed sysregs back into the + * property for KVM. Is it just a bit backward? Yes it is! + */ + cpu->prop_pauth = cpu_isar_feature(aa64_pauth, cpu); + } else { + qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_impdef_property); + } +} + /* -cpu max: if KVM is enabled, like -cpu host (best possible with this host); * otherwise, a CPU with as many features enabled as our emulation supports. * The version of '-cpu max' for qemu-system-arm is defined in cpu.c; @@ -829,13 +855,10 @@ static void aarch64_max_initfn(Object *obj) cpu->dcz_blocksize = 7; /* 512 bytes */ #endif - /* Default to PAUTH on, with the architected algorithm. */ - qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_property); - qdev_property_add_static(DEVICE(obj), &arm_cpu_pauth_impdef_property); - bitmap_fill(cpu->sve_vq_supported, ARM_MAX_VQ); } + aarch64_add_pauth_properties(obj); aarch64_add_sve_properties(obj); object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq, cpu_max_set_sve_max_vq, NULL, NULL); diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index e790d6c9a5..71c3ca6971 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -491,6 +491,12 @@ static int read_sys_reg64(int fd, uint64_t *pret, uint64_t id) return ioctl(fd, KVM_GET_ONE_REG, &idreg); } +static bool kvm_arm_pauth_supported(void) +{ + return (kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_ADDRESS) && + kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_GENERIC)); +} + bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) { /* Identify the feature bits corresponding to the host CPU, and @@ -521,6 +527,17 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) */ struct kvm_vcpu_init init = { .target = -1, }; + /* + * Ask for Pointer Authentication if supported. We can't play the + * SVE trick of synthesising the ID reg as KVM won't tell us + * whether we have the architected or IMPDEF version of PAuth, so + * we have to use the actual ID regs. + */ + if (kvm_arm_pauth_supported()) { + init.features[0] |= (1 << KVM_ARM_VCPU_PTRAUTH_ADDRESS | + 1 << KVM_ARM_VCPU_PTRAUTH_GENERIC); + } + if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) { return false; } @@ -865,6 +882,10 @@ int kvm_arch_init_vcpu(CPUState *cs) assert(kvm_arm_sve_supported()); cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_SVE; } + if (cpu_isar_feature(aa64_pauth, cpu)) { + cpu->kvm_init_features[0] |= (1 << KVM_ARM_VCPU_PTRAUTH_ADDRESS | + 1 << KVM_ARM_VCPU_PTRAUTH_GENERIC); + } /* Do KVM_ARM_VCPU_INIT ioctl */ ret = kvm_arm_vcpu_init(cs); From 9adfbf1b6116125d32d5b1608781a9935e517afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 7 Jan 2022 19:44:27 +0100 Subject: [PATCH 616/730] hw: Move MARVELL_88W8618 Kconfig from audio/ to arm/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Marvell 88W8618 is a system-on-chip with an ARM core. We implement its audio codecs and network interface. Homogeneous SoC Kconfig are usually defined in the hw/$ARCH directory. Move it there. Suggested-by: Richard Henderson Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-id: 20220107184429.423572-2-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/arm/Kconfig | 3 +++ hw/audio/Kconfig | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index e652590943..c459c897cc 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -94,6 +94,9 @@ config MUSCA select SPLIT_IRQ select UNIMP +config MARVELL_88W8618 + bool + config MUSICPAL bool select OR_IRQ diff --git a/hw/audio/Kconfig b/hw/audio/Kconfig index e9c6fed826..e76c69ca7e 100644 --- a/hw/audio/Kconfig +++ b/hw/audio/Kconfig @@ -47,6 +47,3 @@ config PL041 config CS4231 bool - -config MARVELL_88W8618 - bool From 8ede0245e210075f6272b6c91cde648a01003676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 7 Jan 2022 19:44:28 +0100 Subject: [PATCH 617/730] hw/arm/musicpal: Fix coding style of code related to MV88W8618 device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We are going to move this code, so fix its style first to avoid: ERROR: spaces required around that '/' (ctx:VxV) Reviewed-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-id: 20220107184429.423572-3-f4bug@amsat.org Signed-off-by: Peter Maydell --- hw/arm/musicpal.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index 2680ec55b5..1291eb98ab 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -310,13 +310,13 @@ static uint64_t mv88w8618_eth_read(void *opaque, hwaddr offset, return s->imr; case MP_ETH_FRDP0 ... MP_ETH_FRDP3: - return s->frx_queue[(offset - MP_ETH_FRDP0)/4]; + return s->frx_queue[(offset - MP_ETH_FRDP0) / 4]; case MP_ETH_CRDP0 ... MP_ETH_CRDP3: - return s->rx_queue[(offset - MP_ETH_CRDP0)/4]; + return s->rx_queue[(offset - MP_ETH_CRDP0) / 4]; case MP_ETH_CTDP0 ... MP_ETH_CTDP1: - return s->tx_queue[(offset - MP_ETH_CTDP0)/4]; + return s->tx_queue[(offset - MP_ETH_CTDP0) / 4]; default: return 0; @@ -361,16 +361,16 @@ static void mv88w8618_eth_write(void *opaque, hwaddr offset, break; case MP_ETH_FRDP0 ... MP_ETH_FRDP3: - s->frx_queue[(offset - MP_ETH_FRDP0)/4] = value; + s->frx_queue[(offset - MP_ETH_FRDP0) / 4] = value; break; case MP_ETH_CRDP0 ... MP_ETH_CRDP3: - s->rx_queue[(offset - MP_ETH_CRDP0)/4] = - s->cur_rx[(offset - MP_ETH_CRDP0)/4] = value; + s->rx_queue[(offset - MP_ETH_CRDP0) / 4] = + s->cur_rx[(offset - MP_ETH_CRDP0) / 4] = value; break; case MP_ETH_CTDP0 ... MP_ETH_CTDP1: - s->tx_queue[(offset - MP_ETH_CTDP0)/4] = value; + s->tx_queue[(offset - MP_ETH_CTDP0) / 4] = value; break; } } From 6d81f4887f66995ca94fce5f896b26339a537bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 7 Jan 2022 19:44:29 +0100 Subject: [PATCH 618/730] hw/net: Move MV88W8618 network device out of hw/arm/ directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Marvell 88W8618 network device is hidden in the Musicpal machine. Move it into a new unit file under the hw/net/ directory. Acked-by: Richard Henderson Signed-off-by: Philippe Mathieu-Daudé Message-id: 20220107184429.423572-4-f4bug@amsat.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- MAINTAINERS | 2 + hw/arm/musicpal.c | 381 +------------------------------ hw/net/meson.build | 1 + hw/net/mv88w8618_eth.c | 403 +++++++++++++++++++++++++++++++++ include/hw/net/mv88w8618_eth.h | 12 + 5 files changed, 419 insertions(+), 380 deletions(-) create mode 100644 hw/net/mv88w8618_eth.c create mode 100644 include/hw/net/mv88w8618_eth.h diff --git a/MAINTAINERS b/MAINTAINERS index 893a556710..e4b3a4bcdf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -774,6 +774,8 @@ M: Peter Maydell L: qemu-arm@nongnu.org S: Odd Fixes F: hw/arm/musicpal.c +F: hw/net/mv88w8618_eth.c +F: include/hw/net/mv88w8618_eth.h F: docs/system/arm/musicpal.rst Nuvoton NPCM7xx diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index 1291eb98ab..7c840fb428 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -34,12 +34,12 @@ #include "ui/pixel_ops.h" #include "qemu/cutils.h" #include "qom/object.h" +#include "hw/net/mv88w8618_eth.h" #define MP_MISC_BASE 0x80002000 #define MP_MISC_SIZE 0x00001000 #define MP_ETH_BASE 0x80008000 -#define MP_ETH_SIZE 0x00001000 #define MP_WLAN_BASE 0x8000C000 #define MP_WLAN_SIZE 0x00000800 @@ -84,384 +84,6 @@ /* Wolfson 8750 I2C address */ #define MP_WM_ADDR 0x1A -/* Ethernet register offsets */ -#define MP_ETH_SMIR 0x010 -#define MP_ETH_PCXR 0x408 -#define MP_ETH_SDCMR 0x448 -#define MP_ETH_ICR 0x450 -#define MP_ETH_IMR 0x458 -#define MP_ETH_FRDP0 0x480 -#define MP_ETH_FRDP1 0x484 -#define MP_ETH_FRDP2 0x488 -#define MP_ETH_FRDP3 0x48C -#define MP_ETH_CRDP0 0x4A0 -#define MP_ETH_CRDP1 0x4A4 -#define MP_ETH_CRDP2 0x4A8 -#define MP_ETH_CRDP3 0x4AC -#define MP_ETH_CTDP0 0x4E0 -#define MP_ETH_CTDP1 0x4E4 - -/* MII PHY access */ -#define MP_ETH_SMIR_DATA 0x0000FFFF -#define MP_ETH_SMIR_ADDR 0x03FF0000 -#define MP_ETH_SMIR_OPCODE (1 << 26) /* Read value */ -#define MP_ETH_SMIR_RDVALID (1 << 27) - -/* PHY registers */ -#define MP_ETH_PHY1_BMSR 0x00210000 -#define MP_ETH_PHY1_PHYSID1 0x00410000 -#define MP_ETH_PHY1_PHYSID2 0x00610000 - -#define MP_PHY_BMSR_LINK 0x0004 -#define MP_PHY_BMSR_AUTONEG 0x0008 - -#define MP_PHY_88E3015 0x01410E20 - -/* TX descriptor status */ -#define MP_ETH_TX_OWN (1U << 31) - -/* RX descriptor status */ -#define MP_ETH_RX_OWN (1U << 31) - -/* Interrupt cause/mask bits */ -#define MP_ETH_IRQ_RX_BIT 0 -#define MP_ETH_IRQ_RX (1 << MP_ETH_IRQ_RX_BIT) -#define MP_ETH_IRQ_TXHI_BIT 2 -#define MP_ETH_IRQ_TXLO_BIT 3 - -/* Port config bits */ -#define MP_ETH_PCXR_2BSM_BIT 28 /* 2-byte incoming suffix */ - -/* SDMA command bits */ -#define MP_ETH_CMD_TXHI (1 << 23) -#define MP_ETH_CMD_TXLO (1 << 22) - -typedef struct mv88w8618_tx_desc { - uint32_t cmdstat; - uint16_t res; - uint16_t bytes; - uint32_t buffer; - uint32_t next; -} mv88w8618_tx_desc; - -typedef struct mv88w8618_rx_desc { - uint32_t cmdstat; - uint16_t bytes; - uint16_t buffer_size; - uint32_t buffer; - uint32_t next; -} mv88w8618_rx_desc; - -#define TYPE_MV88W8618_ETH "mv88w8618_eth" -OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_eth_state, MV88W8618_ETH) - -struct mv88w8618_eth_state { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - MemoryRegion iomem; - qemu_irq irq; - MemoryRegion *dma_mr; - AddressSpace dma_as; - uint32_t smir; - uint32_t icr; - uint32_t imr; - int mmio_index; - uint32_t vlan_header; - uint32_t tx_queue[2]; - uint32_t rx_queue[4]; - uint32_t frx_queue[4]; - uint32_t cur_rx[4]; - NICState *nic; - NICConf conf; -}; - -static void eth_rx_desc_put(AddressSpace *dma_as, uint32_t addr, - mv88w8618_rx_desc *desc) -{ - cpu_to_le32s(&desc->cmdstat); - cpu_to_le16s(&desc->bytes); - cpu_to_le16s(&desc->buffer_size); - cpu_to_le32s(&desc->buffer); - cpu_to_le32s(&desc->next); - dma_memory_write(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); -} - -static void eth_rx_desc_get(AddressSpace *dma_as, uint32_t addr, - mv88w8618_rx_desc *desc) -{ - dma_memory_read(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); - le32_to_cpus(&desc->cmdstat); - le16_to_cpus(&desc->bytes); - le16_to_cpus(&desc->buffer_size); - le32_to_cpus(&desc->buffer); - le32_to_cpus(&desc->next); -} - -static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size) -{ - mv88w8618_eth_state *s = qemu_get_nic_opaque(nc); - uint32_t desc_addr; - mv88w8618_rx_desc desc; - int i; - - for (i = 0; i < 4; i++) { - desc_addr = s->cur_rx[i]; - if (!desc_addr) { - continue; - } - do { - eth_rx_desc_get(&s->dma_as, desc_addr, &desc); - if ((desc.cmdstat & MP_ETH_RX_OWN) && desc.buffer_size >= size) { - dma_memory_write(&s->dma_as, desc.buffer + s->vlan_header, - buf, size, MEMTXATTRS_UNSPECIFIED); - desc.bytes = size + s->vlan_header; - desc.cmdstat &= ~MP_ETH_RX_OWN; - s->cur_rx[i] = desc.next; - - s->icr |= MP_ETH_IRQ_RX; - if (s->icr & s->imr) { - qemu_irq_raise(s->irq); - } - eth_rx_desc_put(&s->dma_as, desc_addr, &desc); - return size; - } - desc_addr = desc.next; - } while (desc_addr != s->rx_queue[i]); - } - return size; -} - -static void eth_tx_desc_put(AddressSpace *dma_as, uint32_t addr, - mv88w8618_tx_desc *desc) -{ - cpu_to_le32s(&desc->cmdstat); - cpu_to_le16s(&desc->res); - cpu_to_le16s(&desc->bytes); - cpu_to_le32s(&desc->buffer); - cpu_to_le32s(&desc->next); - dma_memory_write(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); -} - -static void eth_tx_desc_get(AddressSpace *dma_as, uint32_t addr, - mv88w8618_tx_desc *desc) -{ - dma_memory_read(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); - le32_to_cpus(&desc->cmdstat); - le16_to_cpus(&desc->res); - le16_to_cpus(&desc->bytes); - le32_to_cpus(&desc->buffer); - le32_to_cpus(&desc->next); -} - -static void eth_send(mv88w8618_eth_state *s, int queue_index) -{ - uint32_t desc_addr = s->tx_queue[queue_index]; - mv88w8618_tx_desc desc; - uint32_t next_desc; - uint8_t buf[2048]; - int len; - - do { - eth_tx_desc_get(&s->dma_as, desc_addr, &desc); - next_desc = desc.next; - if (desc.cmdstat & MP_ETH_TX_OWN) { - len = desc.bytes; - if (len < 2048) { - dma_memory_read(&s->dma_as, desc.buffer, buf, len, - MEMTXATTRS_UNSPECIFIED); - qemu_send_packet(qemu_get_queue(s->nic), buf, len); - } - desc.cmdstat &= ~MP_ETH_TX_OWN; - s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index); - eth_tx_desc_put(&s->dma_as, desc_addr, &desc); - } - desc_addr = next_desc; - } while (desc_addr != s->tx_queue[queue_index]); -} - -static uint64_t mv88w8618_eth_read(void *opaque, hwaddr offset, - unsigned size) -{ - mv88w8618_eth_state *s = opaque; - - switch (offset) { - case MP_ETH_SMIR: - if (s->smir & MP_ETH_SMIR_OPCODE) { - switch (s->smir & MP_ETH_SMIR_ADDR) { - case MP_ETH_PHY1_BMSR: - return MP_PHY_BMSR_LINK | MP_PHY_BMSR_AUTONEG | - MP_ETH_SMIR_RDVALID; - case MP_ETH_PHY1_PHYSID1: - return (MP_PHY_88E3015 >> 16) | MP_ETH_SMIR_RDVALID; - case MP_ETH_PHY1_PHYSID2: - return (MP_PHY_88E3015 & 0xFFFF) | MP_ETH_SMIR_RDVALID; - default: - return MP_ETH_SMIR_RDVALID; - } - } - return 0; - - case MP_ETH_ICR: - return s->icr; - - case MP_ETH_IMR: - return s->imr; - - case MP_ETH_FRDP0 ... MP_ETH_FRDP3: - return s->frx_queue[(offset - MP_ETH_FRDP0) / 4]; - - case MP_ETH_CRDP0 ... MP_ETH_CRDP3: - return s->rx_queue[(offset - MP_ETH_CRDP0) / 4]; - - case MP_ETH_CTDP0 ... MP_ETH_CTDP1: - return s->tx_queue[(offset - MP_ETH_CTDP0) / 4]; - - default: - return 0; - } -} - -static void mv88w8618_eth_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - mv88w8618_eth_state *s = opaque; - - switch (offset) { - case MP_ETH_SMIR: - s->smir = value; - break; - - case MP_ETH_PCXR: - s->vlan_header = ((value >> MP_ETH_PCXR_2BSM_BIT) & 1) * 2; - break; - - case MP_ETH_SDCMR: - if (value & MP_ETH_CMD_TXHI) { - eth_send(s, 1); - } - if (value & MP_ETH_CMD_TXLO) { - eth_send(s, 0); - } - if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr) { - qemu_irq_raise(s->irq); - } - break; - - case MP_ETH_ICR: - s->icr &= value; - break; - - case MP_ETH_IMR: - s->imr = value; - if (s->icr & s->imr) { - qemu_irq_raise(s->irq); - } - break; - - case MP_ETH_FRDP0 ... MP_ETH_FRDP3: - s->frx_queue[(offset - MP_ETH_FRDP0) / 4] = value; - break; - - case MP_ETH_CRDP0 ... MP_ETH_CRDP3: - s->rx_queue[(offset - MP_ETH_CRDP0) / 4] = - s->cur_rx[(offset - MP_ETH_CRDP0) / 4] = value; - break; - - case MP_ETH_CTDP0 ... MP_ETH_CTDP1: - s->tx_queue[(offset - MP_ETH_CTDP0) / 4] = value; - break; - } -} - -static const MemoryRegionOps mv88w8618_eth_ops = { - .read = mv88w8618_eth_read, - .write = mv88w8618_eth_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void eth_cleanup(NetClientState *nc) -{ - mv88w8618_eth_state *s = qemu_get_nic_opaque(nc); - - s->nic = NULL; -} - -static NetClientInfo net_mv88w8618_info = { - .type = NET_CLIENT_DRIVER_NIC, - .size = sizeof(NICState), - .receive = eth_receive, - .cleanup = eth_cleanup, -}; - -static void mv88w8618_eth_init(Object *obj) -{ - SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - DeviceState *dev = DEVICE(sbd); - mv88w8618_eth_state *s = MV88W8618_ETH(dev); - - sysbus_init_irq(sbd, &s->irq); - memory_region_init_io(&s->iomem, obj, &mv88w8618_eth_ops, s, - "mv88w8618-eth", MP_ETH_SIZE); - sysbus_init_mmio(sbd, &s->iomem); -} - -static void mv88w8618_eth_realize(DeviceState *dev, Error **errp) -{ - mv88w8618_eth_state *s = MV88W8618_ETH(dev); - - if (!s->dma_mr) { - error_setg(errp, TYPE_MV88W8618_ETH " 'dma-memory' link not set"); - return; - } - - address_space_init(&s->dma_as, s->dma_mr, "emac-dma"); - s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf, - object_get_typename(OBJECT(dev)), dev->id, s); -} - -static const VMStateDescription mv88w8618_eth_vmsd = { - .name = "mv88w8618_eth", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(smir, mv88w8618_eth_state), - VMSTATE_UINT32(icr, mv88w8618_eth_state), - VMSTATE_UINT32(imr, mv88w8618_eth_state), - VMSTATE_UINT32(vlan_header, mv88w8618_eth_state), - VMSTATE_UINT32_ARRAY(tx_queue, mv88w8618_eth_state, 2), - VMSTATE_UINT32_ARRAY(rx_queue, mv88w8618_eth_state, 4), - VMSTATE_UINT32_ARRAY(frx_queue, mv88w8618_eth_state, 4), - VMSTATE_UINT32_ARRAY(cur_rx, mv88w8618_eth_state, 4), - VMSTATE_END_OF_LIST() - } -}; - -static Property mv88w8618_eth_properties[] = { - DEFINE_NIC_PROPERTIES(mv88w8618_eth_state, conf), - DEFINE_PROP_LINK("dma-memory", mv88w8618_eth_state, dma_mr, - TYPE_MEMORY_REGION, MemoryRegion *), - DEFINE_PROP_END_OF_LIST(), -}; - -static void mv88w8618_eth_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->vmsd = &mv88w8618_eth_vmsd; - device_class_set_props(dc, mv88w8618_eth_properties); - dc->realize = mv88w8618_eth_realize; -} - -static const TypeInfo mv88w8618_eth_info = { - .name = TYPE_MV88W8618_ETH, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(mv88w8618_eth_state), - .instance_init = mv88w8618_eth_init, - .class_init = mv88w8618_eth_class_init, -}; - /* LCD register offsets */ #define MP_LCD_IRQCTRL 0x180 #define MP_LCD_IRQSTAT 0x184 @@ -1746,7 +1368,6 @@ static void musicpal_register_types(void) type_register_static(&mv88w8618_pic_info); type_register_static(&mv88w8618_pit_info); type_register_static(&mv88w8618_flashcfg_info); - type_register_static(&mv88w8618_eth_info); type_register_static(&mv88w8618_wlan_info); type_register_static(&musicpal_lcd_info); type_register_static(&musicpal_gpio_info); diff --git a/hw/net/meson.build b/hw/net/meson.build index bdf71f1f40..685b75badb 100644 --- a/hw/net/meson.build +++ b/hw/net/meson.build @@ -26,6 +26,7 @@ softmmu_ss.add(when: 'CONFIG_ALLWINNER_EMAC', if_true: files('allwinner_emac.c') softmmu_ss.add(when: 'CONFIG_ALLWINNER_SUN8I_EMAC', if_true: files('allwinner-sun8i-emac.c')) softmmu_ss.add(when: 'CONFIG_IMX_FEC', if_true: files('imx_fec.c')) softmmu_ss.add(when: 'CONFIG_MSF2', if_true: files('msf2-emac.c')) +softmmu_ss.add(when: 'CONFIG_MARVELL_88W8618', if_true: files('mv88w8618_eth.c')) softmmu_ss.add(when: 'CONFIG_CADENCE', if_true: files('cadence_gem.c')) softmmu_ss.add(when: 'CONFIG_STELLARIS_ENET', if_true: files('stellaris_enet.c')) diff --git a/hw/net/mv88w8618_eth.c b/hw/net/mv88w8618_eth.c new file mode 100644 index 0000000000..ef30b0d4a6 --- /dev/null +++ b/hw/net/mv88w8618_eth.c @@ -0,0 +1,403 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Marvell MV88W8618 / Freecom MusicPal emulation. + * + * Copyright (c) 2008 Jan Kiszka + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/qdev-properties.h" +#include "hw/sysbus.h" +#include "hw/irq.h" +#include "hw/net/mv88w8618_eth.h" +#include "migration/vmstate.h" +#include "sysemu/dma.h" +#include "net/net.h" + +#define MP_ETH_SIZE 0x00001000 + +/* Ethernet register offsets */ +#define MP_ETH_SMIR 0x010 +#define MP_ETH_PCXR 0x408 +#define MP_ETH_SDCMR 0x448 +#define MP_ETH_ICR 0x450 +#define MP_ETH_IMR 0x458 +#define MP_ETH_FRDP0 0x480 +#define MP_ETH_FRDP1 0x484 +#define MP_ETH_FRDP2 0x488 +#define MP_ETH_FRDP3 0x48C +#define MP_ETH_CRDP0 0x4A0 +#define MP_ETH_CRDP1 0x4A4 +#define MP_ETH_CRDP2 0x4A8 +#define MP_ETH_CRDP3 0x4AC +#define MP_ETH_CTDP0 0x4E0 +#define MP_ETH_CTDP1 0x4E4 + +/* MII PHY access */ +#define MP_ETH_SMIR_DATA 0x0000FFFF +#define MP_ETH_SMIR_ADDR 0x03FF0000 +#define MP_ETH_SMIR_OPCODE (1 << 26) /* Read value */ +#define MP_ETH_SMIR_RDVALID (1 << 27) + +/* PHY registers */ +#define MP_ETH_PHY1_BMSR 0x00210000 +#define MP_ETH_PHY1_PHYSID1 0x00410000 +#define MP_ETH_PHY1_PHYSID2 0x00610000 + +#define MP_PHY_BMSR_LINK 0x0004 +#define MP_PHY_BMSR_AUTONEG 0x0008 + +#define MP_PHY_88E3015 0x01410E20 + +/* TX descriptor status */ +#define MP_ETH_TX_OWN (1U << 31) + +/* RX descriptor status */ +#define MP_ETH_RX_OWN (1U << 31) + +/* Interrupt cause/mask bits */ +#define MP_ETH_IRQ_RX_BIT 0 +#define MP_ETH_IRQ_RX (1 << MP_ETH_IRQ_RX_BIT) +#define MP_ETH_IRQ_TXHI_BIT 2 +#define MP_ETH_IRQ_TXLO_BIT 3 + +/* Port config bits */ +#define MP_ETH_PCXR_2BSM_BIT 28 /* 2-byte incoming suffix */ + +/* SDMA command bits */ +#define MP_ETH_CMD_TXHI (1 << 23) +#define MP_ETH_CMD_TXLO (1 << 22) + +typedef struct mv88w8618_tx_desc { + uint32_t cmdstat; + uint16_t res; + uint16_t bytes; + uint32_t buffer; + uint32_t next; +} mv88w8618_tx_desc; + +typedef struct mv88w8618_rx_desc { + uint32_t cmdstat; + uint16_t bytes; + uint16_t buffer_size; + uint32_t buffer; + uint32_t next; +} mv88w8618_rx_desc; + +OBJECT_DECLARE_SIMPLE_TYPE(mv88w8618_eth_state, MV88W8618_ETH) + +struct mv88w8618_eth_state { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + MemoryRegion iomem; + qemu_irq irq; + MemoryRegion *dma_mr; + AddressSpace dma_as; + uint32_t smir; + uint32_t icr; + uint32_t imr; + int mmio_index; + uint32_t vlan_header; + uint32_t tx_queue[2]; + uint32_t rx_queue[4]; + uint32_t frx_queue[4]; + uint32_t cur_rx[4]; + NICState *nic; + NICConf conf; +}; + +static void eth_rx_desc_put(AddressSpace *dma_as, uint32_t addr, + mv88w8618_rx_desc *desc) +{ + cpu_to_le32s(&desc->cmdstat); + cpu_to_le16s(&desc->bytes); + cpu_to_le16s(&desc->buffer_size); + cpu_to_le32s(&desc->buffer); + cpu_to_le32s(&desc->next); + dma_memory_write(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); +} + +static void eth_rx_desc_get(AddressSpace *dma_as, uint32_t addr, + mv88w8618_rx_desc *desc) +{ + dma_memory_read(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); + le32_to_cpus(&desc->cmdstat); + le16_to_cpus(&desc->bytes); + le16_to_cpus(&desc->buffer_size); + le32_to_cpus(&desc->buffer); + le32_to_cpus(&desc->next); +} + +static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size) +{ + mv88w8618_eth_state *s = qemu_get_nic_opaque(nc); + uint32_t desc_addr; + mv88w8618_rx_desc desc; + int i; + + for (i = 0; i < 4; i++) { + desc_addr = s->cur_rx[i]; + if (!desc_addr) { + continue; + } + do { + eth_rx_desc_get(&s->dma_as, desc_addr, &desc); + if ((desc.cmdstat & MP_ETH_RX_OWN) && desc.buffer_size >= size) { + dma_memory_write(&s->dma_as, desc.buffer + s->vlan_header, + buf, size, MEMTXATTRS_UNSPECIFIED); + desc.bytes = size + s->vlan_header; + desc.cmdstat &= ~MP_ETH_RX_OWN; + s->cur_rx[i] = desc.next; + + s->icr |= MP_ETH_IRQ_RX; + if (s->icr & s->imr) { + qemu_irq_raise(s->irq); + } + eth_rx_desc_put(&s->dma_as, desc_addr, &desc); + return size; + } + desc_addr = desc.next; + } while (desc_addr != s->rx_queue[i]); + } + return size; +} + +static void eth_tx_desc_put(AddressSpace *dma_as, uint32_t addr, + mv88w8618_tx_desc *desc) +{ + cpu_to_le32s(&desc->cmdstat); + cpu_to_le16s(&desc->res); + cpu_to_le16s(&desc->bytes); + cpu_to_le32s(&desc->buffer); + cpu_to_le32s(&desc->next); + dma_memory_write(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); +} + +static void eth_tx_desc_get(AddressSpace *dma_as, uint32_t addr, + mv88w8618_tx_desc *desc) +{ + dma_memory_read(dma_as, addr, desc, sizeof(*desc), MEMTXATTRS_UNSPECIFIED); + le32_to_cpus(&desc->cmdstat); + le16_to_cpus(&desc->res); + le16_to_cpus(&desc->bytes); + le32_to_cpus(&desc->buffer); + le32_to_cpus(&desc->next); +} + +static void eth_send(mv88w8618_eth_state *s, int queue_index) +{ + uint32_t desc_addr = s->tx_queue[queue_index]; + mv88w8618_tx_desc desc; + uint32_t next_desc; + uint8_t buf[2048]; + int len; + + do { + eth_tx_desc_get(&s->dma_as, desc_addr, &desc); + next_desc = desc.next; + if (desc.cmdstat & MP_ETH_TX_OWN) { + len = desc.bytes; + if (len < 2048) { + dma_memory_read(&s->dma_as, desc.buffer, buf, len, + MEMTXATTRS_UNSPECIFIED); + qemu_send_packet(qemu_get_queue(s->nic), buf, len); + } + desc.cmdstat &= ~MP_ETH_TX_OWN; + s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index); + eth_tx_desc_put(&s->dma_as, desc_addr, &desc); + } + desc_addr = next_desc; + } while (desc_addr != s->tx_queue[queue_index]); +} + +static uint64_t mv88w8618_eth_read(void *opaque, hwaddr offset, + unsigned size) +{ + mv88w8618_eth_state *s = opaque; + + switch (offset) { + case MP_ETH_SMIR: + if (s->smir & MP_ETH_SMIR_OPCODE) { + switch (s->smir & MP_ETH_SMIR_ADDR) { + case MP_ETH_PHY1_BMSR: + return MP_PHY_BMSR_LINK | MP_PHY_BMSR_AUTONEG | + MP_ETH_SMIR_RDVALID; + case MP_ETH_PHY1_PHYSID1: + return (MP_PHY_88E3015 >> 16) | MP_ETH_SMIR_RDVALID; + case MP_ETH_PHY1_PHYSID2: + return (MP_PHY_88E3015 & 0xFFFF) | MP_ETH_SMIR_RDVALID; + default: + return MP_ETH_SMIR_RDVALID; + } + } + return 0; + + case MP_ETH_ICR: + return s->icr; + + case MP_ETH_IMR: + return s->imr; + + case MP_ETH_FRDP0 ... MP_ETH_FRDP3: + return s->frx_queue[(offset - MP_ETH_FRDP0) / 4]; + + case MP_ETH_CRDP0 ... MP_ETH_CRDP3: + return s->rx_queue[(offset - MP_ETH_CRDP0) / 4]; + + case MP_ETH_CTDP0 ... MP_ETH_CTDP1: + return s->tx_queue[(offset - MP_ETH_CTDP0) / 4]; + + default: + return 0; + } +} + +static void mv88w8618_eth_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + mv88w8618_eth_state *s = opaque; + + switch (offset) { + case MP_ETH_SMIR: + s->smir = value; + break; + + case MP_ETH_PCXR: + s->vlan_header = ((value >> MP_ETH_PCXR_2BSM_BIT) & 1) * 2; + break; + + case MP_ETH_SDCMR: + if (value & MP_ETH_CMD_TXHI) { + eth_send(s, 1); + } + if (value & MP_ETH_CMD_TXLO) { + eth_send(s, 0); + } + if (value & (MP_ETH_CMD_TXHI | MP_ETH_CMD_TXLO) && s->icr & s->imr) { + qemu_irq_raise(s->irq); + } + break; + + case MP_ETH_ICR: + s->icr &= value; + break; + + case MP_ETH_IMR: + s->imr = value; + if (s->icr & s->imr) { + qemu_irq_raise(s->irq); + } + break; + + case MP_ETH_FRDP0 ... MP_ETH_FRDP3: + s->frx_queue[(offset - MP_ETH_FRDP0) / 4] = value; + break; + + case MP_ETH_CRDP0 ... MP_ETH_CRDP3: + s->rx_queue[(offset - MP_ETH_CRDP0) / 4] = + s->cur_rx[(offset - MP_ETH_CRDP0) / 4] = value; + break; + + case MP_ETH_CTDP0 ... MP_ETH_CTDP1: + s->tx_queue[(offset - MP_ETH_CTDP0) / 4] = value; + break; + } +} + +static const MemoryRegionOps mv88w8618_eth_ops = { + .read = mv88w8618_eth_read, + .write = mv88w8618_eth_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void eth_cleanup(NetClientState *nc) +{ + mv88w8618_eth_state *s = qemu_get_nic_opaque(nc); + + s->nic = NULL; +} + +static NetClientInfo net_mv88w8618_info = { + .type = NET_CLIENT_DRIVER_NIC, + .size = sizeof(NICState), + .receive = eth_receive, + .cleanup = eth_cleanup, +}; + +static void mv88w8618_eth_init(Object *obj) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + DeviceState *dev = DEVICE(sbd); + mv88w8618_eth_state *s = MV88W8618_ETH(dev); + + sysbus_init_irq(sbd, &s->irq); + memory_region_init_io(&s->iomem, obj, &mv88w8618_eth_ops, s, + "mv88w8618-eth", MP_ETH_SIZE); + sysbus_init_mmio(sbd, &s->iomem); +} + +static void mv88w8618_eth_realize(DeviceState *dev, Error **errp) +{ + mv88w8618_eth_state *s = MV88W8618_ETH(dev); + + if (!s->dma_mr) { + error_setg(errp, TYPE_MV88W8618_ETH " 'dma-memory' link not set"); + return; + } + + address_space_init(&s->dma_as, s->dma_mr, "emac-dma"); + s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf, + object_get_typename(OBJECT(dev)), dev->id, s); +} + +static const VMStateDescription mv88w8618_eth_vmsd = { + .name = "mv88w8618_eth", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(smir, mv88w8618_eth_state), + VMSTATE_UINT32(icr, mv88w8618_eth_state), + VMSTATE_UINT32(imr, mv88w8618_eth_state), + VMSTATE_UINT32(vlan_header, mv88w8618_eth_state), + VMSTATE_UINT32_ARRAY(tx_queue, mv88w8618_eth_state, 2), + VMSTATE_UINT32_ARRAY(rx_queue, mv88w8618_eth_state, 4), + VMSTATE_UINT32_ARRAY(frx_queue, mv88w8618_eth_state, 4), + VMSTATE_UINT32_ARRAY(cur_rx, mv88w8618_eth_state, 4), + VMSTATE_END_OF_LIST() + } +}; + +static Property mv88w8618_eth_properties[] = { + DEFINE_NIC_PROPERTIES(mv88w8618_eth_state, conf), + DEFINE_PROP_LINK("dma-memory", mv88w8618_eth_state, dma_mr, + TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void mv88w8618_eth_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->vmsd = &mv88w8618_eth_vmsd; + device_class_set_props(dc, mv88w8618_eth_properties); + dc->realize = mv88w8618_eth_realize; +} + +static const TypeInfo mv88w8618_eth_info = { + .name = TYPE_MV88W8618_ETH, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(mv88w8618_eth_state), + .instance_init = mv88w8618_eth_init, + .class_init = mv88w8618_eth_class_init, +}; + +static void musicpal_register_types(void) +{ + type_register_static(&mv88w8618_eth_info); +} + +type_init(musicpal_register_types) + diff --git a/include/hw/net/mv88w8618_eth.h b/include/hw/net/mv88w8618_eth.h new file mode 100644 index 0000000000..8f4c746092 --- /dev/null +++ b/include/hw/net/mv88w8618_eth.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Marvell MV88W8618 / Freecom MusicPal emulation. + * + * Copyright (c) 2008-2021 QEMU contributors + */ +#ifndef HW_NET_MV88W8618_H +#define HW_NET_MV88W8618_H + +#define TYPE_MV88W8618_ETH "mv88w8618_eth" + +#endif From d55c316f910edcffbda6159053dfd59c7af02042 Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Fri, 7 Jan 2022 16:32:27 +0800 Subject: [PATCH 619/730] hw/arm/virt: Support CPU cluster on ARM virt machine ARM64 machines like Kunpeng Family Server Chips have a level of hardware topology in which a group of CPU cores share L3 cache tag or L2 cache. For example, Kunpeng 920 typically has 6 or 8 clusters in each NUMA node (also represent range of CPU die), and each cluster has 4 CPU cores. All clusters share L3 cache data, but CPU cores in each cluster share a local L3 tag. Running a guest kernel with Cluster-Aware Scheduling on the Hosts which have physical clusters, if we can design a vCPU topology with cluster level for guest kernel and then have a dedicated vCPU pinning, the guest will gain scheduling performance improvement from cache affinity of CPU cluster. So let's enable the support for this new parameter on ARM virt machines. After this patch, we can define a 4-level CPU hierarchy like: cpus=*,maxcpus=*,sockets=*,clusters=*, cores=*,threads=*. Signed-off-by: Yanan Wang Reviewed-by: Andrew Jones Message-id: 20220107083232.16256-2-wangyanan55@huawei.com Signed-off-by: Peter Maydell --- hw/arm/virt.c | 1 + qemu-options.hx | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 84c2444fff..688d873690 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2718,6 +2718,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) hc->unplug_request = virt_machine_device_unplug_request_cb; hc->unplug = virt_machine_device_unplug_cb; mc->nvdimm_supported = true; + mc->smp_props.clusters_supported = true; mc->auto_enable_numa_with_memhp = true; mc->auto_enable_numa_with_memdev = true; mc->default_ram_id = "mach-virt.ram"; diff --git a/qemu-options.hx b/qemu-options.hx index ec90505d84..ba3ae6a42a 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -277,6 +277,16 @@ SRST -smp 16,sockets=2,dies=2,cores=2,threads=2,maxcpus=16 + The following sub-option defines a CPU topology hierarchy (2 sockets + totally on the machine, 2 clusters per socket, 2 cores per cluster, + 2 threads per core) for ARM virt machines which support sockets/clusters + /cores/threads. Some members of the option can be omitted but their values + will be automatically computed: + + :: + + -smp 16,sockets=2,clusters=2,cores=2,threads=2,maxcpus=16 + Historically preference was given to the coarsest topology parameters when computing missing values (ie sockets preferred over cores, which were preferred over threads), however, this behaviour is considered From 28a60a59c06a13cb8dbbdbc06029f3d2031eb45d Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Fri, 7 Jan 2022 16:32:28 +0800 Subject: [PATCH 620/730] hw/arm/virt: Support cluster level in DT cpu-map Support one cluster level between core and physical package in the cpu-map of Arm/virt devicetree. This is also consistent with Linux Doc "Documentation/devicetree/bindings/cpu/cpu-topology.txt". Signed-off-by: Yanan Wang Reviewed-by: Andrew Jones Message-id: 20220107083232.16256-3-wangyanan55@huawei.com Signed-off-by: Peter Maydell --- hw/arm/virt.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 688d873690..177db1da12 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -434,9 +434,8 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) * can contain several layers of clustering within a single physical * package and cluster nodes can be contained in parent cluster nodes. * - * Given that cluster is not yet supported in the vCPU topology, - * we currently generate one cluster node within each socket node - * by default. + * Note: currently we only support one layer of clustering within + * each physical package. */ qemu_fdt_add_subnode(ms->fdt, "/cpus/cpu-map"); @@ -446,14 +445,16 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) if (ms->smp.threads > 1) { map_path = g_strdup_printf( - "/cpus/cpu-map/socket%d/cluster0/core%d/thread%d", - cpu / (ms->smp.cores * ms->smp.threads), + "/cpus/cpu-map/socket%d/cluster%d/core%d/thread%d", + cpu / (ms->smp.clusters * ms->smp.cores * ms->smp.threads), + (cpu / (ms->smp.cores * ms->smp.threads)) % ms->smp.clusters, (cpu / ms->smp.threads) % ms->smp.cores, cpu % ms->smp.threads); } else { map_path = g_strdup_printf( - "/cpus/cpu-map/socket%d/cluster0/core%d", - cpu / ms->smp.cores, + "/cpus/cpu-map/socket%d/cluster%d/core%d", + cpu / (ms->smp.clusters * ms->smp.cores), + (cpu / ms->smp.cores) % ms->smp.clusters, cpu % ms->smp.cores); } qemu_fdt_add_path(ms->fdt, map_path); From 11b9eb1b8a96510508178746b258810392849b20 Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Fri, 7 Jan 2022 16:32:29 +0800 Subject: [PATCH 621/730] hw/acpi/aml-build: Improve scalability of PPTT generation Use g_queue APIs to reduce the nested loops and code indentation with the processor hierarchy levels increasing. Consenquently, it's more scalable to add new topology level to build_pptt. No functional change intended. Signed-off-by: Yanan Wang Reviewed-by: Andrew Jones Message-id: 20220107083232.16256-4-wangyanan55@huawei.com Signed-off-by: Peter Maydell --- hw/acpi/aml-build.c | 50 +++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index b3b3310df3..6aaedca2e5 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -2001,7 +2001,10 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags, void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, const char *oem_id, const char *oem_table_id) { - int pptt_start = table_data->len; + GQueue *list = g_queue_new(); + guint pptt_start = table_data->len; + guint parent_offset; + guint length, i; int uid = 0; int socket; AcpiTable table = { .sig = "PPTT", .rev = 2, @@ -2010,9 +2013,8 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, acpi_table_begin(&table, table_data); for (socket = 0; socket < ms->smp.sockets; socket++) { - uint32_t socket_offset = table_data->len - pptt_start; - int core; - + g_queue_push_tail(list, + GUINT_TO_POINTER(table_data->len - pptt_start)); build_processor_hierarchy_node( table_data, /* @@ -2021,35 +2023,47 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, */ (1 << 0), 0, socket, NULL, 0); + } + length = g_queue_get_length(list); + for (i = 0; i < length; i++) { + int core; + + parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); for (core = 0; core < ms->smp.cores; core++) { - uint32_t core_offset = table_data->len - pptt_start; - int thread; - if (ms->smp.threads > 1) { + g_queue_push_tail(list, + GUINT_TO_POINTER(table_data->len - pptt_start)); build_processor_hierarchy_node( table_data, (0 << 0), /* not a physical package */ - socket_offset, core, NULL, 0); - - for (thread = 0; thread < ms->smp.threads; thread++) { - build_processor_hierarchy_node( - table_data, - (1 << 1) | /* ACPI Processor ID valid */ - (1 << 2) | /* Processor is a Thread */ - (1 << 3), /* Node is a Leaf */ - core_offset, uid++, NULL, 0); - } + parent_offset, core, NULL, 0); } else { build_processor_hierarchy_node( table_data, (1 << 1) | /* ACPI Processor ID valid */ (1 << 3), /* Node is a Leaf */ - socket_offset, uid++, NULL, 0); + parent_offset, uid++, NULL, 0); } } } + length = g_queue_get_length(list); + for (i = 0; i < length; i++) { + int thread; + + parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); + for (thread = 0; thread < ms->smp.threads; thread++) { + build_processor_hierarchy_node( + table_data, + (1 << 1) | /* ACPI Processor ID valid */ + (1 << 2) | /* Processor is a Thread */ + (1 << 3), /* Node is a Leaf */ + parent_offset, uid++, NULL, 0); + } + } + + g_queue_free(list); acpi_table_end(linker, &table); } From 291f6dd566cf1158cbdb90e282c89adbb2d2a875 Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Fri, 7 Jan 2022 16:32:30 +0800 Subject: [PATCH 622/730] tests/acpi/bios-tables-test: Allow changes to virt/PPTT file List test/data/acpi/virt/PPTT as the expected files allowed to be changed in tests/qtest/bios-tables-test-allowed-diff.h Signed-off-by: Yanan Wang Acked-by: Ani Sinha Message-id: 20220107083232.16256-5-wangyanan55@huawei.com Signed-off-by: Peter Maydell --- tests/qtest/bios-tables-test-allowed-diff.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..cb143a55a6 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,2 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/virt/PPTT", From 88d0278aa7f5c882d8a485788ab4bae4702099b8 Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Fri, 7 Jan 2022 16:32:31 +0800 Subject: [PATCH 623/730] hw/acpi/aml-build: Support cluster level in PPTT generation Support CPU cluster topology level in generation of ACPI Processor Properties Topology Table (PPTT). Signed-off-by: Yanan Wang Reviewed-by: Andrew Jones Message-id: 20220107083232.16256-6-wangyanan55@huawei.com Signed-off-by: Peter Maydell --- hw/acpi/aml-build.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 6aaedca2e5..bb2cad63b5 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -2001,6 +2001,7 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags, void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, const char *oem_id, const char *oem_table_id) { + MachineClass *mc = MACHINE_GET_CLASS(ms); GQueue *list = g_queue_new(); guint pptt_start = table_data->len; guint parent_offset; @@ -2025,6 +2026,23 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, 0, socket, NULL, 0); } + if (mc->smp_props.clusters_supported) { + length = g_queue_get_length(list); + for (i = 0; i < length; i++) { + int cluster; + + parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list)); + for (cluster = 0; cluster < ms->smp.clusters; cluster++) { + g_queue_push_tail(list, + GUINT_TO_POINTER(table_data->len - pptt_start)); + build_processor_hierarchy_node( + table_data, + (0 << 0), /* not a physical package */ + parent_offset, cluster, NULL, 0); + } + } + } + length = g_queue_get_length(list); for (i = 0; i < length; i++) { int core; From 3cda85b20308a92faa1e6e66435441735f313881 Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Fri, 7 Jan 2022 16:32:32 +0800 Subject: [PATCH 624/730] tests/acpi/bios-table-test: Update expected virt/PPTT file Run ./tests/data/acpi/rebuild-expected-aml.sh from build directory to update PPTT binary. Also empty bios-tables-test-allowed-diff.h. The disassembled differences between actual and expected PPTT: /* * Intel ACPI Component Architecture * AML/ASL+ Disassembler version 20200528 (64-bit version) * Copyright (c) 2000 - 2020 Intel Corporation * - * Disassembly of tests/data/acpi/virt/PPTT, Tue Jan 4 12:51:11 2022 + * Disassembly of /tmp/aml-2ZGOF1, Tue Jan 4 12:51:11 2022 * * ACPI Data Table [PPTT] * * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue */ [000h 0000 4] Signature : "PPTT" [Processor Properties Topology Table] -[004h 0004 4] Table Length : 0000004C +[004h 0004 4] Table Length : 00000060 [008h 0008 1] Revision : 02 -[009h 0009 1] Checksum : A8 +[009h 0009 1] Checksum : 48 [00Ah 0010 6] Oem ID : "BOCHS " [010h 0016 8] Oem Table ID : "BXPC " [018h 0024 4] Oem Revision : 00000001 [01Ch 0028 4] Asl Compiler ID : "BXPC" [020h 0032 4] Asl Compiler Revision : 00000001 [024h 0036 1] Subtable Type : 00 [Processor Hierarchy Node] [025h 0037 1] Length : 14 [026h 0038 2] Reserved : 0000 [028h 0040 4] Flags (decoded below) : 00000001 Physical package : 1 ACPI Processor ID valid : 0 Processor is a thread : 0 Node is a leaf : 0 Identical Implementation : 0 [02Ch 0044 4] Parent : 00000000 [030h 0048 4] ACPI Processor ID : 00000000 [034h 0052 4] Private Resource Number : 00000000 [038h 0056 1] Subtable Type : 00 [Processor Hierarchy Node] [039h 0057 1] Length : 14 [03Ah 0058 2] Reserved : 0000 -[03Ch 0060 4] Flags (decoded below) : 0000000A +[03Ch 0060 4] Flags (decoded below) : 00000000 Physical package : 0 - ACPI Processor ID valid : 1 + ACPI Processor ID valid : 0 Processor is a thread : 0 - Node is a leaf : 1 + Node is a leaf : 0 Identical Implementation : 0 [040h 0064 4] Parent : 00000024 [044h 0068 4] ACPI Processor ID : 00000000 [048h 0072 4] Private Resource Number : 00000000 -Raw Table Data: Length 76 (0x4C) +[04Ch 0076 1] Subtable Type : 00 [Processor Hierarchy Node] +[04Dh 0077 1] Length : 14 +[04Eh 0078 2] Reserved : 0000 +[050h 0080 4] Flags (decoded below) : 0000000A + Physical package : 0 + ACPI Processor ID valid : 1 + Processor is a thread : 0 + Node is a leaf : 1 + Identical Implementation : 0 +[054h 0084 4] Parent : 00000038 +[058h 0088 4] ACPI Processor ID : 00000000 +[05Ch 0092 4] Private Resource Number : 00000000 + +Raw Table Data: Length 96 (0x60) - 0000: 50 50 54 54 4C 00 00 00 02 A8 42 4F 43 48 53 20 // PPTTL.....BOCHS + 0000: 50 50 54 54 60 00 00 00 02 48 42 4F 43 48 53 20 // PPTT`....HBOCHS 0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43 // BXPC ....BXPC 0020: 01 00 00 00 00 14 00 00 01 00 00 00 00 00 00 00 // ................ - 0030: 00 00 00 00 00 00 00 00 00 14 00 00 0A 00 00 00 // ................ - 0040: 24 00 00 00 00 00 00 00 00 00 00 00 // $........... + 0030: 00 00 00 00 00 00 00 00 00 14 00 00 00 00 00 00 // ................ + 0040: 24 00 00 00 00 00 00 00 00 00 00 00 00 14 00 00 // $............... + 0050: 0A 00 00 00 38 00 00 00 00 00 00 00 00 00 00 00 // ....8........... Signed-off-by: Yanan Wang Reviewed-by: Ani Sinha Message-id: 20220107083232.16256-7-wangyanan55@huawei.com Signed-off-by: Peter Maydell --- tests/data/acpi/virt/PPTT | Bin 76 -> 96 bytes tests/qtest/bios-tables-test-allowed-diff.h | 1 - 2 files changed, 1 deletion(-) diff --git a/tests/data/acpi/virt/PPTT b/tests/data/acpi/virt/PPTT index 7a1258ecf123555b24462c98ccbb76b4ac1d0c2b..f56ea63b369a604877374ad696c396e796ab1c83 100644 GIT binary patch delta 53 pcmeZC;0g!`2}xjJU|{l?$YrDgWH5jU5Ca567#O&Klm(arApowi1QY-O delta 32 fcmYfB;R*-{3GrcIU|?D?k;`ae01J-_kOKn%ZFdCM diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index cb143a55a6..dfb8523c8b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,2 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/virt/PPTT", From 87f14eaa5198373e8716d6e71ad10d48ea2e7ec6 Mon Sep 17 00:00:00 2001 From: Lucas Ramage Date: Wed, 5 Jan 2022 20:56:28 +0000 Subject: [PATCH 625/730] docs/can: convert to restructuredText Buglink: https://gitlab.com/qemu-project/qemu/-/issues/527 Signed-off-by: Lucas Ramage Message-id: 20220105205628.5491-1-oxr463@gmx.us Reviewed-by: Peter Maydell [PMM: Move to docs/system/devices/ rather than top-level; fix a pre-existing typo in passing] Signed-off-by: Peter Maydell --- docs/system/device-emulation.rst | 1 + docs/{can.txt => system/devices/can.rst} | 90 +++++++++++------------- 2 files changed, 41 insertions(+), 50 deletions(-) rename docs/{can.txt => system/devices/can.rst} (68%) diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst index 19944f526c..0b3a3d73ad 100644 --- a/docs/system/device-emulation.rst +++ b/docs/system/device-emulation.rst @@ -82,6 +82,7 @@ Emulated Devices .. toctree:: :maxdepth: 1 + devices/can.rst devices/ivshmem.rst devices/net.rst devices/nvme.rst diff --git a/docs/can.txt b/docs/system/devices/can.rst similarity index 68% rename from docs/can.txt rename to docs/system/devices/can.rst index 0d310237df..16d72c3ac3 100644 --- a/docs/can.txt +++ b/docs/system/devices/can.rst @@ -1,6 +1,5 @@ -QEMU CAN bus emulation support -============================== - +CAN Bus Emulation Support +========================= The CAN bus emulation provides mechanism to connect multiple emulated CAN controller chips together by one or multiple CAN busses (the controller device "canbus" parameter). The individual busses @@ -32,34 +31,39 @@ emulated environment for testing and RTEMS GSoC slot has been donated to work on CAN hardware emulation on QEMU. Examples how to use CAN emulation for SJA1000 based boards -========================================================== - +---------------------------------------------------------- When QEMU with CAN PCI support is compiled then one of the next CAN boards can be selected - (1) CAN bus Kvaser PCI CAN-S (single SJA1000 channel) boad. QEMU startup options +(1) CAN bus Kvaser PCI CAN-S (single SJA1000 channel) board. QEMU startup options:: + -object can-bus,id=canbus0 -device kvaser_pci,canbus=canbus0 - Add "can-host-socketcan" object to connect device to host system CAN bus + +Add "can-host-socketcan" object to connect device to host system CAN bus:: + -object can-host-socketcan,id=canhost0,if=can0,canbus=canbus0 - (2) CAN bus PCM-3680I PCI (dual SJA1000 channel) emulation +(2) CAN bus PCM-3680I PCI (dual SJA1000 channel) emulation:: + -object can-bus,id=canbus0 -device pcm3680_pci,canbus0=canbus0,canbus1=canbus0 - another example: +Another example:: + -object can-bus,id=canbus0 -object can-bus,id=canbus1 -device pcm3680_pci,canbus0=canbus0,canbus1=canbus1 - (3) CAN bus MIOe-3680 PCI (dual SJA1000 channel) emulation +(3) CAN bus MIOe-3680 PCI (dual SJA1000 channel) emulation:: + -device mioe3680_pci,canbus0=canbus0 - The ''kvaser_pci'' board/device model is compatible with and has been tested with -''kvaser_pci'' driver included in mainline Linux kernel. +the ''kvaser_pci'' driver included in mainline Linux kernel. The tested setup was Linux 4.9 kernel on the host and guest side. -Example for qemu-system-x86_64: + +Example for qemu-system-x86_64:: qemu-system-x86_64 -accel kvm -kernel /boot/vmlinuz-4.9.0-4-amd64 \ -initrd ramdisk.cpio \ @@ -69,7 +73,7 @@ Example for qemu-system-x86_64: -device kvaser_pci,canbus=canbus0 \ -nographic -append "console=ttyS0" -Example for qemu-system-arm: +Example for qemu-system-arm:: qemu-system-arm -cpu arm1176 -m 256 -M versatilepb \ -kernel kernel-qemu-arm1176-versatilepb \ @@ -84,24 +88,23 @@ Example for qemu-system-arm: The CAN interface of the host system has to be configured for proper bitrate and set up. Configuration is not propagated from emulated devices through bus to the physical host device. Example configuration -for 1 Mbit/s +for 1 Mbit/s:: ip link set can0 type can bitrate 1000000 ip link set can0 up Virtual (host local only) can interface can be used on the host -side instead of physical interface +side instead of physical interface:: ip link add dev can0 type vcan The CAN interface on the host side can be used to analyze CAN -traffic with "candump" command which is included in "can-utils". +traffic with "candump" command which is included in "can-utils":: candump can0 CTU CAN FD support examples -=========================== - +--------------------------- This open-source core provides CAN FD support. CAN FD drames are delivered even to the host systems when SocketCAN interface is found CAN FD capable. @@ -113,7 +116,7 @@ on the board. Example how to connect the canbus0-bus (virtual wire) to the host Linux system (SocketCAN used) and to both CTU CAN FD cores emulated on the corresponding PCI card expects that host system CAN bus -is setup according to the previous SJA1000 section. +is setup according to the previous SJA1000 section:: qemu-system-x86_64 -enable-kvm -kernel /boot/vmlinuz-4.19.52+ \ -initrd ramdisk.cpio \ @@ -125,7 +128,7 @@ is setup according to the previous SJA1000 section. -device ctucan_pci,canbus0=canbus0-bus,canbus1=canbus0-bus \ -nographic -Setup of CTU CAN FD controller in a guest Linux system +Setup of CTU CAN FD controller in a guest Linux system:: insmod ctucanfd.ko || modprobe ctucanfd insmod ctucanfd_pci.ko || modprobe ctucanfd_pci @@ -150,19 +153,19 @@ Setup of CTU CAN FD controller in a guest Linux system /bin/ip link set $ifc up done -The test can run for example +The test can run for example:: candump can1 -in the guest system and next commands in the host system for basic CAN +in the guest system and next commands in the host system for basic CAN:: cangen can0 -for CAN FD without bitrate switch +for CAN FD without bitrate switch:: cangen can0 -f -and with bitrate switch +and with bitrate switch:: cangen can0 -b @@ -170,29 +173,16 @@ The test can be run viceversa, generate messages in the guest system and capture in the host one and much more combinations. Links to other resources -======================== +------------------------ - (1) CAN related projects at Czech Technical University, Faculty of Electrical Engineering - http://canbus.pages.fel.cvut.cz/ - (2) Repository with development can-pci branch at Czech Technical University - https://gitlab.fel.cvut.cz/canbus/qemu-canbus - (3) RTEMS page describing project - https://devel.rtems.org/wiki/Developer/Simulators/QEMU/CANEmulation - (4) RTLWS 2015 article about the project and its use with CANopen emulation - http://cmp.felk.cvut.cz/~pisa/can/doc/rtlws-17-pisa-qemu-can.pdf - (5) GNU/Linux, CAN and CANopen in Real-time Control Applications - Slides from LinuxDays 2017 (include updated RTLWS 2015 content) - https://www.linuxdays.cz/2017/video/Pavel_Pisa-CAN_canopen.pdf - (6) Linux SocketCAN utilities - https://github.com/linux-can/can-utils/ - (7) CTU CAN FD project including core VHDL design, Linux driver, - test utilities etc. - https://gitlab.fel.cvut.cz/canbus/ctucanfd_ip_core - (8) CTU CAN FD Core Datasheet Documentation - http://canbus.pages.fel.cvut.cz/ctucanfd_ip_core/Progdokum.pdf - (9) CTU CAN FD Core System Architecture Documentation - http://canbus.pages.fel.cvut.cz/ctucanfd_ip_core/ctu_can_fd_architecture.pdf - (10) CTU CAN FD Driver Documentation - http://canbus.pages.fel.cvut.cz/ctucanfd_ip_core/driver_doc/ctucanfd-driver.html - (11) Integration with PCIe interfacing for Intel/Altera Cyclone IV based board - https://gitlab.fel.cvut.cz/canbus/pcie-ctu_can_fd + (1) `CAN related projects at Czech Technical University, Faculty of Electrical Engineering `_ + (2) `Repository with development can-pci branch at Czech Technical University `_ + (3) `RTEMS page describing project `_ + (4) `RTLWS 2015 article about the project and its use with CANopen emulation `_ + (5) `GNU/Linux, CAN and CANopen in Real-time Control Applications Slides from LinuxDays 2017 (include updated RTLWS 2015 content) `_ + (6) `Linux SocketCAN utilities `_ + (7) `CTU CAN FD project including core VHDL design, Linux driver, test utilities etc. `_ + (8) `CTU CAN FD Core Datasheet Documentation `_ + (9) `CTU CAN FD Core System Architecture Documentation `_ + (10) `CTU CAN FD Driver Documentation `_ + (11) `Integration with PCIe interfacing for Intel/Altera Cyclone IV based board `_ From 1263615efe51e5f1f38f4818f0de88abc33b49a6 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 11 Jan 2022 14:33:28 +0800 Subject: [PATCH 626/730] virtio-mem: Correct default THP size for ARM64 The default block size is same as to the THP size, which is either retrieved from "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size" or hardcoded to 2MB. There are flaws in both mechanisms and this intends to fix them up. * When "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size" is used to getting the THP size, 32MB and 512MB are valid values when we have 16KB and 64KB page size on ARM64. * When the hardcoded THP size is used, 2MB, 32MB and 512MB are valid values when we have 4KB, 16KB and 64KB page sizes on ARM64. Co-developed-by: David Hildenbrand Signed-off-by: Gavin Shan Reviewed-by: Jonathan Cameron Reviewed-by: David Hildenbrand Message-id: 20220111063329.74447-2-gshan@redhat.com Signed-off-by: Peter Maydell --- hw/virtio/virtio-mem.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index 04c223b0c9..1ca45336dc 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -46,14 +46,25 @@ */ #define VIRTIO_MEM_MIN_BLOCK_SIZE ((uint32_t)(1 * MiB)) -#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \ - defined(__powerpc64__) -#define VIRTIO_MEM_DEFAULT_THP_SIZE ((uint32_t)(2 * MiB)) -#else - /* fallback to 1 MiB (e.g., the THP size on s390x) */ -#define VIRTIO_MEM_DEFAULT_THP_SIZE VIRTIO_MEM_MIN_BLOCK_SIZE +static uint32_t virtio_mem_default_thp_size(void) +{ + uint32_t default_thp_size = VIRTIO_MEM_MIN_BLOCK_SIZE; + +#if defined(__x86_64__) || defined(__arm__) || defined(__powerpc64__) + default_thp_size = 2 * MiB; +#elif defined(__aarch64__) + if (qemu_real_host_page_size == 4 * KiB) { + default_thp_size = 2 * MiB; + } else if (qemu_real_host_page_size == 16 * KiB) { + default_thp_size = 32 * MiB; + } else if (qemu_real_host_page_size == 64 * KiB) { + default_thp_size = 512 * MiB; + } #endif + return default_thp_size; +} + /* * We want to have a reasonable default block size such that * 1. We avoid splitting THPs when unplugging memory, which degrades @@ -86,11 +97,8 @@ static uint32_t virtio_mem_thp_size(void) if (g_file_get_contents(HPAGE_PMD_SIZE_PATH, &content, NULL, NULL) && !qemu_strtou64(content, &endptr, 0, &tmp) && (!endptr || *endptr == '\n')) { - /* - * Sanity-check the value, if it's too big (e.g., aarch64 with 64k base - * pages) or weird, fallback to something smaller. - */ - if (!tmp || !is_power_of_2(tmp) || tmp > 16 * MiB) { + /* Sanity-check the value and fallback to something reasonable. */ + if (!tmp || !is_power_of_2(tmp)) { warn_report("Read unsupported THP size: %" PRIx64, tmp); } else { thp_size = tmp; @@ -98,7 +106,7 @@ static uint32_t virtio_mem_thp_size(void) } if (!thp_size) { - thp_size = VIRTIO_MEM_DEFAULT_THP_SIZE; + thp_size = virtio_mem_default_thp_size(); warn_report("Could not detect THP size, falling back to %" PRIx64 " MiB.", thp_size / MiB); } From b1b87327a903e298b3b4c79da0beed31b57fb594 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Tue, 11 Jan 2022 14:33:29 +0800 Subject: [PATCH 627/730] hw/arm/virt: Support for virtio-mem-pci This supports virtio-mem-pci device on "virt" platform, by simply following the implementation on x86. * This implements the hotplug handlers to support virtio-mem-pci device hot-add, while the hot-remove isn't supported as we have on x86. * The block size is 512MB on ARM64 instead of 128MB on x86. * It has been passing the tests with various combinations like 64KB and 4KB page sizes on host and guest, different memory device backends like normal, transparent huge page and HugeTLB, plus migration. Co-developed-by: David Hildenbrand Co-developed-by: Jonathan Cameron Signed-off-by: Gavin Shan Reviewed-by: Jonathan Cameron Reviewed-by: David Hildenbrand Message-id: 20220111063329.74447-3-gshan@redhat.com Signed-off-by: Peter Maydell --- hw/arm/Kconfig | 1 + hw/arm/virt.c | 70 ++++++++++++++++++++++++++++++++++++++++++ hw/virtio/virtio-mem.c | 4 ++- 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index c459c897cc..2e0049196d 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -28,6 +28,7 @@ config ARM_VIRT select ACPI_HW_REDUCED select ACPI_APEI select ACPI_VIOT + select VIRTIO_MEM_SUPPORTED config CHEETAH bool diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 177db1da12..a76d86b592 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -71,9 +71,11 @@ #include "hw/arm/smmuv3.h" #include "hw/acpi/acpi.h" #include "target/arm/internals.h" +#include "hw/mem/memory-device.h" #include "hw/mem/pc-dimm.h" #include "hw/mem/nvdimm.h" #include "hw/acpi/generic_event_device.h" +#include "hw/virtio/virtio-mem-pci.h" #include "hw/virtio/virtio-iommu.h" #include "hw/char/pl011.h" #include "qemu/guest-random.h" @@ -2501,6 +2503,64 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev, dev, &error_abort); } +static void virt_virtio_md_pci_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + HotplugHandler *hotplug_dev2 = qdev_get_bus_hotplug_handler(dev); + Error *local_err = NULL; + + if (!hotplug_dev2 && dev->hotplugged) { + /* + * Without a bus hotplug handler, we cannot control the plug/unplug + * order. We should never reach this point when hotplugging on ARM. + * However, it's nice to add a safety net, similar to what we have + * on x86. + */ + error_setg(errp, "hotplug of virtio based memory devices not supported" + " on this bus."); + return; + } + /* + * First, see if we can plug this memory device at all. If that + * succeeds, branch of to the actual hotplug handler. + */ + memory_device_pre_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev), NULL, + &local_err); + if (!local_err && hotplug_dev2) { + hotplug_handler_pre_plug(hotplug_dev2, dev, &local_err); + } + error_propagate(errp, local_err); +} + +static void virt_virtio_md_pci_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + HotplugHandler *hotplug_dev2 = qdev_get_bus_hotplug_handler(dev); + Error *local_err = NULL; + + /* + * Plug the memory device first and then branch off to the actual + * hotplug handler. If that one fails, we can easily undo the memory + * device bits. + */ + memory_device_plug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev)); + if (hotplug_dev2) { + hotplug_handler_plug(hotplug_dev2, dev, &local_err); + if (local_err) { + memory_device_unplug(MEMORY_DEVICE(dev), MACHINE(hotplug_dev)); + } + } + error_propagate(errp, local_err); +} + +static void virt_virtio_md_pci_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + /* We don't support hot unplug of virtio based memory devices */ + error_setg(errp, "virtio based memory devices cannot be unplugged."); +} + + static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -2508,6 +2568,8 @@ static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { virt_memory_pre_plug(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { + virt_virtio_md_pci_pre_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { hwaddr db_start = 0, db_end = 0; char *resv_prop_str; @@ -2559,6 +2621,11 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { virt_memory_plug(hotplug_dev, dev, errp); } + + if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { + virt_virtio_md_pci_plug(hotplug_dev, dev, errp); + } + if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { PCIDevice *pdev = PCI_DEVICE(dev); @@ -2615,6 +2682,8 @@ static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, { if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { virt_dimm_unplug_request(hotplug_dev, dev, errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI)) { + virt_virtio_md_pci_unplug_request(hotplug_dev, dev, errp); } else { error_setg(errp, "device unplug request for unsupported device" " type: %s", object_get_typename(OBJECT(dev))); @@ -2639,6 +2708,7 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, if (device_is_dynamic_sysbus(mc, dev) || object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || + object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MEM_PCI) || object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) { return HOTPLUG_HANDLER(machine); } diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c index 1ca45336dc..f55dcf61f2 100644 --- a/hw/virtio/virtio-mem.c +++ b/hw/virtio/virtio-mem.c @@ -146,7 +146,7 @@ static bool virtio_mem_has_shared_zeropage(RAMBlock *rb) * The memory block size corresponds mostly to the section size. * * This allows e.g., to add 20MB with a section size of 128MB on x86_64, and - * a section size of 1GB on arm64 (as long as the start address is properly + * a section size of 512MB on arm64 (as long as the start address is properly * aligned, similar to ordinary DIMMs). * * We can change this at any time and maybe even make it configurable if @@ -155,6 +155,8 @@ static bool virtio_mem_has_shared_zeropage(RAMBlock *rb) */ #if defined(TARGET_X86_64) || defined(TARGET_I386) #define VIRTIO_MEM_USABLE_EXTENT (2 * (128 * MiB)) +#elif defined(TARGET_ARM) +#define VIRTIO_MEM_USABLE_EXTENT (2 * (512 * MiB)) #else #error VIRTIO_MEM_USABLE_EXTENT not defined #endif From a66a24585fae7036dc2f358c9addd1630be5c50c Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Thu, 13 Jan 2022 16:19:15 +0100 Subject: [PATCH 628/730] hw/intc/arm_gic: Implement read of GICC_IIDR Implement support for reading GICC_IIDR. This register is used by the Linux kernel to recognize that GICv2 with GICC_APRn is present. Signed-off-by: Petr Pavlu Message-id: 20220113151916.17978-2-ppavlu@suse.cz Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/intc/arm_gic.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index a994b1f024..0cd9ceca8d 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -1662,6 +1662,15 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset, } break; } + case 0xfc: + if (s->revision == REV_11MPCORE) { + /* Reserved on 11MPCore */ + *data = 0; + } else { + /* GICv1 or v2; Arm implementation */ + *data = (s->revision << 16) | 0x43b; + } + break; default: qemu_log_mask(LOG_GUEST_ERROR, "gic_cpu_read: Bad offset %x\n", (int)offset); From 5e66daec9ef0cd0107ba30225e23224c66ed24f3 Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Thu, 13 Jan 2022 16:19:16 +0100 Subject: [PATCH 629/730] hw/intc/arm_gic: Allow reset of the running priority When running Linux on a machine with GICv2, the kernel can crash while processing an interrupt and can subsequently start a kdump kernel from the active interrupt handler. In such a case, the crashed kernel might not gracefully signal the end of interrupt to the GICv2 hardware. The kdump kernel will however try to reset the GIC state on startup to get the controller into a sane state, in particular the kernel writes ones to GICD_ICACTIVERn and wipes out GICC_APRn to make sure that no interrupt is active. The patch adds a logic to recalculate the running priority when GICC_APRn/GICC_NSAPRn is written which makes sure that the mentioned reset works with the GICv2 emulation in QEMU too and the kdump kernel starts receiving interrupts. The described scenario can be reproduced on an AArch64 QEMU virt machine with a kdump-enabled Linux system by using the softdog module. The kdump kernel will hang at some point because QEMU still thinks the running priority is that of the timer interrupt and asserts no new interrupts to the system: $ modprobe softdog soft_margin=10 soft_panic=1 $ cat > /dev/watchdog [Press Enter to start the watchdog, wait for its timeout and observe that the kdump kernel hangs on startup.] Signed-off-by: Petr Pavlu Message-id: 20220113151916.17978-3-ppavlu@suse.cz Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/intc/arm_gic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 0cd9ceca8d..492b2421ab 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -1736,6 +1736,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset, } else { s->apr[regno][cpu] = value; } + s->running_priority[cpu] = gic_get_prio_from_apr_bits(s, cpu); break; } case 0xe0: case 0xe4: case 0xe8: case 0xec: @@ -1752,6 +1753,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset, return MEMTX_OK; } s->nsapr[regno][cpu] = value; + s->running_priority[cpu] = gic_get_prio_from_apr_bits(s, cpu); break; } case 0x1000: From c8f008c40fb9dc35bc0fdcd52d747c920d614725 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 14 Jan 2022 14:07:36 +0000 Subject: [PATCH 630/730] hw/arm/virt: Add a control for the the highmem PCIe MMIO Just like we can control the enablement of the highmem PCIe ECAM region using highmem_ecam, let's add a control for the highmem PCIe MMIO region. Similarily to highmem_ecam, this region is disabled when highmem is off. Signed-off-by: Marc Zyngier Reviewed-by: Eric Auger Message-id: 20220114140741.1358263-2-maz@kernel.org Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 10 ++++------ hw/arm/virt.c | 7 +++++-- include/hw/arm/virt.h | 1 + 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index f2514ce77c..449fab0080 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -158,10 +158,9 @@ static void acpi_dsdt_add_virtio(Aml *scope, } static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, - uint32_t irq, bool use_highmem, bool highmem_ecam, - VirtMachineState *vms) + uint32_t irq, VirtMachineState *vms) { - int ecam_id = VIRT_ECAM_ID(highmem_ecam); + int ecam_id = VIRT_ECAM_ID(vms->highmem_ecam); struct GPEXConfig cfg = { .mmio32 = memmap[VIRT_PCIE_MMIO], .pio = memmap[VIRT_PCIE_PIO], @@ -170,7 +169,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, .bus = vms->bus, }; - if (use_highmem) { + if (vms->highmem_mmio) { cfg.mmio64 = memmap[VIRT_HIGH_PCIE_MMIO]; } @@ -869,8 +868,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) acpi_dsdt_add_fw_cfg(scope, &memmap[VIRT_FW_CFG]); acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); - acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE), - vms->highmem, vms->highmem_ecam, vms); + acpi_dsdt_add_pci(scope, memmap, irqmap[VIRT_PCIE] + ARM_SPI_BASE, vms); if (vms->acpi_dev) { build_ged_aml(scope, "\\_SB."GED_DEVICE, HOTPLUG_HANDLER(vms->acpi_dev), diff --git a/hw/arm/virt.c b/hw/arm/virt.c index a76d86b592..16369ce10e 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1419,7 +1419,7 @@ static void create_pcie(VirtMachineState *vms) mmio_reg, base_mmio, size_mmio); memory_region_add_subregion(get_system_memory(), base_mmio, mmio_alias); - if (vms->highmem) { + if (vms->highmem_mmio) { /* Map high MMIO space */ MemoryRegion *high_mmio_alias = g_new0(MemoryRegion, 1); @@ -1473,7 +1473,7 @@ static void create_pcie(VirtMachineState *vms) qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base_ecam, 2, size_ecam); - if (vms->highmem) { + if (vms->highmem_mmio) { qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "ranges", 1, FDT_PCI_RANGE_IOPORT, 2, 0, 2, base_pio, 2, size_pio, @@ -2112,6 +2112,8 @@ static void machvirt_init(MachineState *machine) virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem); + vms->highmem_mmio &= vms->highmem; + create_gic(vms, sysmem); virt_cpu_post_init(vms, sysmem); @@ -2899,6 +2901,7 @@ static void virt_instance_init(Object *obj) vms->gic_version = VIRT_GIC_VERSION_NOSEL; vms->highmem_ecam = !vmc->no_highmem_ecam; + vms->highmem_mmio = true; if (vmc->no_its) { vms->its = false; diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index be0534608f..cf5d8b83de 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -143,6 +143,7 @@ struct VirtMachineState { bool secure; bool highmem; bool highmem_ecam; + bool highmem_mmio; bool its; bool tcg_its; bool virt; From a63618b147443de2485fb93705e21879b25c64c2 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 14 Jan 2022 14:07:37 +0000 Subject: [PATCH 631/730] hw/arm/virt: Add a control for the the highmem redistributors Just like we can control the enablement of the highmem PCIe region using highmem_ecam, let's add a control for the highmem GICv3 redistributor region. Similarily to highmem_ecam, these redistributors are disabled when highmem is off. Reviewed-by: Andrew Jones Signed-off-by: Marc Zyngier Reviewed-by: Eric Auger Message-id: 20220114140741.1358263-3-maz@kernel.org Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 2 ++ hw/arm/virt.c | 2 ++ include/hw/arm/virt.h | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 449fab0080..0757c28f69 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -947,6 +947,8 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) acpi_add_table(table_offsets, tables_blob); build_fadt_rev5(tables_blob, tables->linker, vms, dsdt); + vms->highmem_redists &= vms->highmem; + acpi_add_table(table_offsets, tables_blob); build_madt(tables_blob, tables->linker, vms); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 16369ce10e..62bdce1eb4 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2113,6 +2113,7 @@ static void machvirt_init(MachineState *machine) virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem); vms->highmem_mmio &= vms->highmem; + vms->highmem_redists &= vms->highmem; create_gic(vms, sysmem); @@ -2902,6 +2903,7 @@ static void virt_instance_init(Object *obj) vms->highmem_ecam = !vmc->no_highmem_ecam; vms->highmem_mmio = true; + vms->highmem_redists = true; if (vmc->no_its) { vms->its = false; diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index cf5d8b83de..c1ea17d0de 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -144,6 +144,7 @@ struct VirtMachineState { bool highmem; bool highmem_ecam; bool highmem_mmio; + bool highmem_redists; bool its; bool tcg_its; bool virt; @@ -191,7 +192,8 @@ static inline int virt_gicv3_redist_region_count(VirtMachineState *vms) assert(vms->gic_version == VIRT_GIC_VERSION_3); - return MACHINE(vms)->smp.cpus > redist0_capacity ? 2 : 1; + return (MACHINE(vms)->smp.cpus > redist0_capacity && + vms->highmem_redists) ? 2 : 1; } #endif /* QEMU_ARM_VIRT_H */ From 0152b169ce163b99660b80a8ed6664707e889052 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 14 Jan 2022 14:07:38 +0000 Subject: [PATCH 632/730] hw/arm/virt: Honor highmem setting when computing the memory map Even when the VM is configured with highmem=off, the highest_gpa field includes devices that are above the 4GiB limit. Similarily, nothing seem to check that the memory is within the limit set by the highmem=off option. This leads to failures in virt_kvm_type() on systems that have a crippled IPA range, as the reported IPA space is larger than what it should be. Instead, honor the user-specified limit to only use the devices at the lowest end of the spectrum, and fail if we have memory crossing the 4GiB limit. Reviewed-by: Andrew Jones Reviewed-by: Eric Auger Signed-off-by: Marc Zyngier Message-id: 20220114140741.1358263-4-maz@kernel.org Signed-off-by: Peter Maydell --- hw/arm/virt.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 62bdce1eb4..3b839ba78b 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1670,7 +1670,7 @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx) static void virt_set_memmap(VirtMachineState *vms) { MachineState *ms = MACHINE(vms); - hwaddr base, device_memory_base, device_memory_size; + hwaddr base, device_memory_base, device_memory_size, memtop; int i; vms->memmap = extended_memmap; @@ -1697,7 +1697,11 @@ static void virt_set_memmap(VirtMachineState *vms) device_memory_size = ms->maxram_size - ms->ram_size + ms->ram_slots * GiB; /* Base address of the high IO region */ - base = device_memory_base + ROUND_UP(device_memory_size, GiB); + memtop = base = device_memory_base + ROUND_UP(device_memory_size, GiB); + if (!vms->highmem && memtop > 4 * GiB) { + error_report("highmem=off, but memory crosses the 4GiB limit\n"); + exit(EXIT_FAILURE); + } if (base < device_memory_base) { error_report("maxmem/slots too huge"); exit(EXIT_FAILURE); @@ -1714,7 +1718,7 @@ static void virt_set_memmap(VirtMachineState *vms) vms->memmap[i].size = size; base += size; } - vms->highest_gpa = base - 1; + vms->highest_gpa = (vms->highmem ? base : memtop) - 1; if (device_memory_size > 0) { ms->device_memory = g_malloc0(sizeof(*ms->device_memory)); ms->device_memory->base = device_memory_base; From 3715c251cc781b263fbd7f7c535fde7a4da401c3 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 14 Jan 2022 14:07:39 +0000 Subject: [PATCH 633/730] hw/arm/virt: Use the PA range to compute the memory map The highmem attribute is nothing but another way to express the PA range of a VM. To support HW that has a smaller PA range then what QEMU assumes, pass this PA range to the virt_set_memmap() function, allowing it to correctly exclude highmem devices if they are outside of the PA range. Signed-off-by: Marc Zyngier Reviewed-by: Eric Auger Message-id: 20220114140741.1358263-5-maz@kernel.org Signed-off-by: Peter Maydell --- hw/arm/virt.c | 64 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 3b839ba78b..8627f5ab95 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1667,7 +1667,7 @@ static uint64_t virt_cpu_mp_affinity(VirtMachineState *vms, int idx) return arm_cpu_mp_affinity(idx, clustersz); } -static void virt_set_memmap(VirtMachineState *vms) +static void virt_set_memmap(VirtMachineState *vms, int pa_bits) { MachineState *ms = MACHINE(vms); hwaddr base, device_memory_base, device_memory_size, memtop; @@ -1685,6 +1685,14 @@ static void virt_set_memmap(VirtMachineState *vms) exit(EXIT_FAILURE); } + /* + * !highmem is exactly the same as limiting the PA space to 32bit, + * irrespective of the underlying capabilities of the HW. + */ + if (!vms->highmem) { + pa_bits = 32; + } + /* * We compute the base of the high IO region depending on the * amount of initial and device memory. The device memory start/size @@ -1698,8 +1706,9 @@ static void virt_set_memmap(VirtMachineState *vms) /* Base address of the high IO region */ memtop = base = device_memory_base + ROUND_UP(device_memory_size, GiB); - if (!vms->highmem && memtop > 4 * GiB) { - error_report("highmem=off, but memory crosses the 4GiB limit\n"); + if (memtop > BIT_ULL(pa_bits)) { + error_report("Addressing limited to %d bits, but memory exceeds it by %llu bytes\n", + pa_bits, memtop - BIT_ULL(pa_bits)); exit(EXIT_FAILURE); } if (base < device_memory_base) { @@ -1718,7 +1727,13 @@ static void virt_set_memmap(VirtMachineState *vms) vms->memmap[i].size = size; base += size; } - vms->highest_gpa = (vms->highmem ? base : memtop) - 1; + + /* + * If base fits within pa_bits, all good. If it doesn't, limit it + * to the end of RAM, which is guaranteed to fit within pa_bits. + */ + vms->highest_gpa = (base <= BIT_ULL(pa_bits) ? base : memtop) - 1; + if (device_memory_size > 0) { ms->device_memory = g_malloc0(sizeof(*ms->device_memory)); ms->device_memory->base = device_memory_base; @@ -1909,12 +1924,43 @@ static void machvirt_init(MachineState *machine) unsigned int smp_cpus = machine->smp.cpus; unsigned int max_cpus = machine->smp.max_cpus; + if (!cpu_type_valid(machine->cpu_type)) { + error_report("mach-virt: CPU type %s not supported", machine->cpu_type); + exit(1); + } + + possible_cpus = mc->possible_cpu_arch_ids(machine); + /* * In accelerated mode, the memory map is computed earlier in kvm_type() * to create a VM with the right number of IPA bits. */ if (!vms->memmap) { - virt_set_memmap(vms); + Object *cpuobj; + ARMCPU *armcpu; + int pa_bits; + + /* + * Instanciate a temporary CPU object to find out about what + * we are about to deal with. Once this is done, get rid of + * the object. + */ + cpuobj = object_new(possible_cpus->cpus[0].type); + armcpu = ARM_CPU(cpuobj); + + if (object_property_get_bool(cpuobj, "aarch64", NULL)) { + pa_bits = arm_pamax(armcpu); + } else if (arm_feature(&armcpu->env, ARM_FEATURE_LPAE)) { + /* v7 with LPAE */ + pa_bits = 40; + } else { + /* Anything else */ + pa_bits = 32; + } + + object_unref(cpuobj); + + virt_set_memmap(vms, pa_bits); } /* We can probe only here because during property set @@ -1922,11 +1968,6 @@ static void machvirt_init(MachineState *machine) */ finalize_gic_version(vms); - if (!cpu_type_valid(machine->cpu_type)) { - error_report("mach-virt: CPU type %s not supported", machine->cpu_type); - exit(1); - } - if (vms->secure) { /* * The Secure view of the world is the same as the NonSecure, @@ -1996,7 +2037,6 @@ static void machvirt_init(MachineState *machine) create_fdt(vms); - possible_cpus = mc->possible_cpu_arch_ids(machine); assert(possible_cpus->len == max_cpus); for (n = 0; n < possible_cpus->len; n++) { Object *cpuobj; @@ -2735,7 +2775,7 @@ static int virt_kvm_type(MachineState *ms, const char *type_str) max_vm_pa_size = kvm_arm_get_max_vm_ipa_size(ms, &fixed_ipa); /* we freeze the memory map to compute the highest gpa */ - virt_set_memmap(vms); + virt_set_memmap(vms, max_vm_pa_size); requested_pa_size = 64 - clz64(vms->highest_gpa); From d9afe24c29a0985b29d7535b2f1615affbd1a888 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 14 Jan 2022 14:07:40 +0000 Subject: [PATCH 634/730] hw/arm/virt: Disable highmem devices that don't fit in the PA range In order to only keep the highmem devices that actually fit in the PA range, check their location against the range and update highest_gpa if they fit. If they don't, mark them as disabled. Signed-off-by: Marc Zyngier Reviewed-by: Eric Auger Message-id: 20220114140741.1358263-6-maz@kernel.org Signed-off-by: Peter Maydell --- hw/arm/virt.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 8627f5ab95..8d02c2267d 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1719,21 +1719,43 @@ static void virt_set_memmap(VirtMachineState *vms, int pa_bits) base = vms->memmap[VIRT_MEM].base + LEGACY_RAMLIMIT_BYTES; } + /* We know for sure that at least the memory fits in the PA space */ + vms->highest_gpa = memtop - 1; + for (i = VIRT_LOWMEMMAP_LAST; i < ARRAY_SIZE(extended_memmap); i++) { hwaddr size = extended_memmap[i].size; + bool fits; base = ROUND_UP(base, size); vms->memmap[i].base = base; vms->memmap[i].size = size; + + /* + * Check each device to see if they fit in the PA space, + * moving highest_gpa as we go. + * + * For each device that doesn't fit, disable it. + */ + fits = (base + size) <= BIT_ULL(pa_bits); + if (fits) { + vms->highest_gpa = base + size - 1; + } + + switch (i) { + case VIRT_HIGH_GIC_REDIST2: + vms->highmem_redists &= fits; + break; + case VIRT_HIGH_PCIE_ECAM: + vms->highmem_ecam &= fits; + break; + case VIRT_HIGH_PCIE_MMIO: + vms->highmem_mmio &= fits; + break; + } + base += size; } - /* - * If base fits within pa_bits, all good. If it doesn't, limit it - * to the end of RAM, which is guaranteed to fit within pa_bits. - */ - vms->highest_gpa = (base <= BIT_ULL(pa_bits) ? base : memtop) - 1; - if (device_memory_size > 0) { ms->device_memory = g_malloc0(sizeof(*ms->device_memory)); ms->device_memory->base = device_memory_base; From 2dcb74e5c271b9bb581013b949e4ef3bb3f6969b Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 14 Jan 2022 14:07:41 +0000 Subject: [PATCH 635/730] hw/arm/virt: Drop superfluous checks against highmem Now that the devices present in the extended memory map are checked against the available PA space and disabled when they don't fit, there is no need to keep the same checks against highmem, as highmem really is a shortcut for the PA space being 32bit. Reviewed-by: Eric Auger Signed-off-by: Marc Zyngier Message-id: 20220114140741.1358263-7-maz@kernel.org Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 2 -- hw/arm/virt.c | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 0757c28f69..449fab0080 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -947,8 +947,6 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) acpi_add_table(table_offsets, tables_blob); build_fadt_rev5(tables_blob, tables->linker, vms, dsdt); - vms->highmem_redists &= vms->highmem; - acpi_add_table(table_offsets, tables_blob); build_madt(tables_blob, tables->linker, vms); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 8d02c2267d..141350bf21 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2178,9 +2178,6 @@ static void machvirt_init(MachineState *machine) virt_flash_fdt(vms, sysmem, secure_sysmem ?: sysmem); - vms->highmem_mmio &= vms->highmem; - vms->highmem_redists &= vms->highmem; - create_gic(vms, sysmem); virt_cpu_post_init(vms, sysmem); @@ -2199,7 +2196,7 @@ static void machvirt_init(MachineState *machine) machine->ram_size, "mach-virt.tag"); } - vms->highmem_ecam &= vms->highmem && (!firmware_loaded || aarch64); + vms->highmem_ecam &= (!firmware_loaded || aarch64); create_rtc(vms); From 0419e6a867f9cbb4edc819b5d278a33f441b6051 Mon Sep 17 00:00:00 2001 From: Patrick Venture Date: Tue, 11 Jan 2022 09:23:38 -0800 Subject: [PATCH 636/730] hw/arm: kudo add lm75s behind bus 1 switch at 75 Reviewed-by: Hao Wu Signed-off-by: Patrick Venture Message-id: 20220111172338.1525587-1-venture@google.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/npcm7xx_boards.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c index 7d0f3148be..d701e5cc55 100644 --- a/hw/arm/npcm7xx_boards.c +++ b/hw/arm/npcm7xx_boards.c @@ -332,7 +332,15 @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc) { I2CSlave *i2c_mux; - i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x75); + i2c_mux = i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), + TYPE_PCA9548, 0x75); + + /* tmp105 is compatible with the lm75 */ + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 4), "tmp105", 0x5c); + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), "tmp105", 0x5c); + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 6), "tmp105", 0x5c); + i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 7), "tmp105", 0x5c); + i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x77); i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), TYPE_PCA9548, 0x77); From 119df56bf059431190ed5509f6e3e459d7892723 Mon Sep 17 00:00:00 2001 From: Troy Lee Date: Tue, 11 Jan 2022 16:45:45 +0800 Subject: [PATCH 637/730] hw/misc/aspeed_i3c.c: Introduce a dummy AST2600 I3C model. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aspeed 2600 SDK enables I3C support by default. The I3C driver will try to reset the device controller and set it up through device address table register. This dummy model responds to these registers with default values as listed in the ast2600v10 datasheet chapter 54.2. This avoids a guest machine kernel panic due to referencing an invalid kernel address if the device address table register isn't set correctly. Signed-off-by: Troy Lee Reviewed-by: Graeme Gregory Reviewed-by: Cédric Le Goater Tested-by: Graeme Gregory Message-id: 20220111084546.4145785-2-troy_lee@aspeedtech.com [PMM: tidied commit message; fixed format strings] Signed-off-by: Peter Maydell --- hw/misc/aspeed_i3c.c | 384 +++++++++++++++++++++++++++++++++++ hw/misc/meson.build | 1 + hw/misc/trace-events | 6 + include/hw/misc/aspeed_i3c.h | 48 +++++ 4 files changed, 439 insertions(+) create mode 100644 hw/misc/aspeed_i3c.c create mode 100644 include/hw/misc/aspeed_i3c.h diff --git a/hw/misc/aspeed_i3c.c b/hw/misc/aspeed_i3c.c new file mode 100644 index 0000000000..f54f5da522 --- /dev/null +++ b/hw/misc/aspeed_i3c.c @@ -0,0 +1,384 @@ +/* + * ASPEED I3C Controller + * + * Copyright (C) 2021 ASPEED Technology Inc. + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "hw/misc/aspeed_i3c.h" +#include "hw/registerfields.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "migration/vmstate.h" +#include "trace.h" + +/* I3C Controller Registers */ +REG32(I3C1_REG0, 0x10) +REG32(I3C1_REG1, 0x14) + FIELD(I3C1_REG1, I2C_MODE, 0, 1) + FIELD(I3C1_REG1, SA_EN, 15, 1) +REG32(I3C2_REG0, 0x20) +REG32(I3C2_REG1, 0x24) + FIELD(I3C2_REG1, I2C_MODE, 0, 1) + FIELD(I3C2_REG1, SA_EN, 15, 1) +REG32(I3C3_REG0, 0x30) +REG32(I3C3_REG1, 0x34) + FIELD(I3C3_REG1, I2C_MODE, 0, 1) + FIELD(I3C3_REG1, SA_EN, 15, 1) +REG32(I3C4_REG0, 0x40) +REG32(I3C4_REG1, 0x44) + FIELD(I3C4_REG1, I2C_MODE, 0, 1) + FIELD(I3C4_REG1, SA_EN, 15, 1) +REG32(I3C5_REG0, 0x50) +REG32(I3C5_REG1, 0x54) + FIELD(I3C5_REG1, I2C_MODE, 0, 1) + FIELD(I3C5_REG1, SA_EN, 15, 1) +REG32(I3C6_REG0, 0x60) +REG32(I3C6_REG1, 0x64) + FIELD(I3C6_REG1, I2C_MODE, 0, 1) + FIELD(I3C6_REG1, SA_EN, 15, 1) + +/* I3C Device Registers */ +REG32(DEVICE_CTRL, 0x00) +REG32(DEVICE_ADDR, 0x04) +REG32(HW_CAPABILITY, 0x08) +REG32(COMMAND_QUEUE_PORT, 0x0c) +REG32(RESPONSE_QUEUE_PORT, 0x10) +REG32(RX_TX_DATA_PORT, 0x14) +REG32(IBI_QUEUE_STATUS, 0x18) +REG32(IBI_QUEUE_DATA, 0x18) +REG32(QUEUE_THLD_CTRL, 0x1c) +REG32(DATA_BUFFER_THLD_CTRL, 0x20) +REG32(IBI_QUEUE_CTRL, 0x24) +REG32(IBI_MR_REQ_REJECT, 0x2c) +REG32(IBI_SIR_REQ_REJECT, 0x30) +REG32(RESET_CTRL, 0x34) +REG32(SLV_EVENT_CTRL, 0x38) +REG32(INTR_STATUS, 0x3c) +REG32(INTR_STATUS_EN, 0x40) +REG32(INTR_SIGNAL_EN, 0x44) +REG32(INTR_FORCE, 0x48) +REG32(QUEUE_STATUS_LEVEL, 0x4c) +REG32(DATA_BUFFER_STATUS_LEVEL, 0x50) +REG32(PRESENT_STATE, 0x54) +REG32(CCC_DEVICE_STATUS, 0x58) +REG32(DEVICE_ADDR_TABLE_POINTER, 0x5c) + FIELD(DEVICE_ADDR_TABLE_POINTER, DEPTH, 16, 16) + FIELD(DEVICE_ADDR_TABLE_POINTER, ADDR, 0, 16) +REG32(DEV_CHAR_TABLE_POINTER, 0x60) +REG32(VENDOR_SPECIFIC_REG_POINTER, 0x6c) +REG32(SLV_MIPI_PID_VALUE, 0x70) +REG32(SLV_PID_VALUE, 0x74) +REG32(SLV_CHAR_CTRL, 0x78) +REG32(SLV_MAX_LEN, 0x7c) +REG32(MAX_READ_TURNAROUND, 0x80) +REG32(MAX_DATA_SPEED, 0x84) +REG32(SLV_DEBUG_STATUS, 0x88) +REG32(SLV_INTR_REQ, 0x8c) +REG32(DEVICE_CTRL_EXTENDED, 0xb0) +REG32(SCL_I3C_OD_TIMING, 0xb4) +REG32(SCL_I3C_PP_TIMING, 0xb8) +REG32(SCL_I2C_FM_TIMING, 0xbc) +REG32(SCL_I2C_FMP_TIMING, 0xc0) +REG32(SCL_EXT_LCNT_TIMING, 0xc8) +REG32(SCL_EXT_TERMN_LCNT_TIMING, 0xcc) +REG32(BUS_FREE_TIMING, 0xd4) +REG32(BUS_IDLE_TIMING, 0xd8) +REG32(I3C_VER_ID, 0xe0) +REG32(I3C_VER_TYPE, 0xe4) +REG32(EXTENDED_CAPABILITY, 0xe8) +REG32(SLAVE_CONFIG, 0xec) + +static const uint32_t ast2600_i3c_device_resets[ASPEED_I3C_DEVICE_NR_REGS] = { + [R_HW_CAPABILITY] = 0x000e00bf, + [R_QUEUE_THLD_CTRL] = 0x01000101, + [R_I3C_VER_ID] = 0x3130302a, + [R_I3C_VER_TYPE] = 0x6c633033, + [R_DEVICE_ADDR_TABLE_POINTER] = 0x00080280, + [R_DEV_CHAR_TABLE_POINTER] = 0x00020200, + [A_VENDOR_SPECIFIC_REG_POINTER] = 0x000000b0, + [R_SLV_MAX_LEN] = 0x00ff00ff, +}; + +static uint64_t aspeed_i3c_device_read(void *opaque, hwaddr offset, + unsigned size) +{ + AspeedI3CDevice *s = ASPEED_I3C_DEVICE(opaque); + uint32_t addr = offset >> 2; + uint64_t value; + + switch (addr) { + case R_COMMAND_QUEUE_PORT: + value = 0; + break; + default: + value = s->regs[addr]; + break; + } + + trace_aspeed_i3c_device_read(s->id, offset, value); + + return value; +} + +static void aspeed_i3c_device_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + AspeedI3CDevice *s = ASPEED_I3C_DEVICE(opaque); + uint32_t addr = offset >> 2; + + trace_aspeed_i3c_device_write(s->id, offset, value); + + switch (addr) { + case R_HW_CAPABILITY: + case R_RESPONSE_QUEUE_PORT: + case R_IBI_QUEUE_DATA: + case R_QUEUE_STATUS_LEVEL: + case R_PRESENT_STATE: + case R_CCC_DEVICE_STATUS: + case R_DEVICE_ADDR_TABLE_POINTER: + case R_VENDOR_SPECIFIC_REG_POINTER: + case R_SLV_CHAR_CTRL: + case R_SLV_MAX_LEN: + case R_MAX_READ_TURNAROUND: + case R_I3C_VER_ID: + case R_I3C_VER_TYPE: + case R_EXTENDED_CAPABILITY: + qemu_log_mask(LOG_GUEST_ERROR, + "%s: write to readonly register[0x%02" HWADDR_PRIx + "] = 0x%08" PRIx64 "\n", + __func__, offset, value); + break; + case R_RX_TX_DATA_PORT: + break; + case R_RESET_CTRL: + break; + default: + s->regs[addr] = value; + break; + } +} + +static const VMStateDescription aspeed_i3c_device_vmstate = { + .name = TYPE_ASPEED_I3C, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]){ + VMSTATE_UINT32_ARRAY(regs, AspeedI3CDevice, ASPEED_I3C_DEVICE_NR_REGS), + VMSTATE_END_OF_LIST(), + } +}; + +static const MemoryRegionOps aspeed_i3c_device_ops = { + .read = aspeed_i3c_device_read, + .write = aspeed_i3c_device_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void aspeed_i3c_device_reset(DeviceState *dev) +{ + AspeedI3CDevice *s = ASPEED_I3C_DEVICE(dev); + + memcpy(s->regs, ast2600_i3c_device_resets, sizeof(s->regs)); +} + +static void aspeed_i3c_device_realize(DeviceState *dev, Error **errp) +{ + AspeedI3CDevice *s = ASPEED_I3C_DEVICE(dev); + g_autofree char *name = g_strdup_printf(TYPE_ASPEED_I3C_DEVICE ".%d", + s->id); + + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq); + + memory_region_init_io(&s->mr, OBJECT(s), &aspeed_i3c_device_ops, + s, name, ASPEED_I3C_DEVICE_NR_REGS << 2); +} + +static uint64_t aspeed_i3c_read(void *opaque, hwaddr addr, unsigned int size) +{ + AspeedI3CState *s = ASPEED_I3C(opaque); + uint64_t val = 0; + + val = s->regs[addr >> 2]; + + trace_aspeed_i3c_read(addr, val); + + return val; +} + +static void aspeed_i3c_write(void *opaque, + hwaddr addr, + uint64_t data, + unsigned int size) +{ + AspeedI3CState *s = ASPEED_I3C(opaque); + + trace_aspeed_i3c_write(addr, data); + + addr >>= 2; + + /* I3C controller register */ + switch (addr) { + case R_I3C1_REG1: + case R_I3C2_REG1: + case R_I3C3_REG1: + case R_I3C4_REG1: + case R_I3C5_REG1: + case R_I3C6_REG1: + if (data & R_I3C1_REG1_I2C_MODE_MASK) { + qemu_log_mask(LOG_UNIMP, + "%s: Unsupported I2C mode [0x%08" HWADDR_PRIx + "]=%08" PRIx64 "\n", + __func__, addr << 2, data); + break; + } + if (data & R_I3C1_REG1_SA_EN_MASK) { + qemu_log_mask(LOG_UNIMP, + "%s: Unsupported slave mode [%08" HWADDR_PRIx + "]=0x%08" PRIx64 "\n", + __func__, addr << 2, data); + break; + } + s->regs[addr] = data; + break; + default: + s->regs[addr] = data; + break; + } +} + +static const MemoryRegionOps aspeed_i3c_ops = { + .read = aspeed_i3c_read, + .write = aspeed_i3c_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + } +}; + +static void aspeed_i3c_reset(DeviceState *dev) +{ + AspeedI3CState *s = ASPEED_I3C(dev); + memset(s->regs, 0, sizeof(s->regs)); +} + +static void aspeed_i3c_instance_init(Object *obj) +{ + AspeedI3CState *s = ASPEED_I3C(obj); + int i; + + for (i = 0; i < ASPEED_I3C_NR_DEVICES; ++i) { + object_initialize_child(obj, "device[*]", &s->devices[i], + TYPE_ASPEED_I3C_DEVICE); + } +} + +static void aspeed_i3c_realize(DeviceState *dev, Error **errp) +{ + int i; + AspeedI3CState *s = ASPEED_I3C(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + memory_region_init(&s->iomem_container, OBJECT(s), + TYPE_ASPEED_I3C ".container", 0x8000); + + sysbus_init_mmio(sbd, &s->iomem_container); + + memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_i3c_ops, s, + TYPE_ASPEED_I3C ".regs", ASPEED_I3C_NR_REGS << 2); + + memory_region_add_subregion(&s->iomem_container, 0x0, &s->iomem); + + for (i = 0; i < ASPEED_I3C_NR_DEVICES; ++i) { + Object *dev = OBJECT(&s->devices[i]); + + if (!object_property_set_uint(dev, "device-id", i, errp)) { + return; + } + + if (!sysbus_realize(SYS_BUS_DEVICE(dev), errp)) { + return; + } + + /* + * Register Address of I3CX Device = + * (Base Address of Global Register) + (Offset of I3CX) + Offset + * X = 0, 1, 2, 3, 4, 5 + * Offset of I3C0 = 0x2000 + * Offset of I3C1 = 0x3000 + * Offset of I3C2 = 0x4000 + * Offset of I3C3 = 0x5000 + * Offset of I3C4 = 0x6000 + * Offset of I3C5 = 0x7000 + */ + memory_region_add_subregion(&s->iomem_container, + 0x2000 + i * 0x1000, &s->devices[i].mr); + } + +} + +static Property aspeed_i3c_device_properties[] = { + DEFINE_PROP_UINT8("device-id", AspeedI3CDevice, id, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void aspeed_i3c_device_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "Aspeed I3C Device"; + dc->realize = aspeed_i3c_device_realize; + dc->reset = aspeed_i3c_device_reset; + device_class_set_props(dc, aspeed_i3c_device_properties); +} + +static const TypeInfo aspeed_i3c_device_info = { + .name = TYPE_ASPEED_I3C_DEVICE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(AspeedI3CDevice), + .class_init = aspeed_i3c_device_class_init, +}; + +static const VMStateDescription vmstate_aspeed_i3c = { + .name = TYPE_ASPEED_I3C, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, AspeedI3CState, ASPEED_I3C_NR_REGS), + VMSTATE_STRUCT_ARRAY(devices, AspeedI3CState, ASPEED_I3C_NR_DEVICES, 1, + aspeed_i3c_device_vmstate, AspeedI3CDevice), + VMSTATE_END_OF_LIST(), + } +}; + +static void aspeed_i3c_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = aspeed_i3c_realize; + dc->reset = aspeed_i3c_reset; + dc->desc = "Aspeed I3C Controller"; + dc->vmsd = &vmstate_aspeed_i3c; +} + +static const TypeInfo aspeed_i3c_info = { + .name = TYPE_ASPEED_I3C, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_init = aspeed_i3c_instance_init, + .instance_size = sizeof(AspeedI3CState), + .class_init = aspeed_i3c_class_init, +}; + +static void aspeed_i3c_register_types(void) +{ + type_register_static(&aspeed_i3c_device_info); + type_register_static(&aspeed_i3c_info); +} + +type_init(aspeed_i3c_register_types); diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 3f41a3a5b2..d1a1169108 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -105,6 +105,7 @@ softmmu_ss.add(when: 'CONFIG_PVPANIC_PCI', if_true: files('pvpanic-pci.c')) softmmu_ss.add(when: 'CONFIG_AUX', if_true: files('auxbus.c')) softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files( 'aspeed_hace.c', + 'aspeed_i3c.c', 'aspeed_lpc.c', 'aspeed_scu.c', 'aspeed_sdmc.c', diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 2da96d167a..1c373dd0a4 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -199,6 +199,12 @@ armsse_mhu_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 MHU wri # aspeed_xdma.c aspeed_xdma_write(uint64_t offset, uint64_t data) "XDMA write: offset 0x%" PRIx64 " data 0x%" PRIx64 +# aspeed_i3c.c +aspeed_i3c_read(uint64_t offset, uint64_t data) "I3C read: offset 0x%" PRIx64 " data 0x%" PRIx64 +aspeed_i3c_write(uint64_t offset, uint64_t data) "I3C write: offset 0x%" PRIx64 " data 0x%" PRIx64 +aspeed_i3c_device_read(uint32_t deviceid, uint64_t offset, uint64_t data) "I3C Dev[%u] read: offset 0x%" PRIx64 " data 0x%" PRIx64 +aspeed_i3c_device_write(uint32_t deviceid, uint64_t offset, uint64_t data) "I3C Dev[%u] write: offset 0x%" PRIx64 " data 0x%" PRIx64 + # bcm2835_property.c bcm2835_mbox_property(uint32_t tag, uint32_t bufsize, size_t resplen) "mbox property tag:0x%08x in_sz:%u out_sz:%zu" diff --git a/include/hw/misc/aspeed_i3c.h b/include/hw/misc/aspeed_i3c.h new file mode 100644 index 0000000000..39679dfa1a --- /dev/null +++ b/include/hw/misc/aspeed_i3c.h @@ -0,0 +1,48 @@ +/* + * ASPEED I3C Controller + * + * Copyright (C) 2021 ASPEED Technology Inc. + * + * This code is licensed under the GPL version 2 or later. See + * the COPYING file in the top-level directory. + */ + +#ifndef ASPEED_I3C_H +#define ASPEED_I3C_H + +#include "hw/sysbus.h" + +#define TYPE_ASPEED_I3C "aspeed.i3c" +#define TYPE_ASPEED_I3C_DEVICE "aspeed.i3c.device" +OBJECT_DECLARE_TYPE(AspeedI3CState, AspeedI3CClass, ASPEED_I3C) + +#define ASPEED_I3C_NR_REGS (0x70 >> 2) +#define ASPEED_I3C_DEVICE_NR_REGS (0x300 >> 2) +#define ASPEED_I3C_NR_DEVICES 6 + +OBJECT_DECLARE_SIMPLE_TYPE(AspeedI3CDevice, ASPEED_I3C_DEVICE) +typedef struct AspeedI3CDevice { + /* */ + SysBusDevice parent; + + /* */ + MemoryRegion mr; + qemu_irq irq; + + uint8_t id; + uint32_t regs[ASPEED_I3C_DEVICE_NR_REGS]; +} AspeedI3CDevice; + +typedef struct AspeedI3CState { + /* */ + SysBusDevice parent; + + /* */ + MemoryRegion iomem; + MemoryRegion iomem_container; + qemu_irq irq; + + uint32_t regs[ASPEED_I3C_NR_REGS]; + AspeedI3CDevice devices[ASPEED_I3C_NR_DEVICES]; +} AspeedI3CState; +#endif /* ASPEED_I3C_H */ From 3222165dcb7ec2d390e400d5c886d67b582f37d7 Mon Sep 17 00:00:00 2001 From: Troy Lee Date: Tue, 11 Jan 2022 16:45:46 +0800 Subject: [PATCH 638/730] hw/arm/aspeed: Add the i3c device to the AST2600 SoC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the new i3c device to the AST2600 SoC. Signed-off-by: Troy Lee Reviewed-by: Graeme Gregory Reviewed-by: Cédric Le Goater Tested-by: Graeme Gregory Message-id: 20220111084546.4145785-3-troy_lee@aspeedtech.com [PMM: tidied commit message] Signed-off-by: Peter Maydell --- hw/arm/aspeed_ast2600.c | 16 ++++++++++++++++ include/hw/arm/aspeed_soc.h | 3 +++ 2 files changed, 19 insertions(+) diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c index e33483fb5d..8f37bdb1d8 100644 --- a/hw/arm/aspeed_ast2600.c +++ b/hw/arm/aspeed_ast2600.c @@ -61,6 +61,7 @@ static const hwaddr aspeed_soc_ast2600_memmap[] = { [ASPEED_DEV_UART1] = 0x1E783000, [ASPEED_DEV_UART5] = 0x1E784000, [ASPEED_DEV_VUART] = 0x1E787000, + [ASPEED_DEV_I3C] = 0x1E7A0000, [ASPEED_DEV_SDRAM] = 0x80000000, }; @@ -108,6 +109,7 @@ static const int aspeed_soc_ast2600_irqmap[] = { [ASPEED_DEV_ETH4] = 33, [ASPEED_DEV_KCS] = 138, /* 138 -> 142 */ [ASPEED_DEV_DP] = 62, + [ASPEED_DEV_I3C] = 102, /* 102 -> 107 */ }; static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl) @@ -223,6 +225,8 @@ static void aspeed_soc_ast2600_init(Object *obj) snprintf(typename, sizeof(typename), "aspeed.hace-%s", socname); object_initialize_child(obj, "hace", &s->hace, typename); + + object_initialize_child(obj, "i3c", &s->i3c, TYPE_ASPEED_I3C); } /* @@ -523,6 +527,18 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->hace), 0, sc->memmap[ASPEED_DEV_HACE]); sysbus_connect_irq(SYS_BUS_DEVICE(&s->hace), 0, aspeed_soc_get_irq(s, ASPEED_DEV_HACE)); + + /* I3C */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->i3c), errp)) { + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->i3c), 0, sc->memmap[ASPEED_DEV_I3C]); + for (i = 0; i < ASPEED_I3C_NR_DEVICES; i++) { + qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore), + sc->irqmap[ASPEED_DEV_I3C] + i); + /* The AST2600 I3C controller has one IRQ per bus. */ + sysbus_connect_irq(SYS_BUS_DEVICE(&s->i3c.devices[i]), 0, irq); + } } static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data) diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h index 18fb7eed46..cae9906684 100644 --- a/include/hw/arm/aspeed_soc.h +++ b/include/hw/arm/aspeed_soc.h @@ -21,6 +21,7 @@ #include "hw/timer/aspeed_timer.h" #include "hw/rtc/aspeed_rtc.h" #include "hw/i2c/aspeed_i2c.h" +#include "hw/misc/aspeed_i3c.h" #include "hw/ssi/aspeed_smc.h" #include "hw/misc/aspeed_hace.h" #include "hw/watchdog/wdt_aspeed.h" @@ -51,6 +52,7 @@ struct AspeedSoCState { AspeedRtcState rtc; AspeedTimerCtrlState timerctrl; AspeedI2CState i2c; + AspeedI3CState i3c; AspeedSCUState scu; AspeedHACEState hace; AspeedXDMAState xdma; @@ -141,6 +143,7 @@ enum { ASPEED_DEV_HACE, ASPEED_DEV_DPMCU, ASPEED_DEV_DP, + ASPEED_DEV_I3C, }; #endif /* ASPEED_SOC_H */ From 8f809f699251dcf28811b9693a196ff02367d7d6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:36 +0000 Subject: [PATCH 639/730] hw/intc/arm_gicv3_its: Fix event ID bounds checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In process_its_cmd() and process_mapti() we must check the event ID against a limit defined by the size field in the DTE, which specifies the number of ID bits minus one. Convert this code to our num_foo convention: * change the variable names * use uint64_t and 1ULL when calculating the number of valid event IDs, because DTE.SIZE is 5 bits and so num_eventids may be up to 2^32 * fix the off-by-one error in the comparison Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Message-id: 20220111171048.3545974-2-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index fa3cdb5755..6d11fa0204 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -225,7 +225,7 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, MemTxResult res = MEMTX_OK; bool dte_valid; uint64_t dte = 0; - uint32_t max_eventid; + uint64_t num_eventids; uint16_t icid = 0; uint32_t pIntid = 0; bool ite_valid = false; @@ -258,7 +258,7 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, dte_valid = FIELD_EX64(dte, DTE, VALID); if (dte_valid) { - max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1); + num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1); ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res); @@ -299,10 +299,11 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, dte_valid ? "valid" : "invalid", ite_valid ? "valid" : "invalid", cte_valid ? "valid" : "invalid"); - } else if (eventid > max_eventid) { + } else if (eventid >= num_eventids) { qemu_log_mask(LOG_GUEST_ERROR, - "%s: invalid command attributes: eventid %d > %d\n", - __func__, eventid, max_eventid); + "%s: invalid command attributes: eventid %d >= %" + PRId64 "\n", + __func__, eventid, num_eventids); } else { /* * Current implementation only supports rdbase == procnum @@ -336,7 +337,8 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, AddressSpace *as = &s->gicv3->dma_as; uint32_t devid, eventid; uint32_t pIntid = 0; - uint32_t max_eventid, max_Intid; + uint64_t num_eventids; + uint32_t max_Intid; bool dte_valid; MemTxResult res = MEMTX_OK; uint16_t icid = 0; @@ -376,11 +378,11 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, return result; } dte_valid = FIELD_EX64(dte, DTE, VALID); - max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1); + num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1); max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1; if ((devid >= s->dt.num_ids) || (icid >= s->ct.num_ids) - || !dte_valid || (eventid > max_eventid) || + || !dte_valid || (eventid >= num_eventids) || (((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS))) { qemu_log_mask(LOG_GUEST_ERROR, From 905720f18d77e9ca8737d3ff047cad9079cbde6d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:37 +0000 Subject: [PATCH 640/730] hw/intc/arm_gicv3_its: Convert int ID check to num_intids convention MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bounds check on the number of interrupt IDs is correct, but doesn't match our convention; change the variable name, initialize it to the 2^n value rather than (2^n)-1, and use >= instead of > in the comparison. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Message-id: 20220111171048.3545974-3-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 6d11fa0204..5919b1a3b7 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -338,7 +338,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, uint32_t devid, eventid; uint32_t pIntid = 0; uint64_t num_eventids; - uint32_t max_Intid; + uint32_t num_intids; bool dte_valid; MemTxResult res = MEMTX_OK; uint16_t icid = 0; @@ -379,11 +379,11 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, } dte_valid = FIELD_EX64(dte, DTE, VALID); num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1); - max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1; + num_intids = 1ULL << (GICD_TYPER_IDBITS + 1); if ((devid >= s->dt.num_ids) || (icid >= s->ct.num_ids) || !dte_valid || (eventid >= num_eventids) || - (((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) && + (((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)) && (pIntid != INTID_SPURIOUS))) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes " From 7d62b2dcdb04fa625abb6600dbffd4464c3e4a85 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:38 +0000 Subject: [PATCH 641/730] hw/intc/arm_gicv3_its: Fix handling of process_its_cmd() return value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit process_its_cmd() returns a bool, like all the other process_ functions. However we were putting its return value into 'res', not 'result', which meant we would ignore it when deciding whether to continue or stall the command queue. Fix the typo. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-id: 20220111171048.3545974-4-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 5919b1a3b7..a6c2299a09 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -678,10 +678,10 @@ static void process_cmdq(GICv3ITSState *s) switch (cmd) { case GITS_CMD_INT: - res = process_its_cmd(s, data, cq_offset, INTERRUPT); + result = process_its_cmd(s, data, cq_offset, INTERRUPT); break; case GITS_CMD_CLEAR: - res = process_its_cmd(s, data, cq_offset, CLEAR); + result = process_its_cmd(s, data, cq_offset, CLEAR); break; case GITS_CMD_SYNC: /* From f0b4b2a28c4ab26505f13f07da07190387f848a4 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:39 +0000 Subject: [PATCH 642/730] hw/intc/arm_gicv3_its: Don't use data if reading command failed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In process_cmdq(), we read 64 bits of the command packet, which contain the command identifier, which we then switch() on to dispatch to an appropriate sub-function. However, if address_space_ldq_le() reports a memory transaction failure, we still read the command identifier out of the data and switch() on it. Restructure the code so that we stop immediately (stalling the command queue) in this case. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Message-id: 20220111171048.3545974-5-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index a6c2299a09..c1f76682d0 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -672,8 +672,13 @@ static void process_cmdq(GICv3ITSState *s) data = address_space_ldq_le(as, s->cq.base_addr + cq_offset, MEMTXATTRS_UNSPECIFIED, &res); if (res != MEMTX_OK) { - result = false; + s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: could not read command at 0x%" PRIx64 "\n", + __func__, s->cq.base_addr + cq_offset); + break; } + cmd = (data & CMD_MASK); switch (cmd) { From ef011555da8bcabd74ebd79f6a4e1c2ec763efd0 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:40 +0000 Subject: [PATCH 643/730] hw/intc/arm_gicv3_its: Use enum for return value of process_* functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an ITS detects an error in a command, it has an implementation-defined (CONSTRAINED UNPREDICTABLE) choice of whether to ignore the command, proceeding to the next one in the queue, or to stall the ITS command queue, processing nothing further. The behaviour required when the read of the command packet from memory fails is less clearly documented, but the same set of choices as for command errors seem reasonable. The intention of the QEMU implementation, as documented in the comments, is that if we encounter a memory error reading the command packet or one of the various data tables then we should stall, but for command parameter errors we should ignore the queue and continue. However, we don't actually do this. To get the desired behaviour, the various process_* functions need to return true to cause process_cmdq() to advance to the next command and keep processing, and false to stall command processing. What they mostly do is return false for any kind of error. To make the code clearer, replace the 'bool' return from the process_ functions with an enum which may be either CMD_STALL or CMD_CONTINUE. In this commit no behaviour changes; in subsequent commits we will adjust the error-return paths for the process_ functions one by one. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-id: 20220111171048.3545974-6-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 59 ++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index c1f76682d0..10901a5e70 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -45,6 +45,23 @@ typedef struct { uint64_t itel; } IteEntry; +/* + * The ITS spec permits a range of CONSTRAINED UNPREDICTABLE options + * if a command parameter is not correct. These include both "stall + * processing of the command queue" and "ignore this command, and + * keep processing the queue". In our implementation we choose that + * memory transaction errors reading the command packet provoke a + * stall, but errors in parameters cause us to ignore the command + * and continue processing. + * The process_* functions which handle individual ITS commands all + * return an ItsCmdResult which tells process_cmdq() whether it should + * stall or keep going. + */ +typedef enum ItsCmdResult { + CMD_STALL = 0, + CMD_CONTINUE = 1, +} ItsCmdResult; + static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz) { uint64_t result = 0; @@ -217,8 +234,8 @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res) * 3. handling of ITS CLEAR command * 4. handling of ITS DISCARD command */ -static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, - ItsCmdType cmd) +static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, + uint32_t offset, ItsCmdType cmd) { AddressSpace *as = &s->gicv3->dma_as; uint32_t devid, eventid; @@ -231,7 +248,7 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, bool ite_valid = false; uint64_t cte = 0; bool cte_valid = false; - bool result = false; + ItsCmdResult result = CMD_STALL; uint64_t rdbase; if (cmd == NONE) { @@ -324,15 +341,15 @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset, if (cmd == DISCARD) { IteEntry ite = {}; /* remove mapping from interrupt translation table */ - result = update_ite(s, eventid, dte, ite); + result = update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL; } } return result; } -static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, - bool ignore_pInt) +static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, + uint32_t offset, bool ignore_pInt) { AddressSpace *as = &s->gicv3->dma_as; uint32_t devid, eventid; @@ -343,7 +360,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, MemTxResult res = MEMTX_OK; uint16_t icid = 0; uint64_t dte = 0; - bool result = false; + ItsCmdResult result = CMD_STALL; devid = ((value & DEVID_MASK) >> DEVID_SHIFT); offset += NUM_BYTES_IN_DW; @@ -404,7 +421,7 @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset, ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS); ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid); - result = update_ite(s, eventid, dte, ite); + result = update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL; } return result; @@ -472,14 +489,14 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid, } } -static bool process_mapc(GICv3ITSState *s, uint32_t offset) +static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset) { AddressSpace *as = &s->gicv3->dma_as; uint16_t icid; uint64_t rdbase; bool valid; MemTxResult res = MEMTX_OK; - bool result = false; + ItsCmdResult result = CMD_STALL; uint64_t value; offset += NUM_BYTES_IN_DW; @@ -509,7 +526,7 @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset) * command in the queue */ } else { - result = update_cte(s, icid, valid, rdbase); + result = update_cte(s, icid, valid, rdbase) ? CMD_CONTINUE : CMD_STALL; } return result; @@ -578,7 +595,8 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid, } } -static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset) +static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value, + uint32_t offset) { AddressSpace *as = &s->gicv3->dma_as; uint32_t devid; @@ -586,7 +604,7 @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset) uint64_t itt_addr; bool valid; MemTxResult res = MEMTX_OK; - bool result = false; + ItsCmdResult result = CMD_STALL; devid = ((value & DEVID_MASK) >> DEVID_SHIFT); @@ -623,7 +641,7 @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset) * command in the queue */ } else { - result = update_dte(s, devid, valid, size, itt_addr); + result = update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL; } return result; @@ -641,7 +659,6 @@ static void process_cmdq(GICv3ITSState *s) uint64_t data; AddressSpace *as = &s->gicv3->dma_as; MemTxResult res = MEMTX_OK; - bool result = true; uint8_t cmd; int i; @@ -668,6 +685,8 @@ static void process_cmdq(GICv3ITSState *s) } while (wr_offset != rd_offset) { + ItsCmdResult result = CMD_CONTINUE; + cq_offset = (rd_offset * GITS_CMDQ_ENTRY_SIZE); data = address_space_ldq_le(as, s->cq.base_addr + cq_offset, MEMTXATTRS_UNSPECIFIED, &res); @@ -726,18 +745,16 @@ static void process_cmdq(GICv3ITSState *s) default: break; } - if (result) { + if (result == CMD_CONTINUE) { rd_offset++; rd_offset %= s->cq.num_entries; s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset); } else { - /* - * in this implementation, in case of dma read/write error - * we stall the command processing - */ + /* CMD_STALL */ s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1); qemu_log_mask(LOG_GUEST_ERROR, - "%s: %x cmd processing failed\n", __func__, cmd); + "%s: 0x%x cmd processing failed, stalling\n", + __func__, cmd); break; } } From 593a7cc2d38544040ed79c28b3b027420ec84c40 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:41 +0000 Subject: [PATCH 644/730] hw/intc/arm_gicv3_its: Fix return codes in process_its_cmd() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix process_its_cmd() to consistently return CMD_STALL for memory errors and CMD_CONTINUE for parameter errors, as we claim in the comments that we do. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Message-id: 20220111171048.3545974-7-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 10901a5e70..0929116c0f 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -248,7 +248,6 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, bool ite_valid = false; uint64_t cte = 0; bool cte_valid = false; - ItsCmdResult result = CMD_STALL; uint64_t rdbase; if (cmd == NONE) { @@ -262,7 +261,7 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, } if (res != MEMTX_OK) { - return result; + return CMD_STALL; } eventid = (value & EVENTID_MASK); @@ -270,7 +269,7 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, dte = get_dte(s, devid, &res); if (res != MEMTX_OK) { - return result; + return CMD_STALL; } dte_valid = FIELD_EX64(dte, DTE, VALID); @@ -280,7 +279,7 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res); if (res != MEMTX_OK) { - return result; + return CMD_STALL; } if (ite_valid) { @@ -288,14 +287,14 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, } if (res != MEMTX_OK) { - return result; + return CMD_STALL; } } else { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes: " "invalid dte: %"PRIx64" for %d (MEM_TX: %d)\n", __func__, dte, devid, res); - return result; + return CMD_CONTINUE; } @@ -307,7 +306,7 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes: devid %d>=%d", __func__, devid, s->dt.num_ids); - + return CMD_CONTINUE; } else if (!dte_valid || !ite_valid || !cte_valid) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes: " @@ -316,11 +315,13 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, dte_valid ? "valid" : "invalid", ite_valid ? "valid" : "invalid", cte_valid ? "valid" : "invalid"); + return CMD_CONTINUE; } else if (eventid >= num_eventids) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes: eventid %d >= %" PRId64 "\n", __func__, eventid, num_eventids); + return CMD_CONTINUE; } else { /* * Current implementation only supports rdbase == procnum @@ -329,7 +330,7 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, rdbase = FIELD_EX64(cte, CTE, RDBASE); if (rdbase >= s->gicv3->num_cpu) { - return result; + return CMD_CONTINUE; } if ((cmd == CLEAR) || (cmd == DISCARD)) { @@ -341,11 +342,10 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, if (cmd == DISCARD) { IteEntry ite = {}; /* remove mapping from interrupt translation table */ - result = update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL; + return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL; } + return CMD_CONTINUE; } - - return result; } static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, From be0ed8fb7fd4df3f6e09bb33c619e62a80410380 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:42 +0000 Subject: [PATCH 645/730] hw/intc/arm_gicv3_its: Refactor process_its_cmd() to reduce nesting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor process_its_cmd() so that it consistently uses the structure do thing; if (error condition) { return early; } do next thing; rather than doing some of the work nested inside if (not error) code blocks. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Message-id: 20220111171048.3545974-8-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 103 +++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 53 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 0929116c0f..5dc6846fe3 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -273,79 +273,76 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, } dte_valid = FIELD_EX64(dte, DTE, VALID); - if (dte_valid) { - num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1); - - ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res); - - if (res != MEMTX_OK) { - return CMD_STALL; - } - - if (ite_valid) { - cte_valid = get_cte(s, icid, &cte, &res); - } - - if (res != MEMTX_OK) { - return CMD_STALL; - } - } else { + if (!dte_valid) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes: " - "invalid dte: %"PRIx64" for %d (MEM_TX: %d)\n", - __func__, dte, devid, res); + "invalid dte: %"PRIx64" for %d\n", + __func__, dte, devid); return CMD_CONTINUE; } + num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1); + + ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res); + if (res != MEMTX_OK) { + return CMD_STALL; + } + + if (!ite_valid) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid command attributes: invalid ITE\n", + __func__); + return CMD_CONTINUE; + } + + cte_valid = get_cte(s, icid, &cte, &res); + if (res != MEMTX_OK) { + return CMD_STALL; + } + if (!cte_valid) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid command attributes: " + "invalid cte: %"PRIx64"\n", + __func__, cte); + return CMD_CONTINUE; + } - /* - * In this implementation, in case of guest errors we ignore the - * command and move onto the next command in the queue. - */ if (devid >= s->dt.num_ids) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes: devid %d>=%d", __func__, devid, s->dt.num_ids); return CMD_CONTINUE; - } else if (!dte_valid || !ite_valid || !cte_valid) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: invalid command attributes: " - "dte: %s, ite: %s, cte: %s\n", - __func__, - dte_valid ? "valid" : "invalid", - ite_valid ? "valid" : "invalid", - cte_valid ? "valid" : "invalid"); - return CMD_CONTINUE; - } else if (eventid >= num_eventids) { + } + if (eventid >= num_eventids) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes: eventid %d >= %" PRId64 "\n", __func__, eventid, num_eventids); return CMD_CONTINUE; - } else { - /* - * Current implementation only supports rdbase == procnum - * Hence rdbase physical address is ignored - */ - rdbase = FIELD_EX64(cte, CTE, RDBASE); + } - if (rdbase >= s->gicv3->num_cpu) { - return CMD_CONTINUE; - } + /* + * Current implementation only supports rdbase == procnum + * Hence rdbase physical address is ignored + */ + rdbase = FIELD_EX64(cte, CTE, RDBASE); - if ((cmd == CLEAR) || (cmd == DISCARD)) { - gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0); - } else { - gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1); - } - - if (cmd == DISCARD) { - IteEntry ite = {}; - /* remove mapping from interrupt translation table */ - return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL; - } + if (rdbase >= s->gicv3->num_cpu) { return CMD_CONTINUE; } + + if ((cmd == CLEAR) || (cmd == DISCARD)) { + gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0); + } else { + gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1); + } + + if (cmd == DISCARD) { + IteEntry ite = {}; + /* remove mapping from interrupt translation table */ + return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL; + } + return CMD_CONTINUE; } static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, From 0241f7316073f5e66b560195c36e719e369947d0 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:43 +0000 Subject: [PATCH 646/730] hw/intc/arm_gicv3_its: Fix return codes in process_mapti() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix process_mapti() to consistently return CMD_STALL for memory errors and CMD_CONTINUE for parameter errors, as we claim in the comments that we do. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Message-id: 20220111171048.3545974-9-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 5dc6846fe3..010779a9fd 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -357,7 +357,7 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, MemTxResult res = MEMTX_OK; uint16_t icid = 0; uint64_t dte = 0; - ItsCmdResult result = CMD_STALL; + IteEntry ite = {}; devid = ((value & DEVID_MASK) >> DEVID_SHIFT); offset += NUM_BYTES_IN_DW; @@ -365,7 +365,7 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, MEMTXATTRS_UNSPECIFIED, &res); if (res != MEMTX_OK) { - return result; + return CMD_STALL; } eventid = (value & EVENTID_MASK); @@ -381,7 +381,7 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, MEMTXATTRS_UNSPECIFIED, &res); if (res != MEMTX_OK) { - return result; + return CMD_STALL; } icid = value & ICID_MASK; @@ -389,7 +389,7 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, dte = get_dte(s, devid, &res); if (res != MEMTX_OK) { - return result; + return CMD_STALL; } dte_valid = FIELD_EX64(dte, DTE, VALID); num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1); @@ -409,19 +409,17 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, * we ignore this command and move onto the next * command in the queue */ - } else { - /* add ite entry to interrupt translation table */ - IteEntry ite = {}; - ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid); - ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL); - ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid); - ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS); - ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid); - - result = update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL; + return CMD_CONTINUE; } - return result; + /* add ite entry to interrupt translation table */ + ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid); + ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL); + ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid); + ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS); + ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid); + + return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL; } static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid, From f66751961468813ba6a13de1510c448769b6979a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:44 +0000 Subject: [PATCH 647/730] hw/intc/arm_gicv3_its: Fix return codes in process_mapc() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix process_mapc() to consistently return CMD_STALL for memory errors and CMD_CONTINUE for parameter errors, as we claim in the comments that we do. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Message-id: 20220111171048.3545974-10-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 010779a9fd..80ef4dbcad 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -491,7 +491,6 @@ static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset) uint64_t rdbase; bool valid; MemTxResult res = MEMTX_OK; - ItsCmdResult result = CMD_STALL; uint64_t value; offset += NUM_BYTES_IN_DW; @@ -501,7 +500,7 @@ static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset) MEMTXATTRS_UNSPECIFIED, &res); if (res != MEMTX_OK) { - return result; + return CMD_STALL; } icid = value & ICID_MASK; @@ -520,11 +519,10 @@ static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset) * we ignore this command and move onto the next * command in the queue */ - } else { - result = update_cte(s, icid, valid, rdbase) ? CMD_CONTINUE : CMD_STALL; + return CMD_CONTINUE; } - return result; + return update_cte(s, icid, valid, rdbase) ? CMD_CONTINUE : CMD_STALL; } static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid, From 00d46e72e97ddb5651f62b6eead658a431c58bc6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:45 +0000 Subject: [PATCH 648/730] hw/intc/arm_gicv3_its: Fix return codes in process_mapd() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix process_mapd() to consistently return CMD_STALL for memory errors and CMD_CONTINUE for parameter errors, as we claim in the comments that we do. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Message-id: 20220111171048.3545974-11-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 80ef4dbcad..917201c148 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -597,7 +597,6 @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value, uint64_t itt_addr; bool valid; MemTxResult res = MEMTX_OK; - ItsCmdResult result = CMD_STALL; devid = ((value & DEVID_MASK) >> DEVID_SHIFT); @@ -606,7 +605,7 @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value, MEMTXATTRS_UNSPECIFIED, &res); if (res != MEMTX_OK) { - return result; + return CMD_STALL; } size = (value & SIZE_MASK); @@ -616,7 +615,7 @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value, MEMTXATTRS_UNSPECIFIED, &res); if (res != MEMTX_OK) { - return result; + return CMD_STALL; } itt_addr = (value & ITTADDR_MASK) >> ITTADDR_SHIFT; @@ -633,11 +632,10 @@ static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value, * we ignore this command and move onto the next * command in the queue */ - } else { - result = update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL; + return CMD_CONTINUE; } - return result; + return update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL; } /* From d050f80f8c9b4e535bf2f20d5a400c231e7a5838 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:46 +0000 Subject: [PATCH 649/730] hw/intc/arm_gicv3_its: Factor out "find address of table entry" code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ITS has several tables which all share a similar format, described by the TableDesc struct: the guest may configure them to be a single-level table or a two-level table. Currently we open-code the process of finding the table entry in all the functions which read or write the device table or the collection table. Factor out the "get the address of the table entry" logic into a new function, so that the code which needs to read or write a table entry only needs to call table_entry_addr() and then perform a suitable load or store to that address. Note that the error handling is slightly complicated because we want to handle two cases differently: * failure to read the L1 table entry should end up causing a command stall, like other kinds of DMA error * an L1 table entry that says there is no L2 table for this index (ie whose valid bit is 0) must result in us treating the table entry as not-valid on read, and discarding writes (this is mandated by the spec) Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Alex Bennée Message-id: 20220111171048.3545974-12-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 212 +++++++++++++--------------------------- 1 file changed, 70 insertions(+), 142 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 917201c148..985e316eda 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -83,44 +83,62 @@ static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz) return result; } +static uint64_t table_entry_addr(GICv3ITSState *s, TableDesc *td, + uint32_t idx, MemTxResult *res) +{ + /* + * Given a TableDesc describing one of the ITS in-guest-memory + * tables and an index into it, return the guest address + * corresponding to that table entry. + * If there was a memory error reading the L1 table of an + * indirect table, *res is set accordingly, and we return -1. + * If the L1 table entry is marked not valid, we return -1 with + * *res set to MEMTX_OK. + * + * The specification defines the format of level 1 entries of a + * 2-level table, but the format of level 2 entries and the format + * of flat-mapped tables is IMPDEF. + */ + AddressSpace *as = &s->gicv3->dma_as; + uint32_t l2idx; + uint64_t l2; + uint32_t num_l2_entries; + + *res = MEMTX_OK; + + if (!td->indirect) { + /* Single level table */ + return td->base_addr + idx * td->entry_sz; + } + + /* Two level table */ + l2idx = idx / (td->page_sz / L1TABLE_ENTRY_SIZE); + + l2 = address_space_ldq_le(as, + td->base_addr + (l2idx * L1TABLE_ENTRY_SIZE), + MEMTXATTRS_UNSPECIFIED, res); + if (*res != MEMTX_OK) { + return -1; + } + if (!(l2 & L2_TABLE_VALID_MASK)) { + return -1; + } + + num_l2_entries = td->page_sz / td->entry_sz; + return (l2 & ((1ULL << 51) - 1)) + (idx % num_l2_entries) * td->entry_sz; +} + static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte, MemTxResult *res) { AddressSpace *as = &s->gicv3->dma_as; - uint64_t l2t_addr; - uint64_t value; - bool valid_l2t; - uint32_t l2t_id; - uint32_t num_l2_entries; + uint64_t entry_addr = table_entry_addr(s, &s->ct, icid, res); - if (s->ct.indirect) { - l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE); - - value = address_space_ldq_le(as, - s->ct.base_addr + - (l2t_id * L1TABLE_ENTRY_SIZE), - MEMTXATTRS_UNSPECIFIED, res); - - if (*res == MEMTX_OK) { - valid_l2t = (value & L2_TABLE_VALID_MASK) != 0; - - if (valid_l2t) { - num_l2_entries = s->ct.page_sz / s->ct.entry_sz; - - l2t_addr = value & ((1ULL << 51) - 1); - - *cte = address_space_ldq_le(as, l2t_addr + - ((icid % num_l2_entries) * GITS_CTE_SIZE), - MEMTXATTRS_UNSPECIFIED, res); - } - } - } else { - /* Flat level table */ - *cte = address_space_ldq_le(as, s->ct.base_addr + - (icid * GITS_CTE_SIZE), - MEMTXATTRS_UNSPECIFIED, res); + if (entry_addr == -1) { + return false; /* not valid */ } + *cte = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, res); return FIELD_EX64(*cte, CTE, VALID); } @@ -189,41 +207,12 @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte, static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res) { AddressSpace *as = &s->gicv3->dma_as; - uint64_t l2t_addr; - uint64_t value; - bool valid_l2t; - uint32_t l2t_id; - uint32_t num_l2_entries; + uint64_t entry_addr = table_entry_addr(s, &s->dt, devid, res); - if (s->dt.indirect) { - l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE); - - value = address_space_ldq_le(as, - s->dt.base_addr + - (l2t_id * L1TABLE_ENTRY_SIZE), - MEMTXATTRS_UNSPECIFIED, res); - - if (*res == MEMTX_OK) { - valid_l2t = (value & L2_TABLE_VALID_MASK) != 0; - - if (valid_l2t) { - num_l2_entries = s->dt.page_sz / s->dt.entry_sz; - - l2t_addr = value & ((1ULL << 51) - 1); - - value = address_space_ldq_le(as, l2t_addr + - ((devid % num_l2_entries) * GITS_DTE_SIZE), - MEMTXATTRS_UNSPECIFIED, res); - } - } - } else { - /* Flat level table */ - value = address_space_ldq_le(as, s->dt.base_addr + - (devid * GITS_DTE_SIZE), - MEMTXATTRS_UNSPECIFIED, res); + if (entry_addr == -1) { + return 0; /* a DTE entry with the Valid bit clear */ } - - return value; + return address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, res); } /* @@ -426,11 +415,7 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid, uint64_t rdbase) { AddressSpace *as = &s->gicv3->dma_as; - uint64_t value; - uint64_t l2t_addr; - bool valid_l2t; - uint32_t l2t_id; - uint32_t num_l2_entries; + uint64_t entry_addr; uint64_t cte = 0; MemTxResult res = MEMTX_OK; @@ -444,44 +429,18 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid, cte = FIELD_DP64(cte, CTE, RDBASE, rdbase); } - /* - * The specification defines the format of level 1 entries of a - * 2-level table, but the format of level 2 entries and the format - * of flat-mapped tables is IMPDEF. - */ - if (s->ct.indirect) { - l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE); - - value = address_space_ldq_le(as, - s->ct.base_addr + - (l2t_id * L1TABLE_ENTRY_SIZE), - MEMTXATTRS_UNSPECIFIED, &res); - - if (res != MEMTX_OK) { - return false; - } - - valid_l2t = (value & L2_TABLE_VALID_MASK) != 0; - - if (valid_l2t) { - num_l2_entries = s->ct.page_sz / s->ct.entry_sz; - - l2t_addr = value & ((1ULL << 51) - 1); - - address_space_stq_le(as, l2t_addr + - ((icid % num_l2_entries) * GITS_CTE_SIZE), - cte, MEMTXATTRS_UNSPECIFIED, &res); - } - } else { - /* Flat level table */ - address_space_stq_le(as, s->ct.base_addr + (icid * GITS_CTE_SIZE), - cte, MEMTXATTRS_UNSPECIFIED, &res); - } + entry_addr = table_entry_addr(s, &s->ct, icid, &res); if (res != MEMTX_OK) { + /* memory access error: stall */ return false; - } else { + } + if (entry_addr == -1) { + /* No L2 table for this index: discard write and continue */ return true; } + + address_space_stq_le(as, entry_addr, cte, MEMTXATTRS_UNSPECIFIED, &res); + return res == MEMTX_OK; } static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset) @@ -529,11 +488,7 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid, uint8_t size, uint64_t itt_addr) { AddressSpace *as = &s->gicv3->dma_as; - uint64_t value; - uint64_t l2t_addr; - bool valid_l2t; - uint32_t l2t_id; - uint32_t num_l2_entries; + uint64_t entry_addr; uint64_t dte = 0; MemTxResult res = MEMTX_OK; @@ -548,44 +503,17 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid, return true; } - /* - * The specification defines the format of level 1 entries of a - * 2-level table, but the format of level 2 entries and the format - * of flat-mapped tables is IMPDEF. - */ - if (s->dt.indirect) { - l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE); - - value = address_space_ldq_le(as, - s->dt.base_addr + - (l2t_id * L1TABLE_ENTRY_SIZE), - MEMTXATTRS_UNSPECIFIED, &res); - - if (res != MEMTX_OK) { - return false; - } - - valid_l2t = (value & L2_TABLE_VALID_MASK) != 0; - - if (valid_l2t) { - num_l2_entries = s->dt.page_sz / s->dt.entry_sz; - - l2t_addr = value & ((1ULL << 51) - 1); - - address_space_stq_le(as, l2t_addr + - ((devid % num_l2_entries) * GITS_DTE_SIZE), - dte, MEMTXATTRS_UNSPECIFIED, &res); - } - } else { - /* Flat level table */ - address_space_stq_le(as, s->dt.base_addr + (devid * GITS_DTE_SIZE), - dte, MEMTXATTRS_UNSPECIFIED, &res); - } + entry_addr = table_entry_addr(s, &s->dt, devid, &res); if (res != MEMTX_OK) { + /* memory access error: stall */ return false; - } else { + } + if (entry_addr == -1) { + /* No L2 table for this index: discard write and continue */ return true; } + address_space_stq_le(as, entry_addr, dte, MEMTXATTRS_UNSPECIFIED, &res); + return res == MEMTX_OK; } static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value, From b13148d91805143aba3e0b4441e760b9bea03b8c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:47 +0000 Subject: [PATCH 650/730] hw/intc/arm_gicv3_its: Check indexes before use, not after MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In a few places in the ITS command handling functions, we were doing the range-check of an event ID or device ID only after using it as a table index; move the checks to before the uses. This misordering wouldn't have very bad effects because the tables are in guest memory anyway. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Message-id: 20220111171048.3545974-13-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 42 ++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 985e316eda..ef6c0f55ff 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -255,6 +255,13 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, eventid = (value & EVENTID_MASK); + if (devid >= s->dt.num_ids) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid command attributes: devid %d>=%d", + __func__, devid, s->dt.num_ids); + return CMD_CONTINUE; + } + dte = get_dte(s, devid, &res); if (res != MEMTX_OK) { @@ -272,6 +279,14 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1); + if (eventid >= num_eventids) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid command attributes: eventid %d >= %" + PRId64 "\n", + __func__, eventid, num_eventids); + return CMD_CONTINUE; + } + ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res); if (res != MEMTX_OK) { return CMD_STALL; @@ -296,20 +311,6 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, return CMD_CONTINUE; } - if (devid >= s->dt.num_ids) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: invalid command attributes: devid %d>=%d", - __func__, devid, s->dt.num_ids); - return CMD_CONTINUE; - } - if (eventid >= num_eventids) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: invalid command attributes: eventid %d >= %" - PRId64 "\n", - __func__, eventid, num_eventids); - return CMD_CONTINUE; - } - /* * Current implementation only supports rdbase == procnum * Hence rdbase physical address is ignored @@ -375,6 +376,13 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, icid = value & ICID_MASK; + if (devid >= s->dt.num_ids) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid command attributes: devid %d>=%d", + __func__, devid, s->dt.num_ids); + return CMD_CONTINUE; + } + dte = get_dte(s, devid, &res); if (res != MEMTX_OK) { @@ -384,14 +392,14 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value, num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1); num_intids = 1ULL << (GICD_TYPER_IDBITS + 1); - if ((devid >= s->dt.num_ids) || (icid >= s->ct.num_ids) + if ((icid >= s->ct.num_ids) || !dte_valid || (eventid >= num_eventids) || (((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)) && (pIntid != INTID_SPURIOUS))) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command attributes " - "devid %d or icid %d or eventid %d or pIntid %d or" - "unmapped dte %d\n", __func__, devid, icid, eventid, + "icid %d or eventid %d or pIntid %d or" + "unmapped dte %d\n", __func__, icid, eventid, pIntid, dte_valid); /* * in this implementation, in case of error From 58b88779f00707b6231d827637b5a3d498f9fe28 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 17:10:48 +0000 Subject: [PATCH 651/730] hw/intc/arm_gicv3_its: Range-check ICID before indexing into collection table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In process_its_cmd(), we read an ICID out of the interrupt table entry, and then use it as an index into the collection table. Add a check that it is within range for the collection table first. This check is not strictly necessary, because: * we range check the ICID from the guest before writing it into the interrupt table entry, so the the only way to get an out of range ICID in process_its_cmd() is if a badly-behaved guest is writing directly to the interrupt table memory * the collection table is in guest memory, so QEMU won't fall over if we read off the end of it However, it seems clearer to include the check. Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Message-id: 20220111171048.3545974-14-peter.maydell@linaro.org --- hw/intc/arm_gicv3_its.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index ef6c0f55ff..b2f6a8c7f0 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -299,6 +299,13 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value, return CMD_CONTINUE; } + if (icid >= s->ct.num_ids) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid ICID 0x%x in ITE (table corrupted?)\n", + __func__, icid); + return CMD_CONTINUE; + } + cte_valid = get_cte(s, icid, &cte, &res); if (res != MEMTX_OK) { return CMD_STALL; From b9d383ab797f54ae5fa8746117770709921dc529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 15 Dec 2021 19:24:19 +0100 Subject: [PATCH 652/730] hw/intc/arm_gicv3: Check for !MEMTX_OK instead of MEMTX_ERROR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Quoting Peter Maydell: "These MEMTX_* aren't from the memory transaction API functions; they're just being used by gicd_readl() and friends as a way to indicate a success/failure so that the actual MemoryRegionOps read/write fns like gicv3_dist_read() can log a guest error." We are going to introduce more MemTxResult bits, so it is safer to check for !MEMTX_OK rather than MEMTX_ERROR. Reviewed-by: Peter Xu Reviewed-by: David Hildenbrand Reviewed-by: Peter Maydell Reviewed-by: Stefan Hajnoczi Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Peter Maydell --- hw/intc/arm_gicv3_redist.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c index c8ff3eca08..99b11ca5ee 100644 --- a/hw/intc/arm_gicv3_redist.c +++ b/hw/intc/arm_gicv3_redist.c @@ -462,7 +462,7 @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data, break; } - if (r == MEMTX_ERROR) { + if (r != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid guest read at offset " TARGET_FMT_plx " size %u\n", __func__, offset, size); @@ -521,7 +521,7 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data, break; } - if (r == MEMTX_ERROR) { + if (r != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid guest write at offset " TARGET_FMT_plx " size %u\n", __func__, offset, size); From 28ca4689ae94a27a6a337546425cda30d0e885c3 Mon Sep 17 00:00:00 2001 From: Wilfred Mallawa Date: Mon, 10 Jan 2022 15:16:06 +1000 Subject: [PATCH 653/730] hw: timer: ibex_timer: Fixup reading w/o register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change fixes a bug where a write only register is read. As per https://docs.opentitan.org/hw/ip/rv_timer/doc/#register-table the 'INTR_TEST0' register is write only. Signed-off-by: Wilfred Mallawa Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Message-id: 20220110051606.4031241-1-alistair.francis@opensource.wdc.com Signed-off-by: Alistair Francis --- hw/timer/ibex_timer.c | 14 +++++--------- include/hw/timer/ibex_timer.h | 1 - 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/hw/timer/ibex_timer.c b/hw/timer/ibex_timer.c index 66e1f8e48c..826c38b653 100644 --- a/hw/timer/ibex_timer.c +++ b/hw/timer/ibex_timer.c @@ -130,7 +130,6 @@ static void ibex_timer_reset(DeviceState *dev) s->timer_compare_upper0 = 0xFFFFFFFF; s->timer_intr_enable = 0x00000000; s->timer_intr_state = 0x00000000; - s->timer_intr_test = 0x00000000; ibex_timer_update_irqs(s); } @@ -168,7 +167,8 @@ static uint64_t ibex_timer_read(void *opaque, hwaddr addr, retvalue = s->timer_intr_state; break; case R_INTR_TEST: - retvalue = s->timer_intr_test; + qemu_log_mask(LOG_GUEST_ERROR, + "Attempted to read INTR_TEST, a write only register"); break; default: qemu_log_mask(LOG_GUEST_ERROR, @@ -215,10 +215,7 @@ static void ibex_timer_write(void *opaque, hwaddr addr, s->timer_intr_state &= ~val; break; case R_INTR_TEST: - s->timer_intr_test = val; - if (s->timer_intr_enable & - s->timer_intr_test & - R_INTR_ENABLE_IE_0_MASK) { + if (s->timer_intr_enable & val & R_INTR_ENABLE_IE_0_MASK) { s->timer_intr_state |= R_INTR_STATE_IS_0_MASK; qemu_set_irq(s->irq, true); } @@ -247,8 +244,8 @@ static int ibex_timer_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_ibex_timer = { .name = TYPE_IBEX_TIMER, - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .post_load = ibex_timer_post_load, .fields = (VMStateField[]) { VMSTATE_UINT32(timer_ctrl, IbexTimerState), @@ -257,7 +254,6 @@ static const VMStateDescription vmstate_ibex_timer = { VMSTATE_UINT32(timer_compare_upper0, IbexTimerState), VMSTATE_UINT32(timer_intr_enable, IbexTimerState), VMSTATE_UINT32(timer_intr_state, IbexTimerState), - VMSTATE_UINT32(timer_intr_test, IbexTimerState), VMSTATE_END_OF_LIST() } }; diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h index b6f69b38ee..1a0a28d5fa 100644 --- a/include/hw/timer/ibex_timer.h +++ b/include/hw/timer/ibex_timer.h @@ -43,7 +43,6 @@ struct IbexTimerState { uint32_t timer_compare_upper0; uint32_t timer_intr_enable; uint32_t timer_intr_state; - uint32_t timer_intr_test; uint32_t timebase_freq; From 0df470c3886eda19afdbd5ccd5550ce794feef7b Mon Sep 17 00:00:00 2001 From: Wilfred Mallawa Date: Tue, 11 Jan 2022 17:10:24 +1000 Subject: [PATCH 654/730] riscv: opentitan: fixup plic stride len The following change was made to rectify incorrectly set stride length on the PLIC [1]. Where it should be 32bit and not 24bit (0x18). This was discovered whilst attempting to fix a bug where a timer_interrupt was not serviced on TockOS-OpenTitan. [1] https://docs.opentitan.org/hw/top_earlgrey/ip_autogen/rv_plic/doc/ Signed-off-by: Wilfred Mallawa Reviewed-by: Alistair Francis Tested-by: Alistair Francis Reviewed-by: Bin Meng Message-id: 20220111071025.4169189-1-alistair.francis@opensource.wdc.com Signed-off-by: Alistair Francis --- hw/riscv/opentitan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index 0856c347e8..aec7cfa33f 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -160,7 +160,7 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) qdev_prop_set_uint32(DEVICE(&s->plic), "priority-base", 0x00); qdev_prop_set_uint32(DEVICE(&s->plic), "pending-base", 0x1000); qdev_prop_set_uint32(DEVICE(&s->plic), "enable-base", 0x2000); - qdev_prop_set_uint32(DEVICE(&s->plic), "enable-stride", 0x18); + qdev_prop_set_uint32(DEVICE(&s->plic), "enable-stride", 32); qdev_prop_set_uint32(DEVICE(&s->plic), "context-base", 0x200000); qdev_prop_set_uint32(DEVICE(&s->plic), "context-stride", 8); qdev_prop_set_uint32(DEVICE(&s->plic), "aperture-size", memmap[IBEX_DEV_PLIC].size); From dda94e5c66e4c48c3709acf5532c295a80845730 Mon Sep 17 00:00:00 2001 From: Wilfred Mallawa Date: Tue, 11 Jan 2022 17:10:25 +1000 Subject: [PATCH 655/730] hw: timer: ibex_timer: update/add reg address The following changes: 1. Fixes the incorrectly set CTRL register address. As per [1] https://docs.opentitan.org/hw/ip/rv_timer/doc/#register-table The CTRL register is @ 0x04. This was found when attempting to fixup a bug where a timer_interrupt was not serviced on TockOS-OpenTitan. 2. Adds ALERT_TEST register as documented on [1], adding repective switch cases to error handle and later implement functionality. Signed-off-by: Wilfred Mallawa Reviewed-by: Alistair Francis Tested-by: Alistair Francis Reviewed-by: Bin Meng Message-id: 20220111071025.4169189-2-alistair.francis@opensource.wdc.com Signed-off-by: Alistair Francis --- hw/timer/ibex_timer.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/hw/timer/ibex_timer.c b/hw/timer/ibex_timer.c index 826c38b653..8c2ca364da 100644 --- a/hw/timer/ibex_timer.c +++ b/hw/timer/ibex_timer.c @@ -34,7 +34,9 @@ #include "target/riscv/cpu.h" #include "migration/vmstate.h" -REG32(CTRL, 0x00) +REG32(ALERT_TEST, 0x00) + FIELD(ALERT_TEST, FATAL_FAULT, 0, 1) +REG32(CTRL, 0x04) FIELD(CTRL, ACTIVE, 0, 1) REG32(CFG0, 0x100) FIELD(CFG0, PRESCALE, 0, 12) @@ -142,6 +144,10 @@ static uint64_t ibex_timer_read(void *opaque, hwaddr addr, uint64_t retvalue = 0; switch (addr >> 2) { + case R_ALERT_TEST: + qemu_log_mask(LOG_GUEST_ERROR, + "Attempted to read ALERT_TEST, a write only register"); + break; case R_CTRL: retvalue = s->timer_ctrl; break; @@ -186,6 +192,9 @@ static void ibex_timer_write(void *opaque, hwaddr addr, uint32_t val = val64; switch (addr >> 2) { + case R_ALERT_TEST: + qemu_log_mask(LOG_UNIMP, "Alert triggering not supported"); + break; case R_CTRL: s->timer_ctrl = val; break; From b91a0fa70cdd23ca7929d4e255fcfe93e1fe7513 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:17 +0800 Subject: [PATCH 656/730] update-linux-headers: Add asm-riscv/kvm.h Add asm-riscv/kvm.h for RISC-V KVM. Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Acked-by: Alistair Francis Reviewed-by: Anup Patel Message-id: 20220112081329.1835-2-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- linux-headers/asm-riscv/kvm.h | 128 ++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 linux-headers/asm-riscv/kvm.h diff --git a/linux-headers/asm-riscv/kvm.h b/linux-headers/asm-riscv/kvm.h new file mode 100644 index 0000000000..f808ad1ce5 --- /dev/null +++ b/linux-headers/asm-riscv/kvm.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (C) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + */ + +#ifndef __LINUX_KVM_RISCV_H +#define __LINUX_KVM_RISCV_H + +#ifndef __ASSEMBLY__ + +#include +#include + +#define __KVM_HAVE_READONLY_MEM + +#define KVM_COALESCED_MMIO_PAGE_OFFSET 1 + +#define KVM_INTERRUPT_SET -1U +#define KVM_INTERRUPT_UNSET -2U + +/* for KVM_GET_REGS and KVM_SET_REGS */ +struct kvm_regs { +}; + +/* for KVM_GET_FPU and KVM_SET_FPU */ +struct kvm_fpu { +}; + +/* KVM Debug exit structure */ +struct kvm_debug_exit_arch { +}; + +/* for KVM_SET_GUEST_DEBUG */ +struct kvm_guest_debug_arch { +}; + +/* definition of registers in kvm_run */ +struct kvm_sync_regs { +}; + +/* for KVM_GET_SREGS and KVM_SET_SREGS */ +struct kvm_sregs { +}; + +/* CONFIG registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */ +struct kvm_riscv_config { + unsigned long isa; +}; + +/* CORE registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */ +struct kvm_riscv_core { + struct user_regs_struct regs; + unsigned long mode; +}; + +/* Possible privilege modes for kvm_riscv_core */ +#define KVM_RISCV_MODE_S 1 +#define KVM_RISCV_MODE_U 0 + +/* CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */ +struct kvm_riscv_csr { + unsigned long sstatus; + unsigned long sie; + unsigned long stvec; + unsigned long sscratch; + unsigned long sepc; + unsigned long scause; + unsigned long stval; + unsigned long sip; + unsigned long satp; + unsigned long scounteren; +}; + +/* TIMER registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */ +struct kvm_riscv_timer { + __u64 frequency; + __u64 time; + __u64 compare; + __u64 state; +}; + +/* Possible states for kvm_riscv_timer */ +#define KVM_RISCV_TIMER_STATE_OFF 0 +#define KVM_RISCV_TIMER_STATE_ON 1 + +#define KVM_REG_SIZE(id) \ + (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT)) + +/* If you need to interpret the index values, here is the key: */ +#define KVM_REG_RISCV_TYPE_MASK 0x00000000FF000000 +#define KVM_REG_RISCV_TYPE_SHIFT 24 + +/* Config registers are mapped as type 1 */ +#define KVM_REG_RISCV_CONFIG (0x01 << KVM_REG_RISCV_TYPE_SHIFT) +#define KVM_REG_RISCV_CONFIG_REG(name) \ + (offsetof(struct kvm_riscv_config, name) / sizeof(unsigned long)) + +/* Core registers are mapped as type 2 */ +#define KVM_REG_RISCV_CORE (0x02 << KVM_REG_RISCV_TYPE_SHIFT) +#define KVM_REG_RISCV_CORE_REG(name) \ + (offsetof(struct kvm_riscv_core, name) / sizeof(unsigned long)) + +/* Control and status registers are mapped as type 3 */ +#define KVM_REG_RISCV_CSR (0x03 << KVM_REG_RISCV_TYPE_SHIFT) +#define KVM_REG_RISCV_CSR_REG(name) \ + (offsetof(struct kvm_riscv_csr, name) / sizeof(unsigned long)) + +/* Timer registers are mapped as type 4 */ +#define KVM_REG_RISCV_TIMER (0x04 << KVM_REG_RISCV_TYPE_SHIFT) +#define KVM_REG_RISCV_TIMER_REG(name) \ + (offsetof(struct kvm_riscv_timer, name) / sizeof(__u64)) + +/* F extension registers are mapped as type 5 */ +#define KVM_REG_RISCV_FP_F (0x05 << KVM_REG_RISCV_TYPE_SHIFT) +#define KVM_REG_RISCV_FP_F_REG(name) \ + (offsetof(struct __riscv_f_ext_state, name) / sizeof(__u32)) + +/* D extension registers are mapped as type 6 */ +#define KVM_REG_RISCV_FP_D (0x06 << KVM_REG_RISCV_TYPE_SHIFT) +#define KVM_REG_RISCV_FP_D_REG(name) \ + (offsetof(struct __riscv_d_ext_state, name) / sizeof(__u64)) + +#endif + +#endif /* __LINUX_KVM_RISCV_H */ From 91654e613bf67863f27854a7c8e292a273b50a40 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:18 +0800 Subject: [PATCH 657/730] target/riscv: Add target/riscv/kvm.c to place the public kvm interface Add target/riscv/kvm.c to place kvm_arch_* function needed by kvm/kvm-all.c. Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Reviewed-by: Alistair Francis Reviewed-by: Anup Patel Message-id: 20220112081329.1835-3-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- target/riscv/kvm.c | 133 +++++++++++++++++++++++++++++++++++++++ target/riscv/meson.build | 1 + 2 files changed, 134 insertions(+) create mode 100644 target/riscv/kvm.c diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c new file mode 100644 index 0000000000..687dd4b621 --- /dev/null +++ b/target/riscv/kvm.c @@ -0,0 +1,133 @@ +/* + * RISC-V implementation of KVM hooks + * + * Copyright (c) 2020 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include + +#include + +#include "qemu-common.h" +#include "qemu/timer.h" +#include "qemu/error-report.h" +#include "qemu/main-loop.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" +#include "sysemu/kvm_int.h" +#include "cpu.h" +#include "trace.h" +#include "hw/pci/pci.h" +#include "exec/memattrs.h" +#include "exec/address-spaces.h" +#include "hw/boards.h" +#include "hw/irq.h" +#include "qemu/log.h" +#include "hw/loader.h" + +const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_LAST_INFO +}; + +int kvm_arch_get_registers(CPUState *cs) +{ + return 0; +} + +int kvm_arch_put_registers(CPUState *cs, int level) +{ + return 0; +} + +int kvm_arch_release_virq_post(int virq) +{ + return 0; +} + +int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, + uint64_t address, uint32_t data, PCIDevice *dev) +{ + return 0; +} + +int kvm_arch_destroy_vcpu(CPUState *cs) +{ + return 0; +} + +unsigned long kvm_arch_vcpu_id(CPUState *cpu) +{ + return cpu->cpu_index; +} + +void kvm_arch_init_irq_routing(KVMState *s) +{ +} + +int kvm_arch_init_vcpu(CPUState *cs) +{ + return 0; +} + +int kvm_arch_msi_data_to_gsi(uint32_t data) +{ + abort(); +} + +int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, + int vector, PCIDevice *dev) +{ + return 0; +} + +int kvm_arch_init(MachineState *ms, KVMState *s) +{ + return 0; +} + +int kvm_arch_irqchip_create(KVMState *s) +{ + return 0; +} + +int kvm_arch_process_async_events(CPUState *cs) +{ + return 0; +} + +void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) +{ +} + +MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) +{ + return MEMTXATTRS_UNSPECIFIED; +} + +bool kvm_arch_stop_on_emulation_error(CPUState *cs) +{ + return true; +} + +int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) +{ + return 0; +} + +bool kvm_arch_cpu_check_are_resettable(void) +{ + return true; +} diff --git a/target/riscv/meson.build b/target/riscv/meson.build index a32158da93..95340b44aa 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -20,6 +20,7 @@ riscv_ss.add(files( 'translate.c', 'm128_helper.c' )) +riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) riscv_softmmu_ss = ss.source_set() riscv_softmmu_ss.add(files( From 0a312b85cb433386804a2ca79f4a1f7ab75f64a7 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:19 +0800 Subject: [PATCH 658/730] target/riscv: Implement function kvm_arch_init_vcpu Get isa info from kvm while kvm init. Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Reviewed-by: Alistair Francis Reviewed-by: Anup Patel Message-id: 20220112081329.1835-4-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- target/riscv/kvm.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 687dd4b621..9e66b4a97f 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -38,6 +38,24 @@ #include "qemu/log.h" #include "hw/loader.h" +static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, + uint64_t idx) +{ + uint64_t id = KVM_REG_RISCV | type | idx; + + switch (riscv_cpu_mxl(env)) { + case MXL_RV32: + id |= KVM_REG_SIZE_U32; + break; + case MXL_RV64: + id |= KVM_REG_SIZE_U64; + break; + default: + g_assert_not_reached(); + } + return id; +} + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; @@ -79,7 +97,21 @@ void kvm_arch_init_irq_routing(KVMState *s) int kvm_arch_init_vcpu(CPUState *cs) { - return 0; + int ret = 0; + target_ulong isa; + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + uint64_t id; + + id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, + KVM_REG_RISCV_CONFIG_REG(isa)); + ret = kvm_get_one_reg(cs, id, &isa); + if (ret) { + return ret; + } + env->misa_ext = isa; + + return ret; } int kvm_arch_msi_data_to_gsi(uint32_t data) From 937f0b45120bea964ca4ababbe98e1a2de05a077 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:20 +0800 Subject: [PATCH 659/730] target/riscv: Implement kvm_arch_get_registers Get GPR CSR and FP registers from kvm by KVM_GET_ONE_REG ioctl. Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Reviewed-by: Alistair Francis Reviewed-by: Anup Patel Message-id: 20220112081329.1835-5-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- target/riscv/kvm.c | 112 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 1 deletion(-) diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 9e66b4a97f..039af22125 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -56,13 +56,123 @@ static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, return id; } +#define RISCV_CORE_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \ + KVM_REG_RISCV_CORE_REG(name)) + +#define RISCV_CSR_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \ + KVM_REG_RISCV_CSR_REG(name)) + +#define RISCV_FP_F_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_F, idx) + +#define RISCV_FP_D_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx) + +#define KVM_RISCV_GET_CSR(cs, env, csr, reg) \ + do { \ + int ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ + if (ret) { \ + return ret; \ + } \ + } while (0) + +static int kvm_riscv_get_regs_core(CPUState *cs) +{ + int ret = 0; + int i; + target_ulong reg; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + ret = kvm_get_one_reg(cs, RISCV_CORE_REG(env, regs.pc), ®); + if (ret) { + return ret; + } + env->pc = reg; + + for (i = 1; i < 32; i++) { + uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i); + ret = kvm_get_one_reg(cs, id, ®); + if (ret) { + return ret; + } + env->gpr[i] = reg; + } + + return ret; +} + +static int kvm_riscv_get_regs_csr(CPUState *cs) +{ + int ret = 0; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + KVM_RISCV_GET_CSR(cs, env, sstatus, env->mstatus); + KVM_RISCV_GET_CSR(cs, env, sie, env->mie); + KVM_RISCV_GET_CSR(cs, env, stvec, env->stvec); + KVM_RISCV_GET_CSR(cs, env, sscratch, env->sscratch); + KVM_RISCV_GET_CSR(cs, env, sepc, env->sepc); + KVM_RISCV_GET_CSR(cs, env, scause, env->scause); + KVM_RISCV_GET_CSR(cs, env, stval, env->stval); + KVM_RISCV_GET_CSR(cs, env, sip, env->mip); + KVM_RISCV_GET_CSR(cs, env, satp, env->satp); + return ret; +} + +static int kvm_riscv_get_regs_fp(CPUState *cs) +{ + int ret = 0; + int i; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + if (riscv_has_ext(env, RVD)) { + uint64_t reg; + for (i = 0; i < 32; i++) { + ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(env, i), ®); + if (ret) { + return ret; + } + env->fpr[i] = reg; + } + return ret; + } + + if (riscv_has_ext(env, RVF)) { + uint32_t reg; + for (i = 0; i < 32; i++) { + ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(env, i), ®); + if (ret) { + return ret; + } + env->fpr[i] = reg; + } + return ret; + } + + return ret; +} + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; int kvm_arch_get_registers(CPUState *cs) { - return 0; + int ret = 0; + + ret = kvm_riscv_get_regs_core(cs); + if (ret) { + return ret; + } + + ret = kvm_riscv_get_regs_csr(cs); + if (ret) { + return ret; + } + + ret = kvm_riscv_get_regs_fp(cs); + if (ret) { + return ret; + } + + return ret; } int kvm_arch_put_registers(CPUState *cs, int level) From 9997cc1e19d1f909551783c280cfe441a0838943 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:21 +0800 Subject: [PATCH 660/730] target/riscv: Implement kvm_arch_put_registers Put GPR CSR and FP registers to kvm by KVM_SET_ONE_REG ioctl Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Reviewed-by: Alistair Francis Reviewed-by: Anup Patel Message-id: 20220112081329.1835-6-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- target/riscv/kvm.c | 104 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 039af22125..dbaff53bf2 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -74,6 +74,14 @@ static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, } \ } while (0) +#define KVM_RISCV_SET_CSR(cs, env, csr, reg) \ + do { \ + int ret = kvm_set_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ + if (ret) { \ + return ret; \ + } \ + } while (0) + static int kvm_riscv_get_regs_core(CPUState *cs) { int ret = 0; @@ -99,6 +107,31 @@ static int kvm_riscv_get_regs_core(CPUState *cs) return ret; } +static int kvm_riscv_put_regs_core(CPUState *cs) +{ + int ret = 0; + int i; + target_ulong reg; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + reg = env->pc; + ret = kvm_set_one_reg(cs, RISCV_CORE_REG(env, regs.pc), ®); + if (ret) { + return ret; + } + + for (i = 1; i < 32; i++) { + uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i); + reg = env->gpr[i]; + ret = kvm_set_one_reg(cs, id, ®); + if (ret) { + return ret; + } + } + + return ret; +} + static int kvm_riscv_get_regs_csr(CPUState *cs) { int ret = 0; @@ -116,6 +149,24 @@ static int kvm_riscv_get_regs_csr(CPUState *cs) return ret; } +static int kvm_riscv_put_regs_csr(CPUState *cs) +{ + int ret = 0; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + KVM_RISCV_SET_CSR(cs, env, sstatus, env->mstatus); + KVM_RISCV_SET_CSR(cs, env, sie, env->mie); + KVM_RISCV_SET_CSR(cs, env, stvec, env->stvec); + KVM_RISCV_SET_CSR(cs, env, sscratch, env->sscratch); + KVM_RISCV_SET_CSR(cs, env, sepc, env->sepc); + KVM_RISCV_SET_CSR(cs, env, scause, env->scause); + KVM_RISCV_SET_CSR(cs, env, stval, env->stval); + KVM_RISCV_SET_CSR(cs, env, sip, env->mip); + KVM_RISCV_SET_CSR(cs, env, satp, env->satp); + + return ret; +} + static int kvm_riscv_get_regs_fp(CPUState *cs) { int ret = 0; @@ -149,6 +200,40 @@ static int kvm_riscv_get_regs_fp(CPUState *cs) return ret; } +static int kvm_riscv_put_regs_fp(CPUState *cs) +{ + int ret = 0; + int i; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + if (riscv_has_ext(env, RVD)) { + uint64_t reg; + for (i = 0; i < 32; i++) { + reg = env->fpr[i]; + ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(env, i), ®); + if (ret) { + return ret; + } + } + return ret; + } + + if (riscv_has_ext(env, RVF)) { + uint32_t reg; + for (i = 0; i < 32; i++) { + reg = env->fpr[i]; + ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(env, i), ®); + if (ret) { + return ret; + } + } + return ret; + } + + return ret; +} + + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; @@ -177,7 +262,24 @@ int kvm_arch_get_registers(CPUState *cs) int kvm_arch_put_registers(CPUState *cs, int level) { - return 0; + int ret = 0; + + ret = kvm_riscv_put_regs_core(cs); + if (ret) { + return ret; + } + + ret = kvm_riscv_put_regs_csr(cs); + if (ret) { + return ret; + } + + ret = kvm_riscv_put_regs_fp(cs); + if (ret) { + return ret; + } + + return ret; } int kvm_arch_release_virq_post(int virq) From ad40be27084536408b47a9209181f776ec2c54a5 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:22 +0800 Subject: [PATCH 661/730] target/riscv: Support start kernel directly by KVM Get kernel and fdt start address in virt.c, and pass them to KVM when cpu reset. Add kvm_riscv.h to place riscv specific interface. In addition, PLIC is created without M-mode PLIC contexts when KVM is enabled. Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Reviewed-by: Alistair Francis Reviewed-by: Anup Patel Message-id: 20220112081329.1835-7-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- hw/intc/sifive_plic.c | 20 +++++++--- hw/riscv/boot.c | 16 +++++++- hw/riscv/virt.c | 83 ++++++++++++++++++++++++++++------------ include/hw/riscv/boot.h | 1 + target/riscv/cpu.c | 8 ++++ target/riscv/cpu.h | 3 ++ target/riscv/kvm-stub.c | 25 ++++++++++++ target/riscv/kvm.c | 14 +++++++ target/riscv/kvm_riscv.h | 24 ++++++++++++ target/riscv/meson.build | 2 +- 10 files changed, 164 insertions(+), 32 deletions(-) create mode 100644 target/riscv/kvm-stub.c create mode 100644 target/riscv/kvm_riscv.h diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index 746c0f0343..eebbcf33d4 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -30,6 +30,7 @@ #include "target/riscv/cpu.h" #include "migration/vmstate.h" #include "hw/irq.h" +#include "sysemu/kvm.h" static bool addr_between(uint32_t addr, uint32_t base, uint32_t num) { @@ -430,7 +431,8 @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config, uint32_t context_stride, uint32_t aperture_size) { DeviceState *dev = qdev_new(TYPE_SIFIVE_PLIC); - int i; + int i, j = 0; + SiFivePLICState *plic; assert(enable_stride == (enable_stride & -enable_stride)); assert(context_stride == (context_stride & -context_stride)); @@ -448,13 +450,21 @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config, sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); + plic = SIFIVE_PLIC(dev); for (i = 0; i < num_harts; i++) { CPUState *cpu = qemu_get_cpu(hartid_base + i); - qdev_connect_gpio_out(dev, i, - qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT)); - qdev_connect_gpio_out(dev, num_harts + i, - qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT)); + if (plic->addr_config[j].mode == PLICMode_M) { + j++; + qdev_connect_gpio_out(dev, num_harts + i, + qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT)); + } + + if (plic->addr_config[j].mode == PLICMode_S) { + j++; + qdev_connect_gpio_out(dev, i, + qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT)); + } } return dev; diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index f67264374e..cae74fcbcd 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -30,6 +30,7 @@ #include "elf.h" #include "sysemu/device_tree.h" #include "sysemu/qtest.h" +#include "sysemu/kvm.h" #include @@ -51,7 +52,9 @@ char *riscv_plic_hart_config_string(int hart_count) CPUState *cs = qemu_get_cpu(i); CPURISCVState *env = &RISCV_CPU(cs)->env; - if (riscv_has_ext(env, RVS)) { + if (kvm_enabled()) { + vals[i] = "S"; + } else if (riscv_has_ext(env, RVS)) { vals[i] = "MS"; } else { vals[i] = "M"; @@ -324,3 +327,14 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts return; } + +void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr) +{ + CPUState *cs; + + for (cs = first_cpu; cs; cs = CPU_NEXT(cs)) { + RISCVCPU *riscv_cpu = RISCV_CPU(cs); + riscv_cpu->env.kernel_addr = kernel_addr; + riscv_cpu->env.fdt_addr = fdt_addr; + } +} diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 3af074148e..2643c8bc37 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -38,6 +38,7 @@ #include "chardev/char.h" #include "sysemu/device_tree.h" #include "sysemu/sysemu.h" +#include "sysemu/kvm.h" #include "hw/pci/pci.h" #include "hw/pci-host/gpex.h" #include "hw/display/ramfb.h" @@ -372,13 +373,22 @@ static void create_fdt_socket_plic(RISCVVirtState *s, "sifive,plic-1.0.0", "riscv,plic0" }; - plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4); + if (kvm_enabled()) { + plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2); + } else { + plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4); + } for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) { - plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]); - plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT); - plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]); - plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT); + if (kvm_enabled()) { + plic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]); + plic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_EXT); + } else { + plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]); + plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT); + plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]); + plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT); + } } plic_phandles[socket] = (*phandle)++; @@ -436,10 +446,12 @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap, create_fdt_socket_memory(s, memmap, socket); - if (s->have_aclint) { - create_fdt_socket_aclint(s, memmap, socket, intc_phandles); - } else { - create_fdt_socket_clint(s, memmap, socket, intc_phandles); + if (!kvm_enabled()) { + if (s->have_aclint) { + create_fdt_socket_aclint(s, memmap, socket, intc_phandles); + } else { + create_fdt_socket_clint(s, memmap, socket, intc_phandles); + } } create_fdt_socket_plic(s, memmap, socket, phandle, @@ -801,23 +813,25 @@ static void virt_machine_init(MachineState *machine) hart_count, &error_abort); sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_abort); - /* Per-socket CLINT */ - riscv_aclint_swi_create( - memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size, - base_hartid, hart_count, false); - riscv_aclint_mtimer_create( - memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size + - RISCV_ACLINT_SWI_SIZE, - RISCV_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count, - RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME, - RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true); - - /* Per-socket ACLINT SSWI */ - if (s->have_aclint) { + if (!kvm_enabled()) { + /* Per-socket CLINT */ riscv_aclint_swi_create( - memmap[VIRT_ACLINT_SSWI].base + - i * memmap[VIRT_ACLINT_SSWI].size, - base_hartid, hart_count, true); + memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size, + base_hartid, hart_count, false); + riscv_aclint_mtimer_create( + memmap[VIRT_CLINT].base + i * memmap[VIRT_CLINT].size + + RISCV_ACLINT_SWI_SIZE, + RISCV_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count, + RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME, + RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true); + + /* Per-socket ACLINT SSWI */ + if (s->have_aclint) { + riscv_aclint_swi_create( + memmap[VIRT_ACLINT_SSWI].base + + i * memmap[VIRT_ACLINT_SSWI].size, + base_hartid, hart_count, true); + } } /* Per-socket PLIC hart topology configuration string */ @@ -884,6 +898,16 @@ static void virt_machine_init(MachineState *machine) memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base, mask_rom); + /* + * Only direct boot kernel is currently supported for KVM VM, + * so the "-bios" parameter is ignored and treated like "-bios none" + * when KVM is enabled. + */ + if (kvm_enabled()) { + g_free(machine->firmware); + machine->firmware = g_strdup("none"); + } + if (riscv_is_32bit(&s->soc[0])) { firmware_end_addr = riscv_find_and_load_firmware(machine, RISCV32_BIOS_BIN, start_addr, NULL); @@ -941,6 +965,15 @@ static void virt_machine_init(MachineState *machine) virt_memmap[VIRT_MROM].size, kernel_entry, fdt_load_addr, machine->fdt); + /* + * Only direct boot kernel is currently supported for KVM VM, + * So here setup kernel start address and fdt address. + * TODO:Support firmware loading and integrate to TCG start + */ + if (kvm_enabled()) { + riscv_setup_direct_kernel(kernel_entry, fdt_load_addr); + } + /* SiFive Test MMIO device */ sifive_test_create(memmap[VIRT_TEST].base); diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index baff11dd8a..5834c234aa 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -58,5 +58,6 @@ void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base, hwaddr rom_size, uint32_t reset_vec_size, uint64_t kernel_entry); +void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr); #endif /* RISCV_BOOT_H */ diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 9bc25d3055..a6922dde05 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -29,6 +29,8 @@ #include "hw/qdev-properties.h" #include "migration/vmstate.h" #include "fpu/softfloat-helpers.h" +#include "sysemu/kvm.h" +#include "kvm_riscv.h" /* RISC-V CPU definitions */ @@ -402,6 +404,12 @@ static void riscv_cpu_reset(DeviceState *dev) cs->exception_index = RISCV_EXCP_NONE; env->load_res = -1; set_default_nan_mode(1, &env->fp_status); + +#ifndef CONFIG_USER_ONLY + if (kvm_enabled()) { + kvm_riscv_reset_vcpu(cpu); + } +#endif } static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 4d63086765..8fa6fdcd77 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -269,6 +269,9 @@ struct CPURISCVState { /* Fields from here on are preserved across CPU reset. */ QEMUTimer *timer; /* Internal timer */ + + hwaddr kernel_addr; + hwaddr fdt_addr; }; OBJECT_DECLARE_TYPE(RISCVCPU, RISCVCPUClass, diff --git a/target/riscv/kvm-stub.c b/target/riscv/kvm-stub.c new file mode 100644 index 0000000000..39b96fe3f4 --- /dev/null +++ b/target/riscv/kvm-stub.c @@ -0,0 +1,25 @@ +/* + * QEMU KVM RISC-V specific function stubs + * + * Copyright (c) 2020 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ +#include "qemu/osdep.h" +#include "cpu.h" +#include "kvm_riscv.h" + +void kvm_riscv_reset_vcpu(RISCVCPU *cpu) +{ + abort(); +} diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index dbaff53bf2..d5c6a9d41a 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -37,6 +37,7 @@ #include "hw/irq.h" #include "qemu/log.h" #include "hw/loader.h" +#include "kvm_riscv.h" static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, uint64_t idx) @@ -371,6 +372,19 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) return 0; } +void kvm_riscv_reset_vcpu(RISCVCPU *cpu) +{ + CPURISCVState *env = &cpu->env; + + if (!kvm_enabled()) { + return; + } + env->pc = cpu->env.kernel_addr; + env->gpr[10] = kvm_arch_vcpu_id(CPU(cpu)); /* a0 */ + env->gpr[11] = cpu->env.fdt_addr; /* a1 */ + env->satp = 0; +} + bool kvm_arch_cpu_check_are_resettable(void) { return true; diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h new file mode 100644 index 0000000000..f38c82bf59 --- /dev/null +++ b/target/riscv/kvm_riscv.h @@ -0,0 +1,24 @@ +/* + * QEMU KVM support -- RISC-V specific functions. + * + * Copyright (c) 2020 Huawei Technologies Co., Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef QEMU_KVM_RISCV_H +#define QEMU_KVM_RISCV_H + +void kvm_riscv_reset_vcpu(RISCVCPU *cpu); + +#endif diff --git a/target/riscv/meson.build b/target/riscv/meson.build index 95340b44aa..a3997ed580 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -20,7 +20,7 @@ riscv_ss.add(files( 'translate.c', 'm128_helper.c' )) -riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) +riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c')) riscv_softmmu_ss = ss.source_set() riscv_softmmu_ss.add(files( From 2b650fbbcc2b5d34943bb5697d8799b2c1a885e1 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:23 +0800 Subject: [PATCH 662/730] target/riscv: Support setting external interrupt by KVM When KVM is enabled, set the S-mode external interrupt through kvm_riscv_set_irq function. Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Reviewed-by: Alistair Francis Reviewed-by: Anup Patel Message-id: 20220112081329.1835-8-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 6 +++++- target/riscv/kvm-stub.c | 5 +++++ target/riscv/kvm.c | 17 +++++++++++++++++ target/riscv/kvm_riscv.h | 1 + 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index a6922dde05..53b0524830 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -630,7 +630,11 @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level) case IRQ_S_EXT: case IRQ_VS_EXT: case IRQ_M_EXT: - riscv_cpu_update_mip(cpu, 1 << irq, BOOL_TO_MASK(level)); + if (kvm_enabled()) { + kvm_riscv_set_irq(cpu, irq, level); + } else { + riscv_cpu_update_mip(cpu, 1 << irq, BOOL_TO_MASK(level)); + } break; default: g_assert_not_reached(); diff --git a/target/riscv/kvm-stub.c b/target/riscv/kvm-stub.c index 39b96fe3f4..4e8fc31a21 100644 --- a/target/riscv/kvm-stub.c +++ b/target/riscv/kvm-stub.c @@ -23,3 +23,8 @@ void kvm_riscv_reset_vcpu(RISCVCPU *cpu) { abort(); } + +void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level) +{ + abort(); +} diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index d5c6a9d41a..0ba64795d5 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -385,6 +385,23 @@ void kvm_riscv_reset_vcpu(RISCVCPU *cpu) env->satp = 0; } +void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level) +{ + int ret; + unsigned virq = level ? KVM_INTERRUPT_SET : KVM_INTERRUPT_UNSET; + + if (irq != IRQ_S_EXT) { + perror("kvm riscv set irq != IRQ_S_EXT\n"); + abort(); + } + + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_INTERRUPT, &virq); + if (ret < 0) { + perror("Set irq failed"); + abort(); + } +} + bool kvm_arch_cpu_check_are_resettable(void) { return true; diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h index f38c82bf59..ed281bdce0 100644 --- a/target/riscv/kvm_riscv.h +++ b/target/riscv/kvm_riscv.h @@ -20,5 +20,6 @@ #define QEMU_KVM_RISCV_H void kvm_riscv_reset_vcpu(RISCVCPU *cpu); +void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level); #endif From 4eb471258bd0e331678bece4c894c477928b3b0b Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:24 +0800 Subject: [PATCH 663/730] target/riscv: Handle KVM_EXIT_RISCV_SBI exit Use char-fe to handle console sbi call, which implement early console io while apply 'earlycon=sbi' into kernel parameters. Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Reviewed-by: Anup Patel Reviewed-by: Alistair Francis Message-id: 20220112081329.1835-9-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- target/riscv/kvm.c | 42 ++++++++++++++++- target/riscv/sbi_ecall_interface.h | 72 ++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 target/riscv/sbi_ecall_interface.h diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 0ba64795d5..e90e2a6709 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -38,6 +38,8 @@ #include "qemu/log.h" #include "hw/loader.h" #include "kvm_riscv.h" +#include "sbi_ecall_interface.h" +#include "chardev/char-fe.h" static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, uint64_t idx) @@ -367,9 +369,47 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cs) return true; } +static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run) +{ + int ret = 0; + unsigned char ch; + 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)); + break; + case SBI_EXT_0_1_CONSOLE_GETCHAR: + ret = qemu_chr_fe_read_all(serial_hd(0)->be, &ch, sizeof(ch)); + if (ret == sizeof(ch)) { + run->riscv_sbi.args[0] = ch; + } else { + run->riscv_sbi.args[0] = -1; + } + break; + default: + qemu_log_mask(LOG_UNIMP, + "%s: un-handled SBI EXIT, specific reasons is %lu\n", + __func__, run->riscv_sbi.extension_id); + ret = -1; + break; + } + return ret; +} + int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) { - return 0; + int ret = 0; + switch (run->exit_reason) { + case KVM_EXIT_RISCV_SBI: + ret = kvm_riscv_handle_sbi(cs, run); + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n", + __func__, run->exit_reason); + ret = -1; + break; + } + return ret; } void kvm_riscv_reset_vcpu(RISCVCPU *cpu) diff --git a/target/riscv/sbi_ecall_interface.h b/target/riscv/sbi_ecall_interface.h new file mode 100644 index 0000000000..fb1a3fa8f2 --- /dev/null +++ b/target/riscv/sbi_ecall_interface.h @@ -0,0 +1,72 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Western Digital Corporation or its affiliates. + * + * Authors: + * Anup Patel + */ + +#ifndef __SBI_ECALL_INTERFACE_H__ +#define __SBI_ECALL_INTERFACE_H__ + +/* clang-format off */ + +/* SBI Extension IDs */ +#define SBI_EXT_0_1_SET_TIMER 0x0 +#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1 +#define SBI_EXT_0_1_CONSOLE_GETCHAR 0x2 +#define SBI_EXT_0_1_CLEAR_IPI 0x3 +#define SBI_EXT_0_1_SEND_IPI 0x4 +#define SBI_EXT_0_1_REMOTE_FENCE_I 0x5 +#define SBI_EXT_0_1_REMOTE_SFENCE_VMA 0x6 +#define SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID 0x7 +#define SBI_EXT_0_1_SHUTDOWN 0x8 +#define SBI_EXT_BASE 0x10 +#define SBI_EXT_TIME 0x54494D45 +#define SBI_EXT_IPI 0x735049 +#define SBI_EXT_RFENCE 0x52464E43 +#define SBI_EXT_HSM 0x48534D + +/* SBI function IDs for BASE extension*/ +#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0 +#define SBI_EXT_BASE_GET_IMP_ID 0x1 +#define SBI_EXT_BASE_GET_IMP_VERSION 0x2 +#define SBI_EXT_BASE_PROBE_EXT 0x3 +#define SBI_EXT_BASE_GET_MVENDORID 0x4 +#define SBI_EXT_BASE_GET_MARCHID 0x5 +#define SBI_EXT_BASE_GET_MIMPID 0x6 + +/* SBI function IDs for TIME extension*/ +#define SBI_EXT_TIME_SET_TIMER 0x0 + +/* SBI function IDs for IPI extension*/ +#define SBI_EXT_IPI_SEND_IPI 0x0 + +/* SBI function IDs for RFENCE extension*/ +#define SBI_EXT_RFENCE_REMOTE_FENCE_I 0x0 +#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA 0x1 +#define SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID 0x2 +#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA 0x3 +#define SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID 0x4 +#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA 0x5 +#define SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID 0x6 + +/* SBI function IDs for HSM extension */ +#define SBI_EXT_HSM_HART_START 0x0 +#define SBI_EXT_HSM_HART_STOP 0x1 +#define SBI_EXT_HSM_HART_GET_STATUS 0x2 + +#define SBI_HSM_HART_STATUS_STARTED 0x0 +#define SBI_HSM_HART_STATUS_STOPPED 0x1 +#define SBI_HSM_HART_STATUS_START_PENDING 0x2 +#define SBI_HSM_HART_STATUS_STOP_PENDING 0x3 + +#define SBI_SPEC_VERSION_MAJOR_OFFSET 24 +#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f +#define SBI_SPEC_VERSION_MINOR_MASK 0xffffff +#define SBI_EXT_VENDOR_START 0x09000000 +#define SBI_EXT_VENDOR_END 0x09FFFFFF +/* clang-format on */ + +#endif From 10f1ca27e0fe9930d372591cd5f302e7249aa705 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:25 +0800 Subject: [PATCH 664/730] target/riscv: Add host cpu type 'host' type cpu is set isa to RV32 or RV64 simply, more isa info will obtain from KVM in kvm_arch_init_vcpu() Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Reviewed-by: Alistair Francis Reviewed-by: Anup Patel Message-id: 20220112081329.1835-10-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 15 +++++++++++++++ target/riscv/cpu.h | 1 + 2 files changed, 16 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 53b0524830..32879f1403 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -235,6 +235,18 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj) } #endif +#if defined(CONFIG_KVM) +static void riscv_host_cpu_init(Object *obj) +{ + CPURISCVState *env = &RISCV_CPU(obj)->env; +#if defined(TARGET_RISCV32) + set_misa(env, MXL_RV32, 0); +#elif defined(TARGET_RISCV64) + set_misa(env, MXL_RV64, 0); +#endif +} +#endif + static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) { ObjectClass *oc; @@ -847,6 +859,9 @@ static const TypeInfo riscv_cpu_type_infos[] = { .class_init = riscv_cpu_class_init, }, DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init), +#if defined(CONFIG_KVM) + DEFINE_CPU(TYPE_RISCV_CPU_HOST, riscv_host_cpu_init), +#endif #if defined(TARGET_RISCV32) DEFINE_CPU(TYPE_RISCV_CPU_BASE32, rv32_base_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_IBEX, rv32_ibex_cpu_init), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 8fa6fdcd77..73ced2116b 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -47,6 +47,7 @@ #define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51") #define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34") #define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54") +#define TYPE_RISCV_CPU_HOST RISCV_CPU_TYPE_NAME("host") #if defined(TARGET_RISCV32) # define TYPE_RISCV_CPU_BASE TYPE_RISCV_CPU_BASE32 From 27abe66f31efa8bcd15f0f998db2127b4ffb628a Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:26 +0800 Subject: [PATCH 665/730] target/riscv: Add kvm_riscv_get/put_regs_timer Add kvm_riscv_get/put_regs_timer to synchronize virtual time context from KVM. To set register of RISCV_TIMER_REG(state) will occur a error from KVM on kvm_timer_state == 0. It's better to adapt in KVM, but it doesn't matter that adaping in QEMU. Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Reviewed-by: Anup Patel Acked-by: Alistair Francis Message-id: 20220112081329.1835-11-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 7 +++++ target/riscv/kvm.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 73ced2116b..22c94d3c57 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -273,6 +273,13 @@ struct CPURISCVState { hwaddr kernel_addr; hwaddr fdt_addr; + + /* kvm timer */ + bool kvm_timer_dirty; + uint64_t kvm_timer_time; + uint64_t kvm_timer_compare; + uint64_t kvm_timer_state; + uint64_t kvm_timer_frequency; }; OBJECT_DECLARE_TYPE(RISCVCPU, RISCVCPUClass, diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index e90e2a6709..a43d5a2988 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -40,6 +40,7 @@ #include "kvm_riscv.h" #include "sbi_ecall_interface.h" #include "chardev/char-fe.h" +#include "migration/migration.h" static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, uint64_t idx) @@ -65,6 +66,9 @@ static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, #define RISCV_CSR_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \ KVM_REG_RISCV_CSR_REG(name)) +#define RISCV_TIMER_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_TIMER, \ + KVM_REG_RISCV_TIMER_REG(name)) + #define RISCV_FP_F_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_F, idx) #define RISCV_FP_D_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx) @@ -85,6 +89,22 @@ static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, } \ } while (0) +#define KVM_RISCV_GET_TIMER(cs, env, name, reg) \ + do { \ + int ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(env, name), ®); \ + if (ret) { \ + abort(); \ + } \ + } while (0) + +#define KVM_RISCV_SET_TIMER(cs, env, name, reg) \ + do { \ + int ret = kvm_set_one_reg(cs, RISCV_TIMER_REG(env, time), ®); \ + if (ret) { \ + abort(); \ + } \ + } while (0) + static int kvm_riscv_get_regs_core(CPUState *cs) { int ret = 0; @@ -236,6 +256,58 @@ static int kvm_riscv_put_regs_fp(CPUState *cs) return ret; } +static void kvm_riscv_get_regs_timer(CPUState *cs) +{ + CPURISCVState *env = &RISCV_CPU(cs)->env; + + if (env->kvm_timer_dirty) { + return; + } + + KVM_RISCV_GET_TIMER(cs, env, time, env->kvm_timer_time); + KVM_RISCV_GET_TIMER(cs, env, compare, env->kvm_timer_compare); + KVM_RISCV_GET_TIMER(cs, env, state, env->kvm_timer_state); + KVM_RISCV_GET_TIMER(cs, env, frequency, env->kvm_timer_frequency); + + env->kvm_timer_dirty = true; +} + +static void kvm_riscv_put_regs_timer(CPUState *cs) +{ + uint64_t reg; + CPURISCVState *env = &RISCV_CPU(cs)->env; + + if (!env->kvm_timer_dirty) { + return; + } + + KVM_RISCV_SET_TIMER(cs, env, time, env->kvm_timer_time); + KVM_RISCV_SET_TIMER(cs, env, compare, env->kvm_timer_compare); + + /* + * To set register of RISCV_TIMER_REG(state) will occur a error from KVM + * on env->kvm_timer_state == 0, It's better to adapt in KVM, but it + * doesn't matter that adaping in QEMU now. + * TODO If KVM changes, adapt here. + */ + if (env->kvm_timer_state) { + KVM_RISCV_SET_TIMER(cs, env, state, env->kvm_timer_state); + } + + /* + * For now, migration will not work between Hosts with different timer + * frequency. Therefore, we should check whether they are the same here + * during the migration. + */ + if (migration_is_running(migrate_get_current()->state)) { + KVM_RISCV_GET_TIMER(cs, env, frequency, reg); + if (reg != env->kvm_timer_frequency) { + error_report("Dst Hosts timer frequency != Src Hosts"); + } + } + + env->kvm_timer_dirty = false; +} const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO From 9ad3e016ae1ed2f30c39051bc20f1da327bd9400 Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:27 +0800 Subject: [PATCH 666/730] target/riscv: Implement virtual time adjusting with vm state changing We hope that virtual time adjusts with vm state changing. When a vm is stopped, guest virtual time should stop counting and kvm_timer should be stopped. When the vm is resumed, guest virtual time should continue to count and kvm_timer should be restored. Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Reviewed-by: Anup Patel Reviewed-by: Alistair Francis Message-id: 20220112081329.1835-12-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- target/riscv/kvm.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index a43d5a2988..e6b7cb6d4d 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -41,6 +41,7 @@ #include "sbi_ecall_interface.h" #include "chardev/char-fe.h" #include "migration/migration.h" +#include "sysemu/runstate.h" static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, uint64_t idx) @@ -378,6 +379,18 @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu) return cpu->cpu_index; } +static void kvm_riscv_vm_state_change(void *opaque, bool running, + RunState state) +{ + CPUState *cs = opaque; + + if (running) { + kvm_riscv_put_regs_timer(cs); + } else { + kvm_riscv_get_regs_timer(cs); + } +} + void kvm_arch_init_irq_routing(KVMState *s) { } @@ -390,6 +403,8 @@ int kvm_arch_init_vcpu(CPUState *cs) CPURISCVState *env = &cpu->env; uint64_t id; + qemu_add_vm_change_state_handler(kvm_riscv_vm_state_change, cs); + id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, KVM_REG_RISCV_CONFIG_REG(isa)); ret = kvm_get_one_reg(cs, id, &isa); From 1eb9a5da31abb0a7b613756f5bb7c887b7ef60ea Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:28 +0800 Subject: [PATCH 667/730] target/riscv: Support virtual time context synchronization Add virtual time context description to vmstate_kvmtimer. After cpu being loaded, virtual time context is updated to KVM. Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Reviewed-by: Anup Patel Reviewed-by: Alistair Francis Message-id: 20220112081329.1835-13-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- target/riscv/machine.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 13b9ab375b..098670e680 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -185,6 +185,35 @@ static const VMStateDescription vmstate_rv128 = { } }; +static bool kvmtimer_needed(void *opaque) +{ + return kvm_enabled(); +} + +static int cpu_post_load(void *opaque, int version_id) +{ + RISCVCPU *cpu = opaque; + CPURISCVState *env = &cpu->env; + + env->kvm_timer_dirty = true; + return 0; +} + +static const VMStateDescription vmstate_kvmtimer = { + .name = "cpu/kvmtimer", + .version_id = 1, + .minimum_version_id = 1, + .needed = kvmtimer_needed, + .post_load = cpu_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT64(env.kvm_timer_time, RISCVCPU), + VMSTATE_UINT64(env.kvm_timer_compare, RISCVCPU), + VMSTATE_UINT64(env.kvm_timer_state, RISCVCPU), + + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_riscv_cpu = { .name = "cpu", .version_id = 3, @@ -240,6 +269,7 @@ const VMStateDescription vmstate_riscv_cpu = { &vmstate_vector, &vmstate_pointermasking, &vmstate_rv128, + &vmstate_kvmtimer, NULL } }; From fbf43c7dbf18156d4dce73183dd17b83f6ca65fc Mon Sep 17 00:00:00 2001 From: Yifei Jiang Date: Wed, 12 Jan 2022 16:13:29 +0800 Subject: [PATCH 668/730] target/riscv: enable riscv kvm accel Add riscv kvm support in meson.build file. Signed-off-by: Yifei Jiang Signed-off-by: Mingwang Li Reviewed-by: Alistair Francis Reviewed-by: Anup Patel Message-id: 20220112081329.1835-14-jiangyifei@huawei.com Signed-off-by: Alistair Francis --- meson.build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/meson.build b/meson.build index 333c61deba..833fd6bc4c 100644 --- a/meson.build +++ b/meson.build @@ -90,6 +90,8 @@ elif cpu in ['ppc', 'ppc64'] kvm_targets = ['ppc-softmmu', 'ppc64-softmmu'] elif cpu in ['mips', 'mips64'] kvm_targets = ['mips-softmmu', 'mipsel-softmmu', 'mips64-softmmu', 'mips64el-softmmu'] +elif cpu in ['riscv'] + kvm_targets = ['riscv32-softmmu', 'riscv64-softmmu'] else kvm_targets = [] endif From cfeeeb482a5279f240407a9d7266274c67c21d2e Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 7 Jan 2022 14:38:44 +0100 Subject: [PATCH 669/730] softmmu/device_tree: Silence compiler warning with --enable-sanitizers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If I configure my build with --enable-sanitizers, my GCC (v8.5.0) complains: .../softmmu/device_tree.c: In function ‘qemu_fdt_add_path’: .../softmmu/device_tree.c:560:18: error: ‘retval’ may be used uninitialized in this function [-Werror=maybe-uninitialized] int namelen, retval; ^~~~~~ It's a false warning since the while loop is always executed at least once (p has to be non-NULL, otherwise the derefence in the if-statement earlier will crash). Thus let's switch to a do-while loop here instead to make the compiler happy in all cases. Signed-off-by: Thomas Huth Reviewed-by: Andrew Jones Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Reviewed-by: Yanan Wang Message-id: 20220107133844.145039-1-thuth@redhat.com Signed-off-by: Alistair Francis --- softmmu/device_tree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c index 31d1066940..0a433c98e2 100644 --- a/softmmu/device_tree.c +++ b/softmmu/device_tree.c @@ -566,7 +566,7 @@ int qemu_fdt_add_path(void *fdt, const char *path) return -1; } - while (p) { + do { name = p + 1; p = strchr(name, '/'); namelen = p != NULL ? p - name : strlen(name); @@ -586,7 +586,7 @@ int qemu_fdt_add_path(void *fdt, const char *path) } parent = retval; - } + } while (p); return retval; } From 22599b795c8395fa3e2a90c3b32ca1622035feeb Mon Sep 17 00:00:00 2001 From: Yanan Wang Date: Tue, 11 Jan 2022 11:27:58 +0800 Subject: [PATCH 670/730] softmmu/device_tree: Remove redundant pointer assignment The pointer assignment "const char *p = path;" in function qemu_fdt_add_path is unnecessary. Let's remove it and just use the "path" passed in. No functional change. Suggested-by: Richard Henderson Signed-off-by: Yanan Wang Reviewed-by: Andrew Jones Reviewed-by: Alistair Francis Reviewed-by: Thomas Huth Message-id: 20220111032758.27804-1-wangyanan55@huawei.com Signed-off-by: Alistair Francis --- softmmu/device_tree.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c index 0a433c98e2..6ca3fad285 100644 --- a/softmmu/device_tree.c +++ b/softmmu/device_tree.c @@ -558,7 +558,6 @@ int qemu_fdt_add_subnode(void *fdt, const char *name) int qemu_fdt_add_path(void *fdt, const char *path) { const char *name; - const char *p = path; int namelen, retval; int parent = 0; @@ -567,9 +566,9 @@ int qemu_fdt_add_path(void *fdt, const char *path) } do { - name = p + 1; - p = strchr(name, '/'); - namelen = p != NULL ? p - name : strlen(name); + name = path + 1; + path = strchr(name, '/'); + namelen = path != NULL ? path - name : strlen(name); retval = fdt_subnode_offset_namelen(fdt, parent, name, namelen); if (retval < 0 && retval != -FDT_ERR_NOTFOUND) { @@ -586,7 +585,7 @@ int qemu_fdt_add_path(void *fdt, const char *path) } parent = retval; - } while (p); + } while (path); return retval; } From b4a99d40276eb5bdfa849cc04344d9a2c4c820ef Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:04 +0800 Subject: [PATCH 671/730] target/riscv: rvv-1.0: Add Zve64f extension into RISC-V Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-2-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 4 ++++ target/riscv/cpu.h | 1 + target/riscv/cpu_helper.c | 5 ++++- target/riscv/csr.c | 6 +++++- target/riscv/translate.c | 2 ++ 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 32879f1403..cdb893d601 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -609,6 +609,10 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) } set_vext_version(env, vext_version); } + if (cpu->cfg.ext_zve64f && !cpu->cfg.ext_f) { + error_setg(errp, "Zve64f extension depends upon RVF."); + return; + } if (cpu->cfg.ext_j) { ext |= RVJ; } diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 22c94d3c57..424bdcc7fa 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -340,6 +340,7 @@ struct RISCVCPU { bool ext_icsr; bool ext_zfh; bool ext_zfhmin; + bool ext_zve64f; char *priv_spec; char *user_spec; diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 434a83e66a..43d498aae1 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -69,12 +69,15 @@ static RISCVMXL cpu_get_xl(CPURISCVState *env) void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { + CPUState *cs = env_cpu(env); + RISCVCPU *cpu = RISCV_CPU(cs); + uint32_t flags = 0; *pc = env->pc; *cs_base = 0; - if (riscv_has_ext(env, RVV)) { + if (riscv_has_ext(env, RVV) || cpu->cfg.ext_zve64f) { /* * If env->vl equals to VLMAX, we can use generic vector operation * expanders (GVEC) to accerlate the vector operations. diff --git a/target/riscv/csr.c b/target/riscv/csr.c index adb3d4381d..e9311cfd9d 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -47,7 +47,11 @@ static RISCVException fs(CPURISCVState *env, int csrno) static RISCVException vs(CPURISCVState *env, int csrno) { - if (env->misa_ext & RVV) { + CPUState *cs = env_cpu(env); + RISCVCPU *cpu = RISCV_CPU(cs); + + if (env->misa_ext & RVV || + cpu->cfg.ext_zve64f) { #if !defined(CONFIG_USER_ONLY) if (!env->debugger && !riscv_cpu_vector_enabled(env)) { return RISCV_EXCP_ILLEGAL_INST; diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 615048ec87..d3c0d44e2e 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -79,6 +79,7 @@ typedef struct DisasContext { bool ext_ifencei; bool ext_zfh; bool ext_zfhmin; + bool ext_zve64f; bool hlsx; /* vector extension */ bool vill; @@ -894,6 +895,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->ext_ifencei = cpu->cfg.ext_ifencei; ctx->ext_zfh = cpu->cfg.ext_zfh; ctx->ext_zfhmin = cpu->cfg.ext_zfhmin; + ctx->ext_zve64f = cpu->cfg.ext_zve64f; ctx->vlen = cpu->cfg.vlen; ctx->elen = cpu->cfg.elen; ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS); From c7a26fb2f6bafd45b983d81d180f624c0e8c4d2b Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:05 +0800 Subject: [PATCH 672/730] target/riscv: rvv-1.0: Add Zve64f support for configuration insns All Zve* extensions support the vector configuration instructions. Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-3-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 6c285c958b..5b47729a21 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -129,7 +129,8 @@ static bool do_vsetvl(DisasContext *s, int rd, int rs1, TCGv s2) { TCGv s1, dst; - if (!require_rvv(s) || !has_ext(s, RVV)) { + if (!require_rvv(s) || + !(has_ext(s, RVV) || s->ext_zve64f)) { return false; } @@ -164,7 +165,8 @@ static bool do_vsetivli(DisasContext *s, int rd, TCGv s1, TCGv s2) { TCGv dst; - if (!require_rvv(s) || !has_ext(s, RVV)) { + if (!require_rvv(s) || + !(has_ext(s, RVV) || s->ext_zve64f)) { return false; } From 494104093fafab12208a8f1f0cb2ab5f5c8c7035 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:06 +0800 Subject: [PATCH 673/730] target/riscv: rvv-1.0: Add Zve64f support for load and store insns All Zve* extensions support all vector load and store instructions, except Zve64* extensions do not support EEW=64 for index values when XLEN=32. Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-4-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 5b47729a21..0bf41aaa1e 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -263,10 +263,21 @@ static bool vext_check_st_index(DisasContext *s, int vd, int vs2, int nf, uint8_t eew) { int8_t emul = eew - s->sew + s->lmul; - return (emul >= -3 && emul <= 3) && - require_align(vs2, emul) && - require_align(vd, s->lmul) && - require_nf(vd, nf, s->lmul); + bool ret = (emul >= -3 && emul <= 3) && + require_align(vs2, emul) && + require_align(vd, s->lmul) && + require_nf(vd, nf, s->lmul); + + /* + * All Zve* extensions support all vector load and store instructions, + * except Zve64* extensions do not support EEW=64 for index values + * when XLEN=32. (Section 18.2) + */ + if (get_xl(s) == MXL_RV32) { + ret &= (!has_ext(s, RVV) && s->ext_zve64f ? eew != MO_64 : true); + } + + return ret; } /* From aaae69942f5c73a724daf09dcbd963cd852ccb64 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:07 +0800 Subject: [PATCH 674/730] target/riscv: rvv-1.0: Add Zve64f support for vmulh variant insns All Zve* extensions support all vector integer instructions, except that the vmulh integer multiply variants that return the high word of the product (vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx) are not included for EEW=64 in Zve64*. Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-5-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 39 +++++++++++++++++++++---- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 0bf41aaa1e..e64dddda28 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -1908,14 +1908,41 @@ GEN_OPIVX_TRANS(vmaxu_vx, opivx_check) GEN_OPIVX_TRANS(vmax_vx, opivx_check) /* Vector Single-Width Integer Multiply Instructions */ + +static bool vmulh_vv_check(DisasContext *s, arg_rmrr *a) +{ + /* + * All Zve* extensions support all vector integer instructions, + * except that the vmulh integer multiply variants + * that return the high word of the product + * (vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx) + * are not included for EEW=64 in Zve64*. (Section 18.2) + */ + return opivv_check(s, a) && + (!has_ext(s, RVV) && s->ext_zve64f ? s->sew != MO_64 : true); +} + +static bool vmulh_vx_check(DisasContext *s, arg_rmrr *a) +{ + /* + * All Zve* extensions support all vector integer instructions, + * except that the vmulh integer multiply variants + * that return the high word of the product + * (vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx) + * are not included for EEW=64 in Zve64*. (Section 18.2) + */ + return opivx_check(s, a) && + (!has_ext(s, RVV) && s->ext_zve64f ? s->sew != MO_64 : true); +} + GEN_OPIVV_GVEC_TRANS(vmul_vv, mul) -GEN_OPIVV_TRANS(vmulh_vv, opivv_check) -GEN_OPIVV_TRANS(vmulhu_vv, opivv_check) -GEN_OPIVV_TRANS(vmulhsu_vv, opivv_check) +GEN_OPIVV_TRANS(vmulh_vv, vmulh_vv_check) +GEN_OPIVV_TRANS(vmulhu_vv, vmulh_vv_check) +GEN_OPIVV_TRANS(vmulhsu_vv, vmulh_vv_check) GEN_OPIVX_GVEC_TRANS(vmul_vx, muls) -GEN_OPIVX_TRANS(vmulh_vx, opivx_check) -GEN_OPIVX_TRANS(vmulhu_vx, opivx_check) -GEN_OPIVX_TRANS(vmulhsu_vx, opivx_check) +GEN_OPIVX_TRANS(vmulh_vx, vmulh_vx_check) +GEN_OPIVX_TRANS(vmulhu_vx, vmulh_vx_check) +GEN_OPIVX_TRANS(vmulhsu_vx, vmulh_vx_check) /* Vector Integer Divide Instructions */ GEN_OPIVV_TRANS(vdivu_vv, opivv_check) From 13dbc826fd086dd40b7a4d3f1cb3f1bc8454b586 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:08 +0800 Subject: [PATCH 675/730] target/riscv: rvv-1.0: Add Zve64f support for vsmul.vv and vsmul.vx insns All Zve* extensions support all vector fixed-point arithmetic instructions, except that vsmul.vv and vsmul.vx are not supported for EEW=64 in Zve64*. Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-6-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 27 +++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index e64dddda28..8e493b7933 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -2123,8 +2123,31 @@ GEN_OPIVX_TRANS(vasub_vx, opivx_check) GEN_OPIVX_TRANS(vasubu_vx, opivx_check) /* Vector Single-Width Fractional Multiply with Rounding and Saturation */ -GEN_OPIVV_TRANS(vsmul_vv, opivv_check) -GEN_OPIVX_TRANS(vsmul_vx, opivx_check) + +static bool vsmul_vv_check(DisasContext *s, arg_rmrr *a) +{ + /* + * All Zve* extensions support all vector fixed-point arithmetic + * instructions, except that vsmul.vv and vsmul.vx are not supported + * for EEW=64 in Zve64*. (Section 18.2) + */ + return opivv_check(s, a) && + (!has_ext(s, RVV) && s->ext_zve64f ? s->sew != MO_64 : true); +} + +static bool vsmul_vx_check(DisasContext *s, arg_rmrr *a) +{ + /* + * All Zve* extensions support all vector fixed-point arithmetic + * instructions, except that vsmul.vv and vsmul.vx are not supported + * for EEW=64 in Zve64*. (Section 18.2) + */ + return opivx_check(s, a) && + (!has_ext(s, RVV) && s->ext_zve64f ? s->sew != MO_64 : true); +} + +GEN_OPIVV_TRANS(vsmul_vv, vsmul_vv_check) +GEN_OPIVX_TRANS(vsmul_vx, vsmul_vx_check) /* Vector Single-Width Scaling Shift Instructions */ GEN_OPIVV_TRANS(vssrl_vv, opivv_check) From 40d78c85f6f321c00588230a400477250a85c2e7 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:09 +0800 Subject: [PATCH 676/730] target/riscv: rvv-1.0: Add Zve64f support for scalar fp insns Zve64f extension requires the scalar processor to implement the F extension and implement all vector floating-point instructions for floating-point operands with EEW=32 (i.e., no widening floating-point operations). Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-7-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 41 +++++++++++++++++++------ 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 8e493b7933..56246a5d88 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -66,6 +66,17 @@ static bool require_scale_rvf(DisasContext *s) } } +static bool require_zve64f(DisasContext *s) +{ + /* RVV + Zve64f = RVV. */ + if (has_ext(s, RVV)) { + return true; + } + + /* Zve64f doesn't support FP64. (Section 18.2) */ + return s->ext_zve64f ? s->sew <= MO_32 : true; +} + /* Destination vector register group cannot overlap source mask register. */ static bool require_vm(int vm, int vd) { @@ -2206,7 +2217,8 @@ static bool opfvv_check(DisasContext *s, arg_rmrr *a) return require_rvv(s) && require_rvf(s) && vext_check_isa_ill(s) && - vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm); + vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm) && + require_zve64f(s); } /* OPFVV without GVEC IR */ @@ -2286,7 +2298,8 @@ static bool opfvf_check(DisasContext *s, arg_rmrr *a) return require_rvv(s) && require_rvf(s) && vext_check_isa_ill(s) && - vext_check_ss(s, a->rd, a->rs2, a->vm); + vext_check_ss(s, a->rd, a->rs2, a->vm) && + require_zve64f(s); } /* OPFVF without GVEC IR */ @@ -2503,7 +2516,8 @@ static bool opfv_check(DisasContext *s, arg_rmr *a) require_rvf(s) && vext_check_isa_ill(s) && /* OPFV instructions ignore vs1 check */ - vext_check_ss(s, a->rd, a->rs2, a->vm); + vext_check_ss(s, a->rd, a->rs2, a->vm) && + require_zve64f(s); } static bool do_opfv(DisasContext *s, arg_rmr *a, @@ -2568,7 +2582,8 @@ static bool opfvv_cmp_check(DisasContext *s, arg_rmrr *a) return require_rvv(s) && require_rvf(s) && vext_check_isa_ill(s) && - vext_check_mss(s, a->rd, a->rs1, a->rs2); + vext_check_mss(s, a->rd, a->rs1, a->rs2) && + require_zve64f(s); } GEN_OPFVV_TRANS(vmfeq_vv, opfvv_cmp_check) @@ -2581,7 +2596,8 @@ static bool opfvf_cmp_check(DisasContext *s, arg_rmrr *a) return require_rvv(s) && require_rvf(s) && vext_check_isa_ill(s) && - vext_check_ms(s, a->rd, a->rs2); + vext_check_ms(s, a->rd, a->rs2) && + require_zve64f(s); } GEN_OPFVF_TRANS(vmfeq_vf, opfvf_cmp_check) @@ -2602,7 +2618,8 @@ static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a) if (require_rvv(s) && require_rvf(s) && vext_check_isa_ill(s) && - require_align(a->rd, s->lmul)) { + require_align(a->rd, s->lmul) && + require_zve64f(s)) { gen_set_rm(s, RISCV_FRM_DYN); TCGv_i64 t1; @@ -3328,7 +3345,8 @@ static bool trans_vfmv_f_s(DisasContext *s, arg_vfmv_f_s *a) { if (require_rvv(s) && require_rvf(s) && - vext_check_isa_ill(s)) { + vext_check_isa_ill(s) && + require_zve64f(s)) { gen_set_rm(s, RISCV_FRM_DYN); unsigned int ofs = (8 << s->sew); @@ -3354,7 +3372,8 @@ static bool trans_vfmv_s_f(DisasContext *s, arg_vfmv_s_f *a) { if (require_rvv(s) && require_rvf(s) && - vext_check_isa_ill(s)) { + vext_check_isa_ill(s) && + require_zve64f(s)) { gen_set_rm(s, RISCV_FRM_DYN); /* The instructions ignore LMUL and vector register group. */ @@ -3405,13 +3424,15 @@ GEN_OPIVI_TRANS(vslidedown_vi, IMM_ZX, vslidedown_vx, slidedown_check) static bool fslideup_check(DisasContext *s, arg_rmrr *a) { return slideup_check(s, a) && - require_rvf(s); + require_rvf(s) && + require_zve64f(s); } static bool fslidedown_check(DisasContext *s, arg_rmrr *a) { return slidedown_check(s, a) && - require_rvf(s); + require_rvf(s) && + require_zve64f(s); } GEN_OPFVF_TRANS(vfslide1up_vf, fslideup_check) From 193fb5c9bd1fbf8a0b78c75f2056b0d7d9fc0ffe Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:10 +0800 Subject: [PATCH 677/730] target/riscv: rvv-1.0: Add Zve64f support for single-width fp reduction insns Vector single-width floating-point reduction operations for EEW=32 are supported for Zve64f extension. Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-8-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 56246a5d88..08f25e3ce4 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -2937,7 +2937,8 @@ GEN_OPIVV_WIDEN_TRANS(vwredsumu_vs, reduction_widen_check) static bool freduction_check(DisasContext *s, arg_rmrr *a) { return reduction_check(s, a) && - require_rvf(s); + require_rvf(s) && + require_zve64f(s); } GEN_OPFVV_TRANS(vfredsum_vs, freduction_check) From 235d1161d4ddbcd2d80aad7253ef69f2f5819926 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:11 +0800 Subject: [PATCH 678/730] target/riscv: rvv-1.0: Add Zve64f support for widening type-convert insns Vector widening conversion instructions are provided to and from all supported integer EEWs for Zve64f extension. Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-9-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 32 +++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 08f25e3ce4..58f12366dd 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -77,6 +77,17 @@ static bool require_zve64f(DisasContext *s) return s->ext_zve64f ? s->sew <= MO_32 : true; } +static bool require_scale_zve64f(DisasContext *s) +{ + /* RVV + Zve64f = RVV. */ + if (has_ext(s, RVV)) { + return true; + } + + /* Zve64f doesn't support FP64. (Section 18.2) */ + return s->ext_zve64f ? s->sew <= MO_16 : true; +} + /* Destination vector register group cannot overlap source mask register. */ static bool require_vm(int vm, int vd) { @@ -2333,7 +2344,8 @@ static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a) require_scale_rvf(s) && (s->sew != MO_8) && vext_check_isa_ill(s) && - vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm); + vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm) && + require_scale_zve64f(s); } /* OPFVV with WIDEN */ @@ -2372,7 +2384,8 @@ static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a) require_scale_rvf(s) && (s->sew != MO_8) && vext_check_isa_ill(s) && - vext_check_ds(s, a->rd, a->rs2, a->vm); + vext_check_ds(s, a->rd, a->rs2, a->vm) && + require_scale_zve64f(s); } /* OPFVF with WIDEN */ @@ -2402,7 +2415,8 @@ static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a) require_scale_rvf(s) && (s->sew != MO_8) && vext_check_isa_ill(s) && - vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm); + vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm) && + require_scale_zve64f(s); } /* WIDEN OPFVV with WIDEN */ @@ -2441,7 +2455,8 @@ static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a) require_scale_rvf(s) && (s->sew != MO_8) && vext_check_isa_ill(s) && - vext_check_dd(s, a->rd, a->rs2, a->vm); + vext_check_dd(s, a->rd, a->rs2, a->vm) && + require_scale_zve64f(s); } /* WIDEN OPFVF with WIDEN */ @@ -2700,14 +2715,16 @@ static bool opfv_widen_check(DisasContext *s, arg_rmr *a) static bool opxfv_widen_check(DisasContext *s, arg_rmr *a) { return opfv_widen_check(s, a) && - require_rvf(s); + require_rvf(s) && + require_zve64f(s); } static bool opffv_widen_check(DisasContext *s, arg_rmr *a) { return opfv_widen_check(s, a) && require_scale_rvf(s) && - (s->sew != MO_8); + (s->sew != MO_8) && + require_scale_zve64f(s); } #define GEN_OPFV_WIDEN_TRANS(NAME, CHECK, HELPER, FRM) \ @@ -2758,7 +2775,8 @@ static bool opfxv_widen_check(DisasContext *s, arg_rmr *a) require_scale_rvf(s) && vext_check_isa_ill(s) && /* OPFV widening instructions ignore vs1 check */ - vext_check_ds(s, a->rd, a->rs2, a->vm); + vext_check_ds(s, a->rd, a->rs2, a->vm) && + require_scale_zve64f(s); } #define GEN_OPFXV_WIDEN_TRANS(NAME) \ From 68fa38970ea0f9fdcbf01f6e04531de72d40f755 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:12 +0800 Subject: [PATCH 679/730] target/riscv: rvv-1.0: Add Zve64f support for narrowing type-convert insns Vector narrowing conversion instructions are provided to and from all supported integer EEWs for Zve64f extension. Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-10-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 58f12366dd..9fa3862620 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -2826,14 +2826,16 @@ static bool opfxv_narrow_check(DisasContext *s, arg_rmr *a) { return opfv_narrow_check(s, a) && require_rvf(s) && - (s->sew != MO_64); + (s->sew != MO_64) && + require_zve64f(s); } static bool opffv_narrow_check(DisasContext *s, arg_rmr *a) { return opfv_narrow_check(s, a) && require_scale_rvf(s) && - (s->sew != MO_8); + (s->sew != MO_8) && + require_scale_zve64f(s); } #define GEN_OPFV_NARROW_TRANS(NAME, CHECK, HELPER, FRM) \ @@ -2882,7 +2884,8 @@ static bool opxfv_narrow_check(DisasContext *s, arg_rmr *a) require_scale_rvf(s) && vext_check_isa_ill(s) && /* OPFV narrowing instructions ignore vs1 check */ - vext_check_sd(s, a->rd, a->rs2, a->vm); + vext_check_sd(s, a->rd, a->rs2, a->vm) && + require_scale_zve64f(s); } #define GEN_OPXFV_NARROW_TRANS(NAME, HELPER, FRM) \ From bfefe406b7666bfc624bf54820aa14bd43838dc5 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:13 +0800 Subject: [PATCH 680/730] target/riscv: rvv-1.0: Allow Zve64f extension to be turned on Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-11-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index cdb893d601..4f3d733db4 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -688,6 +688,7 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false), DEFINE_PROP_BOOL("Zfhmin", RISCVCPU, cfg.ext_zfhmin, false), + DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false), DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), From 32e579b8c510f0c8d7023d87b0cfacf782cb4a62 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:14 +0800 Subject: [PATCH 681/730] target/riscv: rvv-1.0: Add Zve32f extension into RISC-V Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-12-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 4 ++-- target/riscv/cpu.h | 1 + target/riscv/cpu_helper.c | 2 +- target/riscv/csr.c | 2 +- target/riscv/translate.c | 2 ++ 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 4f3d733db4..ef269378de 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -609,8 +609,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) } set_vext_version(env, vext_version); } - if (cpu->cfg.ext_zve64f && !cpu->cfg.ext_f) { - error_setg(errp, "Zve64f extension depends upon RVF."); + if ((cpu->cfg.ext_zve32f || cpu->cfg.ext_zve64f) && !cpu->cfg.ext_f) { + error_setg(errp, "Zve32f/Zve64f extension depends upon RVF."); return; } if (cpu->cfg.ext_j) { diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 424bdcc7fa..03552f4aaa 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -340,6 +340,7 @@ struct RISCVCPU { bool ext_icsr; bool ext_zfh; bool ext_zfhmin; + bool ext_zve32f; bool ext_zve64f; char *priv_spec; diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 43d498aae1..afee770951 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -77,7 +77,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, *pc = env->pc; *cs_base = 0; - if (riscv_has_ext(env, RVV) || cpu->cfg.ext_zve64f) { + if (riscv_has_ext(env, RVV) || cpu->cfg.ext_zve32f || cpu->cfg.ext_zve64f) { /* * If env->vl equals to VLMAX, we can use generic vector operation * expanders (GVEC) to accerlate the vector operations. diff --git a/target/riscv/csr.c b/target/riscv/csr.c index e9311cfd9d..a9e7ac903b 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -51,7 +51,7 @@ static RISCVException vs(CPURISCVState *env, int csrno) RISCVCPU *cpu = RISCV_CPU(cs); if (env->misa_ext & RVV || - cpu->cfg.ext_zve64f) { + cpu->cfg.ext_zve32f || cpu->cfg.ext_zve64f) { #if !defined(CONFIG_USER_ONLY) if (!env->debugger && !riscv_cpu_vector_enabled(env)) { return RISCV_EXCP_ILLEGAL_INST; diff --git a/target/riscv/translate.c b/target/riscv/translate.c index d3c0d44e2e..330904265e 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -79,6 +79,7 @@ typedef struct DisasContext { bool ext_ifencei; bool ext_zfh; bool ext_zfhmin; + bool ext_zve32f; bool ext_zve64f; bool hlsx; /* vector extension */ @@ -895,6 +896,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->ext_ifencei = cpu->cfg.ext_ifencei; ctx->ext_zfh = cpu->cfg.ext_zfh; ctx->ext_zfhmin = cpu->cfg.ext_zfhmin; + ctx->ext_zve32f = cpu->cfg.ext_zve32f; ctx->ext_zve64f = cpu->cfg.ext_zve64f; ctx->vlen = cpu->cfg.vlen; ctx->elen = cpu->cfg.elen; From da61f1256f55a5e9fc03f7c88e3caa425d6bf8cf Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:15 +0800 Subject: [PATCH 682/730] target/riscv: rvv-1.0: Add Zve32f support for configuration insns All Zve* extensions support the vector configuration instructions. Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-13-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 9fa3862620..fd6e74c232 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -152,7 +152,7 @@ static bool do_vsetvl(DisasContext *s, int rd, int rs1, TCGv s2) TCGv s1, dst; if (!require_rvv(s) || - !(has_ext(s, RVV) || s->ext_zve64f)) { + !(has_ext(s, RVV) || s->ext_zve32f || s->ext_zve64f)) { return false; } @@ -188,7 +188,7 @@ static bool do_vsetivli(DisasContext *s, int rd, TCGv s1, TCGv s2) TCGv dst; if (!require_rvv(s) || - !(has_ext(s, RVV) || s->ext_zve64f)) { + !(has_ext(s, RVV) || s->ext_zve32f || s->ext_zve64f)) { return false; } From abe2d74032d6d12a6918715086bbdf8843296f36 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:16 +0800 Subject: [PATCH 683/730] target/riscv: rvv-1.0: Add Zve32f support for scalar fp insns Zve32f extension requires the scalar processor to implement the F extension and implement all vector floating-point instructions for floating-point operands with EEW=32 (i.e., no widening floating-point operations). Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-14-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index fd6e74c232..fe4ad5d008 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -66,6 +66,17 @@ static bool require_scale_rvf(DisasContext *s) } } +static bool require_zve32f(DisasContext *s) +{ + /* RVV + Zve32f = RVV. */ + if (has_ext(s, RVV)) { + return true; + } + + /* Zve32f doesn't support FP64. (Section 18.2) */ + return s->ext_zve32f ? s->sew <= MO_32 : true; +} + static bool require_zve64f(DisasContext *s) { /* RVV + Zve64f = RVV. */ @@ -2229,6 +2240,7 @@ static bool opfvv_check(DisasContext *s, arg_rmrr *a) require_rvf(s) && vext_check_isa_ill(s) && vext_check_sss(s, a->rd, a->rs1, a->rs2, a->vm) && + require_zve32f(s) && require_zve64f(s); } @@ -2310,6 +2322,7 @@ static bool opfvf_check(DisasContext *s, arg_rmrr *a) require_rvf(s) && vext_check_isa_ill(s) && vext_check_ss(s, a->rd, a->rs2, a->vm) && + require_zve32f(s) && require_zve64f(s); } @@ -2532,6 +2545,7 @@ static bool opfv_check(DisasContext *s, arg_rmr *a) vext_check_isa_ill(s) && /* OPFV instructions ignore vs1 check */ vext_check_ss(s, a->rd, a->rs2, a->vm) && + require_zve32f(s) && require_zve64f(s); } @@ -2598,6 +2612,7 @@ static bool opfvv_cmp_check(DisasContext *s, arg_rmrr *a) require_rvf(s) && vext_check_isa_ill(s) && vext_check_mss(s, a->rd, a->rs1, a->rs2) && + require_zve32f(s) && require_zve64f(s); } @@ -2612,6 +2627,7 @@ static bool opfvf_cmp_check(DisasContext *s, arg_rmrr *a) require_rvf(s) && vext_check_isa_ill(s) && vext_check_ms(s, a->rd, a->rs2) && + require_zve32f(s) && require_zve64f(s); } @@ -2634,6 +2650,7 @@ static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a) require_rvf(s) && vext_check_isa_ill(s) && require_align(a->rd, s->lmul) && + require_zve32f(s) && require_zve64f(s)) { gen_set_rm(s, RISCV_FRM_DYN); @@ -3368,6 +3385,7 @@ static bool trans_vfmv_f_s(DisasContext *s, arg_vfmv_f_s *a) if (require_rvv(s) && require_rvf(s) && vext_check_isa_ill(s) && + require_zve32f(s) && require_zve64f(s)) { gen_set_rm(s, RISCV_FRM_DYN); @@ -3395,6 +3413,7 @@ static bool trans_vfmv_s_f(DisasContext *s, arg_vfmv_s_f *a) if (require_rvv(s) && require_rvf(s) && vext_check_isa_ill(s) && + require_zve32f(s) && require_zve64f(s)) { gen_set_rm(s, RISCV_FRM_DYN); @@ -3447,6 +3466,7 @@ static bool fslideup_check(DisasContext *s, arg_rmrr *a) { return slideup_check(s, a) && require_rvf(s) && + require_zve32f(s) && require_zve64f(s); } @@ -3454,6 +3474,7 @@ static bool fslidedown_check(DisasContext *s, arg_rmrr *a) { return slidedown_check(s, a) && require_rvf(s) && + require_zve32f(s) && require_zve64f(s); } From 8527b5db728b572c288fdcadb126d369040731be Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:17 +0800 Subject: [PATCH 684/730] target/riscv: rvv-1.0: Add Zve32f support for single-width fp reduction insns Vector single-width floating-point reduction operations for EEW=32 are supported for Zve32f extension. Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-15-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index fe4ad5d008..b02bb555a6 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -2976,6 +2976,7 @@ static bool freduction_check(DisasContext *s, arg_rmrr *a) { return reduction_check(s, a) && require_rvf(s) && + require_zve32f(s) && require_zve64f(s); } From f4dcf51cdcd25e8df150b0a394ccefc0611975dc Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:18 +0800 Subject: [PATCH 685/730] target/riscv: rvv-1.0: Add Zve32f support for widening type-convert insns Vector widening conversion instructions are provided to and from all supported integer EEWs for Zve32f extension. Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-16-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index b02bb555a6..f2d3c9e8b9 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -77,6 +77,17 @@ static bool require_zve32f(DisasContext *s) return s->ext_zve32f ? s->sew <= MO_32 : true; } +static bool require_scale_zve32f(DisasContext *s) +{ + /* RVV + Zve32f = RVV. */ + if (has_ext(s, RVV)) { + return true; + } + + /* Zve32f doesn't support FP64. (Section 18.2) */ + return s->ext_zve64f ? s->sew <= MO_16 : true; +} + static bool require_zve64f(DisasContext *s) { /* RVV + Zve64f = RVV. */ @@ -2358,6 +2369,7 @@ static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a) (s->sew != MO_8) && vext_check_isa_ill(s) && vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm) && + require_scale_zve32f(s) && require_scale_zve64f(s); } @@ -2398,6 +2410,7 @@ static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a) (s->sew != MO_8) && vext_check_isa_ill(s) && vext_check_ds(s, a->rd, a->rs2, a->vm) && + require_scale_zve32f(s) && require_scale_zve64f(s); } @@ -2429,6 +2442,7 @@ static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a) (s->sew != MO_8) && vext_check_isa_ill(s) && vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm) && + require_scale_zve32f(s) && require_scale_zve64f(s); } @@ -2469,6 +2483,7 @@ static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a) (s->sew != MO_8) && vext_check_isa_ill(s) && vext_check_dd(s, a->rd, a->rs2, a->vm) && + require_scale_zve32f(s) && require_scale_zve64f(s); } @@ -2733,6 +2748,7 @@ static bool opxfv_widen_check(DisasContext *s, arg_rmr *a) { return opfv_widen_check(s, a) && require_rvf(s) && + require_zve32f(s) && require_zve64f(s); } @@ -2741,6 +2757,7 @@ static bool opffv_widen_check(DisasContext *s, arg_rmr *a) return opfv_widen_check(s, a) && require_scale_rvf(s) && (s->sew != MO_8) && + require_scale_zve32f(s) && require_scale_zve64f(s); } @@ -2793,6 +2810,7 @@ static bool opfxv_widen_check(DisasContext *s, arg_rmr *a) vext_check_isa_ill(s) && /* OPFV widening instructions ignore vs1 check */ vext_check_ds(s, a->rd, a->rs2, a->vm) && + require_scale_zve32f(s) && require_scale_zve64f(s); } From 6db02328a7537fb62c282700f34d9b0c0a845854 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:19 +0800 Subject: [PATCH 686/730] target/riscv: rvv-1.0: Add Zve32f support for narrowing type-convert insns Vector narrowing conversion instructions are provided to and from all supported integer EEWs for Zve32f extension. Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-17-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index f2d3c9e8b9..7a040b3089 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -2862,6 +2862,7 @@ static bool opfxv_narrow_check(DisasContext *s, arg_rmr *a) return opfv_narrow_check(s, a) && require_rvf(s) && (s->sew != MO_64) && + require_zve32f(s) && require_zve64f(s); } @@ -2870,6 +2871,7 @@ static bool opffv_narrow_check(DisasContext *s, arg_rmr *a) return opfv_narrow_check(s, a) && require_scale_rvf(s) && (s->sew != MO_8) && + require_scale_zve32f(s) && require_scale_zve64f(s); } @@ -2920,6 +2922,7 @@ static bool opxfv_narrow_check(DisasContext *s, arg_rmr *a) vext_check_isa_ill(s) && /* OPFV narrowing instructions ignore vs1 check */ vext_check_sd(s, a->rd, a->rs2, a->vm) && + require_scale_zve32f(s) && require_scale_zve64f(s); } From 2fc1b44dd0e7ea9ad5920352fd04179e4d6836d9 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Tue, 18 Jan 2022 09:45:20 +0800 Subject: [PATCH 687/730] target/riscv: rvv-1.0: Allow Zve32f extension to be turned on Signed-off-by: Frank Chang Reviewed-by: Alistair Francis Message-id: 20220118014522.13613-18-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ef269378de..c2b570e904 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -688,6 +688,7 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false), DEFINE_PROP_BOOL("Zfhmin", RISCVCPU, cfg.ext_zfhmin, false), + DEFINE_PROP_BOOL("Zve32f", RISCVCPU, cfg.ext_zve32f, false), DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false), DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), From 8d8897accb1c9b28267b3c7eb402b6bc5d967f7e Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Thu, 13 Jan 2022 20:20:39 +0530 Subject: [PATCH 688/730] hw/riscv: spike: Allow using binary firmware as bios Currently, we have to use OpenSBI firmware ELF as bios for the spike machine because the HTIF console requires ELF for parsing "fromhost" and "tohost" symbols. The latest OpenSBI can now optionally pick-up HTIF register address from HTIF DT node so using this feature spike machine can now use OpenSBI firmware BIN as bios. Signed-off-by: Anup Patel Reviewed-by: Alistair Francis Reviewed-by: Bin Meng Signed-off-by: Alistair Francis --- hw/char/riscv_htif.c | 35 +++++++++++++++++++----------- hw/riscv/spike.c | 41 ++++++++++++++++++++++-------------- include/hw/char/riscv_htif.h | 5 ++++- include/hw/riscv/spike.h | 1 + 4 files changed, 53 insertions(+), 29 deletions(-) diff --git a/hw/char/riscv_htif.c b/hw/char/riscv_htif.c index ddae738d56..729edbf968 100644 --- a/hw/char/riscv_htif.c +++ b/hw/char/riscv_htif.c @@ -228,13 +228,25 @@ static const MemoryRegionOps htif_mm_ops = { .write = htif_mm_write, }; -HTIFState *htif_mm_init(MemoryRegion *address_space, MemoryRegion *main_mem, - CPURISCVState *env, Chardev *chr) +bool htif_uses_elf_symbols(void) { - uint64_t base = MIN(tohost_addr, fromhost_addr); - uint64_t size = MAX(tohost_addr + 8, fromhost_addr + 8) - base; - uint64_t tohost_offset = tohost_addr - base; - uint64_t fromhost_offset = fromhost_addr - base; + return (address_symbol_set == 3) ? true : false; +} + +HTIFState *htif_mm_init(MemoryRegion *address_space, MemoryRegion *main_mem, + CPURISCVState *env, Chardev *chr, uint64_t nonelf_base) +{ + uint64_t base, size, tohost_offset, fromhost_offset; + + if (!htif_uses_elf_symbols()) { + fromhost_addr = nonelf_base; + tohost_addr = nonelf_base + 8; + } + + base = MIN(tohost_addr, fromhost_addr); + size = MAX(tohost_addr + 8, fromhost_addr + 8) - base; + tohost_offset = tohost_addr - base; + fromhost_offset = fromhost_addr - base; HTIFState *s = g_malloc0(sizeof(HTIFState)); s->address_space = address_space; @@ -249,12 +261,11 @@ HTIFState *htif_mm_init(MemoryRegion *address_space, MemoryRegion *main_mem, qemu_chr_fe_init(&s->chr, chr, &error_abort); qemu_chr_fe_set_handlers(&s->chr, htif_can_recv, htif_recv, htif_event, htif_be_change, s, NULL, true); - if (address_symbol_set == 3) { - memory_region_init_io(&s->mmio, NULL, &htif_mm_ops, s, - TYPE_HTIF_UART, size); - memory_region_add_subregion_overlap(address_space, base, - &s->mmio, 1); - } + + memory_region_init_io(&s->mmio, NULL, &htif_mm_ops, s, + TYPE_HTIF_UART, size); + memory_region_add_subregion_overlap(address_space, base, + &s->mmio, 1); return s; } diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 288d69cd9f..597df4c288 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -42,6 +42,7 @@ static const MemMapEntry spike_memmap[] = { [SPIKE_MROM] = { 0x1000, 0xf000 }, + [SPIKE_HTIF] = { 0x1000000, 0x1000 }, [SPIKE_CLINT] = { 0x2000000, 0x10000 }, [SPIKE_DRAM] = { 0x80000000, 0x0 }, }; @@ -75,6 +76,10 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap, qemu_fdt_add_subnode(fdt, "/htif"); qemu_fdt_setprop_string(fdt, "/htif", "compatible", "ucb,htif0"); + if (!htif_uses_elf_symbols()) { + qemu_fdt_setprop_cells(fdt, "/htif", "reg", + 0x0, memmap[SPIKE_HTIF].base, 0x0, memmap[SPIKE_HTIF].size); + } qemu_fdt_add_subnode(fdt, "/soc"); qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0); @@ -172,6 +177,7 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap, if (cmdline) { qemu_fdt_add_subnode(fdt, "/chosen"); qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); + qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", "/htif"); } } @@ -241,10 +247,6 @@ static void spike_board_init(MachineState *machine) memory_region_add_subregion(system_memory, memmap[SPIKE_DRAM].base, machine->ram); - /* create device tree */ - create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline, - riscv_is_32bit(&s->soc[0])); - /* boot rom */ memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom", memmap[SPIKE_MROM].size, &error_fatal); @@ -266,6 +268,7 @@ static void spike_board_init(MachineState *machine) htif_symbol_callback); } + /* Load kernel */ if (machine->kernel_filename) { kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], firmware_end_addr); @@ -273,17 +276,6 @@ static void spike_board_init(MachineState *machine) kernel_entry = riscv_load_kernel(machine->kernel_filename, kernel_start_addr, htif_symbol_callback); - - if (machine->initrd_filename) { - hwaddr start; - hwaddr end = riscv_load_initrd(machine->initrd_filename, - machine->ram_size, kernel_entry, - &start); - qemu_fdt_setprop_cell(s->fdt, "/chosen", - "linux,initrd-start", start); - qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end", - end); - } } else { /* * If dynamic firmware is used, it doesn't know where is the next mode @@ -292,6 +284,22 @@ static void spike_board_init(MachineState *machine) kernel_entry = 0; } + /* Create device tree */ + create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline, + riscv_is_32bit(&s->soc[0])); + + /* Load initrd */ + if (machine->kernel_filename && machine->initrd_filename) { + hwaddr start; + hwaddr end = riscv_load_initrd(machine->initrd_filename, + machine->ram_size, kernel_entry, + &start); + qemu_fdt_setprop_cell(s->fdt, "/chosen", + "linux,initrd-start", start); + qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end", + end); + } + /* Compute the fdt load address in dram */ fdt_load_addr = riscv_load_fdt(memmap[SPIKE_DRAM].base, machine->ram_size, s->fdt); @@ -303,7 +311,8 @@ static void spike_board_init(MachineState *machine) /* initialize HTIF using symbols found in load_kernel */ htif_mm_init(system_memory, mask_rom, - &s->soc[0].harts[0].env, serial_hd(0)); + &s->soc[0].harts[0].env, serial_hd(0), + memmap[SPIKE_HTIF].base); } static void spike_machine_instance_init(Object *obj) diff --git a/include/hw/char/riscv_htif.h b/include/hw/char/riscv_htif.h index fb9452cf51..f888ac1b30 100644 --- a/include/hw/char/riscv_htif.h +++ b/include/hw/char/riscv_htif.h @@ -52,8 +52,11 @@ extern const MemoryRegionOps htif_io_ops; void htif_symbol_callback(const char *st_name, int st_info, uint64_t st_value, uint64_t st_size); +/* Check if HTIF uses ELF symbols */ +bool htif_uses_elf_symbols(void); + /* legacy pre qom */ HTIFState *htif_mm_init(MemoryRegion *address_space, MemoryRegion *main_mem, - CPURISCVState *env, Chardev *chr); + CPURISCVState *env, Chardev *chr, uint64_t nonelf_base); #endif diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h index cdd1a13011..73d69234de 100644 --- a/include/hw/riscv/spike.h +++ b/include/hw/riscv/spike.h @@ -43,6 +43,7 @@ struct SpikeState { enum { SPIKE_MROM, + SPIKE_HTIF, SPIKE_CLINT, SPIKE_DRAM }; From 092dc6df92f2f97487747eb1044ac2bcac64924d Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Tue, 18 Jan 2022 13:38:56 +0530 Subject: [PATCH 689/730] hw/riscv: Remove macros for ELF BIOS image names Now that RISC-V Spike machine can use BIN BIOS images, we remove the macros used for ELF BIOS image names. Signed-off-by: Anup Patel Reviewed-by: Alistair Francis Reviewed-by: Bin Meng Signed-off-by: Alistair Francis --- hw/riscv/spike.c | 4 ++-- include/hw/riscv/boot.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 597df4c288..d059a67f9b 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -260,11 +260,11 @@ static void spike_board_init(MachineState *machine) */ if (riscv_is_32bit(&s->soc[0])) { firmware_end_addr = riscv_find_and_load_firmware(machine, - RISCV32_BIOS_ELF, memmap[SPIKE_DRAM].base, + RISCV32_BIOS_BIN, memmap[SPIKE_DRAM].base, htif_symbol_callback); } else { firmware_end_addr = riscv_find_and_load_firmware(machine, - RISCV64_BIOS_ELF, memmap[SPIKE_DRAM].base, + RISCV64_BIOS_BIN, memmap[SPIKE_DRAM].base, htif_symbol_callback); } diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index 5834c234aa..d937c5c224 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -25,9 +25,7 @@ #include "hw/riscv/riscv_hart.h" #define RISCV32_BIOS_BIN "opensbi-riscv32-generic-fw_dynamic.bin" -#define RISCV32_BIOS_ELF "opensbi-riscv32-generic-fw_dynamic.elf" #define RISCV64_BIOS_BIN "opensbi-riscv64-generic-fw_dynamic.bin" -#define RISCV64_BIOS_ELF "opensbi-riscv64-generic-fw_dynamic.elf" bool riscv_is_32bit(RISCVHartArrayState *harts); From 4211fc5532343adaa8f648cedfa8e44643944717 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Tue, 18 Jan 2022 14:00:35 +0530 Subject: [PATCH 690/730] roms/opensbi: Remove ELF images Now that all RISC-V machines can use OpenSBI BIN images, we remove OpenSBI ELF images and also exclude these images from BIOS build. Signed-off-by: Anup Patel Reviewed-by: Alistair Francis Reviewed-by: Bin Meng Signed-off-by: Alistair Francis --- .gitlab-ci.d/opensbi.yml | 2 -- pc-bios/meson.build | 2 -- pc-bios/opensbi-riscv32-generic-fw_dynamic.elf | Bin 838904 -> 0 bytes pc-bios/opensbi-riscv64-generic-fw_dynamic.elf | Bin 934696 -> 0 bytes roms/Makefile | 2 -- 5 files changed, 6 deletions(-) delete mode 100644 pc-bios/opensbi-riscv32-generic-fw_dynamic.elf delete mode 100644 pc-bios/opensbi-riscv64-generic-fw_dynamic.elf diff --git a/.gitlab-ci.d/opensbi.yml b/.gitlab-ci.d/opensbi.yml index 5e0a2477c5..29a22930d1 100644 --- a/.gitlab-ci.d/opensbi.yml +++ b/.gitlab-ci.d/opensbi.yml @@ -43,9 +43,7 @@ build-opensbi: artifacts: paths: # 'artifacts.zip' will contains the following files: - pc-bios/opensbi-riscv32-generic-fw_dynamic.bin - - pc-bios/opensbi-riscv32-generic-fw_dynamic.elf - pc-bios/opensbi-riscv64-generic-fw_dynamic.bin - - pc-bios/opensbi-riscv64-generic-fw_dynamic.elf - opensbi32-generic-stdout.log - opensbi32-generic-stderr.log - opensbi64-generic-stdout.log diff --git a/pc-bios/meson.build b/pc-bios/meson.build index 1812a4084f..4ac7a5509b 100644 --- a/pc-bios/meson.build +++ b/pc-bios/meson.build @@ -80,8 +80,6 @@ blobs = files( 'hppa-firmware.img', 'opensbi-riscv32-generic-fw_dynamic.bin', 'opensbi-riscv64-generic-fw_dynamic.bin', - 'opensbi-riscv32-generic-fw_dynamic.elf', - 'opensbi-riscv64-generic-fw_dynamic.elf', 'npcm7xx_bootrom.bin', ) diff --git a/pc-bios/opensbi-riscv32-generic-fw_dynamic.elf b/pc-bios/opensbi-riscv32-generic-fw_dynamic.elf deleted file mode 100644 index a19363e27c1b60668e25bd17d07f9f3131aba165..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 838904 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

    JRDa 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
    |OtqIR*2|1iFFYK(os){dIGUvzK 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

    xw8pwO4Np|jtA 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

  • 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 z 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

    +otc}wOd)_h`=9gxYWxmj@8 zn!0=?*UU}qH{!$Ggeehji39c*g_A;N_Ge)v`8cg@-|ke5IdJx%AsRVpj}vtN!bQui!MR>se?wUrV0xu|6J zVVwy=;MrJc&*sV8kFwnXaox~8J`Hn3vai@R$ou0Rad7HSz6VJ%4v%FAtU}qJDmeW2 zleXN^*4hHRFDhvZ){`IvzJqFUK%#5sBFarEeJ_LWhT1@4Su(&r%GuWh4~W`vQC=?L z&AMQoa2H(J0e3>RI3PJHW$1&c(thC=9t&4?z~2_t&~1Nv4c%yTtqw>|7RBGuK}mJH zt_McS+Mn=Sm<-elZLM#BE{=UiDiwbDMYoyv=TT@)E_t?acU_SqyE4ZqP7;J{-93ON*eVU z&2M+W*Pa6lh8Sf&pPLD20dz8Vm-=`VBRSPsv zmO9{eQH?)dYmWxV_&g=;HVp=2Z2o}EEc@#>z!{|XW2;(~(HWDgWUP-#jC79L&*01h zhSIM?;K>X~y8}*zYIDHpqWb)(RJ(=6OkkwF$NYF27eY74ffs@Y5T}|>wvB-TZjEY! zx53#H7hqE9RZU0fZtylx1Mw|wO*KjIcLKFo@Q(t;p#7Uby%hXw>UZea5vOPj@>lvp^v`2hYm96-*+rF=??t; zwA1?2(C??6Ha<{v+WbJ#X(s~(JT0nEcj*sm_kd(S4N^LDB<=eCmv&|)$e2bq0>w0X z7O28B`o8_ei0>wA)H7}EcnIvR1444}!}^pXN7(`QaO7CKcZ0*=kmt|c3qe}z1+k~k z3PD=y1ld_9h~57q$OT$balorkiyV+h);Rm|0jm#O{E60hdEn z9Pn^lHzd7>43{`yr1ZaH(Y)O#+Z-@b`ad3z@-vj}4ww$@AN6XtKfx!#zel(v?TFnW zO%q}x-M0aS|v(vZe=8^V~q2|8NUtUj!zf-#tmZE?U6===#B#=M{dE>3k8w^Ih4UJHUj z2U*jA2cydNcR_M};ExHU&5q_d@HDdNNC&X?H$iozxt$IaS&SoOhnpxkJ5XfN2~}~xZm13i?18E{V48kMNS_4ld>gn-iCGWX zpQXg21%ArWy=Q4crvu)Hvd43kL2tG-e{}B<^6PYC1=Hqt7MtJc=n1;P9?k{Q4c3U| z@Q5Wm9FUZ(^Gt}fItYOzl?buO%R&Q5 zu_m-Xzorh3$K#~9Q`+|V{n93X{>2nyaO}?olRCrT`-d!vRO^g@SDURm+&8K5cN7R&TIY+wmH^1Ae{z7-7AU4_0d? zj@ftZt_qN`w<8zrW-1%SM59$kKPbdpDm!>sS znO)KrWGzLREs{)ud*t!G;tpl~T#zj-$}DI>)>4#N(AByhNe{=a57Yj1I`y!J9EKUp6cvxhYC~H z%U0jHbvT~6=->&BvIDLWRqHH=)g6Suo>*x8BJ)a60v}|RH)P&IY5jm?2vf%Xth68p zKaC#BUqRXGfRWPQDJ>`~^^`WI-}!6Nt@_DJlQV_|+S*P8d;`_xfb%;OwUVRqB9yHT z7%6>nI2b7h{*M56sa6AAhXcL`Rd&FcP&URpRr4p>4r^Td-!|4>q1xR$c@Tc~u*Um; zm{21ue6uQ#(6+g8qbk%X^tt6L^!s34{FJ?&%H=%zUleF0mAxZ4T4skTMbX+w@;ED@=%yrJ z%X+cjR8(+35=1`i$5iD>%km!V8Cz8)mR+^17e&t-mG|T4LPfIY+S*(w$o%=EipL>q zcR(h9{nTY|f~b6pwvC%^+fOTb)(1W=#mQ7@w|g;8i}XKpBTPA~Jh__8!;RY7JOutJ zRI3AS`!G=_GYspHSbHr5cs?VZ^S`P!V!&oQcegl>r= z$fH2L79?)%>TrizdQ98qba}Do0K{F>)=pO*3eqco!2;z* z)-+~Xv$a^$PTGzu)=6T9n)~Rvdb0L3Kq|95^4=OgX)5T9D+-%FEp0E2@C!06#%)?s ztYp`Pd37&)uqdBIpHE9a^4Al2t$2Gnw%G6WI=LXL-=hWDl48eOmS^)ptEud=I==r0 zJte(@XAQ7ho5fnbgY&u8I`~}PeOs!-eZSz|`re%HY)h8eXWH7L4D8z;ufSLX#hMT} zk$GgdL1f6c6ly8M#g<YXZU$tA;G-BKQKR2Q>db?tt`N8P#q4)YGO-JEz*_%m{E19szYsRQC6Sv|2*e|8V(iu^3BD47-q+$hR-82AaY&NRCrbb#&a zN9FCEw!Z3kRhdrJ9=RptGN|1ZiyJIy)o8SVJ$jr1_=&X?qAQZ%WLVl4=;N#mAy#F{SFJObNdp}l0KK122$as{<0)e-7g_MWa9LQU+(oiQ3|TXGHl~1pZ6`8n@UFhZsb+ zJKKdGun|5lKMx4;J-0`0@Zj%t&r@+{6c)Uas>>a4t*FLrc0RFJ#?hbyl3Y!9MR7^9 zM&^gelV6@rH(|b}bQ>RX~P^XtY zCRT7=DafKrpN+cod7?S+j@c9XZzkPromG&90ZL`oSC$;IjyV%2^R%h$=3+r#JThGBHaGRFj5lTvkLEk&7iB?BJE$v!2_$pUT5cQg4K)=t1}3J99C)`L+rUI?L%9F^R;bU-*~`bkb+gW zC#SG*>VMaxHN)|^!~v&@vdZ@RITo&Muz>hYgjlrIgg_da2(i+1Y^+J=o;uebs=(yc z{G-z3A>+r{H$)B;a<#WJm!yUHl;eu|+%pyPP4HRd+mNY{Z%Xa_>%Q7Bl&)JP(oEnhxJ{A~Lw7ialr5M*@UK z<@>@vWW~tcP+Z?QxY8cdYpV)^O?52>t z@+#RxJhV9=VtWD2eSCOWtupKwT2NoKp7F>qkkhSGBcVfdi3sIN&f*$^6Bdk_v;r zgYxH>4Dcy&jqkm)i#r)NBO&;cp8-#3WQDzsi$Y_pl8d1sIb6{HWE9*+{Z{%OEuWtoz7+X6%Afxe${^jyw8vc4J zpPGO8AkSH9f!vYyk^|DL_Zq9Kd)1zuu&*;nMw$0JSll#ieUrh=rrJ-WVgO-JBG zQCj{E%RGnDJi;AKIR~V6oc!mKolWKT?Q!87aAgPVPkUM&kbzN74^^pz(sF`(j6-|* zUhu89aZZ%IQdz@>{`UDj8P8I3ume9AXOC0@L*2plM-x>32A$;uZYED#j^C*qt~s5P z2a1J${icz1E949PyeM$3r9X++aMs9ItO>Rh3HJV8e4h?$pjewEz`+?I)~Fx^j>!nI zel-Yz(=$S>c|izVkP%`n3PRwrj1X&W5CXSngjhR*5V$iI+UbXS?KK_Q>VR~eO<4b~ zj_T1?yAK7Vp@|Tyh1jhQNdAcsYkd#`$v+Wdk-DEzg}f{E^7ilg2fKd8qTlVZ7&s-=1=60RE*3*!b%C_U z?o0z|kEwt(##F#`JnX8QcHLzjwK*ViOT?Z7$4V>PN={{Fo@ z49M>5Wngw*lL4oy>%0t1Z;Iv2V82GW0Lhska zm-$`QxF+dnv)3&Y$N1JCYCJO@{&z8IG7bEra&nf+>~y9qu2b8nU7G{7C10~#TG%@} z4X3$>LKWc5WziCDPc}$#7Nvc2Oz^t4$wGm3Hwb}GGD55Y3S^5JaCnGqs~*AK+)^8%LIAGKi ze^a8+lqG3Xu9Bg>)h0-LEQ+mBSkHqH_zG%?0}|MuB=1!55oB!+h|EIxHy%-bA*J7m zz!#}qcEC%K417JvfDa=XnEtjI4tx>Gz%<8Xz#-~opBtDFFd1-KBm>i0e*=X*f~jOx z$(I>YC$}gM=0X&63KPKmA608kXzO}Pzwym)+g(uz0)NH6f@d_rZ%Z$l&Uu%mY2`>o z#Jl};l#6R;qmYiOCrP?7KA`%OCrRY z5QM-fp}Xyngf%k=fy|b~Bi5=Q1TtF^Ar_rvXA;1)zwB(79g9w~QxzcHVgBr}g2mos zLLl9d2(j3kObDbq5+N3QlL>)zMxZ!#f}?ns1KOX!>>4oG(-LacujguoM`5+T+f z2O*GMDG_4*yC4LzDoaU=uN3nl{|*0l0X0Mj$QzxwsJ_TGmS^ph#=l>$vDI>#QI zqEng`*eE(+M4)Kwq(ITI*@2=FYXU{Wq~RaJB8wf$#y0}IUtFXA+zPq%l|L^eIYz{D zWJmXVj`Zkj&yinO0z@U2+LnngcYI-w&@v7i4(8IIM8 z&Jfs6#_Gk?@|VkbS)YU7n%}Erye1l2@u338IGes`x3emi9gx+raou%ux>kaX2yHK? zmmV=inl@S==2<_%;BKK@JKY`wm2p>FI|&D-9!(c&e=eb)IpDK!_6#YQ+V&U1Lgfs3 zLA4+oYnkU+pE(@KHvU4HQ=2&bKKOC=z0fSYH!s?E;R> z2(d;5A#hSgh&4S3fpaoKtOY>`tY(B*9YF}}jD?|pZqn>l2gHf>q+QElQQu!s(YcSQ zTyenv8>-y_>0$F{S2b9@NU`F8^l&1?qLb~z7eIPA5n_EScm&eJi4bdA5CVS-s@(zU z^rSA9j>s;a*;NmS-_=KoX3fA%<1YZ5U z=m1^EWozoPjmj+!h~H$OuvP~lFpA=*XCd)Q8U-hIDh2#K{8b$A1yqLvz7~~?I~IZc zX;>lZl0sCgY~x-Cyd({bznU<(oI^ggEC@zQzZ?_%iHiN0=94teE{7!8qHXhrQq$OP zHviQBy|B09`e@LiGP^UPLL%7JeLjG{>_B!z@}D8ghw_&X`P4jzn>%usT<_#r9~kZm zN`JkBah+`195D4*yHca}F$sPDflt8Ml^U4ZwJS9$XUNZ03o^+(&-%>aNVayRhC#Y^ zL;$89Ynf9Uws56(EtiPzRt`ujS>WtX#t8OkYg5opsj)T&A&}LkCJZirh_clIabika zaIvWG7hLk8hMh?Qky~Y3aIw|$c9Ga|-JG)me&$zP; zZ9ZU;mi=Z5W$XT8W$XSz zW!oJKmD}o7wvH}Tw%zfa+FYV{Y^4K}f{h$-K>TR<=cm%DtmbgJ`A;gqba&JTD~&bxwdF)o`AQZ z?5|u1KGHVX@33A3A@C(s*#Tc=>SDbPLg1TNSaM|e2Pj(|@IF+B1Co;q?lbc9Bh zq`!i))dA;1*{xOC9ikgep5A(d}{oNa$pou!wGh0!$OJbLB!JcA}_g__e=F z1jMO@uyqy-zjl%dOhedbM7GM`URq(_Q`jR+bNs=9R5q&2E(IJIA2t-g&m$T5EFtV8 z7=om3Gmv~qu6C{QnRH|_XkFiAI`ou=B_HNmSL)+uMM=UzAqH?7REq;n7uC4QUd+Ro zB{G>RShJ~Zf0R^^uBZu1Ziwg!C~XFf5FVqg{r%DnrD67`b7X&j)((D`bm+OuA;>1B z;6tbu2Ye=~mO92;kxA-U^ohR@_e6?6)Ap;Inv#wj|2M7o?u#XeJ%eG3k4^F6L48}z`q04?ttVZhg6=4vef~pVOayC%Kqem z$|I>BF->OpctR_oV0Oz{yaZ4mcIcKFlq61a%I4pnup1xM{nD=rY+2=$>mB6u6B>Pr7OsW47kKmP=`LVf5?3f_aV zpYV1i6{l$1tLi!gcS4ojIl(7TAG-cONh(g$)+%-h?uN2AR0W?wedq@6PAbmQ)+(+L z+z(}cUS04N)Q4`^A0`#&YHMxm7CZ{|p*t&h0m}aF%=Ukn)V!~)zmvygTd$esIWV)& z|IM01s&iUfe?f6k_%@s!?7QS=4U@PI_p@S*&@5+)`;&(}=j&3wk-fq`Y4S)pu&epc zoa8xQm-4VHmRxV`i-XubE$&d^(Qu2>J)5rWwaC%C=`vwGHBL3y!+j=s&SygTW+K?P zQ059(;4G7s!l};u;RfgEN1pgj1dQ%X8iz(=mpxo*EoC) zZ>s0Z%&pxgQT*rRWarFzt|lBPk0Yb0v{`sJ+#(0O2DPN_ z&Ku8{e3>63bXV|U({;P>emDz%SokPh)d5dJS@<);xQoN*%Y1lr1J@;Mr{9}z$;Tu7 zTKH$eFW{;U_y)?tH^>d{;_&%0A0Ayt6n?nyL^umSRd_m_ofQbqhO+SUg>e^$&zJe| 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 p;!?ky~Ys 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 Z(z{G=gWgVwEdHJgl>d)Lh`%BK{|{38qZ0rC diff --git a/roms/Makefile b/roms/Makefile index b967b53bb7..5e44d97890 100644 --- a/roms/Makefile +++ b/roms/Makefile @@ -178,14 +178,12 @@ opensbi32-generic: CROSS_COMPILE=$(riscv32_cross_prefix) \ PLATFORM="generic" cp opensbi/build/platform/generic/firmware/fw_dynamic.bin ../pc-bios/opensbi-riscv32-generic-fw_dynamic.bin - cp opensbi/build/platform/generic/firmware/fw_dynamic.elf ../pc-bios/opensbi-riscv32-generic-fw_dynamic.elf opensbi64-generic: $(MAKE) -C opensbi \ CROSS_COMPILE=$(riscv64_cross_prefix) \ PLATFORM="generic" cp opensbi/build/platform/generic/firmware/fw_dynamic.bin ../pc-bios/opensbi-riscv64-generic-fw_dynamic.bin - cp opensbi/build/platform/generic/firmware/fw_dynamic.elf ../pc-bios/opensbi-riscv64-generic-fw_dynamic.elf MESON = meson NINJA = ninja From 79f26b3b951dd8eeec23d437c41f0944167ce44d Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:28 +0800 Subject: [PATCH 691/730] target/riscv: Adjust pmpcfg access with mxl Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-2-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/csr.c | 19 +++++++++++++++++++ target/riscv/pmp.c | 12 ++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index a9e7ac903b..6bc7ee780c 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1497,9 +1497,23 @@ static RISCVException write_mseccfg(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static bool check_pmp_reg_index(CPURISCVState *env, uint32_t reg_index) +{ + /* TODO: RV128 restriction check */ + if ((reg_index & 1) && (riscv_cpu_mxl(env) == MXL_RV64)) { + return false; + } + return true; +} + static RISCVException read_pmpcfg(CPURISCVState *env, int csrno, target_ulong *val) { + uint32_t reg_index = csrno - CSR_PMPCFG0; + + if (!check_pmp_reg_index(env, reg_index)) { + return RISCV_EXCP_ILLEGAL_INST; + } *val = pmpcfg_csr_read(env, csrno - CSR_PMPCFG0); return RISCV_EXCP_NONE; } @@ -1507,6 +1521,11 @@ static RISCVException read_pmpcfg(CPURISCVState *env, int csrno, static RISCVException write_pmpcfg(CPURISCVState *env, int csrno, target_ulong val) { + uint32_t reg_index = csrno - CSR_PMPCFG0; + + if (!check_pmp_reg_index(env, reg_index)) { + return RISCV_EXCP_ILLEGAL_INST; + } pmpcfg_csr_write(env, csrno - CSR_PMPCFG0, val); return RISCV_EXCP_NONE; } diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index 54abf42583..81b61bb65c 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -463,16 +463,11 @@ void pmpcfg_csr_write(CPURISCVState *env, uint32_t reg_index, { int i; uint8_t cfg_val; + int pmpcfg_nums = 2 << riscv_cpu_mxl(env); trace_pmpcfg_csr_write(env->mhartid, reg_index, val); - if ((reg_index & 1) && (sizeof(target_ulong) == 8)) { - qemu_log_mask(LOG_GUEST_ERROR, - "ignoring pmpcfg write - incorrect address\n"); - return; - } - - for (i = 0; i < sizeof(target_ulong); i++) { + for (i = 0; i < pmpcfg_nums; i++) { cfg_val = (val >> 8 * i) & 0xff; pmp_write_cfg(env, (reg_index * 4) + i, cfg_val); } @@ -490,8 +485,9 @@ target_ulong pmpcfg_csr_read(CPURISCVState *env, uint32_t reg_index) int i; target_ulong cfg_val = 0; target_ulong val = 0; + int pmpcfg_nums = 2 << riscv_cpu_mxl(env); - for (i = 0; i < sizeof(target_ulong); i++) { + for (i = 0; i < pmpcfg_nums; i++) { val = pmp_read_cfg(env, (reg_index * 4) + i); cfg_val |= (val << (i * 8)); } From b655dc7cd91588a77c3df6f618246fd88ad14249 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:29 +0800 Subject: [PATCH 692/730] target/riscv: Don't save pc when exception return As pc will be written by the xepc in exception return, just ignore pc in translation. Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-3-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/helper.h | 4 ++-- target/riscv/insn_trans/trans_privileged.c.inc | 7 ++----- target/riscv/op_helper.c | 4 ++-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/target/riscv/helper.h b/target/riscv/helper.h index 6cf6d6ce98..72cc2582f4 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -100,8 +100,8 @@ DEF_HELPER_2(csrr_i128, tl, env, int) DEF_HELPER_4(csrw_i128, void, env, int, tl, tl) DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl) #ifndef CONFIG_USER_ONLY -DEF_HELPER_2(sret, tl, env, tl) -DEF_HELPER_2(mret, tl, env, tl) +DEF_HELPER_1(sret, tl, env) +DEF_HELPER_1(mret, tl, env) DEF_HELPER_1(wfi, void, env) DEF_HELPER_1(tlb_flush, void, env) #endif diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc index 75c6ef80a6..6077bbbf11 100644 --- a/target/riscv/insn_trans/trans_privileged.c.inc +++ b/target/riscv/insn_trans/trans_privileged.c.inc @@ -74,10 +74,8 @@ static bool trans_uret(DisasContext *ctx, arg_uret *a) static bool trans_sret(DisasContext *ctx, arg_sret *a) { #ifndef CONFIG_USER_ONLY - tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); - if (has_ext(ctx, RVS)) { - gen_helper_sret(cpu_pc, cpu_env, cpu_pc); + gen_helper_sret(cpu_pc, cpu_env); tcg_gen_exit_tb(NULL, 0); /* no chaining */ ctx->base.is_jmp = DISAS_NORETURN; } else { @@ -92,8 +90,7 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a) static bool trans_mret(DisasContext *ctx, arg_mret *a) { #ifndef CONFIG_USER_ONLY - tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); - gen_helper_mret(cpu_pc, cpu_env, cpu_pc); + gen_helper_mret(cpu_pc, cpu_env); tcg_gen_exit_tb(NULL, 0); /* no chaining */ ctx->base.is_jmp = DISAS_NORETURN; return true; diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 6f040f2fb9..67693cb42b 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -115,7 +115,7 @@ target_ulong helper_csrrw_i128(CPURISCVState *env, int csr, #ifndef CONFIG_USER_ONLY -target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) +target_ulong helper_sret(CPURISCVState *env) { uint64_t mstatus; target_ulong prev_priv, prev_virt; @@ -176,7 +176,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) return retpc; } -target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb) +target_ulong helper_mret(CPURISCVState *env) { if (!(env->priv >= PRV_M)) { riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); From a14db52f7fa9f6843d1806e8d4cd56f3410bb59d Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:30 +0800 Subject: [PATCH 693/730] target/riscv: Sign extend link reg for jal and jalr Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-4-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvi.c.inc | 4 +--- target/riscv/translate.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 3a0ae28fef..b9ba57f266 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -68,9 +68,7 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a) tcg_temp_free(t0); } - if (a->rd != 0) { - tcg_gen_movi_tl(cpu_gpr[a->rd], ctx->pc_succ_insn); - } + gen_set_gpri(ctx, a->rd, ctx->pc_succ_insn); tcg_gen_lookup_and_goto_ptr(); if (misaligned) { diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 330904265e..30c0e28778 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -369,10 +369,8 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm) return; } } - if (rd != 0) { - tcg_gen_movi_tl(cpu_gpr[rd], ctx->pc_succ_insn); - } + gen_set_gpri(ctx, rd, ctx->pc_succ_insn); gen_goto_tb(ctx, 0, ctx->base.pc_next + imm); /* must use this for safety */ ctx->base.is_jmp = DISAS_NORETURN; } From 40f0c2046c490ef4b8bed4ca628620ab8a2bdf87 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:31 +0800 Subject: [PATCH 694/730] target/riscv: Sign extend pc for different XLEN When pc is written, it is sign-extended to fill the widest supported XLEN. Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-5-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- .../riscv/insn_trans/trans_privileged.c.inc | 2 +- target/riscv/insn_trans/trans_rvi.c.inc | 5 ++-- target/riscv/insn_trans/trans_rvv.c.inc | 4 +-- target/riscv/translate.c | 25 ++++++++++++++++--- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc index 6077bbbf11..53613682e8 100644 --- a/target/riscv/insn_trans/trans_privileged.c.inc +++ b/target/riscv/insn_trans/trans_privileged.c.inc @@ -102,7 +102,7 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a) static bool trans_wfi(DisasContext *ctx, arg_wfi *a) { #ifndef CONFIG_USER_ONLY - tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); + gen_set_pc_imm(ctx, ctx->pc_succ_insn); gen_helper_wfi(cpu_env); return true; #else diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index b9ba57f266..04d3ea237f 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -59,6 +59,7 @@ static bool trans_jalr(DisasContext *ctx, arg_jalr *a) tcg_gen_addi_tl(cpu_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm); tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2); + gen_set_pc(ctx, cpu_pc); if (!has_ext(ctx, RVC)) { TCGv t0 = tcg_temp_new(); @@ -827,7 +828,7 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a) * FENCE_I is a no-op in QEMU, * however we need to end the translation block */ - tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); + gen_set_pc_imm(ctx, ctx->pc_succ_insn); tcg_gen_exit_tb(NULL, 0); ctx->base.is_jmp = DISAS_NORETURN; return true; @@ -836,7 +837,7 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a) static bool do_csr_post(DisasContext *ctx) { /* We may have changed important cpu state -- exit to main loop. */ - tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); + gen_set_pc_imm(ctx, ctx->pc_succ_insn); tcg_gen_exit_tb(NULL, 0); ctx->base.is_jmp = DISAS_NORETURN; return true; diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 7a040b3089..e03959c46f 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -194,7 +194,7 @@ static bool do_vsetvl(DisasContext *s, int rd, int rs1, TCGv s2) gen_set_gpr(s, rd, dst); mark_vs_dirty(s); - tcg_gen_movi_tl(cpu_pc, s->pc_succ_insn); + gen_set_pc_imm(s, s->pc_succ_insn); tcg_gen_lookup_and_goto_ptr(); s->base.is_jmp = DISAS_NORETURN; @@ -219,7 +219,7 @@ static bool do_vsetivli(DisasContext *s, int rd, TCGv s1, TCGv s2) gen_helper_vsetvl(dst, cpu_env, s1, s2); gen_set_gpr(s, rd, dst); mark_vs_dirty(s); - tcg_gen_movi_tl(cpu_pc, s->pc_succ_insn); + gen_set_pc_imm(s, s->pc_succ_insn); tcg_gen_lookup_and_goto_ptr(); s->base.is_jmp = DISAS_NORETURN; diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 30c0e28778..2a88bd99dc 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -193,16 +193,33 @@ static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in) tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan); } +static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest) +{ + if (get_xl(ctx) == MXL_RV32) { + dest = (int32_t)dest; + } + tcg_gen_movi_tl(cpu_pc, dest); +} + +static void gen_set_pc(DisasContext *ctx, TCGv dest) +{ + if (get_xl(ctx) == MXL_RV32) { + tcg_gen_ext32s_tl(cpu_pc, dest); + } else { + tcg_gen_mov_tl(cpu_pc, dest); + } +} + static void generate_exception(DisasContext *ctx, int excp) { - tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); + gen_set_pc_imm(ctx, ctx->base.pc_next); gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp)); ctx->base.is_jmp = DISAS_NORETURN; } static void generate_exception_mtval(DisasContext *ctx, int excp) { - tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); + gen_set_pc_imm(ctx, ctx->base.pc_next); tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr)); gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp)); ctx->base.is_jmp = DISAS_NORETURN; @@ -225,10 +242,10 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) { if (translator_use_goto_tb(&ctx->base, dest)) { tcg_gen_goto_tb(n); - tcg_gen_movi_tl(cpu_pc, dest); + gen_set_pc_imm(ctx, dest); tcg_gen_exit_tb(ctx->base.tb, n); } else { - tcg_gen_movi_tl(cpu_pc, dest); + gen_set_pc_imm(ctx, dest); tcg_gen_lookup_and_goto_ptr(); } } From 440544e1cff9877cdf17aae4ecfe775410b1eff2 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:32 +0800 Subject: [PATCH 695/730] target/riscv: Create xl field in env Current xlen has been used in helper functions and many other places. The computation of current xlen is not so trivial, so that we should recompute it as little as possible. Fortunately, xlen only changes in very seldom cases, such as exception, misa write, mstatus write, cpu reset, migration load. So that we can only recompute xlen in this places and cache it into CPURISCVState. Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-6-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 1 + target/riscv/cpu.h | 31 +++++++++++++++++++++++++++++++ target/riscv/cpu_helper.c | 34 ++-------------------------------- target/riscv/csr.c | 2 ++ target/riscv/machine.c | 10 ++++++++++ 5 files changed, 46 insertions(+), 32 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index c2b570e904..736cf1d4e7 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -413,6 +413,7 @@ static void riscv_cpu_reset(DeviceState *dev) /* mmte is supposed to have pm.current hardwired to 1 */ env->mmte |= (PM_EXT_INITIAL | MMTE_M_PM_CURRENT); #endif + env->xl = riscv_cpu_mxl(env); cs->exception_index = RISCV_EXCP_NONE; env->load_res = -1; set_default_nan_mode(1, &env->fp_status); diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 03552f4aaa..7657e22a56 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -146,6 +146,7 @@ struct CPURISCVState { uint32_t misa_mxl_max; /* max mxl for this cpu */ uint32_t misa_ext; /* current extensions */ uint32_t misa_ext_mask; /* max ext for this cpu */ + uint32_t xl; /* current xlen */ /* 128-bit helpers upper part return value */ target_ulong retxh; @@ -456,6 +457,36 @@ static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env) } #endif +#if defined(TARGET_RISCV32) +#define cpu_recompute_xl(env) ((void)(env), MXL_RV32) +#else +static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env) +{ + RISCVMXL xl = env->misa_mxl; +#if !defined(CONFIG_USER_ONLY) + /* + * When emulating a 32-bit-only cpu, use RV32. + * When emulating a 64-bit cpu, and MXL has been reduced to RV32, + * MSTATUSH doesn't have UXL/SXL, therefore XLEN cannot be widened + * back to RV64 for lower privs. + */ + if (xl != MXL_RV32) { + switch (env->priv) { + case PRV_M: + break; + case PRV_U: + xl = get_field(env->mstatus, MSTATUS64_UXL); + break; + default: /* PRV_S | PRV_H */ + xl = get_field(env->mstatus, MSTATUS64_SXL); + break; + } + } +#endif + return xl; +} +#endif + /* * Encode LMUL to lmul as follows: * LMUL vlmul lmul diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index afee770951..8ebcd57af0 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -35,37 +35,6 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) #endif } -static RISCVMXL cpu_get_xl(CPURISCVState *env) -{ -#if defined(TARGET_RISCV32) - return MXL_RV32; -#elif defined(CONFIG_USER_ONLY) - return MXL_RV64; -#else - RISCVMXL xl = riscv_cpu_mxl(env); - - /* - * When emulating a 32-bit-only cpu, use RV32. - * When emulating a 64-bit cpu, and MXL has been reduced to RV32, - * MSTATUSH doesn't have UXL/SXL, therefore XLEN cannot be widened - * back to RV64 for lower privs. - */ - if (xl != MXL_RV32) { - switch (env->priv) { - case PRV_M: - break; - case PRV_U: - xl = get_field(env->mstatus, MSTATUS64_UXL); - break; - default: /* PRV_S | PRV_H */ - xl = get_field(env->mstatus, MSTATUS64_SXL); - break; - } - } - return xl; -#endif -} - void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { @@ -148,7 +117,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, } #endif - flags = FIELD_DP32(flags, TB_FLAGS, XL, cpu_get_xl(env)); + flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl); *pflags = flags; } @@ -364,6 +333,7 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) } /* tlb_flush is unnecessary as mode is contained in mmu_idx */ env->priv = newpriv; + env->xl = cpu_recompute_xl(env); /* * Clear the load reservation - otherwise a reservation placed in one diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 6bc7ee780c..9be2820d2b 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -589,6 +589,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, mstatus = set_field(mstatus, MSTATUS64_UXL, xl); } env->mstatus = mstatus; + env->xl = cpu_recompute_xl(env); return RISCV_EXCP_NONE; } @@ -704,6 +705,7 @@ static RISCVException write_misa(CPURISCVState *env, int csrno, /* flush translation cache */ tb_flush(env_cpu(env)); env->misa_ext = val; + env->xl = riscv_cpu_mxl(env); return RISCV_EXCP_NONE; } diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 098670e680..b76e4db99c 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -214,10 +214,20 @@ static const VMStateDescription vmstate_kvmtimer = { } }; +static int riscv_cpu_post_load(void *opaque, int version_id) +{ + RISCVCPU *cpu = opaque; + CPURISCVState *env = &cpu->env; + + env->xl = cpu_recompute_xl(env); + return 0; +} + const VMStateDescription vmstate_riscv_cpu = { .name = "cpu", .version_id = 3, .minimum_version_id = 3, + .post_load = riscv_cpu_post_load, .fields = (VMStateField[]) { VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32), From 8c796f1a15d0fca41c4f3e985bfbd33a5afb9ddc Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:33 +0800 Subject: [PATCH 696/730] target/riscv: Ignore the pc bits above XLEN The read from PC for translation is in cpu_get_tb_cpu_state, before translation. Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-7-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/cpu_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 8ebcd57af0..d73925a823 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -43,7 +43,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, uint32_t flags = 0; - *pc = env->pc; + *pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc; *cs_base = 0; if (riscv_has_ext(env, RVV) || cpu->cfg.ext_zve32f || cpu->cfg.ext_zve64f) { From bf9e776ec19a7e93dc520824c23cf8754fe274fd Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:34 +0800 Subject: [PATCH 697/730] target/riscv: Extend pc for runtime pc write In some cases, we must restore the guest PC to the address of the start of the TB, such as when the instruction counter hits zero. So extend pc register according to current xlen for these cases. Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-8-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 736cf1d4e7..eac5f7bf03 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -355,7 +355,12 @@ static void riscv_cpu_set_pc(CPUState *cs, vaddr value) { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; - env->pc = value; + + if (env->xl == MXL_RV32) { + env->pc = (int32_t)value; + } else { + env->pc = value; + } } static void riscv_cpu_synchronize_from_tb(CPUState *cs, @@ -363,7 +368,13 @@ static void riscv_cpu_synchronize_from_tb(CPUState *cs, { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; - env->pc = tb->pc; + RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL); + + if (xl == MXL_RV32) { + env->pc = (int32_t)tb->pc; + } else { + env->pc = tb->pc; + } } static bool riscv_cpu_has_work(CPUState *cs) @@ -384,7 +395,12 @@ static bool riscv_cpu_has_work(CPUState *cs) void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb, target_ulong *data) { - env->pc = data[0]; + RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL); + if (xl == MXL_RV32) { + env->pc = (int32_t)data[0]; + } else { + env->pc = data[0]; + } } static void riscv_cpu_reset(DeviceState *dev) From 1191be09a90a866549993d4852cef7e094655e42 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:35 +0800 Subject: [PATCH 698/730] target/riscv: Use gdb xml according to max mxlen Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-9-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 8 ++--- target/riscv/gdbstub.c | 71 +++++++++++++++++++++++++++++++----------- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index eac5f7bf03..690c879901 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -466,6 +466,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) RISCVCPU *cpu = RISCV_CPU(dev); CPURISCVState *env = &cpu->env; RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); + CPUClass *cc = CPU_CLASS(mcc); int priv_version = 0; Error *local_err = NULL; @@ -516,11 +517,13 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) switch (env->misa_mxl_max) { #ifdef TARGET_RISCV64 case MXL_RV64: + cc->gdb_core_xml_file = "riscv-64bit-cpu.xml"; break; case MXL_RV128: break; #endif case MXL_RV32: + cc->gdb_core_xml_file = "riscv-32bit-cpu.xml"; break; default: g_assert_not_reached(); @@ -802,11 +805,6 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) cc->gdb_read_register = riscv_cpu_gdb_read_register; cc->gdb_write_register = riscv_cpu_gdb_write_register; cc->gdb_num_core_regs = 33; -#if defined(TARGET_RISCV32) - cc->gdb_core_xml_file = "riscv-32bit-cpu.xml"; -#elif defined(TARGET_RISCV64) - cc->gdb_core_xml_file = "riscv-64bit-cpu.xml"; -#endif cc->gdb_stop_before_watchpoint = true; cc->disas_set_info = riscv_cpu_disas_set_info; #ifndef CONFIG_USER_ONLY diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index a5429b92d4..f531a74c2f 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -50,11 +50,23 @@ int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; + target_ulong tmp; if (n < 32) { - return gdb_get_regl(mem_buf, env->gpr[n]); + tmp = env->gpr[n]; } else if (n == 32) { - return gdb_get_regl(mem_buf, env->pc); + tmp = env->pc; + } else { + return 0; + } + + switch (env->misa_mxl_max) { + case MXL_RV32: + return gdb_get_reg32(mem_buf, tmp); + case MXL_RV64: + return gdb_get_reg64(mem_buf, tmp); + default: + g_assert_not_reached(); } return 0; } @@ -63,18 +75,32 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; + int length = 0; + target_ulong tmp; - if (n == 0) { - /* discard writes to x0 */ - return sizeof(target_ulong); - } else if (n < 32) { - env->gpr[n] = ldtul_p(mem_buf); - return sizeof(target_ulong); - } else if (n == 32) { - env->pc = ldtul_p(mem_buf); - return sizeof(target_ulong); + switch (env->misa_mxl_max) { + case MXL_RV32: + tmp = (int32_t)ldl_p(mem_buf); + length = 4; + break; + case MXL_RV64: + if (env->xl < MXL_RV64) { + tmp = (int32_t)ldq_p(mem_buf); + } else { + tmp = ldq_p(mem_buf); + } + length = 8; + break; + default: + g_assert_not_reached(); } - return 0; + if (n > 0 && n < 32) { + env->gpr[n] = tmp; + } else if (n == 32) { + env->pc = tmp; + } + + return length; } static int riscv_gdb_get_fpu(CPURISCVState *env, GByteArray *buf, int n) @@ -387,13 +413,20 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) cs->gdb_num_regs), "riscv-vector.xml", 0); } -#if defined(TARGET_RISCV32) - gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual, - 1, "riscv-32bit-virtual.xml", 0); -#elif defined(TARGET_RISCV64) - gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual, - 1, "riscv-64bit-virtual.xml", 0); -#endif + switch (env->misa_mxl_max) { + case MXL_RV32: + gdb_register_coprocessor(cs, riscv_gdb_get_virtual, + riscv_gdb_set_virtual, + 1, "riscv-32bit-virtual.xml", 0); + break; + case MXL_RV64: + gdb_register_coprocessor(cs, riscv_gdb_get_virtual, + riscv_gdb_set_virtual, + 1, "riscv-64bit-virtual.xml", 0); + break; + default: + g_assert_not_reached(); + } gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr, riscv_gen_dynamic_csr_xml(cs, cs->gdb_num_regs), From 47bdec821b8dda7658e3e802a26b9bd8319cdb49 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:36 +0800 Subject: [PATCH 699/730] target/riscv: Relax debug check for pm write Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-10-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/csr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 9be2820d2b..c00a82022e 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1556,6 +1556,9 @@ static bool check_pm_current_disabled(CPURISCVState *env, int csrno) int csr_priv = get_field(csrno, 0x300); int pm_current; + if (env->debugger) { + return false; + } /* * If priv lvls differ that means we're accessing csr from higher priv lvl, * so allow the access From 83b519b8a44d6b7d9b9d9763e7189061e116215d Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:37 +0800 Subject: [PATCH 700/730] target/riscv: Adjust csr write mask with XLEN Write mask is representing the bits we care about. Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-11-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvi.c.inc | 12 ++++++++---- target/riscv/op_helper.c | 3 ++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 04d3ea237f..631bc1f09e 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -924,7 +924,8 @@ static bool do_csrrw_i128(DisasContext *ctx, int rd, int rc, static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a) { - if (get_xl(ctx) < MXL_RV128) { + RISCVMXL xl = get_xl(ctx); + if (xl < MXL_RV128) { TCGv src = get_gpr(ctx, a->rs1, EXT_NONE); /* @@ -935,7 +936,8 @@ static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a) return do_csrw(ctx, a->csr, src); } - TCGv mask = tcg_constant_tl(-1); + TCGv mask = tcg_constant_tl(xl == MXL_RV32 ? UINT32_MAX : + (target_ulong)-1); return do_csrrw(ctx, a->rd, a->csr, src, mask); } else { TCGv srcl = get_gpr(ctx, a->rs1, EXT_NONE); @@ -1013,7 +1015,8 @@ static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a) static bool trans_csrrwi(DisasContext *ctx, arg_csrrwi *a) { - if (get_xl(ctx) < MXL_RV128) { + RISCVMXL xl = get_xl(ctx); + if (xl < MXL_RV128) { TCGv src = tcg_constant_tl(a->rs1); /* @@ -1024,7 +1027,8 @@ static bool trans_csrrwi(DisasContext *ctx, arg_csrrwi *a) return do_csrw(ctx, a->csr, src); } - TCGv mask = tcg_constant_tl(-1); + TCGv mask = tcg_constant_tl(xl == MXL_RV32 ? UINT32_MAX : + (target_ulong)-1); return do_csrrw(ctx, a->rd, a->csr, src, mask); } else { TCGv src = tcg_constant_tl(a->rs1); diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 67693cb42b..1a75ba11e6 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -50,7 +50,8 @@ target_ulong helper_csrr(CPURISCVState *env, int csr) void helper_csrw(CPURISCVState *env, int csr, target_ulong src) { - RISCVException ret = riscv_csrrw(env, csr, NULL, src, -1); + target_ulong mask = env->xl == MXL_RV32 ? UINT32_MAX : (target_ulong)-1; + RISCVException ret = riscv_csrrw(env, csr, NULL, src, mask); if (ret != RISCV_EXCP_NONE) { riscv_raise_exception(env, ret, GETPC()); From 40bfa5f6950afbec943353304fcd4367cc143548 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:38 +0800 Subject: [PATCH 701/730] target/riscv: Create current pm fields in env Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Reviewed-by: Richard Henderson Message-id: 20220120122050.41546-12-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 1 + target/riscv/cpu.h | 4 ++++ target/riscv/cpu_helper.c | 43 +++++++++++++++++++++++++++++++++++++++ target/riscv/csr.c | 19 +++++++++++++++++ target/riscv/machine.c | 1 + 5 files changed, 68 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 690c879901..a120d474df 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -430,6 +430,7 @@ static void riscv_cpu_reset(DeviceState *dev) env->mmte |= (PM_EXT_INITIAL | MMTE_M_PM_CURRENT); #endif env->xl = riscv_cpu_mxl(env); + riscv_cpu_update_mask(env); cs->exception_index = RISCV_EXCP_NONE; env->load_res = -1; set_default_nan_mode(1, &env->fp_status); diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 7657e22a56..6fe842edfd 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -266,6 +266,8 @@ struct CPURISCVState { target_ulong upmmask; target_ulong upmbase; #endif + target_ulong cur_pmmask; + target_ulong cur_pmbase; float_status fp_status; @@ -515,6 +517,8 @@ static inline uint32_t vext_get_vlmax(RISCVCPU *cpu, target_ulong vtype) void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags); +void riscv_cpu_update_mask(CPURISCVState *env); + RISCVException riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, target_ulong new_value, target_ulong write_mask); diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index d73925a823..b239d721f4 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -122,6 +122,48 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, *pflags = flags; } +void riscv_cpu_update_mask(CPURISCVState *env) +{ + target_ulong mask = -1, base = 0; + /* + * TODO: Current RVJ spec does not specify + * how the extension interacts with XLEN. + */ +#ifndef CONFIG_USER_ONLY + if (riscv_has_ext(env, RVJ)) { + switch (env->priv) { + case PRV_M: + if (env->mmte & M_PM_ENABLE) { + mask = env->mpmmask; + base = env->mpmbase; + } + break; + case PRV_S: + if (env->mmte & S_PM_ENABLE) { + mask = env->spmmask; + base = env->spmbase; + } + break; + case PRV_U: + if (env->mmte & U_PM_ENABLE) { + mask = env->upmmask; + base = env->upmbase; + } + break; + default: + g_assert_not_reached(); + } + } +#endif + if (env->xl == MXL_RV32) { + env->cur_pmmask = mask & UINT32_MAX; + env->cur_pmbase = base & UINT32_MAX; + } else { + env->cur_pmmask = mask; + env->cur_pmbase = base; + } +} + #ifndef CONFIG_USER_ONLY static int riscv_cpu_local_irq_pending(CPURISCVState *env) { @@ -334,6 +376,7 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) /* tlb_flush is unnecessary as mode is contained in mmu_idx */ env->priv = newpriv; env->xl = cpu_recompute_xl(env); + riscv_cpu_update_mask(env); /* * Clear the load reservation - otherwise a reservation placed in one diff --git a/target/riscv/csr.c b/target/riscv/csr.c index c00a82022e..292f7e1624 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1607,6 +1607,7 @@ static RISCVException write_mmte(CPURISCVState *env, int csrno, /* hardwiring pm.instruction bit to 0, since it's not supported yet */ wpri_val &= ~(MMTE_M_PM_INSN | MMTE_S_PM_INSN | MMTE_U_PM_INSN); env->mmte = wpri_val | PM_EXT_DIRTY; + riscv_cpu_update_mask(env); /* Set XS and SD bits, since PM CSRs are dirty */ mstatus = env->mstatus | MSTATUS_XS; @@ -1682,6 +1683,9 @@ static RISCVException write_mpmmask(CPURISCVState *env, int csrno, uint64_t mstatus; env->mpmmask = val; + if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) { + env->cur_pmmask = val; + } env->mmte |= PM_EXT_DIRTY; /* Set XS and SD bits, since PM CSRs are dirty */ @@ -1707,6 +1711,9 @@ static RISCVException write_spmmask(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } env->spmmask = val; + if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) { + env->cur_pmmask = val; + } env->mmte |= PM_EXT_DIRTY; /* Set XS and SD bits, since PM CSRs are dirty */ @@ -1732,6 +1739,9 @@ static RISCVException write_upmmask(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } env->upmmask = val; + if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) { + env->cur_pmmask = val; + } env->mmte |= PM_EXT_DIRTY; /* Set XS and SD bits, since PM CSRs are dirty */ @@ -1753,6 +1763,9 @@ static RISCVException write_mpmbase(CPURISCVState *env, int csrno, uint64_t mstatus; env->mpmbase = val; + if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) { + env->cur_pmbase = val; + } env->mmte |= PM_EXT_DIRTY; /* Set XS and SD bits, since PM CSRs are dirty */ @@ -1778,6 +1791,9 @@ static RISCVException write_spmbase(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } env->spmbase = val; + if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) { + env->cur_pmbase = val; + } env->mmte |= PM_EXT_DIRTY; /* Set XS and SD bits, since PM CSRs are dirty */ @@ -1803,6 +1819,9 @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } env->upmbase = val; + if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) { + env->cur_pmbase = val; + } env->mmte |= PM_EXT_DIRTY; /* Set XS and SD bits, since PM CSRs are dirty */ diff --git a/target/riscv/machine.c b/target/riscv/machine.c index b76e4db99c..a4b7859c2a 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -220,6 +220,7 @@ static int riscv_cpu_post_load(void *opaque, int version_id) CPURISCVState *env = &cpu->env; env->xl = cpu_recompute_xl(env); + riscv_cpu_update_mask(env); return 0; } From 0cff460de9e3417d248a5756b1cfbd9211657f94 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:39 +0800 Subject: [PATCH 702/730] target/riscv: Alloc tcg global for cur_pm[mask|base] Replace the array of pm_mask/pm_base with scalar variables. Remove the cached array value in DisasContext. Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-13-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/translate.c | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 2a88bd99dc..43e2ec6dce 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -38,8 +38,8 @@ static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */ static TCGv load_res; static TCGv load_val; /* globals for PM CSRs */ -static TCGv pm_mask[4]; -static TCGv pm_base[4]; +static TCGv pm_mask; +static TCGv pm_base; #include "exec/gen-icount.h" @@ -109,8 +109,6 @@ typedef struct DisasContext { TCGv temp[4]; /* PointerMasking extension */ bool pm_enabled; - TCGv pm_mask; - TCGv pm_base; } DisasContext; static inline bool has_ext(DisasContext *ctx, uint32_t ext) @@ -403,8 +401,8 @@ static TCGv gen_pm_adjust_address(DisasContext *s, TCGv src) return src; } else { temp = temp_new(s); - tcg_gen_andc_tl(temp, src, s->pm_mask); - tcg_gen_or_tl(temp, temp, s->pm_base); + tcg_gen_andc_tl(temp, src, pm_mask); + tcg_gen_or_tl(temp, temp, pm_base); return temp; } } @@ -929,10 +927,6 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->ntemp = 0; memset(ctx->temp, 0, sizeof(ctx->temp)); ctx->pm_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_ENABLED); - int priv = tb_flags & TB_FLAGS_PRIV_MMU_MASK; - ctx->pm_mask = pm_mask[priv]; - ctx->pm_base = pm_base[priv]; - ctx->zero = tcg_constant_tl(0); } @@ -1050,19 +1044,9 @@ void riscv_translate_init(void) "load_res"); load_val = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_val), "load_val"); -#ifndef CONFIG_USER_ONLY /* Assign PM CSRs to tcg globals */ - pm_mask[PRV_U] = - tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, upmmask), "upmmask"); - pm_base[PRV_U] = - tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, upmbase), "upmbase"); - pm_mask[PRV_S] = - tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, spmmask), "spmmask"); - pm_base[PRV_S] = - tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, spmbase), "spmbase"); - pm_mask[PRV_M] = - tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, mpmmask), "mpmmask"); - pm_base[PRV_M] = - tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, mpmbase), "mpmbase"); -#endif + pm_mask = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, cur_pmmask), + "pmmask"); + pm_base = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, cur_pmbase), + "pmbase"); } From 4302bef9e17831902a7e7c8082cac1c8ed151759 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:40 +0800 Subject: [PATCH 703/730] target/riscv: Calculate address according to XLEN Define one common function to compute a canonical address from a register plus offset. Merge gen_pm_adjust_address into this function. Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-14-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rva.c.inc | 9 +++------ target/riscv/insn_trans/trans_rvd.c.inc | 19 ++----------------- target/riscv/insn_trans/trans_rvf.c.inc | 19 ++----------------- target/riscv/insn_trans/trans_rvi.c.inc | 18 ++---------------- target/riscv/translate.c | 25 ++++++++++++------------- 5 files changed, 21 insertions(+), 69 deletions(-) diff --git a/target/riscv/insn_trans/trans_rva.c.inc b/target/riscv/insn_trans/trans_rva.c.inc index 86032fa9a7..45db82c9be 100644 --- a/target/riscv/insn_trans/trans_rva.c.inc +++ b/target/riscv/insn_trans/trans_rva.c.inc @@ -20,12 +20,11 @@ static bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop) { - TCGv src1 = get_gpr(ctx, a->rs1, EXT_ZERO); + TCGv src1 = get_address(ctx, a->rs1, 0); if (a->rl) { tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL); } - src1 = gen_pm_adjust_address(ctx, src1); tcg_gen_qemu_ld_tl(load_val, src1, ctx->mem_idx, mop); if (a->aq) { tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ); @@ -44,8 +43,7 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGLabel *l1 = gen_new_label(); TCGLabel *l2 = gen_new_label(); - src1 = get_gpr(ctx, a->rs1, EXT_ZERO); - src1 = gen_pm_adjust_address(ctx, src1); + src1 = get_address(ctx, a->rs1, 0); tcg_gen_brcond_tl(TCG_COND_NE, load_res, src1, l1); /* @@ -83,10 +81,9 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a, MemOp mop) { TCGv dest = dest_gpr(ctx, a->rd); - TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE); + TCGv src1 = get_address(ctx, a->rs1, 0); TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); - src1 = gen_pm_adjust_address(ctx, src1); func(dest, src1, src2, ctx->mem_idx, mop); gen_set_gpr(ctx, a->rd, dest); diff --git a/target/riscv/insn_trans/trans_rvd.c.inc b/target/riscv/insn_trans/trans_rvd.c.inc index ed444b042a..091ed3a8ad 100644 --- a/target/riscv/insn_trans/trans_rvd.c.inc +++ b/target/riscv/insn_trans/trans_rvd.c.inc @@ -25,14 +25,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - addr = get_gpr(ctx, a->rs1, EXT_NONE); - if (a->imm) { - TCGv temp = temp_new(ctx); - tcg_gen_addi_tl(temp, addr, a->imm); - addr = temp; - } - addr = gen_pm_adjust_address(ctx, addr); - + addr = get_address(ctx, a->rs1, a->imm); tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEUQ); mark_fs_dirty(ctx); @@ -46,16 +39,8 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - addr = get_gpr(ctx, a->rs1, EXT_NONE); - if (a->imm) { - TCGv temp = temp_new(ctx); - tcg_gen_addi_tl(temp, addr, a->imm); - addr = temp; - } - addr = gen_pm_adjust_address(ctx, addr); - + addr = get_address(ctx, a->rs1, a->imm); tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUQ); - return true; } diff --git a/target/riscv/insn_trans/trans_rvf.c.inc b/target/riscv/insn_trans/trans_rvf.c.inc index b5459249c4..0aac87f7db 100644 --- a/target/riscv/insn_trans/trans_rvf.c.inc +++ b/target/riscv/insn_trans/trans_rvf.c.inc @@ -31,14 +31,7 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - addr = get_gpr(ctx, a->rs1, EXT_NONE); - if (a->imm) { - TCGv temp = temp_new(ctx); - tcg_gen_addi_tl(temp, addr, a->imm); - addr = temp; - } - addr = gen_pm_adjust_address(ctx, addr); - + addr = get_address(ctx, a->rs1, a->imm); dest = cpu_fpr[a->rd]; tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_TEUL); gen_nanbox_s(dest, dest); @@ -54,16 +47,8 @@ static bool trans_fsw(DisasContext *ctx, arg_fsw *a) REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - addr = get_gpr(ctx, a->rs1, EXT_NONE); - if (a->imm) { - TCGv temp = tcg_temp_new(); - tcg_gen_addi_tl(temp, addr, a->imm); - addr = temp; - } - addr = gen_pm_adjust_address(ctx, addr); - + addr = get_address(ctx, a->rs1, a->imm); tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUL); - return true; } diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 631bc1f09e..3cd1b3f877 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -226,14 +226,7 @@ static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a) static bool gen_load_tl(DisasContext *ctx, arg_lb *a, MemOp memop) { TCGv dest = dest_gpr(ctx, a->rd); - TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE); - - if (a->imm) { - TCGv temp = temp_new(ctx); - tcg_gen_addi_tl(temp, addr, a->imm); - addr = temp; - } - addr = gen_pm_adjust_address(ctx, addr); + TCGv addr = get_address(ctx, a->rs1, a->imm); tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, memop); gen_set_gpr(ctx, a->rd, dest); @@ -330,16 +323,9 @@ static bool trans_ldu(DisasContext *ctx, arg_ldu *a) static bool gen_store_tl(DisasContext *ctx, arg_sb *a, MemOp memop) { - TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE); + TCGv addr = get_address(ctx, a->rs1, a->imm); TCGv data = get_gpr(ctx, a->rs2, EXT_NONE); - if (a->imm) { - TCGv temp = temp_new(ctx); - tcg_gen_addi_tl(temp, addr, a->imm); - addr = temp; - } - addr = gen_pm_adjust_address(ctx, addr); - tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop); return true; } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 43e2ec6dce..33564d059d 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -390,21 +390,20 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm) ctx->base.is_jmp = DISAS_NORETURN; } -/* - * Generates address adjustment for PointerMasking - */ -static TCGv gen_pm_adjust_address(DisasContext *s, TCGv src) +/* Compute a canonical address from a register plus offset. */ +static TCGv get_address(DisasContext *ctx, int rs1, int imm) { - TCGv temp; - if (!s->pm_enabled) { - /* Load unmodified address */ - return src; - } else { - temp = temp_new(s); - tcg_gen_andc_tl(temp, src, pm_mask); - tcg_gen_or_tl(temp, temp, pm_base); - return temp; + TCGv addr = temp_new(ctx); + TCGv src1 = get_gpr(ctx, rs1, EXT_NONE); + + tcg_gen_addi_tl(addr, src1, imm); + if (ctx->pm_enabled) { + tcg_gen_and_tl(addr, addr, pm_mask); + tcg_gen_or_tl(addr, addr, pm_base); + } else if (get_xl(ctx) == MXL_RV32) { + tcg_gen_ext32u_tl(addr, addr); } + return addr; } #ifndef CONFIG_USER_ONLY From 4208dc7e9e6fe1bb7a0698eac31f44388046dc00 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:41 +0800 Subject: [PATCH 704/730] target/riscv: Split pm_enabled into mask and base Use cached cur_pmmask and cur_pmbase to infer the current PM mode. This may decrease the TCG IR by one when pm_enabled is true and pm_base_enabled is false. Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-15-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 3 ++- target/riscv/cpu_helper.c | 24 ++++++------------------ target/riscv/translate.c | 12 ++++++++---- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6fe842edfd..89621e1996 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -448,7 +448,8 @@ FIELD(TB_FLAGS, MSTATUS_HS_VS, 18, 2) /* The combination of MXL/SXL/UXL that applies to the current cpu mode. */ FIELD(TB_FLAGS, XL, 20, 2) /* If PointerMasking should be applied */ -FIELD(TB_FLAGS, PM_ENABLED, 22, 1) +FIELD(TB_FLAGS, PM_MASK_ENABLED, 22, 1) +FIELD(TB_FLAGS, PM_BASE_ENABLED, 23, 1) #ifdef TARGET_RISCV32 #define riscv_cpu_mxl(env) ((void)(env), MXL_RV32) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index b239d721f4..502aee84ab 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -97,27 +97,15 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_VS, get_field(env->mstatus_hs, MSTATUS_VS)); } - if (riscv_has_ext(env, RVJ)) { - int priv = flags & TB_FLAGS_PRIV_MMU_MASK; - bool pm_enabled = false; - switch (priv) { - case PRV_U: - pm_enabled = env->mmte & U_PM_ENABLE; - break; - case PRV_S: - pm_enabled = env->mmte & S_PM_ENABLE; - break; - case PRV_M: - pm_enabled = env->mmte & M_PM_ENABLE; - break; - default: - g_assert_not_reached(); - } - flags = FIELD_DP32(flags, TB_FLAGS, PM_ENABLED, pm_enabled); - } #endif flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl); + if (env->cur_pmmask < (env->xl == MXL_RV32 ? UINT32_MAX : UINT64_MAX)) { + flags = FIELD_DP32(flags, TB_FLAGS, PM_MASK_ENABLED, 1); + } + if (env->cur_pmbase != 0) { + flags = FIELD_DP32(flags, TB_FLAGS, PM_BASE_ENABLED, 1); + } *pflags = flags; } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 33564d059d..f0bbe80875 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -108,7 +108,8 @@ typedef struct DisasContext { /* Space for 3 operands plus 1 extra for address computation. */ TCGv temp[4]; /* PointerMasking extension */ - bool pm_enabled; + bool pm_mask_enabled; + bool pm_base_enabled; } DisasContext; static inline bool has_ext(DisasContext *ctx, uint32_t ext) @@ -397,12 +398,14 @@ static TCGv get_address(DisasContext *ctx, int rs1, int imm) TCGv src1 = get_gpr(ctx, rs1, EXT_NONE); tcg_gen_addi_tl(addr, src1, imm); - if (ctx->pm_enabled) { + if (ctx->pm_mask_enabled) { tcg_gen_and_tl(addr, addr, pm_mask); - tcg_gen_or_tl(addr, addr, pm_base); } else if (get_xl(ctx) == MXL_RV32) { tcg_gen_ext32u_tl(addr, addr); } + if (ctx->pm_base_enabled) { + tcg_gen_or_tl(addr, addr, pm_base); + } return addr; } @@ -925,7 +928,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->cs = cs; ctx->ntemp = 0; memset(ctx->temp, 0, sizeof(ctx->temp)); - ctx->pm_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_ENABLED); + ctx->pm_mask_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_MASK_ENABLED); + ctx->pm_base_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_BASE_ENABLED); ctx->zero = tcg_constant_tl(0); } From d96a271a8daedb83247baf89349ead0cb8f0c449 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:42 +0800 Subject: [PATCH 705/730] target/riscv: Split out the vill from vtype We need not specially process vtype when XLEN changes. Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-16-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 1 + target/riscv/cpu_helper.c | 3 +-- target/riscv/csr.c | 13 ++++++++++++- target/riscv/machine.c | 5 +++-- target/riscv/vector_helper.c | 3 ++- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 89621e1996..6c740b92c1 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -125,6 +125,7 @@ struct CPURISCVState { target_ulong vl; target_ulong vstart; target_ulong vtype; + bool vill; target_ulong pc; target_ulong load_res; diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 502aee84ab..327a2c4f1d 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -60,8 +60,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, uint32_t maxsz = vlmax << sew; bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl) && (maxsz >= 8); - flags = FIELD_DP32(flags, TB_FLAGS, VILL, - FIELD_EX64(env->vtype, VTYPE, VILL)); + flags = FIELD_DP32(flags, TB_FLAGS, VILL, env->vill); flags = FIELD_DP32(flags, TB_FLAGS, SEW, sew); flags = FIELD_DP32(flags, TB_FLAGS, LMUL, FIELD_EX64(env->vtype, VTYPE, VLMUL)); diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 292f7e1624..b11d92b51b 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -283,7 +283,18 @@ static RISCVException write_fcsr(CPURISCVState *env, int csrno, static RISCVException read_vtype(CPURISCVState *env, int csrno, target_ulong *val) { - *val = env->vtype; + uint64_t vill; + switch (env->xl) { + case MXL_RV32: + vill = (uint32_t)env->vill << 31; + break; + case MXL_RV64: + vill = (uint64_t)env->vill << 63; + break; + default: + g_assert_not_reached(); + } + *val = (target_ulong)vill | env->vtype; return RISCV_EXCP_NONE; } diff --git a/target/riscv/machine.c b/target/riscv/machine.c index a4b7859c2a..740e11fcff 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -124,8 +124,8 @@ static bool vector_needed(void *opaque) static const VMStateDescription vmstate_vector = { .name = "cpu/vector", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .needed = vector_needed, .fields = (VMStateField[]) { VMSTATE_UINT64_ARRAY(env.vreg, RISCVCPU, 32 * RV_VLEN_MAX / 64), @@ -134,6 +134,7 @@ static const VMStateDescription vmstate_vector = { VMSTATE_UINTTL(env.vl, RISCVCPU), VMSTATE_UINTTL(env.vstart, RISCVCPU), VMSTATE_UINTTL(env.vtype, RISCVCPU), + VMSTATE_BOOL(env.vill, RISCVCPU), VMSTATE_END_OF_LIST() } }; diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index ad505ec9b2..a9484c22ea 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -52,7 +52,8 @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1, || (ediv != 0) || (reserved != 0)) { /* only set vill bit. */ - env->vtype = FIELD_DP64(0, VTYPE, VILL, 1); + env->vill = 1; + env->vtype = 0; env->vl = 0; env->vstart = 0; return 0; From 31961cfe505e11cc4ec4cfde52c851957e1bf605 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:43 +0800 Subject: [PATCH 706/730] target/riscv: Adjust vsetvl according to XLEN Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-17-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 5 +++++ target/riscv/vector_helper.c | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6c740b92c1..fe58ccaeae 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -491,6 +491,11 @@ static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env) } #endif +static inline int riscv_cpu_xlen(CPURISCVState *env) +{ + return 16 << env->xl; +} + /* * Encode LMUL to lmul as follows: * LMUL vlmul lmul diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index a9484c22ea..8b7c9ec890 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -36,8 +36,11 @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1, uint64_t lmul = FIELD_EX64(s2, VTYPE, VLMUL); uint16_t sew = 8 << FIELD_EX64(s2, VTYPE, VSEW); uint8_t ediv = FIELD_EX64(s2, VTYPE, VEDIV); - bool vill = FIELD_EX64(s2, VTYPE, VILL); - target_ulong reserved = FIELD_EX64(s2, VTYPE, RESERVED); + int xlen = riscv_cpu_xlen(env); + bool vill = (s2 >> (xlen - 1)) & 0x1; + target_ulong reserved = s2 & + MAKE_64BIT_MASK(R_VTYPE_RESERVED_SHIFT, + xlen - 1 - R_VTYPE_RESERVED_SHIFT); if (lmul & 4) { /* Fractional LMUL. */ From eef11ce325f1544ca0cafb1c734cdb8b1d0cb123 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:44 +0800 Subject: [PATCH 707/730] target/riscv: Remove VILL field in VTYPE Signed-off-by: LIU Zhiwei Acked-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-18-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 1 - 1 file changed, 1 deletion(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index fe58ccaeae..55635d68d5 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -111,7 +111,6 @@ FIELD(VTYPE, VTA, 6, 1) FIELD(VTYPE, VMA, 7, 1) FIELD(VTYPE, VEDIV, 8, 2) FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11) -FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 1, 1) struct CPURISCVState { target_ulong gpr[32]; From 01d09525da655fed6cabc49a6088c4e11f93612a Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:45 +0800 Subject: [PATCH 708/730] target/riscv: Fix check range for first fault only Only check the range that has passed the address translation. Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-19-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/vector_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 8b7c9ec890..efb3129532 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -500,12 +500,12 @@ vext_ldff(void *vd, void *v0, target_ulong base, cpu_mmu_index(env, false)); if (host) { #ifdef CONFIG_USER_ONLY - if (page_check_range(addr, nf << esz, PAGE_READ) < 0) { + if (page_check_range(addr, offset, PAGE_READ) < 0) { vl = i; goto ProbeSuccess; } #else - probe_pages(env, addr, nf << esz, ra, MMU_DATA_LOAD); + probe_pages(env, addr, offset, ra, MMU_DATA_LOAD); #endif } else { vl = i; From d6b9d9302342fc273441811b43dd42dbd3b799e0 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:46 +0800 Subject: [PATCH 709/730] target/riscv: Adjust vector address with mask The mask comes from the pointer masking extension, or the max value corresponding to XLEN bits. Signed-off-by: LIU Zhiwei Acked-by: Alistair Francis Reviewed-by: Richard Henderson Message-id: 20220120122050.41546-20-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/vector_helper.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index efb3129532..020d2e841f 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -139,6 +139,11 @@ static inline uint32_t vext_max_elems(uint32_t desc, uint32_t esz) return scale < 0 ? vlenb >> -scale : vlenb << scale; } +static inline target_ulong adjust_addr(CPURISCVState *env, target_ulong addr) +{ + return (addr & env->cur_pmmask) | env->cur_pmbase; +} + /* * This function checks watchpoint before real load operation. * @@ -156,12 +161,12 @@ static void probe_pages(CPURISCVState *env, target_ulong addr, target_ulong pagelen = -(addr | TARGET_PAGE_MASK); target_ulong curlen = MIN(pagelen, len); - probe_access(env, addr, curlen, access_type, + probe_access(env, adjust_addr(env, addr), curlen, access_type, cpu_mmu_index(env, false), ra); if (len > curlen) { addr += curlen; curlen = len - curlen; - probe_access(env, addr, curlen, access_type, + probe_access(env, adjust_addr(env, addr), curlen, access_type, cpu_mmu_index(env, false), ra); } } @@ -239,7 +244,7 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base, k = 0; while (k < nf) { target_ulong addr = base + stride * i + (k << esz); - ldst_elem(env, addr, i + k * max_elems, vd, ra); + ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra); k++; } } @@ -295,7 +300,7 @@ vext_ldst_us(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc, k = 0; while (k < nf) { target_ulong addr = base + ((i * nf + k) << esz); - ldst_elem(env, addr, i + k * max_elems, vd, ra); + ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra); k++; } } @@ -409,7 +414,7 @@ vext_ldst_index(void *vd, void *v0, target_ulong base, k = 0; while (k < nf) { abi_ptr addr = get_index_addr(base, i, vs2) + (k << esz); - ldst_elem(env, addr, i + k * max_elems, vd, ra); + ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra); k++; } } @@ -488,7 +493,7 @@ vext_ldff(void *vd, void *v0, target_ulong base, if (!vm && !vext_elem_mask(v0, i)) { continue; } - addr = base + i * (nf << esz); + addr = adjust_addr(env, base + i * (nf << esz)); if (i == 0) { probe_pages(env, addr, nf << esz, ra, MMU_DATA_LOAD); } else { @@ -515,7 +520,7 @@ vext_ldff(void *vd, void *v0, target_ulong base, break; } remain -= offset; - addr += offset; + addr = adjust_addr(env, addr + offset); } } } @@ -531,7 +536,7 @@ ProbeSuccess: } while (k < nf) { target_ulong addr = base + ((i * nf + k) << esz); - ldst_elem(env, addr, i + k * max_elems, vd, ra); + ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra); k++; } } @@ -585,7 +590,7 @@ vext_ldst_whole(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc, /* load/store rest of elements of current segment pointed by vstart */ for (pos = off; pos < max_elems; pos++, env->vstart++) { target_ulong addr = base + ((pos + k * max_elems) << esz); - ldst_elem(env, addr, pos + k * max_elems, vd, ra); + ldst_elem(env, adjust_addr(env, addr), pos + k * max_elems, vd, ra); } k++; } @@ -594,7 +599,7 @@ vext_ldst_whole(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc, for (; k < nf; k++) { for (i = 0; i < max_elems; i++, env->vstart++) { target_ulong addr = base + ((i + k * max_elems) << esz); - ldst_elem(env, addr, i + k * max_elems, vd, ra); + ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra); } } From d8c40c24fd5276536a95052ab35763c21def6f01 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:47 +0800 Subject: [PATCH 710/730] target/riscv: Adjust scalar reg in vector with XLEN When sew <= 32bits, not need to extend scalar reg. When sew > 32bits, if xlen is less that sew, we should sign extend the scalar register, except explicitly specified by the spec. Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-21-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index e03959c46f..f85a9e83b4 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -1258,7 +1258,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm, dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); src2 = tcg_temp_new_ptr(); - src1 = get_gpr(s, rs1, EXT_NONE); + src1 = get_gpr(s, rs1, EXT_SIGN); data = FIELD_DP32(data, VDATA, VM, vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); From 5a2ae2350e78cfdc7ca9885b8c3d62137115a494 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:48 +0800 Subject: [PATCH 711/730] target/riscv: Set default XLEN for hypervisor When swap regs for hypervisor, the value of vsstatus or mstatus_hs should have the right XLEN. Otherwise, it will propagate to mstatus. Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-22-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index a120d474df..1cb0436187 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -422,6 +422,16 @@ static void riscv_cpu_reset(DeviceState *dev) */ env->mstatus = set_field(env->mstatus, MSTATUS64_SXL, env->misa_mxl); env->mstatus = set_field(env->mstatus, MSTATUS64_UXL, env->misa_mxl); + if (riscv_has_ext(env, RVH)) { + env->vsstatus = set_field(env->vsstatus, + MSTATUS64_SXL, env->misa_mxl); + env->vsstatus = set_field(env->vsstatus, + MSTATUS64_UXL, env->misa_mxl); + env->mstatus_hs = set_field(env->mstatus_hs, + MSTATUS64_SXL, env->misa_mxl); + env->mstatus_hs = set_field(env->mstatus_hs, + MSTATUS64_UXL, env->misa_mxl); + } } env->mcause = 0; env->pc = env->resetvec; From f310df58bd2c570be8b802bffb37cb30da0c346e Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:49 +0800 Subject: [PATCH 712/730] target/riscv: Enable uxl field write Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-23-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/cpu_bits.h | 3 +++ target/riscv/csr.c | 28 ++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 5a6d49aa64..7c87433645 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -449,6 +449,9 @@ typedef enum { #define COUNTEREN_IR (1 << 2) #define COUNTEREN_HPM3 (1 << 3) +/* vsstatus CSR bits */ +#define VSSTATUS64_UXL 0x0000000300000000ULL + /* Privilege modes */ #define PRV_U 0 #define PRV_S 1 diff --git a/target/riscv/csr.c b/target/riscv/csr.c index b11d92b51b..523d07a95e 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -496,7 +496,7 @@ static const target_ulong vs_delegable_excps = DELEGABLE_EXCPS & (1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT))); static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS | - SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS | (target_ulong)SSTATUS64_UXL; + SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS; static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP; static const target_ulong hip_writable_mask = MIP_VSSIP; static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP; @@ -572,6 +572,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, { uint64_t mstatus = env->mstatus; uint64_t mask = 0; + RISCVMXL xl = riscv_cpu_mxl(env); /* flush tlb on mstatus fields that affect VM */ if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV | @@ -583,21 +584,22 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR | MSTATUS_TW | MSTATUS_VS; - if (riscv_cpu_mxl(env) != MXL_RV32) { + if (xl != MXL_RV32) { /* * RV32: MPV and GVA are not in mstatus. The current plan is to * add them to mstatush. For now, we just don't support it. */ mask |= MSTATUS_MPV | MSTATUS_GVA; + if ((val & MSTATUS64_UXL) != 0) { + mask |= MSTATUS64_UXL; + } } mstatus = (mstatus & ~mask) | (val & mask); - RISCVMXL xl = riscv_cpu_mxl(env); if (xl > MXL_RV32) { - /* SXL and UXL fields are for now read only */ + /* SXL field is for now read only */ mstatus = set_field(mstatus, MSTATUS64_SXL, xl); - mstatus = set_field(mstatus, MSTATUS64_UXL, xl); } env->mstatus = mstatus; env->xl = cpu_recompute_xl(env); @@ -898,6 +900,9 @@ static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno, { uint64_t mask = sstatus_v1_10_mask; uint64_t sstatus = env->mstatus & mask; + if (env->xl != MXL_RV32) { + mask |= SSTATUS64_UXL; + } *val = int128_make128(sstatus, add_status_sd(MXL_RV128, sstatus)); return RISCV_EXCP_NONE; @@ -907,7 +912,9 @@ static RISCVException read_sstatus(CPURISCVState *env, int csrno, target_ulong *val) { target_ulong mask = (sstatus_v1_10_mask); - + if (env->xl != MXL_RV32) { + mask |= SSTATUS64_UXL; + } /* TODO: Use SXL not MXL. */ *val = add_status_sd(riscv_cpu_mxl(env), env->mstatus & mask); return RISCV_EXCP_NONE; @@ -917,6 +924,12 @@ static RISCVException write_sstatus(CPURISCVState *env, int csrno, target_ulong val) { target_ulong mask = (sstatus_v1_10_mask); + + if (env->xl != MXL_RV32) { + if ((val & SSTATUS64_UXL) != 0) { + mask |= SSTATUS64_UXL; + } + } target_ulong newval = (env->mstatus & ~mask) | (val & mask); return write_mstatus(env, CSR_MSTATUS, newval); } @@ -1380,6 +1393,9 @@ static RISCVException write_vsstatus(CPURISCVState *env, int csrno, target_ulong val) { uint64_t mask = (target_ulong)-1; + if ((val & VSSTATUS64_UXL) == 0) { + mask &= ~VSSTATUS64_UXL; + } env->vsstatus = (env->vsstatus & ~mask) | (uint64_t)val; return RISCV_EXCP_NONE; } From f297245f6a780f496fb171af6fcd21ff3e6783c3 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Thu, 20 Jan 2022 20:20:50 +0800 Subject: [PATCH 713/730] target/riscv: Relax UXL field for debugging Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Message-id: 20220120122050.41546-24-zhiwei_liu@c-sky.com Signed-off-by: Alistair Francis --- target/riscv/csr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 523d07a95e..e5f9d4ef93 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -584,7 +584,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR | MSTATUS_TW | MSTATUS_VS; - if (xl != MXL_RV32) { + if (xl != MXL_RV32 || env->debugger) { /* * RV32: MPV and GVA are not in mstatus. The current plan is to * add them to mstatush. For now, we just don't support it. @@ -900,7 +900,7 @@ static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno, { uint64_t mask = sstatus_v1_10_mask; uint64_t sstatus = env->mstatus & mask; - if (env->xl != MXL_RV32) { + if (env->xl != MXL_RV32 || env->debugger) { mask |= SSTATUS64_UXL; } @@ -912,7 +912,7 @@ static RISCVException read_sstatus(CPURISCVState *env, int csrno, target_ulong *val) { target_ulong mask = (sstatus_v1_10_mask); - if (env->xl != MXL_RV32) { + if (env->xl != MXL_RV32 || env->debugger) { mask |= SSTATUS64_UXL; } /* TODO: Use SXL not MXL. */ @@ -925,7 +925,7 @@ static RISCVException write_sstatus(CPURISCVState *env, int csrno, { target_ulong mask = (sstatus_v1_10_mask); - if (env->xl != MXL_RV32) { + if (env->xl != MXL_RV32 || env->debugger) { if ((val & SSTATUS64_UXL) != 0) { mask |= SSTATUS64_UXL; } From 1e4d8b31be35e54b6429fea54f5ecaa0083f91e7 Mon Sep 17 00:00:00 2001 From: John Snow Date: Thu, 20 Jan 2022 19:52:21 -0500 Subject: [PATCH 714/730] python: pin setuptools below v60.0.0 setuptools is a package that replaces the python stdlib 'distutils'. It is generally installed by all venv-creating tools "by default". It isn't actually needed at runtime for the qemu package, so our own setup.cfg does not mention it as a dependency. However, tox will create virtual environments that include it, and will upgrade it to the very latest version. the 'venv' tool will also include whichever version your host system happens to have. Unfortunately, setuptools version 60.0.0 and above include a hack to forcibly overwrite python's built-in distutils. The pylint tool that we use to run code analysis checks on this package relies on distutils and suffers regressions when setuptools >= 60.0.0 is present at all, see https://github.com/PyCQA/pylint/issues/5704 Instruct tox and the 'check-dev' targets to avoid setuptools packages that are too new, for now. Pipenv is unaffected, because setuptools 60 does not offer Python 3.6 support, and our pipenv config is pinned against Python 3.6. Signed-off-by: John Snow Reviewed-by: Beraldo Leal Reviewed-by: Cleber Rosa Tested-by: Cleber Rosa Message-id: 20220121005221.142236-1-jsnow@redhat.com Signed-off-by: John Snow --- python/Makefile | 2 ++ python/setup.cfg | 1 + 2 files changed, 3 insertions(+) diff --git a/python/Makefile b/python/Makefile index 3334311362..949c472624 100644 --- a/python/Makefile +++ b/python/Makefile @@ -68,6 +68,8 @@ $(QEMU_VENV_DIR) $(QEMU_VENV_DIR)/bin/activate: setup.cfg echo "ACTIVATE $(QEMU_VENV_DIR)"; \ . $(QEMU_VENV_DIR)/bin/activate; \ echo "INSTALL qemu[devel] $(QEMU_VENV_DIR)"; \ + pip install --disable-pip-version-check \ + "setuptools<60.0.0" 1>/dev/null; \ make develop 1>/dev/null; \ ) @touch $(QEMU_VENV_DIR) diff --git a/python/setup.cfg b/python/setup.cfg index 417e937839..aa238d8bc9 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -163,6 +163,7 @@ deps = .[devel] .[fuse] # Workaround to trigger tox venv rebuild .[tui] # Workaround to trigger tox venv rebuild + setuptools < 60 # Workaround, please see commit msg. commands = make check From 57a6b4478ce11a6871ea724778ff21f8290ea5d9 Mon Sep 17 00:00:00 2001 From: John Snow Date: Wed, 19 Jan 2022 14:39:13 -0500 Subject: [PATCH 715/730] python: use avocado's "new" runner The old legacy runner no longer seems to work with output logging, so we can't see failure logs when a test case fails. The new runner doesn't (seem to) support Coverage.py yet, but seeing error output is a more important feature. Signed-off-by: John Snow Reviewed-by: Beraldo Leal Message-id: 20220119193916.4138217-3-jsnow@redhat.com Signed-off-by: John Snow --- python/avocado.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/avocado.cfg b/python/avocado.cfg index c7722e7ecd..a460420059 100644 --- a/python/avocado.cfg +++ b/python/avocado.cfg @@ -1,5 +1,5 @@ [run] -test_runner = runner +test_runner = nrunner [simpletests] # Don't show stdout/stderr in the test *summary* From dc6877bd2ea04a38700adcea2359d5d20c1082a6 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:44 -0500 Subject: [PATCH 716/730] python/aqmp: fix docstring typo Reported-by: Vladimir Sementsov-Ogievskiy Signed-off-by: John Snow Reviewed-by: Beraldo Leal --- python/qemu/aqmp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/qemu/aqmp/__init__.py b/python/qemu/aqmp/__init__.py index 880d5b6fa7..173556404d 100644 --- a/python/qemu/aqmp/__init__.py +++ b/python/qemu/aqmp/__init__.py @@ -6,7 +6,7 @@ asynchronously with QMP protocol servers, as implemented by QEMU, the QEMU Guest Agent, and the QEMU Storage Daemon. `QMPClient` provides the main functionality of this package. All errors -raised by this library dervive from `AQMPError`, see `aqmp.error` for +raised by this library derive from `AQMPError`, see `aqmp.error` for additional detail. See `aqmp.events` for an in-depth tutorial on managing QMP events. """ From 3bc72e3aed76e0326703db81964b13f1da075cbf Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:45 -0500 Subject: [PATCH 717/730] python/aqmp: add __del__ method to legacy interface asyncio can complain *very* loudly if you forget to back out of things gracefully before the garbage collector starts destroying objects that contain live references to asyncio Tasks. The usual fix is just to remember to call aqmp.disconnect(), but for the sake of the legacy wrapper and quick, one-off scripts where a graceful shutdown is not necessarily of paramount imporance, add a courtesy cleanup that will trigger prior to seeing screenfuls of confusing asyncio tracebacks. Note that we can't *always* save you from yourself; depending on when the GC runs, you might just seriously be out of luck. The best we can do in this case is to gently remind you to clean up after yourself. (Still much better than multiple pages of incomprehensible python warnings for the crime of forgetting to put your toys away.) Signed-off-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Beraldo Leal --- python/qemu/aqmp/legacy.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py index 9e7b9fb80b..2ccb136b02 100644 --- a/python/qemu/aqmp/legacy.py +++ b/python/qemu/aqmp/legacy.py @@ -16,6 +16,8 @@ from typing import ( import qemu.qmp from qemu.qmp import QMPMessage, QMPReturnValue, SocketAddrT +from .error import AQMPError +from .protocol import Runstate from .qmp_client import QMPClient @@ -136,3 +138,19 @@ class QEMUMonitorProtocol(qemu.qmp.QEMUMonitorProtocol): def send_fd_scm(self, fd: int) -> None: self._aqmp.send_fd_scm(fd) + + def __del__(self) -> None: + if self._aqmp.runstate == Runstate.IDLE: + return + + if not self._aloop.is_running(): + self.close() + else: + # Garbage collection ran while the event loop was running. + # Nothing we can do about it now, but if we don't raise our + # own error, the user will be treated to a lot of traceback + # they might not understand. + raise AQMPError( + "QEMUMonitorProtocol.close()" + " was not called before object was garbage collected" + ) From 3b5bf136f5798a4ea2c66875d6337ca3d6b79434 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:46 -0500 Subject: [PATCH 718/730] python/aqmp: handle asyncio.TimeoutError on execute() This exception can be injected into any await statement. If we are canceled via timeout, we want to clear the pending execution record on our way out. Signed-off-by: John Snow Reviewed-by: Beraldo Leal Reviewed-by: Vladimir Sementsov-Ogievskiy --- python/qemu/aqmp/qmp_client.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/python/qemu/aqmp/qmp_client.py b/python/qemu/aqmp/qmp_client.py index 8105e29fa8..6a985ffe30 100644 --- a/python/qemu/aqmp/qmp_client.py +++ b/python/qemu/aqmp/qmp_client.py @@ -435,7 +435,11 @@ class QMPClient(AsyncProtocol[Message], Events): msg_id = msg['id'] self._pending[msg_id] = asyncio.Queue(maxsize=1) - await self._outgoing.put(msg) + try: + await self._outgoing.put(msg) + except: + del self._pending[msg_id] + raise return msg_id @@ -452,9 +456,9 @@ class QMPClient(AsyncProtocol[Message], Events): was lost, or some other problem. """ queue = self._pending[msg_id] - result = await queue.get() try: + result = await queue.get() if isinstance(result, ExecInterruptedError): raise result return result From 0e6bfd8b96e407db7b0cb5e8c14cc315a7154f53 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:47 -0500 Subject: [PATCH 719/730] python/aqmp: copy type definitions from qmp Copy the remaining type definitions from QMP into the qemu.aqmp.legacy module. Now, users that require the legacy interface don't need to import anything else but qemu.aqmp.legacy wrapper. Signed-off-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Beraldo Leal --- python/qemu/aqmp/legacy.py | 22 ++++++++++++++++++++-- python/qemu/aqmp/protocol.py | 16 ++++++++++------ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py index 2ccb136b02..9431fe9330 100644 --- a/python/qemu/aqmp/legacy.py +++ b/python/qemu/aqmp/legacy.py @@ -6,7 +6,9 @@ This class pretends to be qemu.qmp.QEMUMonitorProtocol. import asyncio from typing import ( + Any, Awaitable, + Dict, List, Optional, TypeVar, @@ -14,13 +16,29 @@ from typing import ( ) import qemu.qmp -from qemu.qmp import QMPMessage, QMPReturnValue, SocketAddrT from .error import AQMPError -from .protocol import Runstate +from .protocol import Runstate, SocketAddrT from .qmp_client import QMPClient +#: QMPMessage is an entire QMP message of any kind. +QMPMessage = Dict[str, Any] + +#: QMPReturnValue is the 'return' value of a command. +QMPReturnValue = object + +#: QMPObject is any object in a QMP message. +QMPObject = Dict[str, object] + +# QMPMessage can be outgoing commands or incoming events/returns. +# QMPReturnValue is usually a dict/json object, but due to QAPI's +# 'returns-whitelist', it can actually be anything. +# +# {'return': {}} is a QMPMessage, +# {} is the QMPReturnValue. + + # pylint: disable=missing-docstring diff --git a/python/qemu/aqmp/protocol.py b/python/qemu/aqmp/protocol.py index c4fbe35a0e..5b4f2f0d0a 100644 --- a/python/qemu/aqmp/protocol.py +++ b/python/qemu/aqmp/protocol.py @@ -46,6 +46,10 @@ T = TypeVar('T') _U = TypeVar('_U') _TaskFN = Callable[[], Awaitable[None]] # aka ``async def func() -> None`` +InternetAddrT = Tuple[str, int] +UnixAddrT = str +SocketAddrT = Union[UnixAddrT, InternetAddrT] + class Runstate(Enum): """Protocol session runstate.""" @@ -257,7 +261,7 @@ class AsyncProtocol(Generic[T]): @upper_half @require(Runstate.IDLE) - async def accept(self, address: Union[str, Tuple[str, int]], + async def accept(self, address: SocketAddrT, ssl: Optional[SSLContext] = None) -> None: """ Accept a connection and begin processing message queues. @@ -275,7 +279,7 @@ class AsyncProtocol(Generic[T]): @upper_half @require(Runstate.IDLE) - async def connect(self, address: Union[str, Tuple[str, int]], + async def connect(self, address: SocketAddrT, ssl: Optional[SSLContext] = None) -> None: """ Connect to the server and begin processing message queues. @@ -337,7 +341,7 @@ class AsyncProtocol(Generic[T]): @upper_half async def _new_session(self, - address: Union[str, Tuple[str, int]], + address: SocketAddrT, ssl: Optional[SSLContext] = None, accept: bool = False) -> None: """ @@ -397,7 +401,7 @@ class AsyncProtocol(Generic[T]): @upper_half async def _establish_connection( self, - address: Union[str, Tuple[str, int]], + address: SocketAddrT, ssl: Optional[SSLContext] = None, accept: bool = False ) -> None: @@ -424,7 +428,7 @@ class AsyncProtocol(Generic[T]): await self._do_connect(address, ssl) @upper_half - async def _do_accept(self, address: Union[str, Tuple[str, int]], + async def _do_accept(self, address: SocketAddrT, ssl: Optional[SSLContext] = None) -> None: """ Acting as the transport server, accept a single connection. @@ -482,7 +486,7 @@ class AsyncProtocol(Generic[T]): self.logger.debug("Connection accepted.") @upper_half - async def _do_connect(self, address: Union[str, Tuple[str, int]], + async def _do_connect(self, address: SocketAddrT, ssl: Optional[SSLContext] = None) -> None: """ Acting as the transport client, initiate a connection to a server. From 728dcac5e356ce5b948943f21c0c72a1b2d96122 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:48 -0500 Subject: [PATCH 720/730] python/aqmp: add SocketAddrT to package root It's a commonly needed definition, it can be re-exported by the root. Signed-off-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Beraldo Leal --- python/qemu/aqmp/__init__.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/python/qemu/aqmp/__init__.py b/python/qemu/aqmp/__init__.py index 173556404d..05f467c141 100644 --- a/python/qemu/aqmp/__init__.py +++ b/python/qemu/aqmp/__init__.py @@ -26,7 +26,12 @@ import logging from .error import AQMPError from .events import EventListener from .message import Message -from .protocol import ConnectError, Runstate, StateError +from .protocol import ( + ConnectError, + Runstate, + SocketAddrT, + StateError, +) from .qmp_client import ExecInterruptedError, ExecuteError, QMPClient @@ -48,4 +53,7 @@ __all__ = ( 'ConnectError', 'ExecuteError', 'ExecInterruptedError', + + # Type aliases + 'SocketAddrT', ) From 6e7751dc388df6daf425db0e245d4d3a10859803 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:49 -0500 Subject: [PATCH 721/730] python/aqmp: rename AQMPError to QMPError This is in preparation for renaming qemu.aqmp to qemu.qmp. I should have done this from this from the very beginning, but it's a convenient time to make sure this churn is taken care of. Signed-off-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy --- python/qemu/aqmp/__init__.py | 6 +++--- python/qemu/aqmp/error.py | 12 ++++++------ python/qemu/aqmp/events.py | 4 ++-- python/qemu/aqmp/legacy.py | 4 ++-- python/qemu/aqmp/protocol.py | 8 ++++---- python/qemu/aqmp/qmp_client.py | 8 ++++---- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/python/qemu/aqmp/__init__.py b/python/qemu/aqmp/__init__.py index 05f467c141..4c22c38079 100644 --- a/python/qemu/aqmp/__init__.py +++ b/python/qemu/aqmp/__init__.py @@ -6,7 +6,7 @@ asynchronously with QMP protocol servers, as implemented by QEMU, the QEMU Guest Agent, and the QEMU Storage Daemon. `QMPClient` provides the main functionality of this package. All errors -raised by this library derive from `AQMPError`, see `aqmp.error` for +raised by this library derive from `QMPError`, see `aqmp.error` for additional detail. See `aqmp.events` for an in-depth tutorial on managing QMP events. """ @@ -23,7 +23,7 @@ managing QMP events. import logging -from .error import AQMPError +from .error import QMPError from .events import EventListener from .message import Message from .protocol import ( @@ -48,7 +48,7 @@ __all__ = ( 'Runstate', # Exceptions, most generic to most explicit - 'AQMPError', + 'QMPError', 'StateError', 'ConnectError', 'ExecuteError', diff --git a/python/qemu/aqmp/error.py b/python/qemu/aqmp/error.py index 781f49b008..24ba4d5054 100644 --- a/python/qemu/aqmp/error.py +++ b/python/qemu/aqmp/error.py @@ -1,21 +1,21 @@ """ -AQMP Error Classes +QMP Error Classes This package seeks to provide semantic error classes that are intended to be used directly by clients when they would like to handle particular semantic failures (e.g. "failed to connect") without needing to know the enumeration of possible reasons for that failure. -AQMPError serves as the ancestor for all exceptions raised by this +QMPError serves as the ancestor for all exceptions raised by this package, and is suitable for use in handling semantic errors from this library. In most cases, individual public methods will attempt to catch and re-encapsulate various exceptions to provide a semantic error-handling interface. -.. admonition:: AQMP Exception Hierarchy Reference +.. admonition:: QMP Exception Hierarchy Reference | `Exception` - | +-- `AQMPError` + | +-- `QMPError` | +-- `ConnectError` | +-- `StateError` | +-- `ExecInterruptedError` @@ -31,11 +31,11 @@ error-handling interface. """ -class AQMPError(Exception): +class QMPError(Exception): """Abstract error class for all errors originating from this package.""" -class ProtocolError(AQMPError): +class ProtocolError(QMPError): """ Abstract error class for protocol failures. diff --git a/python/qemu/aqmp/events.py b/python/qemu/aqmp/events.py index 5f7150c78d..f3d4e2b5e8 100644 --- a/python/qemu/aqmp/events.py +++ b/python/qemu/aqmp/events.py @@ -443,7 +443,7 @@ from typing import ( Union, ) -from .error import AQMPError +from .error import QMPError from .message import Message @@ -451,7 +451,7 @@ EventNames = Union[str, Iterable[str], None] EventFilter = Callable[[Message], bool] -class ListenerError(AQMPError): +class ListenerError(QMPError): """ Generic error class for `EventListener`-related problems. """ diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py index 9431fe9330..27df22818a 100644 --- a/python/qemu/aqmp/legacy.py +++ b/python/qemu/aqmp/legacy.py @@ -17,7 +17,7 @@ from typing import ( import qemu.qmp -from .error import AQMPError +from .error import QMPError from .protocol import Runstate, SocketAddrT from .qmp_client import QMPClient @@ -168,7 +168,7 @@ class QEMUMonitorProtocol(qemu.qmp.QEMUMonitorProtocol): # Nothing we can do about it now, but if we don't raise our # own error, the user will be treated to a lot of traceback # they might not understand. - raise AQMPError( + raise QMPError( "QEMUMonitorProtocol.close()" " was not called before object was garbage collected" ) diff --git a/python/qemu/aqmp/protocol.py b/python/qemu/aqmp/protocol.py index 5b4f2f0d0a..50e973c2f2 100644 --- a/python/qemu/aqmp/protocol.py +++ b/python/qemu/aqmp/protocol.py @@ -29,7 +29,7 @@ from typing import ( cast, ) -from .error import AQMPError +from .error import QMPError from .util import ( bottom_half, create_task, @@ -65,7 +65,7 @@ class Runstate(Enum): DISCONNECTING = 3 -class ConnectError(AQMPError): +class ConnectError(QMPError): """ Raised when the initial connection process has failed. @@ -90,7 +90,7 @@ class ConnectError(AQMPError): return f"{self.error_message}: {cause}" -class StateError(AQMPError): +class StateError(QMPError): """ An API command (connect, execute, etc) was issued at an inappropriate time. @@ -363,7 +363,7 @@ class AsyncProtocol(Generic[T]): This exception will wrap a more concrete one. In most cases, the wrapped exception will be `OSError` or `EOFError`. If a protocol-level failure occurs while establishing a new - session, the wrapped error may also be an `AQMPError`. + session, the wrapped error may also be an `QMPError`. """ assert self.runstate == Runstate.IDLE diff --git a/python/qemu/aqmp/qmp_client.py b/python/qemu/aqmp/qmp_client.py index 6a985ffe30..f1a845cc82 100644 --- a/python/qemu/aqmp/qmp_client.py +++ b/python/qemu/aqmp/qmp_client.py @@ -20,7 +20,7 @@ from typing import ( cast, ) -from .error import AQMPError, ProtocolError +from .error import ProtocolError, QMPError from .events import Events from .message import Message from .models import ErrorResponse, Greeting @@ -66,7 +66,7 @@ class NegotiationError(_WrappedProtocolError): """ -class ExecuteError(AQMPError): +class ExecuteError(QMPError): """ Exception raised by `QMPClient.execute()` on RPC failure. @@ -87,7 +87,7 @@ class ExecuteError(AQMPError): self.error_class: str = error_response.error.class_ -class ExecInterruptedError(AQMPError): +class ExecInterruptedError(QMPError): """ Exception raised by `execute()` (et al) when an RPC is interrupted. @@ -641,7 +641,7 @@ class QMPClient(AsyncProtocol[Message], Events): sock = self._writer.transport.get_extra_info('socket') if sock.family != socket.AF_UNIX: - raise AQMPError("Sending file descriptors requires a UNIX socket.") + raise QMPError("Sending file descriptors requires a UNIX socket.") if not hasattr(sock, 'sendmsg'): # We need to void the warranty sticker. From 7017f3853a59cf9d16c6be24dc657417d1c8f0cb Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:50 -0500 Subject: [PATCH 722/730] python/qemu-ga-client: don't use deprecated CLI syntax in usage comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup related to commit ccd3b3b8112b670f, "qemu-option: warn for short-form boolean options". Signed-off-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Daniel P. Berrangé --- python/qemu/qmp/qemu_ga_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/qemu/qmp/qemu_ga_client.py b/python/qemu/qmp/qemu_ga_client.py index 67ac0b4211..b3e1d98c9e 100644 --- a/python/qemu/qmp/qemu_ga_client.py +++ b/python/qemu/qmp/qemu_ga_client.py @@ -5,7 +5,7 @@ Usage: Start QEMU with: -# qemu [...] -chardev socket,path=/tmp/qga.sock,server,wait=off,id=qga0 \ +# qemu [...] -chardev socket,path=/tmp/qga.sock,server=on,wait=off,id=qga0 \ -device virtio-serial \ -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 From 26db07516fea6e264ba3c30651145f3873f7e4a7 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:51 -0500 Subject: [PATCH 723/730] python/qmp: switch qemu-ga-client to AQMP Async QMP always raises a "ConnectError" on any connection error which houses the cause in a second exception. We can check if this root cause was python's ConnectionError to determine a fairly similar condition to the original error check here. Signed-off-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Beraldo Leal --- python/qemu/qmp/qemu_ga_client.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/python/qemu/qmp/qemu_ga_client.py b/python/qemu/qmp/qemu_ga_client.py index b3e1d98c9e..15ed430c61 100644 --- a/python/qemu/qmp/qemu_ga_client.py +++ b/python/qemu/qmp/qemu_ga_client.py @@ -37,8 +37,8 @@ See also: https://wiki.qemu.org/Features/QAPI/GuestAgent # the COPYING file in the top-level directory. import argparse +import asyncio import base64 -import errno import os import random import sys @@ -50,8 +50,8 @@ from typing import ( Sequence, ) -from qemu import qmp -from qemu.qmp import SocketAddrT +from qemu.aqmp import ConnectError, SocketAddrT +from qemu.aqmp.legacy import QEMUMonitorProtocol # This script has not seen many patches or careful attention in quite @@ -61,7 +61,7 @@ from qemu.qmp import SocketAddrT # pylint: disable=missing-docstring -class QemuGuestAgent(qmp.QEMUMonitorProtocol): +class QemuGuestAgent(QEMUMonitorProtocol): def __getattr__(self, name: str) -> Callable[..., Any]: def wrapper(**kwds: object) -> object: return self.command('guest-' + name.replace('_', '-'), **kwds) @@ -149,7 +149,7 @@ class QemuGuestAgentClient: self.qga.settimeout(timeout) try: self.qga.ping() - except TimeoutError: + except asyncio.TimeoutError: return False return True @@ -172,7 +172,7 @@ class QemuGuestAgentClient: try: getattr(self.qga, 'suspend' + '_' + mode)() # On error exception will raise - except TimeoutError: + except asyncio.TimeoutError: # On success command will timed out return @@ -182,7 +182,7 @@ class QemuGuestAgentClient: try: self.qga.shutdown(mode=mode) - except TimeoutError: + except asyncio.TimeoutError: pass @@ -277,7 +277,7 @@ commands = [m.replace('_cmd_', '') for m in dir() if '_cmd_' in m] def send_command(address: str, cmd: str, args: Sequence[str]) -> None: if not os.path.exists(address): - print('%s not found' % address) + print(f"'{address}' not found. (Is QEMU running?)") sys.exit(1) if cmd not in commands: @@ -287,10 +287,10 @@ def send_command(address: str, cmd: str, args: Sequence[str]) -> None: try: client = QemuGuestAgentClient(address) - except OSError as err: + except ConnectError as err: print(err) - if err.errno == errno.ECONNREFUSED: - print('Hint: qemu is not running?') + if isinstance(err.exc, ConnectionError): + print('(Is QEMU running?)') sys.exit(1) if cmd == 'fsfreeze' and args[0] == 'freeze': From 8d6cdc5118e8c7d71ccb716ded2a618e6f78a295 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:52 -0500 Subject: [PATCH 724/730] python/qmp: switch qom tools to AQMP Signed-off-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Beraldo Leal --- python/qemu/qmp/qom.py | 5 +++-- python/qemu/qmp/qom_common.py | 3 ++- python/qemu/qmp/qom_fuse.py | 11 ++++++----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/python/qemu/qmp/qom.py b/python/qemu/qmp/qom.py index 8ff28a8343..bb5d1a78f5 100644 --- a/python/qemu/qmp/qom.py +++ b/python/qemu/qmp/qom.py @@ -32,7 +32,8 @@ QOM commands: import argparse -from . import QMPResponseError +from qemu.aqmp import ExecuteError + from .qom_common import QOMCommand @@ -233,7 +234,7 @@ class QOMTree(QOMCommand): rsp = self.qmp.command('qom-get', path=path, property=item.name) print(f" {item.name}: {rsp} ({item.type})") - except QMPResponseError as err: + except ExecuteError as err: print(f" {item.name}: ({item.type})") print('') for item in items: diff --git a/python/qemu/qmp/qom_common.py b/python/qemu/qmp/qom_common.py index 2e4c741f77..e034a6f247 100644 --- a/python/qemu/qmp/qom_common.py +++ b/python/qemu/qmp/qom_common.py @@ -27,7 +27,8 @@ from typing import ( TypeVar, ) -from . import QEMUMonitorProtocol, QMPError +from qemu.aqmp import QMPError +from qemu.aqmp.legacy import QEMUMonitorProtocol class ObjectPropertyInfo: diff --git a/python/qemu/qmp/qom_fuse.py b/python/qemu/qmp/qom_fuse.py index 43f4671fdb..653a76b93b 100644 --- a/python/qemu/qmp/qom_fuse.py +++ b/python/qemu/qmp/qom_fuse.py @@ -48,7 +48,8 @@ from typing import ( import fuse from fuse import FUSE, FuseOSError, Operations -from . import QMPResponseError +from qemu.aqmp import ExecuteError + from .qom_common import QOMCommand @@ -99,7 +100,7 @@ class QOMFuse(QOMCommand, Operations): try: self.qom_list(path) return True - except QMPResponseError: + except ExecuteError: return False def is_property(self, path: str) -> bool: @@ -112,7 +113,7 @@ class QOMFuse(QOMCommand, Operations): if item.name == prop: return True return False - except QMPResponseError: + except ExecuteError: return False def is_link(self, path: str) -> bool: @@ -125,7 +126,7 @@ class QOMFuse(QOMCommand, Operations): if item.name == prop and item.link: return True return False - except QMPResponseError: + except ExecuteError: return False def read(self, path: str, size: int, offset: int, fh: IO[bytes]) -> bytes: @@ -138,7 +139,7 @@ class QOMFuse(QOMCommand, Operations): try: data = str(self.qmp.command('qom-get', path=path, property=prop)) data += '\n' # make values shell friendly - except QMPResponseError as err: + except ExecuteError as err: raise FuseOSError(EPERM) from err if offset > len(data): From f3efd12930f34b9724e15d8fd2ff56a97b67219d Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:53 -0500 Subject: [PATCH 725/730] python/qmp: switch qmp-shell to AQMP We have a replacement for async QMP, but it doesn't have feature parity yet. For now, then, port the old tool onto the new backend. Signed-off-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy --- python/qemu/aqmp/legacy.py | 3 +++ python/qemu/qmp/qmp_shell.py | 31 +++++++++++++++++-------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py index 27df22818a..0890f95b16 100644 --- a/python/qemu/aqmp/legacy.py +++ b/python/qemu/aqmp/legacy.py @@ -22,6 +22,9 @@ from .protocol import Runstate, SocketAddrT from .qmp_client import QMPClient +# (Temporarily) Re-export QMPBadPortError +QMPBadPortError = qemu.qmp.QMPBadPortError + #: QMPMessage is an entire QMP message of any kind. QMPMessage = Dict[str, Any] diff --git a/python/qemu/qmp/qmp_shell.py b/python/qemu/qmp/qmp_shell.py index e7d7eb18f1..d11bf54b00 100644 --- a/python/qemu/qmp/qmp_shell.py +++ b/python/qemu/qmp/qmp_shell.py @@ -95,8 +95,13 @@ from typing import ( Sequence, ) -from qemu import qmp -from qemu.qmp import QMPMessage +from qemu.aqmp import ConnectError, QMPError, SocketAddrT +from qemu.aqmp.legacy import ( + QEMUMonitorProtocol, + QMPBadPortError, + QMPMessage, + QMPObject, +) LOG = logging.getLogger(__name__) @@ -125,7 +130,7 @@ class QMPCompleter: return None -class QMPShellError(qmp.QMPError): +class QMPShellError(QMPError): """ QMP Shell Base error class. """ @@ -153,7 +158,7 @@ class FuzzyJSON(ast.NodeTransformer): return node -class QMPShell(qmp.QEMUMonitorProtocol): +class QMPShell(QEMUMonitorProtocol): """ QMPShell provides a basic readline-based QMP shell. @@ -161,7 +166,7 @@ class QMPShell(qmp.QEMUMonitorProtocol): :param pretty: Pretty-print QMP messages. :param verbose: Echo outgoing QMP messages to console. """ - def __init__(self, address: qmp.SocketAddrT, + def __init__(self, address: SocketAddrT, pretty: bool = False, verbose: bool = False): super().__init__(address) self._greeting: Optional[QMPMessage] = None @@ -237,7 +242,7 @@ class QMPShell(qmp.QEMUMonitorProtocol): def _cli_expr(self, tokens: Sequence[str], - parent: qmp.QMPObject) -> None: + parent: QMPObject) -> None: for arg in tokens: (key, sep, val) = arg.partition('=') if sep != '=': @@ -403,7 +408,7 @@ class HMPShell(QMPShell): :param pretty: Pretty-print QMP messages. :param verbose: Echo outgoing QMP messages to console. """ - def __init__(self, address: qmp.SocketAddrT, + def __init__(self, address: SocketAddrT, pretty: bool = False, verbose: bool = False): super().__init__(address, pretty, verbose) self._cpu_index = 0 @@ -512,19 +517,17 @@ def main() -> None: try: address = shell_class.parse_address(args.qmp_server) - except qmp.QMPBadPortError: + except QMPBadPortError: parser.error(f"Bad port number: {args.qmp_server}") return # pycharm doesn't know error() is noreturn with shell_class(address, args.pretty, args.verbose) as qemu: try: qemu.connect(negotiate=not args.skip_negotiation) - except qmp.QMPConnectError: - die("Didn't get QMP greeting message") - except qmp.QMPCapabilitiesError: - die("Couldn't negotiate capabilities") - except OSError as err: - die(f"Couldn't connect to {args.qmp_server}: {err!s}") + except ConnectError as err: + if isinstance(err.exc, OSError): + die(f"Couldn't connect to {args.qmp_server}: {err!s}") + die(str(err)) for _ in qemu.repl(): pass From 0347c4c4cfed47e54d9dc275ceb28d35b250749f Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:54 -0500 Subject: [PATCH 726/730] python: move qmp utilities to python/qemu/utils In order to upload a QMP package to PyPI, I want to remove any scripts that I am not 100% confident I want to support upstream, beyond our castle walls. Move most of our QMP utilities into the utils package so we can split them out from the PyPI upload. Signed-off-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Beraldo Leal --- python/qemu/{qmp => utils}/qemu_ga_client.py | 0 python/qemu/{qmp => utils}/qom.py | 0 python/qemu/{qmp => utils}/qom_common.py | 0 python/qemu/{qmp => utils}/qom_fuse.py | 0 python/setup.cfg | 16 ++++++++-------- scripts/qmp/qemu-ga-client | 2 +- scripts/qmp/qom-fuse | 2 +- scripts/qmp/qom-get | 2 +- scripts/qmp/qom-list | 2 +- scripts/qmp/qom-set | 2 +- scripts/qmp/qom-tree | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) rename python/qemu/{qmp => utils}/qemu_ga_client.py (100%) rename python/qemu/{qmp => utils}/qom.py (100%) rename python/qemu/{qmp => utils}/qom_common.py (100%) rename python/qemu/{qmp => utils}/qom_fuse.py (100%) diff --git a/python/qemu/qmp/qemu_ga_client.py b/python/qemu/utils/qemu_ga_client.py similarity index 100% rename from python/qemu/qmp/qemu_ga_client.py rename to python/qemu/utils/qemu_ga_client.py diff --git a/python/qemu/qmp/qom.py b/python/qemu/utils/qom.py similarity index 100% rename from python/qemu/qmp/qom.py rename to python/qemu/utils/qom.py diff --git a/python/qemu/qmp/qom_common.py b/python/qemu/utils/qom_common.py similarity index 100% rename from python/qemu/qmp/qom_common.py rename to python/qemu/utils/qom_common.py diff --git a/python/qemu/qmp/qom_fuse.py b/python/qemu/utils/qom_fuse.py similarity index 100% rename from python/qemu/qmp/qom_fuse.py rename to python/qemu/utils/qom_fuse.py diff --git a/python/setup.cfg b/python/setup.cfg index aa238d8bc9..04a41ef1a0 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -60,13 +60,13 @@ tui = [options.entry_points] console_scripts = - qom = qemu.qmp.qom:main - qom-set = qemu.qmp.qom:QOMSet.entry_point - qom-get = qemu.qmp.qom:QOMGet.entry_point - qom-list = qemu.qmp.qom:QOMList.entry_point - qom-tree = qemu.qmp.qom:QOMTree.entry_point - qom-fuse = qemu.qmp.qom_fuse:QOMFuse.entry_point [fuse] - qemu-ga-client = qemu.qmp.qemu_ga_client:main + qom = qemu.utils.qom:main + qom-set = qemu.utils.qom:QOMSet.entry_point + qom-get = qemu.utils.qom:QOMGet.entry_point + qom-list = qemu.utils.qom:QOMList.entry_point + qom-tree = qemu.utils.qom:QOMTree.entry_point + qom-fuse = qemu.utils.qom_fuse:QOMFuse.entry_point [fuse] + qemu-ga-client = qemu.utils.qemu_ga_client:main qmp-shell = qemu.qmp.qmp_shell:main aqmp-tui = qemu.aqmp.aqmp_tui:main [tui] @@ -80,7 +80,7 @@ python_version = 3.6 warn_unused_configs = True namespace_packages = True -[mypy-qemu.qmp.qom_fuse] +[mypy-qemu.utils.qom_fuse] # fusepy has no type stubs: allow_subclassing_any = True diff --git a/scripts/qmp/qemu-ga-client b/scripts/qmp/qemu-ga-client index 102fd2cad9..56edd0234a 100755 --- a/scripts/qmp/qemu-ga-client +++ b/scripts/qmp/qemu-ga-client @@ -4,7 +4,7 @@ import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) -from qemu.qmp import qemu_ga_client +from qemu.utils import qemu_ga_client if __name__ == '__main__': diff --git a/scripts/qmp/qom-fuse b/scripts/qmp/qom-fuse index a58c8ef979..d453807b27 100755 --- a/scripts/qmp/qom-fuse +++ b/scripts/qmp/qom-fuse @@ -4,7 +4,7 @@ import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) -from qemu.qmp.qom_fuse import QOMFuse +from qemu.utils.qom_fuse import QOMFuse if __name__ == '__main__': diff --git a/scripts/qmp/qom-get b/scripts/qmp/qom-get index e4f3e0c013..04ebe052e8 100755 --- a/scripts/qmp/qom-get +++ b/scripts/qmp/qom-get @@ -4,7 +4,7 @@ import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) -from qemu.qmp.qom import QOMGet +from qemu.utils.qom import QOMGet if __name__ == '__main__': diff --git a/scripts/qmp/qom-list b/scripts/qmp/qom-list index 7a071a54e1..853b85a8d3 100755 --- a/scripts/qmp/qom-list +++ b/scripts/qmp/qom-list @@ -4,7 +4,7 @@ import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) -from qemu.qmp.qom import QOMList +from qemu.utils.qom import QOMList if __name__ == '__main__': diff --git a/scripts/qmp/qom-set b/scripts/qmp/qom-set index 9ca9e2ba10..06820feec4 100755 --- a/scripts/qmp/qom-set +++ b/scripts/qmp/qom-set @@ -4,7 +4,7 @@ import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) -from qemu.qmp.qom import QOMSet +from qemu.utils.qom import QOMSet if __name__ == '__main__': diff --git a/scripts/qmp/qom-tree b/scripts/qmp/qom-tree index 7d0ccca3a4..760e172277 100755 --- a/scripts/qmp/qom-tree +++ b/scripts/qmp/qom-tree @@ -4,7 +4,7 @@ import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) -from qemu.qmp.qom import QOMTree +from qemu.utils.qom import QOMTree if __name__ == '__main__': From fd9c3a6219b0470c356c8486188052d353846806 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:55 -0500 Subject: [PATCH 727/730] python: move qmp-shell under the AQMP package Signed-off-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Beraldo Leal --- python/README.rst | 2 +- python/qemu/{qmp => aqmp}/qmp_shell.py | 0 python/setup.cfg | 2 +- scripts/qmp/qmp-shell | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename python/qemu/{qmp => aqmp}/qmp_shell.py (100%) diff --git a/python/README.rst b/python/README.rst index 9c1fceaee7..fcf74f69ea 100644 --- a/python/README.rst +++ b/python/README.rst @@ -59,7 +59,7 @@ Package installation also normally provides executable console scripts, so that tools like ``qmp-shell`` are always available via $PATH. To invoke them without installation, you can invoke e.g.: -``> PYTHONPATH=~/src/qemu/python python3 -m qemu.qmp.qmp_shell`` +``> PYTHONPATH=~/src/qemu/python python3 -m qemu.aqmp.qmp_shell`` The mappings between console script name and python module path can be found in ``setup.cfg``. diff --git a/python/qemu/qmp/qmp_shell.py b/python/qemu/aqmp/qmp_shell.py similarity index 100% rename from python/qemu/qmp/qmp_shell.py rename to python/qemu/aqmp/qmp_shell.py diff --git a/python/setup.cfg b/python/setup.cfg index 04a41ef1a0..3fb18f845d 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -67,7 +67,7 @@ console_scripts = qom-tree = qemu.utils.qom:QOMTree.entry_point qom-fuse = qemu.utils.qom_fuse:QOMFuse.entry_point [fuse] qemu-ga-client = qemu.utils.qemu_ga_client:main - qmp-shell = qemu.qmp.qmp_shell:main + qmp-shell = qemu.aqmp.qmp_shell:main aqmp-tui = qemu.aqmp.aqmp_tui:main [tui] [flake8] diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell index 4a20f97db7..31b19d73e2 100755 --- a/scripts/qmp/qmp-shell +++ b/scripts/qmp/qmp-shell @@ -4,7 +4,7 @@ import os import sys sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python')) -from qemu.qmp import qmp_shell +from qemu.aqmp import qmp_shell if __name__ == '__main__': From 99221256151845f5eb4cedac750b08e7ab14d92d Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:57 -0500 Subject: [PATCH 728/730] scripts/cpu-x86-uarch-abi: fix CLI parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Snow Reviewed-by: Daniel P. Berrangé Reviewed-by: Vladimir Sementsov-Ogievskiy --- scripts/cpu-x86-uarch-abi.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/cpu-x86-uarch-abi.py b/scripts/cpu-x86-uarch-abi.py index 08acc52a81..8963d90f0b 100644 --- a/scripts/cpu-x86-uarch-abi.py +++ b/scripts/cpu-x86-uarch-abi.py @@ -9,7 +9,7 @@ from qemu import qmp import sys -if len(sys.argv) != 1: +if len(sys.argv) != 2: print("syntax: %s QMP-SOCK\n\n" % __file__ + "Where QMP-SOCK points to a QEMU process such as\n\n" + " # qemu-system-x86_64 -qmp unix:/tmp/qmp,server,nowait " + @@ -66,7 +66,6 @@ levels = [ sock = sys.argv[1] -cmd = sys.argv[2] shell = qmp.QEMUMonitorProtocol(sock) shell.connect() From 0665410dcf3d3fa8758545668998dd16d3abbaa9 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:58 -0500 Subject: [PATCH 729/730] scripts/cpu-x86-uarch-abi: switch to AQMP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Snow Reviewed-by: Daniel P. Berrangé Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Beraldo Leal --- scripts/cpu-x86-uarch-abi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/cpu-x86-uarch-abi.py b/scripts/cpu-x86-uarch-abi.py index 8963d90f0b..c262d2f027 100644 --- a/scripts/cpu-x86-uarch-abi.py +++ b/scripts/cpu-x86-uarch-abi.py @@ -6,7 +6,7 @@ # compatibility levels for each CPU model. # -from qemu import qmp +from qemu.aqmp.legacy import QEMUMonitorProtocol import sys if len(sys.argv) != 2: @@ -66,7 +66,7 @@ levels = [ sock = sys.argv[1] -shell = qmp.QEMUMonitorProtocol(sock) +shell = QEMUMonitorProtocol(sock) shell.connect() models = shell.cmd("query-cpu-definitions") From 05908602429cf9d6fce9b60704b8395f6d295441 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 18:28:59 -0500 Subject: [PATCH 730/730] scripts/render-block-graph: switch to AQMP Creating an instance of qemu.aqmp.ExecuteError is too involved here, so just drop the specificity down to a generic QMPError. Signed-off-by: John Snow Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Beraldo Leal --- scripts/render_block_graph.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py index 42288a3cfb..b33fb70d5e 100755 --- a/scripts/render_block_graph.py +++ b/scripts/render_block_graph.py @@ -25,10 +25,8 @@ import json from graphviz import Digraph sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'python')) -from qemu.qmp import ( - QEMUMonitorProtocol, - QMPResponseError, -) +from qemu.aqmp import QMPError +from qemu.aqmp.legacy import QEMUMonitorProtocol def perm(arr): @@ -104,7 +102,7 @@ class LibvirtGuest(): reply = json.loads(subprocess.check_output(ar)) if 'error' in reply: - raise QMPResponseError(reply) + raise QMPError(reply) return reply['return']

  • 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 iQ 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

    V#wuXNDFvdA+fx5 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 diff --git a/roms/SLOF b/roms/SLOF index a6906b024c..5b4c5acdcd 160000 --- a/roms/SLOF +++ b/roms/SLOF @@ -1 +1 @@ -Subproject commit a6906b024c6cca5a86496f51eb4bfee3a0c36148 +Subproject commit 5b4c5acdcd552a4e1796aeca6bb700f6cbb0282d From cced3a72300c3b077be3bef7048688b9cf6f98c3 Mon Sep 17 00:00:00 2001 From: Kostiantyn Kostiuk Date: Wed, 5 Jan 2022 09:09:42 +0000 Subject: [PATCH 362/730] MAINTAINERS: Add entry for QEMU Guest Agent Windows components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kostiantyn Kostiuk Reviewed-by: Marc-André Lureau Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Michael Roth --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index c98a61caee..391904bc60 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2737,6 +2737,14 @@ F: scripts/qemu-guest-agent/ F: tests/unit/test-qga.c T: git https://github.com/mdroth/qemu.git qga +QEMU Guest Agent Win32 +M: Konstantin Kostiuk +S: Maintained +F: qga/*win32* +F: qga/vss-win32/ +F: qga/installer/ +T: git https://github.com/kostyanf14/qemu.git qga-win32 + QOM M: Paolo Bonzini R: Daniel P. Berrange From d0b896a7495b71313c43aff4329714ade56799d4 Mon Sep 17 00:00:00 2001 From: Kostiantyn Kostiuk Date: Tue, 3 Aug 2021 09:38:39 +0000 Subject: [PATCH 363/730] gqa-win: get_pci_info: Clean dev_info if handle is valid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kostiantyn Kostiuk Reviewed-by: Marc-André Lureau Signed-off-by: Kostiantyn Kostiuk --- qga/commands-win32.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 4e84afd83b..3dd74fe225 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -514,7 +514,7 @@ DEFINE_GUID(GUID_DEVINTERFACE_STORAGEPORT, static GuestPCIAddress *get_pci_info(int number, Error **errp) { - HDEVINFO dev_info; + HDEVINFO dev_info = INVALID_HANDLE_VALUE; SP_DEVINFO_DATA dev_info_data; SP_DEVICE_INTERFACE_DATA dev_iface_data; HANDLE dev_file; @@ -749,7 +749,9 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) } free_dev_info: - SetupDiDestroyDeviceInfoList(dev_info); + if (dev_info != INVALID_HANDLE_VALUE) { + SetupDiDestroyDeviceInfoList(dev_info); + } out: return pci; } From e78ca586d66e0d2001a6caef90bf7361f3ef3ad1 Mon Sep 17 00:00:00 2001 From: Kostiantyn Kostiuk Date: Tue, 3 Aug 2021 10:11:48 +0000 Subject: [PATCH 364/730] gqa-win: get_pci_info: Use common 'end' label MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To prevent memory leaks, always try to free initialized variables. Signed-off-by: Kostiantyn Kostiuk Reviewed-by: Marc-André Lureau Signed-off-by: Kostiantyn Kostiuk --- qga/commands-win32.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 3dd74fe225..93c5375132 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -532,7 +532,7 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (dev_info == INVALID_HANDLE_VALUE) { error_setg_win32(errp, GetLastError(), "failed to get devices tree"); - goto out; + goto end; } g_debug("enumerating devices"); @@ -562,7 +562,7 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) } else { error_setg_win32(errp, GetLastError(), "failed to get device interfaces"); - goto free_dev_info; + goto end; } } @@ -576,7 +576,7 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) CloseHandle(dev_file); error_setg_win32(errp, GetLastError(), "failed to get device slot number"); - goto free_dev_info; + goto end; } CloseHandle(dev_file); @@ -586,7 +586,7 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) } else { error_setg_win32(errp, GetLastError(), "failed to get device interfaces"); - goto free_dev_info; + goto end; } g_debug("found device slot %d. Getting storage controller", number); @@ -603,7 +603,7 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) } else { error_setg_win32(errp, GetLastError(), "failed to get device instance ID"); - goto out; + goto end; } } @@ -617,14 +617,14 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) g_error("CM_Locate_DevInst failed with code %lx", cr); error_setg_win32(errp, GetLastError(), "failed to get device instance"); - goto out; + goto end; } cr = CM_Get_Parent(&parent_dev_inst, dev_inst, 0); if (cr != CR_SUCCESS) { g_error("CM_Get_Parent failed with code %lx", cr); error_setg_win32(errp, GetLastError(), "failed to get parent device instance"); - goto out; + goto end; } cr = CM_Get_Device_ID_Size(&dev_id_size, parent_dev_inst, 0); @@ -632,7 +632,7 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) g_error("CM_Get_Device_ID_Size failed with code %lx", cr); error_setg_win32(errp, GetLastError(), "failed to get parent device ID length"); - goto out; + goto end; } ++dev_id_size; @@ -647,7 +647,7 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) g_error("CM_Get_Device_ID failed with code %lx", cr); error_setg_win32(errp, GetLastError(), "failed to get parent device ID"); - goto out; + goto end; } } @@ -661,14 +661,14 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) if (parent_dev_info == INVALID_HANDLE_VALUE) { error_setg_win32(errp, GetLastError(), "failed to get parent device"); - goto out; + goto end; } parent_dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); if (!SetupDiEnumDeviceInfo(parent_dev_info, 0, &parent_dev_info_data)) { error_setg_win32(errp, GetLastError(), "failed to get parent device data"); - goto out; + goto end; } for (j = 0; @@ -748,11 +748,10 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) break; } -free_dev_info: +end: if (dev_info != INVALID_HANDLE_VALUE) { SetupDiDestroyDeviceInfoList(dev_info); } -out: return pci; } From c49ca88b5586cf17d8f9597aaab46e181a7fc797 Mon Sep 17 00:00:00 2001 From: Kostiantyn Kostiuk Date: Tue, 3 Aug 2021 10:26:14 +0000 Subject: [PATCH 365/730] gqa-win: get_pci_info: Free parent_dev_info properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case when the function fails to get parent device data, the parent_dev_info variable will be initialized, but not freed. Signed-off-by: Kostiantyn Kostiuk Reviewed-by: Marc-André Lureau Signed-off-by: Kostiantyn Kostiuk --- qga/commands-win32.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 93c5375132..f6de9e2676 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -515,6 +515,8 @@ DEFINE_GUID(GUID_DEVINTERFACE_STORAGEPORT, static GuestPCIAddress *get_pci_info(int number, Error **errp) { HDEVINFO dev_info = INVALID_HANDLE_VALUE; + HDEVINFO parent_dev_info = INVALID_HANDLE_VALUE; + SP_DEVINFO_DATA dev_info_data; SP_DEVICE_INTERFACE_DATA dev_iface_data; HANDLE dev_file; @@ -542,7 +544,6 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) PSP_DEVICE_INTERFACE_DETAIL_DATA pdev_iface_detail_data = NULL; STORAGE_DEVICE_NUMBER sdn; char *parent_dev_id = NULL; - HDEVINFO parent_dev_info; SP_DEVINFO_DATA parent_dev_info_data; DWORD j; DWORD size = 0; @@ -744,11 +745,13 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) break; } } - SetupDiDestroyDeviceInfoList(parent_dev_info); break; } end: + if (parent_dev_info != INVALID_HANDLE_VALUE) { + SetupDiDestroyDeviceInfoList(parent_dev_info); + } if (dev_info != INVALID_HANDLE_VALUE) { SetupDiDestroyDeviceInfoList(dev_info); } From 7cc354613e73bba407c56e3fc700abb76a419f20 Mon Sep 17 00:00:00 2001 From: Kostiantyn Kostiuk Date: Tue, 14 Dec 2021 12:15:27 +0000 Subject: [PATCH 366/730] gqa-win: get_pci_info: Split logic to separate functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kostiantyn Kostiuk Reviewed-by: Marc-André Lureau Signed-off-by: Kostiantyn Kostiuk --- qga/commands-win32.c | 161 +++++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 74 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index f6de9e2676..8588fa8633 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -512,6 +512,92 @@ DEFINE_GUID(GUID_DEVINTERFACE_STORAGEPORT, 0x2accfe60L, 0xc130, 0x11d2, 0xb0, 0x82, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +static void get_pci_address_for_device(GuestPCIAddress *pci, + HDEVINFO dev_info) +{ + SP_DEVINFO_DATA dev_info_data; + DWORD j; + DWORD size; + bool partial_pci = false; + + dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); + + for (j = 0; + SetupDiEnumDeviceInfo(dev_info, j, &dev_info_data); + j++) { + DWORD addr, bus, ui_slot, type; + int func, slot; + size = sizeof(DWORD); + + /* + * There is no need to allocate buffer in the next functions. The + * size is known and ULONG according to + * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx + */ + if (!SetupDiGetDeviceRegistryProperty( + dev_info, &dev_info_data, SPDRP_BUSNUMBER, + &type, (PBYTE)&bus, size, NULL)) { + debug_error("failed to get PCI bus"); + bus = -1; + partial_pci = true; + } + + /* + * The function retrieves the device's address. This value will be + * transformed into device function and number + */ + if (!SetupDiGetDeviceRegistryProperty( + dev_info, &dev_info_data, SPDRP_ADDRESS, + &type, (PBYTE)&addr, size, NULL)) { + debug_error("failed to get PCI address"); + addr = -1; + partial_pci = true; + } + + /* + * This call returns UINumber of DEVICE_CAPABILITIES structure. + * This number is typically a user-perceived slot number. + */ + if (!SetupDiGetDeviceRegistryProperty( + dev_info, &dev_info_data, SPDRP_UI_NUMBER, + &type, (PBYTE)&ui_slot, size, NULL)) { + debug_error("failed to get PCI slot"); + ui_slot = -1; + partial_pci = true; + } + + /* + * SetupApi gives us the same information as driver with + * IoGetDeviceProperty. According to Microsoft: + * + * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF) + * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF) + * SPDRP_ADDRESS is propertyAddress, so we do the same. + * + * https://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya + */ + if (partial_pci) { + pci->domain = -1; + pci->slot = -1; + pci->function = -1; + pci->bus = -1; + continue; + } else { + func = ((int)addr == -1) ? -1 : addr & 0x0000FFFF; + slot = ((int)addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF; + if ((int)ui_slot != slot) { + g_debug("mismatch with reported slot values: %d vs %d", + (int)ui_slot, slot); + } + pci->domain = 0; + pci->slot = (int)ui_slot; + pci->function = func; + pci->bus = (int)bus; + return; + } + } +} + static GuestPCIAddress *get_pci_info(int number, Error **errp) { HDEVINFO dev_info = INVALID_HANDLE_VALUE; @@ -522,7 +608,6 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) HANDLE dev_file; int i; GuestPCIAddress *pci = NULL; - bool partial_pci = false; pci = g_malloc0(sizeof(*pci)); pci->domain = -1; @@ -545,7 +630,6 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) STORAGE_DEVICE_NUMBER sdn; char *parent_dev_id = NULL; SP_DEVINFO_DATA parent_dev_info_data; - DWORD j; DWORD size = 0; g_debug("getting device path"); @@ -672,79 +756,8 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) goto end; } - for (j = 0; - SetupDiEnumDeviceInfo(parent_dev_info, j, &parent_dev_info_data); - j++) { - DWORD addr, bus, ui_slot, type; - int func, slot; + get_pci_address_for_device(pci, parent_dev_info); - /* - * There is no need to allocate buffer in the next functions. The - * size is known and ULONG according to - * https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx - */ - if (!SetupDiGetDeviceRegistryProperty( - parent_dev_info, &parent_dev_info_data, SPDRP_BUSNUMBER, - &type, (PBYTE)&bus, size, NULL)) { - debug_error("failed to get PCI bus"); - bus = -1; - partial_pci = true; - } - - /* - * The function retrieves the device's address. This value will be - * transformed into device function and number - */ - if (!SetupDiGetDeviceRegistryProperty( - parent_dev_info, &parent_dev_info_data, SPDRP_ADDRESS, - &type, (PBYTE)&addr, size, NULL)) { - debug_error("failed to get PCI address"); - addr = -1; - partial_pci = true; - } - - /* - * This call returns UINumber of DEVICE_CAPABILITIES structure. - * This number is typically a user-perceived slot number. - */ - if (!SetupDiGetDeviceRegistryProperty( - parent_dev_info, &parent_dev_info_data, SPDRP_UI_NUMBER, - &type, (PBYTE)&ui_slot, size, NULL)) { - debug_error("failed to get PCI slot"); - ui_slot = -1; - partial_pci = true; - } - - /* - * SetupApi gives us the same information as driver with - * IoGetDeviceProperty. According to Microsoft: - * - * FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF) - * DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF) - * SPDRP_ADDRESS is propertyAddress, so we do the same. - * - * https://docs.microsoft.com/en-us/windows/desktop/api/setupapi/nf-setupapi-setupdigetdeviceregistrypropertya - */ - if (partial_pci) { - pci->domain = -1; - pci->slot = -1; - pci->function = -1; - pci->bus = -1; - continue; - } else { - func = ((int)addr == -1) ? -1 : addr & 0x0000FFFF; - slot = ((int)addr == -1) ? -1 : (addr >> 16) & 0x0000FFFF; - if ((int)ui_slot != slot) { - g_debug("mismatch with reported slot values: %d vs %d", - (int)ui_slot, slot); - } - pci->domain = 0; - pci->slot = (int)ui_slot; - pci->function = func; - pci->bus = (int)bus; - break; - } - } break; } From 5f22473ebb6889dab79bd0a649b9de35ad075136 Mon Sep 17 00:00:00 2001 From: Kostiantyn Kostiuk Date: Tue, 3 Aug 2021 10:23:49 +0000 Subject: [PATCH 367/730] gqa-win: get_pci_info: Add g_autofree for few variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kostiantyn Kostiuk Reviewed-by: Marc-André Lureau Signed-off-by: Kostiantyn Kostiuk --- qga/commands-win32.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 8588fa8633..3092566313 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -626,9 +626,9 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); dev_iface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) { - PSP_DEVICE_INTERFACE_DETAIL_DATA pdev_iface_detail_data = NULL; + g_autofree PSP_DEVICE_INTERFACE_DETAIL_DATA pdev_iface_detail_data = NULL; STORAGE_DEVICE_NUMBER sdn; - char *parent_dev_id = NULL; + g_autofree char *parent_dev_id = NULL; SP_DEVINFO_DATA parent_dev_info_data; DWORD size = 0; @@ -654,7 +654,6 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) dev_file = CreateFile(pdev_iface_detail_data->DevicePath, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - g_free(pdev_iface_detail_data); if (!DeviceIoControl(dev_file, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &size, NULL)) { @@ -741,7 +740,6 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) parent_dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_STORAGEPORT, parent_dev_id, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - g_free(parent_dev_id); if (parent_dev_info == INVALID_HANDLE_VALUE) { error_setg_win32(errp, GetLastError(), From d919cea07c5e3506c3df7389f8d620b08c54b033 Mon Sep 17 00:00:00 2001 From: Kostiantyn Kostiuk Date: Wed, 8 Dec 2021 12:14:32 +0000 Subject: [PATCH 368/730] gqa-win: get_pci_info: Replace 'while' with 2 calls of the function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Microsoft suggests this solution in the documentation: https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetdeviceinterfacedetaila Signed-off-by: Kostiantyn Kostiuk Reviewed-by: Marc-André Lureau Signed-off-by: Kostiantyn Kostiuk --- qga/commands-win32.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 3092566313..892082504f 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -636,10 +636,10 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) if (SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data, &GUID_DEVINTERFACE_DISK, 0, &dev_iface_data)) { - while (!SetupDiGetDeviceInterfaceDetail(dev_info, &dev_iface_data, - pdev_iface_detail_data, - size, &size, - &dev_info_data)) { + if (!SetupDiGetDeviceInterfaceDetail(dev_info, &dev_iface_data, + pdev_iface_detail_data, + size, &size, + &dev_info_data)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { pdev_iface_detail_data = g_malloc(size); pdev_iface_detail_data->cbSize = @@ -651,6 +651,16 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) } } + if (!SetupDiGetDeviceInterfaceDetail(dev_info, &dev_iface_data, + pdev_iface_detail_data, + size, &size, + &dev_info_data)) { + // pdev_iface_detail_data already is allocated + error_setg_win32(errp, GetLastError(), + "failed to get device interfaces"); + goto end; + } + dev_file = CreateFile(pdev_iface_detail_data->DevicePath, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); @@ -680,8 +690,8 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) ULONG dev_id_size = 0; size = 0; - while (!SetupDiGetDeviceInstanceId(dev_info, &dev_info_data, - parent_dev_id, size, &size)) { + if (!SetupDiGetDeviceInstanceId(dev_info, &dev_info_data, + parent_dev_id, size, &size)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { parent_dev_id = g_malloc(size); } else { @@ -691,6 +701,14 @@ static GuestPCIAddress *get_pci_info(int number, Error **errp) } } + if (!SetupDiGetDeviceInstanceId(dev_info, &dev_info_data, + parent_dev_id, size, &size)) { + // parent_dev_id already is allocated + error_setg_win32(errp, GetLastError(), + "failed to get device instance ID"); + goto end; + } + /* * CM API used here as opposed to * SetupDiGetDeviceProperty(..., DEVPKEY_Device_Parent, ...) From 92857cd73848a488506fbe937e0a978c42d52e2c Mon Sep 17 00:00:00 2001 From: Kostiantyn Kostiuk Date: Tue, 14 Sep 2021 10:28:44 +0000 Subject: [PATCH 369/730] qga-win: Detect OS based on Windows 10 by first build number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows Server 2016, 2019, 2022 are based on Windows 10 and have the same major and minor versions. So, the only way to detect the proper version is to use the build number. Before this commit, the guest agent use the last build number for each OS, but it causes problems when new OS releases. There are few preview versions before release, and we can't update this list. After this commit, the guest agent will use the first build number. For each new preview version or release version, Microsoft increases the build number, so we can add the number of the first preview build and this will work until the new OS release. Signed-off-by: Kostiantyn Kostiuk Reviewed-by: Marc-André Lureau Signed-off-by: Kostiantyn Kostiuk --- qga/commands-win32.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 892082504f..3f60419419 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -2195,7 +2195,7 @@ static ga_matrix_lookup_t const WIN_VERSION_MATRIX[2][8] = { }; typedef struct _ga_win_10_0_server_t { - int final_build; + int first_build; char const *version; char const *version_id; } ga_win_10_0_server_t; @@ -2235,18 +2235,22 @@ static char *ga_get_win_name(OSVERSIONINFOEXW const *os_version, bool id) int tbl_idx = (os_version->wProductType != VER_NT_WORKSTATION); ga_matrix_lookup_t const *table = WIN_VERSION_MATRIX[tbl_idx]; ga_win_10_0_server_t const *win_10_0_table = WIN_10_0_SERVER_VERSION_MATRIX; + ga_win_10_0_server_t const *win_10_0_version = NULL; while (table->version != NULL) { if (major == 10 && minor == 0 && tbl_idx) { while (win_10_0_table->version != NULL) { - if (build <= win_10_0_table->final_build) { - if (id) { - return g_strdup(win_10_0_table->version_id); - } else { - return g_strdup(win_10_0_table->version); - } + if (build >= win_10_0_table->first_build) { + win_10_0_version = win_10_0_table; } win_10_0_table++; } + if (win_10_0_table) { + if (id) { + return g_strdup(win_10_0_version->version_id); + } else { + return g_strdup(win_10_0_version->version); + } + } } else if (major == table->major && minor == table->minor) { if (id) { return g_strdup(table->version_id); From 206ce9699fae1f631ac74b7e1115db2affc759fd Mon Sep 17 00:00:00 2001 From: Kostiantyn Kostiuk Date: Tue, 14 Sep 2021 10:58:13 +0000 Subject: [PATCH 370/730] qga-win: Detect Windows 11 by build number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows 10 and 11 have the same major and minor versions. So, the only way to determine the correct version is to use the build number. After this commit, the guest agent will return the proper "version" and "version-id" for Windows 11. The "pretty-name" is read from the registry and will be incorrect until the MS updates the registry. We only can create some workaround and replace 10 to 11. Signed-off-by: Kostiantyn Kostiuk Reviewed-by: Marc-André Lureau Signed-off-by: Kostiantyn Kostiuk --- qga/commands-win32.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 3f60419419..484cb1c6bd 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -2170,7 +2170,7 @@ typedef struct _ga_matrix_lookup_t { char const *version_id; } ga_matrix_lookup_t; -static ga_matrix_lookup_t const WIN_VERSION_MATRIX[2][8] = { +static ga_matrix_lookup_t const WIN_VERSION_MATRIX[2][7] = { { /* Desktop editions */ { 5, 0, "Microsoft Windows 2000", "2000"}, @@ -2179,7 +2179,6 @@ static ga_matrix_lookup_t const WIN_VERSION_MATRIX[2][8] = { { 6, 1, "Microsoft Windows 7" "7"}, { 6, 2, "Microsoft Windows 8", "8"}, { 6, 3, "Microsoft Windows 8.1", "8.1"}, - {10, 0, "Microsoft Windows 10", "10"}, { 0, 0, 0} },{ /* Server editions */ @@ -2189,24 +2188,29 @@ static ga_matrix_lookup_t const WIN_VERSION_MATRIX[2][8] = { { 6, 2, "Microsoft Windows Server 2012", "2012"}, { 6, 3, "Microsoft Windows Server 2012 R2", "2012r2"}, { 0, 0, 0}, - { 0, 0, 0}, { 0, 0, 0} } }; -typedef struct _ga_win_10_0_server_t { +typedef struct _ga_win_10_0_t { int first_build; char const *version; char const *version_id; -} ga_win_10_0_server_t; +} ga_win_10_0_t; -static ga_win_10_0_server_t const WIN_10_0_SERVER_VERSION_MATRIX[4] = { +static ga_win_10_0_t const WIN_10_0_SERVER_VERSION_MATRIX[4] = { {14393, "Microsoft Windows Server 2016", "2016"}, {17763, "Microsoft Windows Server 2019", "2019"}, {20344, "Microsoft Windows Server 2022", "2022"}, {0, 0} }; +static ga_win_10_0_t const WIN_10_0_CLIENT_VERSION_MATRIX[3] = { + {10240, "Microsoft Windows 10", "10"}, + {22000, "Microsoft Windows 11", "11"}, + {0, 0} +}; + static void ga_get_win_version(RTL_OSVERSIONINFOEXW *info, Error **errp) { typedef NTSTATUS(WINAPI *rtl_get_version_t)( @@ -2234,10 +2238,11 @@ static char *ga_get_win_name(OSVERSIONINFOEXW const *os_version, bool id) DWORD build = os_version->dwBuildNumber; int tbl_idx = (os_version->wProductType != VER_NT_WORKSTATION); ga_matrix_lookup_t const *table = WIN_VERSION_MATRIX[tbl_idx]; - ga_win_10_0_server_t const *win_10_0_table = WIN_10_0_SERVER_VERSION_MATRIX; - ga_win_10_0_server_t const *win_10_0_version = NULL; + ga_win_10_0_t const *win_10_0_table = tbl_idx ? + WIN_10_0_SERVER_VERSION_MATRIX : WIN_10_0_CLIENT_VERSION_MATRIX; + ga_win_10_0_t const *win_10_0_version = NULL; while (table->version != NULL) { - if (major == 10 && minor == 0 && tbl_idx) { + if (major == 10 && minor == 0) { while (win_10_0_table->version != NULL) { if (build >= win_10_0_table->first_build) { win_10_0_version = win_10_0_table; From 847e9bc974b5734f3ae6eb677e2ad65a0f80c7ad Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 10 Jan 2022 00:46:10 -0500 Subject: [PATCH 371/730] Revert "virtio-pci: add support for configure interrupt" This reverts commit d5d24d859c3957ea1674d0e102f96439cdbfe93a. Fixes: d5d24d859c ("virtio-pci: add support for configure interrupt") Cc: "Cindy Lu" Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 92 ++++++------------------------------------ hw/virtio/virtio-pci.h | 4 +- 2 files changed, 13 insertions(+), 83 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 98fb5493ae..7201cf3dc1 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -727,8 +727,7 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, VirtQueue *vq; if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { - *n = virtio_config_get_guest_notifier(vdev); - *vector = vdev->config_vector; + return -1; } else { if (!virtio_queue_get_num(vdev, queue_no)) { return -1; @@ -803,10 +802,6 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) return ret; } -static int kvm_virtio_pci_vector_config_use(VirtIOPCIProxy *proxy) -{ - return kvm_virtio_pci_vector_use_one(proxy, VIRTIO_CONFIG_IRQ_IDX); -} static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy, int queue_no) @@ -844,11 +839,6 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) } } -static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy) -{ - kvm_virtio_pci_vector_release_one(proxy, VIRTIO_CONFIG_IRQ_IDX); -} - static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, unsigned int queue_no, unsigned int vector, @@ -930,17 +920,9 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, } vq = virtio_vector_next_queue(vq); } - /* unmask config intr */ - n = virtio_config_get_guest_notifier(vdev); - ret = virtio_pci_one_vector_unmask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, - msg, n); - if (ret < 0) { - goto undo_config; - } + return 0; -undo_config: - n = virtio_config_get_guest_notifier(vdev); - virtio_pci_one_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n); + undo: vq = virtio_vector_first_queue(vdev, vector); while (vq && unmasked >= 0) { @@ -974,8 +956,6 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) } vq = virtio_vector_next_queue(vq); } - n = virtio_config_get_guest_notifier(vdev); - virtio_pci_one_vector_mask(proxy, VIRTIO_CONFIG_IRQ_IDX, vector, n); } static void virtio_pci_vector_poll(PCIDevice *dev, @@ -1007,34 +987,6 @@ static void virtio_pci_vector_poll(PCIDevice *dev, msix_set_pending(dev, vector); } } - /* poll the config intr */ - ret = virtio_pci_get_notifier(proxy, VIRTIO_CONFIG_IRQ_IDX, ¬ifier, - &vector); - if (ret < 0) { - return; - } - if (vector < vector_start || vector >= vector_end || - !msix_is_masked(dev, vector)) { - return; - } - if (k->guest_notifier_pending) { - if (k->guest_notifier_pending(vdev, VIRTIO_CONFIG_IRQ_IDX)) { - msix_set_pending(dev, vector); - } - } else if (event_notifier_test_and_clear(notifier)) { - msix_set_pending(dev, vector); - } -} - -void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq, - int n, bool assign, - bool with_irqfd) -{ - if (n == VIRTIO_CONFIG_IRQ_IDX) { - virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); - } else { - virtio_queue_set_guest_notifier_fd_handler(vq, assign, with_irqfd); - } } static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, @@ -1043,25 +995,17 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign, VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); - VirtQueue *vq = NULL; - EventNotifier *notifier = NULL; - - if (n == VIRTIO_CONFIG_IRQ_IDX) { - notifier = virtio_config_get_guest_notifier(vdev); - } else { - vq = virtio_get_queue(vdev, n); - notifier = virtio_queue_get_guest_notifier(vq); - } + VirtQueue *vq = virtio_get_queue(vdev, n); + EventNotifier *notifier = virtio_queue_get_guest_notifier(vq); if (assign) { int r = event_notifier_init(notifier, 0); if (r < 0) { return r; } - virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, true, with_irqfd); + virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd); } else { - virtio_pci_set_guest_notifier_fd_handler(vdev, vq, n, false, - with_irqfd); + virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd); event_notifier_cleanup(notifier); } @@ -1103,7 +1047,6 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) msix_unset_vector_notifiers(&proxy->pci_dev); if (proxy->vector_irqfd) { kvm_virtio_pci_vector_release(proxy, nvqs); - kvm_virtio_pci_vector_config_release(proxy); g_free(proxy->vector_irqfd); proxy->vector_irqfd = NULL; } @@ -1119,11 +1062,7 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) goto assign_error; } } - r = virtio_pci_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, assign, - with_irqfd); - if (r < 0) { - goto config_assign_error; - } + /* Must set vector notifier after guest notifier has been assigned */ if ((with_irqfd || k->guest_notifier_mask) && assign) { if (with_irqfd) { @@ -1132,14 +1071,11 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) msix_nr_vectors_allocated(&proxy->pci_dev)); r = kvm_virtio_pci_vector_use(proxy, nvqs); if (r < 0) { - goto config_assign_error; + goto assign_error; } } - r = kvm_virtio_pci_vector_config_use(proxy); - if (r < 0) { - goto config_error; - } - r = msix_set_vector_notifiers(&proxy->pci_dev, virtio_pci_vector_unmask, + r = msix_set_vector_notifiers(&proxy->pci_dev, + virtio_pci_vector_unmask, virtio_pci_vector_mask, virtio_pci_vector_poll); if (r < 0) { @@ -1154,11 +1090,7 @@ notifiers_error: assert(assign); kvm_virtio_pci_vector_release(proxy, nvqs); } -config_error: - kvm_virtio_pci_vector_config_release(proxy); -config_assign_error: - virtio_pci_set_guest_notifier(d, VIRTIO_CONFIG_IRQ_IDX, !assign, - with_irqfd); + assign_error: /* We get here on assignment failure. Recover by undoing for VQs 0 .. n. */ assert(assign); diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index b704acc5a8..2446dcd9ae 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -251,7 +251,5 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t); * @fixed_queues. */ unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues); -void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq, - int n, bool assign, - bool with_irqfd); + #endif From 99478e5941df06e2de9016e63064d8b8681ceb81 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 10 Jan 2022 00:46:15 -0500 Subject: [PATCH 372/730] Revert "virtio-mmio: add support for configure interrupt" This reverts commit d48185f1a40d4e4ed2fa2873a42b2a5eb8748256. Fixes: d48185f1a4 ("virtio-mmio: add support for configure interrupt") Cc: "Cindy Lu" Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-mmio.c | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index 809132018b..72da12fea5 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -673,30 +673,7 @@ static int virtio_mmio_set_guest_notifier(DeviceState *d, int n, bool assign, return 0; } -static int virtio_mmio_set_config_guest_notifier(DeviceState *d, bool assign) -{ - VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d); - VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); - bool with_irqfd = false; - EventNotifier *notifier = virtio_config_get_guest_notifier(vdev); - int r = 0; - if (assign) { - r = event_notifier_init(notifier, 0); - if (r < 0) { - return r; - } - virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); - } else { - virtio_config_set_guest_notifier_fd_handler(vdev, assign, with_irqfd); - event_notifier_cleanup(notifier); - } - if (vdc->guest_notifier_mask && vdev->use_guest_notifier_mask) { - vdc->guest_notifier_mask(vdev, VIRTIO_CONFIG_IRQ_IDX, !assign); - } - return r; -} static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) { @@ -718,10 +695,6 @@ static int virtio_mmio_set_guest_notifiers(DeviceState *d, int nvqs, goto assign_error; } } - r = virtio_mmio_set_config_guest_notifier(d, assign); - if (r < 0) { - goto assign_error; - } return 0; From b3ef6664b7f1222e708f72685270d8663ae1625c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 10 Jan 2022 00:46:16 -0500 Subject: [PATCH 373/730] Revert "virtio-net: add support for configure interrupt" This reverts commit 497679d51087090d5a22fd265d1b96cf92d49d9d. Fixes: 497679d510 ("virtio-net: add support for configure interrupt") Cc: "Cindy Lu" Signed-off-by: Michael S. Tsirkin --- hw/net/vhost_net-stub.c | 9 --------- hw/net/vhost_net.c | 9 --------- hw/net/virtio-net.c | 4 ++-- include/net/vhost_net.h | 2 -- 4 files changed, 2 insertions(+), 22 deletions(-) diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c index 126ee35b70..89d71cfb8e 100644 --- a/hw/net/vhost_net-stub.c +++ b/hw/net/vhost_net-stub.c @@ -101,12 +101,3 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu) { return 0; } - -bool vhost_net_config_pending(VHostNetState *net) -{ - return false; -} - -void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask) -{ -} diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 9c9fd0a73f..30379d2ca4 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -457,15 +457,6 @@ void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, vhost_virtqueue_mask(&net->dev, dev, idx, mask); } -bool vhost_net_config_pending(VHostNetState *net) -{ - return vhost_config_pending(&net->dev); -} - -void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask) -{ - vhost_config_mask(&net->dev, dev, mask); -} VHostNetState *get_vhost_net(NetClientState *nc) { VHostNetState *vhost_net = 0; diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 5806a50c8d..5e03c0dd14 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -3169,7 +3169,7 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); assert(n->vhost_started); if (idx == VIRTIO_CONFIG_IRQ_IDX) { - return vhost_net_config_pending(get_vhost_net(nc->peer)); + return false; } return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx); } @@ -3181,9 +3181,9 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); assert(n->vhost_started); if (idx == VIRTIO_CONFIG_IRQ_IDX) { - vhost_net_config_mask(get_vhost_net(nc->peer), vdev, mask); return; } + vhost_net_virtqueue_mask(get_vhost_net(nc->peer), vdev, idx, mask); } diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index fc37498550..387e913e4e 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -39,8 +39,6 @@ int vhost_net_set_config(struct vhost_net *net, const uint8_t *data, bool vhost_net_virtqueue_pending(VHostNetState *net, int n); void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, int idx, bool mask); -bool vhost_net_config_pending(VHostNetState *net); -void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask); int vhost_net_notify_migration_done(VHostNetState *net, char* mac_addr); VHostNetState *get_vhost_net(NetClientState *nc); From a86d1a0a938793883477b30af48d4d1939199358 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 10 Jan 2022 00:47:49 -0500 Subject: [PATCH 374/730] Revert "vhost: add support for configure interrupt" This reverts commit f7220a7ce21604a4bc6260ccca4dc9068c1f27f2. Fixes: f7220a7ce2 ("vhost: add support for configure interrupt") Cc: "Cindy Lu" Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost.c | 76 --------------------------------------- include/hw/virtio/vhost.h | 4 --- 2 files changed, 80 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index cbf3b792da..7b03efccec 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1554,67 +1554,6 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n, } } -bool vhost_config_pending(struct vhost_dev *hdev) -{ - assert(hdev->vhost_ops); - if ((hdev->started == false) || - (hdev->vhost_ops->vhost_set_config_call == NULL)) { - return false; - } - - EventNotifier *notifier = - &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier; - return event_notifier_test_and_clear(notifier); -} - -void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask) -{ - int fd; - int r; - EventNotifier *notifier = - &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier; - EventNotifier *config_notifier = &vdev->config_notifier; - assert(hdev->vhost_ops); - - if ((hdev->started == false) || - (hdev->vhost_ops->vhost_set_config_call == NULL)) { - return; - } - if (mask) { - assert(vdev->use_guest_notifier_mask); - fd = event_notifier_get_fd(notifier); - } else { - fd = event_notifier_get_fd(config_notifier); - } - r = hdev->vhost_ops->vhost_set_config_call(hdev, fd); - if (r < 0) { - VHOST_OPS_DEBUG(r, "vhost_set_config_call failed"); - } -} - -static void vhost_stop_config_intr(struct vhost_dev *dev) -{ - int fd = -1; - assert(dev->vhost_ops); - if (dev->vhost_ops->vhost_set_config_call) { - dev->vhost_ops->vhost_set_config_call(dev, fd); - } -} - -static void vhost_start_config_intr(struct vhost_dev *dev) -{ - int r; - - assert(dev->vhost_ops); - int fd = event_notifier_get_fd(&dev->vdev->config_notifier); - if (dev->vhost_ops->vhost_set_config_call) { - r = dev->vhost_ops->vhost_set_config_call(dev, fd); - if (!r) { - event_notifier_set(&dev->vdev->config_notifier); - } - } -} - uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits, uint64_t features) { @@ -1827,16 +1766,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) } } - r = event_notifier_init( - &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier, 0); - if (r < 0) { - return r; - } - event_notifier_test_and_clear( - &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); - if (!vdev->use_guest_notifier_mask) { - vhost_config_mask(hdev, vdev, true); - } if (hdev->log_enabled) { uint64_t log_base; @@ -1869,7 +1798,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) vhost_device_iotlb_miss(hdev, vq->used_phys, true); } } - vhost_start_config_intr(hdev); return 0; fail_log: vhost_log_put(hdev, false); @@ -1895,9 +1823,6 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) /* should only be called after backend is connected */ assert(hdev->vhost_ops); - event_notifier_test_and_clear( - &hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier); - event_notifier_test_and_clear(&vdev->config_notifier); if (hdev->vhost_ops->vhost_dev_start) { hdev->vhost_ops->vhost_dev_start(hdev, false); @@ -1915,7 +1840,6 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) } memory_listener_unregister(&hdev->iommu_listener); } - vhost_stop_config_intr(hdev); vhost_log_put(hdev, true); hdev->started = false; hdev->vdev = NULL; diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index b0f3b78987..58a73e7b7a 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -29,7 +29,6 @@ struct vhost_virtqueue { unsigned long long used_phys; unsigned used_size; EventNotifier masked_notifier; - EventNotifier masked_config_notifier; struct vhost_dev *dev; }; @@ -38,7 +37,6 @@ typedef unsigned long vhost_log_chunk_t; #define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t)) #define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS) #define VHOST_INVALID_FEATURE_BIT (0xff) -#define VHOST_QUEUE_NUM_CONFIG_INR 0 struct vhost_log { unsigned long long size; @@ -118,8 +116,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev); void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev); int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); -bool vhost_config_pending(struct vhost_dev *hdev); -void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask); /* Test and clear masked event pending status. * Should be called after unmask to avoid losing events. From 81c3ebc32f6bbf00de916c43b070ccda0c8dbc9a Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 10 Jan 2022 00:47:50 -0500 Subject: [PATCH 375/730] Revert "virtio: add support for configure interrupt" This reverts commit 081f864f56307551f59c5e934e3f30a7290d0faa. Fixes: 081f864f56 ("virtio: add support for configure interrupt") Cc: "Cindy Lu" Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 29 ----------------------------- include/hw/virtio/virtio.h | 4 ---- 2 files changed, 33 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 971e59a663..5d18868d7d 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3494,14 +3494,7 @@ static void virtio_queue_guest_notifier_read(EventNotifier *n) virtio_irq(vq); } } -static void virtio_config_guest_notifier_read(EventNotifier *n) -{ - VirtIODevice *vdev = container_of(n, VirtIODevice, config_notifier); - if (event_notifier_test_and_clear(n)) { - virtio_notify_config(vdev); - } -} void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, bool with_irqfd) { @@ -3518,23 +3511,6 @@ void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, } } -void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev, - bool assign, bool with_irqfd) -{ - EventNotifier *n; - n = &vdev->config_notifier; - if (assign && !with_irqfd) { - event_notifier_set_handler(n, virtio_config_guest_notifier_read); - } else { - event_notifier_set_handler(n, NULL); - } - if (!assign) { - /* Test and clear notifier before closing it,*/ - /* in case poll callback didn't have time to run. */ - virtio_config_guest_notifier_read(n); - } -} - EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq) { return &vq->guest_notifier; @@ -3608,11 +3584,6 @@ EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq) return &vq->host_notifier; } -EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev) -{ - return &vdev->config_notifier; -} - void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled) { vq->host_notifier_enabled = enabled; diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index d78088d872..605ea79c90 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -111,7 +111,6 @@ struct VirtIODevice bool use_guest_notifier_mask; AddressSpace *dma_as; QLIST_HEAD(, VirtQueue) *vector_queues; - EventNotifier config_notifier; }; struct VirtioDeviceClass { @@ -314,14 +313,11 @@ uint16_t virtio_get_queue_index(VirtQueue *vq); EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq); void virtio_queue_set_guest_notifier_fd_handler(VirtQueue *vq, bool assign, bool with_irqfd); -void virtio_config_set_guest_notifier_fd_handler(VirtIODevice *vdev, - bool assign, bool with_irqfd); int virtio_device_start_ioeventfd(VirtIODevice *vdev); int virtio_device_grab_ioeventfd(VirtIODevice *vdev); void virtio_device_release_ioeventfd(VirtIODevice *vdev); bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev); EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq); -EventNotifier *virtio_config_get_guest_notifier(VirtIODevice *vdev); void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled); void virtio_queue_host_notifier_read(EventNotifier *n); void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, From 73bd56abe1709352ab123952c96cc3255d0cbeff Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 10 Jan 2022 00:47:51 -0500 Subject: [PATCH 376/730] Revert "vhost-vdpa: add support for config interrupt" This reverts commit 634f7c89fbd78f57d00d5d6b39c0ade9df1fe27f. Fixes: 634f7c89fb ("vhost-vdpa: add support for config interrupt") Cc: "Cindy Lu" Signed-off-by: Michael S. Tsirkin --- hw/virtio/trace-events | 1 - hw/virtio/vhost-vdpa.c | 7 ------- 2 files changed, 8 deletions(-) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 595ce015ff..f7ad6be5fb 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -53,7 +53,6 @@ vhost_vdpa_get_features(void *dev, uint64_t features) "dev: %p features: 0x%"PRI vhost_vdpa_set_owner(void *dev) "dev: %p" vhost_vdpa_vq_get_addr(void *dev, void *vq, uint64_t desc_user_addr, uint64_t avail_user_addr, uint64_t used_user_addr) "dev: %p vq: %p desc_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" used_user_addr: 0x%"PRIx64 vhost_vdpa_get_iova_range(void *dev, uint64_t first, uint64_t last) "dev: %p first: 0x%"PRIx64" last: 0x%"PRIx64 -vhost_vdpa_set_config_call(void *dev, int fd)"dev: %p fd: %d" # virtio.c virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned out_num) "elem %p size %zd in_num %u out_num %u" diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index ac0cb575fb..04ea43704f 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -734,12 +734,6 @@ static int vhost_vdpa_set_vring_call(struct vhost_dev *dev, trace_vhost_vdpa_set_vring_call(dev, file->index, file->fd); return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file); } -static int vhost_vdpa_set_config_call(struct vhost_dev *dev, - int fd) -{ - trace_vhost_vdpa_set_config_call(dev, fd); - return vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG_CALL, &fd); -} static int vhost_vdpa_get_features(struct vhost_dev *dev, uint64_t *features) @@ -810,5 +804,4 @@ const VhostOps vdpa_ops = { .vhost_get_device_id = vhost_vdpa_get_device_id, .vhost_vq_get_addr = vhost_vdpa_vq_get_addr, .vhost_force_iommu = vhost_vdpa_force_iommu, - .vhost_set_config_call = vhost_vdpa_set_config_call, }; From 98b34e030e39969300952e97d873d8553dcf650f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 10 Jan 2022 00:47:52 -0500 Subject: [PATCH 377/730] Revert "vhost: introduce new VhostOps vhost_set_config_call" This reverts commit 88062372340d33090b7f089ed3b1a00f530a8914. Fixes: 8806237234 ("vhost: introduce new VhostOps vhost_set_config_call") Cc: "Cindy Lu" Signed-off-by: Michael S. Tsirkin --- include/hw/virtio/vhost-backend.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h index ff34eb7c8a..81bf3109f8 100644 --- a/include/hw/virtio/vhost-backend.h +++ b/include/hw/virtio/vhost-backend.h @@ -126,8 +126,6 @@ typedef int (*vhost_get_device_id_op)(struct vhost_dev *dev, uint32_t *dev_id); typedef bool (*vhost_force_iommu_op)(struct vhost_dev *dev); -typedef int (*vhost_set_config_call_op)(struct vhost_dev *dev, - int fd); typedef struct VhostOps { VhostBackendType backend_type; vhost_backend_init vhost_backend_init; @@ -173,7 +171,6 @@ typedef struct VhostOps { vhost_vq_get_addr_op vhost_vq_get_addr; vhost_get_device_id_op vhost_get_device_id; vhost_force_iommu_op vhost_force_iommu; - vhost_set_config_call_op vhost_set_config_call; } VhostOps; int vhost_backend_update_device_iotlb(struct vhost_dev *dev, From 38ce405198827d9b4807af54836238b55cb1c21e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 10 Jan 2022 00:47:53 -0500 Subject: [PATCH 378/730] Revert "virtio-pci: decouple the single vector from the interrupt process" This reverts commit 316011b8a74e777eb3ba03171cd701a291c28867. Fixes: 316011b8a7 ("virtio-pci: decouple the single vector from the interrupt process") Cc: "Cindy Lu" Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 163 +++++++++++++++++++---------------------- 1 file changed, 74 insertions(+), 89 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 7201cf3dc1..4bdb6e5694 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -677,6 +677,7 @@ static uint32_t virtio_read_config(PCIDevice *pci_dev, } static int kvm_virtio_pci_vq_vector_use(VirtIOPCIProxy *proxy, + unsigned int queue_no, unsigned int vector) { VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; @@ -739,103 +740,87 @@ static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, return 0; } -static int kvm_virtio_pci_vector_use_one(VirtIOPCIProxy *proxy, int queue_no) -{ - unsigned int vector; - int ret; - EventNotifier *n; - PCIDevice *dev = &proxy->pci_dev; - VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - - ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); - if (ret < 0) { - return ret; - } - if (vector >= msix_nr_vectors_allocated(dev)) { - return 0; - } - ret = kvm_virtio_pci_vq_vector_use(proxy, vector); - if (ret < 0) { - goto undo; - } - /* - * If guest supports masking, set up irqfd now. - * Otherwise, delay until unmasked in the frontend. - */ - if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); - if (ret < 0) { - kvm_virtio_pci_vq_vector_release(proxy, vector); - goto undo; - } - } - - return 0; -undo: - - vector = virtio_queue_vector(vdev, queue_no); - if (vector >= msix_nr_vectors_allocated(dev)) { - return ret; - } - if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); - if (ret < 0) { - return ret; - } - kvm_virtio_pci_irqfd_release(proxy, n, vector); - } - return ret; -} static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) { - int queue_no; - int ret = 0; - VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - - for (queue_no = 0; queue_no < nvqs; queue_no++) { - if (!virtio_queue_get_num(vdev, queue_no)) { - return -1; - } - ret = kvm_virtio_pci_vector_use_one(proxy, queue_no); - } - return ret; -} - - -static void kvm_virtio_pci_vector_release_one(VirtIOPCIProxy *proxy, - int queue_no) -{ - VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - unsigned int vector; - EventNotifier *n; - int ret; - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); PCIDevice *dev = &proxy->pci_dev; - - ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); - if (ret < 0) { - return; - } - if (vector >= msix_nr_vectors_allocated(dev)) { - return; - } - if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - kvm_virtio_pci_irqfd_release(proxy, n, vector); - } - kvm_virtio_pci_vq_vector_release(proxy, vector); -} - -static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) -{ - int queue_no; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + unsigned int vector; + int ret, queue_no; + EventNotifier *n; for (queue_no = 0; queue_no < nvqs; queue_no++) { if (!virtio_queue_get_num(vdev, queue_no)) { break; } - kvm_virtio_pci_vector_release_one(proxy, queue_no); + ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); + if (ret < 0) { + break; + } + if (vector >= msix_nr_vectors_allocated(dev)) { + continue; + } + ret = kvm_virtio_pci_vq_vector_use(proxy, queue_no, vector); + if (ret < 0) { + goto undo; + } + /* If guest supports masking, set up irqfd now. + * Otherwise, delay until unmasked in the frontend. + */ + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { + ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); + if (ret < 0) { + kvm_virtio_pci_vq_vector_release(proxy, vector); + goto undo; + } + } + } + return 0; + +undo: + while (--queue_no >= 0) { + vector = virtio_queue_vector(vdev, queue_no); + if (vector >= msix_nr_vectors_allocated(dev)) { + continue; + } + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { + ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); + if (ret < 0) { + break; + } + kvm_virtio_pci_irqfd_release(proxy, n, vector); + } + kvm_virtio_pci_vq_vector_release(proxy, vector); + } + return ret; +} + +static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) +{ + PCIDevice *dev = &proxy->pci_dev; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + unsigned int vector; + int queue_no; + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + EventNotifier *n; + int ret ; + for (queue_no = 0; queue_no < nvqs; queue_no++) { + if (!virtio_queue_get_num(vdev, queue_no)) { + break; + } + ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); + if (ret < 0) { + break; + } + if (vector >= msix_nr_vectors_allocated(dev)) { + continue; + } + /* If guest supports masking, clean up irqfd now. + * Otherwise, it was cleaned when masked in the frontend. + */ + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { + kvm_virtio_pci_irqfd_release(proxy, n, vector); + } + kvm_virtio_pci_vq_vector_release(proxy, vector); } } From a20fa00ce1baa69b29276fa9fab1cdf5235c7ec6 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 10 Jan 2022 00:47:54 -0500 Subject: [PATCH 379/730] Revert "virtio-pci: decouple notifier from interrupt process" This reverts commit e3480ef81f6fb61cc9c04e3b5be8b7e84484fc05. Fixes: e3480ef81f ("virtio-pci: decouple notifier from interrupt process") Cc: "Cindy Lu" Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 88 +++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 57 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 4bdb6e5694..750aa47ec1 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -704,41 +704,29 @@ static void kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy, } static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy, - EventNotifier *n, + unsigned int queue_no, unsigned int vector) { VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtQueue *vq = virtio_get_queue(vdev, queue_no); + EventNotifier *n = virtio_queue_get_guest_notifier(vq); return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, n, NULL, irqfd->virq); } static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy, - EventNotifier *n , + unsigned int queue_no, unsigned int vector) { + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtQueue *vq = virtio_get_queue(vdev, queue_no); + EventNotifier *n = virtio_queue_get_guest_notifier(vq); VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector]; int ret; ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, irqfd->virq); assert(ret == 0); } -static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no, - EventNotifier **n, unsigned int *vector) -{ - VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - VirtQueue *vq; - - if (queue_no == VIRTIO_CONFIG_IRQ_IDX) { - return -1; - } else { - if (!virtio_queue_get_num(vdev, queue_no)) { - return -1; - } - *vector = virtio_queue_vector(vdev, queue_no); - vq = virtio_get_queue(vdev, queue_no); - *n = virtio_queue_get_guest_notifier(vq); - } - return 0; -} static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) { @@ -747,15 +735,12 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); unsigned int vector; int ret, queue_no; - EventNotifier *n; + for (queue_no = 0; queue_no < nvqs; queue_no++) { if (!virtio_queue_get_num(vdev, queue_no)) { break; } - ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); - if (ret < 0) { - break; - } + vector = virtio_queue_vector(vdev, queue_no); if (vector >= msix_nr_vectors_allocated(dev)) { continue; } @@ -767,7 +752,7 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs) * Otherwise, delay until unmasked in the frontend. */ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); + ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); if (ret < 0) { kvm_virtio_pci_vq_vector_release(proxy, vector); goto undo; @@ -783,11 +768,7 @@ undo: continue; } if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); - if (ret < 0) { - break; - } - kvm_virtio_pci_irqfd_release(proxy, n, vector); + kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); } kvm_virtio_pci_vq_vector_release(proxy, vector); } @@ -801,16 +782,12 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) unsigned int vector; int queue_no; VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); - EventNotifier *n; - int ret ; + for (queue_no = 0; queue_no < nvqs; queue_no++) { if (!virtio_queue_get_num(vdev, queue_no)) { break; } - ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); - if (ret < 0) { - break; - } + vector = virtio_queue_vector(vdev, queue_no); if (vector >= msix_nr_vectors_allocated(dev)) { continue; } @@ -818,20 +795,21 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy *proxy, int nvqs) * Otherwise, it was cleaned when masked in the frontend. */ if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - kvm_virtio_pci_irqfd_release(proxy, n, vector); + kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); } kvm_virtio_pci_vq_vector_release(proxy, vector); } } -static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, +static int virtio_pci_vq_vector_unmask(VirtIOPCIProxy *proxy, unsigned int queue_no, unsigned int vector, - MSIMessage msg, - EventNotifier *n) + MSIMessage msg) { VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + VirtQueue *vq = virtio_get_queue(vdev, queue_no); + EventNotifier *n = virtio_queue_get_guest_notifier(vq); VirtIOIRQFD *irqfd; int ret = 0; @@ -858,15 +836,14 @@ static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, event_notifier_set(n); } } else { - ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); + ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector); } return ret; } -static void virtio_pci_one_vector_mask(VirtIOPCIProxy *proxy, +static void virtio_pci_vq_vector_mask(VirtIOPCIProxy *proxy, unsigned int queue_no, - unsigned int vector, - EventNotifier *n) + unsigned int vector) { VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); @@ -877,7 +854,7 @@ static void virtio_pci_one_vector_mask(VirtIOPCIProxy *proxy, if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { k->guest_notifier_mask(vdev, queue_no, true); } else { - kvm_virtio_pci_irqfd_release(proxy, n, vector); + kvm_virtio_pci_irqfd_release(proxy, queue_no, vector); } } @@ -887,7 +864,6 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); VirtQueue *vq = virtio_vector_first_queue(vdev, vector); - EventNotifier *n; int ret, index, unmasked = 0; while (vq) { @@ -896,8 +872,7 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector, break; } if (index < proxy->nvqs_with_notifiers) { - n = virtio_queue_get_guest_notifier(vq); - ret = virtio_pci_one_vector_unmask(proxy, index, vector, msg, n); + ret = virtio_pci_vq_vector_unmask(proxy, index, vector, msg); if (ret < 0) { goto undo; } @@ -913,8 +888,7 @@ undo: while (vq && unmasked >= 0) { index = virtio_get_queue_index(vq); if (index < proxy->nvqs_with_notifiers) { - n = virtio_queue_get_guest_notifier(vq); - virtio_pci_one_vector_mask(proxy, index, vector, n); + virtio_pci_vq_vector_mask(proxy, index, vector); --unmasked; } vq = virtio_vector_next_queue(vq); @@ -927,17 +901,15 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector) VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev); VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); VirtQueue *vq = virtio_vector_first_queue(vdev, vector); - EventNotifier *n; int index; while (vq) { index = virtio_get_queue_index(vq); - n = virtio_queue_get_guest_notifier(vq); if (!virtio_queue_get_num(vdev, index)) { break; } if (index < proxy->nvqs_with_notifiers) { - virtio_pci_one_vector_mask(proxy, index, vector, n); + virtio_pci_vq_vector_mask(proxy, index, vector); } vq = virtio_vector_next_queue(vq); } @@ -953,17 +925,19 @@ static void virtio_pci_vector_poll(PCIDevice *dev, int queue_no; unsigned int vector; EventNotifier *notifier; - int ret; + VirtQueue *vq; for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) { - ret = virtio_pci_get_notifier(proxy, queue_no, ¬ifier, &vector); - if (ret < 0) { + if (!virtio_queue_get_num(vdev, queue_no)) { break; } + vector = virtio_queue_vector(vdev, queue_no); if (vector < vector_start || vector >= vector_end || !msix_is_masked(dev, vector)) { continue; } + vq = virtio_get_queue(vdev, queue_no); + notifier = virtio_queue_get_guest_notifier(vq); if (k->guest_notifier_pending) { if (k->guest_notifier_pending(vdev, queue_no)) { msix_set_pending(dev, vector); From a882b5712373171d3bd53cd82ddab4453ddef468 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 10 Jan 2022 00:47:56 -0500 Subject: [PATCH 380/730] Revert "virtio: introduce macro IRTIO_CONFIG_IRQ_IDX" This reverts commit bf1d85c166c19af95dbd27b1faba1d2909732323. Fixes: bf1d85c166 ("virtio: introduce macro IRTIO_CONFIG_IRQ_IDX") Cc: "Cindy Lu" Signed-off-by: Michael S. Tsirkin --- hw/display/vhost-user-gpu.c | 6 ------ hw/net/virtio-net.c | 10 ++-------- hw/virtio/vhost-user-fs.c | 6 ------ hw/virtio/vhost-vsock-common.c | 6 ------ hw/virtio/virtio-crypto.c | 6 ------ include/hw/virtio/virtio.h | 3 --- 6 files changed, 2 insertions(+), 35 deletions(-) diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index d4a440e815..09818231bd 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -485,9 +485,6 @@ vhost_user_gpu_guest_notifier_pending(VirtIODevice *vdev, int idx) { VhostUserGPU *g = VHOST_USER_GPU(vdev); - if (idx == VIRTIO_CONFIG_IRQ_IDX) { - return false; - } return vhost_virtqueue_pending(&g->vhost->dev, idx); } @@ -496,9 +493,6 @@ vhost_user_gpu_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask) { VhostUserGPU *g = VHOST_USER_GPU(vdev); - if (idx == VIRTIO_CONFIG_IRQ_IDX) { - return; - } vhost_virtqueue_mask(&g->vhost->dev, vdev, idx, mask); } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 5e03c0dd14..cf8ab0f8af 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -3168,9 +3168,6 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) VirtIONet *n = VIRTIO_NET(vdev); NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); assert(n->vhost_started); - if (idx == VIRTIO_CONFIG_IRQ_IDX) { - return false; - } return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx); } @@ -3180,11 +3177,8 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx, VirtIONet *n = VIRTIO_NET(vdev); NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx)); assert(n->vhost_started); - if (idx == VIRTIO_CONFIG_IRQ_IDX) { - return; - } - - vhost_net_virtqueue_mask(get_vhost_net(nc->peer), vdev, idx, mask); + vhost_net_virtqueue_mask(get_vhost_net(nc->peer), + vdev, idx, mask); } static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features) diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c index 9b0349922e..c595957983 100644 --- a/hw/virtio/vhost-user-fs.c +++ b/hw/virtio/vhost-user-fs.c @@ -161,9 +161,6 @@ static void vuf_guest_notifier_mask(VirtIODevice *vdev, int idx, { VHostUserFS *fs = VHOST_USER_FS(vdev); - if (idx == VIRTIO_CONFIG_IRQ_IDX) { - return; - } vhost_virtqueue_mask(&fs->vhost_dev, vdev, idx, mask); } @@ -171,9 +168,6 @@ static bool vuf_guest_notifier_pending(VirtIODevice *vdev, int idx) { VHostUserFS *fs = VHOST_USER_FS(vdev); - if (idx == VIRTIO_CONFIG_IRQ_IDX) { - return false; - } return vhost_virtqueue_pending(&fs->vhost_dev, idx); } diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c index d1b9c027b6..3f3771274e 100644 --- a/hw/virtio/vhost-vsock-common.c +++ b/hw/virtio/vhost-vsock-common.c @@ -125,9 +125,6 @@ static void vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx, { VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); - if (idx == VIRTIO_CONFIG_IRQ_IDX) { - return; - } vhost_virtqueue_mask(&vvc->vhost_dev, vdev, idx, mask); } @@ -136,9 +133,6 @@ static bool vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev, { VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); - if (idx == VIRTIO_CONFIG_IRQ_IDX) { - return false; - } return vhost_virtqueue_pending(&vvc->vhost_dev, idx); } diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c index 1d5192f8b4..54f9bbb789 100644 --- a/hw/virtio/virtio-crypto.c +++ b/hw/virtio/virtio-crypto.c @@ -948,9 +948,6 @@ static void virtio_crypto_guest_notifier_mask(VirtIODevice *vdev, int idx, assert(vcrypto->vhost_started); - if (idx == VIRTIO_CONFIG_IRQ_IDX) { - return; - } cryptodev_vhost_virtqueue_mask(vdev, queue, idx, mask); } @@ -961,9 +958,6 @@ static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx) assert(vcrypto->vhost_started); - if (idx == VIRTIO_CONFIG_IRQ_IDX) { - return false; - } return cryptodev_vhost_virtqueue_pending(vdev, queue, idx); } diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 605ea79c90..8bab9cfb75 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -67,9 +67,6 @@ typedef struct VirtQueueElement #define VIRTIO_NO_VECTOR 0xffff -/* special index value used internally for config irqs */ -#define VIRTIO_CONFIG_IRQ_IDX -1 - #define TYPE_VIRTIO_DEVICE "virtio-device" OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE) From f75b20e4f16663af4c65657821c5727b1d1c2493 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 14:13:47 -0500 Subject: [PATCH 381/730] python/aqmp: use absolute import statement pylint's dependency astroid appears to have bugs in 2.9.1 and 2.9.2 (Dec 31 and Jan 3) that appear to erroneously expect the qemu namespace to have an __init__.py file. astroid 2.9.3 (Jan 9) avoids that problem, but appears to not understand a relative import within a namespace package. Update the relative import - it was worth changing anyway, because these packages will eventually be packaged and distributed separately. Signed-off-by: John Snow Reviewed-by: Beraldo Leal Message-id: 20220110191349.1841027-2-jsnow@redhat.com Signed-off-by: John Snow --- python/qemu/aqmp/aqmp_tui.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/qemu/aqmp/aqmp_tui.py b/python/qemu/aqmp/aqmp_tui.py index a2929f771c..f1e926dd75 100644 --- a/python/qemu/aqmp/aqmp_tui.py +++ b/python/qemu/aqmp/aqmp_tui.py @@ -35,7 +35,8 @@ from pygments import token as Token import urwid import urwid_readline -from ..qmp import QEMUMonitorProtocol, QMPBadPortError +from qemu.qmp import QEMUMonitorProtocol, QMPBadPortError + from .error import ProtocolError from .message import DeserializationError, Message, UnexpectedTypeError from .protocol import ConnectError, Runstate From 42d73f2894ea1855df5a25d58e0d9eac6023dcc3 Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 14:13:48 -0500 Subject: [PATCH 382/730] Python/aqmp: fix type definitions for mypy 0.920 0.920 (Released 2021-12-15) is not entirely happy with the way that I was defining _FutureT: qemu/aqmp/protocol.py:601: error: Item "object" of the upper bound "Optional[Future[Any]]" of type variable "_FutureT" has no attribute "done" Update it with something a little mechanically simpler that works better across a wider array of mypy versions. Signed-off-by: John Snow Message-id: 20220110191349.1841027-3-jsnow@redhat.com Signed-off-by: John Snow --- python/qemu/aqmp/protocol.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/qemu/aqmp/protocol.py b/python/qemu/aqmp/protocol.py index 5190b33b13..c4fbe35a0e 100644 --- a/python/qemu/aqmp/protocol.py +++ b/python/qemu/aqmp/protocol.py @@ -43,8 +43,8 @@ from .util import ( T = TypeVar('T') +_U = TypeVar('_U') _TaskFN = Callable[[], Awaitable[None]] # aka ``async def func() -> None`` -_FutureT = TypeVar('_FutureT', bound=Optional['asyncio.Future[Any]']) class Runstate(Enum): @@ -591,7 +591,8 @@ class AsyncProtocol(Generic[T]): """ Fully reset this object to a clean state and return to `IDLE`. """ - def _paranoid_task_erase(task: _FutureT) -> Optional[_FutureT]: + def _paranoid_task_erase(task: Optional['asyncio.Future[_U]'] + ) -> Optional['asyncio.Future[_U]']: # Help to erase a task, ENSURING it is fully quiesced first. assert (task is None) or task.done() return None if (task and task.done()) else task From 366d33158cea72e80d80505f94c34cb505385c0a Mon Sep 17 00:00:00 2001 From: John Snow Date: Mon, 10 Jan 2022 14:13:49 -0500 Subject: [PATCH 383/730] python: update type hints for mypy 0.930 Mypy 0.930, released Dec 22, changes the way argparse objects are considered. Crafting a definition that works under Python 3.6 and an older mypy alongside newer versions simultaneously is ... difficult, so... eh. Stub it out with an 'Any' definition to get the CI moving again. Oh well. Signed-off-by: John Snow Reviewed-by: Beraldo Leal Message-id: 20220110191349.1841027-4-jsnow@redhat.com Signed-off-by: John Snow --- python/qemu/qmp/qom_common.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/python/qemu/qmp/qom_common.py b/python/qemu/qmp/qom_common.py index a59ae1a2a1..2e4c741f77 100644 --- a/python/qemu/qmp/qom_common.py +++ b/python/qemu/qmp/qom_common.py @@ -30,10 +30,6 @@ from typing import ( from . import QEMUMonitorProtocol, QMPError -# The following is needed only for a type alias. -Subparsers = argparse._SubParsersAction # pylint: disable=protected-access - - class ObjectPropertyInfo: """ Represents the return type from e.g. qom-list. @@ -89,7 +85,7 @@ class QOMCommand: self.qmp.connect() @classmethod - def register(cls, subparsers: Subparsers) -> None: + def register(cls, subparsers: Any) -> None: """ Register this command with the argument parser. From 9ebfc5a583d8aa94bf1bc37c1f71559187fd809c Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 7 Jan 2022 16:30:19 +0100 Subject: [PATCH 384/730] simplebench: Fix Python syntax error (reported by LGTM) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: b2fcb0c5754c2554b8406376e99a75e9e0a6b7bd Signed-off-by: Stefan Weil Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: John Snow Message-id: 20220107153019.504124-1-sw@weilnetz.de Signed-off-by: John Snow --- scripts/simplebench/bench-example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/simplebench/bench-example.py b/scripts/simplebench/bench-example.py index 4864435f39..fc370691e0 100644 --- a/scripts/simplebench/bench-example.py +++ b/scripts/simplebench/bench-example.py @@ -25,7 +25,7 @@ from bench_block_job import bench_block_copy, drv_file, drv_nbd def bench_func(env, case): """ Handle one "cell" of benchmarking table. """ - return bench_block_copy(env['qemu_binary'], env['cmd'], {} + return bench_block_copy(env['qemu_binary'], env['cmd'], {}, case['source'], case['target']) From d010b8bd93b833dcbe0addf54cbb7d763068e90d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:20 -0800 Subject: [PATCH 385/730] linux-user/alpha: Set TRAP_UNK for bugchk and unknown gentrap These si_codes were changed in 535906c684fca, for linux 4.17. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/alpha/cpu_loop.c | 4 ++-- linux-user/syscall_defs.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/linux-user/alpha/cpu_loop.c b/linux-user/alpha/cpu_loop.c index 37c33f0ccd..96466b23f9 100644 --- a/linux-user/alpha/cpu_loop.c +++ b/linux-user/alpha/cpu_loop.c @@ -86,7 +86,7 @@ void cpu_loop(CPUAlphaState *env) /* BUGCHK */ info.si_signo = TARGET_SIGTRAP; info.si_errno = 0; - info.si_code = 0; + info.si_code = TARGET_TRAP_UNK; info._sifields._sigfault._addr = env->pc; queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; @@ -155,7 +155,7 @@ void cpu_loop(CPUAlphaState *env) break; default: info.si_signo = TARGET_SIGTRAP; - info.si_code = 0; + info.si_code = TARGET_TRAP_UNK; break; } info.si_errno = 0; diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index cca561f622..18bed558fe 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -715,6 +715,7 @@ typedef struct target_siginfo { #define TARGET_TRAP_TRACE (2) /* process trace trap */ #define TARGET_TRAP_BRANCH (3) /* process taken branch trap */ #define TARGET_TRAP_HWBKPT (4) /* hardware breakpoint/watchpoint */ +#define TARGET_TRAP_UNK (5) /* undiagnosed trap */ struct target_rlimit { abi_ulong rlim_cur; From d9c5d7cf4d8e8668e178b1a0dfdb0eaa2d4f0f8f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:21 -0800 Subject: [PATCH 386/730] linux-user/alpha: Set FPE_FLTUNK for gentrap ROPRAND This si_code was changed in 4cc13e4f6d441, for linux 4.17. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/alpha/cpu_loop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/alpha/cpu_loop.c b/linux-user/alpha/cpu_loop.c index 96466b23f9..caeea97b9d 100644 --- a/linux-user/alpha/cpu_loop.c +++ b/linux-user/alpha/cpu_loop.c @@ -151,7 +151,7 @@ void cpu_loop(CPUAlphaState *env) info.si_code = TARGET_FPE_FLTRES; break; case TARGET_GEN_ROPRAND: - info.si_code = 0; + info.si_code = TARGET_FPE_FLTUNK; break; default: info.si_signo = TARGET_SIGTRAP; From 1c165977de21d02f8f1590499dd34fc748fbfffa Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:22 -0800 Subject: [PATCH 387/730] linux-user/alpha: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-4-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/alpha/cpu_loop.c | 61 ++++++++++++------------------------- 1 file changed, 19 insertions(+), 42 deletions(-) diff --git a/linux-user/alpha/cpu_loop.c b/linux-user/alpha/cpu_loop.c index caeea97b9d..de6e0c901c 100644 --- a/linux-user/alpha/cpu_loop.c +++ b/linux-user/alpha/cpu_loop.c @@ -27,8 +27,7 @@ void cpu_loop(CPUAlphaState *env) { CPUState *cs = env_cpu(env); - int trapnr; - target_siginfo_t info; + int trapnr, si_code; abi_long sysret; while (1) { @@ -56,18 +55,10 @@ void cpu_loop(CPUAlphaState *env) break; case EXCP_OPCDEC: do_sigill: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPC; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); break; case EXCP_ARITH: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = TARGET_FPE_FLTINV; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_FLTINV, env->pc); break; case EXCP_FEN: /* No-op. Linux simply re-enables the FPU. */ @@ -76,20 +67,10 @@ void cpu_loop(CPUAlphaState *env) switch (env->error_code) { case 0x80: /* BPT */ - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; + goto do_sigtrap_brkpt; case 0x81: /* BUGCHK */ - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_UNK; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; + goto do_sigtrap_unk; case 0x83: /* CALLSYS */ trapnr = env->ir[IR_V0]; @@ -130,47 +111,43 @@ void cpu_loop(CPUAlphaState *env) abort(); case 0xAA: /* GENTRAP */ - info.si_signo = TARGET_SIGFPE; switch (env->ir[IR_A0]) { case TARGET_GEN_INTOVF: - info.si_code = TARGET_FPE_INTOVF; + si_code = TARGET_FPE_INTOVF; break; case TARGET_GEN_INTDIV: - info.si_code = TARGET_FPE_INTDIV; + si_code = TARGET_FPE_INTDIV; break; case TARGET_GEN_FLTOVF: - info.si_code = TARGET_FPE_FLTOVF; + si_code = TARGET_FPE_FLTOVF; break; case TARGET_GEN_FLTUND: - info.si_code = TARGET_FPE_FLTUND; + si_code = TARGET_FPE_FLTUND; break; case TARGET_GEN_FLTINV: - info.si_code = TARGET_FPE_FLTINV; + si_code = TARGET_FPE_FLTINV; break; case TARGET_GEN_FLTINE: - info.si_code = TARGET_FPE_FLTRES; + si_code = TARGET_FPE_FLTRES; break; case TARGET_GEN_ROPRAND: - info.si_code = TARGET_FPE_FLTUNK; + si_code = TARGET_FPE_FLTUNK; break; default: - info.si_signo = TARGET_SIGTRAP; - info.si_code = TARGET_TRAP_UNK; - break; + goto do_sigtrap_unk; } - info.si_errno = 0; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, si_code, env->pc); break; default: goto do_sigill; } break; case EXCP_DEBUG: - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + do_sigtrap_brkpt: + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); + break; + do_sigtrap_unk: + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_UNK, env->pc); break; case EXCP_INTERRUPT: /* Just indicate that signals should be handled asap. */ From 32e321861d43d4b7fec813f3884562bc58dce4fe Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:23 -0800 Subject: [PATCH 388/730] linux-user/cris: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Fill in the missing PC for SIGTRAP. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-5-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/cris/cpu_loop.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/linux-user/cris/cpu_loop.c b/linux-user/cris/cpu_loop.c index 5213aebf55..0f46b3c1a8 100644 --- a/linux-user/cris/cpu_loop.c +++ b/linux-user/cris/cpu_loop.c @@ -28,8 +28,7 @@ void cpu_loop(CPUCRISState *env) { CPUState *cs = env_cpu(env); int trapnr, ret; - target_siginfo_t info; - + while (1) { cpu_exec_start(cs); trapnr = cpu_exec(cs); @@ -38,8 +37,8 @@ void cpu_loop(CPUCRISState *env) switch (trapnr) { case EXCP_INTERRUPT: - /* just indicate that signals should be handled asap */ - break; + /* just indicate that signals should be handled asap */ + break; case EXCP_BREAK: ret = do_syscall(env, env->regs[9], @@ -57,10 +56,7 @@ void cpu_loop(CPUCRISState *env) } break; case EXCP_DEBUG: - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); From f64859684a6fa37bbf6118ca732af7ae70617990 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:24 -0800 Subject: [PATCH 389/730] linux-user/hppa: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Fill in the missing PC for SIGTRAP and missing si_code for SIGBUS. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-6-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/hppa/cpu_loop.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c index a47a63176b..4740da1b7a 100644 --- a/linux-user/hppa/cpu_loop.c +++ b/linux-user/hppa/cpu_loop.c @@ -110,7 +110,6 @@ static abi_ulong hppa_lws(CPUHPPAState *env) void cpu_loop(CPUHPPAState *env) { CPUState *cs = env_cpu(env); - target_siginfo_t info; abi_ulong ret; int trapnr; @@ -147,26 +146,15 @@ void cpu_loop(CPUHPPAState *env) case EXCP_ILL: case EXCP_PRIV_OPR: case EXCP_PRIV_REG: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPN; - info._sifields._sigfault._addr = env->iaoq_f; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->iaoq_f); break; case EXCP_OVERFLOW: case EXCP_COND: case EXCP_ASSIST: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = 0; - info._sifields._sigfault._addr = env->iaoq_f; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f); break; case EXCP_DEBUG: - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f); break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ From 7337adeac0900a944ba789ad24b11c6a00099897 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:25 -0800 Subject: [PATCH 390/730] linux-user/hppa: Use the proper si_code for PRIV_OPR, PRIV_REG, OVERFLOW These si_codes have been properly set by the kernel since the beginning. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-7-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/hppa/cpu_loop.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c index 4740da1b7a..a65e1571a0 100644 --- a/linux-user/hppa/cpu_loop.c +++ b/linux-user/hppa/cpu_loop.c @@ -144,11 +144,17 @@ void cpu_loop(CPUHPPAState *env) env->iaoq_b = env->gr[31] + 4; break; case EXCP_ILL: - case EXCP_PRIV_OPR: - case EXCP_PRIV_REG: force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->iaoq_f); break; + case EXCP_PRIV_OPR: + force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f); + break; + case EXCP_PRIV_REG: + force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVREG, env->iaoq_f); + break; case EXCP_OVERFLOW: + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->iaoq_f); + break; case EXCP_COND: case EXCP_ASSIST: force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f); From 6ac3bf1f55a007b8ee55b3794d542144615c762e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:26 -0800 Subject: [PATCH 391/730] linux-user: Remove TARGET_NSIGFPE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This define is unused, and we have no similar define for the other signal sub-codes. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-8-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall_defs.h | 1 - 1 file changed, 1 deletion(-) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 18bed558fe..510a8c1ab5 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -688,7 +688,6 @@ typedef struct target_siginfo { #define TARGET_FPE_FLTINV (7) /* floating point invalid operation */ #define TARGET_FPE_FLTSUB (8) /* subscript out of range */ #define TARGET_FPE_FLTUNK (14) /* undiagnosed fp exception */ -#define TARGET_NSIGFPE 15 /* * SIGSEGV si_codes From 0edf34c93ed0cd35be3bb6c67f3044b10dcd29f3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:27 -0800 Subject: [PATCH 392/730] linux-user/hppa: Set FPE_CONDTRAP for COND MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This si_code was changed in 75abf64287cab, for linux 4.17. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-9-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/hppa/cpu_loop.c | 2 ++ linux-user/syscall_defs.h | 1 + 2 files changed, 3 insertions(+) diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c index a65e1571a0..a576d1a249 100644 --- a/linux-user/hppa/cpu_loop.c +++ b/linux-user/hppa/cpu_loop.c @@ -156,6 +156,8 @@ void cpu_loop(CPUHPPAState *env) force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->iaoq_f); break; case EXCP_COND: + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_CONDTRAP, env->iaoq_f); + break; case EXCP_ASSIST: force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f); break; diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 510a8c1ab5..f23f0a2178 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -688,6 +688,7 @@ typedef struct target_siginfo { #define TARGET_FPE_FLTINV (7) /* floating point invalid operation */ #define TARGET_FPE_FLTSUB (8) /* subscript out of range */ #define TARGET_FPE_FLTUNK (14) /* undiagnosed fp exception */ +#define TARGET_FPE_CONDTRAP (15) /* trap on condition */ /* * SIGSEGV si_codes From 1ade5b2fed4966a05cfde6261e4a67c27e715fac Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:28 -0800 Subject: [PATCH 393/730] linux-user/i386: Split out maybe_handle_vm86_trap Reduce the number of ifdefs within cpu_loop(). Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-10-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/i386/cpu_loop.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c index 9aaae93e2f..ac0f4e3211 100644 --- a/linux-user/i386/cpu_loop.c +++ b/linux-user/i386/cpu_loop.c @@ -198,6 +198,17 @@ static void emulate_vsyscall(CPUX86State *env) } #endif +static bool maybe_handle_vm86_trap(CPUX86State *env, int trapnr) +{ +#ifndef TARGET_X86_64 + if (env->eflags & VM_MASK) { + handle_vm86_trap(env, trapnr); + return true; + } +#endif + return false; +} + void cpu_loop(CPUX86State *env) { CPUState *cs = env_cpu(env); @@ -259,12 +270,9 @@ void cpu_loop(CPUX86State *env) break; case EXCP0D_GPF: /* XXX: potential problem if ABI32 */ -#ifndef TARGET_X86_64 - if (env->eflags & VM_MASK) { - handle_vm86_fault(env); + if (maybe_handle_vm86_trap(env, trapnr)) { break; } -#endif gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0); break; case EXCP0E_PAGE: @@ -274,22 +282,16 @@ void cpu_loop(CPUX86State *env) env->cr[2]); break; case EXCP00_DIVZ: -#ifndef TARGET_X86_64 - if (env->eflags & VM_MASK) { - handle_vm86_trap(env, trapnr); + if (maybe_handle_vm86_trap(env, trapnr)) { break; } -#endif gen_signal(env, TARGET_SIGFPE, TARGET_FPE_INTDIV, env->eip); break; case EXCP01_DB: case EXCP03_INT3: -#ifndef TARGET_X86_64 - if (env->eflags & VM_MASK) { - handle_vm86_trap(env, trapnr); + if (maybe_handle_vm86_trap(env, trapnr)) { break; } -#endif if (trapnr == EXCP01_DB) { gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip); } else { @@ -298,12 +300,9 @@ void cpu_loop(CPUX86State *env) break; case EXCP04_INTO: case EXCP05_BOUND: -#ifndef TARGET_X86_64 - if (env->eflags & VM_MASK) { - handle_vm86_trap(env, trapnr); + if (maybe_handle_vm86_trap(env, trapnr)) { break; } -#endif gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0); break; case EXCP06_ILLOP: From d08d6d66f6a999ce84c805ed1fb5380ff157a6e8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:29 -0800 Subject: [PATCH 394/730] linux-user/i386: Use force_sig, force_sig_fault Replace the local gen_signal with the generic functions that match how the kernel raises signals. Fill in the missing PC for SIGTRAP. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-11-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/i386/cpu_loop.c | 47 +++++++++++++++----------------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c index ac0f4e3211..29dfd7cd0c 100644 --- a/linux-user/i386/cpu_loop.c +++ b/linux-user/i386/cpu_loop.c @@ -84,17 +84,6 @@ static void set_idt(int n, unsigned int dpl) } #endif -static void gen_signal(CPUX86State *env, int sig, int code, abi_ptr addr) -{ - target_siginfo_t info = { - .si_signo = sig, - .si_code = code, - ._sifields._sigfault._addr = addr - }; - - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); -} - #ifdef TARGET_X86_64 static bool write_ok_or_segv(CPUX86State *env, abi_ptr addr, size_t len) { @@ -107,7 +96,7 @@ static bool write_ok_or_segv(CPUX86State *env, abi_ptr addr, size_t len) } env->error_code = PG_ERROR_W_MASK | PG_ERROR_U_MASK; - gen_signal(env, TARGET_SIGSEGV, TARGET_SEGV_MAPERR, addr); + force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, addr); return false; } @@ -193,8 +182,7 @@ static void emulate_vsyscall(CPUX86State *env) return; sigsegv: - /* Like force_sig(SIGSEGV). */ - gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0); + force_sig(TARGET_SIGSEGV); } #endif @@ -266,53 +254,54 @@ void cpu_loop(CPUX86State *env) #endif case EXCP0B_NOSEG: case EXCP0C_STACK: - gen_signal(env, TARGET_SIGBUS, TARGET_SI_KERNEL, 0); + force_sig(TARGET_SIGBUS); break; case EXCP0D_GPF: /* XXX: potential problem if ABI32 */ if (maybe_handle_vm86_trap(env, trapnr)) { break; } - gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0); + force_sig(TARGET_SIGSEGV); break; case EXCP0E_PAGE: - gen_signal(env, TARGET_SIGSEGV, - (env->error_code & 1 ? - TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR), - env->cr[2]); + force_sig_fault(TARGET_SIGSEGV, + (env->error_code & PG_ERROR_P_MASK ? + TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR), + env->cr[2]); break; case EXCP00_DIVZ: if (maybe_handle_vm86_trap(env, trapnr)) { break; } - gen_signal(env, TARGET_SIGFPE, TARGET_FPE_INTDIV, env->eip); + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->eip); break; case EXCP01_DB: + if (maybe_handle_vm86_trap(env, trapnr)) { + break; + } + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip); + break; case EXCP03_INT3: if (maybe_handle_vm86_trap(env, trapnr)) { break; } - if (trapnr == EXCP01_DB) { - gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip); - } else { - gen_signal(env, TARGET_SIGTRAP, TARGET_SI_KERNEL, 0); - } + force_sig(TARGET_SIGTRAP); break; case EXCP04_INTO: case EXCP05_BOUND: if (maybe_handle_vm86_trap(env, trapnr)) { break; } - gen_signal(env, TARGET_SIGSEGV, TARGET_SI_KERNEL, 0); + force_sig(TARGET_SIGSEGV); break; case EXCP06_ILLOP: - gen_signal(env, TARGET_SIGILL, TARGET_ILL_ILLOPN, env->eip); + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->eip); break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; case EXCP_DEBUG: - gen_signal(env, TARGET_SIGTRAP, TARGET_TRAP_BRKPT, 0); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->eip); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); From 71dc6f7488d5dd18b92bbe54cbb165132332a17c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:30 -0800 Subject: [PATCH 395/730] linux-user/m68k: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Fill in the missing PC for SIGTRAP. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-12-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/m68k/cpu_loop.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/linux-user/m68k/cpu_loop.c b/linux-user/m68k/cpu_loop.c index 3181594414..928a18e3cf 100644 --- a/linux-user/m68k/cpu_loop.c +++ b/linux-user/m68k/cpu_loop.c @@ -29,7 +29,6 @@ void cpu_loop(CPUM68KState *env) CPUState *cs = env_cpu(env); int trapnr; unsigned int n; - target_siginfo_t info; for(;;) { cpu_exec_start(cs); @@ -46,25 +45,13 @@ void cpu_loop(CPUM68KState *env) case EXCP_ILLEGAL: case EXCP_LINEA: case EXCP_LINEF: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPN; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc); break; case EXCP_CHK: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = TARGET_FPE_INTOVF; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->pc); break; case EXCP_DIV0: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = TARGET_FPE_INTDIV; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc); break; case EXCP_TRAP0: { @@ -91,10 +78,7 @@ void cpu_loop(CPUM68KState *env) /* just indicate that signals should be handled asap */ break; case EXCP_DEBUG: - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); From 23ae825ab7af5e0a30c2d051e388e4e6aa618878 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:31 -0800 Subject: [PATCH 396/730] linux-user/microblaze: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Fill in the missing PC for SIGTRAP. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-13-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/microblaze/cpu_loop.c | 61 +++++++++++++------------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/linux-user/microblaze/cpu_loop.c b/linux-user/microblaze/cpu_loop.c index ff1fb26c8b..08620d4e68 100644 --- a/linux-user/microblaze/cpu_loop.c +++ b/linux-user/microblaze/cpu_loop.c @@ -27,9 +27,8 @@ void cpu_loop(CPUMBState *env) { CPUState *cs = env_cpu(env); - int trapnr, ret; - target_siginfo_t info; - + int trapnr, ret, si_code; + while (1) { cpu_exec_start(cs); trapnr = cpu_exec(cs); @@ -38,8 +37,8 @@ void cpu_loop(CPUMBState *env) switch (trapnr) { case EXCP_INTERRUPT: - /* just indicate that signals should be handled asap */ - break; + /* just indicate that signals should be handled asap */ + break; case EXCP_SYSCALL: /* Return address is 4 bytes after the call. */ env->regs[14] += 4; @@ -67,6 +66,7 @@ void cpu_loop(CPUMBState *env) */ env->regs[14] = env->pc; break; + case EXCP_HW_EXCP: env->regs[17] = env->pc + 4; if (env->iflags & D_FLAG) { @@ -74,42 +74,31 @@ void cpu_loop(CPUMBState *env) env->pc -= 4; /* FIXME: if branch was immed, replay the imm as well. */ } - env->iflags &= ~(IMM_FLAG | D_FLAG); - switch (env->esr & 31) { - case ESR_EC_DIVZERO: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = TARGET_FPE_FLTDIV; - info._sifields._sigfault._addr = 0; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; - case ESR_EC_FPU: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - if (env->fsr & FSR_IO) { - info.si_code = TARGET_FPE_FLTINV; - } - if (env->fsr & FSR_DZ) { - info.si_code = TARGET_FPE_FLTDIV; - } - info._sifields._sigfault._addr = 0; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; - default: - fprintf(stderr, "Unhandled hw-exception: 0x%x\n", - env->esr & ESR_EC_MASK); - cpu_dump_state(cs, stderr, 0); - exit(EXIT_FAILURE); - break; + case ESR_EC_DIVZERO: + si_code = TARGET_FPE_FLTDIV; + break; + case ESR_EC_FPU: + si_code = 0; + if (env->fsr & FSR_IO) { + si_code = TARGET_FPE_FLTINV; + } + if (env->fsr & FSR_DZ) { + si_code = TARGET_FPE_FLTDIV; + } + break; + default: + fprintf(stderr, "Unhandled hw-exception: 0x%x\n", + env->esr & ESR_EC_MASK); + cpu_dump_state(cs, stderr, 0); + exit(EXIT_FAILURE); } + force_sig_fault(TARGET_SIGFPE, si_code, env->pc); break; + case EXCP_DEBUG: - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); From 0b25c4a1f6345994d103ad08b2f4e1b366131dd9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:32 -0800 Subject: [PATCH 397/730] linux-user/microblaze: Fix SIGFPE si_codes Fix a typo for ESR_EC_DIVZERO, which is integral not floating-point. Fix the if ladder for decoding floating-point exceptions. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-14-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/microblaze/cpu_loop.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/linux-user/microblaze/cpu_loop.c b/linux-user/microblaze/cpu_loop.c index 08620d4e68..1a2556be2c 100644 --- a/linux-user/microblaze/cpu_loop.c +++ b/linux-user/microblaze/cpu_loop.c @@ -77,15 +77,25 @@ void cpu_loop(CPUMBState *env) env->iflags &= ~(IMM_FLAG | D_FLAG); switch (env->esr & 31) { case ESR_EC_DIVZERO: - si_code = TARGET_FPE_FLTDIV; + si_code = TARGET_FPE_INTDIV; break; case ESR_EC_FPU: - si_code = 0; - if (env->fsr & FSR_IO) { + /* + * Note that the kernel passes along fsr as si_code + * if there's no recognized bit set. Possibly this + * implies that si_code is 0, but follow the structure. + */ + si_code = env->fsr; + if (si_code & FSR_IO) { si_code = TARGET_FPE_FLTINV; - } - if (env->fsr & FSR_DZ) { + } else if (si_code & FSR_OF) { + si_code = TARGET_FPE_FLTOVF; + } else if (si_code & FSR_UF) { + si_code = TARGET_FPE_FLTUND; + } else if (si_code & FSR_DZ) { si_code = TARGET_FPE_FLTDIV; + } else if (si_code & FSR_DO) { + si_code = TARGET_FPE_FLTRES; } break; default: From bf19bdb8f39a3aeb1353d412669b958c2b6cece8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:33 -0800 Subject: [PATCH 398/730] linux-user/mips: Improve do_break MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename to do_tr_or_bp, as per the kernel function. Add a 'trap' argument, akin to the kernel's si_code, but clearer. The return value is always 0, so change the return value to void. Use force_sig and force_sig_fault. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-15-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/mips/cpu_loop.c | 46 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index 32f9fc1c1c..4fa24cc074 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -40,29 +40,25 @@ enum { BRK_DIVZERO = 7 }; -static int do_break(CPUMIPSState *env, target_siginfo_t *info, - unsigned int code) +static void do_tr_or_bp(CPUMIPSState *env, unsigned int code, bool trap) { - int ret = -1; + target_ulong pc = env->active_tc.PC; switch (code) { case BRK_OVERFLOW: + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, pc); + break; case BRK_DIVZERO: - info->si_signo = TARGET_SIGFPE; - info->si_errno = 0; - info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; - queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); - ret = 0; + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, pc); break; default: - info->si_signo = TARGET_SIGTRAP; - info->si_errno = 0; - queue_signal(env, info->si_signo, QEMU_SI_FAULT, &*info); - ret = 0; + if (trap) { + force_sig(TARGET_SIGTRAP); + } else { + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, pc); + } break; } - - return ret; } void cpu_loop(CPUMIPSState *env) @@ -205,6 +201,13 @@ done_syscall: abi_ulong trap_instr; unsigned int code; + /* + * FIXME: It would be better to decode the trap number + * during translate, and store it in error_code while + * raising the exception. We should not be re-reading + * the opcode here. + */ + if (env->hflags & MIPS_HFLAG_M16) { if (env->insn_flags & ASE_MICROMIPS) { /* microMIPS mode */ @@ -257,9 +260,7 @@ done_syscall: } } - if (do_break(env, &info, code) != 0) { - goto error; - } + do_tr_or_bp(env, code, false); } break; case EXCP_TRAP: @@ -267,6 +268,13 @@ done_syscall: abi_ulong trap_instr; unsigned int code = 0; + /* + * FIXME: It would be better to decode the trap number + * during translate, and store it in error_code while + * raising the exception. We should not be re-reading + * the opcode here. + */ + if (env->hflags & MIPS_HFLAG_M16) { /* microMIPS mode */ abi_ulong instr[2]; @@ -293,9 +301,7 @@ done_syscall: } } - if (do_break(env, &info, code) != 0) { - goto error; - } + do_tr_or_bp(env, code, true); } break; case EXCP_ATOMIC: From 73c0aa6a85253d1d5df6a7dfa14c7568e084cf96 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:34 -0800 Subject: [PATCH 399/730] linux-user/mips: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Fill in the missing PC for SIGTRAP and SIGFPE; use force_sig (SI_KERNEL) for EXCP_DSPDIS. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-16-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/mips/cpu_loop.c | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index 4fa24cc074..1286fbc2e0 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -64,8 +64,7 @@ static void do_tr_or_bp(CPUMIPSState *env, unsigned int code, bool trap) void cpu_loop(CPUMIPSState *env) { CPUState *cs = env_cpu(env); - target_siginfo_t info; - int trapnr; + int trapnr, si_code; abi_long ret; # ifdef TARGET_ABI_MIPSO32 unsigned int syscall_num; @@ -156,43 +155,32 @@ done_syscall: break; case EXCP_CpU: case EXCP_RI: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = 0; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + case EXCP_DSPDIS: + force_sig(TARGET_SIGILL); break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; case EXCP_DEBUG: - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; - case EXCP_DSPDIS: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPC; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, + env->active_tc.PC); break; case EXCP_FPE: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = TARGET_FPE_FLTUNK; + si_code = TARGET_FPE_FLTUNK; if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) { - info.si_code = TARGET_FPE_FLTINV; + si_code = TARGET_FPE_FLTINV; } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_DIV0) { - info.si_code = TARGET_FPE_FLTDIV; + si_code = TARGET_FPE_FLTDIV; } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_OVERFLOW) { - info.si_code = TARGET_FPE_FLTOVF; + si_code = TARGET_FPE_FLTOVF; } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_UNDERFLOW) { - info.si_code = TARGET_FPE_FLTUND; + si_code = TARGET_FPE_FLTUND; } else if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INEXACT) { - info.si_code = TARGET_FPE_FLTRES; + si_code = TARGET_FPE_FLTRES; } - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, si_code, env->active_tc.PC); break; + /* The code below was inspired by the MIPS Linux kernel trap * handling code in arch/mips/kernel/traps.c. */ From 6f3533dd1b6afbce8d215bb89027fa5b7caa4168 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:35 -0800 Subject: [PATCH 400/730] target/mips: Extract break code into env->error_code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify cpu_loop by doing all of the decode in translate. This fixes a bug in that cpu_loop was not handling the different layout of the R6 version of break16. This fixes a bug in that cpu_loop extracted the wrong bits for the mips16e break16 instruction. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-17-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/mips/cpu_loop.c | 73 +++-------------------- target/mips/tcg/micromips_translate.c.inc | 6 +- target/mips/tcg/mips16e_translate.c.inc | 2 +- target/mips/tcg/translate.c | 12 +++- target/mips/tcg/translate.h | 1 + 5 files changed, 25 insertions(+), 69 deletions(-) diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index 1286fbc2e0..9a6ab2dd98 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -65,6 +65,7 @@ void cpu_loop(CPUMIPSState *env) { CPUState *cs = env_cpu(env); int trapnr, si_code; + unsigned int code; abi_long ret; # ifdef TARGET_ABI_MIPSO32 unsigned int syscall_num; @@ -185,71 +186,15 @@ done_syscall: * handling code in arch/mips/kernel/traps.c. */ case EXCP_BREAK: - { - abi_ulong trap_instr; - unsigned int code; - - /* - * FIXME: It would be better to decode the trap number - * during translate, and store it in error_code while - * raising the exception. We should not be re-reading - * the opcode here. - */ - - if (env->hflags & MIPS_HFLAG_M16) { - if (env->insn_flags & ASE_MICROMIPS) { - /* microMIPS mode */ - ret = get_user_u16(trap_instr, env->active_tc.PC); - if (ret != 0) { - goto error; - } - - if ((trap_instr >> 10) == 0x11) { - /* 16-bit instruction */ - code = trap_instr & 0xf; - } else { - /* 32-bit instruction */ - abi_ulong instr_lo; - - ret = get_user_u16(instr_lo, - env->active_tc.PC + 2); - if (ret != 0) { - goto error; - } - trap_instr = (trap_instr << 16) | instr_lo; - code = ((trap_instr >> 6) & ((1 << 20) - 1)); - /* Unfortunately, microMIPS also suffers from - the old assembler bug... */ - if (code >= (1 << 10)) { - code >>= 10; - } - } - } else { - /* MIPS16e mode */ - ret = get_user_u16(trap_instr, env->active_tc.PC); - if (ret != 0) { - goto error; - } - code = (trap_instr >> 6) & 0x3f; - } - } else { - ret = get_user_u32(trap_instr, env->active_tc.PC); - if (ret != 0) { - goto error; - } - - /* As described in the original Linux kernel code, the - * below checks on 'code' are to work around an old - * assembly bug. - */ - code = ((trap_instr >> 6) & ((1 << 20) - 1)); - if (code >= (1 << 10)) { - code >>= 10; - } - } - - do_tr_or_bp(env, code, false); + /* + * As described in the original Linux kernel code, the below + * checks on 'code' are to work around an old assembly bug. + */ + code = env->error_code; + if (code >= (1 << 10)) { + code >>= 10; } + do_tr_or_bp(env, code, false); break; case EXCP_TRAP: { diff --git a/target/mips/tcg/micromips_translate.c.inc b/target/mips/tcg/micromips_translate.c.inc index 0760941431..9013f84037 100644 --- a/target/mips/tcg/micromips_translate.c.inc +++ b/target/mips/tcg/micromips_translate.c.inc @@ -822,7 +822,7 @@ static void gen_pool16c_insn(DisasContext *ctx) gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode)); break; case BREAK16: - generate_exception_end(ctx, EXCP_BREAK); + generate_exception_break(ctx, extract32(ctx->opcode, 0, 4)); break; case SDBBP16: if (is_uhi(extract32(ctx->opcode, 0, 4))) { @@ -937,7 +937,7 @@ static void gen_pool16c_r6_insn(DisasContext *ctx) break; case R6_BREAK16: /* BREAK16 */ - generate_exception(ctx, EXCP_BREAK); + generate_exception_break(ctx, extract32(ctx->opcode, 6, 4)); break; case R6_SDBBP16: /* SDBBP16 */ @@ -1812,7 +1812,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) gen_pool32axf(env, ctx, rt, rs); break; case BREAK32: - generate_exception_end(ctx, EXCP_BREAK); + generate_exception_break(ctx, extract32(ctx->opcode, 6, 20)); break; case SIGRIE: check_insn(ctx, ISA_MIPS_R6); diff --git a/target/mips/tcg/mips16e_translate.c.inc b/target/mips/tcg/mips16e_translate.c.inc index 84d816603a..f57e0a5f2a 100644 --- a/target/mips/tcg/mips16e_translate.c.inc +++ b/target/mips/tcg/mips16e_translate.c.inc @@ -969,7 +969,7 @@ static int decode_ase_mips16e(CPUMIPSState *env, DisasContext *ctx) gen_slt(ctx, OPC_SLTU, 24, rx, ry); break; case RR_BREAK: - generate_exception_end(ctx, EXCP_BREAK); + generate_exception_break(ctx, extract32(ctx->opcode, 5, 6)); break; case RR_SLLV: gen_shift(ctx, OPC_SLLV, ry, rx, ry); diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 1c2264417c..7f0cc81a90 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -1367,6 +1367,16 @@ void generate_exception_end(DisasContext *ctx, int excp) generate_exception_err(ctx, excp, 0); } +void generate_exception_break(DisasContext *ctx, int code) +{ +#ifdef CONFIG_USER_ONLY + /* Pass the break code along to cpu_loop. */ + tcg_gen_st_i32(tcg_constant_i32(code), cpu_env, + offsetof(CPUMIPSState, error_code)); +#endif + generate_exception_end(ctx, EXCP_BREAK); +} + void gen_reserved_instruction(DisasContext *ctx) { generate_exception_end(ctx, EXCP_RI); @@ -14160,7 +14170,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) generate_exception_end(ctx, EXCP_SYSCALL); break; case OPC_BREAK: - generate_exception_end(ctx, EXCP_BREAK); + generate_exception_break(ctx, extract32(ctx->opcode, 6, 20)); break; case OPC_SYNC: check_insn(ctx, ISA_MIPS2); diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h index 6111493651..ae01515efe 100644 --- a/target/mips/tcg/translate.h +++ b/target/mips/tcg/translate.h @@ -129,6 +129,7 @@ enum { void generate_exception(DisasContext *ctx, int excp); void generate_exception_err(DisasContext *ctx, int excp, int err); void generate_exception_end(DisasContext *ctx, int excp); +void generate_exception_break(DisasContext *ctx, int code); void gen_reserved_instruction(DisasContext *ctx); void check_insn(DisasContext *ctx, uint64_t flags); From 0a3336f6fd7b38d058044504758eef49aa9b03eb Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:36 -0800 Subject: [PATCH 401/730] target/mips: Extract trap code into env->error_code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify cpu_loop by doing all of the decode in translate. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-18-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/mips/cpu_loop.c | 41 +---------------------- target/mips/tcg/micromips_translate.c.inc | 4 +-- target/mips/tcg/nanomips_translate.c.inc | 4 +-- target/mips/tcg/translate.c | 24 ++++++++++--- 4 files changed, 25 insertions(+), 48 deletions(-) diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index 9a6ab2dd98..9bb12a07ba 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -197,51 +197,12 @@ done_syscall: do_tr_or_bp(env, code, false); break; case EXCP_TRAP: - { - abi_ulong trap_instr; - unsigned int code = 0; - - /* - * FIXME: It would be better to decode the trap number - * during translate, and store it in error_code while - * raising the exception. We should not be re-reading - * the opcode here. - */ - - if (env->hflags & MIPS_HFLAG_M16) { - /* microMIPS mode */ - abi_ulong instr[2]; - - ret = get_user_u16(instr[0], env->active_tc.PC) || - get_user_u16(instr[1], env->active_tc.PC + 2); - - trap_instr = (instr[0] << 16) | instr[1]; - } else { - ret = get_user_u32(trap_instr, env->active_tc.PC); - } - - if (ret != 0) { - goto error; - } - - /* The immediate versions don't provide a code. */ - if (!(trap_instr & 0xFC000000)) { - if (env->hflags & MIPS_HFLAG_M16) { - /* microMIPS mode */ - code = ((trap_instr >> 12) & ((1 << 4) - 1)); - } else { - code = ((trap_instr >> 6) & ((1 << 10) - 1)); - } - } - - do_tr_or_bp(env, code, true); - } + do_tr_or_bp(env, env->error_code, true); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); break; default: -error: EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); abort(); } diff --git a/target/mips/tcg/micromips_translate.c.inc b/target/mips/tcg/micromips_translate.c.inc index 9013f84037..fc6ede75b8 100644 --- a/target/mips/tcg/micromips_translate.c.inc +++ b/target/mips/tcg/micromips_translate.c.inc @@ -1047,7 +1047,7 @@ static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs) case TNE: mips32_op = OPC_TNE; do_trap: - gen_trap(ctx, mips32_op, rs, rt, -1); + gen_trap(ctx, mips32_op, rs, rt, -1, extract32(ctx->opcode, 12, 4)); break; #ifndef CONFIG_USER_ONLY case MFC0: @@ -2439,7 +2439,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) check_insn_opc_removed(ctx, ISA_MIPS_R6); mips32_op = OPC_TEQI; do_trapi: - gen_trap(ctx, mips32_op, rs, -1, imm); + gen_trap(ctx, mips32_op, rs, -1, imm, 0); break; case BNEZC: diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc index 2c022a49f2..916cece4d2 100644 --- a/target/mips/tcg/nanomips_translate.c.inc +++ b/target/mips/tcg/nanomips_translate.c.inc @@ -1268,11 +1268,11 @@ static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx) switch (extract32(ctx->opcode, 10, 1)) { case NM_TEQ: check_nms(ctx); - gen_trap(ctx, OPC_TEQ, rs, rt, -1); + gen_trap(ctx, OPC_TEQ, rs, rt, -1, rd); break; case NM_TNE: check_nms(ctx); - gen_trap(ctx, OPC_TNE, rs, rt, -1); + gen_trap(ctx, OPC_TNE, rs, rt, -1, rd); break; } break; diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 7f0cc81a90..b82a7ec6ad 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -4733,7 +4733,7 @@ static void gen_loongson_lsdc2(DisasContext *ctx, int rt, /* Traps */ static void gen_trap(DisasContext *ctx, uint32_t opc, - int rs, int rt, int16_t imm) + int rs, int rt, int16_t imm, int code) { int cond; TCGv t0 = tcg_temp_new(); @@ -4778,6 +4778,11 @@ static void gen_trap(DisasContext *ctx, uint32_t opc, case OPC_TGEU: /* rs >= rs unsigned */ case OPC_TGEIU: /* r0 >= 0 unsigned */ /* Always trap */ +#ifdef CONFIG_USER_ONLY + /* Pass the break code along to cpu_loop. */ + tcg_gen_st_i32(tcg_constant_i32(code), cpu_env, + offsetof(CPUMIPSState, error_code)); +#endif generate_exception_end(ctx, EXCP_TRAP); break; case OPC_TLT: /* rs < rs */ @@ -4818,6 +4823,18 @@ static void gen_trap(DisasContext *ctx, uint32_t opc, tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1); break; } +#ifdef CONFIG_USER_ONLY + /* Pass the break code along to cpu_loop. */ + tcg_gen_st_i32(tcg_constant_i32(code), cpu_env, + offsetof(CPUMIPSState, error_code)); +#endif + /* Like save_cpu_state, only don't update saved values. */ + if (ctx->base.pc_next != ctx->saved_pc) { + gen_save_pc(ctx->base.pc_next); + } + if (ctx->hflags != ctx->saved_hflags) { + tcg_gen_movi_i32(hflags, ctx->hflags); + } generate_exception(ctx, EXCP_TRAP); gen_set_label(l1); } @@ -14155,7 +14172,7 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) case OPC_TEQ: case OPC_TNE: check_insn(ctx, ISA_MIPS2); - gen_trap(ctx, op1, rs, rt, -1); + gen_trap(ctx, op1, rs, rt, -1, extract32(ctx->opcode, 6, 10)); break; case OPC_PMON: /* Pmon entry point, also R4010 selsl */ @@ -15289,11 +15306,10 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx) case OPC_TLTI: case OPC_TLTIU: case OPC_TEQI: - case OPC_TNEI: check_insn(ctx, ISA_MIPS2); check_insn_opc_removed(ctx, ISA_MIPS_R6); - gen_trap(ctx, op1, rs, -1, imm); + gen_trap(ctx, op1, rs, -1, imm, 0); break; case OPC_SIGRIE: check_insn(ctx, ISA_MIPS_R6); From b60070566914d09f52d0225006e8eeab85a233cf Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:37 -0800 Subject: [PATCH 402/730] linux-user/openrisc: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Fill in the missing PC for SIGTRAP. Reviewed-by: Stafford Horne Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-19-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/openrisc/cpu_loop.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/linux-user/openrisc/cpu_loop.c b/linux-user/openrisc/cpu_loop.c index 592901a68b..7683bea064 100644 --- a/linux-user/openrisc/cpu_loop.c +++ b/linux-user/openrisc/cpu_loop.c @@ -29,7 +29,6 @@ void cpu_loop(CPUOpenRISCState *env) CPUState *cs = env_cpu(env); int trapnr; abi_long ret; - target_siginfo_t info; for (;;) { cpu_exec_start(cs); @@ -55,27 +54,16 @@ void cpu_loop(CPUOpenRISCState *env) } break; case EXCP_ALIGN: - info.si_signo = TARGET_SIGBUS; - info.si_errno = 0; - info.si_code = TARGET_BUS_ADRALN; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, env->eear); break; case EXCP_ILLEGAL: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPC; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); break; case EXCP_INTERRUPT: /* We processed the pending cpu work above. */ break; case EXCP_DEBUG: - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); From d30e60e7b4c38c3688e5690bc28f582c64a3c971 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:38 -0800 Subject: [PATCH 403/730] linux-user/ppc: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Fill in the missing PC for SIGTRAP. The fault address for POWERPC_EXCP_ISI is nip exactly, not nip - 4. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-20-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/ppc/cpu_loop.c | 136 ++++++++------------------------------ 1 file changed, 28 insertions(+), 108 deletions(-) diff --git a/linux-user/ppc/cpu_loop.c b/linux-user/ppc/cpu_loop.c index 30c82f2354..46e6ffd6d3 100644 --- a/linux-user/ppc/cpu_loop.c +++ b/linux-user/ppc/cpu_loop.c @@ -76,8 +76,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) void cpu_loop(CPUPPCState *env) { CPUState *cs = env_cpu(env); - target_siginfo_t info; - int trapnr; + int trapnr, si_signo, si_code; target_ulong ret; for(;;) { @@ -102,61 +101,10 @@ void cpu_loop(CPUPPCState *env) "Aborting\n"); break; case POWERPC_EXCP_DSI: /* Data storage exception */ - /* XXX: check this. Seems bugged */ - switch (env->error_code & 0xFF000000) { - case 0x40000000: - case 0x42000000: - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_MAPERR; - break; - case 0x04000000: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLADR; - break; - case 0x08000000: - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_ACCERR; - break; - default: - /* Let's send a regular segfault... */ - EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", - env->error_code); - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_MAPERR; - break; - } - info._sifields._sigfault._addr = env->spr[SPR_DAR]; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; case POWERPC_EXCP_ISI: /* Instruction storage exception */ - /* XXX: check this */ - switch (env->error_code & 0xFF000000) { - case 0x40000000: - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_MAPERR; - break; - case 0x10000000: - case 0x08000000: - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_ACCERR; - break; - default: - /* Let's send a regular segfault... */ - EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", - env->error_code); - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_MAPERR; - break; - } - info._sifields._sigfault._addr = env->nip - 4; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + /* FIXME: handle maperr in ppc_cpu_record_sigsegv. */ + force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, + env->spr[SPR_DAR]); break; case POWERPC_EXCP_EXTERNAL: /* External input */ cpu_abort(cs, "External interrupt while in user mode. " @@ -167,24 +115,23 @@ void cpu_loop(CPUPPCState *env) /* XXX: check this */ switch (env->error_code & ~0xF) { case POWERPC_EXCP_FP: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; + si_signo = TARGET_SIGFPE; switch (env->error_code & 0xF) { case POWERPC_EXCP_FP_OX: - info.si_code = TARGET_FPE_FLTOVF; + si_code = TARGET_FPE_FLTOVF; break; case POWERPC_EXCP_FP_UX: - info.si_code = TARGET_FPE_FLTUND; + si_code = TARGET_FPE_FLTUND; break; case POWERPC_EXCP_FP_ZX: case POWERPC_EXCP_FP_VXZDZ: - info.si_code = TARGET_FPE_FLTDIV; + si_code = TARGET_FPE_FLTDIV; break; case POWERPC_EXCP_FP_XX: - info.si_code = TARGET_FPE_FLTRES; + si_code = TARGET_FPE_FLTRES; break; case POWERPC_EXCP_FP_VXSOFT: - info.si_code = TARGET_FPE_FLTINV; + si_code = TARGET_FPE_FLTINV; break; case POWERPC_EXCP_FP_VXSNAN: case POWERPC_EXCP_FP_VXISI: @@ -193,51 +140,50 @@ void cpu_loop(CPUPPCState *env) case POWERPC_EXCP_FP_VXVC: case POWERPC_EXCP_FP_VXSQRT: case POWERPC_EXCP_FP_VXCVI: - info.si_code = TARGET_FPE_FLTSUB; + si_code = TARGET_FPE_FLTSUB; break; default: EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", env->error_code); + si_code = 0; break; } break; case POWERPC_EXCP_INVAL: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; + si_signo = TARGET_SIGILL; switch (env->error_code & 0xF) { case POWERPC_EXCP_INVAL_INVAL: - info.si_code = TARGET_ILL_ILLOPC; + si_code = TARGET_ILL_ILLOPC; break; case POWERPC_EXCP_INVAL_LSWX: - info.si_code = TARGET_ILL_ILLOPN; + si_code = TARGET_ILL_ILLOPN; break; case POWERPC_EXCP_INVAL_SPR: - info.si_code = TARGET_ILL_PRVREG; + si_code = TARGET_ILL_PRVREG; break; case POWERPC_EXCP_INVAL_FP: - info.si_code = TARGET_ILL_COPROC; + si_code = TARGET_ILL_COPROC; break; default: EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", env->error_code & 0xF); - info.si_code = TARGET_ILL_ILLADR; + si_code = TARGET_ILL_ILLADR; break; } break; case POWERPC_EXCP_PRIV: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; + si_signo = TARGET_SIGILL; switch (env->error_code & 0xF) { case POWERPC_EXCP_PRIV_OPC: - info.si_code = TARGET_ILL_PRVOPC; + si_code = TARGET_ILL_PRVOPC; break; case POWERPC_EXCP_PRIV_REG: - info.si_code = TARGET_ILL_PRVREG; + si_code = TARGET_ILL_PRVREG; break; default: EXCP_DUMP(env, "Unknown privilege violation (%02x)\n", env->error_code & 0xF); - info.si_code = TARGET_ILL_PRVOPC; + si_code = TARGET_ILL_PRVOPC; break; } break; @@ -250,28 +196,19 @@ void cpu_loop(CPUPPCState *env) env->error_code); break; } - info._sifields._sigfault._addr = env->nip; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(si_signo, si_code, env->nip); break; case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_COPROC; - info._sifields._sigfault._addr = env->nip; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ + case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ + case POWERPC_EXCP_VPU: /* Vector unavailable exception */ + force_sig_fault(TARGET_SIGILL, TARGET_ILL_COPROC, env->nip); break; case POWERPC_EXCP_SYSCALL: /* System call exception */ case POWERPC_EXCP_SYSCALL_VECTORED: cpu_abort(cs, "Syscall exception while in user mode. " "Aborting\n"); break; - case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_COPROC; - info._sifields._sigfault._addr = env->nip; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; case POWERPC_EXCP_DECR: /* Decrementer exception */ cpu_abort(cs, "Decrementer interrupt while in user mode. " "Aborting\n"); @@ -292,13 +229,6 @@ void cpu_loop(CPUPPCState *env) cpu_abort(cs, "Instruction TLB exception while in user mode. " "Aborting\n"); break; - case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_COPROC; - info._sifields._sigfault._addr = env->nip; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ cpu_abort(cs, "Embedded floating-point data IRQ not handled\n"); break; @@ -355,13 +285,6 @@ void cpu_loop(CPUPPCState *env) cpu_abort(cs, "Hypervisor instruction segment exception " "while in user mode. Aborting\n"); break; - case POWERPC_EXCP_VPU: /* Vector unavailable exception */ - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_COPROC; - info._sifields._sigfault._addr = env->nip; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - break; case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ cpu_abort(cs, "Programmable interval timer interrupt " "while in user mode. Aborting\n"); @@ -444,10 +367,7 @@ void cpu_loop(CPUPPCState *env) env->gpr[3] = ret; break; case EXCP_DEBUG: - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->nip); break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ From 8521cc21addac658997170fc8670d44625e44b24 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:39 -0800 Subject: [PATCH 404/730] linux-user/riscv: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Fix missing PC from EXCP_DEBUG by merging the case with EXCP_BREAKPOINT. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-21-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/riscv/cpu_loop.c | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/linux-user/riscv/cpu_loop.c b/linux-user/riscv/cpu_loop.c index 0cd8985cb8..26d446f323 100644 --- a/linux-user/riscv/cpu_loop.c +++ b/linux-user/riscv/cpu_loop.c @@ -30,8 +30,7 @@ void cpu_loop(CPURISCVState *env) { CPUState *cs = env_cpu(env); - int trapnr, signum, sigcode; - target_ulong sigaddr; + int trapnr; target_ulong ret; for (;;) { @@ -40,10 +39,6 @@ void cpu_loop(CPURISCVState *env) cpu_exec_end(cs); process_queued_cpu_work(cs); - signum = 0; - sigcode = 0; - sigaddr = 0; - switch (trapnr) { case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ @@ -79,39 +74,23 @@ void cpu_loop(CPURISCVState *env) } break; case RISCV_EXCP_ILLEGAL_INST: - signum = TARGET_SIGILL; - sigcode = TARGET_ILL_ILLOPC; + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); break; case RISCV_EXCP_BREAKPOINT: - signum = TARGET_SIGTRAP; - sigcode = TARGET_TRAP_BRKPT; - sigaddr = env->pc; + case EXCP_DEBUG: + gdbstep: + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); break; case RISCV_EXCP_SEMIHOST: env->gpr[xA0] = do_common_semihosting(cs); env->pc += 4; break; - case EXCP_DEBUG: - gdbstep: - signum = TARGET_SIGTRAP; - sigcode = TARGET_TRAP_BRKPT; - break; default: EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n", trapnr); exit(EXIT_FAILURE); } - if (signum) { - target_siginfo_t info = { - .si_signo = signum, - .si_errno = 0, - .si_code = sigcode, - ._sifields._sigfault._addr = sigaddr - }; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - } - process_pending_signals(env); } } From 8f0bebebd29b672a11a5de48b3330ca60524d286 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:40 -0800 Subject: [PATCH 405/730] linux-user/s390x: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-22-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/s390x/cpu_loop.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/linux-user/s390x/cpu_loop.c b/linux-user/s390x/cpu_loop.c index ad0c3cd263..7901dfe6f5 100644 --- a/linux-user/s390x/cpu_loop.c +++ b/linux-user/s390x/cpu_loop.c @@ -58,7 +58,6 @@ void cpu_loop(CPUS390XState *env) { CPUState *cs = env_cpu(env); int trapnr, n, sig; - target_siginfo_t info; target_ulong addr; abi_long ret; @@ -158,11 +157,7 @@ void cpu_loop(CPUS390XState *env) */ env->psw.addr += env->int_pgm_ilen; do_signal: - info.si_signo = sig; - info.si_errno = 0; - info.si_code = n; - info._sifields._sigfault._addr = addr; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(sig, n, addr); break; case EXCP_ATOMIC: From 588c7a171b01876963894bd48946fbcc5bdf21a8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:41 -0800 Subject: [PATCH 406/730] linux-user/sh4: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Fill in the missing PC for SIGTRAP. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-23-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sh4/cpu_loop.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/linux-user/sh4/cpu_loop.c b/linux-user/sh4/cpu_loop.c index 3290f6445c..1bd313cb19 100644 --- a/linux-user/sh4/cpu_loop.c +++ b/linux-user/sh4/cpu_loop.c @@ -28,7 +28,6 @@ void cpu_loop(CPUSH4State *env) { CPUState *cs = env_cpu(env); int trapnr, ret; - target_siginfo_t info; while (1) { bool arch_interrupt = true; @@ -60,10 +59,7 @@ void cpu_loop(CPUSH4State *env) /* just indicate that signals should be handled asap */ break; case EXCP_DEBUG: - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); From ac80d8b1512f91184eef1c9b73888302b7cfa8d5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:42 -0800 Subject: [PATCH 407/730] linux-user/sparc: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Fill in the missing PC for SIGTRAP. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-24-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/sparc/cpu_loop.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/linux-user/sparc/cpu_loop.c b/linux-user/sparc/cpu_loop.c index 8765ab6020..baf3d9ae01 100644 --- a/linux-user/sparc/cpu_loop.c +++ b/linux-user/sparc/cpu_loop.c @@ -155,7 +155,6 @@ void cpu_loop (CPUSPARCState *env) CPUState *cs = env_cpu(env); int trapnr; abi_long ret; - target_siginfo_t info; while (1) { cpu_exec_start(cs); @@ -241,19 +240,10 @@ void cpu_loop (CPUSPARCState *env) /* just indicate that signals should be handled asap */ break; case TT_ILL_INSN: - { - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = TARGET_ILL_ILLOPC; - info._sifields._sigfault._addr = env->pc; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); - } + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); break; case EXCP_DEBUG: - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); break; case EXCP_ATOMIC: cpu_exec_step_atomic(cs); From 2dd4634963224834d79221718e95987c7d351290 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Jan 2022 13:32:43 -0800 Subject: [PATCH 408/730] linux-user/xtensa: Use force_sig_fault Use the new function instead of setting up a target_siginfo_t and calling queue_signal. Fill in the missing PC for SIGTRAP. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-Id: <20220107213243.212806-25-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/xtensa/cpu_loop.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/linux-user/xtensa/cpu_loop.c b/linux-user/xtensa/cpu_loop.c index 6bc6d6dee6..d51ce05392 100644 --- a/linux-user/xtensa/cpu_loop.c +++ b/linux-user/xtensa/cpu_loop.c @@ -126,7 +126,6 @@ static void xtensa_underflow12(CPUXtensaState *env) void cpu_loop(CPUXtensaState *env) { CPUState *cs = env_cpu(env); - target_siginfo_t info; abi_ulong ret; int trapnr; @@ -163,14 +162,12 @@ void cpu_loop(CPUXtensaState *env) case EXC_USER: switch (env->sregs[EXCCAUSE]) { case ILLEGAL_INSTRUCTION_CAUSE: + force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, + env->sregs[EPC1]); + break; case PRIVILEGED_CAUSE: - info.si_signo = TARGET_SIGILL; - info.si_errno = 0; - info.si_code = - env->sregs[EXCCAUSE] == ILLEGAL_INSTRUCTION_CAUSE ? - TARGET_ILL_ILLOPC : TARGET_ILL_PRVOPC; - info._sifields._sigfault._addr = env->sregs[EPC1]; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, + env->sregs[EPC1]); break; case SYSCALL_CAUSE: @@ -219,11 +216,8 @@ void cpu_loop(CPUXtensaState *env) break; case INTEGER_DIVIDE_BY_ZERO_CAUSE: - info.si_signo = TARGET_SIGFPE; - info.si_errno = 0; - info.si_code = TARGET_FPE_INTDIV; - info._sifields._sigfault._addr = env->sregs[EPC1]; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, + env->sregs[EPC1]); break; default: @@ -232,10 +226,8 @@ void cpu_loop(CPUXtensaState *env) } break; case EXCP_DEBUG: - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, + env->sregs[EPC1]); break; case EXC_DEBUG: default: From ffe81d439812b2858065bb1410551027eafe938b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Jan 2022 20:25:59 -0800 Subject: [PATCH 409/730] linux-user/arm: Move target_oabi_flock64 out of target_structs.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Place it next to copy_from/to_user_oabi_flock64, the only users, inside the existing target-specific ifdef. This leaves only generic ipc structs in target_structs.h. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Laurent Vivier Message-Id: <20220107042600.149852-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/arm/target_structs.h | 8 -------- linux-user/syscall.c | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/linux-user/arm/target_structs.h b/linux-user/arm/target_structs.h index 339b070bf1..25bf8dd3a5 100644 --- a/linux-user/arm/target_structs.h +++ b/linux-user/arm/target_structs.h @@ -48,12 +48,4 @@ struct target_shmid_ds { abi_ulong __unused4; abi_ulong __unused5; }; - -struct target_oabi_flock64 { - abi_short l_type; - abi_short l_whence; - abi_llong l_start; - abi_llong l_len; - abi_int l_pid; -} QEMU_PACKED; #endif diff --git a/linux-user/syscall.c b/linux-user/syscall.c index ce9d64896c..ca6e0b8fb0 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6927,6 +6927,14 @@ typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr); typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl); #if defined(TARGET_ARM) && TARGET_ABI_BITS == 32 +struct target_oabi_flock64 { + abi_short l_type; + abi_short l_whence; + abi_llong l_start; + abi_llong l_len; + abi_int l_pid; +} QEMU_PACKED; + static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl, abi_ulong target_flock_addr) { From 72f692694fac92b49a2518fb7ea6149df1cbb214 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Jan 2022 20:26:00 -0800 Subject: [PATCH 410/730] linux-user: Move target_struct.h generic definitions to generic/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most targets share the same generic ipc structure definitions. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Laurent Vivier Message-Id: <20220107042600.149852-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/aarch64/target_structs.h | 59 +------------------------- linux-user/arm/target_structs.h | 52 +---------------------- linux-user/cris/target_structs.h | 59 +------------------------- linux-user/generic/target_structs.h | 58 +++++++++++++++++++++++++ linux-user/hexagon/target_structs.h | 55 +----------------------- linux-user/i386/target_structs.h | 59 +------------------------- linux-user/m68k/target_structs.h | 59 +------------------------- linux-user/microblaze/target_structs.h | 59 +------------------------- linux-user/nios2/target_structs.h | 59 +------------------------- linux-user/openrisc/target_structs.h | 59 +------------------------- linux-user/riscv/target_structs.h | 47 +------------------- linux-user/sh4/target_structs.h | 59 +------------------------- linux-user/x86_64/target_structs.h | 36 +--------------- 13 files changed, 70 insertions(+), 650 deletions(-) create mode 100644 linux-user/generic/target_structs.h diff --git a/linux-user/aarch64/target_structs.h b/linux-user/aarch64/target_structs.h index 7c748344ca..3a06f373c3 100644 --- a/linux-user/aarch64/target_structs.h +++ b/linux-user/aarch64/target_structs.h @@ -1,58 +1 @@ -/* - * ARM AArch64 specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef AARCH64_TARGET_STRUCTS_H -#define AARCH64_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/arm/target_structs.h b/linux-user/arm/target_structs.h index 25bf8dd3a5..3a06f373c3 100644 --- a/linux-user/arm/target_structs.h +++ b/linux-user/arm/target_structs.h @@ -1,51 +1 @@ -/* - * ARM specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef ARM_TARGET_STRUCTS_H -#define ARM_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ - abi_ulong __unused1; - abi_ulong shm_dtime; /* time of last shmdt() */ - abi_ulong __unused2; - abi_ulong shm_ctime; /* time of last change by shmctl() */ - abi_ulong __unused3; - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/cris/target_structs.h b/linux-user/cris/target_structs.h index f949d2331e..3a06f373c3 100644 --- a/linux-user/cris/target_structs.h +++ b/linux-user/cris/target_structs.h @@ -1,58 +1 @@ -/* - * CRIS specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef CRIS_TARGET_STRUCTS_H -#define CRIS_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/generic/target_structs.h b/linux-user/generic/target_structs.h new file mode 100644 index 0000000000..09ff858b6e --- /dev/null +++ b/linux-user/generic/target_structs.h @@ -0,0 +1,58 @@ +/* + * Generic structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef GENERIC_TARGET_STRUCTS_H +#define GENERIC_TARGET_STRUCTS_H + +struct target_ipc_perm { + abi_int __key; /* Key. */ + abi_uint uid; /* Owner's user ID. */ + abi_uint gid; /* Owner's group ID. */ + abi_uint cuid; /* Creator's user ID. */ + abi_uint cgid; /* Creator's group ID. */ + abi_ushort mode; /* Read/write permission. */ + abi_ushort __pad1; + abi_ushort __seq; /* Sequence number. */ + abi_ushort __pad2; + abi_ulong __unused1; + abi_ulong __unused2; +}; + +struct target_shmid_ds { + struct target_ipc_perm shm_perm; /* operation permission struct */ + abi_long shm_segsz; /* size of segment in bytes */ + abi_ulong shm_atime; /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 + abi_ulong __unused1; +#endif + abi_ulong shm_dtime; /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 + abi_ulong __unused2; +#endif + abi_ulong shm_ctime; /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 + abi_ulong __unused3; +#endif + abi_int shm_cpid; /* pid of creator */ + abi_int shm_lpid; /* pid of last shmop */ + abi_ulong shm_nattch; /* number of current attaches */ + abi_ulong __unused4; + abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/hexagon/target_structs.h b/linux-user/hexagon/target_structs.h index c217d9442a..3a06f373c3 100644 --- a/linux-user/hexagon/target_structs.h +++ b/linux-user/hexagon/target_structs.h @@ -1,54 +1 @@ -/* - * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -/* - * Hexagon specific structures for linux-user - */ -#ifndef HEXAGON_TARGET_STRUCTS_H -#define HEXAGON_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ - abi_ulong __unused1; - abi_ulong shm_dtime; /* time of last shmdt() */ - abi_ulong __unused2; - abi_ulong shm_ctime; /* time of last change by shmctl() */ - abi_ulong __unused3; - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/i386/target_structs.h b/linux-user/i386/target_structs.h index e22847fd20..3a06f373c3 100644 --- a/linux-user/i386/target_structs.h +++ b/linux-user/i386/target_structs.h @@ -1,58 +1 @@ -/* - * i386 specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef I386_TARGET_STRUCTS_H -#define I386_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/m68k/target_structs.h b/linux-user/m68k/target_structs.h index e373d481e1..3a06f373c3 100644 --- a/linux-user/m68k/target_structs.h +++ b/linux-user/m68k/target_structs.h @@ -1,58 +1 @@ -/* - * m68k specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef M68K_TARGET_STRUCTS_H -#define M68K_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/microblaze/target_structs.h b/linux-user/microblaze/target_structs.h index d08f6a53a8..3a06f373c3 100644 --- a/linux-user/microblaze/target_structs.h +++ b/linux-user/microblaze/target_structs.h @@ -1,58 +1 @@ -/* - * MicroBlaze specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef MICROBLAZE_TARGET_STRUCTS_H -#define MICROBLAZE_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/nios2/target_structs.h b/linux-user/nios2/target_structs.h index daa2886f98..3a06f373c3 100644 --- a/linux-user/nios2/target_structs.h +++ b/linux-user/nios2/target_structs.h @@ -1,58 +1 @@ -/* - * Nios2 specific structures for linux-user - * - * Copyright (c) 2016 Marek Vasut - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef NIOS2_TARGET_STRUCTS_H -#define NIOS2_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/openrisc/target_structs.h b/linux-user/openrisc/target_structs.h index e98e2bc799..3a06f373c3 100644 --- a/linux-user/openrisc/target_structs.h +++ b/linux-user/openrisc/target_structs.h @@ -1,58 +1 @@ -/* - * OpenRISC specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef OPENRISC_TARGET_STRUCTS_H -#define OPENRISC_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/riscv/target_structs.h b/linux-user/riscv/target_structs.h index ea3e5ed17e..3a06f373c3 100644 --- a/linux-user/riscv/target_structs.h +++ b/linux-user/riscv/target_structs.h @@ -1,46 +1 @@ -/* - * RISC-V specific structures for linux-user - * - * This is a copy of ../aarch64/target_structs.h atm. - * - */ -#ifndef RISCV_TARGET_STRUCTS_H -#define RISCV_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/sh4/target_structs.h b/linux-user/sh4/target_structs.h index 00ac39478b..3a06f373c3 100644 --- a/linux-user/sh4/target_structs.h +++ b/linux-user/sh4/target_structs.h @@ -1,58 +1 @@ -/* - * SH4 specific structures for linux-user - * - * Copyright (c) 2013 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#ifndef SH4_TARGET_STRUCTS_H -#define SH4_TARGET_STRUCTS_H - -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; - -#endif +#include "../generic/target_structs.h" diff --git a/linux-user/x86_64/target_structs.h b/linux-user/x86_64/target_structs.h index ce367b253b..f1181383c4 100644 --- a/linux-user/x86_64/target_structs.h +++ b/linux-user/x86_64/target_structs.h @@ -19,41 +19,7 @@ #ifndef X86_64_TARGET_STRUCTS_H #define X86_64_TARGET_STRUCTS_H -struct target_ipc_perm { - abi_int __key; /* Key. */ - abi_uint uid; /* Owner's user ID. */ - abi_uint gid; /* Owner's group ID. */ - abi_uint cuid; /* Creator's user ID. */ - abi_uint cgid; /* Creator's group ID. */ - abi_ushort mode; /* Read/write permission. */ - abi_ushort __pad1; - abi_ushort __seq; /* Sequence number. */ - abi_ushort __pad2; - abi_ulong __unused1; - abi_ulong __unused2; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; /* operation permission struct */ - abi_long shm_segsz; /* size of segment in bytes */ - abi_ulong shm_atime; /* time of last shmat() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused1; -#endif - abi_ulong shm_dtime; /* time of last shmdt() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused2; -#endif - abi_ulong shm_ctime; /* time of last change by shmctl() */ -#if TARGET_ABI_BITS == 32 - abi_ulong __unused3; -#endif - abi_int shm_cpid; /* pid of creator */ - abi_int shm_lpid; /* pid of last shmop */ - abi_ulong shm_nattch; /* number of current attaches */ - abi_ulong __unused4; - abi_ulong __unused5; -}; +#include "../generic/target_structs.h" /* The x86 definition differs from the generic one in that the * two padding fields exist whether the ABI is 32 bits or 64 bits. From 08f5f973491b7e575231afbb1fa5c96f39c257b2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Jan 2022 14:57:35 -0800 Subject: [PATCH 411/730] linux-user: Do not special-case NULL for PR_GET_PDEATHSIG The kernel does not special-case arg2 != NULL, so neither should we. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20220106225738.103012-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index ca6e0b8fb0..eff107b8bc 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6444,7 +6444,7 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, int deathsig; ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig, arg3, arg4, arg5)); - if (!is_error(ret) && arg2 && put_user_s32(deathsig, arg2)) { + if (!is_error(ret) && put_user_s32(deathsig, arg2)) { return -TARGET_EFAULT; } return ret; From 1edebb36ea1809c7882a7be9654260adbbfdcb35 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Jan 2022 14:57:36 -0800 Subject: [PATCH 412/730] linux-user: Map signal number in PR_GET_PDEATHSIG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert the host signal number to guest signal number before returning the value to the guest. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220106225738.103012-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index eff107b8bc..b17cfe31c8 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6444,7 +6444,8 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, int deathsig; ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig, arg3, arg4, arg5)); - if (!is_error(ret) && put_user_s32(deathsig, arg2)) { + if (!is_error(ret) && + put_user_s32(host_to_target_signal(deathsig), arg2)) { return -TARGET_EFAULT; } return ret; From f746c65909ee6df4b560804bc152cdb3e9ad9bf8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Jan 2022 14:57:37 -0800 Subject: [PATCH 413/730] linux-user: Implement PR_SET_PDEATHSIG Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20220106225738.103012-4-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b17cfe31c8..f9ae6328b5 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6450,6 +6450,9 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, } return ret; } + case PR_SET_PDEATHSIG: + return get_errno(prctl(PR_SET_PDEATHSIG, target_to_host_signal(arg2), + arg3, arg4, arg5)); case PR_GET_NAME: { void *name = lock_user(VERIFY_WRITE, arg2, 16, 1); From 4f4e5567f856d9b841494b3b5216a37d2952ee54 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 6 Jan 2022 14:57:38 -0800 Subject: [PATCH 414/730] linux-user: Implement capability prctls This is PR_CAPBSET_READ, PR_CAPBSET_DROP and the "legacy" PR_CAP_AMBIENT PR_GET_SECUREBITS, PR_SET_SECUREBITS. All of these arguments are integer values only, and do not require mapping of values between host and guest. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20220106225738.103012-5-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f9ae6328b5..5950222a77 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6504,10 +6504,15 @@ static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2, case PR_SET_UNALIGN: return do_prctl_set_unalign(env, arg2); + case PR_CAP_AMBIENT: + case PR_CAPBSET_READ: + case PR_CAPBSET_DROP: case PR_GET_DUMPABLE: case PR_SET_DUMPABLE: case PR_GET_KEEPCAPS: case PR_SET_KEEPCAPS: + case PR_GET_SECUREBITS: + case PR_SET_SECUREBITS: case PR_GET_TIMING: case PR_SET_TIMING: case PR_GET_TIMERSLACK: From b37778b840f6dc6d1bbaf0e8e0641b3d48ad77c5 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 11 Jan 2022 08:29:00 +0000 Subject: [PATCH 415/730] linux-user: Fix clang warning for nios2-linux-user code The clang in Ubuntu 18.04 (10.0.0-4ubuntu1) produces a warning on the code added in commit f5ef0e518d03 where we use a shifted expression in a boolean context: ../../linux-user/elfload.c:2423:16: error: converting the result of '<<' to a boolean always evaluates to true [-Werror,-Wtautological-constant-compare] } else if (LO_COMMPAGE) { ^ ../../linux-user/elfload.c:1102:22: note: expanded from macro 'LO_COMMPAGE' #define LO_COMMPAGE TARGET_PAGE_SIZE ^ /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/include/exec/cpu-all.h:231:31: note: expanded from macro 'TARGET_PAGE_SIZE' #define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS) ^ 1 error generated. The warning is bogus because whether LO_COMMPAGE is zero or not depends on compile-time ifdefs; shut the compiler up by adding an explicit comparison to zero. Fixes: f5ef0e518d0331 ("linux-user/nios2: Map a real kuser page") Signed-off-by: Peter Maydell Reviewed-by: Laurent Vivier Message-id: 20220111082900.3341274-1-peter.maydell@linaro.org Signed-off-by: Peter Maydell --- linux-user/elfload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 329b2375ef..d3274edfdb 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -2420,7 +2420,7 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr, } else { offset = -(HI_COMMPAGE & -align); } - } else if (LO_COMMPAGE) { + } else if (LO_COMMPAGE != 0) { loaddr = MIN(loaddr, LO_COMMPAGE & -align); } From 23ab6d8813685c38fd1d87f573dded9fe37ee17f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 12 Jan 2022 11:28:26 +0100 Subject: [PATCH 416/730] target/ppc: Add popcntb instruction to POWER5+ processors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit popcntb instruction was added in ISA v2.02. Add support for POWER5+ processors since they implement ISA v2.03. PPC970 CPUs implement v2.01 and do not support popcntb. Signed-off-by: Cédric Le Goater Reviewed-by: Fabiano Rosas Message-Id: <20220105095142.3990430-2-clg@kaod.org> Signed-off-by: Cédric Le Goater --- target/ppc/cpu_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index cc93bff3fa..f15a52259c 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6957,6 +6957,7 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data) PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | PPC_64B | + PPC_POPCNTB | PPC_SEGMENT_64B | PPC_SLBI; pcc->insns_flags2 = PPC2_FP_CVT_S64; pcc->msr_mask = (1ull << MSR_SF) | From 2460e1d75ba60ee67fadabccd988705b7bb911cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 12 Jan 2022 11:28:26 +0100 Subject: [PATCH 417/730] spapr: Fix support of POWER5+ processors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit POWER5+ (ISA v2.03) processors are supported by the pseries machine but they do not have Altivec instructions. Do not advertise support for it in the DT. To be noted that this test is in contradiction with the assert in cap_vsx_apply(). Signed-off-by: Cédric Le Goater Tested-by: Fabiano Rosas Message-Id: <20220105095142.3990430-3-clg@kaod.org> Signed-off-by: Cédric Le Goater --- hw/ppc/spapr.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 8373429325..72f5dce751 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -723,10 +723,12 @@ static void spapr_dt_cpu(CPUState *cs, void *fdt, int offset, * * Only CPUs for which we create core types in spapr_cpu_core.c * are possible, and all of those have VMX */ - if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) { - _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2))); - } else { - _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1))); + if (env->insns_flags & PPC_ALTIVEC) { + if (spapr_get_cap(spapr, SPAPR_CAP_VSX) != 0) { + _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 2))); + } else { + _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", 1))); + } } /* Advertise DFP (Decimal Floating Point) if available From 91137619c6555a3c7cdd829f3b91b6da2bf67475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 12 Jan 2022 11:28:26 +0100 Subject: [PATCH 418/730] target/ppc: Add extra float instructions to POWER5P processors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISA v2.03 introduced Floating Round to Integer instructions : frin, friz, frip, and frim. Add them to POWER5+. The PPC_FLOAT_EXT flag also includes the fre (Floating Reciprocal Estimate) instruction which was introduced in ISA v2.0x. The architecture document says its optional and that might be the reason why it has been kept under the PPC_FLOAT_EXT flag. This means 970 CPUs can not use it under QEMU, which doesn't seem to be a problem. Signed-off-by: Cédric Le Goater --- target/ppc/cpu_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index f15a52259c..e30e86fe9d 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6953,6 +6953,7 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data) PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | PPC_FLOAT_STFIWX | + PPC_FLOAT_EXT | PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | PPC_MEM_SYNC | PPC_MEM_EIEIO | PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | From 808ead89a678789285d45ede951afa09413feda6 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jan 2022 11:28:26 +0100 Subject: [PATCH 419/730] docs/system/ppc: Merge the PEF information into the pseries page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Protected Execution Facility is only available with the pseries machine, so let's merge the old ASCII text into the new RST file now. Signed-off-by: Thomas Huth Reviewed-by: Daniel Henrique Barboza Message-Id: <20220105103232.405204-1-thuth@redhat.com> Signed-off-by: Cédric Le Goater --- docs/papr-pef.txt | 30 ------------------------------ docs/system/ppc/pseries.rst | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 30 deletions(-) delete mode 100644 docs/papr-pef.txt diff --git a/docs/papr-pef.txt b/docs/papr-pef.txt deleted file mode 100644 index 72550e9bf8..0000000000 --- a/docs/papr-pef.txt +++ /dev/null @@ -1,30 +0,0 @@ -POWER (PAPR) Protected Execution Facility (PEF) -=============================================== - -Protected Execution Facility (PEF), also known as Secure Guest support -is a feature found on IBM POWER9 and POWER10 processors. - -If a suitable firmware including an Ultravisor is installed, it adds -an extra memory protection mode to the CPU. The ultravisor manages a -pool of secure memory which cannot be accessed by the hypervisor. - -When this feature is enabled in QEMU, a guest can use ultracalls to -enter "secure mode". This transfers most of its memory to secure -memory, where it cannot be eavesdropped by a compromised hypervisor. - -Launching ---------- - -To launch a guest which will be permitted to enter PEF secure mode: - -# ${QEMU} \ - -object pef-guest,id=pef0 \ - -machine confidential-guest-support=pef0 \ - ... - -Live Migration ----------------- - -Live migration is not yet implemented for PEF guests. For -consistency, we currently prevent migration if the PEF feature is -enabled, whether or not the guest has actually entered secure mode. diff --git a/docs/system/ppc/pseries.rst b/docs/system/ppc/pseries.rst index 72e315eff6..16394fa521 100644 --- a/docs/system/ppc/pseries.rst +++ b/docs/system/ppc/pseries.rst @@ -230,6 +230,39 @@ nested. Combinations not shown in the table are not available. .. [3] Introduced on Power10 machines. + +POWER (PAPR) Protected Execution Facility (PEF) +----------------------------------------------- + +Protected Execution Facility (PEF), also known as Secure Guest support +is a feature found on IBM POWER9 and POWER10 processors. + +If a suitable firmware including an Ultravisor is installed, it adds +an extra memory protection mode to the CPU. The ultravisor manages a +pool of secure memory which cannot be accessed by the hypervisor. + +When this feature is enabled in QEMU, a guest can use ultracalls to +enter "secure mode". This transfers most of its memory to secure +memory, where it cannot be eavesdropped by a compromised hypervisor. + +Launching +^^^^^^^^^ + +To launch a guest which will be permitted to enter PEF secure mode:: + + $ qemu-system-ppc64 \ + -object pef-guest,id=pef0 \ + -machine confidential-guest-support=pef0 \ + ... + +Live Migration +^^^^^^^^^^^^^^ + +Live migration is not yet implemented for PEF guests. For +consistency, QEMU currently prevents migration if the PEF feature is +enabled, whether or not the guest has actually entered secure mode. + + Maintainer contact information ------------------------------ From c52887687e057f21b4b748759c2107aa7e3981b6 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 12 Jan 2022 11:28:26 +0100 Subject: [PATCH 420/730] MAINTAINERS: Improve the PowerPC machines section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some documentation files to the corresponding machine sections and mention the machine names in the section titles where it is not so obvious (e.g. that "taihu" is a 405 machine). Signed-off-by: Thomas Huth Reviewed-by: Daniel Henrique Barboza Reviewed-by: Mark Cave-Ayland Message-Id: <20220105104800.407570-1-thuth@redhat.com> Signed-off-by: Cédric Le Goater --- MAINTAINERS | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index c98a61caee..6ccdec7f02 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1245,7 +1245,7 @@ F: hw/openrisc/openrisc_sim.c PowerPC Machines ---------------- -405 +405 (ref405ep and taihu) L: qemu-ppc@nongnu.org S: Orphan F: hw/ppc/ppc405_boards.c @@ -1281,6 +1281,7 @@ New World (mac99) M: Mark Cave-Ayland L: qemu-ppc@nongnu.org S: Odd Fixes +F: docs/system/ppc/powermac.rst F: hw/ppc/mac_newworld.c F: hw/pci-host/uninorth.c F: hw/pci-bridge/dec.[hc] @@ -1299,6 +1300,7 @@ Old World (g3beige) M: Mark Cave-Ayland L: qemu-ppc@nongnu.org S: Odd Fixes +F: docs/system/ppc/powermac.rst F: hw/ppc/mac_oldworld.c F: hw/pci-host/grackle.c F: hw/misc/macio/ @@ -1312,6 +1314,7 @@ PReP M: Hervé Poussineau L: qemu-ppc@nongnu.org S: Maintained +F: docs/system/ppc/prep.rst F: hw/ppc/prep.c F: hw/ppc/prep_systemio.c F: hw/ppc/rs6000_mc.c @@ -1324,7 +1327,7 @@ F: include/hw/isa/pc87312.h F: include/hw/rtc/m48t59.h F: tests/avocado/ppc_prep_40p.py -sPAPR +sPAPR (pseries) M: Cédric Le Goater M: Daniel Henrique Barboza R: David Gibson @@ -1336,8 +1339,8 @@ F: include/hw/*/spapr* F: hw/*/xics* F: include/hw/*/xics* F: pc-bios/slof.bin -F: docs/specs/ppc-spapr-hcalls.txt -F: docs/specs/ppc-spapr-hotplug.txt +F: docs/system/ppc/pseries.rst +F: docs/specs/ppc-spapr-* F: tests/qtest/spapr* F: tests/qtest/libqos/*spapr* F: tests/qtest/rtas* @@ -1348,6 +1351,7 @@ PowerNV (Non-Virtualized) M: Cédric Le Goater L: qemu-ppc@nongnu.org S: Maintained +F: docs/system/ppc/powernv.rst F: hw/ppc/pnv* F: hw/intc/pnv* F: hw/intc/xics_pnv.c From a23a72dd1ec2695cb24dde695666d726d40823ca Mon Sep 17 00:00:00 2001 From: Leonardo Garcia Date: Wed, 12 Jan 2022 11:28:26 +0100 Subject: [PATCH 421/730] docs: Clarifications and formatting changes in ppc docs. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Leonardo Garcia Reviewed-by: Cédric Le Goater Message-Id: <3b228af4785241c7fb4a2c70f0c495d2a9adea83.1641405872.git.lagarcia@br.ibm.com> Signed-off-by: Cédric Le Goater --- docs/specs/ppc-spapr-hcalls.rst | 21 ++++++++--------- docs/system/ppc/pseries.rst | 42 ++++++++++++++++----------------- 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/docs/specs/ppc-spapr-hcalls.rst b/docs/specs/ppc-spapr-hcalls.rst index 28daf9734a..6cdcef2026 100644 --- a/docs/specs/ppc-spapr-hcalls.rst +++ b/docs/specs/ppc-spapr-hcalls.rst @@ -1,13 +1,12 @@ +====================== sPAPR hypervisor calls ----------------------- +====================== When used with the ``pseries`` machine type, ``qemu-system-ppc64`` implements -a set of hypervisor calls (a.k.a. hcalls) defined in the `Linux on Power -Architecture Reference document (LoPAR) -`_. -This document is a subset of the Power Architecture Platform Reference (PAPR+) -specification (IBM internal only), which is what PowerVM, the IBM proprietary -hypervisor, adheres to. +a set of hypervisor calls (a.k.a. hcalls) defined in the Linux on Power +Architecture Reference ([LoPAR]_) document. This document is a subset of the +Power Architecture Platform Reference (PAPR+) specification (IBM internal only), +which is what PowerVM, the IBM proprietary hypervisor, adheres to. The subset in LoPAR is selected based on the requirements of Linux as a guest. @@ -18,8 +17,8 @@ running in the guest and QEMU. All those hypercalls start at hcall number 0xf000 which correspond to an implementation specific range in PAPR. -H_RTAS (0xf000) -^^^^^^^^^^^^^^^ +``H_RTAS (0xf000)`` +=================== RTAS stands for Run-Time Abstraction Sercies and is a set of runtime services generally provided by the firmware inside the guest to the operating system. It @@ -44,8 +43,8 @@ Returns: ``H_PARAMETER``: Unknown token. -H_LOGICAL_MEMOP (0xf001) -^^^^^^^^^^^^^^^^^^^^^^^^ +``H_LOGICAL_MEMOP (0xf001)`` +============================ When the guest runs in "real mode" (in powerpc terminology this means with MMU disabled, i.e. guest effective address equals to guest physical address), it diff --git a/docs/system/ppc/pseries.rst b/docs/system/ppc/pseries.rst index 16394fa521..1689324815 100644 --- a/docs/system/ppc/pseries.rst +++ b/docs/system/ppc/pseries.rst @@ -1,19 +1,18 @@ +=================================== pSeries family boards (``pseries``) =================================== -The Power machine para-virtualized environment described by the `Linux on Power -Architecture Reference document (LoPAR) -`_ -is called pSeries. This environment is also known as sPAPR, System p guests, or -simply Power Linux guests (although it is capable of running other operating -systems, such as AIX). +The Power machine para-virtualized environment described by the Linux on Power +Architecture Reference ([LoPAR]_) document is called pSeries. This environment +is also known as sPAPR, System p guests, or simply Power Linux guests (although +it is capable of running other operating systems, such as AIX). Even though pSeries is designed to behave as a guest environment, it is also capable of acting as a hypervisor OS, providing, on that role, nested virtualization capabilities. Supported devices ------------------ +================= * Multi processor support for many Power processors generations: POWER7, POWER7+, POWER8, POWER8NVL, POWER9, and Power10. Support for POWER5+ exists, @@ -26,12 +25,12 @@ Supported devices * PCIe device pass through. Missing devices ---------------- +=============== * SPICE support. Firmware --------- +======== `SLOF `_ (Slimline Open Firmware) is an implementation of the `IEEE 1275-1994, Standard for Boot (Initialization @@ -42,14 +41,14 @@ QEMU includes a prebuilt image of SLOF which is updated when a more recent version is required. Build directions ----------------- +================ .. code-block:: bash ./configure --target-list=ppc64-softmmu && make Running instructions --------------------- +==================== Someone can select the pSeries machine type by running QEMU with the following options: @@ -59,7 +58,7 @@ options: qemu-system-ppc64 -M pseries sPAPR devices -------------- +============= The sPAPR specification defines a set of para-virtualized devices, which are also supported by the pSeries machine in QEMU and can be instantiated with the @@ -102,11 +101,9 @@ device, or specify one with an ID NVRAM device with ``-global spapr-nvram.drive=pfid``. sPAPR specification -^^^^^^^^^^^^^^^^^^^ +------------------- -The main source of documentation on the sPAPR standard is the `Linux on Power -Architecture Reference document (LoPAR) -`_. +The main source of documentation on the sPAPR standard is the [LoPAR]_ document. However, documentation specific to QEMU's implementation of the specification can also be found in QEMU documentation: @@ -124,7 +121,7 @@ Other documentation available in QEMU docs directory: (``/docs/specs/ppc-spapr-uv-hcalls.txt``). Switching between the KVM-PR and KVM-HV kernel module ------------------------------------------------------ +===================================================== Currently, there are two implementations of KVM on Power, ``kvm_hv.ko`` and ``kvm_pr.ko``. @@ -139,7 +136,7 @@ possible to switch between the two modes with the ``kvm-type`` parameter: instead. KVM-PR -^^^^^^ +------ KVM-PR uses the so-called **PR**\ oblem state of the PPC CPUs to run the guests, i.e. the virtual machine is run in user mode and all privileged instructions @@ -166,7 +163,7 @@ In order to run KVM-PR guests with POWER9 processors, someone will need to start QEMU with ``kernel_irqchip=off`` command line option. KVM-HV -^^^^^^ +------ KVM-HV uses the hypervisor mode of more recent Power processors, that allow access to the bare metal hardware directly. Although POWER7 had this capability, @@ -188,7 +185,7 @@ CPUs generations, e.g. you can run a POWER7 guest on a POWER8 host by using ``-cpu POWER8,compat=power7`` as parameter to QEMU. Modules support ---------------- +=============== As noticed in the sections above, each module can run in a different environment. The following table shows with which environment each module can @@ -264,8 +261,11 @@ enabled, whether or not the guest has actually entered secure mode. Maintainer contact information ------------------------------- +============================== Cédric Le Goater Daniel Henrique Barboza + +.. [LoPAR] `Linux on Power Architecture Reference document (LoPAR) revision + 2.9 `_. From e4e27df72fba1cde2d1e030b1bedf26ca8cefe46 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Wed, 12 Jan 2022 11:28:26 +0100 Subject: [PATCH 422/730] target/ppc: powerpc_excp: Extract software TLB logging into a function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabiano Rosas Reviewed-by: David Gibson Reviewed-by: Richard Henderson Message-Id: <20220107222601.4101511-2-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 63 +++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index a779dc936a..2c5d5470de 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -135,6 +135,41 @@ static void dump_hcall(CPUPPCState *env) env->nip); } +static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp) +{ +#if defined(DEBUG_SOFTWARE_TLB) + const char *es; + target_ulong *miss, *cmp; + int en; + + if (!qemu_log_enabled()) { + return; + } + + if (excp == POWERPC_EXCP_IFTLB) { + es = "I"; + en = 'I'; + miss = &env->spr[SPR_IMISS]; + cmp = &env->spr[SPR_ICMP]; + } else { + if (excp == POWERPC_EXCP_DLTLB) { + es = "DL"; + } else { + es = "DS"; + } + en = 'D'; + miss = &env->spr[SPR_DMISS]; + cmp = &env->spr[SPR_DCMP]; + } + qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " + TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 " + TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, + env->spr[SPR_HASH1], env->spr[SPR_HASH2], + env->error_code); +#endif +} + + static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, target_ulong *msr) { @@ -777,34 +812,8 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) } /* fall through */ case POWERPC_EXCP_7x5: -#if defined(DEBUG_SOFTWARE_TLB) - if (qemu_log_enabled()) { - const char *es; - target_ulong *miss, *cmp; - int en; + ppc_excp_debug_sw_tlb(env, excp); - if (excp == POWERPC_EXCP_IFTLB) { - es = "I"; - en = 'I'; - miss = &env->spr[SPR_IMISS]; - cmp = &env->spr[SPR_ICMP]; - } else { - if (excp == POWERPC_EXCP_DLTLB) { - es = "DL"; - } else { - es = "DS"; - } - en = 'D'; - miss = &env->spr[SPR_DMISS]; - cmp = &env->spr[SPR_DCMP]; - } - qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " - TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 " - TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, - env->spr[SPR_HASH1], env->spr[SPR_HASH2], - env->error_code); - } -#endif msr |= env->crf[0] << 28; msr |= env->error_code; /* key, D/I, S/L bits */ /* Set way using a LRU mechanism */ From 2e089eced81e26bb6b8535776faf1bf265a0cdb4 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Wed, 12 Jan 2022 11:28:26 +0100 Subject: [PATCH 423/730] target/ppc: powerpc_excp: Keep 60x/7x5 soft MMU logs active MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the compile time definition and make the logging be controlled by the `-d mmu` option in the cmdline. Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Reviewed-by: David Gibson Message-Id: <20220107222601.4101511-3-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 2c5d5470de..a12ed14c30 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -30,8 +30,6 @@ #include "exec/cpu_ldst.h" #endif -/* #define DEBUG_SOFTWARE_TLB */ - /*****************************************************************************/ /* Exception processing */ #if !defined(CONFIG_USER_ONLY) @@ -137,12 +135,11 @@ static void dump_hcall(CPUPPCState *env) static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp) { -#if defined(DEBUG_SOFTWARE_TLB) const char *es; target_ulong *miss, *cmp; int en; - if (!qemu_log_enabled()) { + if (!qemu_loglevel_mask(CPU_LOG_MMU)) { return; } @@ -166,7 +163,6 @@ static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp) TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, env->spr[SPR_HASH1], env->spr[SPR_HASH2], env->error_code); -#endif } From 4dff75fe95e1aa101567d7052301f125a21323e4 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 424/730] target/ppc: powerpc_excp: Group unimplemented exceptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabiano Rosas Reviewed-by: Cédric Le Goater Reviewed-by: David Gibson Reviewed-by: Richard Henderson Message-Id: <20220107222601.4101511-4-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 77 +++++----------------------------------- 1 file changed, 8 insertions(+), 69 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index a12ed14c30..a52340ac0a 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -700,23 +700,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable/VPU */ env->spr[SPR_BOOKE_ESR] = ESR_SPV; break; - case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ - /* XXX: TODO */ - cpu_abort(cs, "Embedded floating point data exception " - "is not implemented yet !\n"); - env->spr[SPR_BOOKE_ESR] = ESR_SPV; - break; - case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ - /* XXX: TODO */ - cpu_abort(cs, "Embedded floating point round exception " - "is not implemented yet !\n"); - env->spr[SPR_BOOKE_ESR] = ESR_SPV; - break; - case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ - /* XXX: TODO */ - cpu_abort(cs, - "Performance counter exception is not implemented yet !\n"); - break; case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ break; case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ @@ -781,19 +764,6 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ trace_ppc_excp_print("PIT"); break; - case POWERPC_EXCP_IO: /* IO error exception */ - /* XXX: TODO */ - cpu_abort(cs, "601 IO error exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_RUNM: /* Run mode exception */ - /* XXX: TODO */ - cpu_abort(cs, "601 run mode exception is not implemented yet !\n"); - break; - case POWERPC_EXCP_EMUL: /* Emulation trap exception */ - /* XXX: TODO */ - cpu_abort(cs, "602 emulation trap exception " - "is not implemented yet !\n"); - break; case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ @@ -820,56 +790,25 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) break; } break; + case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ + case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ + case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ + case POWERPC_EXCP_IO: /* IO error exception */ + case POWERPC_EXCP_RUNM: /* Run mode exception */ + case POWERPC_EXCP_EMUL: /* Emulation trap exception */ case POWERPC_EXCP_FPA: /* Floating-point assist exception */ - /* XXX: TODO */ - cpu_abort(cs, "Floating point assist exception " - "is not implemented yet !\n"); - break; case POWERPC_EXCP_DABR: /* Data address breakpoint */ - /* XXX: TODO */ - cpu_abort(cs, "DABR exception is not implemented yet !\n"); - break; case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ - /* XXX: TODO */ - cpu_abort(cs, "IABR exception is not implemented yet !\n"); - break; case POWERPC_EXCP_SMI: /* System management interrupt */ - /* XXX: TODO */ - cpu_abort(cs, "SMI exception is not implemented yet !\n"); - break; case POWERPC_EXCP_THERM: /* Thermal interrupt */ - /* XXX: TODO */ - cpu_abort(cs, "Thermal management exception " - "is not implemented yet !\n"); - break; case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ - /* XXX: TODO */ - cpu_abort(cs, - "Performance counter exception is not implemented yet !\n"); - break; case POWERPC_EXCP_VPUA: /* Vector assist exception */ - /* XXX: TODO */ - cpu_abort(cs, "VPU assist exception is not implemented yet !\n"); - break; case POWERPC_EXCP_SOFTP: /* Soft patch exception */ - /* XXX: TODO */ - cpu_abort(cs, - "970 soft-patch exception is not implemented yet !\n"); - break; case POWERPC_EXCP_MAINT: /* Maintenance exception */ - /* XXX: TODO */ - cpu_abort(cs, - "970 maintenance exception is not implemented yet !\n"); - break; case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ - /* XXX: TODO */ - cpu_abort(cs, "Maskable external exception " - "is not implemented yet !\n"); - break; case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ - /* XXX: TODO */ - cpu_abort(cs, "Non maskable external exception " - "is not implemented yet !\n"); + cpu_abort(cs, "%s exception not implemented\n", + powerpc_excp_name(excp)); break; default: excp_invalid: From 516fc1036b06a48042de1309c4e76abda255cf7b Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 425/730] target/ppc: Add HV support to ppc_interrupts_little_endian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ppc_interrupts_little_endian function could be used for interrupts delivered in Hypervisor mode, so add support for powernv8 and powernv9 to it. Also drop the comment because it is inaccurate, all CPUs that can run little endian can have interrupts in little endian. The point is whether they can take interrupts in an endianness different from MSR_LE. This change has no functional impact. Signed-off-by: Fabiano Rosas Reviewed-by: David Gibson Message-Id: <20220107222601.4101511-5-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/arch_dump.c | 2 +- target/ppc/cpu.h | 23 +++++++++++++++-------- target/ppc/excp_helper.c | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c index bb392f6d88..12cde198a3 100644 --- a/target/ppc/arch_dump.c +++ b/target/ppc/arch_dump.c @@ -237,7 +237,7 @@ int cpu_get_dump_info(ArchDumpInfo *info, info->d_machine = PPC_ELF_MACHINE; info->d_class = ELFCLASS; - if (ppc_interrupts_little_endian(cpu)) { + if (ppc_interrupts_little_endian(cpu, false)) { info->d_endian = ELFDATA2LSB; } else { info->d_endian = ELFDATA2MSB; diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index f20d4ffa6d..a6fc857ad4 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -2728,20 +2728,27 @@ static inline bool ppc_has_spr(PowerPCCPU *cpu, int spr) return cpu->env.spr_cb[spr].name != NULL; } -static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu) +#if !defined(CONFIG_USER_ONLY) +static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu, bool hv) { PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); + CPUPPCState *env = &cpu->env; + bool ile = false; - /* - * Only models that have an LPCR and know about LPCR_ILE can do little - * endian. - */ - if (pcc->lpcr_mask & LPCR_ILE) { - return !!(cpu->env.spr[SPR_LPCR] & LPCR_ILE); + if (hv && env->has_hv_mode) { + if (is_isa300(pcc)) { + ile = !!(env->spr[SPR_HID0] & HID0_POWER9_HILE); + } else { + ile = !!(env->spr[SPR_HID0] & HID0_HILE); + } + + } else if (pcc->lpcr_mask & LPCR_ILE) { + ile = !!(env->spr[SPR_LPCR] & LPCR_ILE); } - return false; + return ile; } +#endif void dump_mmu(CPUPPCState *env); diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index a52340ac0a..3a430f23d6 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -1070,7 +1070,7 @@ void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector) */ msr = (1ULL << MSR_ME); msr |= env->msr & (1ULL << MSR_SF); - if (ppc_interrupts_little_endian(cpu)) { + if (ppc_interrupts_little_endian(cpu, false)) { msr |= (1ULL << MSR_LE); } From 2e89484821883457cc76a576cf398a7efde4e052 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 426/730] target/ppc: Add MSR_ILE support to ppc_interrupts_little_endian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some CPUs set ILE via an MSR bit. We can make ppc_interrupts_little_endian handle that case as well. Now we have a centralized way of determining the endianness of interrupts. This change has no functional impact. Signed-off-by: Fabiano Rosas Reviewed-by: David Gibson Message-Id: <20220107222601.4101511-6-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/cpu.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index a6fc857ad4..f99cd0ea92 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -2733,7 +2733,7 @@ static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu, bool hv) { PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); CPUPPCState *env = &cpu->env; - bool ile = false; + bool ile; if (hv && env->has_hv_mode) { if (is_isa300(pcc)) { @@ -2744,6 +2744,8 @@ static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu, bool hv) } else if (pcc->lpcr_mask & LPCR_ILE) { ile = !!(env->spr[SPR_LPCR] & LPCR_ILE); + } else { + ile = !!(msr_ile); } return ile; From 19bd7f5747dc75120f7fdaad7a153aa90d468df0 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 427/730] target/ppc: Use ppc_interrupts_little_endian in powerpc_excp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ppc_interrupts_little_endian function is now suitable for determining the endianness of interrupts for all CPUs. Signed-off-by: Fabiano Rosas Reviewed-by: David Gibson Message-Id: <20220107222601.4101511-7-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 3a430f23d6..3b4123bc65 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -832,36 +832,9 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) * Sort out endianness of interrupt, this differs depending on the * CPU, the HV mode, etc... */ -#ifdef TARGET_PPC64 - if (excp_model == POWERPC_EXCP_POWER7) { - if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) { - new_msr |= (target_ulong)1 << MSR_LE; - } - } else if (excp_model == POWERPC_EXCP_POWER8) { - if (new_msr & MSR_HVB) { - if (env->spr[SPR_HID0] & HID0_HILE) { - new_msr |= (target_ulong)1 << MSR_LE; - } - } else if (env->spr[SPR_LPCR] & LPCR_ILE) { - new_msr |= (target_ulong)1 << MSR_LE; - } - } else if (excp_model == POWERPC_EXCP_POWER9 || - excp_model == POWERPC_EXCP_POWER10) { - if (new_msr & MSR_HVB) { - if (env->spr[SPR_HID0] & HID0_POWER9_HILE) { - new_msr |= (target_ulong)1 << MSR_LE; - } - } else if (env->spr[SPR_LPCR] & LPCR_ILE) { - new_msr |= (target_ulong)1 << MSR_LE; - } - } else if (msr_ile) { + if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) { new_msr |= (target_ulong)1 << MSR_LE; } -#else - if (msr_ile) { - new_msr |= (target_ulong)1 << MSR_LE; - } -#endif #if defined(TARGET_PPC64) if (excp_model == POWERPC_EXCP_BOOKE) { From dc88dd0a864b441453934a26a2c672f33c1d6ee7 Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 428/730] target/ppc: Introduce a wrapper for powerpc_excp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Next patches will split powerpc_excp in multiple family specific handlers. This patch adds a wrapper to make the transition clearer. Signed-off-by: Fabiano Rosas Reviewed-by: David Gibson Message-Id: <20220107222601.4101511-8-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/excp_helper.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 3b4123bc65..bc646c67a0 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -396,7 +396,7 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, * Note that this function should be greatly optimized when called * with a constant excp, from ppc_hw_interrupt */ -static void powerpc_excp(PowerPCCPU *cpu, int excp) +static inline void powerpc_excp_legacy(PowerPCCPU *cpu, int excp) { CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -867,6 +867,16 @@ static void powerpc_excp(PowerPCCPU *cpu, int excp) powerpc_set_excp_state(cpu, vector, new_msr); } +static void powerpc_excp(PowerPCCPU *cpu, int excp) +{ + CPUPPCState *env = &cpu->env; + + switch (env->excp_model) { + default: + powerpc_excp_legacy(cpu, excp); + } +} + void ppc_cpu_do_interrupt(CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); From 5609400a422809c89ea788e4d0e13124a617582e Mon Sep 17 00:00:00 2001 From: Fabiano Rosas Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 429/730] target/ppc: Set the correct endianness for powernv memory dumps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We use the endianness of interrupts to determine which endianness to use for the guest kernel memory dump. For machines that support HILE (powernv8 and up) we have been always generating big endian dump files. This patch uses the HILE support recently added to ppc_interrupts_little_endian to fix the endianness of the dumps for powernv machines. Here are two dumps created at different moments: $ file skiboot.dump skiboot.dump: ELF 64-bit MSB core file, 64-bit PowerPC ... $ file kernel.dump kernel.dump: ELF 64-bit LSB core file, 64-bit PowerPC ... Suggested-by: David Gibson Signed-off-by: Fabiano Rosas Reviewed-by: David Gibson Message-Id: <20220107222601.4101511-9-farosas@linux.ibm.com> Signed-off-by: Cédric Le Goater --- target/ppc/arch_dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c index 12cde198a3..993740897d 100644 --- a/target/ppc/arch_dump.c +++ b/target/ppc/arch_dump.c @@ -237,7 +237,7 @@ int cpu_get_dump_info(ArchDumpInfo *info, info->d_machine = PPC_ELF_MACHINE; info->d_class = ELFCLASS; - if (ppc_interrupts_little_endian(cpu, false)) { + if (ppc_interrupts_little_endian(cpu, cpu->env.has_hv_mode)) { info->d_endian = ELFDATA2LSB; } else { info->d_endian = ELFDATA2MSB; From 392c278302b8e20a7c593708395a6649452d323b Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 430/730] pnv_phb3.c: add unique chassis and slot for pnv_phb3_root_port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When creating a pnv_phb3_root_port using the command line, the first root port is created successfully, but the second fails with the following error: qemu-system-ppc64: -device pnv-phb3-root-port,bus=phb3-root.0,id=pcie.3: Can't add chassis slot, error -16 This error comes from the realize() function of its parent type, rp_realize() from TYPE_PCIE_ROOT_PORT. pcie_chassis_add_slot() fails with -EBUSY if there's an existing PCIESlot that has the same chassis/slot value, regardless of being in a different bus. One way to prevent this error is simply set chassis and slot values in the command line. However, since phb3 root buses only supports a single root port, we can just get an unique chassis/slot value by checking which root bus the pnv_phb3_root_port is going to be attached, get the equivalent phb3 device and use its chip-id and index values, which are guaranteed to be unique. Signed-off-by: Daniel Henrique Barboza Message-Id: <20220105212338.49899-2-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb3.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index c78084cce7..3467bbb5d9 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -1142,8 +1142,24 @@ static const TypeInfo pnv_phb3_root_bus_info = { static void pnv_phb3_root_port_realize(DeviceState *dev, Error **errp) { PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); + PCIDevice *pci = PCI_DEVICE(dev); + PCIBus *bus = pci_get_bus(pci); + PnvPHB3 *phb = NULL; Error *local_err = NULL; + phb = (PnvPHB3 *) object_dynamic_cast(OBJECT(bus->qbus.parent), + TYPE_PNV_PHB3); + + if (!phb) { + error_setg(errp, +"pnv_phb3_root_port devices must be connected to pnv-phb3 buses"); + return; + } + + /* Set unique chassis/slot values for the root port */ + qdev_prop_set_uint8(&pci->qdev, "chassis", phb->chip_id); + qdev_prop_set_uint16(&pci->qdev, "slot", phb->phb_id); + rpc->parent_realize(dev, &local_err); if (local_err) { error_propagate(errp, local_err); From 5ff21d94e2ce0a89ca1a490a31929171cf28e92f Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 431/730] pnv_phb4.c: add unique chassis and slot for pnv_phb4_root_port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A similar situation as described previously with pnv_phb3_root_port devices also happens with pnv_phb4_root_ports. The solution is the same: assign an unique chassis/slot combo for them. Signed-off-by: Daniel Henrique Barboza Message-Id: <20220105212338.49899-3-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 5ba26e250a..836b0c156c 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1338,8 +1338,23 @@ static void pnv_phb4_root_port_reset(DeviceState *dev) static void pnv_phb4_root_port_realize(DeviceState *dev, Error **errp) { PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); + PCIDevice *pci = PCI_DEVICE(dev); + PCIBus *bus = pci_get_bus(pci); + PnvPHB4 *phb = NULL; Error *local_err = NULL; + phb = (PnvPHB4 *) object_dynamic_cast(OBJECT(bus->qbus.parent), + TYPE_PNV_PHB4); + + if (!phb) { + error_setg(errp, "%s must be connected to pnv-phb4 buses", dev->id); + return; + } + + /* Set unique chassis/slot values for the root port */ + qdev_prop_set_uint8(&pci->qdev, "chassis", phb->chip_id); + qdev_prop_set_uint16(&pci->qdev, "slot", phb->phb_id); + rpc->parent_realize(dev, &local_err); if (local_err) { error_propagate(errp, local_err); From a71cd51e2aae333dde272ff83661f9ef0fe62a30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 432/730] ppc/pnv: Attach PHB3 root port device when defaults are enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This cleanups the PHB3 model a bit more since the root port is an independent device and it will ease our task when adding user created PHB3s. pnv_phb_attach_root_port() is made public in pnv.c so it can be reused with the pnv_phb4 root port later. Signed-off-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220105212338.49899-4-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb3.c | 15 ++++++--------- hw/ppc/pnv.c | 8 ++++++++ include/hw/pci-host/pnv_phb3.h | 2 -- include/hw/ppc/pnv.h | 1 + 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index 3467bbb5d9..fdc8d0b437 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -19,6 +19,7 @@ #include "hw/irq.h" #include "hw/qdev-properties.h" #include "qom/object.h" +#include "sysemu/sysemu.h" #define phb3_error(phb, fmt, ...) \ qemu_log_mask(LOG_GUEST_ERROR, "phb3[%d:%d]: " fmt "\n", \ @@ -981,10 +982,6 @@ static void pnv_phb3_instance_init(Object *obj) /* Power Bus Common Queue */ object_initialize_child(obj, "pbcq", &phb->pbcq, TYPE_PNV_PBCQ); - /* Root Port */ - object_initialize_child(obj, "root", &phb->root, TYPE_PNV_PHB3_ROOT_PORT); - qdev_prop_set_int32(DEVICE(&phb->root), "addr", PCI_DEVFN(0, 0)); - qdev_prop_set_bit(DEVICE(&phb->root), "multifunction", false); } static void pnv_phb3_realize(DeviceState *dev, Error **errp) @@ -1053,10 +1050,10 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb); - /* Add a single Root port */ - qdev_prop_set_uint8(DEVICE(&phb->root), "chassis", phb->chip_id); - qdev_prop_set_uint16(DEVICE(&phb->root), "slot", phb->phb_id); - qdev_realize(DEVICE(&phb->root), BUS(pci->bus), &error_fatal); + if (defaults_enabled()) { + pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb), + TYPE_PNV_PHB3_ROOT_PORT); + } } void pnv_phb3_update_regions(PnvPHB3 *phb) @@ -1177,7 +1174,7 @@ static void pnv_phb3_root_port_class_init(ObjectClass *klass, void *data) device_class_set_parent_realize(dc, pnv_phb3_root_port_realize, &rpc->parent_realize); - dc->user_creatable = false; + dc->user_creatable = true; k->vendor_id = PCI_VENDOR_ID_IBM; k->device_id = 0x03dc; diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 9de8b83530..3a263f631a 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1156,6 +1156,14 @@ static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) } } +/* Attach a root port device */ +void pnv_phb_attach_root_port(PCIHostState *pci, const char *name) +{ + PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name); + + pci_realize_and_unref(root, pci->bus, &error_fatal); +} + static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) { PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h index e9c13e6bd8..2e423c3890 100644 --- a/include/hw/pci-host/pnv_phb3.h +++ b/include/hw/pci-host/pnv_phb3.h @@ -155,8 +155,6 @@ struct PnvPHB3 { PnvPBCQState pbcq; - PnvPHB3RootPort root; - QLIST_HEAD(, PnvPhb3DMASpace) dma_spaces; PnvChip *chip; diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index c781525277..c726288e5e 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -177,6 +177,7 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10, TYPE_PNV_CHIP_POWER10) PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir); +void pnv_phb_attach_root_port(PCIHostState *pci, const char *name); #define TYPE_PNV_MACHINE MACHINE_TYPE_NAME("powernv") typedef struct PnvMachineClass PnvMachineClass; From 1360fd832b0d41b00d15574a0e9ecd6d513dbeaa Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 433/730] pnv_phb4.c: make pnv-phb4-root-port user creatable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to create only the absolutely minimal amount of devices when running with -nodefaults. The root port is something that the machine can boot up without. But, to do that, we need to provide a way for the user to add them by hand. This patch makes pnv-phb4-root-port user creatable and then uses the pnv_phb_attach_root_port() helper to add a pnv_phb4_root_port only when running with default settings. Signed-off-by: Daniel Henrique Barboza Message-Id: <20220105212338.49899-5-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 18 +++++++----------- include/hw/pci-host/pnv_phb4.h | 2 -- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 836b0c156c..14827f8464 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -22,6 +22,7 @@ #include "hw/irq.h" #include "hw/qdev-properties.h" #include "qom/object.h" +#include "sysemu/sysemu.h" #include "trace.h" #define phb_error(phb, fmt, ...) \ @@ -1159,12 +1160,6 @@ static void pnv_phb4_instance_init(Object *obj) /* XIVE interrupt source object */ object_initialize_child(obj, "source", &phb->xsrc, TYPE_XIVE_SOURCE); - - /* Root Port */ - object_initialize_child(obj, "root", &phb->root, TYPE_PNV_PHB4_ROOT_PORT); - - qdev_prop_set_int32(DEVICE(&phb->root), "addr", PCI_DEVFN(0, 0)); - qdev_prop_set_bit(DEVICE(&phb->root), "multifunction", false); } static void pnv_phb4_realize(DeviceState *dev, Error **errp) @@ -1208,10 +1203,11 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb); pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; - /* Add a single Root port */ - qdev_prop_set_uint8(DEVICE(&phb->root), "chassis", phb->chip_id); - qdev_prop_set_uint16(DEVICE(&phb->root), "slot", phb->phb_id); - qdev_realize(DEVICE(&phb->root), BUS(pci->bus), &error_fatal); + /* Add a single Root port if running with defaults */ + if (defaults_enabled()) { + pnv_phb_attach_root_port(PCI_HOST_BRIDGE(phb), + TYPE_PNV_PHB4_ROOT_PORT); + } /* Setup XIVE Source */ if (phb->big_phb) { @@ -1369,7 +1365,7 @@ static void pnv_phb4_root_port_class_init(ObjectClass *klass, void *data) PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); dc->desc = "IBM PHB4 PCIE Root Port"; - dc->user_creatable = false; + dc->user_creatable = true; device_class_set_parent_realize(dc, pnv_phb4_root_port_realize, &rpc->parent_realize); diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 4a19338db3..ea63df9676 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -78,8 +78,6 @@ OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4, PNV_PHB4) struct PnvPHB4 { PCIExpressHost parent_obj; - PnvPHB4RootPort root; - uint32_t chip_id; uint32_t phb_id; From e022e5a73a13bf1a67bb044ebbe7376c11ff4d55 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 434/730] pnv_phb4.c: check if root port exists in rc_config functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pnv_phb4_rc_config_read() and pnv_phb4_rc_config_write() are asserting the existence of the root port. The root port is now optional, and there will be cases where a pnv-phb4 device won't have a root port attached. Instead of asserting, check if the root port exists before read/writing into it. Signed-off-by: Daniel Henrique Barboza Message-Id: <20220105212338.49899-6-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 14827f8464..83dedc878a 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -152,7 +152,10 @@ static void pnv_phb4_rc_config_write(PnvPHB4 *phb, unsigned off, } pdev = pci_find_device(pci->bus, 0, 0); - assert(pdev); + if (!pdev) { + phb_error(phb, "rc_config_write device not found\n"); + return; + } pci_host_config_write_common(pdev, off, PHB_RC_CONFIG_SIZE, bswap32(val), 4); @@ -171,7 +174,10 @@ static uint64_t pnv_phb4_rc_config_read(PnvPHB4 *phb, unsigned off, } pdev = pci_find_device(pci->bus, 0, 0); - assert(pdev); + if (!pdev) { + phb_error(phb, "rc_config_read device not found\n"); + return ~0ull; + } val = pci_host_config_read_common(pdev, off, PHB_RC_CONFIG_SIZE, 4); return bswap32(val); From 1f6a88fffc7533a9fd64c74c298d82590277cb3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 435/730] ppc/pnv: Introduce support for user created PHB3 devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PHB3 devices and PCI devices can now be added to the powernv8 machine using : -device pnv-phb3,chip-id=0,index=1 \ -device nec-usb-xhci,bus=pci.1,addr=0x0 The 'index' property identifies the PHB3 in the chip. In case of user created devices, a lookup on 'chip-id' is required to assign the owning chip. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater Message-Id: <20220105212338.49899-7-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb3.c | 11 ++++++++++- hw/ppc/pnv.c | 23 ++++++++++++++++++----- include/hw/ppc/pnv.h | 2 ++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index fdc8d0b437..1ebe43df5d 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -991,6 +991,15 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); int i; + /* User created devices */ + if (!phb->chip) { + phb->chip = pnv_get_chip(pnv, phb->chip_id); + if (!phb->chip) { + error_setg(errp, "invalid chip id: %d", phb->chip_id); + return; + } + } + if (phb->phb_id >= PNV_CHIP_GET_CLASS(phb->chip)->num_phbs) { error_setg(errp, "invalid PHB index: %d", phb->phb_id); return; @@ -1104,7 +1113,7 @@ static void pnv_phb3_class_init(ObjectClass *klass, void *data) dc->realize = pnv_phb3_realize; device_class_set_props(dc, pnv_phb3_properties); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->user_creatable = false; + dc->user_creatable = true; } static const TypeInfo pnv_phb3_type_info = { diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 3a263f631a..ad02d56aa7 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1117,14 +1117,14 @@ static void pnv_chip_power8_instance_init(Object *obj) object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER); - for (i = 0; i < pcc->num_phbs; i++) { + if (defaults_enabled()) { + chip->num_phbs = pcc->num_phbs; + } + + for (i = 0; i < chip->num_phbs; i++) { object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3); } - /* - * Number of PHBs is the chip default - */ - chip->num_phbs = pcc->num_phbs; } static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) @@ -1814,6 +1814,19 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq) return NULL; } +PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id) +{ + int i; + + for (i = 0; i < pnv->num_chips; i++) { + PnvChip *chip = pnv->chips[i]; + if (chip->chip_id == chip_id) { + return chip; + } + } + return NULL; +} + static int pnv_ics_resend_child(Object *child, void *opaque) { PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3); diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index c726288e5e..64bab7112b 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -218,6 +218,8 @@ struct PnvMachineState { hwaddr fw_load_addr; }; +PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id); + #define PNV_FDT_ADDR 0x01000000 #define PNV_TIMEBASE_FREQ 512000000ULL From c29dd0034deafc9772eb256f7b4cea16c5bffd65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 436/730] ppc/pnv: Reparent user created PHB3 devices to the PnvChip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The powernv machine uses the object hierarchy to populate the device tree and each device should be parented to the chip it belongs to. This is not the case for user created devices which are parented to the container "/unattached". Make sure a PHB3 device is parented to its chip by reparenting the object if necessary. Reviewed-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Signed-off-by: Cédric Le Goater Message-Id: <20220105212338.49899-8-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb3.c | 6 ++++++ hw/ppc/pnv.c | 17 +++++++++++++++++ include/hw/ppc/pnv.h | 1 + 3 files changed, 24 insertions(+) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index 1ebe43df5d..a52aedcad3 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -998,6 +998,12 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) error_setg(errp, "invalid chip id: %d", phb->chip_id); return; } + + /* + * Reparent user created devices to the chip to build + * correctly the device tree. + */ + pnv_chip_parent_fixup(phb->chip, OBJECT(phb), phb->phb_id); } if (phb->phb_id >= PNV_CHIP_GET_CLASS(phb->chip)->num_phbs) { diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index ad02d56aa7..fa5e7bc751 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1814,6 +1814,23 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq) return NULL; } +void pnv_chip_parent_fixup(PnvChip *chip, Object *obj, int index) +{ + Object *parent = OBJECT(chip); + g_autofree char *default_id = + g_strdup_printf("%s[%d]", object_get_typename(obj), index); + + if (obj->parent == parent) { + return; + } + + object_ref(obj); + object_unparent(obj); + object_property_add_child( + parent, DEVICE(obj)->id ? DEVICE(obj)->id : default_id, obj); + object_unref(obj); +} + PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id) { int i; diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index 64bab7112b..f4219da7c5 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -178,6 +178,7 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10, PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir); void pnv_phb_attach_root_port(PCIHostState *pci, const char *name); +void pnv_chip_parent_fixup(PnvChip *chip, Object *obj, int index); #define TYPE_PNV_MACHINE MACHINE_TYPE_NAME("powernv") typedef struct PnvMachineClass PnvMachineClass; From db041b06e67f1010620c696011f8c867275dac42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 437/730] ppc/pnv: Complete user created PHB3 devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PHB3s ared SysBus devices and should be allowed to be dynamically created. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater Message-Id: <20220105212338.49899-9-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb3.c | 9 +++++++++ hw/ppc/pnv.c | 2 ++ 2 files changed, 11 insertions(+) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index a52aedcad3..7fb35dc031 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -993,6 +993,9 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) /* User created devices */ if (!phb->chip) { + Error *local_err = NULL; + BusState *s; + phb->chip = pnv_get_chip(pnv, phb->chip_id); if (!phb->chip) { error_setg(errp, "invalid chip id: %d", phb->chip_id); @@ -1004,6 +1007,12 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) * correctly the device tree. */ pnv_chip_parent_fixup(phb->chip, OBJECT(phb), phb->phb_id); + + s = qdev_get_parent_bus(DEVICE(phb->chip)); + if (!qdev_set_parent_bus(DEVICE(phb), s, &local_err)) { + error_propagate(errp, local_err); + return; + } } if (phb->phb_id >= PNV_CHIP_GET_CLASS(phb->chip)->num_phbs) { diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index fa5e7bc751..8dc6382357 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1941,6 +1941,8 @@ static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) pmc->compat = compat; pmc->compat_size = sizeof(compat); + + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB3); } static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) From eb93c82888f4d19c00ac1aafaec23346c2e899b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 438/730] ppc/pnv: Move num_phbs under Pnv8Chip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is not used elsewhere so that's where it belongs. Signed-off-by: Cédric Le Goater Message-Id: <20220105212338.49899-10-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/ppc/pnv.c | 7 +++---- include/hw/ppc/pnv.h | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 8dc6382357..fe7e67e73a 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1099,7 +1099,6 @@ static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, static void pnv_chip_power8_instance_init(Object *obj) { - PnvChip *chip = PNV_CHIP(obj); Pnv8Chip *chip8 = PNV8_CHIP(obj); PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); int i; @@ -1118,10 +1117,10 @@ static void pnv_chip_power8_instance_init(Object *obj) object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER); if (defaults_enabled()) { - chip->num_phbs = pcc->num_phbs; + chip8->num_phbs = pcc->num_phbs; } - for (i = 0; i < chip->num_phbs; i++) { + for (i = 0; i < chip8->num_phbs; i++) { object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3); } @@ -1247,7 +1246,7 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) &chip8->homer.regs); /* PHB3 controllers */ - for (i = 0; i < chip->num_phbs; i++) { + for (i = 0; i < chip8->num_phbs; i++) { PnvPHB3 *phb = &chip8->phbs[i]; object_property_set_int(OBJECT(phb), "index", i, &error_fatal); diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index f4219da7c5..0e9e16544f 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -52,7 +52,6 @@ struct PnvChip { uint64_t cores_mask; PnvCore **cores; - uint32_t num_phbs; uint32_t num_pecs; MemoryRegion xscom_mmio; @@ -82,6 +81,7 @@ struct Pnv8Chip { #define PNV8_CHIP_PHB3_MAX 4 PnvPHB3 phbs[PNV8_CHIP_PHB3_MAX]; + uint32_t num_phbs; XICSFabric *xics; }; @@ -136,8 +136,8 @@ struct PnvChipClass { /*< public >*/ uint64_t chip_cfam_id; uint64_t cores_mask; - uint32_t num_phbs; uint32_t num_pecs; + uint32_t num_phbs; DeviceRealize parent_realize; From 41cb8d319df0488f31abd11519f21daf76ee1459 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 439/730] pnv_phb3.h: change TYPE_PNV_PHB3_ROOT_BUS name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TYPE_PNV_PHB3_ROOT_BUS name is used as the default bus name when the dev has no 'id'. However, pnv-phb3-root-bus is a bit too long to be used as a bus name. Most common QEMU buses and PCI controllers are named based on their bus type (e.g. pSeries spapr-pci-host-bridge is called 'pci'). The most common name for a PCIE bus controller in QEMU is 'pcie'. Naming it 'pcie' would break the documented use of the pnv-phb3 device, since 'pcie.0' would now refer to the root bus instead of the first root port. There's nothing particularly wrong with the 'root-bus' name used before, aside from the fact that 'root-bus' is being used for pnv-phb3 and pnv-phb4 created buses, which is not quite correct since these buses aren't implemented the same way in QEMU - you can't plug a pnv-phb4-root-port into a pnv-phb3 root bus, for example. This patch renames it as 'pnv-phb3-root', which is a compromise between the existing and the previously used name. Creating 3 phbs without ID will result in an "info qtree" output similar to this: bus: main-system-bus type System dev: pnv-phb3, id "" index = 2 (0x2) chip-id = 0 (0x0) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb3-root.2 type pnv-phb3-root (...) dev: pnv-phb3, id "" index = 1 (0x1) chip-id = 0 (0x0) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb3-root.1 type pnv-phb3-root (...) dev: pnv-phb3, id "" index = 0 (0x0) chip-id = 0 (0x0) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb3-root.0 type pnv-phb3-root Signed-off-by: Daniel Henrique Barboza Message-Id: <20220105212338.49899-11-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- include/hw/pci-host/pnv_phb3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h index 2e423c3890..af6ec83cf6 100644 --- a/include/hw/pci-host/pnv_phb3.h +++ b/include/hw/pci-host/pnv_phb3.h @@ -105,7 +105,7 @@ struct PnvPBCQState { /* * PHB3 PCIe Root port */ -#define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root-bus" +#define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root" #define TYPE_PNV_PHB3_ROOT_PORT "pnv-phb3-root-port" From 451575816c07284f7620b88e2208086588288925 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 440/730] pnv_phb4.c: change TYPE_PNV_PHB4_ROOT_BUS name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to what was happening with pnv-phb3 buses, TYPE_PNV_PHB4_ROOT_BUS set to "pnv-phb4-root-bus" is a bit too long for a default root bus name. The usual default name for theses buses in QEMU are 'pcie', but we want to make a distinction between pnv-phb4 buses and other PCIE buses, at least as far as default name goes, because not all PCIE devices are attachable to a pnv-phb4 root-bus type. Changing the default to 'pnv-phb4-root' allow us to have a shorter name while making this bus distinct, and the user can always set its own bus naming via the "id" attribute anyway. This is the 'info qtree' output after this change, using a powernv9 domain with 2 sockets and default settings enabled: qemu-system-ppc64 -m 4G -machine powernv9,accel=tcg \ -smp 2,sockets=2,cores=1,threads=1 dev: pnv-phb4, id "" index = 5 (0x5) chip-id = 1 (0x1) version = 704374636546 (0xa400000002) device-id = 1217 (0x4c1) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb4-root.11 type pnv-phb4-root dev: pnv-phb4-root-port, id "" (...) dev: pnv-phb4, id "" index = 0 (0x0) chip-id = 1 (0x1) version = 704374636546 (0xa400000002) device-id = 1217 (0x4c1) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb4-root.6 type pnv-phb4-root dev: pnv-phb4-root-port, id "" (..) dev: pnv-phb4, id "" index = 5 (0x5) chip-id = 0 (0x0) version = 704374636546 (0xa400000002) device-id = 1217 (0x4c1) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb4-root.5 type pnv-phb4-root dev: pnv-phb4-root-port, id "" (...) dev: pnv-phb4, id "" index = 0 (0x0) chip-id = 0 (0x0) version = 704374636546 (0xa400000002) device-id = 1217 (0x4c1) x-config-reg-migration-enabled = true bypass-iommu = false bus: pnv-phb4-root.0 type pnv-phb4-root dev: pnv-phb4-root-port, id "" Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220110143346.455901-11-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- include/hw/pci-host/pnv_phb4.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index ea63df9676..88dc6abb1c 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -46,7 +46,7 @@ typedef struct PnvPhb4DMASpace { /* * PHB4 PCIe Root port */ -#define TYPE_PNV_PHB4_ROOT_BUS "pnv-phb4-root-bus" +#define TYPE_PNV_PHB4_ROOT_BUS "pnv-phb4-root" #define TYPE_PNV_PHB4_ROOT_PORT "pnv-phb4-root-port" typedef struct PnvPHB4RootPort { From 5032f5d70524af38259a27fb132a57cd3ca40619 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 441/730] pnv_phb4_pec.c: move pnv_pec_phb_offset() to pnv_phb4.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The logic inside pnv_pec_phb_offset() will be useful in the next patch to determine the stack that should contain a PHB4 device. Move the function to pnv_phb4.c and make it public since there's no pnv_phb4_pec.h header. While we're at it, add 'stack_index' as a parameter and make the function return 'phb-id' directly. And rename it to pnv_phb4_pec_get_phb_id() to be even clearer about the function intent. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220110143346.455901-3-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 17 +++++++++++++++++ hw/pci-host/pnv_phb4_pec.c | 15 +-------------- include/hw/pci-host/pnv_phb4.h | 2 ++ 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 83dedc878a..2223b985b2 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1069,6 +1069,23 @@ static const TypeInfo pnv_phb4_iommu_memory_region_info = { .class_init = pnv_phb4_iommu_memory_region_class_init, }; +/* + * Return the index/phb-id of a PHB4 that belongs to a + * pec->stacks[stack_index] stack. + */ +int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index) +{ + PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); + int index = pec->index; + int offset = 0; + + while (index--) { + offset += pecc->num_stacks[index]; + } + + return offset + stack_index; +} + /* * MSI/MSIX memory region implementation. * The handler handles both MSI and MSIX. diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index f3e4fa0c82..49360de8c8 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -374,19 +374,6 @@ static void pnv_pec_instance_init(Object *obj) } } -static int pnv_pec_phb_offset(PnvPhb4PecState *pec) -{ - PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); - int index = pec->index; - int offset = 0; - - while (index--) { - offset += pecc->num_stacks[index]; - } - - return offset; -} - static void pnv_pec_realize(DeviceState *dev, Error **errp) { PnvPhb4PecState *pec = PNV_PHB4_PEC(dev); @@ -405,7 +392,7 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp) for (i = 0; i < pec->num_stacks; i++) { PnvPhb4PecStack *stack = &pec->stacks[i]; Object *stk_obj = OBJECT(stack); - int phb_id = pnv_pec_phb_offset(pec) + i; + int phb_id = pnv_phb4_pec_get_phb_id(pec, i); object_property_set_int(stk_obj, "stack-no", i, &error_abort); object_property_set_int(stk_obj, "phb-id", phb_id, &error_abort); diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 88dc6abb1c..5ee996ebc6 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -15,6 +15,7 @@ #include "hw/ppc/xive.h" #include "qom/object.h" +typedef struct PnvPhb4PecState PnvPhb4PecState; typedef struct PnvPhb4PecStack PnvPhb4PecStack; typedef struct PnvPHB4 PnvPHB4; typedef struct PnvChip PnvChip; @@ -131,6 +132,7 @@ struct PnvPHB4 { void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon); void pnv_phb4_update_regions(PnvPhb4PecStack *stack); +int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index); extern const MemoryRegionOps pnv_phb4_xscom_ops; /* From d22b0c94e4c9c5bba1224b9fd6dcc23373af0261 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 442/730] pnv_phb4_pec: use pnv_phb4_pec_get_phb_id() in pnv_pec_dt_xscom() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Relying on stack->phb to write the xscom DT of the PEC is something that we won't be able to do with user creatable pnv-phb4 devices. Hopefully, this can be done by using pnv_phb4_pec_get_phb_id(), which is already used by pnv_pec_realize() to set the phb-id of the stack. Use the same idea in pnv_pec_dt_xscom() to write ibm,phb-index without the need to accessing stack->phb, since stack->phb is not granted to be != NULL when user creatable phbs are introduced. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220110143346.455901-4-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4_pec.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 49360de8c8..d64310e7db 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -449,8 +449,7 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt, pecc->compat_size))); for (i = 0; i < pec->num_stacks; i++) { - PnvPhb4PecStack *stack = &pec->stacks[i]; - PnvPHB4 *phb = &stack->phb; + int phb_id = pnv_phb4_pec_get_phb_id(pec, i); int stk_offset; name = g_strdup_printf("stack@%x", i); @@ -460,7 +459,7 @@ static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt, _FDT((fdt_setprop(fdt, stk_offset, "compatible", pecc->stk_compat, pecc->stk_compat_size))); _FDT((fdt_setprop_cell(fdt, stk_offset, "reg", i))); - _FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", phb->phb_id))); + _FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", phb_id))); } return 0; From b580713a962ecb4b5aa928975799b8c9e970c880 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 443/730] ppc/pnv: set phb4 properties in stk_realize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moving all phb4 properties setup to stk_realize() keeps this logic in a single place instead of having it scattered between stk_realize() and pec_realize(). 'phb->index' can be retrieved using stack->stack_no and pnv_phb4_pec_get_phb_id(), deprecating the use of 'phb-id' alias that was being used for this purpose in pec_realize(). Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220111131027.599784-2-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4_pec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index d64310e7db..f8038dff17 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -392,10 +392,8 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp) for (i = 0; i < pec->num_stacks; i++) { PnvPhb4PecStack *stack = &pec->stacks[i]; Object *stk_obj = OBJECT(stack); - int phb_id = pnv_phb4_pec_get_phb_id(pec, i); object_property_set_int(stk_obj, "stack-no", i, &error_abort); - object_property_set_int(stk_obj, "phb-id", phb_id, &error_abort); object_property_set_link(stk_obj, "pec", OBJECT(pec), &error_abort); if (!qdev_realize(DEVICE(stk_obj), NULL, errp)) { return; @@ -534,7 +532,6 @@ static void pnv_pec_stk_instance_init(Object *obj) PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(obj); object_initialize_child(obj, "phb", &stack->phb, TYPE_PNV_PHB4); - object_property_add_alias(obj, "phb-id", OBJECT(&stack->phb), "index"); } static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) @@ -543,6 +540,7 @@ static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) PnvPhb4PecState *pec = stack->pec; PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); PnvChip *chip = pec->chip; + int phb_id = pnv_phb4_pec_get_phb_id(pec, stack->stack_no); uint32_t pec_nest_base; uint32_t pec_pci_base; char name[64]; @@ -570,6 +568,8 @@ static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) object_property_set_int(OBJECT(&stack->phb), "chip-id", pec->chip_id, &error_fatal); + object_property_set_int(OBJECT(&stack->phb), "index", phb_id, + &error_fatal); object_property_set_int(OBJECT(&stack->phb), "version", pecc->version, &error_fatal); object_property_set_link(OBJECT(&stack->phb), "stack", OBJECT(stack), From 3d2adf1713b298206f831b78c00218a4e6e3ddad Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 444/730] ppc/pnv: move PHB4 XSCOM init to phb4_realize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'stack->phb_regs_mr' PHB4 passthrough XSCOM initialization relies on 'stack->phb' being not NULL. Moving 'stack->phb_regs_mr' region_init() and add_subregion() to phb4_realize() time is a natural thing to do since it's strictly PHB related. The remaining XSCOM initialization is also related to 'stack->phb' but in a different manner. For instance, 'stack->nest_regs_mr' MemoryRegionOps, 'pnv_pec_stk_nest_xscom_ops', uses pnv_pec_stk_nest_xscom_write() as a write callback. When trying to write the PEC_NEST_STK_BAR_EN reg, pnv_pec_stk_update_map() is called. Inside this function, pnv_phb4_update_regions() is called twice. This function uses 'stack->phb' to manipulate memory regions of the phb. This is not a problem now but, when enabling user creatable phb4s, a stack that doesn't have an associated phb (i.e. stack->phb = NULL) it will cause a SIGINT during boot in pnv_phb4_update_regions(). All this can be avoided if all XSCOM realize is moved to phb4_realize(), when we have certainty about the existence of 'stack->phb'. A lot of code was moved from pnv_phb4_pec.c to pnv_phb4.c due to static constant and variables being used but the cleaner logic is worth the trouble. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220111131027.599784-3-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 304 +++++++++++++++++++++++++++++++++++++ hw/pci-host/pnv_phb4_pec.c | 292 ----------------------------------- 2 files changed, 304 insertions(+), 292 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 2223b985b2..8ef58bf2de 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -29,6 +29,10 @@ qemu_log_mask(LOG_GUEST_ERROR, "phb4[%d:%d]: " fmt "\n", \ (phb)->chip_id, (phb)->phb_id, ## __VA_ARGS__) +#define phb_pec_error(pec, fmt, ...) \ + qemu_log_mask(LOG_GUEST_ERROR, "phb4_pec[%d:%d]: " fmt "\n", \ + (pec)->chip_id, (pec)->index, ## __VA_ARGS__) + /* * QEMU version of the GETFIELD/SETFIELD macros * @@ -854,6 +858,258 @@ const MemoryRegionOps pnv_phb4_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; +static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr, + unsigned size) +{ + PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); + uint32_t reg = addr >> 3; + + /* TODO: add list of allowed registers and error out if not */ + return stack->nest_regs[reg]; +} + +static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) +{ + PnvPhb4PecState *pec = stack->pec; + MemoryRegion *sysmem = get_system_memory(); + uint64_t bar_en = stack->nest_regs[PEC_NEST_STK_BAR_EN]; + uint64_t bar, mask, size; + char name[64]; + + /* + * NOTE: This will really not work well if those are remapped + * after the PHB has created its sub regions. We could do better + * if we had a way to resize regions but we don't really care + * that much in practice as the stuff below really only happens + * once early during boot + */ + + /* Handle unmaps */ + if (memory_region_is_mapped(&stack->mmbar0) && + !(bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) { + memory_region_del_subregion(sysmem, &stack->mmbar0); + } + if (memory_region_is_mapped(&stack->mmbar1) && + !(bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) { + memory_region_del_subregion(sysmem, &stack->mmbar1); + } + if (memory_region_is_mapped(&stack->phbbar) && + !(bar_en & PEC_NEST_STK_BAR_EN_PHB)) { + memory_region_del_subregion(sysmem, &stack->phbbar); + } + if (memory_region_is_mapped(&stack->intbar) && + !(bar_en & PEC_NEST_STK_BAR_EN_INT)) { + memory_region_del_subregion(sysmem, &stack->intbar); + } + + /* Update PHB */ + pnv_phb4_update_regions(stack); + + /* Handle maps */ + if (!memory_region_is_mapped(&stack->mmbar0) && + (bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) { + bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0] >> 8; + mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0_MASK]; + size = ((~mask) >> 8) + 1; + snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio0", + pec->chip_id, pec->index, stack->stack_no); + memory_region_init(&stack->mmbar0, OBJECT(stack), name, size); + memory_region_add_subregion(sysmem, bar, &stack->mmbar0); + stack->mmio0_base = bar; + stack->mmio0_size = size; + } + if (!memory_region_is_mapped(&stack->mmbar1) && + (bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) { + bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1] >> 8; + mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1_MASK]; + size = ((~mask) >> 8) + 1; + snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio1", + pec->chip_id, pec->index, stack->stack_no); + memory_region_init(&stack->mmbar1, OBJECT(stack), name, size); + memory_region_add_subregion(sysmem, bar, &stack->mmbar1); + stack->mmio1_base = bar; + stack->mmio1_size = size; + } + if (!memory_region_is_mapped(&stack->phbbar) && + (bar_en & PEC_NEST_STK_BAR_EN_PHB)) { + bar = stack->nest_regs[PEC_NEST_STK_PHB_REGS_BAR] >> 8; + size = PNV_PHB4_NUM_REGS << 3; + snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-phb", + pec->chip_id, pec->index, stack->stack_no); + memory_region_init(&stack->phbbar, OBJECT(stack), name, size); + memory_region_add_subregion(sysmem, bar, &stack->phbbar); + } + if (!memory_region_is_mapped(&stack->intbar) && + (bar_en & PEC_NEST_STK_BAR_EN_INT)) { + bar = stack->nest_regs[PEC_NEST_STK_INT_BAR] >> 8; + size = PNV_PHB4_MAX_INTs << 16; + snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-int", + stack->pec->chip_id, stack->pec->index, stack->stack_no); + memory_region_init(&stack->intbar, OBJECT(stack), name, size); + memory_region_add_subregion(sysmem, bar, &stack->intbar); + } + + /* Update PHB */ + pnv_phb4_update_regions(stack); +} + +static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); + PnvPhb4PecState *pec = stack->pec; + uint32_t reg = addr >> 3; + + switch (reg) { + case PEC_NEST_STK_PCI_NEST_FIR: + stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] = val; + break; + case PEC_NEST_STK_PCI_NEST_FIR_CLR: + stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] &= val; + break; + case PEC_NEST_STK_PCI_NEST_FIR_SET: + stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] |= val; + break; + case PEC_NEST_STK_PCI_NEST_FIR_MSK: + stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] = val; + break; + case PEC_NEST_STK_PCI_NEST_FIR_MSKC: + stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] &= val; + break; + case PEC_NEST_STK_PCI_NEST_FIR_MSKS: + stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] |= val; + break; + case PEC_NEST_STK_PCI_NEST_FIR_ACT0: + case PEC_NEST_STK_PCI_NEST_FIR_ACT1: + stack->nest_regs[reg] = val; + break; + case PEC_NEST_STK_PCI_NEST_FIR_WOF: + stack->nest_regs[reg] = 0; + break; + case PEC_NEST_STK_ERR_REPORT_0: + case PEC_NEST_STK_ERR_REPORT_1: + case PEC_NEST_STK_PBCQ_GNRL_STATUS: + /* Flag error ? */ + break; + case PEC_NEST_STK_PBCQ_MODE: + stack->nest_regs[reg] = val & 0xff00000000000000ull; + break; + case PEC_NEST_STK_MMIO_BAR0: + case PEC_NEST_STK_MMIO_BAR0_MASK: + case PEC_NEST_STK_MMIO_BAR1: + case PEC_NEST_STK_MMIO_BAR1_MASK: + if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & + (PEC_NEST_STK_BAR_EN_MMIO0 | + PEC_NEST_STK_BAR_EN_MMIO1)) { + phb_pec_error(pec, "Changing enabled BAR unsupported\n"); + } + stack->nest_regs[reg] = val & 0xffffffffff000000ull; + break; + case PEC_NEST_STK_PHB_REGS_BAR: + if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_PHB) { + phb_pec_error(pec, "Changing enabled BAR unsupported\n"); + } + stack->nest_regs[reg] = val & 0xffffffffffc00000ull; + break; + case PEC_NEST_STK_INT_BAR: + if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_INT) { + phb_pec_error(pec, "Changing enabled BAR unsupported\n"); + } + stack->nest_regs[reg] = val & 0xfffffff000000000ull; + break; + case PEC_NEST_STK_BAR_EN: + stack->nest_regs[reg] = val & 0xf000000000000000ull; + pnv_pec_stk_update_map(stack); + break; + case PEC_NEST_STK_DATA_FRZ_TYPE: + case PEC_NEST_STK_PBCQ_TUN_BAR: + /* Not used for now */ + stack->nest_regs[reg] = val; + break; + default: + qemu_log_mask(LOG_UNIMP, "phb4_pec: nest_xscom_write 0x%"HWADDR_PRIx + "=%"PRIx64"\n", addr, val); + } +} + +static const MemoryRegionOps pnv_pec_stk_nest_xscom_ops = { + .read = pnv_pec_stk_nest_xscom_read, + .write = pnv_pec_stk_nest_xscom_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static uint64_t pnv_pec_stk_pci_xscom_read(void *opaque, hwaddr addr, + unsigned size) +{ + PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); + uint32_t reg = addr >> 3; + + /* TODO: add list of allowed registers and error out if not */ + return stack->pci_regs[reg]; +} + +static void pnv_pec_stk_pci_xscom_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); + uint32_t reg = addr >> 3; + + switch (reg) { + case PEC_PCI_STK_PCI_FIR: + stack->nest_regs[reg] = val; + break; + case PEC_PCI_STK_PCI_FIR_CLR: + stack->nest_regs[PEC_PCI_STK_PCI_FIR] &= val; + break; + case PEC_PCI_STK_PCI_FIR_SET: + stack->nest_regs[PEC_PCI_STK_PCI_FIR] |= val; + break; + case PEC_PCI_STK_PCI_FIR_MSK: + stack->nest_regs[reg] = val; + break; + case PEC_PCI_STK_PCI_FIR_MSKC: + stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] &= val; + break; + case PEC_PCI_STK_PCI_FIR_MSKS: + stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] |= val; + break; + case PEC_PCI_STK_PCI_FIR_ACT0: + case PEC_PCI_STK_PCI_FIR_ACT1: + stack->nest_regs[reg] = val; + break; + case PEC_PCI_STK_PCI_FIR_WOF: + stack->nest_regs[reg] = 0; + break; + case PEC_PCI_STK_ETU_RESET: + stack->nest_regs[reg] = val & 0x8000000000000000ull; + /* TODO: Implement reset */ + break; + case PEC_PCI_STK_PBAIB_ERR_REPORT: + break; + case PEC_PCI_STK_PBAIB_TX_CMD_CRED: + case PEC_PCI_STK_PBAIB_TX_DAT_CRED: + stack->nest_regs[reg] = val; + break; + default: + qemu_log_mask(LOG_UNIMP, "phb4_pec_stk: pci_xscom_write 0x%"HWADDR_PRIx + "=%"PRIx64"\n", addr, val); + } +} + +static const MemoryRegionOps pnv_pec_stk_pci_xscom_ops = { + .read = pnv_pec_stk_pci_xscom_read, + .write = pnv_pec_stk_pci_xscom_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + static int pnv_phb4_map_irq(PCIDevice *pci_dev, int irq_num) { /* Check that out properly ... */ @@ -1175,6 +1431,52 @@ static AddressSpace *pnv_phb4_dma_iommu(PCIBus *bus, void *opaque, int devfn) return &ds->dma_as; } +static void pnv_phb4_xscom_realize(PnvPHB4 *phb) +{ + PnvPhb4PecStack *stack = phb->stack; + PnvPhb4PecState *pec = stack->pec; + PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); + uint32_t pec_nest_base; + uint32_t pec_pci_base; + char name[64]; + + assert(pec); + + /* Initialize the XSCOM regions for the stack registers */ + snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest-stack-%d", + pec->chip_id, pec->index, stack->stack_no); + pnv_xscom_region_init(&stack->nest_regs_mr, OBJECT(stack), + &pnv_pec_stk_nest_xscom_ops, stack, name, + PHB4_PEC_NEST_STK_REGS_COUNT); + + snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d", + pec->chip_id, pec->index, stack->stack_no); + pnv_xscom_region_init(&stack->pci_regs_mr, OBJECT(stack), + &pnv_pec_stk_pci_xscom_ops, stack, name, + PHB4_PEC_PCI_STK_REGS_COUNT); + + /* PHB pass-through */ + snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d-phb", + pec->chip_id, pec->index, stack->stack_no); + pnv_xscom_region_init(&stack->phb_regs_mr, OBJECT(phb), + &pnv_phb4_xscom_ops, phb, name, 0x40); + + pec_nest_base = pecc->xscom_nest_base(pec); + pec_pci_base = pecc->xscom_pci_base(pec); + + /* Populate the XSCOM address space. */ + pnv_xscom_add_subregion(pec->chip, + pec_nest_base + 0x40 * (stack->stack_no + 1), + &stack->nest_regs_mr); + pnv_xscom_add_subregion(pec->chip, + pec_pci_base + 0x40 * (stack->stack_no + 1), + &stack->pci_regs_mr); + pnv_xscom_add_subregion(pec->chip, + pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 + + 0x40 * stack->stack_no, + &stack->phb_regs_mr); +} + static void pnv_phb4_instance_init(Object *obj) { PnvPHB4 *phb = PNV_PHB4(obj); @@ -1247,6 +1549,8 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) pnv_phb4_update_xsrc(phb); phb->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs); + + pnv_phb4_xscom_realize(phb); } static const char *pnv_phb4_root_bus_path(PCIHostState *host_bridge, diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index f8038dff17..bf0fdf33fd 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -111,258 +111,6 @@ static const MemoryRegionOps pnv_pec_pci_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr, - unsigned size) -{ - PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); - uint32_t reg = addr >> 3; - - /* TODO: add list of allowed registers and error out if not */ - return stack->nest_regs[reg]; -} - -static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) -{ - PnvPhb4PecState *pec = stack->pec; - MemoryRegion *sysmem = get_system_memory(); - uint64_t bar_en = stack->nest_regs[PEC_NEST_STK_BAR_EN]; - uint64_t bar, mask, size; - char name[64]; - - /* - * NOTE: This will really not work well if those are remapped - * after the PHB has created its sub regions. We could do better - * if we had a way to resize regions but we don't really care - * that much in practice as the stuff below really only happens - * once early during boot - */ - - /* Handle unmaps */ - if (memory_region_is_mapped(&stack->mmbar0) && - !(bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) { - memory_region_del_subregion(sysmem, &stack->mmbar0); - } - if (memory_region_is_mapped(&stack->mmbar1) && - !(bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) { - memory_region_del_subregion(sysmem, &stack->mmbar1); - } - if (memory_region_is_mapped(&stack->phbbar) && - !(bar_en & PEC_NEST_STK_BAR_EN_PHB)) { - memory_region_del_subregion(sysmem, &stack->phbbar); - } - if (memory_region_is_mapped(&stack->intbar) && - !(bar_en & PEC_NEST_STK_BAR_EN_INT)) { - memory_region_del_subregion(sysmem, &stack->intbar); - } - - /* Update PHB */ - pnv_phb4_update_regions(stack); - - /* Handle maps */ - if (!memory_region_is_mapped(&stack->mmbar0) && - (bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) { - bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0] >> 8; - mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0_MASK]; - size = ((~mask) >> 8) + 1; - snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio0", - pec->chip_id, pec->index, stack->stack_no); - memory_region_init(&stack->mmbar0, OBJECT(stack), name, size); - memory_region_add_subregion(sysmem, bar, &stack->mmbar0); - stack->mmio0_base = bar; - stack->mmio0_size = size; - } - if (!memory_region_is_mapped(&stack->mmbar1) && - (bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) { - bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1] >> 8; - mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1_MASK]; - size = ((~mask) >> 8) + 1; - snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio1", - pec->chip_id, pec->index, stack->stack_no); - memory_region_init(&stack->mmbar1, OBJECT(stack), name, size); - memory_region_add_subregion(sysmem, bar, &stack->mmbar1); - stack->mmio1_base = bar; - stack->mmio1_size = size; - } - if (!memory_region_is_mapped(&stack->phbbar) && - (bar_en & PEC_NEST_STK_BAR_EN_PHB)) { - bar = stack->nest_regs[PEC_NEST_STK_PHB_REGS_BAR] >> 8; - size = PNV_PHB4_NUM_REGS << 3; - snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-phb", - pec->chip_id, pec->index, stack->stack_no); - memory_region_init(&stack->phbbar, OBJECT(stack), name, size); - memory_region_add_subregion(sysmem, bar, &stack->phbbar); - } - if (!memory_region_is_mapped(&stack->intbar) && - (bar_en & PEC_NEST_STK_BAR_EN_INT)) { - bar = stack->nest_regs[PEC_NEST_STK_INT_BAR] >> 8; - size = PNV_PHB4_MAX_INTs << 16; - snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-int", - stack->pec->chip_id, stack->pec->index, stack->stack_no); - memory_region_init(&stack->intbar, OBJECT(stack), name, size); - memory_region_add_subregion(sysmem, bar, &stack->intbar); - } - - /* Update PHB */ - pnv_phb4_update_regions(stack); -} - -static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); - PnvPhb4PecState *pec = stack->pec; - uint32_t reg = addr >> 3; - - switch (reg) { - case PEC_NEST_STK_PCI_NEST_FIR: - stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] = val; - break; - case PEC_NEST_STK_PCI_NEST_FIR_CLR: - stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] &= val; - break; - case PEC_NEST_STK_PCI_NEST_FIR_SET: - stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] |= val; - break; - case PEC_NEST_STK_PCI_NEST_FIR_MSK: - stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] = val; - break; - case PEC_NEST_STK_PCI_NEST_FIR_MSKC: - stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] &= val; - break; - case PEC_NEST_STK_PCI_NEST_FIR_MSKS: - stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] |= val; - break; - case PEC_NEST_STK_PCI_NEST_FIR_ACT0: - case PEC_NEST_STK_PCI_NEST_FIR_ACT1: - stack->nest_regs[reg] = val; - break; - case PEC_NEST_STK_PCI_NEST_FIR_WOF: - stack->nest_regs[reg] = 0; - break; - case PEC_NEST_STK_ERR_REPORT_0: - case PEC_NEST_STK_ERR_REPORT_1: - case PEC_NEST_STK_PBCQ_GNRL_STATUS: - /* Flag error ? */ - break; - case PEC_NEST_STK_PBCQ_MODE: - stack->nest_regs[reg] = val & 0xff00000000000000ull; - break; - case PEC_NEST_STK_MMIO_BAR0: - case PEC_NEST_STK_MMIO_BAR0_MASK: - case PEC_NEST_STK_MMIO_BAR1: - case PEC_NEST_STK_MMIO_BAR1_MASK: - if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & - (PEC_NEST_STK_BAR_EN_MMIO0 | - PEC_NEST_STK_BAR_EN_MMIO1)) { - phb_pec_error(pec, "Changing enabled BAR unsupported\n"); - } - stack->nest_regs[reg] = val & 0xffffffffff000000ull; - break; - case PEC_NEST_STK_PHB_REGS_BAR: - if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_PHB) { - phb_pec_error(pec, "Changing enabled BAR unsupported\n"); - } - stack->nest_regs[reg] = val & 0xffffffffffc00000ull; - break; - case PEC_NEST_STK_INT_BAR: - if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_INT) { - phb_pec_error(pec, "Changing enabled BAR unsupported\n"); - } - stack->nest_regs[reg] = val & 0xfffffff000000000ull; - break; - case PEC_NEST_STK_BAR_EN: - stack->nest_regs[reg] = val & 0xf000000000000000ull; - pnv_pec_stk_update_map(stack); - break; - case PEC_NEST_STK_DATA_FRZ_TYPE: - case PEC_NEST_STK_PBCQ_TUN_BAR: - /* Not used for now */ - stack->nest_regs[reg] = val; - break; - default: - qemu_log_mask(LOG_UNIMP, "phb4_pec: nest_xscom_write 0x%"HWADDR_PRIx - "=%"PRIx64"\n", addr, val); - } -} - -static const MemoryRegionOps pnv_pec_stk_nest_xscom_ops = { - .read = pnv_pec_stk_nest_xscom_read, - .write = pnv_pec_stk_nest_xscom_write, - .valid.min_access_size = 8, - .valid.max_access_size = 8, - .impl.min_access_size = 8, - .impl.max_access_size = 8, - .endianness = DEVICE_BIG_ENDIAN, -}; - -static uint64_t pnv_pec_stk_pci_xscom_read(void *opaque, hwaddr addr, - unsigned size) -{ - PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); - uint32_t reg = addr >> 3; - - /* TODO: add list of allowed registers and error out if not */ - return stack->pci_regs[reg]; -} - -static void pnv_pec_stk_pci_xscom_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); - uint32_t reg = addr >> 3; - - switch (reg) { - case PEC_PCI_STK_PCI_FIR: - stack->nest_regs[reg] = val; - break; - case PEC_PCI_STK_PCI_FIR_CLR: - stack->nest_regs[PEC_PCI_STK_PCI_FIR] &= val; - break; - case PEC_PCI_STK_PCI_FIR_SET: - stack->nest_regs[PEC_PCI_STK_PCI_FIR] |= val; - break; - case PEC_PCI_STK_PCI_FIR_MSK: - stack->nest_regs[reg] = val; - break; - case PEC_PCI_STK_PCI_FIR_MSKC: - stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] &= val; - break; - case PEC_PCI_STK_PCI_FIR_MSKS: - stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] |= val; - break; - case PEC_PCI_STK_PCI_FIR_ACT0: - case PEC_PCI_STK_PCI_FIR_ACT1: - stack->nest_regs[reg] = val; - break; - case PEC_PCI_STK_PCI_FIR_WOF: - stack->nest_regs[reg] = 0; - break; - case PEC_PCI_STK_ETU_RESET: - stack->nest_regs[reg] = val & 0x8000000000000000ull; - /* TODO: Implement reset */ - break; - case PEC_PCI_STK_PBAIB_ERR_REPORT: - break; - case PEC_PCI_STK_PBAIB_TX_CMD_CRED: - case PEC_PCI_STK_PBAIB_TX_DAT_CRED: - stack->nest_regs[reg] = val; - break; - default: - qemu_log_mask(LOG_UNIMP, "phb4_pec_stk: pci_xscom_write 0x%"HWADDR_PRIx - "=%"PRIx64"\n", addr, val); - } -} - -static const MemoryRegionOps pnv_pec_stk_pci_xscom_ops = { - .read = pnv_pec_stk_pci_xscom_read, - .write = pnv_pec_stk_pci_xscom_write, - .valid.min_access_size = 8, - .valid.max_access_size = 8, - .impl.min_access_size = 8, - .impl.max_access_size = 8, - .endianness = DEVICE_BIG_ENDIAN, -}; - static void pnv_pec_instance_init(Object *obj) { PnvPhb4PecState *pec = PNV_PHB4_PEC(obj); @@ -539,32 +287,7 @@ static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev); PnvPhb4PecState *pec = stack->pec; PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); - PnvChip *chip = pec->chip; int phb_id = pnv_phb4_pec_get_phb_id(pec, stack->stack_no); - uint32_t pec_nest_base; - uint32_t pec_pci_base; - char name[64]; - - assert(pec); - - /* Initialize the XSCOM regions for the stack registers */ - snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest-stack-%d", - pec->chip_id, pec->index, stack->stack_no); - pnv_xscom_region_init(&stack->nest_regs_mr, OBJECT(stack), - &pnv_pec_stk_nest_xscom_ops, stack, name, - PHB4_PEC_NEST_STK_REGS_COUNT); - - snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d", - pec->chip_id, pec->index, stack->stack_no); - pnv_xscom_region_init(&stack->pci_regs_mr, OBJECT(stack), - &pnv_pec_stk_pci_xscom_ops, stack, name, - PHB4_PEC_PCI_STK_REGS_COUNT); - - /* PHB pass-through */ - snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d-phb", - pec->chip_id, pec->index, stack->stack_no); - pnv_xscom_region_init(&stack->phb_regs_mr, OBJECT(&stack->phb), - &pnv_phb4_xscom_ops, &stack->phb, name, 0x40); object_property_set_int(OBJECT(&stack->phb), "chip-id", pec->chip_id, &error_fatal); @@ -577,21 +300,6 @@ static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) if (!sysbus_realize(SYS_BUS_DEVICE(&stack->phb), errp)) { return; } - - pec_nest_base = pecc->xscom_nest_base(pec); - pec_pci_base = pecc->xscom_pci_base(pec); - - /* Populate the XSCOM address space. */ - pnv_xscom_add_subregion(chip, - pec_nest_base + 0x40 * (stack->stack_no + 1), - &stack->nest_regs_mr); - pnv_xscom_add_subregion(chip, - pec_pci_base + 0x40 * (stack->stack_no + 1), - &stack->pci_regs_mr); - pnv_xscom_add_subregion(chip, - pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 + - 0x40 * stack->stack_no, - &stack->phb_regs_mr); } static Property pnv_pec_stk_properties[] = { From dc8e2914ab27e09ce6483fa41be6822b2ff3b650 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 445/730] ppc/pnv: turn 'phb' into a pointer in struct PnvPhb4PecStack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At this moment, stack->phb is the plain PnvPHB4 device itself instead of a pointer to the device. This will present a problem when adding user creatable devices because we can't deal with this struct and the realize() callback from the user creatable device. We can't get rid of this attribute, similar to what we did when enabling pnv-phb3 user creatable devices, because pnv_phb4_update_regions() needs to access stack->phb to do its job. This function is called twice in pnv_pec_stk_update_map(), which is one of the nested xscom write callbacks (via pnv_pec_stk_nest_xscom_write()). In fact, pnv_pec_stk_update_map() code comment is explicit about how the order of the unmap/map operations relates with the PHB subregions. All of this indicates that this code is tied together in a way that we either go on a crusade, featuring lots of refactories and redesign and considerable pain, to decouple stack and phb mapping, or we allow stack update_map operations to access the associated PHB as it is today even after introducing pnv-phb4 user devices. This patch chooses the latter. Instead of getting rid of stack->phb, turn it into a PHB pointer. This will allow us to assign an user created PHB to an existing stack later. In this process, pnv_pec_stk_instance_init() is removed because stack->phb is being initialized in stk_realize() instead. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220111131027.599784-4-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 2 +- hw/pci-host/pnv_phb4_pec.c | 20 +++++++------------- include/hw/pci-host/pnv_phb4.h | 7 +++++-- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 8ef58bf2de..e25adb8860 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1728,7 +1728,7 @@ type_init(pnv_phb4_register_types); void pnv_phb4_update_regions(PnvPhb4PecStack *stack) { - PnvPHB4 *phb = &stack->phb; + PnvPHB4 *phb = stack->phb; /* Unmap first always */ if (memory_region_is_mapped(&phb->mr_regs)) { diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index bf0fdf33fd..d4c52a5d28 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -275,13 +275,6 @@ static const TypeInfo pnv_pec_type_info = { } }; -static void pnv_pec_stk_instance_init(Object *obj) -{ - PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(obj); - - object_initialize_child(obj, "phb", &stack->phb, TYPE_PNV_PHB4); -} - static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) { PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev); @@ -289,15 +282,17 @@ static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); int phb_id = pnv_phb4_pec_get_phb_id(pec, stack->stack_no); - object_property_set_int(OBJECT(&stack->phb), "chip-id", pec->chip_id, + stack->phb = PNV_PHB4(qdev_new(TYPE_PNV_PHB4)); + + object_property_set_int(OBJECT(stack->phb), "chip-id", pec->chip_id, &error_fatal); - object_property_set_int(OBJECT(&stack->phb), "index", phb_id, + object_property_set_int(OBJECT(stack->phb), "index", phb_id, &error_fatal); - object_property_set_int(OBJECT(&stack->phb), "version", pecc->version, + object_property_set_int(OBJECT(stack->phb), "version", pecc->version, &error_fatal); - object_property_set_link(OBJECT(&stack->phb), "stack", OBJECT(stack), + object_property_set_link(OBJECT(stack->phb), "stack", OBJECT(stack), &error_abort); - if (!sysbus_realize(SYS_BUS_DEVICE(&stack->phb), errp)) { + if (!sysbus_realize(SYS_BUS_DEVICE(stack->phb), errp)) { return; } } @@ -324,7 +319,6 @@ static const TypeInfo pnv_pec_stk_type_info = { .name = TYPE_PNV_PHB4_PEC_STACK, .parent = TYPE_DEVICE, .instance_size = sizeof(PnvPhb4PecStack), - .instance_init = pnv_pec_stk_instance_init, .class_init = pnv_pec_stk_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_PNV_XSCOM_INTERFACE }, diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 5ee996ebc6..82f054cf21 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -177,8 +177,11 @@ struct PnvPhb4PecStack { /* The owner PEC */ PnvPhb4PecState *pec; - /* The actual PHB */ - PnvPHB4 phb; + /* + * PHB4 pointer. pnv_phb4_update_regions() needs to access + * the PHB4 via a PnvPhb4PecStack pointer. + */ + PnvPHB4 *phb; }; struct PnvPhb4PecState { From 5bc67b052b511ef042bd420857227e1e5173c88a Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 446/730] ppc/pnv: Introduce user creatable pnv-phb4 devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch introduces pnv-phb4 user creatable devices that are created in a similar manner as pnv-phb3 devices, allowing the user to interact with the PHBs directly instead of creating PCI Express Controllers that will create a certain amount of PHBs per controller index. We accomplish this by doing the following: - add a pnv_phb4_get_stack() helper to retrieve which stack an user created phb4 would occupy; - when dealing with an user created pnv-phb4 (detected by checking if phb->stack is NULL at the start of phb4_realize()), retrieve its stack and initialize its properties as done in stk_realize(); - use 'defaults_enabled()' in stk_realize() to avoid creating and initializing a 'stack->phb' qdev that might be overwritten by an user created pnv-phb4 device. This process is wrapped into a new helper called pnv_pec_stk_default_phb_realize(). Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220111131027.599784-5-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 74 ++++++++++++++++++++++++++++++++++++-- hw/pci-host/pnv_phb4_pec.c | 17 +++++++-- hw/ppc/pnv.c | 2 ++ 3 files changed, 89 insertions(+), 4 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index e25adb8860..ffa1453eee 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1487,15 +1487,85 @@ static void pnv_phb4_instance_init(Object *obj) object_initialize_child(obj, "source", &phb->xsrc, TYPE_XIVE_SOURCE); } +static PnvPhb4PecStack *pnv_phb4_get_stack(PnvChip *chip, PnvPHB4 *phb, + Error **errp) +{ + Pnv9Chip *chip9 = PNV9_CHIP(chip); + int chip_id = phb->chip_id; + int index = phb->phb_id; + int i, j; + + for (i = 0; i < chip->num_pecs; i++) { + /* + * For each PEC, check the amount of stacks it supports + * and see if the given phb4 index matches a stack. + */ + PnvPhb4PecState *pec = &chip9->pecs[i]; + + for (j = 0; j < pec->num_stacks; j++) { + if (index == pnv_phb4_pec_get_phb_id(pec, j)) { + return &pec->stacks[j]; + } + } + } + + error_setg(errp, + "pnv-phb4 chip-id %d index %d didn't match any existing PEC", + chip_id, index); + + return NULL; +} + static void pnv_phb4_realize(DeviceState *dev, Error **errp) { PnvPHB4 *phb = PNV_PHB4(dev); PCIHostState *pci = PCI_HOST_BRIDGE(dev); XiveSource *xsrc = &phb->xsrc; + Error *local_err = NULL; int nr_irqs; char name[32]; - assert(phb->stack); + /* User created PHB */ + if (!phb->stack) { + PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); + PnvChip *chip = pnv_get_chip(pnv, phb->chip_id); + PnvPhb4PecClass *pecc; + BusState *s; + + if (!chip) { + error_setg(errp, "invalid chip id: %d", phb->chip_id); + return; + } + + phb->stack = pnv_phb4_get_stack(chip, phb, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + /* All other phb properties but 'version' are already set */ + pecc = PNV_PHB4_PEC_GET_CLASS(phb->stack->pec); + object_property_set_int(OBJECT(phb), "version", pecc->version, + &error_fatal); + + /* + * Assign stack->phb since pnv_phb4_update_regions() uses it + * to access the phb. + */ + phb->stack->phb = phb; + + /* + * Reparent user created devices to the chip to build + * correctly the device tree. + */ + pnv_chip_parent_fixup(chip, OBJECT(phb), phb->phb_id); + + s = qdev_get_parent_bus(DEVICE(chip)); + if (!qdev_set_parent_bus(DEVICE(phb), s, &local_err)) { + error_propagate(errp, local_err); + return; + } + } /* Set the "big_phb" flag */ phb->big_phb = phb->phb_id == 0 || phb->phb_id == 3; @@ -1600,7 +1670,7 @@ static void pnv_phb4_class_init(ObjectClass *klass, void *data) dc->realize = pnv_phb4_realize; device_class_set_props(dc, pnv_phb4_properties); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->user_creatable = false; + dc->user_creatable = true; xfc->notify = pnv_phb4_xive_notify; } diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index d4c52a5d28..7fe7f1f007 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -19,6 +19,7 @@ #include "hw/pci/pci_bus.h" #include "hw/ppc/pnv.h" #include "hw/qdev-properties.h" +#include "sysemu/sysemu.h" #include @@ -275,9 +276,9 @@ static const TypeInfo pnv_pec_type_info = { } }; -static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) +static void pnv_pec_stk_default_phb_realize(PnvPhb4PecStack *stack, + Error **errp) { - PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev); PnvPhb4PecState *pec = stack->pec; PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); int phb_id = pnv_phb4_pec_get_phb_id(pec, stack->stack_no); @@ -292,11 +293,23 @@ static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) &error_fatal); object_property_set_link(OBJECT(stack->phb), "stack", OBJECT(stack), &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(stack->phb), errp)) { return; } } +static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) +{ + PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev); + + if (!defaults_enabled()) { + return; + } + + pnv_pec_stk_default_phb_realize(stack, errp); +} + static Property pnv_pec_stk_properties[] = { DEFINE_PROP_UINT32("stack-no", PnvPhb4PecStack, stack_no, 0), DEFINE_PROP_LINK("pec", PnvPhb4PecStack, pec, TYPE_PNV_PHB4_PEC, diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index fe7e67e73a..837146a2fb 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1960,6 +1960,8 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) pmc->compat = compat; pmc->compat_size = sizeof(compat); pmc->dt_power_mgt = pnv_dt_power_mgt; + + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB4); } static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) From 7e1e0912ec67f813473a7191274d52cab1fe476d Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 447/730] ppc/pnv: turn pnv_phb4_update_regions() into static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Its only callers are inside pnv_phb4.c. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Message-Id: <20220111131027.599784-6-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 52 +++++++++++++++++----------------- include/hw/pci-host/pnv_phb4.h | 1 - 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index ffa1453eee..be29174f13 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -868,6 +868,32 @@ static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr, return stack->nest_regs[reg]; } +static void pnv_phb4_update_regions(PnvPhb4PecStack *stack) +{ + PnvPHB4 *phb = stack->phb; + + /* Unmap first always */ + if (memory_region_is_mapped(&phb->mr_regs)) { + memory_region_del_subregion(&stack->phbbar, &phb->mr_regs); + } + if (memory_region_is_mapped(&phb->xsrc.esb_mmio)) { + memory_region_del_subregion(&stack->intbar, &phb->xsrc.esb_mmio); + } + + /* Map registers if enabled */ + if (memory_region_is_mapped(&stack->phbbar)) { + memory_region_add_subregion(&stack->phbbar, 0, &phb->mr_regs); + } + + /* Map ESB if enabled */ + if (memory_region_is_mapped(&stack->intbar)) { + memory_region_add_subregion(&stack->intbar, 0, &phb->xsrc.esb_mmio); + } + + /* Check/update m32 */ + pnv_phb4_check_all_mbt(phb); +} + static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) { PnvPhb4PecState *pec = stack->pec; @@ -1796,32 +1822,6 @@ static void pnv_phb4_register_types(void) type_init(pnv_phb4_register_types); -void pnv_phb4_update_regions(PnvPhb4PecStack *stack) -{ - PnvPHB4 *phb = stack->phb; - - /* Unmap first always */ - if (memory_region_is_mapped(&phb->mr_regs)) { - memory_region_del_subregion(&stack->phbbar, &phb->mr_regs); - } - if (memory_region_is_mapped(&phb->xsrc.esb_mmio)) { - memory_region_del_subregion(&stack->intbar, &phb->xsrc.esb_mmio); - } - - /* Map registers if enabled */ - if (memory_region_is_mapped(&stack->phbbar)) { - memory_region_add_subregion(&stack->phbbar, 0, &phb->mr_regs); - } - - /* Map ESB if enabled */ - if (memory_region_is_mapped(&stack->intbar)) { - memory_region_add_subregion(&stack->intbar, 0, &phb->xsrc.esb_mmio); - } - - /* Check/update m32 */ - pnv_phb4_check_all_mbt(phb); -} - void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon) { uint32_t offset = phb->regs[PHB_INT_NOTIFY_INDEX >> 3]; diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 82f054cf21..4b7ce8a723 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -131,7 +131,6 @@ struct PnvPHB4 { }; void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon); -void pnv_phb4_update_regions(PnvPhb4PecStack *stack); int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index); extern const MemoryRegionOps pnv_phb4_xscom_ops; From f83460bb203a49dd1693bf8b664d2a935a5be621 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 12 Jan 2022 11:28:27 +0100 Subject: [PATCH 448/730] ppc/pnv: use stack->pci_regs[] in pnv_pec_stk_pci_xscom_write() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pnv_pec_stk_pci_xscom_write() is pnv_pec_stk_pci_xscom_ops write callback. It writes values into regs in the stack->nest_regs[] array. The pnv_pec_stk_pci_xscom_read read callback, on the other hand, returns values of the stack->pci_regs[]. In fact, at this moment, the only use of stack->pci_regs[] is in pnv_pec_stk_pci_xscom_read(). There's no code that is written anything in stack->pci_regs[], which is suspicious. Considering that stack->nest_regs[] is widely used by the nested MemoryOps pnv_pec_stk_nest_xscom_ops, in both read and write callbacks, the conclusion is that we're writing the wrong array in pnv_pec_stk_pci_xscom_write(). This function should write stack->pci_regs[] instead. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220111200132.633896-2-danielhb413@gmail.com> Signed-off-by: Cédric Le Goater --- hw/pci-host/pnv_phb4.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index be29174f13..a7b638831e 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1086,39 +1086,39 @@ static void pnv_pec_stk_pci_xscom_write(void *opaque, hwaddr addr, switch (reg) { case PEC_PCI_STK_PCI_FIR: - stack->nest_regs[reg] = val; + stack->pci_regs[reg] = val; break; case PEC_PCI_STK_PCI_FIR_CLR: - stack->nest_regs[PEC_PCI_STK_PCI_FIR] &= val; + stack->pci_regs[PEC_PCI_STK_PCI_FIR] &= val; break; case PEC_PCI_STK_PCI_FIR_SET: - stack->nest_regs[PEC_PCI_STK_PCI_FIR] |= val; + stack->pci_regs[PEC_PCI_STK_PCI_FIR] |= val; break; case PEC_PCI_STK_PCI_FIR_MSK: - stack->nest_regs[reg] = val; + stack->pci_regs[reg] = val; break; case PEC_PCI_STK_PCI_FIR_MSKC: - stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] &= val; + stack->pci_regs[PEC_PCI_STK_PCI_FIR_MSK] &= val; break; case PEC_PCI_STK_PCI_FIR_MSKS: - stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] |= val; + stack->pci_regs[PEC_PCI_STK_PCI_FIR_MSK] |= val; break; case PEC_PCI_STK_PCI_FIR_ACT0: case PEC_PCI_STK_PCI_FIR_ACT1: - stack->nest_regs[reg] = val; + stack->pci_regs[reg] = val; break; case PEC_PCI_STK_PCI_FIR_WOF: - stack->nest_regs[reg] = 0; + stack->pci_regs[reg] = 0; break; case PEC_PCI_STK_ETU_RESET: - stack->nest_regs[reg] = val & 0x8000000000000000ull; + stack->pci_regs[reg] = val & 0x8000000000000000ull; /* TODO: Implement reset */ break; case PEC_PCI_STK_PBAIB_ERR_REPORT: break; case PEC_PCI_STK_PBAIB_TX_CMD_CRED: case PEC_PCI_STK_PBAIB_TX_DAT_CRED: - stack->nest_regs[reg] = val; + stack->pci_regs[reg] = val; break; default: qemu_log_mask(LOG_UNIMP, "phb4_pec_stk: pci_xscom_write 0x%"HWADDR_PRIx From a3a576b0bf376eeb3cfc6c97c082628a8b73ff60 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 21 Dec 2021 16:23:55 +0100 Subject: [PATCH 449/730] meson: reuse common_user_inc when building files specific to user-mode emulators Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index c1b1db1e28..2aa44c965a 100644 --- a/meson.build +++ b/meson.build @@ -2919,6 +2919,7 @@ foreach target : target_dirs else abi = config_target['TARGET_ABI_DIR'] target_type='user' + target_inc += common_user_inc qemu_target_name = 'qemu-' + target_name if target_base_arch in target_user_arch t = target_user_arch[target_base_arch].apply(config_target, strict: false) @@ -2927,7 +2928,6 @@ foreach target : target_dirs endif if 'CONFIG_LINUX_USER' in config_target base_dir = 'linux-user' - target_inc += include_directories('linux-user/host/' / host_arch) endif if 'CONFIG_BSD_USER' in config_target base_dir = 'bsd-user' From 05a248715cef192336a594afed812871a52efc1f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 21 Dec 2021 16:20:32 +0100 Subject: [PATCH 450/730] user: move common-user includes to a subdirectory of {bsd,linux}-user/ Avoid polluting the compilation of common-user/ with local include files; making an include file available to common-user/ should be a deliberate decision in order to keep a clear interface that can be used by both bsd-user/ and linux-user/. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- bsd-user/{ => include}/special-errno.h | 0 bsd-user/meson.build | 2 +- linux-user/{ => include}/host/aarch64/host-signal.h | 0 linux-user/{ => include}/host/alpha/host-signal.h | 0 linux-user/{ => include}/host/arm/host-signal.h | 0 linux-user/{ => include}/host/i386/host-signal.h | 0 linux-user/{ => include}/host/loongarch64/host-signal.h | 0 linux-user/{ => include}/host/mips/host-signal.h | 0 linux-user/{ => include}/host/ppc/host-signal.h | 0 linux-user/{ => include}/host/ppc64/host-signal.h | 0 linux-user/{ => include}/host/riscv/host-signal.h | 0 linux-user/{ => include}/host/s390/host-signal.h | 0 linux-user/{ => include}/host/s390x/host-signal.h | 0 linux-user/{ => include}/host/sparc/host-signal.h | 0 linux-user/{ => include}/host/sparc64/host-signal.h | 0 linux-user/{ => include}/host/x32/host-signal.h | 0 linux-user/{ => include}/host/x86_64/host-signal.h | 0 linux-user/{ => include}/special-errno.h | 0 linux-user/meson.build | 4 ++-- 19 files changed, 3 insertions(+), 3 deletions(-) rename bsd-user/{ => include}/special-errno.h (100%) rename linux-user/{ => include}/host/aarch64/host-signal.h (100%) rename linux-user/{ => include}/host/alpha/host-signal.h (100%) rename linux-user/{ => include}/host/arm/host-signal.h (100%) rename linux-user/{ => include}/host/i386/host-signal.h (100%) rename linux-user/{ => include}/host/loongarch64/host-signal.h (100%) rename linux-user/{ => include}/host/mips/host-signal.h (100%) rename linux-user/{ => include}/host/ppc/host-signal.h (100%) rename linux-user/{ => include}/host/ppc64/host-signal.h (100%) rename linux-user/{ => include}/host/riscv/host-signal.h (100%) rename linux-user/{ => include}/host/s390/host-signal.h (100%) rename linux-user/{ => include}/host/s390x/host-signal.h (100%) rename linux-user/{ => include}/host/sparc/host-signal.h (100%) rename linux-user/{ => include}/host/sparc64/host-signal.h (100%) rename linux-user/{ => include}/host/x32/host-signal.h (100%) rename linux-user/{ => include}/host/x86_64/host-signal.h (100%) rename linux-user/{ => include}/special-errno.h (100%) diff --git a/bsd-user/special-errno.h b/bsd-user/include/special-errno.h similarity index 100% rename from bsd-user/special-errno.h rename to bsd-user/include/special-errno.h diff --git a/bsd-user/meson.build b/bsd-user/meson.build index 9fcb80c3fa..8380fa44c2 100644 --- a/bsd-user/meson.build +++ b/bsd-user/meson.build @@ -4,7 +4,7 @@ endif bsd_user_ss = ss.source_set() -common_user_inc += include_directories('.') +common_user_inc += include_directories('include') bsd_user_ss.add(files( 'bsdload.c', diff --git a/linux-user/host/aarch64/host-signal.h b/linux-user/include/host/aarch64/host-signal.h similarity index 100% rename from linux-user/host/aarch64/host-signal.h rename to linux-user/include/host/aarch64/host-signal.h diff --git a/linux-user/host/alpha/host-signal.h b/linux-user/include/host/alpha/host-signal.h similarity index 100% rename from linux-user/host/alpha/host-signal.h rename to linux-user/include/host/alpha/host-signal.h diff --git a/linux-user/host/arm/host-signal.h b/linux-user/include/host/arm/host-signal.h similarity index 100% rename from linux-user/host/arm/host-signal.h rename to linux-user/include/host/arm/host-signal.h diff --git a/linux-user/host/i386/host-signal.h b/linux-user/include/host/i386/host-signal.h similarity index 100% rename from linux-user/host/i386/host-signal.h rename to linux-user/include/host/i386/host-signal.h diff --git a/linux-user/host/loongarch64/host-signal.h b/linux-user/include/host/loongarch64/host-signal.h similarity index 100% rename from linux-user/host/loongarch64/host-signal.h rename to linux-user/include/host/loongarch64/host-signal.h diff --git a/linux-user/host/mips/host-signal.h b/linux-user/include/host/mips/host-signal.h similarity index 100% rename from linux-user/host/mips/host-signal.h rename to linux-user/include/host/mips/host-signal.h diff --git a/linux-user/host/ppc/host-signal.h b/linux-user/include/host/ppc/host-signal.h similarity index 100% rename from linux-user/host/ppc/host-signal.h rename to linux-user/include/host/ppc/host-signal.h diff --git a/linux-user/host/ppc64/host-signal.h b/linux-user/include/host/ppc64/host-signal.h similarity index 100% rename from linux-user/host/ppc64/host-signal.h rename to linux-user/include/host/ppc64/host-signal.h diff --git a/linux-user/host/riscv/host-signal.h b/linux-user/include/host/riscv/host-signal.h similarity index 100% rename from linux-user/host/riscv/host-signal.h rename to linux-user/include/host/riscv/host-signal.h diff --git a/linux-user/host/s390/host-signal.h b/linux-user/include/host/s390/host-signal.h similarity index 100% rename from linux-user/host/s390/host-signal.h rename to linux-user/include/host/s390/host-signal.h diff --git a/linux-user/host/s390x/host-signal.h b/linux-user/include/host/s390x/host-signal.h similarity index 100% rename from linux-user/host/s390x/host-signal.h rename to linux-user/include/host/s390x/host-signal.h diff --git a/linux-user/host/sparc/host-signal.h b/linux-user/include/host/sparc/host-signal.h similarity index 100% rename from linux-user/host/sparc/host-signal.h rename to linux-user/include/host/sparc/host-signal.h diff --git a/linux-user/host/sparc64/host-signal.h b/linux-user/include/host/sparc64/host-signal.h similarity index 100% rename from linux-user/host/sparc64/host-signal.h rename to linux-user/include/host/sparc64/host-signal.h diff --git a/linux-user/host/x32/host-signal.h b/linux-user/include/host/x32/host-signal.h similarity index 100% rename from linux-user/host/x32/host-signal.h rename to linux-user/include/host/x32/host-signal.h diff --git a/linux-user/host/x86_64/host-signal.h b/linux-user/include/host/x86_64/host-signal.h similarity index 100% rename from linux-user/host/x86_64/host-signal.h rename to linux-user/include/host/x86_64/host-signal.h diff --git a/linux-user/special-errno.h b/linux-user/include/special-errno.h similarity index 100% rename from linux-user/special-errno.h rename to linux-user/include/special-errno.h diff --git a/linux-user/meson.build b/linux-user/meson.build index b2f4afd5e7..de4320af05 100644 --- a/linux-user/meson.build +++ b/linux-user/meson.build @@ -4,8 +4,8 @@ endif linux_user_ss = ss.source_set() -common_user_inc += include_directories('host/' / host_arch) -common_user_inc += include_directories('.') +common_user_inc += include_directories('include/host/' / host_arch) +common_user_inc += include_directories('include') linux_user_ss.add(files( 'elfload.c', From 9d24fb73a1c1b0d892f8c26297f922c85460513d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 21 Dec 2021 16:09:54 +0100 Subject: [PATCH 451/730] meson: cleanup common-user/ build It is not necessary to have a separate static_library just for common_user files; using the one that already covers the rest of common_ss is enough unless you need to reuse some source files between emulators and tests. Just place common files for all user-mode emulators in common_ss, similar to what is already done for softmmu_ss in full system emulators. The only disadvantage is that the include_directories under bsd-user/include/ and linux-user/include/ are now enabled for all targets rather than only user mode emulators. This however is not different from how include/sysemu/ is available when building user mode emulators. Tested-by: Richard Henderson Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- common-user/meson.build | 2 +- meson.build | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/common-user/meson.build b/common-user/meson.build index 5cb42bc664..26212dda5c 100644 --- a/common-user/meson.build +++ b/common-user/meson.build @@ -1,6 +1,6 @@ common_user_inc += include_directories('host/' / host_arch) -common_user_ss.add(files( +user_ss.add(files( 'safe-syscall.S', 'safe-syscall-error.c', )) diff --git a/meson.build b/meson.build index 2aa44c965a..f0567daf42 100644 --- a/meson.build +++ b/meson.build @@ -2399,7 +2399,6 @@ blockdev_ss = ss.source_set() block_ss = ss.source_set() chardev_ss = ss.source_set() common_ss = ss.source_set() -common_user_ss = ss.source_set() crypto_ss = ss.source_set() hwcore_ss = ss.source_set() io_ss = ss.source_set() @@ -2651,17 +2650,6 @@ subdir('common-user') subdir('bsd-user') subdir('linux-user') -common_user_ss = common_user_ss.apply(config_all, strict: false) -common_user = static_library('common-user', - sources: common_user_ss.sources(), - dependencies: common_user_ss.dependencies(), - include_directories: common_user_inc, - name_suffix: 'fa', - build_by_default: false) -common_user = declare_dependency(link_with: common_user) - -user_ss.add(common_user) - # needed for fuzzing binaries subdir('tests/qtest/libqos') subdir('tests/qtest/fuzz') @@ -2879,6 +2867,7 @@ common_all = common_ss.apply(config_all, strict: false) common_all = static_library('common', build_by_default: false, sources: common_all.sources() + genh, + include_directories: common_user_inc, implicit_include_directories: false, dependencies: common_all.dependencies(), name_suffix: 'fa') From a5730b8bd3675f484ed0eacea052452048eeb35d Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 15 Dec 2021 13:58:24 +0100 Subject: [PATCH 452/730] block/file-posix: Simplify the XFS_IOC_DIOINFO handling The handling for the XFS_IOC_DIOINFO ioctl is currently quite excessive: This is not a "real" feature like the other features that we provide with the "--enable-xxx" and "--disable-xxx" switches for the configure script, since this does not influence lots of code (it's only about one call to xfsctl() in file-posix.c), so people don't gain much with the ability to disable this with "--disable-xfsctl". It's also unfortunate that the ioctl will be disabled on Linux in case the user did not install the right xfsprogs-devel package before running configure. Thus let's simplify this by providing the ioctl definition on our own, so we can completely get rid of the header dependency and thus the related code in the configure script. Suggested-by: Paolo Bonzini Signed-off-by: Thomas Huth Message-Id: <20211215125824.250091-1-thuth@redhat.com> Signed-off-by: Paolo Bonzini --- block/file-posix.c | 37 ++++++++----------- configure | 31 ---------------- meson.build | 1 - .../ci/org.centos/stream/8/x86_64/configure | 1 - scripts/coverity-scan/run-coverity-scan | 2 +- 5 files changed, 17 insertions(+), 55 deletions(-) diff --git a/block/file-posix.c b/block/file-posix.c index b283093e5b..1f1756e192 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -106,10 +106,6 @@ #include #endif -#ifdef CONFIG_XFS -#include -#endif - /* OS X does not have O_DSYNC */ #ifndef O_DSYNC #ifdef O_SYNC @@ -156,9 +152,6 @@ typedef struct BDRVRawState { int perm_change_flags; BDRVReopenState *reopen_state; -#ifdef CONFIG_XFS - bool is_xfs:1; -#endif bool has_discard:1; bool has_write_zeroes:1; bool discard_zeroes:1; @@ -409,14 +402,22 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp) if (probe_logical_blocksize(fd, &bs->bl.request_alignment) < 0) { bs->bl.request_alignment = 0; } -#ifdef CONFIG_XFS - if (s->is_xfs) { - struct dioattr da; - if (xfsctl(NULL, fd, XFS_IOC_DIOINFO, &da) >= 0) { - bs->bl.request_alignment = da.d_miniosz; - /* The kernel returns wrong information for d_mem */ - /* s->buf_align = da.d_mem; */ - } + +#ifdef __linux__ + /* + * The XFS ioctl definitions are shipped in extra packages that might + * not always be available. Since we just need the XFS_IOC_DIOINFO ioctl + * here, we simply use our own definition instead: + */ + struct xfs_dioattr { + uint32_t d_mem; + uint32_t d_miniosz; + uint32_t d_maxiosz; + } da; + if (ioctl(fd, _IOR('X', 30, struct xfs_dioattr), &da) >= 0) { + bs->bl.request_alignment = da.d_miniosz; + /* The kernel returns wrong information for d_mem */ + /* s->buf_align = da.d_mem; */ } #endif @@ -798,12 +799,6 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, #endif s->needs_alignment = raw_needs_alignment(bs); -#ifdef CONFIG_XFS - if (platform_test_xfs_fd(s->fd)) { - s->is_xfs = true; - } -#endif - bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK; if (S_ISREG(st.st_mode)) { /* When extending regular files, we get zeros from the OS */ diff --git a/configure b/configure index 030728d11e..3a523a3d14 100755 --- a/configure +++ b/configure @@ -291,7 +291,6 @@ EXTRA_CXXFLAGS="" EXTRA_LDFLAGS="" xen_ctrl_version="$default_feature" -xfs="$default_feature" membarrier="$default_feature" vhost_kernel="$default_feature" vhost_net="$default_feature" @@ -1021,10 +1020,6 @@ for opt do ;; --enable-opengl) opengl="yes" ;; - --disable-xfsctl) xfs="no" - ;; - --enable-xfsctl) xfs="yes" - ;; --disable-zlib-test) ;; --enable-guest-agent) guest_agent="yes" @@ -1431,7 +1426,6 @@ cat << EOF avx512f AVX512F optimization support replication replication support opengl opengl support - xfsctl xfsctl support qom-cast-debug cast debugging support tools build qemu-io, qemu-nbd and qemu-img tools bochs bochs image format support @@ -2323,28 +2317,6 @@ EOF fi fi -########################################## -# xfsctl() probe, used for file-posix.c -if test "$xfs" != "no" ; then - cat > $TMPC << EOF -#include /* NULL */ -#include -int main(void) -{ - xfsctl(NULL, 0, 0, NULL); - return 0; -} -EOF - if compile_prog "" "" ; then - xfs="yes" - else - if test "$xfs" = "yes" ; then - feature_not_found "xfs" "Install xfsprogs/xfslibs devel" - fi - xfs=no - fi -fi - ########################################## # plugin linker support probe @@ -3456,9 +3428,6 @@ echo "CONFIG_BDRV_RO_WHITELIST=$block_drv_ro_whitelist" >> $config_host_mak if test "$block_drv_whitelist_tools" = "yes" ; then echo "CONFIG_BDRV_WHITELIST_TOOLS=y" >> $config_host_mak fi -if test "$xfs" = "yes" ; then - echo "CONFIG_XFS=y" >> $config_host_mak -fi qemu_version=$(head $source_path/VERSION) echo "PKGVERSION=$pkgversion" >>$config_host_mak echo "SRC_PATH=$source_path" >> $config_host_mak diff --git a/meson.build b/meson.build index f0567daf42..be592aa942 100644 --- a/meson.build +++ b/meson.build @@ -3445,7 +3445,6 @@ if spice_protocol.found() summary_info += {' spice server support': spice} endif summary_info += {'rbd support': rbd} -summary_info += {'xfsctl support': config_host.has_key('CONFIG_XFS')} summary_info += {'smartcard support': cacard} summary_info += {'U2F support': u2f} summary_info += {'libusb': libusb} diff --git a/scripts/ci/org.centos/stream/8/x86_64/configure b/scripts/ci/org.centos/stream/8/x86_64/configure index 048e80dc49..e05f2fddcc 100755 --- a/scripts/ci/org.centos/stream/8/x86_64/configure +++ b/scripts/ci/org.centos/stream/8/x86_64/configure @@ -151,7 +151,6 @@ --disable-whpx \ --disable-xen \ --disable-xen-pci-passthrough \ ---disable-xfsctl \ --disable-xkbcommon \ --disable-zstd \ --enable-attr \ diff --git a/scripts/coverity-scan/run-coverity-scan b/scripts/coverity-scan/run-coverity-scan index 7395bbfad4..6d443250a9 100755 --- a/scripts/coverity-scan/run-coverity-scan +++ b/scripts/coverity-scan/run-coverity-scan @@ -398,7 +398,7 @@ echo "Configuring..." --enable-xen --enable-brlapi \ --enable-linux-aio --enable-attr \ --enable-cap-ng --enable-trace-backends=log --enable-spice --enable-rbd \ - --enable-xfsctl --enable-libusb --enable-usb-redir \ + --enable-libusb --enable-usb-redir \ --enable-libiscsi --enable-libnfs --enable-seccomp \ --enable-tpm --enable-libssh --enable-lzo --enable-snappy --enable-bzip2 \ --enable-numa --enable-rdma --enable-smartcard --enable-virglrenderer \ From 37650689473c4cdb5838f90cbc1aefbcd9332fb0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 10 Dec 2021 09:55:15 +0100 Subject: [PATCH 453/730] configure: simplify creation of plugin symbol list --dynamic-list is present on all supported ELF (not Windows or Darwin) platforms, since it dates back to 2006; -exported_symbols_list is likewise present on all supported versions of macOS. Do not bother doing a functional test in configure. Remove the file creation from configure as well: for Darwin, move the the creation of the Darwin-formatted symbols to meson; for ELF, use the file in the source path directly and switch from -Wl, to -Xlinker to not break weird paths that include a comma. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- configure | 81 +-------------------------------------------- plugins/meson.build | 13 +++++--- 2 files changed, 10 insertions(+), 84 deletions(-) diff --git a/configure b/configure index 3a523a3d14..1b5fa5ae93 100755 --- a/configure +++ b/configure @@ -78,7 +78,6 @@ TMPC="${TMPDIR1}/${TMPB}.c" TMPO="${TMPDIR1}/${TMPB}.o" TMPCXX="${TMPDIR1}/${TMPB}.cxx" TMPE="${TMPDIR1}/${TMPB}.exe" -TMPTXT="${TMPDIR1}/${TMPB}.txt" rm -f config.log @@ -1696,6 +1695,7 @@ if test "$static" = "yes" ; then plugins="no" fi fi +test "$plugins" = "" && plugins=yes cat > $TMPC << EOF @@ -2317,69 +2317,6 @@ EOF fi fi -########################################## -# plugin linker support probe - -if test "$plugins" != "no"; then - - ######################################### - # See if --dynamic-list is supported by the linker - - ld_dynamic_list="no" - cat > $TMPTXT < $TMPC < -void foo(void); - -void foo(void) -{ - printf("foo\n"); -} - -int main(void) -{ - foo(); - return 0; -} -EOF - - if compile_prog "" "-Wl,--dynamic-list=$TMPTXT" ; then - ld_dynamic_list="yes" - fi - - ######################################### - # See if -exported_symbols_list is supported by the linker - - ld_exported_symbols_list="no" - cat > $TMPTXT <> $config_host_mak - # Copy the export object list to the build dir - if test "$ld_dynamic_list" = "yes" ; then - echo "CONFIG_HAS_LD_DYNAMIC_LIST=yes" >> $config_host_mak - ld_symbols=qemu-plugins-ld.symbols - cp "$source_path/plugins/qemu-plugins.symbols" $ld_symbols - elif test "$ld_exported_symbols_list" = "yes" ; then - echo "CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST=yes" >> $config_host_mak - ld64_symbols=qemu-plugins-ld64.symbols - echo "# Automatically generated by configure - do not modify" > $ld64_symbols - grep 'qemu_' "$source_path/plugins/qemu-plugins.symbols" | sed 's/;//g' | \ - sed -E 's/^[[:space:]]*(.*)/_\1/' >> $ld64_symbols - else - error_exit \ - "If \$plugins=yes, either \$ld_dynamic_list or " \ - "\$ld_exported_symbols_list should have been set to 'yes'." - fi fi if test -n "$gdb_bin"; then diff --git a/plugins/meson.build b/plugins/meson.build index b3de57853b..fa12047327 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -1,10 +1,15 @@ plugin_ldflags = [] # Modules need more symbols than just those in plugins/qemu-plugins.symbols if not enable_modules - if 'CONFIG_HAS_LD_DYNAMIC_LIST' in config_host - plugin_ldflags = ['-Wl,--dynamic-list=qemu-plugins-ld.symbols'] - elif 'CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST' in config_host - plugin_ldflags = ['-Wl,-exported_symbols_list,qemu-plugins-ld64.symbols'] + if targetos == 'darwin' + qemu_plugins_symbols_list = configure_file( + input: files('qemu-plugins.symbols'), + output: 'qemu-plugins-ld64.symbols', + capture: true, + command: ['sed', '-ne', 's/^[[:space:]]*\\(qemu_.*\\);/_\\1/p', '@INPUT@']) + plugin_ldflags = ['-Wl,-exported_symbols_list,plugins/qemu-plugins-ld64.symbols'] + else + plugin_ldflags = ['-Xlinker', '--dynamic-list=' + (meson.project_source_root() / 'plugins/qemu-plugins.symbols')] endif endif From b915a2f15c016c9e4a3ccafb99d445560742a9ab Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 9 Nov 2021 10:10:41 +0100 Subject: [PATCH 454/730] configure: do not set bsd_user/linux_user early Similar to other optional features, leave the variables empty and compute the actual value later. Use the existence of include or source directories to detect whether an OS or CPU supports respectively bsd-user and linux-user. For now, BSD user-mode emulation is buildable even on TCI-only architectures. This probably will change once safe signals are brought over from linux-user. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- configure | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 1b5fa5ae93..f35d3f198f 100755 --- a/configure +++ b/configure @@ -320,8 +320,8 @@ linux="no" solaris="no" profiler="no" softmmu="yes" -linux_user="no" -bsd_user="no" +linux_user="" +bsd_user="" pkgversion="" pie="" qom_cast_debug="yes" @@ -538,7 +538,6 @@ gnu/kfreebsd) ;; freebsd) bsd="yes" - bsd_user="yes" make="${MAKE-gmake}" # needed for kinfo_getvmmap(3) in libutil.h ;; @@ -583,7 +582,6 @@ haiku) ;; linux) linux="yes" - linux_user="yes" vhost_user=${default_feature:-yes} ;; esac @@ -1259,18 +1257,26 @@ if eval test -z "\${cross_cc_$cpu}"; then cross_cc_vars="$cross_cc_vars cross_cc_${cpu}" fi -# For user-mode emulation the host arch has to be one we explicitly -# support, even if we're using TCI. -if [ "$ARCH" = "unknown" ]; then - bsd_user="no" - linux_user="no" -fi - default_target_list="" deprecated_targets_list=ppc64abi32-linux-user deprecated_features="" mak_wilds="" +if [ "$linux_user" != no ]; then + if [ "$targetos" = linux ] && [ -d $source_path/linux-user/include/host/$cpu ]; then + linux_user=yes + elif [ "$linux_user" = yes ]; then + error_exit "linux-user not supported on this architecture" + fi +fi +if [ "$bsd_user" != no ]; then + if [ "$bsd_user" = "" ]; then + test $targetos = freebsd && bsd_user=yes + fi + if [ "$bsd_user" = yes ] && ! [ -d $source_path/bsd-user/$targetos ]; then + error_exit "bsd-user not supported on this host OS" + fi +fi if [ "$softmmu" = "yes" ]; then mak_wilds="${mak_wilds} $source_path/configs/targets/*-softmmu.mak" fi From 9da9be2c26f509728106db591538bfa2eee03947 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 13 Oct 2021 13:51:32 +0200 Subject: [PATCH 455/730] configure, makefile: remove traces of really old files These files have been removed for more than year in the best case, or for more than ten years for some really old TCG files. Remove any traces of it. Acked-by: Richard Henderson Signed-off-by: Paolo Bonzini --- Makefile | 11 ++++------- configure | 9 --------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 5d66c35ea5..8037f73b35 100644 --- a/Makefile +++ b/Makefile @@ -206,14 +206,11 @@ recurse-clean: $(addsuffix /clean, $(ROM_DIRS)) clean: recurse-clean -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean || : -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) clean-ctlist || : -# avoid old build problems by removing potentially incorrect old files - rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h find . \( -name '*.so' -o -name '*.dll' -o -name '*.[oda]' \) -type f \ ! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-aarch64.a \ ! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-arm.a \ -exec rm {} + - rm -f TAGS cscope.* *.pod *~ */*~ - rm -f fsdev/*.pod scsi/*.pod + rm -f TAGS cscope.* *~ */*~ VERSION = $(shell cat $(SRC_PATH)/VERSION) @@ -224,10 +221,10 @@ qemu-%.tar.bz2: distclean: clean -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || : - rm -f config-host.mak config-host.h* config-poison.h + rm -f config-host.mak config-poison.h rm -f tests/tcg/config-*.mak - rm -f config-all-disas.mak config.status - rm -f roms/seabios/config.mak roms/vgabios/config.mak + rm -f config.status + rm -f roms/seabios/config.mak rm -f qemu-plugins-ld.symbols qemu-plugins-ld64.symbols rm -f *-config-target.h *-config-devices.mak *-config-devices.h rm -rf meson-private meson-logs meson-info compile_commands.json diff --git a/configure b/configure index f35d3f198f..a02febe09c 100755 --- a/configure +++ b/configure @@ -3672,9 +3672,6 @@ fi # so the build tree will be missing the link back to the new file, and # tests might fail. Prefer to keep the relevant files in their own # directory and symlink the directory instead. -# UNLINK is used to remove symlinks from older development versions -# that might get into the way when doing "git update" without doing -# a "make distclean" in between. LINKS="Makefile" LINKS="$LINKS tests/tcg/Makefile.target" LINKS="$LINKS pc-bios/optionrom/Makefile" @@ -3686,7 +3683,6 @@ LINKS="$LINKS tests/avocado tests/data" LINKS="$LINKS tests/qemu-iotests/check" LINKS="$LINKS python" LINKS="$LINKS contrib/plugins/Makefile " -UNLINK="pc-bios/keymaps" for bios_file in \ $source_path/pc-bios/*.bin \ $source_path/pc-bios/*.elf \ @@ -3708,11 +3704,6 @@ for f in $LINKS ; do symlink "$source_path/$f" "$f" fi done -for f in $UNLINK ; do - if [ -L "$f" ]; then - rm -f "$f" - fi -done (for i in $cross_cc_vars; do export $i From a70248dbd381b2ce82192acdcbc3bde441e6c29b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 9 Nov 2021 10:36:39 +0100 Subject: [PATCH 456/730] configure: parse --enable/--disable-strip automatically, flip default Always include the STRIP variable in config-host.mak (it's only used by the s390-ccw firmware build, and it adds a default if configure omitted it), and use meson-buildoptions.sh to turn --enable/--disable-strip into -Dstrip. The default is now not to strip the binaries like for almost every other package that has a configure script. Signed-off-by: Paolo Bonzini --- configure | 10 +--------- pc-bios/s390-ccw/Makefile | 2 -- scripts/meson-buildoptions.py | 21 ++++++++++++++------- scripts/meson-buildoptions.sh | 3 +++ 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/configure b/configure index a02febe09c..be05bcf856 100755 --- a/configure +++ b/configure @@ -307,7 +307,6 @@ debug="no" sanitizers="no" tsan="no" fortify_source="$default_feature" -strip_opt="yes" mingw32="no" gcov="no" EXESUF="" @@ -892,7 +891,6 @@ for opt do debug_tcg="yes" debug_mutex="yes" debug="yes" - strip_opt="no" fortify_source="no" ;; --enable-sanitizers) sanitizers="yes" @@ -903,8 +901,6 @@ for opt do ;; --disable-tsan) tsan="no" ;; - --disable-strip) strip_opt="no" - ;; --disable-slirp) slirp="disabled" ;; --enable-slirp) slirp="enabled" @@ -1367,7 +1363,6 @@ Advanced options (experts only): --enable-debug enable common debug build options --enable-sanitizers enable default sanitizers --enable-tsan enable thread sanitizer - --disable-strip disable stripping binaries --disable-werror disable compilation abort on warning --disable-stack-protector disable compiler-provided stack protection --audio-drv-list=LIST set audio drivers to try if -audiodev is not used @@ -3315,9 +3310,6 @@ echo "GIT_SUBMODULES_ACTION=$git_submodules_action" >> $config_host_mak if test "$debug_tcg" = "yes" ; then echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak fi -if test "$strip_opt" = "yes" ; then - echo "STRIP=${strip}" >> $config_host_mak -fi if test "$mingw32" = "yes" ; then echo "CONFIG_WIN32=y" >> $config_host_mak if test "$guest_agent_with_vss" = "yes" ; then @@ -3595,6 +3587,7 @@ echo "GLIB_LIBS=$glib_libs" >> $config_host_mak echo "GLIB_VERSION=$(pkg-config --modversion glib-2.0)" >> $config_host_mak echo "QEMU_LDFLAGS=$QEMU_LDFLAGS" >> $config_host_mak echo "LD_I386_EMULATION=$ld_i386_emulation" >> $config_host_mak +echo "STRIP=$strip" >> $config_host_mak echo "EXESUF=$EXESUF" >> $config_host_mak echo "LIBS_QGA=$libs_qga" >> $config_host_mak @@ -3812,7 +3805,6 @@ if test "$skip_meson" = no; then -Doptimization=$(if test "$debug" = yes; then echo 0; else echo 2; fi) \ -Ddebug=$(if test "$debug_info" = yes; then echo true; else echo false; fi) \ -Dwerror=$(if test "$werror" = yes; then echo true; else echo false; fi) \ - -Dstrip=$(if test "$strip_opt" = yes; then echo true; else echo false; fi) \ -Db_pie=$(if test "$pie" = yes; then echo true; else echo false; fi) \ -Db_coverage=$(if test "$gcov" = yes; then echo true; else echo false; fi) \ -Db_lto=$lto -Dcfi=$cfi -Dtcg=$tcg -Dxen=$xen \ diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile index cee9d2c63b..0eb68efc7b 100644 --- a/pc-bios/s390-ccw/Makefile +++ b/pc-bios/s390-ccw/Makefile @@ -44,8 +44,6 @@ build-all: s390-ccw.img s390-netboot.img s390-ccw.elf: $(OBJECTS) $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS),"BUILD","$(TARGET_DIR)$@") -STRIP ?= strip - s390-ccw.img: s390-ccw.elf $(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,"STRIP","$(TARGET_DIR)$@") diff --git a/scripts/meson-buildoptions.py b/scripts/meson-buildoptions.py index 96969d89ee..98ae944148 100755 --- a/scripts/meson-buildoptions.py +++ b/scripts/meson-buildoptions.py @@ -36,6 +36,10 @@ SKIP_OPTIONS = { "trace_file", } +BUILTIN_OPTIONS = { + "strip", +} + LINE_WIDTH = 76 @@ -90,14 +94,17 @@ def allow_arg(opt): return not (set(opt["choices"]) <= {"auto", "disabled", "enabled"}) +def filter_options(json): + if ":" in json["name"]: + return False + if json["section"] == "user": + return json["name"] not in SKIP_OPTIONS + else: + return json["name"] in BUILTIN_OPTIONS + + def load_options(json): - json = [ - x - for x in json - if x["section"] == "user" - and ":" not in x["name"] - and x["name"] not in SKIP_OPTIONS - ] + json = [x for x in json if filter_options(x)] return sorted(json, key=lambda x: x["name"]) diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index 50bd7bed4d..a4af02c527 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -13,6 +13,7 @@ meson_options_help() { printf "%s\n" ' jemalloc/system/tcmalloc)' printf "%s\n" ' --enable-slirp[=CHOICE] Whether and how to find the slirp library' printf "%s\n" ' (choices: auto/disabled/enabled/internal/system)' + printf "%s\n" ' --enable-strip Strip targets on install' printf "%s\n" ' --enable-tcg-interpreter TCG with bytecode interpreter (slow)' printf "%s\n" ' --enable-trace-backends=CHOICE' printf "%s\n" ' Set available tracing backends [log] (choices:' @@ -237,6 +238,8 @@ _meson_option_parse() { --disable-spice) printf "%s" -Dspice=disabled ;; --enable-spice-protocol) printf "%s" -Dspice_protocol=enabled ;; --disable-spice-protocol) printf "%s" -Dspice_protocol=disabled ;; + --enable-strip) printf "%s" -Dstrip=true ;; + --disable-strip) printf "%s" -Dstrip=false ;; --enable-tcg) printf "%s" -Dtcg=enabled ;; --disable-tcg) printf "%s" -Dtcg=disabled ;; --enable-tcg-interpreter) printf "%s" -Dtcg_interpreter=true ;; From 3b0d864384f2a273702168ab16935f0973011045 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 13 Oct 2021 14:14:53 +0200 Subject: [PATCH 457/730] configure: move non-command-line variables away from command-line parsing section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it easier to identify candidates for moving to Meson. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- configure | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/configure b/configure index be05bcf856..56c113bd83 100755 --- a/configure +++ b/configure @@ -307,16 +307,12 @@ debug="no" sanitizers="no" tsan="no" fortify_source="$default_feature" -mingw32="no" gcov="no" EXESUF="" modules="no" module_upgrades="no" prefix="/usr/local" qemu_suffix="qemu" -bsd="no" -linux="no" -solaris="no" profiler="no" softmmu="yes" linux_user="" @@ -330,8 +326,6 @@ opengl="$default_feature" cpuid_h="no" avx2_opt="$default_feature" guest_agent="$default_feature" -guest_agent_with_vss="no" -guest_agent_ntddscsi="no" vss_win32_sdk="$default_feature" win_sdk="no" want_tools="$default_feature" @@ -526,6 +520,10 @@ fi # OS specific +mingw32="no" +bsd="no" +linux="no" +solaris="no" case $targetos in windows) mingw32="yes" @@ -2549,6 +2547,7 @@ fi ########################################## # check if we have VSS SDK headers for win +guest_agent_with_vss="no" if test "$mingw32" = "yes" && test "$guest_agent" != "no" && \ test "$vss_win32_sdk" != "no" ; then case "$vss_win32_sdk" in @@ -2579,7 +2578,6 @@ EOF echo "ERROR: The headers are extracted in the directory \`inc'." feature_not_found "VSS support" fi - guest_agent_with_vss="no" fi fi @@ -2606,6 +2604,7 @@ fi ########################################## # check if mingw environment provides a recent ntddscsi.h +guest_agent_ntddscsi="no" if test "$mingw32" = "yes" && test "$guest_agent" != "no"; then cat > $TMPC << EOF #include From b962a1d507bdb7e157f5e0ef3376f3e8e40edfe7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 20 Dec 2021 09:28:46 +0100 Subject: [PATCH 458/730] meson: build contrib/ executables after generated headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will be needed as soon as config-poison.h moves from configure to a meson custom_target (which is built at "ninja" time). Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- contrib/elf2dmp/meson.build | 2 +- contrib/ivshmem-client/meson.build | 2 +- contrib/ivshmem-server/meson.build | 2 +- contrib/rdmacm-mux/meson.build | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/elf2dmp/meson.build b/contrib/elf2dmp/meson.build index 4d86cb390a..6707d43c4f 100644 --- a/contrib/elf2dmp/meson.build +++ b/contrib/elf2dmp/meson.build @@ -1,5 +1,5 @@ if curl.found() - executable('elf2dmp', files('main.c', 'addrspace.c', 'download.c', 'pdb.c', 'qemu_elf.c'), + executable('elf2dmp', files('main.c', 'addrspace.c', 'download.c', 'pdb.c', 'qemu_elf.c'), genh, dependencies: [glib, curl], install: true) endif diff --git a/contrib/ivshmem-client/meson.build b/contrib/ivshmem-client/meson.build index 1b171efb4f..ce8dcca84d 100644 --- a/contrib/ivshmem-client/meson.build +++ b/contrib/ivshmem-client/meson.build @@ -1,4 +1,4 @@ -executable('ivshmem-client', files('ivshmem-client.c', 'main.c'), +executable('ivshmem-client', files('ivshmem-client.c', 'main.c'), genh, dependencies: glib, build_by_default: targetos == 'linux', install: false) diff --git a/contrib/ivshmem-server/meson.build b/contrib/ivshmem-server/meson.build index 3a53942201..c6c3c82e89 100644 --- a/contrib/ivshmem-server/meson.build +++ b/contrib/ivshmem-server/meson.build @@ -1,4 +1,4 @@ -executable('ivshmem-server', files('ivshmem-server.c', 'main.c'), +executable('ivshmem-server', files('ivshmem-server.c', 'main.c'), genh, dependencies: [qemuutil, rt], build_by_default: targetos == 'linux', install: false) diff --git a/contrib/rdmacm-mux/meson.build b/contrib/rdmacm-mux/meson.build index 6cc5016747..7674f54cc5 100644 --- a/contrib/rdmacm-mux/meson.build +++ b/contrib/rdmacm-mux/meson.build @@ -2,7 +2,7 @@ if 'CONFIG_PVRDMA' in config_host # if not found, CONFIG_PVRDMA should not be set # FIXME: broken on big endian architectures libumad = cc.find_library('ibumad', required: true) - executable('rdmacm-mux', files('main.c'), + executable('rdmacm-mux', files('main.c'), genh, dependencies: [glib, libumad], build_by_default: false, install: false) From eed56e9a89f7003e692982a11002bbc432cc2d9f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 10 Nov 2021 11:01:26 +0100 Subject: [PATCH 459/730] configure, meson: move config-poison.h to meson This ensures that the file is regenerated properly whenever config-target.h or config-devices.h files change. Signed-off-by: Paolo Bonzini --- Makefile | 2 +- configure | 11 ----------- meson.build | 12 ++++++++++++ scripts/make-config-poison.sh | 16 ++++++++++++++++ 4 files changed, 29 insertions(+), 12 deletions(-) create mode 100755 scripts/make-config-poison.sh diff --git a/Makefile b/Makefile index 8037f73b35..9e2e3bf004 100644 --- a/Makefile +++ b/Makefile @@ -221,7 +221,7 @@ qemu-%.tar.bz2: distclean: clean -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || : - rm -f config-host.mak config-poison.h + rm -f config-host.mak rm -f tests/tcg/config-*.mak rm -f config.status rm -f roms/seabios/config.mak diff --git a/configure b/configure index 56c113bd83..0026388343 100755 --- a/configure +++ b/configure @@ -3834,17 +3834,6 @@ if test -n "${deprecated_features}"; then echo " features: ${deprecated_features}" fi -# Create list of config switches that should be poisoned in common code... -# but filter out CONFIG_TCG and CONFIG_USER_ONLY which are special. -target_configs_h=$(ls *-config-devices.h *-config-target.h 2>/dev/null) -if test -n "$target_configs_h" ; then - sed -n -e '/CONFIG_TCG/d' -e '/CONFIG_USER_ONLY/d' \ - -e '/^#define / { s///; s/ .*//; s/^/#pragma GCC poison /p; }' \ - $target_configs_h | sort -u > config-poison.h -else - :> config-poison.h -fi - # Save the configure command line for later reuse. cat <config.status #!/bin/sh diff --git a/meson.build b/meson.build index be592aa942..d36a18cb28 100644 --- a/meson.build +++ b/meson.build @@ -2028,6 +2028,18 @@ config_all += { 'CONFIG_ALL': true, } +target_configs_h = [] +foreach target: target_dirs + target_configs_h += config_target_h[target] + target_configs_h += config_devices_h.get(target, []) +endforeach +genh += custom_target('config-poison.h', + input: [target_configs_h], + output: 'config-poison.h', + capture: true, + command: [find_program('scripts/make-config-poison.sh'), + target_configs_h]) + ############## # Submodules # ############## diff --git a/scripts/make-config-poison.sh b/scripts/make-config-poison.sh new file mode 100755 index 0000000000..d222a04304 --- /dev/null +++ b/scripts/make-config-poison.sh @@ -0,0 +1,16 @@ +#! /bin/sh + +if test $# = 0; then + exit 0 +fi + +# Create list of config switches that should be poisoned in common code... +# but filter out CONFIG_TCG and CONFIG_USER_ONLY which are special. +exec sed -n \ + -e' /CONFIG_TCG/d' \ + -e '/CONFIG_USER_ONLY/d' \ + -e '/^#define / {' \ + -e 's///' \ + -e 's/ .*//' \ + -e 's/^/#pragma GCC poison /p' \ + -e '}' "$@" From b7a75c8c4275a4dec2d034a225f6446ca441e6d5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 8 Nov 2021 12:59:16 +0100 Subject: [PATCH 460/730] meson: add comments in the target-specific flags section Signed-off-by: Paolo Bonzini --- meson.build | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/meson.build b/meson.build index d36a18cb28..937658359e 100644 --- a/meson.build +++ b/meson.build @@ -238,6 +238,7 @@ endif # Target-specific checks and dependencies # ########################################### +# Fuzzing if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \ not cc.links(''' #include @@ -249,6 +250,7 @@ if get_option('fuzzing') and get_option('fuzzing_engine') == '' and \ error('Your compiler does not support -fsanitize=fuzzer') endif +# Tracing backends if 'ftrace' in get_option('trace_backends') and targetos != 'linux' error('ftrace is supported only on Linux') endif @@ -262,6 +264,7 @@ if 'syslog' in get_option('trace_backends') and not cc.compiles(''' error('syslog is not supported on this system') endif +# Miscellaneous Linux-only features if targetos != 'linux' and get_option('mpath').enabled() error('Multipath is supported only on Linux') endif @@ -271,6 +274,7 @@ if targetos != 'linux' and get_option('multiprocess').enabled() endif multiprocess_allowed = targetos == 'linux' and not get_option('multiprocess').disabled() +# Target-specific libraries and flags libm = cc.find_library('m', required: false) threads = dependency('threads') util = cc.find_library('util', required: false) @@ -311,6 +315,7 @@ elif targetos == 'openbsd' endif endif +# Target-specific configuration of accelerators accelerators = [] if not get_option('kvm').disabled() and targetos == 'linux' accelerators += 'CONFIG_KVM' From 8f515d386971c242be9aee0da4c21661e12fa30a Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Mon, 1 Nov 2021 15:22:58 +0200 Subject: [PATCH 461/730] KVM: use KVM_{GET|SET}_SREGS2 when supported. This allows to make PDPTRs part of the migration stream and thus not reload them after migration which is against X86 spec. Signed-off-by: Maxim Levitsky Message-Id: <20211101132300.192584-2-mlevitsk@redhat.com> Signed-off-by: Paolo Bonzini --- target/i386/cpu.h | 3 ++ target/i386/kvm/kvm.c | 108 +++++++++++++++++++++++++++++++++++++++++- target/i386/machine.c | 29 ++++++++++++ 3 files changed, 138 insertions(+), 2 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 04f2b790c9..9911d7c871 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1455,6 +1455,9 @@ typedef struct CPUX86State { SegmentCache idt; /* only base and limit are used */ target_ulong cr[5]; /* NOTE: cr1 is unused */ + + bool pdptrs_valid; + uint64_t pdptrs[4]; int32_t a20_mask; BNDReg bnd_regs[4]; diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 13f8e30c2a..d81745620b 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -124,6 +124,7 @@ static uint32_t num_architectural_pmu_fixed_counters; static int has_xsave; static int has_xcrs; static int has_pit_state2; +static int has_sregs2; static int has_exception_payload; static bool has_msr_mcg_ext_ctl; @@ -2324,6 +2325,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) has_xsave = kvm_check_extension(s, KVM_CAP_XSAVE); has_xcrs = kvm_check_extension(s, KVM_CAP_XCRS); has_pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2); + has_sregs2 = kvm_check_extension(s, KVM_CAP_SREGS2) > 0; hv_vpindex_settable = kvm_check_extension(s, KVM_CAP_HYPERV_VP_INDEX); @@ -2650,6 +2652,61 @@ static int kvm_put_sregs(X86CPU *cpu) return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS, &sregs); } +static int kvm_put_sregs2(X86CPU *cpu) +{ + CPUX86State *env = &cpu->env; + struct kvm_sregs2 sregs; + int i; + + sregs.flags = 0; + + if ((env->eflags & VM_MASK)) { + set_v8086_seg(&sregs.cs, &env->segs[R_CS]); + set_v8086_seg(&sregs.ds, &env->segs[R_DS]); + set_v8086_seg(&sregs.es, &env->segs[R_ES]); + set_v8086_seg(&sregs.fs, &env->segs[R_FS]); + set_v8086_seg(&sregs.gs, &env->segs[R_GS]); + set_v8086_seg(&sregs.ss, &env->segs[R_SS]); + } else { + set_seg(&sregs.cs, &env->segs[R_CS]); + set_seg(&sregs.ds, &env->segs[R_DS]); + set_seg(&sregs.es, &env->segs[R_ES]); + set_seg(&sregs.fs, &env->segs[R_FS]); + set_seg(&sregs.gs, &env->segs[R_GS]); + set_seg(&sregs.ss, &env->segs[R_SS]); + } + + set_seg(&sregs.tr, &env->tr); + set_seg(&sregs.ldt, &env->ldt); + + sregs.idt.limit = env->idt.limit; + sregs.idt.base = env->idt.base; + memset(sregs.idt.padding, 0, sizeof sregs.idt.padding); + sregs.gdt.limit = env->gdt.limit; + sregs.gdt.base = env->gdt.base; + memset(sregs.gdt.padding, 0, sizeof sregs.gdt.padding); + + sregs.cr0 = env->cr[0]; + sregs.cr2 = env->cr[2]; + sregs.cr3 = env->cr[3]; + sregs.cr4 = env->cr[4]; + + sregs.cr8 = cpu_get_apic_tpr(cpu->apic_state); + sregs.apic_base = cpu_get_apic_base(cpu->apic_state); + + sregs.efer = env->efer; + + if (env->pdptrs_valid) { + for (i = 0; i < 4; i++) { + sregs.pdptrs[i] = env->pdptrs[i]; + } + sregs.flags |= KVM_SREGS2_FLAGS_PDPTRS_VALID; + } + + return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_SREGS2, &sregs); +} + + static void kvm_msr_buf_reset(X86CPU *cpu) { memset(cpu->kvm_msr_buf, 0, MSR_BUF_SIZE); @@ -3330,6 +3387,53 @@ static int kvm_get_sregs(X86CPU *cpu) return 0; } +static int kvm_get_sregs2(X86CPU *cpu) +{ + CPUX86State *env = &cpu->env; + struct kvm_sregs2 sregs; + int i, ret; + + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS2, &sregs); + if (ret < 0) { + return ret; + } + + get_seg(&env->segs[R_CS], &sregs.cs); + get_seg(&env->segs[R_DS], &sregs.ds); + get_seg(&env->segs[R_ES], &sregs.es); + get_seg(&env->segs[R_FS], &sregs.fs); + get_seg(&env->segs[R_GS], &sregs.gs); + get_seg(&env->segs[R_SS], &sregs.ss); + + get_seg(&env->tr, &sregs.tr); + get_seg(&env->ldt, &sregs.ldt); + + env->idt.limit = sregs.idt.limit; + env->idt.base = sregs.idt.base; + env->gdt.limit = sregs.gdt.limit; + env->gdt.base = sregs.gdt.base; + + env->cr[0] = sregs.cr0; + env->cr[2] = sregs.cr2; + env->cr[3] = sregs.cr3; + env->cr[4] = sregs.cr4; + + env->efer = sregs.efer; + + env->pdptrs_valid = sregs.flags & KVM_SREGS2_FLAGS_PDPTRS_VALID; + + if (env->pdptrs_valid) { + for (i = 0; i < 4; i++) { + env->pdptrs[i] = sregs.pdptrs[i]; + } + } + + /* changes to apic base and cr8/tpr are read back via kvm_arch_post_run */ + x86_update_hflags(env); + + return 0; +} + static int kvm_get_msrs(X86CPU *cpu) { CPUX86State *env = &cpu->env; @@ -4173,7 +4277,7 @@ int kvm_arch_put_registers(CPUState *cpu, int level) assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); /* must be before kvm_put_nested_state so that EFER.SVME is set */ - ret = kvm_put_sregs(x86_cpu); + ret = has_sregs2 ? kvm_put_sregs2(x86_cpu) : kvm_put_sregs(x86_cpu); if (ret < 0) { return ret; } @@ -4278,7 +4382,7 @@ int kvm_arch_get_registers(CPUState *cs) if (ret < 0) { goto out; } - ret = kvm_get_sregs(cpu); + ret = has_sregs2 ? kvm_get_sregs2(cpu) : kvm_get_sregs(cpu); if (ret < 0) { goto out; } diff --git a/target/i386/machine.c b/target/i386/machine.c index 83c2b91529..6202f47793 100644 --- a/target/i386/machine.c +++ b/target/i386/machine.c @@ -1451,6 +1451,34 @@ static const VMStateDescription vmstate_msr_intel_sgx = { .needed = intel_sgx_msrs_needed, .fields = (VMStateField[]) { VMSTATE_UINT64_ARRAY(env.msr_ia32_sgxlepubkeyhash, X86CPU, 4), + VMSTATE_END_OF_LIST() + } + }; + +static bool pdptrs_needed(void *opaque) +{ + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + return env->pdptrs_valid; +} + +static int pdptrs_post_load(void *opaque, int version_id) +{ + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + env->pdptrs_valid = true; + return 0; +} + + +static const VMStateDescription vmstate_pdptrs = { + .name = "cpu/pdptrs", + .version_id = 1, + .minimum_version_id = 1, + .needed = pdptrs_needed, + .post_load = pdptrs_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT64_ARRAY(env.pdptrs, X86CPU, 4), VMSTATE_END_OF_LIST() } }; @@ -1593,6 +1621,7 @@ const VMStateDescription vmstate_x86_cpu = { #endif &vmstate_msr_tsx_ctrl, &vmstate_msr_intel_sgx, + &vmstate_pdptrs, NULL } }; From 1520f8bb671ce3c1b8a3b5ed3bbdfe1a06aa8691 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 21 Dec 2021 10:12:53 +0100 Subject: [PATCH 462/730] KVM: x86: ignore interrupt_bitmap field of KVM_GET/SET_SREGS This is unnecessary, because the interrupt would be retrieved and queued anyway by KVM_GET_VCPU_EVENTS and KVM_SET_VCPU_EVENTS respectively, and it makes the flow more similar to the one for KVM_GET/SET_SREGS2. Signed-off-by: Paolo Bonzini --- target/i386/kvm/kvm.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index d81745620b..2c8feb4a6f 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -2607,11 +2607,11 @@ static int kvm_put_sregs(X86CPU *cpu) CPUX86State *env = &cpu->env; struct kvm_sregs sregs; + /* + * The interrupt_bitmap is ignored because KVM_SET_SREGS is + * always followed by KVM_SET_VCPU_EVENTS. + */ memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap)); - if (env->interrupt_injected >= 0) { - sregs.interrupt_bitmap[env->interrupt_injected / 64] |= - (uint64_t)1 << (env->interrupt_injected % 64); - } if ((env->eflags & VM_MASK)) { set_v8086_seg(&sregs.cs, &env->segs[R_CS]); @@ -3341,23 +3341,17 @@ static int kvm_get_sregs(X86CPU *cpu) { CPUX86State *env = &cpu->env; struct kvm_sregs sregs; - int bit, i, ret; + int ret; ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_SREGS, &sregs); if (ret < 0) { return ret; } - /* There can only be one pending IRQ set in the bitmap at a time, so try - to find it and save its number instead (-1 for none). */ - env->interrupt_injected = -1; - for (i = 0; i < ARRAY_SIZE(sregs.interrupt_bitmap); i++) { - if (sregs.interrupt_bitmap[i]) { - bit = ctz64(sregs.interrupt_bitmap[i]); - env->interrupt_injected = i * 64 + bit; - break; - } - } + /* + * The interrupt_bitmap is ignored because KVM_GET_SREGS is + * always preceded by KVM_GET_VCPU_EVENTS. + */ get_seg(&env->segs[R_CS], &sregs.cs); get_seg(&env->segs[R_DS], &sregs.ds); From 533b0a1a41df3d9edeb44d6dc957f04d20ca143f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Sun, 26 Dec 2021 01:15:41 +0100 Subject: [PATCH 463/730] tests/tcg: Fix target-specific Makefile variables path for user-mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 812b31d3f91 refactor missed to update this path. Fixes: 812b31d3f91 ("configs: rename default-configs to configs and reorganise") Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211226001541.3807919-1-f4bug@amsat.org> Signed-off-by: Paolo Bonzini --- tests/tcg/Makefile.target | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target index 0f8645f782..ae8004c76e 100644 --- a/tests/tcg/Makefile.target +++ b/tests/tcg/Makefile.target @@ -33,7 +33,7 @@ all: -include ../../../config-host.mak -include ../config-$(TARGET).mak ifeq ($(CONFIG_USER_ONLY),y) --include $(SRC_PATH)/default-configs/targets/$(TARGET).mak +-include $(SRC_PATH)/configs/targets/$(TARGET)/default.mak endif # for including , in command strings From bb7cb3ad295c1d99e694f3133de571d80442fb61 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Jan 2022 12:40:29 +0100 Subject: [PATCH 464/730] configure: do not create roms/seabios/config.mak if SeaBIOS not present If roms/seabios/Makefile is not present, the configure script is not creating the roms/seabios directory anymore (commit 5dce7b8d8c, "configure: remove DIRS", 2021-12-18); thus, creating roms/seabios/config.mak fails. The easiest thing to do is to not create the file, since it will not be used. Signed-off-by: Paolo Bonzini --- configure | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 0026388343..e1a31fb332 100755 --- a/configure +++ b/configure @@ -3704,7 +3704,8 @@ export target_list source_path use_containers cpu $source_path/tests/tcg/configure.sh) # temporary config to build submodules -for rom in seabios; do +if test -f $source_path/roms/seabios/Makefile; then + for rom in seabios; do config_mak=roms/$rom/config.mak echo "# Automatically generated by configure - do not modify" > $config_mak echo "SRC_PATH=$source_path/roms/$rom" >> $config_mak @@ -3717,7 +3718,8 @@ for rom in seabios; do echo "IASL=$iasl" >> $config_mak echo "LD=$ld" >> $config_mak echo "RANLIB=$ranlib" >> $config_mak -done + done +fi config_mak=pc-bios/optionrom/config.mak echo "# Automatically generated by configure - do not modify" > $config_mak From fb72176ba64057ce0ee5c1a0a443d9f72e270636 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Jan 2022 13:00:44 +0100 Subject: [PATCH 465/730] meson: build all modules by default With more recent versions of Meson, the build.ninja file is more selective as to what is built by default, and not building the modules results in test failures. Mark the modules as built-by-default and, to make the dependencies more precise, also require them to be up-to-date before running tests. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/801 Tested-by: Li Zhang Signed-off-by: Paolo Bonzini --- meson.build | 4 +++- tests/qtest/meson.build | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index 937658359e..762d7cee85 100644 --- a/meson.build +++ b/meson.build @@ -2866,8 +2866,10 @@ common_ss.add(hwcore) # Targets # ########### +emulator_modules = [] foreach m : block_mods + softmmu_mods - shared_module(m.name(), + emulator_modules += shared_module(m.name(), + build_by_default: true, name_prefix: '', link_whole: m, install: true, diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 37e1eaa449..26937deb6d 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -335,10 +335,9 @@ foreach dir : target_dirs test: executable(test, src, dependencies: deps) } endif - # FIXME: missing dependency on the emulator binary and qemu-img test('qtest-@0@/@1@'.format(target_base, test), qtest_executables[test], - depends: [test_deps, qtest_emulator], + depends: [test_deps, qtest_emulator, emulator_modules], env: qtest_env, args: ['--tap', '-k'], protocol: 'tap', From 9d30c78c7d3b994825cbe63fa277279ae3ef4248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Fri, 7 Jan 2022 14:35:14 +0100 Subject: [PATCH 466/730] meson: reenable filemonitor-inotify compilation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reenable util/filemonitor-inotify compilation. Compilation was disabled when commit a620fbe9ac ("configure: convert compiler tests to meson, part 5") moved CONFIG_INOTIFY1 from config-host.mak to config-host.h. This fixes the usb-mtp device and reenables test-util-filemonitor. Fixes: a620fbe9ac ("configure: convert compiler tests to meson, part 5") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/800 Signed-off-by: Volker Rümelin Message-Id: <20220107133514.7785-1-vr_qemu@t-online.de> Signed-off-by: Paolo Bonzini --- tests/unit/meson.build | 2 +- util/meson.build | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/unit/meson.build b/tests/unit/meson.build index 90acf5b0da..64a5e7bfde 100644 --- a/tests/unit/meson.build +++ b/tests/unit/meson.build @@ -129,7 +129,7 @@ if have_system 'test-vmstate': [migration, io], 'test-yank': ['socket-helpers.c', qom, io, chardev] } - if 'CONFIG_INOTIFY1' in config_host + if config_host_data.get('CONFIG_INOTIFY1') tests += {'test-util-filemonitor': []} endif diff --git a/util/meson.build b/util/meson.build index e676b2f6c6..c9a9cc1cf5 100644 --- a/util/meson.build +++ b/util/meson.build @@ -84,7 +84,10 @@ if have_block util_ss.add(files('readline.c')) util_ss.add(files('throttle.c')) util_ss.add(files('timed-average.c')) - util_ss.add(when: 'CONFIG_INOTIFY1', if_true: files('filemonitor-inotify.c'), - if_false: files('filemonitor-stub.c')) + if config_host_data.get('CONFIG_INOTIFY1') + util_ss.add(files('filemonitor-inotify.c')) + else + util_ss.add(files('filemonitor-stub.c')) + endif util_ss.add(when: 'CONFIG_LINUX', if_true: files('vfio-helpers.c')) endif From 826cc32423db2a99d184dbf4f507c737d7e7a4ae Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 7 Dec 2021 13:23:31 +0000 Subject: [PATCH 467/730] aio-posix: split poll check from ready handler Adaptive polling measures the execution time of the polling check plus handlers called when a polled event becomes ready. Handlers can take a significant amount of time, making it look like polling was running for a long time when in fact the event handler was running for a long time. For example, on Linux the io_submit(2) syscall invoked when a virtio-blk device's virtqueue becomes ready can take 10s of microseconds. This can exceed the default polling interval (32 microseconds) and cause adaptive polling to stop polling. By excluding the handler's execution time from the polling check we make the adaptive polling calculation more accurate. As a result, the event loop now stays in polling mode where previously it would have fallen back to file descriptor monitoring. The following data was collected with virtio-blk num-queues=2 event_idx=off using an IOThread. Before: 168k IOPS, IOThread syscalls: 9837.115 ( 0.020 ms): IO iothread1/620155 io_submit(ctx_id: 140512552468480, nr: 16, iocbpp: 0x7fcb9f937db0) = 16 9837.158 ( 0.002 ms): IO iothread1/620155 write(fd: 103, buf: 0x556a2ef71b88, count: 8) = 8 9837.161 ( 0.001 ms): IO iothread1/620155 write(fd: 104, buf: 0x556a2ef71b88, count: 8) = 8 9837.163 ( 0.001 ms): IO iothread1/620155 ppoll(ufds: 0x7fcb90002800, nfds: 4, tsp: 0x7fcb9f1342d0, sigsetsize: 8) = 3 9837.164 ( 0.001 ms): IO iothread1/620155 read(fd: 107, buf: 0x7fcb9f939cc0, count: 512) = 8 9837.174 ( 0.001 ms): IO iothread1/620155 read(fd: 105, buf: 0x7fcb9f939cc0, count: 512) = 8 9837.176 ( 0.001 ms): IO iothread1/620155 read(fd: 106, buf: 0x7fcb9f939cc0, count: 512) = 8 9837.209 ( 0.035 ms): IO iothread1/620155 io_submit(ctx_id: 140512552468480, nr: 32, iocbpp: 0x7fca7d0cebe0) = 32 174k IOPS (+3.6%), IOThread syscalls: 9809.566 ( 0.036 ms): IO iothread1/623061 io_submit(ctx_id: 140539805028352, nr: 32, iocbpp: 0x7fd0cdd62be0) = 32 9809.625 ( 0.001 ms): IO iothread1/623061 write(fd: 103, buf: 0x5647cfba5f58, count: 8) = 8 9809.627 ( 0.002 ms): IO iothread1/623061 write(fd: 104, buf: 0x5647cfba5f58, count: 8) = 8 9809.663 ( 0.036 ms): IO iothread1/623061 io_submit(ctx_id: 140539805028352, nr: 32, iocbpp: 0x7fd0d0388b50) = 32 Notice that ppoll(2) and eventfd read(2) syscalls are eliminated because the IOThread stays in polling mode instead of falling back to file descriptor monitoring. As usual, polling is not implemented on Windows so this patch ignores the new io_poll_read() callback in aio-win32.c. Signed-off-by: Stefan Hajnoczi Reviewed-by: Stefano Garzarella Message-id: 20211207132336.36627-2-stefanha@redhat.com [Fixed up aio_set_event_notifier() calls in tests/unit/test-fdmon-epoll.c added after this series was queued. --Stefan] Signed-off-by: Stefan Hajnoczi --- block/curl.c | 11 +++-- block/export/fuse.c | 4 +- block/io_uring.c | 19 ++++---- block/iscsi.c | 4 +- block/linux-aio.c | 16 ++++--- block/nfs.c | 6 +-- block/nvme.c | 51 +++++++++++++------- block/ssh.c | 4 +- block/win32-aio.c | 4 +- hw/virtio/virtio.c | 16 ++++--- hw/xen/xen-bus.c | 6 +-- include/block/aio.h | 4 +- io/channel-command.c | 6 ++- io/channel-file.c | 3 +- io/channel-socket.c | 3 +- migration/rdma.c | 8 ++-- tests/unit/test-aio.c | 4 +- tests/unit/test-fdmon-epoll.c | 4 +- util/aio-posix.c | 89 ++++++++++++++++++++++++++--------- util/aio-posix.h | 1 + util/aio-win32.c | 4 +- util/async.c | 10 +++- util/main-loop.c | 4 +- util/qemu-coroutine-io.c | 5 +- util/vhost-user-server.c | 11 +++-- 25 files changed, 193 insertions(+), 104 deletions(-) diff --git a/block/curl.c b/block/curl.c index 4a8ae2b269..6a6cd72975 100644 --- a/block/curl.c +++ b/block/curl.c @@ -125,7 +125,7 @@ static gboolean curl_drop_socket(void *key, void *value, void *opaque) BDRVCURLState *s = socket->s; aio_set_fd_handler(s->aio_context, socket->fd, false, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); return true; } @@ -173,19 +173,20 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, switch (action) { case CURL_POLL_IN: aio_set_fd_handler(s->aio_context, fd, false, - curl_multi_do, NULL, NULL, socket); + curl_multi_do, NULL, NULL, NULL, socket); break; case CURL_POLL_OUT: aio_set_fd_handler(s->aio_context, fd, false, - NULL, curl_multi_do, NULL, socket); + NULL, curl_multi_do, NULL, NULL, socket); break; case CURL_POLL_INOUT: aio_set_fd_handler(s->aio_context, fd, false, - curl_multi_do, curl_multi_do, NULL, socket); + curl_multi_do, curl_multi_do, + NULL, NULL, socket); break; case CURL_POLL_REMOVE: aio_set_fd_handler(s->aio_context, fd, false, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); break; } diff --git a/block/export/fuse.c b/block/export/fuse.c index 823c126d23..6710d8aed8 100644 --- a/block/export/fuse.c +++ b/block/export/fuse.c @@ -223,7 +223,7 @@ static int setup_fuse_export(FuseExport *exp, const char *mountpoint, aio_set_fd_handler(exp->common.ctx, fuse_session_fd(exp->fuse_session), true, - read_from_fuse_export, NULL, NULL, exp); + read_from_fuse_export, NULL, NULL, NULL, exp); exp->fd_handler_set_up = true; return 0; @@ -267,7 +267,7 @@ static void fuse_export_shutdown(BlockExport *blk_exp) if (exp->fd_handler_set_up) { aio_set_fd_handler(exp->common.ctx, fuse_session_fd(exp->fuse_session), true, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); exp->fd_handler_set_up = false; } } diff --git a/block/io_uring.c b/block/io_uring.c index dfa475cc87..782afdb433 100644 --- a/block/io_uring.c +++ b/block/io_uring.c @@ -292,12 +292,14 @@ static bool qemu_luring_poll_cb(void *opaque) { LuringState *s = opaque; - if (io_uring_cq_ready(&s->ring)) { - luring_process_completions_and_submit(s); - return true; - } + return io_uring_cq_ready(&s->ring); +} - return false; +static void qemu_luring_poll_ready(void *opaque) +{ + LuringState *s = opaque; + + luring_process_completions_and_submit(s); } static void ioq_init(LuringQueue *io_q) @@ -402,8 +404,8 @@ int coroutine_fn luring_co_submit(BlockDriverState *bs, LuringState *s, int fd, void luring_detach_aio_context(LuringState *s, AioContext *old_context) { - aio_set_fd_handler(old_context, s->ring.ring_fd, false, NULL, NULL, NULL, - s); + aio_set_fd_handler(old_context, s->ring.ring_fd, false, + NULL, NULL, NULL, NULL, s); qemu_bh_delete(s->completion_bh); s->aio_context = NULL; } @@ -413,7 +415,8 @@ void luring_attach_aio_context(LuringState *s, AioContext *new_context) s->aio_context = new_context; s->completion_bh = aio_bh_new(new_context, qemu_luring_completion_bh, s); aio_set_fd_handler(s->aio_context, s->ring.ring_fd, false, - qemu_luring_completion_cb, NULL, qemu_luring_poll_cb, s); + qemu_luring_completion_cb, NULL, + qemu_luring_poll_cb, qemu_luring_poll_ready, s); } LuringState *luring_init(Error **errp) diff --git a/block/iscsi.c b/block/iscsi.c index 57aa07a40d..51f2a5eeaa 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -363,7 +363,7 @@ iscsi_set_events(IscsiLun *iscsilun) false, (ev & POLLIN) ? iscsi_process_read : NULL, (ev & POLLOUT) ? iscsi_process_write : NULL, - NULL, + NULL, NULL, iscsilun); iscsilun->events = ev; } @@ -1534,7 +1534,7 @@ static void iscsi_detach_aio_context(BlockDriverState *bs) IscsiLun *iscsilun = bs->opaque; aio_set_fd_handler(iscsilun->aio_context, iscsi_get_fd(iscsilun->iscsi), - false, NULL, NULL, NULL, NULL); + false, NULL, NULL, NULL, NULL, NULL); iscsilun->events = 0; if (iscsilun->nop_timer) { diff --git a/block/linux-aio.c b/block/linux-aio.c index f53ae72e21..4c423fcccf 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -263,12 +263,15 @@ static bool qemu_laio_poll_cb(void *opaque) LinuxAioState *s = container_of(e, LinuxAioState, e); struct io_event *events; - if (!io_getevents_peek(s->ctx, &events)) { - return false; - } + return io_getevents_peek(s->ctx, &events); +} + +static void qemu_laio_poll_ready(EventNotifier *opaque) +{ + EventNotifier *e = opaque; + LinuxAioState *s = container_of(e, LinuxAioState, e); qemu_laio_process_completions_and_submit(s); - return true; } static void ioq_init(LaioQueue *io_q) @@ -427,7 +430,7 @@ int coroutine_fn laio_co_submit(BlockDriverState *bs, LinuxAioState *s, int fd, void laio_detach_aio_context(LinuxAioState *s, AioContext *old_context) { - aio_set_event_notifier(old_context, &s->e, false, NULL, NULL); + aio_set_event_notifier(old_context, &s->e, false, NULL, NULL, NULL); qemu_bh_delete(s->completion_bh); s->aio_context = NULL; } @@ -438,7 +441,8 @@ void laio_attach_aio_context(LinuxAioState *s, AioContext *new_context) s->completion_bh = aio_bh_new(new_context, qemu_laio_completion_bh, s); aio_set_event_notifier(new_context, &s->e, false, qemu_laio_completion_cb, - qemu_laio_poll_cb); + qemu_laio_poll_cb, + qemu_laio_poll_ready); } LinuxAioState *laio_init(Error **errp) diff --git a/block/nfs.c b/block/nfs.c index 577aea1d22..444c40b458 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -197,7 +197,7 @@ static void nfs_set_events(NFSClient *client) false, (ev & POLLIN) ? nfs_process_read : NULL, (ev & POLLOUT) ? nfs_process_write : NULL, - NULL, client); + NULL, NULL, client); } client->events = ev; @@ -372,7 +372,7 @@ static void nfs_detach_aio_context(BlockDriverState *bs) NFSClient *client = bs->opaque; aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), - false, NULL, NULL, NULL, NULL); + false, NULL, NULL, NULL, NULL, NULL); client->events = 0; } @@ -390,7 +390,7 @@ static void nfs_client_close(NFSClient *client) if (client->context) { qemu_mutex_lock(&client->mutex); aio_set_fd_handler(client->aio_context, nfs_get_fd(client->context), - false, NULL, NULL, NULL, NULL); + false, NULL, NULL, NULL, NULL, NULL); qemu_mutex_unlock(&client->mutex); if (client->fh) { nfs_close(client->context, client->fh); diff --git a/block/nvme.c b/block/nvme.c index fa360b9b3c..dd20de3865 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -605,10 +605,8 @@ out: return ret; } -static bool nvme_poll_queue(NVMeQueuePair *q) +static void nvme_poll_queue(NVMeQueuePair *q) { - bool progress = false; - const size_t cqe_offset = q->cq.head * NVME_CQ_ENTRY_BYTES; NvmeCqe *cqe = (NvmeCqe *)&q->cq.queue[cqe_offset]; @@ -619,30 +617,23 @@ static bool nvme_poll_queue(NVMeQueuePair *q) * cannot race with itself. */ if ((le16_to_cpu(cqe->status) & 0x1) == q->cq_phase) { - return false; + return; } qemu_mutex_lock(&q->lock); while (nvme_process_completion(q)) { /* Keep polling */ - progress = true; } qemu_mutex_unlock(&q->lock); - - return progress; } -static bool nvme_poll_queues(BDRVNVMeState *s) +static void nvme_poll_queues(BDRVNVMeState *s) { - bool progress = false; int i; for (i = 0; i < s->queue_count; i++) { - if (nvme_poll_queue(s->queues[i])) { - progress = true; - } + nvme_poll_queue(s->queues[i]); } - return progress; } static void nvme_handle_event(EventNotifier *n) @@ -703,8 +694,30 @@ static bool nvme_poll_cb(void *opaque) EventNotifier *e = opaque; BDRVNVMeState *s = container_of(e, BDRVNVMeState, irq_notifier[MSIX_SHARED_IRQ_IDX]); + int i; - return nvme_poll_queues(s); + for (i = 0; i < s->queue_count; i++) { + NVMeQueuePair *q = s->queues[i]; + const size_t cqe_offset = q->cq.head * NVME_CQ_ENTRY_BYTES; + NvmeCqe *cqe = (NvmeCqe *)&q->cq.queue[cqe_offset]; + + /* + * q->lock isn't needed because nvme_process_completion() only runs in + * the event loop thread and cannot race with itself. + */ + if ((le16_to_cpu(cqe->status) & 0x1) != q->cq_phase) { + return true; + } + } + return false; +} + +static void nvme_poll_ready(EventNotifier *e) +{ + BDRVNVMeState *s = container_of(e, BDRVNVMeState, + irq_notifier[MSIX_SHARED_IRQ_IDX]); + + nvme_poll_queues(s); } static int nvme_init(BlockDriverState *bs, const char *device, int namespace, @@ -839,7 +852,8 @@ static int nvme_init(BlockDriverState *bs, const char *device, int namespace, } aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier[MSIX_SHARED_IRQ_IDX], - false, nvme_handle_event, nvme_poll_cb); + false, nvme_handle_event, nvme_poll_cb, + nvme_poll_ready); if (!nvme_identify(bs, namespace, errp)) { ret = -EIO; @@ -924,7 +938,7 @@ static void nvme_close(BlockDriverState *bs) g_free(s->queues); aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier[MSIX_SHARED_IRQ_IDX], - false, NULL, NULL); + false, NULL, NULL, NULL); event_notifier_cleanup(&s->irq_notifier[MSIX_SHARED_IRQ_IDX]); qemu_vfio_pci_unmap_bar(s->vfio, 0, s->bar0_wo_map, 0, sizeof(NvmeBar) + NVME_DOORBELL_SIZE); @@ -1520,7 +1534,7 @@ static void nvme_detach_aio_context(BlockDriverState *bs) aio_set_event_notifier(bdrv_get_aio_context(bs), &s->irq_notifier[MSIX_SHARED_IRQ_IDX], - false, NULL, NULL); + false, NULL, NULL, NULL); } static void nvme_attach_aio_context(BlockDriverState *bs, @@ -1530,7 +1544,8 @@ static void nvme_attach_aio_context(BlockDriverState *bs, s->aio_context = new_context; aio_set_event_notifier(new_context, &s->irq_notifier[MSIX_SHARED_IRQ_IDX], - false, nvme_handle_event, nvme_poll_cb); + false, nvme_handle_event, nvme_poll_cb, + nvme_poll_ready); for (unsigned i = 0; i < s->queue_count; i++) { NVMeQueuePair *q = s->queues[i]; diff --git a/block/ssh.c b/block/ssh.c index e0fbb4934b..3b5bf34031 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -990,7 +990,7 @@ static void restart_coroutine(void *opaque) AioContext *ctx = bdrv_get_aio_context(bs); trace_ssh_restart_coroutine(restart->co); - aio_set_fd_handler(ctx, s->sock, false, NULL, NULL, NULL, NULL); + aio_set_fd_handler(ctx, s->sock, false, NULL, NULL, NULL, NULL, NULL); aio_co_wake(restart->co); } @@ -1020,7 +1020,7 @@ static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs) trace_ssh_co_yield(s->sock, rd_handler, wr_handler); aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, - false, rd_handler, wr_handler, NULL, &restart); + false, rd_handler, wr_handler, NULL, NULL, &restart); qemu_coroutine_yield(); trace_ssh_co_yield_back(s->sock); } diff --git a/block/win32-aio.c b/block/win32-aio.c index b7221a272f..c57e10c997 100644 --- a/block/win32-aio.c +++ b/block/win32-aio.c @@ -172,7 +172,7 @@ int win32_aio_attach(QEMUWin32AIOState *aio, HANDLE hfile) void win32_aio_detach_aio_context(QEMUWin32AIOState *aio, AioContext *old_context) { - aio_set_event_notifier(old_context, &aio->e, false, NULL, NULL); + aio_set_event_notifier(old_context, &aio->e, false, NULL, NULL, NULL); aio->aio_ctx = NULL; } @@ -181,7 +181,7 @@ void win32_aio_attach_aio_context(QEMUWin32AIOState *aio, { aio->aio_ctx = new_context; aio_set_event_notifier(new_context, &aio->e, false, - win32_aio_completion_cb, NULL); + win32_aio_completion_cb, NULL, NULL); } QEMUWin32AIOState *win32_aio_init(void) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 5d18868d7d..5db7f69237 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3536,11 +3536,14 @@ static bool virtio_queue_host_notifier_aio_poll(void *opaque) EventNotifier *n = opaque; VirtQueue *vq = container_of(n, VirtQueue, host_notifier); - if (!vq->vring.desc || virtio_queue_empty(vq)) { - return false; - } + return vq->vring.desc && !virtio_queue_empty(vq); +} - return virtio_queue_notify_aio_vq(vq); +static void virtio_queue_host_notifier_aio_poll_ready(EventNotifier *n) +{ + VirtQueue *vq = container_of(n, VirtQueue, host_notifier); + + virtio_queue_notify_aio_vq(vq); } static void virtio_queue_host_notifier_aio_poll_end(EventNotifier *n) @@ -3558,12 +3561,13 @@ void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, vq->handle_aio_output = handle_output; aio_set_event_notifier(ctx, &vq->host_notifier, true, virtio_queue_host_notifier_aio_read, - virtio_queue_host_notifier_aio_poll); + virtio_queue_host_notifier_aio_poll, + virtio_queue_host_notifier_aio_poll_ready); aio_set_event_notifier_poll(ctx, &vq->host_notifier, virtio_queue_host_notifier_aio_poll_begin, virtio_queue_host_notifier_aio_poll_end); } else { - aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL, NULL); + aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL, NULL, NULL); /* Test and clear notifier before after disabling event, * in case poll callback didn't have time to run. */ virtio_queue_host_notifier_aio_read(&vq->host_notifier); diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c index 416583f130..645a29a5a0 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -1115,11 +1115,11 @@ void xen_device_set_event_channel_context(XenDevice *xendev, if (channel->ctx) aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); channel->ctx = ctx; aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true, - xen_device_event, NULL, xen_device_poll, channel); + xen_device_event, NULL, xen_device_poll, NULL, channel); } XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev, @@ -1193,7 +1193,7 @@ void xen_device_unbind_event_channel(XenDevice *xendev, QLIST_REMOVE(channel, list); aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); if (xenevtchn_unbind(channel->xeh, channel->local_port) < 0) { error_setg_errno(errp, errno, "xenevtchn_unbind failed"); diff --git a/include/block/aio.h b/include/block/aio.h index 47fbe9d81f..5634173b12 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -469,6 +469,7 @@ void aio_set_fd_handler(AioContext *ctx, IOHandler *io_read, IOHandler *io_write, AioPollFn *io_poll, + IOHandler *io_poll_ready, void *opaque); /* Set polling begin/end callbacks for a file descriptor that has already been @@ -490,7 +491,8 @@ void aio_set_event_notifier(AioContext *ctx, EventNotifier *notifier, bool is_external, EventNotifierHandler *io_read, - AioPollFn *io_poll); + AioPollFn *io_poll, + EventNotifierHandler *io_poll_ready); /* Set polling begin/end callbacks for an event notifier that has already been * registered with aio_set_event_notifier. Do nothing if the event notifier is diff --git a/io/channel-command.c b/io/channel-command.c index b2a9e27138..338da73ade 100644 --- a/io/channel-command.c +++ b/io/channel-command.c @@ -346,8 +346,10 @@ static void qio_channel_command_set_aio_fd_handler(QIOChannel *ioc, void *opaque) { QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); - aio_set_fd_handler(ctx, cioc->readfd, false, io_read, NULL, NULL, opaque); - aio_set_fd_handler(ctx, cioc->writefd, false, NULL, io_write, NULL, opaque); + aio_set_fd_handler(ctx, cioc->readfd, false, + io_read, NULL, NULL, NULL, opaque); + aio_set_fd_handler(ctx, cioc->writefd, false, + NULL, io_write, NULL, NULL, opaque); } diff --git a/io/channel-file.c b/io/channel-file.c index c4bf799a80..d7cf6d278f 100644 --- a/io/channel-file.c +++ b/io/channel-file.c @@ -191,7 +191,8 @@ static void qio_channel_file_set_aio_fd_handler(QIOChannel *ioc, void *opaque) { QIOChannelFile *fioc = QIO_CHANNEL_FILE(ioc); - aio_set_fd_handler(ctx, fioc->fd, false, io_read, io_write, NULL, opaque); + aio_set_fd_handler(ctx, fioc->fd, false, io_read, io_write, + NULL, NULL, opaque); } static GSource *qio_channel_file_create_watch(QIOChannel *ioc, diff --git a/io/channel-socket.c b/io/channel-socket.c index 606ec97cf7..459922c874 100644 --- a/io/channel-socket.c +++ b/io/channel-socket.c @@ -761,7 +761,8 @@ static void qio_channel_socket_set_aio_fd_handler(QIOChannel *ioc, void *opaque) { QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); - aio_set_fd_handler(ctx, sioc->fd, false, io_read, io_write, NULL, opaque); + aio_set_fd_handler(ctx, sioc->fd, false, + io_read, io_write, NULL, NULL, opaque); } static GSource *qio_channel_socket_create_watch(QIOChannel *ioc, diff --git a/migration/rdma.c b/migration/rdma.c index f5d3bbe7e9..c7c7a38487 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -3161,14 +3161,14 @@ static void qio_channel_rdma_set_aio_fd_handler(QIOChannel *ioc, QIOChannelRDMA *rioc = QIO_CHANNEL_RDMA(ioc); if (io_read) { aio_set_fd_handler(ctx, rioc->rdmain->recv_comp_channel->fd, - false, io_read, io_write, NULL, opaque); + false, io_read, io_write, NULL, NULL, opaque); aio_set_fd_handler(ctx, rioc->rdmain->send_comp_channel->fd, - false, io_read, io_write, NULL, opaque); + false, io_read, io_write, NULL, NULL, opaque); } else { aio_set_fd_handler(ctx, rioc->rdmaout->recv_comp_channel->fd, - false, io_read, io_write, NULL, opaque); + false, io_read, io_write, NULL, NULL, opaque); aio_set_fd_handler(ctx, rioc->rdmaout->send_comp_channel->fd, - false, io_read, io_write, NULL, opaque); + false, io_read, io_write, NULL, NULL, opaque); } } diff --git a/tests/unit/test-aio.c b/tests/unit/test-aio.c index 6feeb9a4a9..178048d2f2 100644 --- a/tests/unit/test-aio.c +++ b/tests/unit/test-aio.c @@ -130,7 +130,7 @@ static void *test_acquire_thread(void *opaque) static void set_event_notifier(AioContext *ctx, EventNotifier *notifier, EventNotifierHandler *handler) { - aio_set_event_notifier(ctx, notifier, false, handler, NULL); + aio_set_event_notifier(ctx, notifier, false, handler, NULL, NULL); } static void dummy_notifier_read(EventNotifier *n) @@ -390,7 +390,7 @@ static void test_aio_external_client(void) for (i = 1; i < 3; i++) { EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true }; event_notifier_init(&data.e, false); - aio_set_event_notifier(ctx, &data.e, true, event_ready_cb, NULL); + aio_set_event_notifier(ctx, &data.e, true, event_ready_cb, NULL, NULL); event_notifier_set(&data.e); for (j = 0; j < i; j++) { aio_disable_external(ctx); diff --git a/tests/unit/test-fdmon-epoll.c b/tests/unit/test-fdmon-epoll.c index 11fd8a2fa9..ef5a856d09 100644 --- a/tests/unit/test-fdmon-epoll.c +++ b/tests/unit/test-fdmon-epoll.c @@ -22,14 +22,14 @@ static void add_event_notifiers(EventNotifier *notifiers, size_t n) for (size_t i = 0; i < n; i++) { event_notifier_init(¬ifiers[i], false); aio_set_event_notifier(ctx, ¬ifiers[i], false, - dummy_fd_handler, NULL); + dummy_fd_handler, NULL, NULL); } } static void remove_event_notifiers(EventNotifier *notifiers, size_t n) { for (size_t i = 0; i < n; i++) { - aio_set_event_notifier(ctx, ¬ifiers[i], false, NULL, NULL); + aio_set_event_notifier(ctx, ¬ifiers[i], false, NULL, NULL, NULL); event_notifier_cleanup(¬ifiers[i]); } } diff --git a/util/aio-posix.c b/util/aio-posix.c index 2b86777e91..7b9f629218 100644 --- a/util/aio-posix.c +++ b/util/aio-posix.c @@ -23,6 +23,15 @@ #include "trace.h" #include "aio-posix.h" +/* + * G_IO_IN and G_IO_OUT are not appropriate revents values for polling, since + * the handler may not need to access the file descriptor. For example, the + * handler doesn't need to read from an EventNotifier if it polled a memory + * location and a read syscall would be slow. Define our own unique revents + * value to indicate that polling determined this AioHandler is ready. + */ +#define REVENTS_POLL_READY 0 + /* Stop userspace polling on a handler if it isn't active for some time */ #define POLL_IDLE_INTERVAL_NS (7 * NANOSECONDS_PER_SECOND) @@ -93,6 +102,7 @@ void aio_set_fd_handler(AioContext *ctx, IOHandler *io_read, IOHandler *io_write, AioPollFn *io_poll, + IOHandler *io_poll_ready, void *opaque) { AioHandler *node; @@ -101,6 +111,10 @@ void aio_set_fd_handler(AioContext *ctx, bool deleted = false; int poll_disable_change; + if (io_poll && !io_poll_ready) { + io_poll = NULL; /* polling only makes sense if there is a handler */ + } + qemu_lockcnt_lock(&ctx->list_lock); node = find_aio_handler(ctx, fd); @@ -127,6 +141,7 @@ void aio_set_fd_handler(AioContext *ctx, new_node->io_read = io_read; new_node->io_write = io_write; new_node->io_poll = io_poll; + new_node->io_poll_ready = io_poll_ready; new_node->opaque = opaque; new_node->is_external = is_external; @@ -182,10 +197,12 @@ void aio_set_event_notifier(AioContext *ctx, EventNotifier *notifier, bool is_external, EventNotifierHandler *io_read, - AioPollFn *io_poll) + AioPollFn *io_poll, + EventNotifierHandler *io_poll_ready) { aio_set_fd_handler(ctx, event_notifier_get_fd(notifier), is_external, - (IOHandler *)io_read, NULL, io_poll, notifier); + (IOHandler *)io_read, NULL, io_poll, + (IOHandler *)io_poll_ready, notifier); } void aio_set_event_notifier_poll(AioContext *ctx, @@ -198,7 +215,8 @@ void aio_set_event_notifier_poll(AioContext *ctx, (IOHandler *)io_poll_end); } -static bool poll_set_started(AioContext *ctx, bool started) +static bool poll_set_started(AioContext *ctx, AioHandlerList *ready_list, + bool started) { AioHandler *node; bool progress = false; @@ -228,8 +246,9 @@ static bool poll_set_started(AioContext *ctx, bool started) } /* Poll one last time in case ->io_poll_end() raced with the event */ - if (!started) { - progress = node->io_poll(node->opaque) || progress; + if (!started && node->io_poll(node->opaque)) { + aio_add_ready_handler(ready_list, node, REVENTS_POLL_READY); + progress = true; } } qemu_lockcnt_dec(&ctx->list_lock); @@ -240,8 +259,11 @@ static bool poll_set_started(AioContext *ctx, bool started) bool aio_prepare(AioContext *ctx) { + AioHandlerList ready_list = QLIST_HEAD_INITIALIZER(ready_list); + /* Poll mode cannot be used with glib's event loop, disable it. */ - poll_set_started(ctx, false); + poll_set_started(ctx, &ready_list, false); + /* TODO what to do with this list? */ return false; } @@ -321,6 +343,18 @@ static bool aio_dispatch_handler(AioContext *ctx, AioHandler *node) } QLIST_INSERT_HEAD(&ctx->poll_aio_handlers, node, node_poll); } + if (!QLIST_IS_INSERTED(node, node_deleted) && + revents == 0 && + aio_node_check(ctx, node->is_external) && + node->io_poll_ready) { + node->io_poll_ready(node->opaque); + + /* + * Return early since revents was zero. aio_notify() does not count as + * progress. + */ + return node->opaque != &ctx->notifier; + } if (!QLIST_IS_INSERTED(node, node_deleted) && (revents & (G_IO_IN | G_IO_HUP | G_IO_ERR)) && @@ -387,6 +421,7 @@ void aio_dispatch(AioContext *ctx) } static bool run_poll_handlers_once(AioContext *ctx, + AioHandlerList *ready_list, int64_t now, int64_t *timeout) { @@ -397,6 +432,8 @@ static bool run_poll_handlers_once(AioContext *ctx, QLIST_FOREACH_SAFE(node, &ctx->poll_aio_handlers, node_poll, tmp) { if (aio_node_check(ctx, node->is_external) && node->io_poll(node->opaque)) { + aio_add_ready_handler(ready_list, node, REVENTS_POLL_READY); + node->poll_idle_timeout = now + POLL_IDLE_INTERVAL_NS; /* @@ -420,7 +457,9 @@ static bool fdmon_supports_polling(AioContext *ctx) return ctx->fdmon_ops->need_wait != aio_poll_disabled; } -static bool remove_idle_poll_handlers(AioContext *ctx, int64_t now) +static bool remove_idle_poll_handlers(AioContext *ctx, + AioHandlerList *ready_list, + int64_t now) { AioHandler *node; AioHandler *tmp; @@ -451,7 +490,11 @@ static bool remove_idle_poll_handlers(AioContext *ctx, int64_t now) * Nevermind about re-adding the handler in the rare case where * this causes progress. */ - progress = node->io_poll(node->opaque) || progress; + if (node->io_poll(node->opaque)) { + aio_add_ready_handler(ready_list, node, + REVENTS_POLL_READY); + progress = true; + } } } } @@ -461,6 +504,7 @@ static bool remove_idle_poll_handlers(AioContext *ctx, int64_t now) /* run_poll_handlers: * @ctx: the AioContext + * @ready_list: the list to place ready handlers on * @max_ns: maximum time to poll for, in nanoseconds * * Polls for a given time. @@ -469,7 +513,8 @@ static bool remove_idle_poll_handlers(AioContext *ctx, int64_t now) * * Returns: true if progress was made, false otherwise */ -static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout) +static bool run_poll_handlers(AioContext *ctx, AioHandlerList *ready_list, + int64_t max_ns, int64_t *timeout) { bool progress; int64_t start_time, elapsed_time; @@ -490,13 +535,15 @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout) start_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); do { - progress = run_poll_handlers_once(ctx, start_time, timeout); + progress = run_poll_handlers_once(ctx, ready_list, + start_time, timeout); elapsed_time = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - start_time; max_ns = qemu_soonest_timeout(*timeout, max_ns); assert(!(max_ns && progress)); } while (elapsed_time < max_ns && !ctx->fdmon_ops->need_wait(ctx)); - if (remove_idle_poll_handlers(ctx, start_time + elapsed_time)) { + if (remove_idle_poll_handlers(ctx, ready_list, + start_time + elapsed_time)) { *timeout = 0; progress = true; } @@ -514,6 +561,7 @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout) /* try_poll_mode: * @ctx: the AioContext + * @ready_list: list to add handlers that need to be run * @timeout: timeout for blocking wait, computed by the caller and updated if * polling succeeds. * @@ -521,7 +569,8 @@ static bool run_poll_handlers(AioContext *ctx, int64_t max_ns, int64_t *timeout) * * Returns: true if progress was made, false otherwise */ -static bool try_poll_mode(AioContext *ctx, int64_t *timeout) +static bool try_poll_mode(AioContext *ctx, AioHandlerList *ready_list, + int64_t *timeout) { int64_t max_ns; @@ -531,14 +580,14 @@ static bool try_poll_mode(AioContext *ctx, int64_t *timeout) max_ns = qemu_soonest_timeout(*timeout, ctx->poll_ns); if (max_ns && !ctx->fdmon_ops->need_wait(ctx)) { - poll_set_started(ctx, true); + poll_set_started(ctx, ready_list, true); - if (run_poll_handlers(ctx, max_ns, timeout)) { + if (run_poll_handlers(ctx, ready_list, max_ns, timeout)) { return true; } } - if (poll_set_started(ctx, false)) { + if (poll_set_started(ctx, ready_list, false)) { *timeout = 0; return true; } @@ -549,7 +598,6 @@ static bool try_poll_mode(AioContext *ctx, int64_t *timeout) bool aio_poll(AioContext *ctx, bool blocking) { AioHandlerList ready_list = QLIST_HEAD_INITIALIZER(ready_list); - int ret = 0; bool progress; bool use_notify_me; int64_t timeout; @@ -574,7 +622,7 @@ bool aio_poll(AioContext *ctx, bool blocking) } timeout = blocking ? aio_compute_timeout(ctx) : 0; - progress = try_poll_mode(ctx, &timeout); + progress = try_poll_mode(ctx, &ready_list, &timeout); assert(!(timeout && progress)); /* @@ -604,7 +652,7 @@ bool aio_poll(AioContext *ctx, bool blocking) * system call---a single round of run_poll_handlers_once suffices. */ if (timeout || ctx->fdmon_ops->need_wait(ctx)) { - ret = ctx->fdmon_ops->wait(ctx, &ready_list, timeout); + ctx->fdmon_ops->wait(ctx, &ready_list, timeout); } if (use_notify_me) { @@ -657,10 +705,7 @@ bool aio_poll(AioContext *ctx, bool blocking) } progress |= aio_bh_poll(ctx); - - if (ret > 0) { - progress |= aio_dispatch_ready_handlers(ctx, &ready_list); - } + progress |= aio_dispatch_ready_handlers(ctx, &ready_list); aio_free_deleted_handlers(ctx); diff --git a/util/aio-posix.h b/util/aio-posix.h index c80c04506a..7f2c37a684 100644 --- a/util/aio-posix.h +++ b/util/aio-posix.h @@ -24,6 +24,7 @@ struct AioHandler { IOHandler *io_read; IOHandler *io_write; AioPollFn *io_poll; + IOHandler *io_poll_ready; IOHandler *io_poll_begin; IOHandler *io_poll_end; void *opaque; diff --git a/util/aio-win32.c b/util/aio-win32.c index d5b09a1193..7aac89df3a 100644 --- a/util/aio-win32.c +++ b/util/aio-win32.c @@ -68,6 +68,7 @@ void aio_set_fd_handler(AioContext *ctx, IOHandler *io_read, IOHandler *io_write, AioPollFn *io_poll, + IOHandler *io_poll_ready, void *opaque) { /* fd is a SOCKET in our case */ @@ -136,7 +137,8 @@ void aio_set_event_notifier(AioContext *ctx, EventNotifier *e, bool is_external, EventNotifierHandler *io_notify, - AioPollFn *io_poll) + AioPollFn *io_poll, + EventNotifierHandler *io_poll_ready) { AioHandler *node; diff --git a/util/async.c b/util/async.c index 6f6717a34b..08d25feef5 100644 --- a/util/async.c +++ b/util/async.c @@ -362,7 +362,7 @@ aio_ctx_finalize(GSource *source) g_free(bh); } - aio_set_event_notifier(ctx, &ctx->notifier, false, NULL, NULL); + aio_set_event_notifier(ctx, &ctx->notifier, false, NULL, NULL, NULL); event_notifier_cleanup(&ctx->notifier); qemu_rec_mutex_destroy(&ctx->lock); qemu_lockcnt_destroy(&ctx->list_lock); @@ -485,6 +485,11 @@ static bool aio_context_notifier_poll(void *opaque) return qatomic_read(&ctx->notified); } +static void aio_context_notifier_poll_ready(EventNotifier *e) +{ + /* Do nothing, we just wanted to kick the event loop */ +} + static void co_schedule_bh_cb(void *opaque) { AioContext *ctx = opaque; @@ -536,7 +541,8 @@ AioContext *aio_context_new(Error **errp) aio_set_event_notifier(ctx, &ctx->notifier, false, aio_context_notifier_cb, - aio_context_notifier_poll); + aio_context_notifier_poll, + aio_context_notifier_poll_ready); #ifdef CONFIG_LINUX_AIO ctx->linux_aio = NULL; #endif diff --git a/util/main-loop.c b/util/main-loop.c index 06b18b195c..4d5a5b9943 100644 --- a/util/main-loop.c +++ b/util/main-loop.c @@ -582,7 +582,7 @@ void qemu_set_fd_handler(int fd, { iohandler_init(); aio_set_fd_handler(iohandler_ctx, fd, false, - fd_read, fd_write, NULL, opaque); + fd_read, fd_write, NULL, NULL, opaque); } void event_notifier_set_handler(EventNotifier *e, @@ -590,5 +590,5 @@ void event_notifier_set_handler(EventNotifier *e, { iohandler_init(); aio_set_event_notifier(iohandler_ctx, e, false, - handler, NULL); + handler, NULL, NULL); } diff --git a/util/qemu-coroutine-io.c b/util/qemu-coroutine-io.c index 5b80bb416f..7f5839cb76 100644 --- a/util/qemu-coroutine-io.c +++ b/util/qemu-coroutine-io.c @@ -75,7 +75,8 @@ typedef struct { static void fd_coroutine_enter(void *opaque) { FDYieldUntilData *data = opaque; - aio_set_fd_handler(data->ctx, data->fd, false, NULL, NULL, NULL, NULL); + aio_set_fd_handler(data->ctx, data->fd, false, + NULL, NULL, NULL, NULL, NULL); qemu_coroutine_enter(data->co); } @@ -88,6 +89,6 @@ void coroutine_fn yield_until_fd_readable(int fd) data.co = qemu_coroutine_self(); data.fd = fd; aio_set_fd_handler( - data.ctx, fd, false, fd_coroutine_enter, NULL, NULL, &data); + data.ctx, fd, false, fd_coroutine_enter, NULL, NULL, NULL, &data); qemu_coroutine_yield(); } diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c index 783d847a6d..f68287e811 100644 --- a/util/vhost-user-server.c +++ b/util/vhost-user-server.c @@ -250,7 +250,7 @@ set_watch(VuDev *vu_dev, int fd, int vu_evt, vu_fd_watch->cb = cb; qemu_set_nonblock(fd); aio_set_fd_handler(server->ioc->ctx, fd, true, kick_handler, - NULL, NULL, vu_fd_watch); + NULL, NULL, NULL, vu_fd_watch); vu_fd_watch->vu_dev = vu_dev; vu_fd_watch->pvt = pvt; } @@ -270,7 +270,8 @@ static void remove_watch(VuDev *vu_dev, int fd) if (!vu_fd_watch) { return; } - aio_set_fd_handler(server->ioc->ctx, fd, true, NULL, NULL, NULL, NULL); + aio_set_fd_handler(server->ioc->ctx, fd, true, + NULL, NULL, NULL, NULL, NULL); QTAILQ_REMOVE(&server->vu_fd_watches, vu_fd_watch, next); g_free(vu_fd_watch); @@ -334,7 +335,7 @@ void vhost_user_server_stop(VuServer *server) QTAILQ_FOREACH(vu_fd_watch, &server->vu_fd_watches, next) { aio_set_fd_handler(server->ctx, vu_fd_watch->fd, true, - NULL, NULL, NULL, vu_fd_watch); + NULL, NULL, NULL, NULL, vu_fd_watch); } qio_channel_shutdown(server->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); @@ -377,7 +378,7 @@ void vhost_user_server_attach_aio_context(VuServer *server, AioContext *ctx) QTAILQ_FOREACH(vu_fd_watch, &server->vu_fd_watches, next) { aio_set_fd_handler(ctx, vu_fd_watch->fd, true, kick_handler, NULL, - NULL, vu_fd_watch); + NULL, NULL, vu_fd_watch); } aio_co_schedule(ctx, server->co_trip); @@ -391,7 +392,7 @@ void vhost_user_server_detach_aio_context(VuServer *server) QTAILQ_FOREACH(vu_fd_watch, &server->vu_fd_watches, next) { aio_set_fd_handler(server->ctx, vu_fd_watch->fd, true, - NULL, NULL, NULL, vu_fd_watch); + NULL, NULL, NULL, NULL, vu_fd_watch); } qio_channel_detach_aio_context(server->ioc); From d93d16c0450b3d0fe8e25568663531eb250d6aae Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 7 Dec 2021 13:23:32 +0000 Subject: [PATCH 468/730] virtio: get rid of VirtIOHandleAIOOutput The virtqueue host notifier API virtio_queue_aio_set_host_notifier_handler() polls the virtqueue for new buffers. AioContext previously required a bool progress return value indicating whether an event was handled or not. This is no longer necessary because the AioContext polling API has been split into a poll check function and an event handler function. The event handler is only run when we know there is work to do, so it doesn't return bool. The VirtIOHandleAIOOutput function signature is now the same as VirtIOHandleOutput. Get rid of the bool return value. Further simplifications will be made for virtio-blk and virtio-scsi in the next patch. Signed-off-by: Stefan Hajnoczi Reviewed-by: Stefano Garzarella Message-id: 20211207132336.36627-3-stefanha@redhat.com Signed-off-by: Stefan Hajnoczi --- hw/block/dataplane/virtio-blk.c | 4 ++-- hw/scsi/virtio-scsi-dataplane.c | 18 ++++++------------ hw/virtio/virtio.c | 12 ++++-------- include/hw/virtio/virtio.h | 3 +-- 4 files changed, 13 insertions(+), 24 deletions(-) diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index ee5a5352dc..a2fa407b98 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -154,7 +154,7 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s) g_free(s); } -static bool virtio_blk_data_plane_handle_output(VirtIODevice *vdev, +static void virtio_blk_data_plane_handle_output(VirtIODevice *vdev, VirtQueue *vq) { VirtIOBlock *s = (VirtIOBlock *)vdev; @@ -162,7 +162,7 @@ static bool virtio_blk_data_plane_handle_output(VirtIODevice *vdev, assert(s->dataplane); assert(s->dataplane_started); - return virtio_blk_handle_vq(s, vq); + virtio_blk_handle_vq(s, vq); } /* Context: QEMU global mutex held */ diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 18eb824c97..76137de67f 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -49,49 +49,43 @@ void virtio_scsi_dataplane_setup(VirtIOSCSI *s, Error **errp) } } -static bool virtio_scsi_data_plane_handle_cmd(VirtIODevice *vdev, +static void virtio_scsi_data_plane_handle_cmd(VirtIODevice *vdev, VirtQueue *vq) { - bool progress = false; VirtIOSCSI *s = VIRTIO_SCSI(vdev); virtio_scsi_acquire(s); if (!s->dataplane_fenced) { assert(s->ctx && s->dataplane_started); - progress = virtio_scsi_handle_cmd_vq(s, vq); + virtio_scsi_handle_cmd_vq(s, vq); } virtio_scsi_release(s); - return progress; } -static bool virtio_scsi_data_plane_handle_ctrl(VirtIODevice *vdev, +static void virtio_scsi_data_plane_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) { - bool progress = false; VirtIOSCSI *s = VIRTIO_SCSI(vdev); virtio_scsi_acquire(s); if (!s->dataplane_fenced) { assert(s->ctx && s->dataplane_started); - progress = virtio_scsi_handle_ctrl_vq(s, vq); + virtio_scsi_handle_ctrl_vq(s, vq); } virtio_scsi_release(s); - return progress; } -static bool virtio_scsi_data_plane_handle_event(VirtIODevice *vdev, +static void virtio_scsi_data_plane_handle_event(VirtIODevice *vdev, VirtQueue *vq) { - bool progress = false; VirtIOSCSI *s = VIRTIO_SCSI(vdev); virtio_scsi_acquire(s); if (!s->dataplane_fenced) { assert(s->ctx && s->dataplane_started); - progress = virtio_scsi_handle_event_vq(s, vq); + virtio_scsi_handle_event_vq(s, vq); } virtio_scsi_release(s); - return progress; } static int virtio_scsi_set_host_notifier(VirtIOSCSI *s, VirtQueue *vq, int n) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 5db7f69237..323f549aad 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -125,7 +125,7 @@ struct VirtQueue uint16_t vector; VirtIOHandleOutput handle_output; - VirtIOHandleAIOOutput handle_aio_output; + VirtIOHandleOutput handle_aio_output; VirtIODevice *vdev; EventNotifier guest_notifier; EventNotifier host_notifier; @@ -2303,22 +2303,18 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align) } } -static bool virtio_queue_notify_aio_vq(VirtQueue *vq) +static void virtio_queue_notify_aio_vq(VirtQueue *vq) { - bool ret = false; - if (vq->vring.desc && vq->handle_aio_output) { VirtIODevice *vdev = vq->vdev; trace_virtio_queue_notify(vdev, vq - vdev->vq, vq); - ret = vq->handle_aio_output(vdev, vq); + vq->handle_aio_output(vdev, vq); if (unlikely(vdev->start_on_kick)) { virtio_set_started(vdev, true); } } - - return ret; } static void virtio_queue_notify_vq(VirtQueue *vq) @@ -3555,7 +3551,7 @@ static void virtio_queue_host_notifier_aio_poll_end(EventNotifier *n) } void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, - VirtIOHandleAIOOutput handle_output) + VirtIOHandleOutput handle_output) { if (handle_output) { vq->handle_aio_output = handle_output; diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 8bab9cfb75..b90095628f 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -175,7 +175,6 @@ void virtio_error(VirtIODevice *vdev, const char *fmt, ...) GCC_FMT_ATTR(2, 3); void virtio_device_set_child_bus_name(VirtIODevice *vdev, char *bus_name); typedef void (*VirtIOHandleOutput)(VirtIODevice *, VirtQueue *); -typedef bool (*VirtIOHandleAIOOutput)(VirtIODevice *, VirtQueue *); VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, VirtIOHandleOutput handle_output); @@ -318,7 +317,7 @@ EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq); void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled); void virtio_queue_host_notifier_read(EventNotifier *n); void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, - VirtIOHandleAIOOutput handle_output); + VirtIOHandleOutput handle_output); VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector); VirtQueue *virtio_vector_next_queue(VirtQueue *vq); From 186b9691730ca4d3d59fa135d7d24467a3254c9a Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 7 Dec 2021 13:23:33 +0000 Subject: [PATCH 469/730] virtio-blk: drop unused virtio_blk_handle_vq() return value The return value of virtio_blk_handle_vq() is no longer used. Get rid of it. This is a step towards unifying the dataplane and non-dataplane virtqueue handler functions. Prepare virtio_blk_handle_output() to be used by both dataplane and non-dataplane by making the condition for starting ioeventfd more specific. This way it won't trigger when dataplane has already been started. Signed-off-by: Stefan Hajnoczi Reviewed-by: Stefano Garzarella Message-id: 20211207132336.36627-4-stefanha@redhat.com Signed-off-by: Stefan Hajnoczi --- hw/block/virtio-blk.c | 14 +++----------- include/hw/virtio/virtio-blk.h | 2 +- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index f139cd7cc9..82676cdd01 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -767,12 +767,11 @@ static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb) return 0; } -bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq) +void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq) { VirtIOBlockReq *req; MultiReqBuffer mrb = {}; bool suppress_notifications = virtio_queue_get_notification(vq); - bool progress = false; aio_context_acquire(blk_get_aio_context(s->blk)); blk_io_plug(s->blk); @@ -783,7 +782,6 @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq) } while ((req = virtio_blk_get_request(s, vq))) { - progress = true; if (virtio_blk_handle_request(req, &mrb)) { virtqueue_detach_element(req->vq, &req->elem, 0); virtio_blk_free_request(req); @@ -802,19 +800,13 @@ bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq) blk_io_unplug(s->blk); aio_context_release(blk_get_aio_context(s->blk)); - return progress; -} - -static void virtio_blk_handle_output_do(VirtIOBlock *s, VirtQueue *vq) -{ - virtio_blk_handle_vq(s, vq); } static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) { VirtIOBlock *s = (VirtIOBlock *)vdev; - if (s->dataplane) { + if (s->dataplane && !s->dataplane_started) { /* Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start * dataplane here instead of waiting for .set_status(). */ @@ -823,7 +815,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) return; } } - virtio_blk_handle_output_do(s, vq); + virtio_blk_handle_vq(s, vq); } void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh) diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h index 29655a406d..d311c57cca 100644 --- a/include/hw/virtio/virtio-blk.h +++ b/include/hw/virtio/virtio-blk.h @@ -90,7 +90,7 @@ typedef struct MultiReqBuffer { bool is_write; } MultiReqBuffer; -bool virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq); +void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq); void virtio_blk_process_queued_requests(VirtIOBlock *s, bool is_bh); #endif From f34e8d8b8d48d73f36a67b6d5e492ef9784b5012 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 7 Dec 2021 13:23:34 +0000 Subject: [PATCH 470/730] virtio-scsi: prepare virtio_scsi_handle_cmd for dataplane Prepare virtio_scsi_handle_cmd() to be used by both dataplane and non-dataplane by making the condition for starting ioeventfd more specific. This way it won't trigger when dataplane has already been started. Signed-off-by: Stefan Hajnoczi Reviewed-by: Stefano Garzarella Message-id: 20211207132336.36627-5-stefanha@redhat.com Signed-off-by: Stefan Hajnoczi --- hw/scsi/virtio-scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 51fd09522a..34a968ecfb 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -720,7 +720,7 @@ static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq) /* use non-QOM casts in the data path */ VirtIOSCSI *s = (VirtIOSCSI *)vdev; - if (s->ctx) { + if (s->ctx && !s->dataplane_started) { virtio_device_start_ioeventfd(vdev); if (!s->dataplane_fenced) { return; From d6fbfe2b83ca466e7618f1b6fef1544544ff2e43 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 7 Dec 2021 13:23:35 +0000 Subject: [PATCH 471/730] virtio: use ->handle_output() instead of ->handle_aio_output() The difference between ->handle_output() and ->handle_aio_output() was that ->handle_aio_output() returned a bool return value indicating progress. This was needed by the old polling API but now that the bool return value is gone, the two functions can be unified. Signed-off-by: Stefan Hajnoczi Reviewed-by: Stefano Garzarella Message-id: 20211207132336.36627-6-stefanha@redhat.com Signed-off-by: Stefan Hajnoczi --- hw/virtio/virtio.c | 33 +++------------------------------ 1 file changed, 3 insertions(+), 30 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 323f549aad..e938e6513b 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -125,7 +125,6 @@ struct VirtQueue uint16_t vector; VirtIOHandleOutput handle_output; - VirtIOHandleOutput handle_aio_output; VirtIODevice *vdev; EventNotifier guest_notifier; EventNotifier host_notifier; @@ -2303,20 +2302,6 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align) } } -static void virtio_queue_notify_aio_vq(VirtQueue *vq) -{ - if (vq->vring.desc && vq->handle_aio_output) { - VirtIODevice *vdev = vq->vdev; - - trace_virtio_queue_notify(vdev, vq - vdev->vq, vq); - vq->handle_aio_output(vdev, vq); - - if (unlikely(vdev->start_on_kick)) { - virtio_set_started(vdev, true); - } - } -} - static void virtio_queue_notify_vq(VirtQueue *vq) { if (vq->vring.desc && vq->handle_output) { @@ -2395,7 +2380,6 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, vdev->vq[i].vring.num_default = queue_size; vdev->vq[i].vring.align = VIRTIO_PCI_VRING_ALIGN; vdev->vq[i].handle_output = handle_output; - vdev->vq[i].handle_aio_output = NULL; vdev->vq[i].used_elems = g_malloc0(sizeof(VirtQueueElement) * queue_size); @@ -2407,7 +2391,6 @@ void virtio_delete_queue(VirtQueue *vq) vq->vring.num = 0; vq->vring.num_default = 0; vq->handle_output = NULL; - vq->handle_aio_output = NULL; g_free(vq->used_elems); vq->used_elems = NULL; virtio_virtqueue_reset_region_cache(vq); @@ -3512,14 +3495,6 @@ EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq) return &vq->guest_notifier; } -static void virtio_queue_host_notifier_aio_read(EventNotifier *n) -{ - VirtQueue *vq = container_of(n, VirtQueue, host_notifier); - if (event_notifier_test_and_clear(n)) { - virtio_queue_notify_aio_vq(vq); - } -} - static void virtio_queue_host_notifier_aio_poll_begin(EventNotifier *n) { VirtQueue *vq = container_of(n, VirtQueue, host_notifier); @@ -3539,7 +3514,7 @@ static void virtio_queue_host_notifier_aio_poll_ready(EventNotifier *n) { VirtQueue *vq = container_of(n, VirtQueue, host_notifier); - virtio_queue_notify_aio_vq(vq); + virtio_queue_notify_vq(vq); } static void virtio_queue_host_notifier_aio_poll_end(EventNotifier *n) @@ -3554,9 +3529,8 @@ void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, VirtIOHandleOutput handle_output) { if (handle_output) { - vq->handle_aio_output = handle_output; aio_set_event_notifier(ctx, &vq->host_notifier, true, - virtio_queue_host_notifier_aio_read, + virtio_queue_host_notifier_read, virtio_queue_host_notifier_aio_poll, virtio_queue_host_notifier_aio_poll_ready); aio_set_event_notifier_poll(ctx, &vq->host_notifier, @@ -3566,8 +3540,7 @@ void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL, NULL, NULL); /* Test and clear notifier before after disabling event, * in case poll callback didn't have time to run. */ - virtio_queue_host_notifier_aio_read(&vq->host_notifier); - vq->handle_aio_output = NULL; + virtio_queue_host_notifier_read(&vq->host_notifier); } } From db608fb78444c58896db69495729e4458eeaace1 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 7 Dec 2021 13:23:36 +0000 Subject: [PATCH 472/730] virtio: unify dataplane and non-dataplane ->handle_output() Now that virtio-blk and virtio-scsi are ready, get rid of the handle_aio_output() callback. It's no longer needed. Signed-off-by: Stefan Hajnoczi Reviewed-by: Stefano Garzarella Message-id: 20211207132336.36627-7-stefanha@redhat.com Signed-off-by: Stefan Hajnoczi --- hw/block/dataplane/virtio-blk.c | 16 ++-------- hw/scsi/virtio-scsi-dataplane.c | 54 ++++----------------------------- hw/virtio/virtio.c | 32 +++++++++---------- include/hw/virtio/virtio.h | 4 +-- 4 files changed, 26 insertions(+), 80 deletions(-) diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index a2fa407b98..49276e46f2 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -154,17 +154,6 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s) g_free(s); } -static void virtio_blk_data_plane_handle_output(VirtIODevice *vdev, - VirtQueue *vq) -{ - VirtIOBlock *s = (VirtIOBlock *)vdev; - - assert(s->dataplane); - assert(s->dataplane_started); - - virtio_blk_handle_vq(s, vq); -} - /* Context: QEMU global mutex held */ int virtio_blk_data_plane_start(VirtIODevice *vdev) { @@ -258,8 +247,7 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) for (i = 0; i < nvqs; i++) { VirtQueue *vq = virtio_get_queue(s->vdev, i); - virtio_queue_aio_set_host_notifier_handler(vq, s->ctx, - virtio_blk_data_plane_handle_output); + virtio_queue_aio_attach_host_notifier(vq, s->ctx); } aio_context_release(s->ctx); return 0; @@ -302,7 +290,7 @@ static void virtio_blk_data_plane_stop_bh(void *opaque) for (i = 0; i < s->conf->num_queues; i++) { VirtQueue *vq = virtio_get_queue(s->vdev, i); - virtio_queue_aio_set_host_notifier_handler(vq, s->ctx, NULL); + virtio_queue_aio_detach_host_notifier(vq, s->ctx); } } diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 76137de67f..29575cbaf6 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -49,45 +49,6 @@ void virtio_scsi_dataplane_setup(VirtIOSCSI *s, Error **errp) } } -static void virtio_scsi_data_plane_handle_cmd(VirtIODevice *vdev, - VirtQueue *vq) -{ - VirtIOSCSI *s = VIRTIO_SCSI(vdev); - - virtio_scsi_acquire(s); - if (!s->dataplane_fenced) { - assert(s->ctx && s->dataplane_started); - virtio_scsi_handle_cmd_vq(s, vq); - } - virtio_scsi_release(s); -} - -static void virtio_scsi_data_plane_handle_ctrl(VirtIODevice *vdev, - VirtQueue *vq) -{ - VirtIOSCSI *s = VIRTIO_SCSI(vdev); - - virtio_scsi_acquire(s); - if (!s->dataplane_fenced) { - assert(s->ctx && s->dataplane_started); - virtio_scsi_handle_ctrl_vq(s, vq); - } - virtio_scsi_release(s); -} - -static void virtio_scsi_data_plane_handle_event(VirtIODevice *vdev, - VirtQueue *vq) -{ - VirtIOSCSI *s = VIRTIO_SCSI(vdev); - - virtio_scsi_acquire(s); - if (!s->dataplane_fenced) { - assert(s->ctx && s->dataplane_started); - virtio_scsi_handle_event_vq(s, vq); - } - virtio_scsi_release(s); -} - static int virtio_scsi_set_host_notifier(VirtIOSCSI *s, VirtQueue *vq, int n) { BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s))); @@ -112,10 +73,10 @@ static void virtio_scsi_dataplane_stop_bh(void *opaque) VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s); int i; - virtio_queue_aio_set_host_notifier_handler(vs->ctrl_vq, s->ctx, NULL); - virtio_queue_aio_set_host_notifier_handler(vs->event_vq, s->ctx, NULL); + virtio_queue_aio_detach_host_notifier(vs->ctrl_vq, s->ctx); + virtio_queue_aio_detach_host_notifier(vs->event_vq, s->ctx); for (i = 0; i < vs->conf.num_queues; i++) { - virtio_queue_aio_set_host_notifier_handler(vs->cmd_vqs[i], s->ctx, NULL); + virtio_queue_aio_detach_host_notifier(vs->cmd_vqs[i], s->ctx); } } @@ -176,14 +137,11 @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev) memory_region_transaction_commit(); aio_context_acquire(s->ctx); - virtio_queue_aio_set_host_notifier_handler(vs->ctrl_vq, s->ctx, - virtio_scsi_data_plane_handle_ctrl); - virtio_queue_aio_set_host_notifier_handler(vs->event_vq, s->ctx, - virtio_scsi_data_plane_handle_event); + virtio_queue_aio_attach_host_notifier(vs->ctrl_vq, s->ctx); + virtio_queue_aio_attach_host_notifier(vs->event_vq, s->ctx); for (i = 0; i < vs->conf.num_queues; i++) { - virtio_queue_aio_set_host_notifier_handler(vs->cmd_vqs[i], s->ctx, - virtio_scsi_data_plane_handle_cmd); + virtio_queue_aio_attach_host_notifier(vs->cmd_vqs[i], s->ctx); } s->dataplane_starting = false; diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index e938e6513b..aae72fb8b7 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3525,23 +3525,23 @@ static void virtio_queue_host_notifier_aio_poll_end(EventNotifier *n) virtio_queue_set_notification(vq, 1); } -void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, - VirtIOHandleOutput handle_output) +void virtio_queue_aio_attach_host_notifier(VirtQueue *vq, AioContext *ctx) { - if (handle_output) { - aio_set_event_notifier(ctx, &vq->host_notifier, true, - virtio_queue_host_notifier_read, - virtio_queue_host_notifier_aio_poll, - virtio_queue_host_notifier_aio_poll_ready); - aio_set_event_notifier_poll(ctx, &vq->host_notifier, - virtio_queue_host_notifier_aio_poll_begin, - virtio_queue_host_notifier_aio_poll_end); - } else { - aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL, NULL, NULL); - /* Test and clear notifier before after disabling event, - * in case poll callback didn't have time to run. */ - virtio_queue_host_notifier_read(&vq->host_notifier); - } + aio_set_event_notifier(ctx, &vq->host_notifier, true, + virtio_queue_host_notifier_read, + virtio_queue_host_notifier_aio_poll, + virtio_queue_host_notifier_aio_poll_ready); + aio_set_event_notifier_poll(ctx, &vq->host_notifier, + virtio_queue_host_notifier_aio_poll_begin, + virtio_queue_host_notifier_aio_poll_end); +} + +void virtio_queue_aio_detach_host_notifier(VirtQueue *vq, AioContext *ctx) +{ + aio_set_event_notifier(ctx, &vq->host_notifier, true, NULL, NULL, NULL); + /* Test and clear notifier before after disabling event, + * in case poll callback didn't have time to run. */ + virtio_queue_host_notifier_read(&vq->host_notifier); } void virtio_queue_host_notifier_read(EventNotifier *n) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index b90095628f..f095637058 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -316,8 +316,8 @@ bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev); EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq); void virtio_queue_set_host_notifier_enabled(VirtQueue *vq, bool enabled); void virtio_queue_host_notifier_read(EventNotifier *n); -void virtio_queue_aio_set_host_notifier_handler(VirtQueue *vq, AioContext *ctx, - VirtIOHandleOutput handle_output); +void virtio_queue_aio_attach_host_notifier(VirtQueue *vq, AioContext *ctx); +void virtio_queue_aio_detach_host_notifier(VirtQueue *vq, AioContext *ctx); VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector); VirtQueue *virtio_vector_next_queue(VirtQueue *vq); From 5280117b1e66555a526e04c624d9e1e8e7fec1ae Mon Sep 17 00:00:00 2001 From: Dario Binacchi Date: Wed, 12 Jan 2022 10:01:25 +0100 Subject: [PATCH 473/730] hw/usb/dev-wacom: add missing HID descriptor Linux need to fill up the HID descriptor in order to let the driver be emulated. The descriptor was downloaded from [1]. The patch was tested with evtest tool on top of qemu 5.2.0 with linux kernel 4.19.208. [1] https://github.com/linuxwacom/wacom-hid-descriptors/tree/master/Wacom%20PenPartner Signed-off-by: Michael Trimarchi Co-developed-by: Michael Trimarchi Signed-off-by: Dario Binacchi Message-Id: <20220112090125.381364-1-dario.binacchi@amarulasolutions.com> Signed-off-by: Gerd Hoffmann --- hw/usb/dev-wacom.c | 72 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c index ed687bc9f1..8323650c6a 100644 --- a/hw/usb/dev-wacom.c +++ b/hw/usb/dev-wacom.c @@ -69,6 +69,65 @@ static const USBDescStrings desc_strings = { [STR_SERIALNUMBER] = "1", }; +static const uint8_t qemu_wacom_hid_report_descriptor[] = { + 0x05, 0x01, /* Usage Page (Desktop) */ + 0x09, 0x02, /* Usage (Mouse) */ + 0xa1, 0x01, /* Collection (Application) */ + 0x85, 0x01, /* Report ID (1) */ + 0x09, 0x01, /* Usage (Pointer) */ + 0xa1, 0x00, /* Collection (Physical) */ + 0x05, 0x09, /* Usage Page (Button) */ + 0x19, 0x01, /* Usage Minimum (01h) */ + 0x29, 0x03, /* Usage Maximum (03h) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x95, 0x03, /* Report Count (3) */ + 0x75, 0x01, /* Report Size (1) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + 0x95, 0x01, /* Report Count (1) */ + 0x75, 0x05, /* Report Size (5) */ + 0x81, 0x01, /* Input (Constant) */ + 0x05, 0x01, /* Usage Page (Desktop) */ + 0x09, 0x30, /* Usage (X) */ + 0x09, 0x31, /* Usage (Y) */ + 0x09, 0x38, /* Usage (Wheel) */ + 0x15, 0x81, /* Logical Minimum (-127) */ + 0x25, 0x7f, /* Logical Maximum (127) */ + 0x75, 0x08, /* Report Size (8) */ + 0x95, 0x03, /* Report Count (3) */ + 0x81, 0x06, /* Input (Data, Variable, Relative) */ + 0x95, 0x03, /* Report Count (3) */ + 0x81, 0x01, /* Input (Constant) */ + 0xc0, /* End Collection */ + 0xc0, /* End Collection */ + 0x05, 0x0d, /* Usage Page (Digitizer) */ + 0x09, 0x01, /* Usage (Digitizer) */ + 0xa1, 0x01, /* Collection (Application) */ + 0x85, 0x02, /* Report ID (2) */ + 0xa1, 0x00, /* Collection (Physical) */ + 0x06, 0x00, 0xff,/* Usage Page (ff00h), vendor-defined */ + 0x09, 0x01, /* Usage (01h) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x26, 0xff, 0x00,/* Logical Maximum (255) */ + 0x75, 0x08, /* Report Size (8) */ + 0x95, 0x07, /* Report Count (7) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + 0xc0, /* End Collection */ + 0x09, 0x01, /* Usage (01h) */ + 0x85, 0x63, /* Report ID (99) */ + 0x95, 0x07, /* Report Count (7) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + 0x09, 0x01, /* Usage (01h) */ + 0x85, 0x02, /* Report ID (2) */ + 0x95, 0x01, /* Report Count (1) */ + 0xb1, 0x02, /* Feature (Variable) */ + 0x09, 0x01, /* Usage (01h) */ + 0x85, 0x03, /* Report ID (3) */ + 0x95, 0x01, /* Report Count (1) */ + 0xb1, 0x02, /* Feature (Variable) */ + 0xc0 /* End Collection */ +}; + static const USBDescIface desc_iface_wacom = { .bInterfaceNumber = 0, .bNumEndpoints = 1, @@ -86,7 +145,7 @@ static const USBDescIface desc_iface_wacom = { 0x00, /* u8 country_code */ 0x01, /* u8 num_descriptors */ USB_DT_REPORT, /* u8 type: Report */ - 0x6e, 0, /* u16 len */ + sizeof(qemu_wacom_hid_report_descriptor), 0, /* u16 len */ }, }, }, @@ -266,6 +325,17 @@ static void usb_wacom_handle_control(USBDevice *dev, USBPacket *p, } switch (request) { + case InterfaceRequest | USB_REQ_GET_DESCRIPTOR: + switch (value >> 8) { + case 0x22: + memcpy(data, qemu_wacom_hid_report_descriptor, + sizeof(qemu_wacom_hid_report_descriptor)); + p->actual_length = sizeof(qemu_wacom_hid_report_descriptor); + break; + default: + return; + } + break; case WACOM_SET_REPORT: if (s->mouse_grabbed) { qemu_remove_mouse_event_handler(s->eh_entry); From 7cd2cfa2e6d61fac3652422f46aa77899bbeb757 Mon Sep 17 00:00:00 2001 From: zhenwei pi Date: Wed, 12 Jan 2022 09:58:35 +0800 Subject: [PATCH 474/730] usb: allow max 8192 bytes for desc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A device of USB video class usually uses larger desc structure, so use larger buffer to avoid failure. (dev-video.c is ready) This is an unlikely code path: 1, during guest startup, guest tries to probe device. 2, run 'lsusb' command in guest(or other similar commands). Reviewed-by: Daniel P. Berrangé Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: zhenwei pi Message-Id: <20220112015835.900619-1-pizhenwei@bytedance.com> Signed-off-by: Gerd Hoffmann --- hw/usb/desc.c | 15 ++++++++------- hw/usb/desc.h | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/hw/usb/desc.c b/hw/usb/desc.c index 8b6eaea407..7f6cc2f99b 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -632,7 +632,8 @@ int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p, bool msos = (dev->flags & (1 << USB_DEV_FLAG_MSOS_DESC_IN_USE)); const USBDesc *desc = usb_device_get_usb_desc(dev); const USBDescDevice *other_dev; - uint8_t buf[256]; + size_t buflen = USB_DESC_MAX_LEN; + g_autofree uint8_t *buf = g_malloc(buflen); uint8_t type = value >> 8; uint8_t index = value & 0xff; int flags, ret = -1; @@ -650,36 +651,36 @@ int usb_desc_get_descriptor(USBDevice *dev, USBPacket *p, switch(type) { case USB_DT_DEVICE: - ret = usb_desc_device(&desc->id, dev->device, msos, buf, sizeof(buf)); + ret = usb_desc_device(&desc->id, dev->device, msos, buf, buflen); trace_usb_desc_device(dev->addr, len, ret); break; case USB_DT_CONFIG: if (index < dev->device->bNumConfigurations) { ret = usb_desc_config(dev->device->confs + index, flags, - buf, sizeof(buf)); + buf, buflen); } trace_usb_desc_config(dev->addr, index, len, ret); break; case USB_DT_STRING: - ret = usb_desc_string(dev, index, buf, sizeof(buf)); + ret = usb_desc_string(dev, index, buf, buflen); trace_usb_desc_string(dev->addr, index, len, ret); break; case USB_DT_DEVICE_QUALIFIER: if (other_dev != NULL) { - ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf)); + ret = usb_desc_device_qualifier(other_dev, buf, buflen); } trace_usb_desc_device_qualifier(dev->addr, len, ret); break; case USB_DT_OTHER_SPEED_CONFIG: if (other_dev != NULL && index < other_dev->bNumConfigurations) { ret = usb_desc_config(other_dev->confs + index, flags, - buf, sizeof(buf)); + buf, buflen); buf[0x01] = USB_DT_OTHER_SPEED_CONFIG; } trace_usb_desc_other_speed_config(dev->addr, index, len, ret); break; case USB_DT_BOS: - ret = usb_desc_bos(desc, buf, sizeof(buf)); + ret = usb_desc_bos(desc, buf, buflen); trace_usb_desc_bos(dev->addr, len, ret); break; diff --git a/hw/usb/desc.h b/hw/usb/desc.h index 3ac604ecfa..35babdeff6 100644 --- a/hw/usb/desc.h +++ b/hw/usb/desc.h @@ -199,6 +199,7 @@ struct USBDesc { const USBDescMSOS *msos; }; +#define USB_DESC_MAX_LEN 8192 #define USB_DESC_FLAG_SUPER (1 << 1) /* little helpers */ From 1dbbe6f172810026c51dc84ed927a3cc23017949 Mon Sep 17 00:00:00 2001 From: Rao Lei Date: Wed, 5 Jan 2022 10:08:08 +0800 Subject: [PATCH 475/730] ui/vnc.c: Fixed a deadlock bug. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GDB statck is as follows: (gdb) bt 0 __lll_lock_wait (futex=futex@entry=0x56211df20360, private=0) at lowlevellock.c:52 1 0x00007f263caf20a3 in __GI___pthread_mutex_lock (mutex=0x56211df20360) at ../nptl/pthread_mutex_lock.c:80 2 0x000056211a757364 in qemu_mutex_lock_impl (mutex=0x56211df20360, file=0x56211a804857 "../ui/vnc-jobs.h", line=60) at ../util/qemu-thread-posix.c:80 3 0x000056211a0ef8c7 in vnc_lock_output (vs=0x56211df14200) at ../ui/vnc-jobs.h:60 4 0x000056211a0efcb7 in vnc_clipboard_send (vs=0x56211df14200, count=1, dwords=0x7ffdf1701338) at ../ui/vnc-clipboard.c:138 5 0x000056211a0f0129 in vnc_clipboard_notify (notifier=0x56211df244c8, data=0x56211dd1bbf0) at ../ui/vnc-clipboard.c:209 6 0x000056211a75dde8 in notifier_list_notify (list=0x56211afa17d0 , data=0x56211dd1bbf0) at ../util/notify.c:39 7 0x000056211a0bf0e6 in qemu_clipboard_update (info=0x56211dd1bbf0) at ../ui/clipboard.c:50 8 0x000056211a0bf05d in qemu_clipboard_peer_release (peer=0x56211df244c0, selection=QEMU_CLIPBOARD_SELECTION_CLIPBOARD) at ../ui/clipboard.c:41 9 0x000056211a0bef9b in qemu_clipboard_peer_unregister (peer=0x56211df244c0) at ../ui/clipboard.c:19 10 0x000056211a0d45f3 in vnc_disconnect_finish (vs=0x56211df14200) at ../ui/vnc.c:1358 11 0x000056211a0d4c9d in vnc_client_read (vs=0x56211df14200) at ../ui/vnc.c:1611 12 0x000056211a0d4df8 in vnc_client_io (ioc=0x56211ce70690, condition=G_IO_IN, opaque=0x56211df14200) at ../ui/vnc.c:1649 13 0x000056211a5b976c in qio_channel_fd_source_dispatch (source=0x56211ce50a00, callback=0x56211a0d4d71 , user_data=0x56211df14200) at ../io/channel-watch.c:84 14 0x00007f263ccede8e in g_main_context_dispatch () at /lib/x86_64-linux-gnu/libglib-2.0.so.0 15 0x000056211a77d4a1 in glib_pollfds_poll () at ../util/main-loop.c:232 16 0x000056211a77d51f in os_host_main_loop_wait (timeout=958545) at ../util/main-loop.c:255 17 0x000056211a77d630 in main_loop_wait (nonblocking=0) at ../util/main-loop.c:531 18 0x000056211a45bc8e in qemu_main_loop () at ../softmmu/runstate.c:726 19 0x000056211a0b45fa in main (argc=69, argv=0x7ffdf1701778, envp=0x7ffdf17019a8) at ../softmmu/main.c:50 From the call trace, we can see it is a deadlock bug. vnc_disconnect_finish will acquire the output_mutex. But, the output_mutex will be acquired again in vnc_clipboard_send. Repeated locking will cause deadlock. So, I move qemu_clipboard_peer_unregister() behind vnc_unlock_output(); Fixes: 0bf41cab93e ("ui/vnc: clipboard support") Signed-off-by: Lei Rao Reviewed-by: Marc-André Lureau Message-Id: <20220105020808.597325-1-lei.rao@intel.com> Signed-off-by: Gerd Hoffmann --- ui/vnc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/vnc.c b/ui/vnc.c index 1ed1c7efc6..3ccd33dedc 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -1354,12 +1354,12 @@ void vnc_disconnect_finish(VncState *vs) /* last client gone */ vnc_update_server_surface(vs->vd); } + vnc_unlock_output(vs); + if (vs->cbpeer.notifier.notify) { qemu_clipboard_peer_unregister(&vs->cbpeer); } - vnc_unlock_output(vs); - qemu_mutex_destroy(&vs->output_mutex); if (vs->bh != NULL) { qemu_bh_delete(vs->bh); From ead789eb46a7df4eaab9e14e29e1d0d2a379988d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sun, 26 Dec 2021 16:40:15 +0100 Subject: [PATCH 476/730] jackaudio: use ifdefs to hide unavailable functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Windows the jack_set_thread_creator() function and on MacOS the pthread_setname_np() function with a thread pointer paramater is not available. Use #ifdefs to remove the jack_set_thread_creator() function call and the qjack_thread_creator() function in both cases. The qjack_thread_creator() function just sets the name of the created thread for debugging purposes and isn't really necessary. From the jack_set_thread_creator() documentation: (...) No normal application/client should consider calling this. (...) Resolves: https://gitlab.com/qemu-project/qemu/-/issues/785 Signed-off-by: Volker Rümelin Reviewed-by: Christian Schoenebeck Message-Id: <20211226154017.6067-1-vr_qemu@t-online.de> Signed-off-by: Gerd Hoffmann --- audio/jackaudio.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/audio/jackaudio.c b/audio/jackaudio.c index e7de6d5433..317009e936 100644 --- a/audio/jackaudio.c +++ b/audio/jackaudio.c @@ -622,6 +622,7 @@ static void qjack_enable_in(HWVoiceIn *hw, bool enable) ji->c.enabled = enable; } +#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID) static int qjack_thread_creator(jack_native_thread_t *thread, const pthread_attr_t *attr, void *(*function)(void *), void *arg) { @@ -635,6 +636,7 @@ static int qjack_thread_creator(jack_native_thread_t *thread, return ret; } +#endif static void *qjack_init(Audiodev *dev) { @@ -687,7 +689,9 @@ static void register_audio_jack(void) { qemu_mutex_init(&qjack_shutdown_lock); audio_driver_register(&jack_driver); +#if !defined(WIN32) && defined(CONFIG_PTHREAD_SETNAME_NP_W_TID) jack_set_thread_creator(qjack_thread_creator); +#endif jack_set_error_function(qjack_error); jack_set_info_function(qjack_info); } From 9d90ceb27461d7d0d172fd941b812d511794a6c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sun, 26 Dec 2021 16:40:16 +0100 Subject: [PATCH 477/730] dsoundaudio: fix crackling audio recordings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audio recordings with the DirectSound backend don't sound right. A look a the Microsoft online documentation tells us why. From the DirectSound Programming Guide, Capture Buffer Information: 'You can safely copy data from the buffer only up to the read cursor.' Change the code to read up to the read cursor instead of the capture cursor. Signed-off-by: Volker Rümelin Message-Id: <20211226154017.6067-2-vr_qemu@t-online.de> Signed-off-by: Gerd Hoffmann --- audio/dsoundaudio.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c index cfc79c129e..3dd2c4d4a6 100644 --- a/audio/dsoundaudio.c +++ b/audio/dsoundaudio.c @@ -536,13 +536,12 @@ static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size) DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer; HRESULT hr; - DWORD cpos, rpos, act_size; + DWORD rpos, act_size; size_t req_size; int err; void *ret; - hr = IDirectSoundCaptureBuffer_GetCurrentPosition( - dscb, &cpos, ds->first_time ? &rpos : NULL); + hr = IDirectSoundCaptureBuffer_GetCurrentPosition(dscb, NULL, &rpos); if (FAILED(hr)) { dsound_logerr(hr, "Could not get capture buffer position\n"); *size = 0; @@ -554,7 +553,7 @@ static void *dsound_get_buffer_in(HWVoiceIn *hw, size_t *size) ds->first_time = false; } - req_size = audio_ring_dist(cpos, hw->pos_emul, hw->size_emul); + req_size = audio_ring_dist(rpos, hw->pos_emul, hw->size_emul); req_size = MIN(*size, MIN(req_size, hw->size_emul - hw->pos_emul)); if (req_size == 0) { From ecd5f2882fdd10f798984eb52abd00ffc78c2ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sun, 26 Dec 2021 16:40:17 +0100 Subject: [PATCH 478/730] hw/audio/intel-hda: fix stream reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Quote from: High Definition Audio Specification 1.0a, section 3.3.35 Offset 80: {IOB}SDnCTL Stream Reset (SRST): Writing a 1 causes the corresponding stream to be reset. The Stream Descriptor registers (except the SRST bit itself) ... are reset. Change the code to reset the Stream Descriptor Control and Status registers except the SRST bit. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/757 Signed-off-by: Volker Rümelin Message-Id: <20211226154017.6067-3-vr_qemu@t-online.de> Signed-off-by: Gerd Hoffmann --- hw/audio/intel-hda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index 2b55d52150..5f8a878f20 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -581,7 +581,7 @@ static void intel_hda_set_st_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint3 if (st->ctl & 0x01) { /* reset */ dprint(d, 1, "st #%d: reset\n", reg->stream); - st->ctl = SD_STS_FIFO_READY << 24; + st->ctl = SD_STS_FIFO_READY << 24 | SD_CTL_STREAM_RESET; } if ((st->ctl & 0x02) != (old & 0x02)) { uint32_t stnr = (st->ctl >> 20) & 0x0f; From fc94d1159c8c8da6105cd2beb11c1f24746a2d07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 22 Dec 2021 18:40:32 +0400 Subject: [PATCH 479/730] ui/dbus: fix buffer-overflow detected by ASAN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On the last added dbus patch, I left a tiny BO: ==441487==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x611000025a70 at pc 0x7f0817bb764c bp 0x7ffde672ae60 sp 0x7ffde672ae58 WRITE of size 8 at 0x611000025a70 thread T0 #0 0x7f0817bb764b in dbus_vc_class_init ../ui/dbus.c:401 A cookie for ASAN! not you C :) Signed-off-by: Marc-André Lureau Fixes: 7f767ca35e5 ("ui/dbus: register D-Bus VC handler") Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211222144032.443424-1-marcandre.lureau@redhat.com> Signed-off-by: Gerd Hoffmann --- ui/dbus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/dbus.c b/ui/dbus.c index b2c1c9fb52..0074424c1f 100644 --- a/ui/dbus.c +++ b/ui/dbus.c @@ -405,6 +405,7 @@ dbus_vc_class_init(ObjectClass *oc, void *data) static const TypeInfo dbus_vc_type_info = { .name = TYPE_CHARDEV_VC, .parent = TYPE_CHARDEV_DBUS, + .class_size = sizeof(DBusVCClass), .class_init = dbus_vc_class_init, }; From 87800d940584cb22fbfa1a0da61f2365e6ede3a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 16 Dec 2021 12:32:33 +0400 Subject: [PATCH 480/730] ui: fix gtk clipboard clear assertion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When closing the QEMU Gtk display window, it can occasionaly warn: qemu-system-x86_64: Gtk: gtk_clipboard_set_with_data: assertion 'targets != NULL' failed #3 0x00007ffff4f02f22 in gtk_clipboard_set_with_data (clipboard=, targets=, n_targets=, get_func=, clear_func=, user_data=) at /usr/src/debug/gtk3-3.24.30-4.fc35.x86_64/gtk/gtkclipboard.c:672 #4 0x00007ffff552cd75 in gd_clipboard_update_info (gd=0x5555579a9e00, info=0x555557ba4b50) at ../ui/gtk-clipboard.c:98 #5 0x00007ffff552ce00 in gd_clipboard_notify (notifier=0x5555579aaba8, data=0x7fffffffd720) at ../ui/gtk-clipboard.c:128 #6 0x000055555603e0ff in notifier_list_notify (list=0x555556657470 , data=0x7fffffffd720) at ../util/notify.c:39 #7 0x000055555594e8e0 in qemu_clipboard_update (info=0x555557ba4b50) at ../ui/clipboard.c:54 #8 0x000055555594e840 in qemu_clipboard_peer_release (peer=0x55555684a5b0, selection=QEMU_CLIPBOARD_SELECTION_PRIMARY) at ../ui/clipboard.c:40 #9 0x000055555594e786 in qemu_clipboard_peer_unregister (peer=0x55555684a5b0) at ../ui/clipboard.c:19 #10 0x000055555595f044 in vdagent_disconnect (vd=0x55555684a400) at ../ui/vdagent.c:852 #11 0x000055555595f262 in vdagent_chr_fini (obj=0x55555684a400) at ../ui/vdagent.c:908 Signed-off-by: Marc-André Lureau Message-Id: <20211216083233.1166504-1-marcandre.lureau@redhat.com> Signed-off-by: Gerd Hoffmann --- ui/gtk-clipboard.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c index e0b8b283fe..d58fd761ab 100644 --- a/ui/gtk-clipboard.c +++ b/ui/gtk-clipboard.c @@ -83,7 +83,7 @@ static void gd_clipboard_update_info(GtkDisplayState *gd, if (info != qemu_clipboard_info(s)) { gd->cbpending[s] = 0; if (!self_update) { - GtkTargetList *list; + g_autoptr(GtkTargetList) list = NULL; GtkTargetEntry *targets; gint n_targets; @@ -94,15 +94,16 @@ static void gd_clipboard_update_info(GtkDisplayState *gd, targets = gtk_target_table_new_from_list(list, &n_targets); gtk_clipboard_clear(gd->gtkcb[s]); - gd->cbowner[s] = true; - gtk_clipboard_set_with_data(gd->gtkcb[s], - targets, n_targets, - gd_clipboard_get_data, - gd_clipboard_clear, - gd); + if (targets) { + gd->cbowner[s] = true; + gtk_clipboard_set_with_data(gd->gtkcb[s], + targets, n_targets, + gd_clipboard_get_data, + gd_clipboard_clear, + gd); - gtk_target_table_free(targets, n_targets); - gtk_target_list_unref(list); + gtk_target_table_free(targets, n_targets); + } } return; } From 1c6c0b9ec1c0d980d4f0ac2604c4f9fd9611034b Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 10 Dec 2021 09:06:59 +0100 Subject: [PATCH 481/730] uas: add missing return MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we run the error handling code even for successful requests. Fixes: 13b250b12ad3 ("uas: add stream number sanity checks.") Reported-by: Guenter Roeck Signed-off-by: Gerd Hoffmann Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20211210080659.2537084-1-kraxel@redhat.com> --- hw/usb/dev-uas.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index 599d6b52a0..c9f295e7e4 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -908,6 +908,7 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p) p->status = USB_RET_STALL; break; } + return; err_stream: error_report("%s: invalid stream %d", __func__, p->stream); From 3ac25236ea6dd52a44c679ebd0a8126662d0ab4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 6 Dec 2021 23:45:25 +0100 Subject: [PATCH 482/730] hw/display: Rename VGA_ISA_MM -> VGA_MMIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no ISA bus part in the MMIO VGA device, so rename: * hw/display/vga-isa-mm.c -> hw/display/vga-mmio.c * CONFIG_VGA_ISA_MM -> CONFIG_VGA_MMIO * ISAVGAMMState -> VGAMmioState * isa_vga_mm_init() -> vga_mmio_init() Reviewed-by: BALATON Zoltan Reviewed-by: Thomas Huth Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211206224528.563588-2-f4bug@amsat.org> Signed-off-by: Gerd Hoffmann --- configs/devices/mips-softmmu/common.mak | 2 +- hw/display/Kconfig | 2 +- hw/display/meson.build | 2 +- hw/display/{vga-isa-mm.c => vga-mmio.c} | 19 +++++++++---------- hw/mips/Kconfig | 2 +- hw/mips/jazz.c | 2 +- include/hw/display/vga.h | 5 ++--- 7 files changed, 16 insertions(+), 18 deletions(-) rename hw/display/{vga-isa-mm.c => vga-mmio.c} (90%) diff --git a/configs/devices/mips-softmmu/common.mak b/configs/devices/mips-softmmu/common.mak index 752b62b1e6..d2202c839e 100644 --- a/configs/devices/mips-softmmu/common.mak +++ b/configs/devices/mips-softmmu/common.mak @@ -7,7 +7,7 @@ CONFIG_ISA_BUS=y CONFIG_PCI=y CONFIG_PCI_DEVICES=y CONFIG_VGA_ISA=y -CONFIG_VGA_ISA_MM=y +CONFIG_VGA_MMIO=y CONFIG_VGA_CIRRUS=y CONFIG_VMWARE_VGA=y CONFIG_SERIAL=y diff --git a/hw/display/Kconfig b/hw/display/Kconfig index a2306b67d8..a1b159becd 100644 --- a/hw/display/Kconfig +++ b/hw/display/Kconfig @@ -49,7 +49,7 @@ config VGA_ISA depends on ISA_BUS select VGA -config VGA_ISA_MM +config VGA_MMIO bool select VGA diff --git a/hw/display/meson.build b/hw/display/meson.build index 861c43ff98..adc53dd8b6 100644 --- a/hw/display/meson.build +++ b/hw/display/meson.build @@ -18,7 +18,7 @@ softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xenfb.c')) softmmu_ss.add(when: 'CONFIG_VGA_PCI', if_true: files('vga-pci.c')) softmmu_ss.add(when: 'CONFIG_VGA_ISA', if_true: files('vga-isa.c')) -softmmu_ss.add(when: 'CONFIG_VGA_ISA_MM', if_true: files('vga-isa-mm.c')) +softmmu_ss.add(when: 'CONFIG_VGA_MMIO', if_true: files('vga-mmio.c')) softmmu_ss.add(when: 'CONFIG_VMWARE_VGA', if_true: files('vmware_vga.c')) softmmu_ss.add(when: 'CONFIG_BOCHS_DISPLAY', if_true: files('bochs-display.c')) diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-mmio.c similarity index 90% rename from hw/display/vga-isa-mm.c rename to hw/display/vga-mmio.c index 7321b7a06d..4ffe3afe32 100644 --- a/hw/display/vga-isa-mm.c +++ b/hw/display/vga-mmio.c @@ -1,5 +1,5 @@ /* - * QEMU ISA MM VGA Emulator. + * QEMU MMIO VGA Emulator. * * Copyright (c) 2003 Fabrice Bellard * @@ -32,15 +32,15 @@ #define VGA_RAM_SIZE (8 * MiB) -typedef struct ISAVGAMMState { +typedef struct VGAMmioState { VGACommonState vga; int it_shift; -} ISAVGAMMState; +} VGAMmioState; /* Memory mapped interface */ static uint64_t vga_mm_read(void *opaque, hwaddr addr, unsigned size) { - ISAVGAMMState *s = opaque; + VGAMmioState *s = opaque; return vga_ioport_read(&s->vga, addr >> s->it_shift) & MAKE_64BIT_MASK(0, size * 8); @@ -49,7 +49,7 @@ static uint64_t vga_mm_read(void *opaque, hwaddr addr, unsigned size) static void vga_mm_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - ISAVGAMMState *s = opaque; + VGAMmioState *s = opaque; vga_ioport_write(&s->vga, addr >> s->it_shift, value & MAKE_64BIT_MASK(0, size * 8)); @@ -65,7 +65,7 @@ static const MemoryRegionOps vga_mm_ctrl_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void vga_mm_init(ISAVGAMMState *s, hwaddr vram_base, +static void vga_mm_init(VGAMmioState *s, hwaddr vram_base, hwaddr ctrl_base, int it_shift, MemoryRegion *address_space) { @@ -91,11 +91,10 @@ static void vga_mm_init(ISAVGAMMState *s, hwaddr vram_base, memory_region_set_coalescing(vga_io_memory); } -int isa_vga_mm_init(hwaddr vram_base, - hwaddr ctrl_base, int it_shift, - MemoryRegion *address_space) +int vga_mmio_init(hwaddr vram_base, hwaddr ctrl_base, + int it_shift, MemoryRegion *address_space) { - ISAVGAMMState *s; + VGAMmioState *s; s = g_malloc0(sizeof(*s)); diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index b4c5549ce8..725525358d 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -16,7 +16,7 @@ config JAZZ select I8254 select I8257 select PCSPK - select VGA_ISA_MM + select VGA_MMIO select G364FB select DP8393X select ESP diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index f5a26e174d..8f345afd13 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -274,7 +274,7 @@ static void mips_jazz_init(MachineState *machine, } break; case JAZZ_PICA61: - isa_vga_mm_init(0x40000000, 0x60000000, 0, get_system_memory()); + vga_mmio_init(0x40000000, 0x60000000, 0, get_system_memory()); break; default: break; diff --git a/include/hw/display/vga.h b/include/hw/display/vga.h index 5f7825e0e3..c16a5c26da 100644 --- a/include/hw/display/vga.h +++ b/include/hw/display/vga.h @@ -24,8 +24,7 @@ enum vga_retrace_method { extern enum vga_retrace_method vga_retrace_method; -int isa_vga_mm_init(hwaddr vram_base, - hwaddr ctrl_base, int it_shift, - MemoryRegion *address_space); +int vga_mmio_init(hwaddr vram_base, hwaddr ctrl_base, + int it_shift, MemoryRegion *address_space); #endif From 6bd06f773163459706017d5fead84ae899e4ac16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 6 Dec 2021 23:45:26 +0100 Subject: [PATCH 483/730] hw/display/vga-mmio: Inline vga_mm_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inline vga_mm_init() in vga_mmio_init() to simplify the next patch review. Kind of. Reviewed-by: BALATON Zoltan Reviewed-by: Thomas Huth Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20211206224528.563588-3-f4bug@amsat.org> Signed-off-by: Gerd Hoffmann --- hw/display/vga-mmio.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/hw/display/vga-mmio.c b/hw/display/vga-mmio.c index 4ffe3afe32..5671fdb920 100644 --- a/hw/display/vga-mmio.c +++ b/hw/display/vga-mmio.c @@ -65,12 +65,18 @@ static const MemoryRegionOps vga_mm_ctrl_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void vga_mm_init(VGAMmioState *s, hwaddr vram_base, - hwaddr ctrl_base, int it_shift, - MemoryRegion *address_space) +int vga_mmio_init(hwaddr vram_base, hwaddr ctrl_base, + int it_shift, MemoryRegion *address_space) { + VGAMmioState *s; MemoryRegion *s_ioport_ctrl, *vga_io_memory; + s = g_malloc0(sizeof(*s)); + + s->vga.vram_size_mb = VGA_RAM_SIZE / MiB; + s->vga.global_vmstate = true; + vga_common_init(&s->vga, NULL); + s->it_shift = it_shift; s_ioport_ctrl = g_malloc(sizeof(*s_ioport_ctrl)); memory_region_init_io(s_ioport_ctrl, NULL, &vga_mm_ctrl_ops, s, @@ -89,19 +95,6 @@ static void vga_mm_init(VGAMmioState *s, hwaddr vram_base, memory_region_add_subregion(address_space, vram_base + 0x000a0000, vga_io_memory); memory_region_set_coalescing(vga_io_memory); -} - -int vga_mmio_init(hwaddr vram_base, hwaddr ctrl_base, - int it_shift, MemoryRegion *address_space) -{ - VGAMmioState *s; - - s = g_malloc0(sizeof(*s)); - - s->vga.vram_size_mb = VGA_RAM_SIZE / MiB; - s->vga.global_vmstate = true; - vga_common_init(&s->vga, NULL); - vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space); s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s); From 23f6e3b11be74abae77584a069ec710d719ac5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 6 Dec 2021 23:45:27 +0100 Subject: [PATCH 484/730] hw/display/vga-mmio: QOM'ify vga_mmio_init() as TYPE_VGA_MMIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce TYPE_VGA_MMIO, a sysbus device. While there is no change in the vga_mmio_init() interface, this is a migration compatibility break of the MIPS Acer Pica 61 Jazz machine (pica61). Suggested-by: Thomas Huth Reviewed-by: BALATON Zoltan Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Message-Id: <20211206224528.563588-4-f4bug@amsat.org> Signed-off-by: Gerd Hoffmann --- hw/display/vga-mmio.c | 132 +++++++++++++++++++++++++++------------ include/hw/display/vga.h | 2 + 2 files changed, 94 insertions(+), 40 deletions(-) diff --git a/hw/display/vga-mmio.c b/hw/display/vga-mmio.c index 5671fdb920..10bde32af5 100644 --- a/hw/display/vga-mmio.c +++ b/hw/display/vga-mmio.c @@ -23,21 +23,34 @@ */ #include "qemu/osdep.h" -#include "qemu/bitops.h" -#include "qemu/units.h" -#include "migration/vmstate.h" +#include "qapi/error.h" #include "hw/display/vga.h" +#include "hw/sysbus.h" +#include "hw/display/vga.h" +#include "hw/qdev-properties.h" #include "vga_int.h" -#include "ui/pixel_ops.h" -#define VGA_RAM_SIZE (8 * MiB) +/* + * QEMU interface: + * + sysbus MMIO region 0: VGA I/O registers + * + sysbus MMIO region 1: VGA MMIO registers + * + sysbus MMIO region 2: VGA memory + */ -typedef struct VGAMmioState { +OBJECT_DECLARE_SIMPLE_TYPE(VGAMmioState, VGA_MMIO) + +struct VGAMmioState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ VGACommonState vga; - int it_shift; -} VGAMmioState; + MemoryRegion iomem; + MemoryRegion lowmem; + + uint8_t it_shift; +}; -/* Memory mapped interface */ static uint64_t vga_mm_read(void *opaque, hwaddr addr, unsigned size) { VGAMmioState *s = opaque; @@ -65,42 +78,81 @@ static const MemoryRegionOps vga_mm_ctrl_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; +static void vga_mmio_reset(DeviceState *dev) +{ + VGAMmioState *s = VGA_MMIO(dev); + + vga_common_reset(&s->vga); +} + int vga_mmio_init(hwaddr vram_base, hwaddr ctrl_base, int it_shift, MemoryRegion *address_space) { - VGAMmioState *s; - MemoryRegion *s_ioport_ctrl, *vga_io_memory; + DeviceState *dev; + SysBusDevice *s; - s = g_malloc0(sizeof(*s)); + dev = qdev_new(TYPE_VGA_MMIO); + qdev_prop_set_uint8(dev, "it_shift", it_shift); + s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); - s->vga.vram_size_mb = VGA_RAM_SIZE / MiB; - s->vga.global_vmstate = true; - vga_common_init(&s->vga, NULL); - - s->it_shift = it_shift; - s_ioport_ctrl = g_malloc(sizeof(*s_ioport_ctrl)); - memory_region_init_io(s_ioport_ctrl, NULL, &vga_mm_ctrl_ops, s, - "vga-mm-ctrl", 0x100000); - memory_region_set_flush_coalesced(s_ioport_ctrl); - - vga_io_memory = g_malloc(sizeof(*vga_io_memory)); - /* XXX: endianness? */ - memory_region_init_io(vga_io_memory, NULL, &vga_mem_ops, &s->vga, - "vga-mem", 0x20000); - - vmstate_register(NULL, 0, &vmstate_vga_common, s); - - memory_region_add_subregion(address_space, ctrl_base, s_ioport_ctrl); - s->vga.bank_offset = 0; - memory_region_add_subregion(address_space, - vram_base + 0x000a0000, vga_io_memory); - memory_region_set_coalescing(vga_io_memory); - - s->vga.con = graphic_console_init(NULL, 0, s->vga.hw_ops, s); - - memory_region_add_subregion(address_space, - VBE_DISPI_LFB_PHYSICAL_ADDRESS, - &s->vga.vram); + sysbus_mmio_map(s, 0, ctrl_base); + sysbus_mmio_map(s, 1, vram_base + 0x000a0000); + sysbus_mmio_map(s, 2, VBE_DISPI_LFB_PHYSICAL_ADDRESS); return 0; } + +static void vga_mmio_realizefn(DeviceState *dev, Error **errp) +{ + VGAMmioState *s = VGA_MMIO(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + memory_region_init_io(&s->iomem, OBJECT(dev), &vga_mm_ctrl_ops, s, + "vga-mmio", 0x100000); + memory_region_set_flush_coalesced(&s->iomem); + sysbus_init_mmio(sbd, &s->iomem); + + /* XXX: endianness? */ + memory_region_init_io(&s->lowmem, OBJECT(dev), &vga_mem_ops, &s->vga, + "vga-lowmem", 0x20000); + memory_region_set_coalescing(&s->lowmem); + sysbus_init_mmio(sbd, &s->lowmem); + + s->vga.bank_offset = 0; + s->vga.global_vmstate = true; + vga_common_init(&s->vga, OBJECT(dev)); + sysbus_init_mmio(sbd, &s->vga.vram); + s->vga.con = graphic_console_init(dev, 0, s->vga.hw_ops, &s->vga); +} + +static Property vga_mmio_properties[] = { + DEFINE_PROP_UINT8("it_shift", VGAMmioState, it_shift, 0), + DEFINE_PROP_UINT32("vgamem_mb", VGAMmioState, vga.vram_size_mb, 8), + DEFINE_PROP_END_OF_LIST(), +}; + +static void vga_mmio_class_initfn(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = vga_mmio_realizefn; + dc->reset = vga_mmio_reset; + dc->vmsd = &vmstate_vga_common; + device_class_set_props(dc, vga_mmio_properties); + set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories); +} + +static const TypeInfo vga_mmio_info = { + .name = TYPE_VGA_MMIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(VGAMmioState), + .class_init = vga_mmio_class_initfn, +}; + +static void vga_mmio_register_types(void) +{ + type_register_static(&vga_mmio_info); +} + +type_init(vga_mmio_register_types) diff --git a/include/hw/display/vga.h b/include/hw/display/vga.h index c16a5c26da..98b2e560f9 100644 --- a/include/hw/display/vga.h +++ b/include/hw/display/vga.h @@ -24,6 +24,8 @@ enum vga_retrace_method { extern enum vga_retrace_method vga_retrace_method; +#define TYPE_VGA_MMIO "vga-mmio" + int vga_mmio_init(hwaddr vram_base, hwaddr ctrl_base, int it_shift, MemoryRegion *address_space); From 7336c94434b2f697a375126d0df8549777a58148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 6 Dec 2021 23:45:28 +0100 Subject: [PATCH 485/730] hw/mips/jazz: Inline vga_mmio_init() and remove it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vga_mmio_init() is used only one time and not very helpful, inline and remove it. Reviewed-by: BALATON Zoltan Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Message-Id: <20211206224528.563588-5-f4bug@amsat.org> Signed-off-by: Gerd Hoffmann --- hw/display/vga-mmio.c | 19 ------------------- hw/mips/jazz.c | 9 ++++++++- include/hw/display/vga.h | 5 ----- 3 files changed, 8 insertions(+), 25 deletions(-) diff --git a/hw/display/vga-mmio.c b/hw/display/vga-mmio.c index 10bde32af5..4969368081 100644 --- a/hw/display/vga-mmio.c +++ b/hw/display/vga-mmio.c @@ -24,7 +24,6 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "hw/display/vga.h" #include "hw/sysbus.h" #include "hw/display/vga.h" #include "hw/qdev-properties.h" @@ -85,24 +84,6 @@ static void vga_mmio_reset(DeviceState *dev) vga_common_reset(&s->vga); } -int vga_mmio_init(hwaddr vram_base, hwaddr ctrl_base, - int it_shift, MemoryRegion *address_space) -{ - DeviceState *dev; - SysBusDevice *s; - - dev = qdev_new(TYPE_VGA_MMIO); - qdev_prop_set_uint8(dev, "it_shift", it_shift); - s = SYS_BUS_DEVICE(dev); - sysbus_realize_and_unref(s, &error_fatal); - - sysbus_mmio_map(s, 0, ctrl_base); - sysbus_mmio_map(s, 1, vram_base + 0x000a0000); - sysbus_mmio_map(s, 2, VBE_DISPI_LFB_PHYSICAL_ADDRESS); - - return 0; -} - static void vga_mmio_realizefn(DeviceState *dev, Error **errp) { VGAMmioState *s = VGA_MMIO(dev); diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c index 8f345afd13..44f0d48bfd 100644 --- a/hw/mips/jazz.c +++ b/hw/mips/jazz.c @@ -43,6 +43,7 @@ #include "hw/rtc/mc146818rtc.h" #include "hw/timer/i8254.h" #include "hw/display/vga.h" +#include "hw/display/bochs-vbe.h" #include "hw/audio/pcspk.h" #include "hw/input/i8042.h" #include "hw/sysbus.h" @@ -274,7 +275,13 @@ static void mips_jazz_init(MachineState *machine, } break; case JAZZ_PICA61: - vga_mmio_init(0x40000000, 0x60000000, 0, get_system_memory()); + dev = qdev_new(TYPE_VGA_MMIO); + qdev_prop_set_uint8(dev, "it_shift", 0); + sysbus = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sysbus, &error_fatal); + sysbus_mmio_map(sysbus, 0, 0x60000000); + sysbus_mmio_map(sysbus, 1, 0x400a0000); + sysbus_mmio_map(sysbus, 2, VBE_DISPI_LFB_PHYSICAL_ADDRESS); break; default: break; diff --git a/include/hw/display/vga.h b/include/hw/display/vga.h index 98b2e560f9..a79aa2909b 100644 --- a/include/hw/display/vga.h +++ b/include/hw/display/vga.h @@ -9,8 +9,6 @@ #ifndef QEMU_HW_DISPLAY_VGA_H #define QEMU_HW_DISPLAY_VGA_H -#include "exec/hwaddr.h" - /* * modules can reference this symbol to avoid being loaded * into system emulators without vga support @@ -26,7 +24,4 @@ extern enum vga_retrace_method vga_retrace_method; #define TYPE_VGA_MMIO "vga-mmio" -int vga_mmio_init(hwaddr vram_base, hwaddr ctrl_base, - int it_shift, MemoryRegion *address_space); - #endif From de72c4b7cdf6ec18bfe9fe714aa96e48db6fd895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Mon, 29 Nov 2021 14:05:08 +0000 Subject: [PATCH 486/730] edid: set default resolution to 1280x800 (WXGA) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently QEMU defaults to a resolution of 1024x768 when exposing EDID info to the guest OS. The EDID default info is important as this will influence what resolution many guest OS will configure the screen with on boot. It can also potentially influence what resolution the firmware will configure the screen with, though until very recently EDK2 would not handle EDID info. One important thing to bear in mind is that the default graphics card driver provided by Windows will leave the display set to whatever resolution was enabled by the firmware on boot. Even if sufficient VRAM is available, the resolution can't be changed without installing new drivers. IOW, the default resolution choice is quite important for usability of Windows. Modern real world monitor hardware for desktop/laptop has supported resolutions higher than 1024x768 for a long time now, perhaps as long as 15+ years. There are quite a wide variety of native resolutions in use today, however, and in wide screen form factors the height may not be all that tall. None the less, it is considered that there is scope for making the QEMU default resolution slightly larger. In considering what possible new default could be suitable, choices considered were 1280x720 (720p), 1280x800 (WXGA) and 1280x1024 (SXGA). In many ways, vertical space is the most important, and so 720p was discarded due to loosing vertical space, despite being 25% wider. The SXGA resolution would be good, but when taking into account window titlebars/toolbars and window manager desktop UI, this might be a little too tall for some users to fit the guest on their physical montior. This patch thus suggests a modest change to 1280x800 (WXGA). This only consumes 1 MB per colour channel, allowing double buffered framebuffer in 8 MB of VRAM. Width wise this is 25% larger than QEMU's current default, but height wise this only adds 5%, so the difference isn't massive on the QEMU side. Overall there doesn't appear to be a compelling reason to stick with 1024x768 resolution. Signed-off-by: Daniel P. Berrangé Reviewed-by: Gerd Hoffmann Message-Id: <20211129140508.1745130-1-berrange@redhat.com> Signed-off-by: Gerd Hoffmann --- hw/display/edid-generate.c | 4 ++-- include/hw/virtio/virtio-gpu.h | 4 ++-- qemu-edid.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/display/edid-generate.c b/hw/display/edid-generate.c index f2b874d5e3..6f5ac6a38a 100644 --- a/hw/display/edid-generate.c +++ b/hw/display/edid-generate.c @@ -401,10 +401,10 @@ void qemu_edid_generate(uint8_t *edid, size_t size, info->name = "QEMU Monitor"; } if (!info->prefx) { - info->prefx = 1024; + info->prefx = 1280; } if (!info->prefy) { - info->prefy = 768; + info->prefy = 800; } if (info->prefx >= 4096 || info->prefy >= 4096) { large_screen = 1; diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index acfba7c76c..2179b75703 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -147,8 +147,8 @@ struct VirtIOGPUBaseClass { DEFINE_PROP_UINT32("max_outputs", _state, _conf.max_outputs, 1), \ DEFINE_PROP_BIT("edid", _state, _conf.flags, \ VIRTIO_GPU_FLAG_EDID_ENABLED, true), \ - DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1024), \ - DEFINE_PROP_UINT32("yres", _state, _conf.yres, 768) + DEFINE_PROP_UINT32("xres", _state, _conf.xres, 1280), \ + DEFINE_PROP_UINT32("yres", _state, _conf.yres, 800) typedef struct VGPUDMABuf { QemuDmaBuf buf; diff --git a/qemu-edid.c b/qemu-edid.c index c3a9fba10d..20c958d9c7 100644 --- a/qemu-edid.c +++ b/qemu-edid.c @@ -10,8 +10,8 @@ #include "hw/display/edid.h" static qemu_edid_info info = { - .prefx = 1024, - .prefy = 768, + .prefx = 1280, + .prefy = 800, }; static void usage(FILE *out) From f0602b709985b28bc8ce572d6c517d9c26669735 Mon Sep 17 00:00:00 2001 From: Satyeshwar Singh Date: Tue, 16 Nov 2021 14:11:03 -0800 Subject: [PATCH 487/730] edid: Added support for 4k@60 Hz monitor Previously, the large modes (>1080p) that were generated by Qemu in its EDID were all 50 Hz. If we provide them to a Guest OS and the user selects one of these modes, then the OS by default only gets 50 FPS. This is especially true for Windows OS. With this patch, we are now exposing a 3840x2160@60 Hz which will allow the guest OS to get 60 FPS. Cc: Gerd Hoffmann Signed-off-by: Satyeshwar Singh Message-Id: <20211116221103.27128-1-dongwon.kim@intel.com> Signed-off-by: Gerd Hoffmann --- hw/display/edid-generate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/display/edid-generate.c b/hw/display/edid-generate.c index 6f5ac6a38a..bccf32af69 100644 --- a/hw/display/edid-generate.c +++ b/hw/display/edid-generate.c @@ -24,6 +24,9 @@ static const struct edid_mode { { .xres = 2048, .yres = 1152 }, { .xres = 1920, .yres = 1080, .dta = 31 }, + /* dea/dta extension timings (all @ 60 Hz) */ + { .xres = 3840, .yres = 2160, .dta = 97 }, + /* additional standard timings 3 (all @ 60Hz) */ { .xres = 1920, .yres = 1200, .xtra3 = 10, .bit = 0 }, { .xres = 1600, .yres = 1200, .xtra3 = 9, .bit = 2 }, From 64ebbb7d62cfe3e435b1ce87f839398b75bbc35a Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Sat, 8 Jan 2022 16:39:43 +0100 Subject: [PATCH 488/730] ps2: Initial horizontal scroll support This change adds support for horizontal scroll to ps/2 mouse device code. The code is implemented to match the logic of linux kernel which is used as a reference. Signed-off-by: Dmitry Petrov Message-Id: <20220108153947.171861-2-dpetroff@gmail.com> Signed-off-by: Gerd Hoffmann --- hw/input/ps2.c | 57 +++++++++++++++++++++++++++++++++++++++++++------- qapi/ui.json | 2 +- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/hw/input/ps2.c b/hw/input/ps2.c index 9376a8f4ce..6236711e1b 100644 --- a/hw/input/ps2.c +++ b/hw/input/ps2.c @@ -123,6 +123,7 @@ typedef struct { int mouse_dx; /* current values, needed for 'poll' mode */ int mouse_dy; int mouse_dz; + int mouse_dw; uint8_t mouse_buttons; } PS2MouseState; @@ -715,7 +716,7 @@ static int ps2_mouse_send_packet(PS2MouseState *s) /* IMPS/2 and IMEX send 4 bytes, PS2 sends 3 bytes */ const int needed = s->mouse_type ? 4 : 3; unsigned int b; - int dx1, dy1, dz1; + int dx1, dy1, dz1, dw1; if (PS2_QUEUE_SIZE - s->common.queue.count < needed) { return 0; @@ -724,6 +725,7 @@ static int ps2_mouse_send_packet(PS2MouseState *s) dx1 = s->mouse_dx; dy1 = s->mouse_dy; dz1 = s->mouse_dz; + dw1 = s->mouse_dw; /* XXX: increase range to 8 bits ? */ if (dx1 > 127) dx1 = 127; @@ -740,6 +742,9 @@ static int ps2_mouse_send_packet(PS2MouseState *s) /* extra byte for IMPS/2 or IMEX */ switch(s->mouse_type) { default: + /* Just ignore the wheels if not supported */ + s->mouse_dz = 0; + s->mouse_dw = 0; break; case 3: if (dz1 > 127) @@ -747,13 +752,41 @@ static int ps2_mouse_send_packet(PS2MouseState *s) else if (dz1 < -127) dz1 = -127; ps2_queue_noirq(&s->common, dz1 & 0xff); + s->mouse_dz -= dz1; + s->mouse_dw = 0; break; case 4: - if (dz1 > 7) - dz1 = 7; - else if (dz1 < -7) - dz1 = -7; - b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); + /* + * This matches what the Linux kernel expects for exps/2 in + * drivers/input/mouse/psmouse-base.c. Note, if you happen to + * press/release the 4th or 5th buttons at the same moment as a + * horizontal wheel scroll, those button presses will get lost. I'm not + * sure what to do about that, since by this point we don't know + * whether those buttons actually changed state. + */ + if (dw1 != 0) { + if (dw1 > 31) { + dw1 = 31; + } else if (dw1 < -31) { + dw1 = -31; + } + + /* + * linux kernel expects first 6 bits to represent the value + * for horizontal scroll + */ + b = (dw1 & 0x3f) | 0x40; + s->mouse_dw -= dw1; + } else { + if (dz1 > 7) { + dz1 = 7; + } else if (dz1 < -7) { + dz1 = -7; + } + + b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); + s->mouse_dz -= dz1; + } ps2_queue_noirq(&s->common, b); break; } @@ -764,7 +797,6 @@ static int ps2_mouse_send_packet(PS2MouseState *s) /* update deltas */ s->mouse_dx -= dx1; s->mouse_dy -= dy1; - s->mouse_dz -= dz1; return 1; } @@ -806,6 +838,12 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src, } else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) { s->mouse_dz++; } + + if (btn->button == INPUT_BUTTON_WHEEL_RIGHT) { + s->mouse_dw--; + } else if (btn->button == INPUT_BUTTON_WHEEL_LEFT) { + s->mouse_dw++; + } } else { s->mouse_buttons &= ~bmap[btn->button]; } @@ -833,8 +871,10 @@ static void ps2_mouse_sync(DeviceState *dev) /* if not remote, send event. Multiple events are sent if too big deltas */ while (ps2_mouse_send_packet(s)) { - if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0) + if (s->mouse_dx == 0 && s->mouse_dy == 0 + && s->mouse_dz == 0 && s->mouse_dw == 0) { break; + } } } } @@ -1036,6 +1076,7 @@ static void ps2_mouse_reset(void *opaque) s->mouse_dx = 0; s->mouse_dy = 0; s->mouse_dz = 0; + s->mouse_dw = 0; s->mouse_buttons = 0; } diff --git a/qapi/ui.json b/qapi/ui.json index 2b4371da37..9354f4c467 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -905,7 +905,7 @@ ## { 'enum' : 'InputButton', 'data' : [ 'left', 'middle', 'right', 'wheel-up', 'wheel-down', 'side', - 'extra' ] } + 'extra', 'wheel-left', 'wheel-right' ] } ## # @InputAxis: From d70a5de441d6a4634fae39253f26ef3f39f8622a Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Sat, 8 Jan 2022 16:39:44 +0100 Subject: [PATCH 489/730] ui/cocoa: pass horizontal scroll information to the device code Signed-off-by: Dmitry Petrov Message-Id: <20220108153947.171861-3-dpetroff@gmail.com> Signed-off-by: Gerd Hoffmann --- ui/cocoa.m | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/ui/cocoa.m b/ui/cocoa.m index 69745c483b..ac18e14ce0 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -970,21 +970,27 @@ QemuCocoaView *cocoaView; */ /* - * When deltaY is zero, it means that this scrolling event was - * either horizontal, or so fine that it only appears in - * scrollingDeltaY. So we drop the event. + * We shouldn't have got a scroll event when deltaY and delta Y + * are zero, hence no harm in dropping the event */ - if ([event deltaY] != 0) { + if ([event deltaY] != 0 || [event deltaX] != 0) { /* Determine if this is a scroll up or scroll down event */ - buttons = ([event deltaY] > 0) ? + if ([event deltaY] != 0) { + buttons = ([event deltaY] > 0) ? INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHEEL_DOWN; + } else if ([event deltaX] != 0) { + buttons = ([event deltaX] > 0) ? + INPUT_BUTTON_WHEEL_LEFT : INPUT_BUTTON_WHEEL_RIGHT; + } + qemu_input_queue_btn(dcl.con, buttons, true); qemu_input_event_sync(); qemu_input_queue_btn(dcl.con, buttons, false); qemu_input_event_sync(); } + /* - * Since deltaY also reports scroll wheel events we prevent mouse + * Since deltaX/deltaY also report scroll wheel events we prevent mouse * movement code from executing. */ mouse_event = false; From 13cb360f6e60fca63b90ec0ff96f6135d937a1af Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Sat, 8 Jan 2022 16:39:45 +0100 Subject: [PATCH 490/730] ui/gtk: pass horizontal scroll information to the device code Signed-off-by: Dmitry Petrov Message-Id: <20220108153947.171861-4-dpetroff@gmail.com> Signed-off-by: Gerd Hoffmann --- ui/gtk.c | 54 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index 6a1f65d518..a8567b9ddc 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -968,33 +968,63 @@ static gboolean gd_scroll_event(GtkWidget *widget, GdkEventScroll *scroll, void *opaque) { VirtualConsole *vc = opaque; - InputButton btn; + InputButton btn_vertical; + InputButton btn_horizontal; + bool has_vertical = false; + bool has_horizontal = false; if (scroll->direction == GDK_SCROLL_UP) { - btn = INPUT_BUTTON_WHEEL_UP; + btn_vertical = INPUT_BUTTON_WHEEL_UP; + has_vertical = true; } else if (scroll->direction == GDK_SCROLL_DOWN) { - btn = INPUT_BUTTON_WHEEL_DOWN; + btn_vertical = INPUT_BUTTON_WHEEL_DOWN; + has_vertical = true; + } else if (scroll->direction == GDK_SCROLL_LEFT) { + btn_horizontal = INPUT_BUTTON_WHEEL_LEFT; + has_horizontal = true; + } else if (scroll->direction == GDK_SCROLL_RIGHT) { + btn_horizontal = INPUT_BUTTON_WHEEL_RIGHT; + has_horizontal = true; } else if (scroll->direction == GDK_SCROLL_SMOOTH) { gdouble delta_x, delta_y; if (!gdk_event_get_scroll_deltas((GdkEvent *)scroll, &delta_x, &delta_y)) { return TRUE; } - if (delta_y == 0) { - return TRUE; - } else if (delta_y > 0) { - btn = INPUT_BUTTON_WHEEL_DOWN; + + if (delta_y > 0) { + btn_vertical = INPUT_BUTTON_WHEEL_DOWN; + has_vertical = true; + } else if (delta_y < 0) { + btn_vertical = INPUT_BUTTON_WHEEL_UP; + has_vertical = true; + } else if (delta_x > 0) { + btn_horizontal = INPUT_BUTTON_WHEEL_RIGHT; + has_horizontal = true; + } else if (delta_x < 0) { + btn_horizontal = INPUT_BUTTON_WHEEL_LEFT; + has_horizontal = true; } else { - btn = INPUT_BUTTON_WHEEL_UP; + return TRUE; } } else { return TRUE; } - qemu_input_queue_btn(vc->gfx.dcl.con, btn, true); - qemu_input_event_sync(); - qemu_input_queue_btn(vc->gfx.dcl.con, btn, false); - qemu_input_event_sync(); + if (has_vertical) { + qemu_input_queue_btn(vc->gfx.dcl.con, btn_vertical, true); + qemu_input_event_sync(); + qemu_input_queue_btn(vc->gfx.dcl.con, btn_vertical, false); + qemu_input_event_sync(); + } + + if (has_horizontal) { + qemu_input_queue_btn(vc->gfx.dcl.con, btn_horizontal, true); + qemu_input_event_sync(); + qemu_input_queue_btn(vc->gfx.dcl.con, btn_horizontal, false); + qemu_input_event_sync(); + } + return TRUE; } From ed80f503a1cd31ee547bb44f7e13ea313733e8cc Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Sat, 8 Jan 2022 16:39:46 +0100 Subject: [PATCH 491/730] ui/sdl2: pass horizontal scroll information to the device code Signed-off-by: Dmitry Petrov Message-Id: <20220108153947.171861-5-dpetroff@gmail.com> Signed-off-by: Gerd Hoffmann --- ui/sdl2.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ui/sdl2.c b/ui/sdl2.c index 0bd30504cf..46a252d7d9 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -33,6 +33,7 @@ #include "sysemu/runstate-action.h" #include "sysemu/sysemu.h" #include "ui/win32-kbd-hook.h" +#include "qemu/log.h" static int sdl2_num_outputs; static struct sdl2_console *sdl2_console; @@ -535,6 +536,10 @@ static void handle_mousewheel(SDL_Event *ev) btn = INPUT_BUTTON_WHEEL_UP; } else if (wev->y < 0) { btn = INPUT_BUTTON_WHEEL_DOWN; + } else if (wev->x < 0) { + btn = INPUT_BUTTON_WHEEL_RIGHT; + } else if (wev->x > 0) { + btn = INPUT_BUTTON_WHEEL_LEFT; } else { return; } From 17f6315ef883a142b6a41a491b63a6554e784a5c Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Sat, 8 Jan 2022 16:39:47 +0100 Subject: [PATCH 492/730] ui/input-legacy: pass horizontal scroll information This code seems to be used by vmport hack, passing these values allows to implement horizontal scroll support even when using vmport. In case it's not supported horizontal scroll will act as a vertical one. Signed-off-by: Dmitry Petrov Message-Id: <20220108153947.171861-6-dpetroff@gmail.com> Signed-off-by: Gerd Hoffmann --- ui/input-legacy.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ui/input-legacy.c b/ui/input-legacy.c index 9fc78a639b..46ea74e44d 100644 --- a/ui/input-legacy.c +++ b/ui/input-legacy.c @@ -23,6 +23,7 @@ */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "qapi/qapi-commands-ui.h" #include "ui/console.h" #include "keymaps.h" @@ -179,6 +180,20 @@ static void legacy_mouse_event(DeviceState *dev, QemuConsole *src, 1, s->buttons); } + if (btn->down && btn->button == INPUT_BUTTON_WHEEL_RIGHT) { + s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque, + s->axis[INPUT_AXIS_X], + s->axis[INPUT_AXIS_Y], + -2, + s->buttons); + } + if (btn->down && btn->button == INPUT_BUTTON_WHEEL_LEFT) { + s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque, + s->axis[INPUT_AXIS_X], + s->axis[INPUT_AXIS_Y], + 2, + s->buttons); + } break; case INPUT_EVENT_KIND_ABS: move = evt->u.abs.data; From fa8fc1d09f9b4deaf764420ac11d8b3c88f8af60 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 15 Dec 2021 07:11:38 -0500 Subject: [PATCH 493/730] block_int: make bdrv_backing_overridden static bdrv_backing_overridden is only used in block.c, so there is no need to leave it in block_int.h Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Stefan Hajnoczi Message-Id: <20211215121140.456939-2-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- block.c | 4 +++- include/block/block_int.h | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/block.c b/block.c index 0ac5b163d2..10346b5011 100644 --- a/block.c +++ b/block.c @@ -103,6 +103,8 @@ static int bdrv_reopen_prepare(BDRVReopenState *reopen_state, static void bdrv_reopen_commit(BDRVReopenState *reopen_state); static void bdrv_reopen_abort(BDRVReopenState *reopen_state); +static bool bdrv_backing_overridden(BlockDriverState *bs); + /* If non-zero, use only whitelisted block drivers */ static int use_bdrv_whitelist; @@ -7475,7 +7477,7 @@ static bool append_strong_runtime_options(QDict *d, BlockDriverState *bs) /* Note: This function may return false positives; it may return true * even if opening the backing file specified by bs's image header * would result in exactly bs->backing. */ -bool bdrv_backing_overridden(BlockDriverState *bs) +static bool bdrv_backing_overridden(BlockDriverState *bs) { if (bs->backing) { return strcmp(bs->auto_backing_file, diff --git a/include/block/block_int.h b/include/block/block_int.h index f4c75e8ba9..27008cfb22 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -1122,9 +1122,6 @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix, QDict *options); -bool bdrv_backing_overridden(BlockDriverState *bs); - - /** * bdrv_add_aio_context_notifier: * From cc67f28ea2760505a4cc6efdc36cbb9b8421f928 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 15 Dec 2021 07:11:39 -0500 Subject: [PATCH 494/730] include/sysemu/blockdev.h: remove drive_mark_claimed_by_board and inline drive_def drive_def is only a particular use case of qemu_opts_parse_noisily, so it can be inlined. Also remove drive_mark_claimed_by_board, as it is only defined but not implemented (nor used) anywhere. Signed-off-by: Emanuele Giuseppe Esposito Message-Id: <20211215121140.456939-3-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- block/monitor/block-hmp-cmds.c | 2 +- blockdev.c | 7 +------ include/sysemu/blockdev.h | 2 -- softmmu/vl.c | 4 +++- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c index 2ac4aedfff..bfb3c043a0 100644 --- a/block/monitor/block-hmp-cmds.c +++ b/block/monitor/block-hmp-cmds.c @@ -101,7 +101,7 @@ void hmp_drive_add(Monitor *mon, const QDict *qdict) return; } - opts = drive_def(optstr); + opts = qemu_opts_parse_noisily(qemu_find_opts("drive"), optstr, false); if (!opts) return; diff --git a/blockdev.c b/blockdev.c index b5ff9b854e..25b3b202e7 100644 --- a/blockdev.c +++ b/blockdev.c @@ -197,17 +197,12 @@ static int drive_index_to_unit_id(BlockInterfaceType type, int index) return max_devs ? index % max_devs : index; } -QemuOpts *drive_def(const char *optstr) -{ - return qemu_opts_parse_noisily(qemu_find_opts("drive"), optstr, false); -} - QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file, const char *optstr) { QemuOpts *opts; - opts = drive_def(optstr); + opts = qemu_opts_parse_noisily(qemu_find_opts("drive"), optstr, false); if (!opts) { return NULL; } diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index a750f99b79..ea35c42f5c 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -45,13 +45,11 @@ BlockBackend *blk_by_legacy_dinfo(DriveInfo *dinfo); void override_max_devs(BlockInterfaceType type, int max_devs); DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); -void drive_mark_claimed_by_board(void); void drive_check_orphaned(void); DriveInfo *drive_get_by_index(BlockInterfaceType type, int index); int drive_get_max_bus(BlockInterfaceType type); int drive_get_max_devs(BlockInterfaceType type); -QemuOpts *drive_def(const char *optstr); QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file, const char *optstr); DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type, diff --git a/softmmu/vl.c b/softmmu/vl.c index a8cad43691..207a9eb8be 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2887,7 +2887,9 @@ void qemu_init(int argc, char **argv, char **envp) break; } case QEMU_OPTION_drive: - if (drive_def(optarg) == NULL) { + opts = qemu_opts_parse_noisily(qemu_find_opts("drive"), + optarg, false); + if (opts == NULL) { exit(1); } break; From eac32e2232f949c0a1638acbef8f6ba0e4feeb67 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Wed, 15 Dec 2021 07:11:40 -0500 Subject: [PATCH 495/730] include/sysemu/blockdev.h: remove drive_get_max_devs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove drive_get_max_devs, as it is not used by anyone. Last use was removed in commit 8f2d75e81d5 ("hw: Drop superfluous special checks for orphaned -drive"). Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Stefan Hajnoczi Message-Id: <20211215121140.456939-4-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- blockdev.c | 17 ----------------- include/sysemu/blockdev.h | 1 - 2 files changed, 18 deletions(-) diff --git a/blockdev.c b/blockdev.c index 25b3b202e7..8197165bb5 100644 --- a/blockdev.c +++ b/blockdev.c @@ -168,23 +168,6 @@ void blockdev_auto_del(BlockBackend *blk) } } -/** - * Returns the current mapping of how many units per bus - * a particular interface can support. - * - * A positive integer indicates n units per bus. - * 0 implies the mapping has not been established. - * -1 indicates an invalid BlockInterfaceType was given. - */ -int drive_get_max_devs(BlockInterfaceType type) -{ - if (type >= IF_IDE && type < IF_COUNT) { - return if_max_devs[type]; - } - - return -1; -} - static int drive_index_to_bus_id(BlockInterfaceType type, int index) { int max_devs = if_max_devs[type]; diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index ea35c42f5c..f9fb54d437 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -48,7 +48,6 @@ DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit); void drive_check_orphaned(void); DriveInfo *drive_get_by_index(BlockInterfaceType type, int index); int drive_get_max_bus(BlockInterfaceType type); -int drive_get_max_devs(BlockInterfaceType type); QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file, const char *optstr); From 64b4529a432507ee84a924be69a03432639e87ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 5 Jan 2022 12:38:47 +0000 Subject: [PATCH 496/730] softmmu: fix device deletion events with -device JSON syntax MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The -device JSON syntax impl leaks a reference on the created DeviceState instance. As a result when you hot-unplug the device, the device_finalize method won't be called and thus it will fail to emit the required DEVICE_DELETED event. A 'json-cli' feature was previously added against the 'device_add' QMP command QAPI schema to indicated to mgmt apps that -device supported JSON syntax. Given the hotplug bug that feature flag is not usable for its purpose, so we add a new 'json-cli-hotplug' feature to indicate the -device supports JSON without breaking hotplug. Fixes: 5dacda5167560b3af8eadbce5814f60ba44b467e Resolves: https://gitlab.com/qemu-project/qemu/-/issues/802 Signed-off-by: Daniel P. Berrangé Message-Id: <20220105123847.4047954-2-berrange@redhat.com> Reviewed-by: Laurent Vivier Tested-by: Ján Tomko Reviewed-by: Thomas Huth Signed-off-by: Kevin Wolf --- qapi/qdev.json | 5 ++++- softmmu/vl.c | 4 +++- tests/qtest/device-plug-test.c | 19 +++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/qapi/qdev.json b/qapi/qdev.json index 69656b14df..26cd10106b 100644 --- a/qapi/qdev.json +++ b/qapi/qdev.json @@ -44,6 +44,9 @@ # @json-cli: If present, the "-device" command line option supports JSON # syntax with a structure identical to the arguments of this # command. +# @json-cli-hotplug: If present, the "-device" command line option supports JSON +# syntax without the reference counting leak that broke +# hot-unplug # # Notes: # @@ -74,7 +77,7 @@ { 'command': 'device_add', 'data': {'driver': 'str', '*bus': 'str', '*id': 'str'}, 'gen': false, # so we can get the additional arguments - 'features': ['json-cli'] } + 'features': ['json-cli', 'json-cli-hotplug'] } ## # @device_del: diff --git a/softmmu/vl.c b/softmmu/vl.c index 207a9eb8be..5e1b35ba48 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2684,6 +2684,7 @@ static void qemu_create_cli_devices(void) qemu_opts_foreach(qemu_find_opts("device"), device_init_func, NULL, &error_fatal); QTAILQ_FOREACH(opt, &device_opts, next) { + DeviceState *dev; loc_push_restore(&opt->loc); /* * TODO Eventually we should call qmp_device_add() here to make sure it @@ -2692,7 +2693,8 @@ static void qemu_create_cli_devices(void) * from the start, so call qdev_device_add_from_qdict() directly for * now. */ - qdev_device_add_from_qdict(opt->opts, true, &error_fatal); + dev = qdev_device_add_from_qdict(opt->opts, true, &error_fatal); + object_unref(OBJECT(dev)); loc_pop(&opt->loc); } rom_reset_order_override(); diff --git a/tests/qtest/device-plug-test.c b/tests/qtest/device-plug-test.c index 559d47727a..ad79bd4c14 100644 --- a/tests/qtest/device-plug-test.c +++ b/tests/qtest/device-plug-test.c @@ -77,6 +77,23 @@ static void test_pci_unplug_request(void) qtest_quit(qtest); } +static void test_pci_unplug_json_request(void) +{ + QTestState *qtest = qtest_initf( + "-device '{\"driver\": \"virtio-mouse-pci\", \"id\": \"dev0\"}'"); + + /* + * Request device removal. As the guest is not running, the request won't + * be processed. However during system reset, the removal will be + * handled, removing the device. + */ + device_del(qtest, "dev0"); + system_reset(qtest); + wait_device_deleted_event(qtest, "dev0"); + + qtest_quit(qtest); +} + static void test_ccw_unplug(void) { QTestState *qtest = qtest_initf("-device virtio-balloon-ccw,id=dev0"); @@ -145,6 +162,8 @@ int main(int argc, char **argv) */ qtest_add_func("/device-plug/pci-unplug-request", test_pci_unplug_request); + qtest_add_func("/device-plug/pci-unplug-json-request", + test_pci_unplug_json_request); if (!strcmp(arch, "s390x")) { qtest_add_func("/device-plug/ccw-unplug", From 9bd11f9638cbc08dcab6777f0a27f597cb44c22a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 7 Jan 2022 11:54:18 +0100 Subject: [PATCH 497/730] docs: Correct 'vhost-user-blk' spelling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Eric Blake Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20220107105420.395011-2-f4bug@amsat.org> Signed-off-by: Kevin Wolf --- docs/tools/qemu-storage-daemon.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tools/qemu-storage-daemon.rst b/docs/tools/qemu-storage-daemon.rst index 3e5a9dc032..9b0eaba6e5 100644 --- a/docs/tools/qemu-storage-daemon.rst +++ b/docs/tools/qemu-storage-daemon.rst @@ -201,7 +201,7 @@ Export raw image file ``disk.img`` over NBD UNIX domain socket ``nbd.sock``:: --nbd-server addr.type=unix,addr.path=nbd.sock \ --export type=nbd,id=export,node-name=disk,writable=on -Export a qcow2 image file ``disk.qcow2`` as a vhosts-user-blk device over UNIX +Export a qcow2 image file ``disk.qcow2`` as a vhost-user-blk device over UNIX domain socket ``vhost-user-blk.sock``:: $ qemu-storage-daemon \ From c8cbc9524269d9583749aaaea8aa244add7e1900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 7 Jan 2022 11:54:19 +0100 Subject: [PATCH 498/730] qemu-storage-daemon: Add vhost-user-blk help MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing vhost-user-blk help: $ qemu-storage-daemon -h ... --export [type=]vhost-user-blk,id=,node-name=, addr.type=unix,addr.path=[,writable=on|off] [,logical-block-size=][,num-queues=] export the specified block node as a vhosts-user-blk device over UNIX domain socket --export [type=]vhost-user-blk,id=,node-name=, fd,addr.str=[,writable=on|off] [,logical-block-size=][,num-queues=] export the specified block node as a vhosts-user-blk device over file descriptor ... Fixes: 90fc91d50b7 ("convert vhost-user-blk server to block export API") Reported-by: Qing Wang Reviewed-by: Eric Blake Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20220107105420.395011-3-f4bug@amsat.org> Signed-off-by: Kevin Wolf --- storage-daemon/qemu-storage-daemon.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/storage-daemon/qemu-storage-daemon.c b/storage-daemon/qemu-storage-daemon.c index 52cf17e8ac..9d76d1114d 100644 --- a/storage-daemon/qemu-storage-daemon.c +++ b/storage-daemon/qemu-storage-daemon.c @@ -104,6 +104,19 @@ static void help(void) " export the specified block node over FUSE\n" "\n" #endif /* CONFIG_FUSE */ +#ifdef CONFIG_VHOST_USER_BLK_SERVER +" --export [type=]vhost-user-blk,id=,node-name=,\n" +" addr.type=unix,addr.path=[,writable=on|off]\n" +" [,logical-block-size=][,num-queues=]\n" +" export the specified block node as a\n" +" vhost-user-blk device over UNIX domain socket\n" +" --export [type=]vhost-user-blk,id=,node-name=,\n" +" fd,addr.str=[,writable=on|off]\n" +" [,logical-block-size=][,num-queues=]\n" +" export the specified block node as a\n" +" vhost-user-blk device over file descriptor\n" +"\n" +#endif /* CONFIG_VHOST_USER_BLK_SERVER */ " --monitor [chardev=]name[,mode=control][,pretty[=on|off]]\n" " configure a QMP monitor\n" "\n" From bb01ea7311004b4a87b510446be689afb7f040ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 7 Jan 2022 11:54:20 +0100 Subject: [PATCH 499/730] qapi/block: Restrict vhost-user-blk to CONFIG_VHOST_USER_BLK_SERVER MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building QEMU with --disable-vhost-user and using introspection, query-qmp-schema lists vhost-user-blk even though it's not actually available: { "execute": "query-qmp-schema" } { "return": [ ... { "name": "312", "members": [ { "name": "nbd" }, { "name": "vhost-user-blk" } ], "meta-type": "enum", "values": [ "nbd", "vhost-user-blk" ] }, Restrict vhost-user-blk in BlockExportType when CONFIG_VHOST_USER_BLK_SERVER is disabled, so it doesn't end listed by query-qmp-schema. Fixes: 90fc91d50b7 ("convert vhost-user-blk server to block export API") Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20220107105420.395011-4-f4bug@amsat.org> Signed-off-by: Kevin Wolf --- qapi/block-export.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/qapi/block-export.json b/qapi/block-export.json index c1b92ce1c1..f9ce79a974 100644 --- a/qapi/block-export.json +++ b/qapi/block-export.json @@ -277,7 +277,8 @@ # Since: 4.2 ## { 'enum': 'BlockExportType', - 'data': [ 'nbd', 'vhost-user-blk', + 'data': [ 'nbd', + { 'name': 'vhost-user-blk', 'if': 'CONFIG_VHOST_USER_BLK_SERVER' }, { 'name': 'fuse', 'if': 'CONFIG_FUSE' } ] } ## @@ -319,7 +320,8 @@ 'discriminator': 'type', 'data': { 'nbd': 'BlockExportOptionsNbd', - 'vhost-user-blk': 'BlockExportOptionsVhostUserBlk', + 'vhost-user-blk': { 'type': 'BlockExportOptionsVhostUserBlk', + 'if': 'CONFIG_VHOST_USER_BLK_SERVER' }, 'fuse': { 'type': 'BlockExportOptionsFuse', 'if': 'CONFIG_FUSE' } } } From 1e3552dbd28359d35967b7c28dc86cde1bc29205 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Tue, 11 Jan 2022 15:36:12 +0000 Subject: [PATCH 500/730] block-backend: prevent dangling BDS pointers across aio_poll() The BlockBackend root child can change when aio_poll() is invoked. This happens when a temporary filter node is removed upon blockjob completion, for example. Functions in block/block-backend.c must be aware of this when using a blk_bs() pointer across aio_poll() because the BlockDriverState refcnt may reach 0, resulting in a stale pointer. One example is scsi_device_purge_requests(), which calls blk_drain() to wait for in-flight requests to cancel. If the backup blockjob is active, then the BlockBackend root child is a temporary filter BDS owned by the blockjob. The blockjob can complete during bdrv_drained_begin() and the last reference to the BDS is released when the temporary filter node is removed. This results in a use-after-free when blk_drain() calls bdrv_drained_end(bs) on the dangling pointer. Explicitly hold a reference to bs across block APIs that invoke aio_poll(). Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2021778 Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2036178 Signed-off-by: Stefan Hajnoczi Message-Id: <20220111153613.25453-2-stefanha@redhat.com> Signed-off-by: Kevin Wolf --- block/block-backend.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/block/block-backend.c b/block/block-backend.c index 12ef80ea17..23e727199b 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -822,16 +822,22 @@ BlockBackend *blk_by_public(BlockBackendPublic *public) void blk_remove_bs(BlockBackend *blk) { ThrottleGroupMember *tgm = &blk->public.throttle_group_member; - BlockDriverState *bs; BdrvChild *root; notifier_list_notify(&blk->remove_bs_notifiers, blk); if (tgm->throttle_state) { - bs = blk_bs(blk); + BlockDriverState *bs = blk_bs(blk); + + /* + * Take a ref in case blk_bs() changes across bdrv_drained_begin(), for + * example, if a temporary filter node is removed by a blockjob. + */ + bdrv_ref(bs); bdrv_drained_begin(bs); throttle_group_detach_aio_context(tgm); throttle_group_attach_aio_context(tgm, qemu_get_aio_context()); bdrv_drained_end(bs); + bdrv_unref(bs); } blk_update_root_state(blk); @@ -1705,6 +1711,7 @@ void blk_drain(BlockBackend *blk) BlockDriverState *bs = blk_bs(blk); if (bs) { + bdrv_ref(bs); bdrv_drained_begin(bs); } @@ -1714,6 +1721,7 @@ void blk_drain(BlockBackend *blk) if (bs) { bdrv_drained_end(bs); + bdrv_unref(bs); } } @@ -2044,10 +2052,13 @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context, int ret; if (bs) { + bdrv_ref(bs); + if (update_root_node) { ret = bdrv_child_try_set_aio_context(bs, new_context, blk->root, errp); if (ret < 0) { + bdrv_unref(bs); return ret; } } @@ -2057,6 +2068,8 @@ static int blk_do_set_aio_context(BlockBackend *blk, AioContext *new_context, throttle_group_attach_aio_context(tgm, new_context); bdrv_drained_end(bs); } + + bdrv_unref(bs); } blk->ctx = new_context; @@ -2326,11 +2339,13 @@ void blk_io_limits_disable(BlockBackend *blk) ThrottleGroupMember *tgm = &blk->public.throttle_group_member; assert(tgm->throttle_state); if (bs) { + bdrv_ref(bs); bdrv_drained_begin(bs); } throttle_group_unregister_tgm(tgm); if (bs) { bdrv_drained_end(bs); + bdrv_unref(bs); } } From 2ca1d5d6b91f8a52a5c651f660b2f58c94bf97ba Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Tue, 11 Jan 2022 15:36:13 +0000 Subject: [PATCH 501/730] iotests/stream-error-on-reset: New test Test the following scenario: - Simple stream block in two-layer backing chain (base and top) - The job is drained via blk_drain(), then an error occurs while the job settles the ongoing request - And so the job completes while in blk_drain() This was reported as a segfault, but is fixed by "block-backend: prevent dangling BDS pointers across aio_poll()". Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2036178 Signed-off-by: Hanna Reitz Signed-off-by: Stefan Hajnoczi Message-Id: <20220111153613.25453-3-stefanha@redhat.com> Signed-off-by: Kevin Wolf --- .../qemu-iotests/tests/stream-error-on-reset | 140 ++++++++++++++++++ .../tests/stream-error-on-reset.out | 5 + 2 files changed, 145 insertions(+) create mode 100755 tests/qemu-iotests/tests/stream-error-on-reset create mode 100644 tests/qemu-iotests/tests/stream-error-on-reset.out diff --git a/tests/qemu-iotests/tests/stream-error-on-reset b/tests/qemu-iotests/tests/stream-error-on-reset new file mode 100755 index 0000000000..7eaedb24d7 --- /dev/null +++ b/tests/qemu-iotests/tests/stream-error-on-reset @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +# group: rw quick +# +# Test what happens when a stream job completes in a blk_drain(). +# +# Copyright (C) 2022 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import os +import iotests +from iotests import imgfmt, qemu_img_create, qemu_io_silent, QMPTestCase + + +image_size = 1 * 1024 * 1024 +data_size = 64 * 1024 +base = os.path.join(iotests.test_dir, 'base.img') +top = os.path.join(iotests.test_dir, 'top.img') + + +# We want to test completing a stream job in a blk_drain(). +# +# The blk_drain() we are going to use is a virtio-scsi device resetting, +# which we can trigger by resetting the system. +# +# In order to have the block job complete on drain, we (1) throttle its +# base image so we can start the drain after it has begun, but before it +# completes, and (2) make it encounter an I/O error on the ensuing write. +# (If it completes regularly, the completion happens after the drain for +# some reason.) + +class TestStreamErrorOnReset(QMPTestCase): + def setUp(self) -> None: + """ + Create two images: + - base image {base} with {data_size} bytes allocated + - top image {top} without any data allocated + + And the following VM configuration: + - base image throttled to {data_size} + - top image with a blkdebug configuration so the first write access + to it will result in an error + - top image is attached to a virtio-scsi device + """ + assert qemu_img_create('-f', imgfmt, base, str(image_size)) == 0 + assert qemu_io_silent('-c', f'write 0 {data_size}', base) == 0 + assert qemu_img_create('-f', imgfmt, top, str(image_size)) == 0 + + self.vm = iotests.VM() + self.vm.add_args('-accel', 'tcg') # Make throttling work properly + self.vm.add_object(self.vm.qmp_to_opts({ + 'qom-type': 'throttle-group', + 'id': 'thrgr', + 'x-bps-total': str(data_size) + })) + self.vm.add_blockdev(self.vm.qmp_to_opts({ + 'driver': imgfmt, + 'node-name': 'base', + 'file': { + 'driver': 'throttle', + 'throttle-group': 'thrgr', + 'file': { + 'driver': 'file', + 'filename': base + } + } + })) + self.vm.add_blockdev(self.vm.qmp_to_opts({ + 'driver': imgfmt, + 'node-name': 'top', + 'file': { + 'driver': 'blkdebug', + 'node-name': 'top-blkdebug', + 'inject-error': [{ + 'event': 'pwritev', + 'immediately': 'true', + 'once': 'true' + }], + 'image': { + 'driver': 'file', + 'filename': top + } + }, + 'backing': 'base' + })) + self.vm.add_device(self.vm.qmp_to_opts({ + 'driver': 'virtio-scsi', + 'id': 'vscsi' + })) + self.vm.add_device(self.vm.qmp_to_opts({ + 'driver': 'scsi-hd', + 'bus': 'vscsi.0', + 'drive': 'top' + })) + self.vm.launch() + + def tearDown(self) -> None: + self.vm.shutdown() + os.remove(top) + os.remove(base) + + def test_stream_error_on_reset(self) -> None: + # Launch a stream job, which will take at least a second to + # complete, because the base image is throttled (so we can + # get in between it having started and it having completed) + res = self.vm.qmp('block-stream', job_id='stream', device='top') + self.assert_qmp(res, 'return', {}) + + while True: + ev = self.vm.event_wait('JOB_STATUS_CHANGE') + if ev['data']['status'] == 'running': + # Once the stream job is running, reset the system, which + # forces the virtio-scsi device to be reset, thus draining + # the stream job, and making it complete. Completing + # inside of that drain should not result in a segfault. + res = self.vm.qmp('system_reset') + self.assert_qmp(res, 'return', {}) + elif ev['data']['status'] == 'null': + # The test is done once the job is gone + break + + +if __name__ == '__main__': + # Passes with any format with backing file support, but qed and + # qcow1 do not seem to exercise the used-to-be problematic code + # path, so there is no point in having them in this list + iotests.main(supported_fmts=['qcow2', 'vmdk'], + supported_protocols=['file']) diff --git a/tests/qemu-iotests/tests/stream-error-on-reset.out b/tests/qemu-iotests/tests/stream-error-on-reset.out new file mode 100644 index 0000000000..ae1213e6f8 --- /dev/null +++ b/tests/qemu-iotests/tests/stream-error-on-reset.out @@ -0,0 +1,5 @@ +. +---------------------------------------------------------------------- +Ran 1 tests + +OK From e2eec2819a96f3a5d68f899c836ad365468cec01 Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Mon, 3 Jan 2022 13:00:14 +0100 Subject: [PATCH 502/730] iotests/308: Fix for CAP_DAC_OVERRIDE With CAP_DAC_OVERRIDE (which e.g. root generally has), permission checks will be bypassed when opening files. 308 in one instance tries to open a read-only file (FUSE export) with qemu-io as read/write, and expects this to fail. However, when running it as root, opening will succeed (thanks to CAP_DAC_OVERRIDE) and only the actual write operation will fail. Note this as "Case not run", but have the test pass in either case. Reported-by: Vladimir Sementsov-Ogievskiy Fixes: 2c7dd057aa7bd7a875e9b1a53975c220d6380bc4 ("export/fuse: Pass default_permissions for mount") Signed-off-by: Hanna Reitz Message-Id: <20220103120014.13061-1-hreitz@redhat.com> Signed-off-by: Kevin Wolf --- tests/qemu-iotests/308 | 25 +++++++++++++++++++++++-- tests/qemu-iotests/308.out | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/tests/qemu-iotests/308 b/tests/qemu-iotests/308 index 2e3f8f4282..bde4aac2fa 100755 --- a/tests/qemu-iotests/308 +++ b/tests/qemu-iotests/308 @@ -230,8 +230,29 @@ echo '=== Writable export ===' fuse_export_add 'export-mp' "'mountpoint': '$EXT_MP', 'writable': true" # Check that writing to the read-only export fails -$QEMU_IO -f raw -c 'write -P 42 1M 64k' "$TEST_IMG" 2>&1 \ - | _filter_qemu_io | _filter_testdir | _filter_imgfmt +output=$($QEMU_IO -f raw -c 'write -P 42 1M 64k' "$TEST_IMG" 2>&1 \ + | _filter_qemu_io | _filter_testdir | _filter_imgfmt) + +# Expected reference output: Opening the file fails because it has no +# write permission +reference="Could not open 'TEST_DIR/t.IMGFMT': Permission denied" + +if echo "$output" | grep -q "$reference"; then + echo "Writing to read-only export failed: OK" +elif echo "$output" | grep -q "write failed: Permission denied"; then + # With CAP_DAC_OVERRIDE (e.g. when running this test as root), the export + # can be opened regardless of its file permissions, but writing will then + # fail. This is not the result for which we want to test, so count this as + # a SKIP. + _casenotrun "Opening RO export as R/W succeeded, perhaps because of" \ + "CAP_DAC_OVERRIDE" + + # Still, write this to the reference output to make the test pass + echo "Writing to read-only export failed: OK" +else + echo "Writing to read-only export failed: ERROR" + echo "$output" +fi # But here it should work $QEMU_IO -f raw -c 'write -P 42 1M 64k' "$EXT_MP" | _filter_qemu_io diff --git a/tests/qemu-iotests/308.out b/tests/qemu-iotests/308.out index fc47bb11a2..e4467a10cf 100644 --- a/tests/qemu-iotests/308.out +++ b/tests/qemu-iotests/308.out @@ -95,7 +95,7 @@ virtual size: 0 B (0 bytes) 'mountpoint': 'TEST_DIR/t.IMGFMT.fuse', 'writable': true } } {"return": {}} -qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'TEST_DIR/t.IMGFMT': Permission denied +Writing to read-only export failed: OK wrote 65536/65536 bytes at offset 1048576 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 65536/65536 bytes at offset 1048576 From 2db9b9e96f0b57ceaa49666d9b8a573290114fdf Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 9 Dec 2021 16:18:15 +0100 Subject: [PATCH 503/730] vvfat: Fix size of temporary qcow file The size of the qcow size was calculated so that only the FAT partition would fit on it, but not the whole disk. However, offsets relative to the whole disk are used to access it, so increase its size to be large enough for that. Signed-off-by: Kevin Wolf Message-Id: <20211209151815.23495-1-kwolf@redhat.com> Signed-off-by: Kevin Wolf --- block/vvfat.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/block/vvfat.c b/block/vvfat.c index 5dacc6cfac..36e73d4c64 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -1230,6 +1230,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, dirname, cyls, heads, secs)); s->sector_count = cyls * heads * secs - s->offset_to_bootsector; + bs->total_sectors = cyls * heads * secs; if (qemu_opt_get_bool(opts, "rw", false)) { if (!bdrv_is_read_only(bs)) { @@ -1250,8 +1251,6 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, } } - bs->total_sectors = cyls * heads * secs; - if (init_directories(s, dirname, heads, secs, errp)) { ret = -EIO; goto fail; @@ -3147,8 +3146,8 @@ static int enable_write_target(BlockDriverState *bs, Error **errp) } opts = qemu_opts_create(bdrv_qcow->create_opts, NULL, 0, &error_abort); - qemu_opt_set_number(opts, BLOCK_OPT_SIZE, s->sector_count * 512, - &error_abort); + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, + bs->total_sectors * BDRV_SECTOR_SIZE, &error_abort); qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, "fat:", &error_abort); ret = bdrv_create(bdrv_qcow, s->qcow_filename, opts, errp); From b9b8860d24676ec59c878d5206ea6bcfc87af798 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 9 Dec 2021 16:22:31 +0100 Subject: [PATCH 504/730] vvfat: Fix vvfat_write() for writes before the root directory The calculation in sector2cluster() is done relative to the offset of the root directory. Any writes to blocks before the start of the root directory (in particular, writes to the FAT) result in negative values, which are not handled correctly in vvfat_write(). This changes sector2cluster() to return a signed value, and makes sure that vvfat_write() doesn't try to find mappings for negative cluster number. It clarifies the code in vvfat_write() to make it more obvious that the cluster numbers can be negative. Signed-off-by: Kevin Wolf Message-Id: <20211209152231.23756-1-kwolf@redhat.com> Signed-off-by: Kevin Wolf --- block/vvfat.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/block/vvfat.c b/block/vvfat.c index 36e73d4c64..b2b58d93b8 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -882,7 +882,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index) return 0; } -static inline uint32_t sector2cluster(BDRVVVFATState* s,off_t sector_num) +static inline int32_t sector2cluster(BDRVVVFATState* s,off_t sector_num) { return (sector_num - s->offset_to_root_dir) / s->sectors_per_cluster; } @@ -2981,6 +2981,7 @@ static int vvfat_write(BlockDriverState *bs, int64_t sector_num, { BDRVVVFATState *s = bs->opaque; int i, ret; + int first_cluster, last_cluster; DLOG(checkpoint()); @@ -2999,9 +3000,20 @@ DLOG(checkpoint()); if (sector_num < s->offset_to_fat) return -1; - for (i = sector2cluster(s, sector_num); - i <= sector2cluster(s, sector_num + nb_sectors - 1);) { - mapping_t* mapping = find_mapping_for_cluster(s, i); + /* + * Values will be negative for writes to the FAT, which is located before + * the root directory. + */ + first_cluster = sector2cluster(s, sector_num); + last_cluster = sector2cluster(s, sector_num + nb_sectors - 1); + + for (i = first_cluster; i <= last_cluster;) { + mapping_t *mapping = NULL; + + if (i >= 0) { + mapping = find_mapping_for_cluster(s, i); + } + if (mapping) { if (mapping->read_only) { fprintf(stderr, "Tried to write to write-protected file %s\n", @@ -3041,8 +3053,9 @@ DLOG(checkpoint()); } } i = mapping->end; - } else + } else { i++; + } } /* @@ -3056,10 +3069,11 @@ DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sec return ret; } - for (i = sector2cluster(s, sector_num); - i <= sector2cluster(s, sector_num + nb_sectors - 1); i++) - if (i >= 0) + for (i = first_cluster; i <= last_cluster; i++) { + if (i >= 0) { s->used_clusters[i] |= USED_ALLOCATED; + } + } DLOG(checkpoint()); /* TODO: add timeout */ From 51cd8bddd63540514d44808f7920811439baa253 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 17 Dec 2021 17:46:53 +0100 Subject: [PATCH 505/730] iotests: Test qemu-img convert of zeroed data cluster This demonstrates what happens when the block status changes in sub-min_sparse granularity, but all of the parts are zeroed out. The alignment logic in is_allocated_sectors() prevents that the target image remains fully sparse as expected, but turns it into a data cluster of explicit zeros. Signed-off-by: Kevin Wolf Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20211217164654.1184218-2-vsementsov@virtuozzo.com> Tested-by: Peter Lieven Signed-off-by: Kevin Wolf --- tests/qemu-iotests/122 | 1 + tests/qemu-iotests/122.out | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/qemu-iotests/122 b/tests/qemu-iotests/122 index efb260d822..be0f6b79e5 100755 --- a/tests/qemu-iotests/122 +++ b/tests/qemu-iotests/122 @@ -251,6 +251,7 @@ $QEMU_IO -c "write -P 0 0 64k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_test $QEMU_IO -c "write 0 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir $QEMU_IO -c "write 8k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir $QEMU_IO -c "write 17k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir +$QEMU_IO -c "write -P 0 65k 1k" "$TEST_IMG" 2>&1 | _filter_qemu_io | _filter_testdir for min_sparse in 4k 8k; do echo diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out index 8fbdac2b39..69b8e8b803 100644 --- a/tests/qemu-iotests/122.out +++ b/tests/qemu-iotests/122.out @@ -192,6 +192,8 @@ wrote 1024/1024 bytes at offset 8192 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) wrote 1024/1024 bytes at offset 17408 1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 1024/1024 bytes at offset 66560 +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) convert -S 4k [{ "start": 0, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET}, @@ -199,7 +201,9 @@ convert -S 4k { "start": 8192, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET}, { "start": 12288, "length": 4096, "depth": 0, "present": false, "zero": true, "data": false}, { "start": 16384, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET}, -{ "start": 20480, "length": 67088384, "depth": 0, "present": false, "zero": true, "data": false}] +{ "start": 20480, "length": 46080, "depth": 0, "present": false, "zero": true, "data": false}, +{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET}, +{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}] convert -c -S 4k [{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true}, @@ -211,7 +215,9 @@ convert -c -S 4k convert -S 8k [{ "start": 0, "length": 24576, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET}, -{ "start": 24576, "length": 67084288, "depth": 0, "present": false, "zero": true, "data": false}] +{ "start": 24576, "length": 41984, "depth": 0, "present": false, "zero": true, "data": false}, +{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET}, +{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}] convert -c -S 8k [{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true}, From 96054c76ff2db74165385a69f234c57a6bbc941e Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Fri, 17 Dec 2021 17:46:54 +0100 Subject: [PATCH 506/730] qemu-img: make is_allocated_sectors() more efficient Consider the case when the whole buffer is zero and end is unaligned. If i <= tail, we return 1 and do one unaligned WRITE, RMW happens. If i > tail, we do on aligned WRITE_ZERO (or skip if target is zeroed) and again one unaligned WRITE, RMW happens. Let's do better: don't fragment the whole-zero buffer and report it as ZERO: in case of zeroed target we just do nothing and avoid RMW. If target is not zeroes, one unaligned WRITE_ZERO should not be much worse than one unaligned WRITE. Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20211217164654.1184218-3-vsementsov@virtuozzo.com> Tested-by: Peter Lieven Signed-off-by: Kevin Wolf --- qemu-img.c | 23 +++++++++++++++++++---- tests/qemu-iotests/122.out | 8 ++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index 21ba1e6800..6fe2466032 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -1171,19 +1171,34 @@ static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum, } } + if (i == n) { + /* + * The whole buf is the same. + * No reason to split it into chunks, so return now. + */ + *pnum = i; + return !is_zero; + } + tail = (sector_num + i) & (alignment - 1); if (tail) { if (is_zero && i <= tail) { - /* treat unallocated areas which only consist - * of a small tail as allocated. */ + /* + * For sure next sector after i is data, and it will rewrite this + * tail anyway due to RMW. So, let's just write data now. + */ is_zero = false; } if (!is_zero) { - /* align up end offset of allocated areas. */ + /* If possible, align up end offset of allocated areas. */ i += alignment - tail; i = MIN(i, n); } else { - /* align down end offset of zero areas. */ + /* + * For sure next sector after i is data, and it will rewrite this + * tail anyway due to RMW. Better is avoid RMW and write zeroes up + * to aligned bound. + */ i -= tail; } } diff --git a/tests/qemu-iotests/122.out b/tests/qemu-iotests/122.out index 69b8e8b803..e18766e167 100644 --- a/tests/qemu-iotests/122.out +++ b/tests/qemu-iotests/122.out @@ -201,9 +201,7 @@ convert -S 4k { "start": 8192, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET}, { "start": 12288, "length": 4096, "depth": 0, "present": false, "zero": true, "data": false}, { "start": 16384, "length": 4096, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET}, -{ "start": 20480, "length": 46080, "depth": 0, "present": false, "zero": true, "data": false}, -{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET}, -{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}] +{ "start": 20480, "length": 67088384, "depth": 0, "present": false, "zero": true, "data": false}] convert -c -S 4k [{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true}, @@ -215,9 +213,7 @@ convert -c -S 4k convert -S 8k [{ "start": 0, "length": 24576, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET}, -{ "start": 24576, "length": 41984, "depth": 0, "present": false, "zero": true, "data": false}, -{ "start": 66560, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true, "offset": OFFSET}, -{ "start": 67584, "length": 67041280, "depth": 0, "present": false, "zero": true, "data": false}] +{ "start": 24576, "length": 67084288, "depth": 0, "present": false, "zero": true, "data": false}] convert -c -S 8k [{ "start": 0, "length": 1024, "depth": 0, "present": true, "zero": false, "data": true}, From 64631f368115a332bdca32553a430568ecc7761d Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Thu, 2 Sep 2021 12:37:54 +0300 Subject: [PATCH 507/730] block: drop BLK_PERM_GRAPH_MOD First, this permission never protected a node from being changed, as generic child-replacing functions don't check it. Second, it's a strange thing: it presents a permission of parent node to change its child. But generally, children are replaced by different mechanisms, like jobs or qmp commands, not by nodes. Graph-mod permission is hard to understand. All other permissions describe operations which done by parent node on its child: read, write, resize. Graph modification operations are something completely different. The only place where BLK_PERM_GRAPH_MOD is used as "perm" (not shared perm) is mirror_start_job, for s->target. Still modern code should use bdrv_freeze_backing_chain() to protect from graph modification, if we don't do it somewhere it may be considered as a bug. So, it's a bit risky to drop GRAPH_MOD, and analyzing of possible loss of protection is hard. But one day we should do it, let's do it now. One more bit of information is that locking the corresponding byte in file-posix doesn't make sense at all. Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20210902093754.2352-1-vsementsov@virtuozzo.com> Signed-off-by: Kevin Wolf --- block.c | 7 +------ block/commit.c | 1 - block/mirror.c | 15 +++------------ hw/block/block.c | 3 +-- include/block/block.h | 9 +++++---- qapi/block-core.json | 7 ++----- scripts/render_block_graph.py | 1 - tests/qemu-iotests/273.out | 4 ---- 8 files changed, 12 insertions(+), 35 deletions(-) diff --git a/block.c b/block.c index 10346b5011..7b3ce415d8 100644 --- a/block.c +++ b/block.c @@ -2485,7 +2485,6 @@ char *bdrv_perm_names(uint64_t perm) { BLK_PERM_WRITE, "write" }, { BLK_PERM_WRITE_UNCHANGED, "write unchanged" }, { BLK_PERM_RESIZE, "resize" }, - { BLK_PERM_GRAPH_MOD, "change children" }, { 0, NULL } }; @@ -2601,8 +2600,7 @@ static void bdrv_default_perms_for_cow(BlockDriverState *bs, BdrvChild *c, shared = 0; } - shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_GRAPH_MOD | - BLK_PERM_WRITE_UNCHANGED; + shared |= BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED; if (bs->open_flags & BDRV_O_INACTIVE) { shared |= BLK_PERM_WRITE | BLK_PERM_RESIZE; @@ -2720,7 +2718,6 @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm) [BLOCK_PERMISSION_WRITE] = BLK_PERM_WRITE, [BLOCK_PERMISSION_WRITE_UNCHANGED] = BLK_PERM_WRITE_UNCHANGED, [BLOCK_PERMISSION_RESIZE] = BLK_PERM_RESIZE, - [BLOCK_PERMISSION_GRAPH_MOD] = BLK_PERM_GRAPH_MOD, }; QEMU_BUILD_BUG_ON(ARRAY_SIZE(permissions) != BLOCK_PERMISSION__MAX); @@ -5546,8 +5543,6 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, update_inherits_from = bdrv_inherits_from_recursive(base, explicit_top); /* success - we can delete the intermediate states, and link top->base */ - /* TODO Check graph modification op blockers (BLK_PERM_GRAPH_MOD) once - * we've figured out how they should work. */ if (!backing_file_str) { bdrv_refresh_filename(base); backing_file_str = base->filename; diff --git a/block/commit.c b/block/commit.c index 10cc5ff451..b1fc7b908b 100644 --- a/block/commit.c +++ b/block/commit.c @@ -370,7 +370,6 @@ void commit_start(const char *job_id, BlockDriverState *bs, s->base = blk_new(s->common.job.aio_context, base_perms, BLK_PERM_CONSISTENT_READ - | BLK_PERM_GRAPH_MOD | BLK_PERM_WRITE_UNCHANGED); ret = blk_insert_bs(s->base, base, errp); if (ret < 0) { diff --git a/block/mirror.c b/block/mirror.c index 959e3dfbd6..69b2c1c697 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1139,10 +1139,7 @@ static void mirror_complete(Job *job, Error **errp) replace_aio_context = bdrv_get_aio_context(s->to_replace); aio_context_acquire(replace_aio_context); - /* TODO Translate this into permission system. Current definition of - * GRAPH_MOD would require to request it for the parents; they might - * not even be BlockDriverStates, however, so a BdrvChild can't address - * them. May need redefinition of GRAPH_MOD. */ + /* TODO Translate this into child freeze system. */ error_setg(&s->replace_blocker, "block device is in use by block-job-complete"); bdrv_op_block_all(s->to_replace, s->replace_blocker); @@ -1666,7 +1663,7 @@ static BlockJob *mirror_start_job( s = block_job_create(job_id, driver, NULL, mirror_top_bs, BLK_PERM_CONSISTENT_READ, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED | - BLK_PERM_WRITE | BLK_PERM_GRAPH_MOD, speed, + BLK_PERM_WRITE, speed, creation_flags, cb, opaque, errp); if (!s) { goto fail; @@ -1710,9 +1707,7 @@ static BlockJob *mirror_start_job( target_perms |= BLK_PERM_RESIZE; } - target_shared_perms |= BLK_PERM_CONSISTENT_READ - | BLK_PERM_WRITE - | BLK_PERM_GRAPH_MOD; + target_shared_perms |= BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE; } else if (bdrv_chain_contains(bs, bdrv_skip_filters(target))) { /* * We may want to allow this in the future, but it would @@ -1723,10 +1718,6 @@ static BlockJob *mirror_start_job( goto fail; } - if (backing_mode != MIRROR_LEAVE_BACKING_CHAIN) { - target_perms |= BLK_PERM_GRAPH_MOD; - } - s->target = blk_new(s->common.job.aio_context, target_perms, target_shared_perms); ret = blk_insert_bs(s->target, target, errp); diff --git a/hw/block/block.c b/hw/block/block.c index d47ebf005a..25f45df723 100644 --- a/hw/block/block.c +++ b/hw/block/block.c @@ -171,8 +171,7 @@ bool blkconf_apply_backend_options(BlockConf *conf, bool readonly, perm |= BLK_PERM_WRITE; } - shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED | - BLK_PERM_GRAPH_MOD; + shared_perm = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE_UNCHANGED; if (resizable) { shared_perm |= BLK_PERM_RESIZE; } diff --git a/include/block/block.h b/include/block/block.h index e5dd22b034..9d4050220b 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -269,12 +269,13 @@ enum { BLK_PERM_RESIZE = 0x08, /** - * This permission is required to change the node that this BdrvChild - * points to. + * There was a now-removed bit BLK_PERM_GRAPH_MOD, with value of 0x10. QEMU + * 6.1 and earlier may still lock the corresponding byte in block/file-posix + * locking. So, implementing some new permission should be very careful to + * not interfere with this old unused thing. */ - BLK_PERM_GRAPH_MOD = 0x10, - BLK_PERM_ALL = 0x1f, + BLK_PERM_ALL = 0x0f, DEFAULT_PERM_PASSTHROUGH = BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE diff --git a/qapi/block-core.json b/qapi/block-core.json index bd0b285245..9a5a3641d0 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1878,14 +1878,11 @@ # # @resize: This permission is required to change the size of a block node. # -# @graph-mod: This permission is required to change the node that this -# BdrvChild points to. -# # Since: 4.0 ## { 'enum': 'BlockPermission', - 'data': [ 'consistent-read', 'write', 'write-unchanged', 'resize', - 'graph-mod' ] } + 'data': [ 'consistent-read', 'write', 'write-unchanged', 'resize' ] } + ## # @XDbgBlockGraphEdge: # diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py index da6acf050d..42288a3cfb 100755 --- a/scripts/render_block_graph.py +++ b/scripts/render_block_graph.py @@ -35,7 +35,6 @@ def perm(arr): s = 'w' if 'write' in arr else '_' s += 'r' if 'consistent-read' in arr else '_' s += 'u' if 'write-unchanged' in arr else '_' - s += 'g' if 'graph-mod' in arr else '_' s += 's' if 'resize' in arr else '_' return s diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out index 4e840b6730..6a74a8138b 100644 --- a/tests/qemu-iotests/273.out +++ b/tests/qemu-iotests/273.out @@ -204,7 +204,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev "name": "file", "parent": 5, "shared-perm": [ - "graph-mod", "write-unchanged", "consistent-read" ], @@ -219,7 +218,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev "name": "backing", "parent": 5, "shared-perm": [ - "graph-mod", "resize", "write-unchanged", "write", @@ -233,7 +231,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev "name": "file", "parent": 3, "shared-perm": [ - "graph-mod", "write-unchanged", "consistent-read" ], @@ -246,7 +243,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev "name": "backing", "parent": 3, "shared-perm": [ - "graph-mod", "resize", "write-unchanged", "write", From e5e748739562268ef4063ee77bf53ad7040b25c7 Mon Sep 17 00:00:00 2001 From: Vladimir Sementsov-Ogievskiy Date: Fri, 10 Dec 2021 21:14:50 +0100 Subject: [PATCH 508/730] iotests/testrunner.py: refactor test_field_width A lot of Optional[] types doesn't make code beautiful. test_field_width defaults to 8, but that is never used in the code. More over, if we want some default behavior for single call of test_run(), it should just print the whole test name, not limiting or expanding its width, so 8 is bad default. So, just drop the default as unused for now. Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20211210201450.101576-1-vsementsov@virtuozzo.com> Reviewed-by: John Snow Signed-off-by: Kevin Wolf --- tests/qemu-iotests/testrunner.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/tests/qemu-iotests/testrunner.py b/tests/qemu-iotests/testrunner.py index 0feaa396d0..15788f919e 100644 --- a/tests/qemu-iotests/testrunner.py +++ b/tests/qemu-iotests/testrunner.py @@ -174,19 +174,17 @@ class TestRunner(ContextManager['TestRunner']): def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None: self._stack.close() - def test_print_one_line(self, test: str, starttime: str, + def test_print_one_line(self, test: str, + test_field_width: int, + starttime: str, endtime: Optional[str] = None, status: str = '...', lasttime: Optional[float] = None, thistime: Optional[float] = None, description: str = '', - test_field_width: Optional[int] = None, end: str = '\n') -> None: """ Print short test info before/after test run """ test = os.path.basename(test) - if test_field_width is None: - test_field_width = 8 - if self.makecheck and status != '...': if status and status != 'pass': status = f' [{status}]' @@ -328,7 +326,7 @@ class TestRunner(ContextManager['TestRunner']): casenotrun=casenotrun) def run_test(self, test: str, - test_field_width: Optional[int] = None, + test_field_width: int, mp: bool = False) -> TestResult: """ Run one test and print short status @@ -347,20 +345,21 @@ class TestRunner(ContextManager['TestRunner']): if not self.makecheck: self.test_print_one_line(test=test, + test_field_width=test_field_width, status = 'started' if mp else '...', starttime=start, lasttime=last_el, - end = '\n' if mp else '\r', - test_field_width=test_field_width) + end = '\n' if mp else '\r') res = self.do_run_test(test, mp) end = datetime.datetime.now().strftime('%H:%M:%S') - self.test_print_one_line(test=test, status=res.status, + self.test_print_one_line(test=test, + test_field_width=test_field_width, + status=res.status, starttime=start, endtime=end, lasttime=last_el, thistime=res.elapsed, - description=res.description, - test_field_width=test_field_width) + description=res.description) if res.casenotrun: print(res.casenotrun) From 8d7ebae4803611ebd03096fc4804396add52ec62 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 15 Jan 2022 14:24:36 +0000 Subject: [PATCH 509/730] roms/openbios: update OpenBIOS images to 04dfc98 built from submodule Signed-off-by: Mark Cave-Ayland --- pc-bios/openbios-ppc | Bin 696912 -> 697088 bytes pc-bios/openbios-sparc32 | Bin 382048 -> 382048 bytes pc-bios/openbios-sparc64 | Bin 1593408 -> 1593408 bytes roms/openbios | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc index 67f32a8602e368a2485ec463cf6c8a96da77b46d..5f35274cbea022fe42b8f163c632a029cde11c21 100644 GIT binary patch delta 123967 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

    ;1 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ఐ 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

  • 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 iQ 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%0DIRwW-m}j_Ot8Y(Oq{Q+z$ibZ`ln*cL#ZV za+iRjd^a&Zeg|eb_H?Q{RCEpf+^&6dhYrn8TocH~Prw5G7*6KzxOV@SUi*B+hr15% zJ?8O|tUS1%nTn)z-~91CM@}B*pn>?|FMbqrgCE1Z z7wc;aR(;u}6Q{1bY~s`ge6!LFKE&@ab4TWmAKb^HGy0p3R;T#AV`Ac++a`6n>C61h z;^99e7C9X_d{Jn<%@VDWK zZTZul`jn^g^N=S`oVo`eRlvW;J$YUq{@&gx|FS1O`YHUd{QaHsM?K+jPveK>pLtRX z2R~;JQq26yQzlOR9X`C@{rf@a&ztdiCq7#+7k?Ypmp=Y2uD1i<&%)=`@tf@~#(LFG ze4ZBb_LqNb;?$S^$;7D>`2DI^Oq{ytl@q7F0-rbI_j~aBEx7&=J|D*KkK^|vzhmOm z0et>0+CLF(pNY>V%$Yy*ofD_-#`P=kc{6^m`w6Uv{rD)(#N$nG#`+pQ??t`u{z-hl z-1Uy(`%Q6u>OPaFK>OHu>OUZiX5yKEG&%XN8`k6hB*lx*eXTo=4;95`UD)p6G!M52uv7Hrv@-9mj!gu&SrwT~4}w`@ah(^_CD!X;-g| zkITD!m{wnXY+Lwgxh`oT_id`Z+pXX2%h#jU)a6MdD@cmiSNCpSx4bgu?$NYgGP516 zMyXD$4AT&XX&iKHaCLYC*8c%Fo|<_WeoW15(0^ZBFb`D;O~p(!AYV_-4BuTX7o5;8 zSOA*K+5KQ