Re: [PATCH 4/4] ui: Fix gtk/gl when the scaled virtual console does not fit the window

2021-12-20 Thread Marc-André Lureau
Hi

On Sun, Dec 19, 2021 at 6:32 AM Alexander Orzechowski <
orzechowski.alexan...@gmail.com> wrote:

> gtk/gl was incorrectly always rendering as if the 'Zoom to Fit' was
> always checked even if it wasn't. This is now using logic closer
> to what is being used for the existing cairo code paths.
>
> Signed-off-by: Alexander Orzechowski 
>

This doesn't work as expected, the display is not being centered correctly.

---
>  ui/gtk-gl-area.c | 34 +-
>  1 file changed, 29 insertions(+), 5 deletions(-)
>
> diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
> index 01e4e74ee3..ea72f1817b 100644
> --- a/ui/gtk-gl-area.c
> +++ b/ui/gtk-gl-area.c
> @@ -41,16 +41,40 @@ void gd_gl_area_draw(VirtualConsole *vc)
>  #ifdef CONFIG_GBM
>  QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
>  #endif
> +GtkDisplayState *s = vc->s;
>  int ww, wh, ws, y1, y2;
> +int mx, my;
> +int fbh, fbw;
>
>  if (!vc->gfx.gls) {
>  return;
>  }
>
>  gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area));
> +
> +fbw = surface_width(vc->gfx.ds);
> +fbh = surface_height(vc->gfx.ds);
> +
>  ws =
> gdk_window_get_scale_factor(gtk_widget_get_window(vc->gfx.drawing_area));
> -ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area) * ws;
> -wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area) * ws;
> +ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area);
> +wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area);
> +
> +if (s->full_screen) {
> +vc->gfx.scale_x = (double)ww / fbw;
> +vc->gfx.scale_y = (double)wh / fbh;
> +} else if (s->free_scale) {
> +double sx, sy;
> +
> +sx = (double)ww / fbw;
> +sy = (double)wh / fbh;
> +
> +vc->gfx.scale_x = vc->gfx.scale_y = MIN(sx, sy);
> +}
> +
> +fbw *= vc->gfx.scale_x * ws;
> +fbh *= vc->gfx.scale_y * ws;
> +mx = (ww * ws - fbw) / 2;
> +my = (wh * ws - fbh) / 2;
>
>  if (vc->gfx.scanout_mode) {
>  if (!vc->gfx.guest_fb.framebuffer) {
> @@ -70,11 +94,11 @@ void gd_gl_area_draw(VirtualConsole *vc)
>  glBindFramebuffer(GL_READ_FRAMEBUFFER,
> vc->gfx.guest_fb.framebuffer);
>  /* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */
>
> -glViewport(0, 0, ww, wh);
> +glViewport(mx, my, fbw, fbh);
>  y1 = vc->gfx.y0_top ? 0 : vc->gfx.h;
>  y2 = vc->gfx.y0_top ? vc->gfx.h : 0;
>  glBlitFramebuffer(0, y1, vc->gfx.w, y2,
> -  0, 0, ww, wh,
> +  mx, my, fbw, fbh,
>GL_COLOR_BUFFER_BIT, GL_NEAREST);
>  #ifdef CONFIG_GBM
>  if (dmabuf) {
> @@ -98,7 +122,7 @@ void gd_gl_area_draw(VirtualConsole *vc)
>  }
>  gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area));
>
> -surface_gl_setup_viewport(vc->gfx.gls, vc->gfx.ds, ww, wh);
> +glViewport(mx, my, fbw, fbh);
>  surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds);
>  }
>
> --
> 2.34.1
>
>
>

-- 
Marc-André Lureau


[PULL v2 33/36] option: add g_auto for QemuOpts

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

Used in the next commit.

Signed-off-by: Marc-André Lureau 
Acked-by: Gerd Hoffmann 
---
 include/qemu/option.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/qemu/option.h b/include/qemu/option.h
index 306bf0757509..bbd86e1c4eab 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -150,4 +150,6 @@ QDict *keyval_parse(const char *params, const char 
*implied_key,
 bool *help, Error **errp);
 void keyval_merge(QDict *old, const QDict *new, Error **errp);
 
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(QemuOpts, qemu_opts_del)
+
 #endif
-- 
2.34.1.8.g35151cf07204




Re: [PATCH 2/4] ui: Remove unnecessary checks

2021-12-20 Thread Marc-André Lureau
Hi

On Sun, Dec 19, 2021 at 6:32 AM Alexander Orzechowski <
orzechowski.alexan...@gmail.com> wrote:

> These conditionals should never be false as scale_x and scale_y should
> scale the fbw and fbh variables such that the ww and wh variables always
> have a greater magnitude.
>
> Signed-off-by: Alexander Orzechowski 
>

I don't understand how you reached that conclusion.

scale_x/scale_y can have various values, from 0.25 manually, or pretty much
anything in freescale.

Just adding a breakpoint/debug there and you can see they can be false.

---
>  ui/gtk.c | 27 ++-
>  1 file changed, 6 insertions(+), 21 deletions(-)
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index 824334ff3d..f2d74b253d 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -416,13 +416,8 @@ static void gd_update(DisplayChangeListener *dcl,
>  ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area);
>  wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area);
>
> -mx = my = 0;
> -if (ww > fbw) {
> -mx = (ww - fbw) / 2;
> -}
> -if (wh > fbh) {
> -my = (wh - fbh) / 2;
> -}
> +mx = (ww - fbw) / 2;
> +my = (wh - fbh) / 2;
>
>  gtk_widget_queue_draw_area(vc->gfx.drawing_area,
> mx + x1, my + y1, (x2 - x1), (y2 - y1));
> @@ -801,13 +796,8 @@ static gboolean gd_draw_event(GtkWidget *widget,
> cairo_t *cr, void *opaque)
>  fbw *= vc->gfx.scale_x;
>  fbh *= vc->gfx.scale_y;
>
> -mx = my = 0;
> -if (ww > fbw) {
> -mx = (ww - fbw) / 2;
> -}
> -if (wh > fbh) {
> -my = (wh - fbh) / 2;
> -}
> +mx = (ww - fbw) / 2;
> +my = (wh - fbh) / 2;
>
>  cairo_rectangle(cr, 0, 0, ww, wh);
>
> @@ -850,13 +840,8 @@ static gboolean gd_motion_event(GtkWidget *widget,
> GdkEventMotion *motion,
>  ws = gdk_window_get_scale_factor(
>  gtk_widget_get_window(vc->gfx.drawing_area));
>
> -mx = my = 0;
> -if (ww > fbw) {
> -mx = (ww - fbw) / 2;
> -}
> -if (wh > fbh) {
> -my = (wh - fbh) / 2;
> -}
> +mx = (ww - fbw) / 2;
> +my = (wh - fbh) / 2;
>
>  x = (motion->x - mx) / vc->gfx.scale_x * ws;
>  y = (motion->y - my) / vc->gfx.scale_y * ws;
> --
> 2.34.1
>
>
>

-- 
Marc-André Lureau


Re: [PATCH v4 3/3] target/riscv: Implement the stval/mtval illegal instruction

2021-12-20 Thread Bin Meng
On Mon, Dec 20, 2021 at 2:49 PM Alistair Francis
 wrote:
>
> From: Alistair Francis 
>
> 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 
> ---
>  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 0760c0af93..3a163b57ed 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -127,6 +127,8 @@ struct CPURISCVState {
>  target_ulong frm;
>
>  target_ulong badaddr;
> +uint32_t bins;

nits: does "badins" sound a better name? I took some time to figure
out what "bins" means :)

> +
>  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 9e1f5ee177..f76ba834e6 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -1007,6 +1007,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 24251bc8cc..921ca06bf9 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -167,6 +167,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);
>  }
>

Otherwise,
Reviewed-by: Bin Meng 



[PULL v2 28/36] tests: start dbus-display-test

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 ..43c77aff045c
--- /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, );
+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, );
+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(, );
+
+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,
+));
+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, );
+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;
+ 

Re: [PATCH v4 2/3] target/riscv: Fixup setting GVA

2021-12-20 Thread Bin Meng
On Mon, Dec 20, 2021 at 2:49 PM Alistair Francis
 wrote:
>
> From: Alistair Francis 
>
> In preperation for adding support for the illegal instruction address

typo: preparation

> let's fixup the Hypervisor extension setting GVA logic and improve the
> variable names.
>
> Signed-off-by: Alistair Francis 
> ---
>  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 9eeed38c7e..9e1f5ee177 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -967,6 +967,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>
>  RISCVCPU *cpu = RISCV_CPU(cs);
>  CPURISCVState *env = >env;
> +bool write_gva = false;
>  uint64_t s;
>
>  /* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
> @@ -975,7 +976,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;
> @@ -1004,7 +1004,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:
> @@ -1041,18 +1041,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 */
>  /*
> @@ -1063,7 +1051,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);
> @@ -1072,6 +1060,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);
> @@ -1079,7 +1068,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);

This does not look correct to me.

The env->hstatus[GVA] should remain untouched in the 2nd and 3rd
branch. It only needs to be set in the first branch.

>  }
>
>  s = env->mstatus;

Regards,
Bin



[PULL v2 25/36] ui: add a D-Bus display backend

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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   methodh -   -
.SetUIInfo  methodqqiiuu-   -
.DeviceAddress  property  s "pci//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 
---
 meson.build   |  11 +
 qapi/ui.json  |  27 +-
 include/qemu/dbus.h   |  19 ++
 ui/dbus.h |  83 ++
 ui/dbus-console.c | 497 ++
 ui/dbus-error.c   |  48 
 ui/dbus-listener.c| 486 +
 ui/dbus.c | 262 ++
 meson_options.txt |   2 +
 qemu-options.hx   |  15 +
 scripts/meson-buildoptions.sh |   3 +
 ui/dbus-display1.xml  | 378 ++
 ui/meson.build|  22 ++
 ui/trace-events   |  11 +
 14 files changed, 1862 insertions(+), 2 deletions(-)
 create mode 100644 ui/dbus.h
 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

diff --git a/meson.build b/meson.build
index c37eb92ebeaa..73d4b241df1a 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/qapi/ui.json b/qapi/ui.json
index d7567ac86683..80855328b1d4 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' } }
+
  ##
  # 

Re: [PATCH 1/4] ui: Use allocated size instead of window size

2021-12-20 Thread Marc-André Lureau
Hi

On Sun, Dec 19, 2021 at 6:33 AM Alexander Orzechowski <
orzechowski.alexan...@gmail.com> wrote:

> In these cases, we only care about the size of the virtual console
> itself. Previously, these calculations were made using the size of
> the entire window, which would include the size of the virtual console
> plus all the ui elements around it.
>
> Signed-off-by: Alexander Orzechowski 
>

It's not obvious to me that the drawing area doesn't have its own window.

Nonetheless, it is better to use the allocated size.

Reviewed-by: Marc-André Lureau 

---
>  ui/gtk.c | 26 ++
>  1 file changed, 10 insertions(+), 16 deletions(-)
>
> diff --git a/ui/gtk.c b/ui/gtk.c
> index 428f02f2df..824334ff3d 100644
> --- a/ui/gtk.c
> +++ b/ui/gtk.c
> @@ -340,8 +340,8 @@ static void gd_update_full_redraw(VirtualConsole *vc)
>  {
>  GtkWidget *area = vc->gfx.drawing_area;
>  int ww, wh;
> -ww = gdk_window_get_width(gtk_widget_get_window(area));
> -wh = gdk_window_get_height(gtk_widget_get_window(area));
> +ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area);
> +wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area);
>  #if defined(CONFIG_OPENGL)
>  if (vc->gfx.gls && gtk_use_gl_area) {
>  gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area));
> @@ -387,7 +387,6 @@ static void gd_update(DisplayChangeListener *dcl,
>int x, int y, int w, int h)
>  {
>  VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
> -GdkWindow *win;
>  int x1, x2, y1, y2;
>  int mx, my;
>  int fbw, fbh;
> @@ -414,12 +413,8 @@ static void gd_update(DisplayChangeListener *dcl,
>  fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
>  fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
>
> -win = gtk_widget_get_window(vc->gfx.drawing_area);
> -if (!win) {
> -return;
> -}
> -ww = gdk_window_get_width(win);
> -wh = gdk_window_get_height(win);
> +ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area);
> +wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area);
>
>  mx = my = 0;
>  if (ww > fbw) {
> @@ -788,8 +783,8 @@ static gboolean gd_draw_event(GtkWidget *widget,
> cairo_t *cr, void *opaque)
>  fbw = surface_width(vc->gfx.ds);
>  fbh = surface_height(vc->gfx.ds);
>
> -ww = gdk_window_get_width(gtk_widget_get_window(widget));
> -wh = gdk_window_get_height(gtk_widget_get_window(widget));
> +ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area);
> +wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area);
>
>  if (s->full_screen) {
>  vc->gfx.scale_x = (double)ww / fbw;
> @@ -838,7 +833,6 @@ static gboolean gd_motion_event(GtkWidget *widget,
> GdkEventMotion *motion,
>  {
>  VirtualConsole *vc = opaque;
>  GtkDisplayState *s = vc->s;
> -GdkWindow *window;
>  int x, y;
>  int mx, my;
>  int fbh, fbw;
> @@ -851,10 +845,10 @@ static gboolean gd_motion_event(GtkWidget *widget,
> GdkEventMotion *motion,
>  fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x;
>  fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y;
>
> -window = gtk_widget_get_window(vc->gfx.drawing_area);
> -ww = gdk_window_get_width(window);
> -wh = gdk_window_get_height(window);
> -ws = gdk_window_get_scale_factor(window);
> +ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area);
> +wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area);
> +ws = gdk_window_get_scale_factor(
> +gtk_widget_get_window(vc->gfx.drawing_area));
>
>  mx = my = 0;
>  if (ww > fbw) {
> --
> 2.34.1
>
>
>

-- 
Marc-André Lureau


[PULL v2 20/36] docs/sphinx: add sphinx modules to include D-Bus documentation

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 763e7d243448..e79015975e6a 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -73,6 +73,12 @@
 # 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_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 ..be284ed08fd7
--- /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": 

Re: [PATCH v4 1/3] target/riscv: Set the opcode in DisasContext

2021-12-20 Thread Bin Meng
On Mon, Dec 20, 2021 at 2:49 PM Alistair Francis
 wrote:
>
> From: Alistair Francis 
>
> Signed-off-by: Alistair Francis 
> Reviewed-by: Richard Henderson 
> ---
>  target/riscv/translate.c | 2 ++
>  1 file changed, 2 insertions(+)
>

I remember I once reviewed the whole series. Not sure what changed in
the versions

Reviewed-by: Bin Meng 



[PULL v2 32/36] chardev: make socket derivable

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
Acked-by: Gerd Hoffmann 
Reviewed-by: Philippe Mathieu-Daudé 
---
 include/chardev/char-socket.h | 84 +++
 chardev/char-socket.c | 58 +---
 2 files changed, 85 insertions(+), 57 deletions(-)
 create mode 100644 include/chardev/char-socket.h

diff --git a/include/chardev/char-socket.h b/include/chardev/char-socket.h
new file mode 100644
index ..1a9274f2e3ac
--- /dev/null
+++ b/include/chardev/char-socket.h
@@ -0,0 +1,84 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-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.
+ */
+#ifndef CHAR_SOCKET_H_
+#define CHAR_SOCKET_H_
+
+#include "io/channel-socket.h"
+#include "io/channel-tls.h"
+#include "io/net-listener.h"
+#include "chardev/char.h"
+#include "qom/object.h"
+
+#define TCP_MAX_FDS 16
+
+typedef struct {
+char buf[21];
+size_t buflen;
+} TCPChardevTelnetInit;
+
+typedef enum {
+TCP_CHARDEV_STATE_DISCONNECTED,
+TCP_CHARDEV_STATE_CONNECTING,
+TCP_CHARDEV_STATE_CONNECTED,
+} TCPChardevState;
+
+struct SocketChardev {
+Chardev parent;
+QIOChannel *ioc; /* Client I/O channel */
+QIOChannelSocket *sioc; /* Client master channel */
+QIONetListener *listener;
+GSource *hup_source;
+QCryptoTLSCreds *tls_creds;
+char *tls_authz;
+TCPChardevState state;
+int max_size;
+int do_telnetopt;
+int do_nodelay;
+int *read_msgfds;
+size_t read_msgfds_num;
+int *write_msgfds;
+size_t write_msgfds_num;
+bool registered_yank;
+
+SocketAddress *addr;
+bool is_listen;
+bool is_telnet;
+bool is_tn3270;
+GSource *telnet_source;
+TCPChardevTelnetInit *telnet_init;
+
+bool is_websock;
+
+GSource *reconnect_timer;
+int64_t reconnect_time;
+bool connect_err_reported;
+
+QIOTask *connect_task;
+};
+typedef struct SocketChardev SocketChardev;
+
+DECLARE_INSTANCE_CHECKER(SocketChardev, SOCKET_CHARDEV,
+ TYPE_CHARDEV_SOCKET)
+
+#endif /* CHAR_SOCKET_H_ */
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index a2b02e021d6b..d619088232d3 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -25,9 +25,7 @@
 #include "qemu/osdep.h"
 #include "chardev/char.h"
 #include "io/channel-socket.h"
-#include "io/channel-tls.h"
 #include "io/channel-websock.h"
-#include "io/net-listener.h"
 #include "qemu/error-report.h"
 #include "qemu/module.h"
 #include "qemu/option.h"
@@ -37,61 +35,7 @@
 #include "qemu/yank.h"
 
 #include "chardev/char-io.h"
-#include "qom/object.h"
-
-/***/
-/* TCP Net console */
-
-#define TCP_MAX_FDS 16
-
-typedef struct {
-char buf[21];
-size_t buflen;
-} TCPChardevTelnetInit;
-
-typedef enum {
-TCP_CHARDEV_STATE_DISCONNECTED,
-TCP_CHARDEV_STATE_CONNECTING,
-TCP_CHARDEV_STATE_CONNECTED,
-} TCPChardevState;
-
-struct SocketChardev {
-Chardev parent;
-QIOChannel *ioc; /* Client I/O channel */
-QIOChannelSocket *sioc; /* Client master channel */
-QIONetListener *listener;
-GSource *hup_source;
-QCryptoTLSCreds *tls_creds;
-char *tls_authz;
-TCPChardevState state;
-int max_size;
-int do_telnetopt;
-int do_nodelay;
-int *read_msgfds;
-size_t read_msgfds_num;
-int *write_msgfds;
-size_t write_msgfds_num;
-bool registered_yank;
-
-SocketAddress *addr;
-bool is_listen;
-bool is_telnet;
-bool is_tn3270;
-GSource *telnet_source;
-TCPChardevTelnetInit *telnet_init;
-
-bool is_websock;
-
-GSource *reconnect_timer;
-int64_t reconnect_time;
-bool connect_err_reported;
-
-QIOTask *connect_task;
-};
-typedef struct SocketChardev SocketChardev;
-
-DECLARE_INSTANCE_CHECKER(SocketChardev, SOCKET_CHARDEV,
- TYPE_CHARDEV_SOCKET)
+#include 

[PULL v2 19/36] scripts: teach modinfo to skip non-C sources

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 4acb188c3e89..61b90688c6dc 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)
-- 
2.34.1.8.g35151cf07204




[PULL v2 36/36] MAINTAINERS: update D-Bus section

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 1de6ce6e44eb..dc4b6f7c1e06 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 
-- 
2.34.1.8.g35151cf07204




[PULL v2 35/36] ui/dbus: register D-Bus VC handler

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 41f1716f255a..b2c1c9fb522c 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(_vc_type_info);
 }
 
 static void
-- 
2.34.1.8.g35151cf07204




[PULL v2 29/36] audio: add "dbus" audio backend

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 
---
 qapi/audio.json|   3 +-
 qapi/ui.json   |   5 +-
 audio/audio_int.h  |   7 +
 audio/audio_template.h |   2 +
 ui/dbus.h  |   1 +
 audio/audio.c  |   1 +
 audio/dbusaudio.c  | 654 +
 ui/dbus.c  |  35 +++
 audio/meson.build  |   6 +
 audio/trace-events |   5 +
 qemu-options.hx|   3 +
 ui/dbus-display1.xml   | 211 +
 12 files changed, 931 insertions(+), 2 deletions(-)
 create mode 100644 audio/dbusaudio.c

diff --git a/qapi/audio.json b/qapi/audio.json
index 9cba0df8a4e9..693e327c6b6a 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 d435e9472264..2b4371da3777 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/audio/audio_int.h b/audio/audio_int.h
index 6d685e24a388..428a091d05e5 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 c6714946aaed..d2d348638b8c 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/ui/dbus.h b/ui/dbus.h
index 4698d324632e..ca1f0f4ab94f 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;
diff --git a/audio/audio.c b/audio/audio.c
index 54a153c0ef07..dc28685d226d 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/dbusaudio.c b/audio/dbusaudio.c
new file mode 100644
index ..f178b47deec1
--- /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,
+ * 

[PULL v2 16/36] ui: split the GL context in a different object

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 3ff51b492e5b..fe08b4dd040f 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 9374fe41e32b..c2761d747a4e 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 7d22affd381a..101b147d1b98 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,
 

[PULL v2 31/36] chardev: teach socket to accept no addresses

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

The following patches are going to use CharSocket as a base class for
sockets that are created with a given fd (without a given address).

Signed-off-by: Marc-André Lureau 
Acked-by: Gerd Hoffmann 
---
 chardev/char-socket.c | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 836cfa0bc21b..a2b02e021d6b 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -1248,6 +1248,10 @@ static int qmp_chardev_open_socket_server(Chardev *chr,
 qio_net_listener_set_name(s->listener, name);
 g_free(name);
 
+if (s->addr->type == SOCKET_ADDRESS_TYPE_FD && !*s->addr->u.fd.str) {
+goto skip_listen;
+}
+
 if (qio_net_listener_open_sync(s->listener, s->addr, 1, errp) < 0) {
 object_unref(OBJECT(s->listener));
 s->listener = NULL;
@@ -1256,6 +1260,8 @@ static int qmp_chardev_open_socket_server(Chardev *chr,
 
 qapi_free_SocketAddress(s->addr);
 s->addr = socket_local_address(s->listener->sioc[0]->fd, errp);
+
+skip_listen:
 update_disconnected_filename(s);
 
 if (is_waitconnect) {
@@ -1466,9 +1472,9 @@ static void qemu_chr_parse_socket(QemuOpts *opts, 
ChardevBackend *backend,
 SocketAddressLegacy *addr;
 ChardevSocket *sock;
 
-if ((!!path + !!fd + !!host) != 1) {
+if ((!!path + !!fd + !!host) > 1) {
 error_setg(errp,
-   "Exactly one of 'path', 'fd' or 'host' required");
+   "None or one of 'path', 'fd' or 'host' option required.");
 return;
 }
 
@@ -1542,12 +1548,10 @@ static void qemu_chr_parse_socket(QemuOpts *opts, 
ChardevBackend *backend,
 .has_ipv6 = qemu_opt_get(opts, "ipv6"),
 .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
 };
-} else if (fd) {
+} else {
 addr->type = SOCKET_ADDRESS_TYPE_FD;
 addr->u.fd.data = g_new(String, 1);
 addr->u.fd.data->str = g_strdup(fd);
-} else {
-g_assert_not_reached();
 }
 sock->addr = addr;
 }
-- 
2.34.1.8.g35151cf07204




[PULL v2 30/36] ui/dbus: add clipboard interface

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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.h|  14 ++
 ui/dbus-clipboard.c  | 457 +++
 ui/dbus.c|   7 +
 ui/dbus-display1.xml |  97 +
 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.h b/ui/dbus.h
index ca1f0f4ab94f..3e89eafcab6e 100644
--- a/ui/dbus.h
+++ b/ui/dbus.h
@@ -27,9 +27,16 @@
 #include "qemu/dbus.h"
 #include "qom/object.h"
 #include "ui/console.h"
+#include "ui/clipboard.h"
 
 #include "dbus-display1.h"
 
+typedef struct DBusClipboardRequest {
+GDBusMethodInvocation *invocation;
+QemuClipboardType type;
+guint timeout_id;
+} DBusClipboardRequest;
+
 struct DBusDisplay {
 Object parent;
 
@@ -44,6 +51,11 @@ struct DBusDisplay {
 QemuDBusDisplay1VM *iface;
 GPtrArray *consoles;
 GCancellable *add_client_cancellable;
+
+QemuClipboardPeer clipboard_peer;
+QemuDBusDisplay1Clipboard *clipboard;
+QemuDBusDisplay1Clipboard *clipboard_proxy;
+DBusClipboardRequest clipboard_request[QEMU_CLIPBOARD_SELECTION__COUNT];
 };
 
 #define TYPE_DBUS_DISPLAY "dbus-display"
@@ -83,4 +95,6 @@ dbus_display_listener_get_bus_name(DBusDisplayListener *ddl);
 extern const DisplayChangeListenerOps dbus_gl_dcl_ops;
 extern const DisplayChangeListenerOps dbus_dcl_ops;
 
+void dbus_clipboard_init(DBusDisplay *dpy);
+
 #endif /* UI_DBUS_H_ */
diff --git a/ui/dbus-clipboard.c b/ui/dbus-clipboard.c
new file mode 100644
index ..5843d26cd2cb
--- /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 == >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 = >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(>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,
+ 

[PULL v2 26/36] ui/dbus: add p2p=on/off option

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 
---
 qapi/misc.json|   4 +-
 qapi/ui.json  |   6 ++-
 include/qemu/cutils.h |   5 ++
 include/ui/dbus-display.h |  17 ++
 include/ui/dbus-module.h  |  11 
 ui/dbus.h |   2 +
 monitor/qmp-cmds.c|  13 +
 ui/dbus-console.c |   2 +-
 ui/dbus-listener.c|   2 +-
 ui/dbus-module.c  |  35 
 ui/dbus.c | 109 --
 qemu-options.hx   |   6 ++-
 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/qapi/misc.json b/qapi/misc.json
index 358548abe1ad..e8054f415b21 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=)
+# @protocol: protocol name. Valid names are "vnc", "spice", "@dbus-display" or
+#the name of a character device (eg. from -chardev id=)
 #
 # @fdname: file descriptor name previously passed via 'getfd' command
 #
diff --git a/qapi/ui.json b/qapi/ui.json
index 80855328b1d4..d435e9472264 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/include/qemu/cutils.h b/include/qemu/cutils.h
index 986ed8e15f41..320543950c4c 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 ..88f153c2371d
--- /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 ..ace4a17a5c25
--- /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/ui/dbus.h b/ui/dbus.h
index d3c9598dd133..4698d324632e 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/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index 343353e27a7a..14e3beeaafcf 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);
+   

[PULL v2 22/36] docs: move D-Bus VMState documentation to source XML

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 
---
 docs/interop/dbus-vmstate.rst | 52 ++-
 backends/dbus-vmstate1.xml| 42 +++-
 2 files changed, 49 insertions(+), 45 deletions(-)

diff --git a/docs/interop/dbus-vmstate.rst b/docs/interop/dbus-vmstate.rst
index 1d719c1c604f..5fb3f279e280 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
-=
-
-On object path ``/org/qemu/VMState1``, the following
-``org.qemu.VMState1`` interface should be implemented:
-
-.. code:: xml
-
-  
-
-
-  
-
-
-  
-
-  
-
-"Id" property
--
-
-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.
+.. only:: sphinx4
 
-The helper may be initially started in a waiting state (with
-an --incoming argument for example), and it may resume on success.
+   .. dbus-doc:: backends/dbus-vmstate1.xml
 
-An error may be returned to the caller.
+.. only:: not sphinx4
 
-Save(out u8[] bytes) method

+   .. warning::
+  Sphinx 4 is required to build D-Bus documentation.
 
-The method called on the source to get the current state to be
-migrated. The helper should continue to run normally.
+  This is the content of ``backends/dbus-vmstate1.xml``:
 
-An error may be returned to the caller.
+   .. literalinclude:: ../../backends/dbus-vmstate1.xml
+  :language: xml
diff --git a/backends/dbus-vmstate1.xml b/backends/dbus-vmstate1.xml
index cc8563be4c92..601ee8dc7e4d 100644
--- a/backends/dbus-vmstate1.xml
+++ b/backends/dbus-vmstate1.xml
@@ -1,10 +1,50 @@
-
+
 http://www.freedesktop.org/dbus/1.0/doc.dtd;>
+  
   
+
+
 
+
+
 
   
 
+
+
 
   
 
-- 
2.34.1.8.g35151cf07204




[PULL v2 15/36] ui: dispatch GL events to all listeners

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 6f21007737e5..13c0d001c096 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, >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, >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, >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, >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, >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, >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, >listeners, next) {
+dcl->ops->dpy_gl_update(dcl, x, y, w, h);
+}
 graphic_hw_gl_block(con, false);
 }
 
-- 
2.34.1.8.g35151cf07204




[PULL v2 24/36] build-sys: set glib dependency version

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 8ccfe51673eb..51eae49daf7d 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 1c70839bbf17..c37eb92ebeaa 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')
-- 
2.34.1.8.g35151cf07204




[PULL v2 27/36] tests/qtests: add qtest_qmp_add_client()

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 dff6b31cf0ec..a6d38d7ef7fb 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 65ed9496850f..a68326caae98 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, , 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.
-- 
2.34.1.8.g35151cf07204




[PULL v2 18/36] console: save current scanout details

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 eefd7e4dc1f4..f590819880b5 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 78583df92035..40eebb6d2cc2 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, 

[PULL v2 11/36] ui: associate GL context outside of display listener registration

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 7b83e6cdea77..87f897e46dc4 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 a26a2520c496..08327c40c6ee 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 = _ops;
 edpy->gls = qemu_gl_init_shader();
+qemu_console_set_display_gl_ctx(con, >dcl);
 register_displaychangelistener(>dcl);
 }
 }
diff --git a/ui/gtk.c b/ui/gtk.c
index c0d8a9f061ee..25896023ffe7 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, >gfx.dcl);
+}
 register_displaychangelistener(>gfx.dcl);
 
 gd_connect_vc_gfx_signals(vc);
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 9ba3bc49e798..bb186a381acd 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, _console[i].dcl);
+}
 register_displaychangelistener(_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 52d9f3260aab..2c204bceee27 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, >dcl);
+}
 register_displaychangelistener(>dcl);
 }
 
-- 
2.34.1.8.g35151cf07204




[PULL v2 21/36] backends: move dbus-vmstate1.xml to backends/

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 ebeac59b3f95..913e987409d5 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',
-- 
2.34.1.8.g35151cf07204




[PULL v2 23/36] docs: add dbus-display documentation

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 ..8c6e8e0f5a82
--- /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 be596d3f418c..427debc9c504 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 47b9ed82bbc0..c59bac983407 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 ..e69de29bb2d1
-- 
2.34.1.8.g35151cf07204




[PULL v2 17/36] ui: move qemu_spice_fill_device_address to ui/util.c

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

Other backends can use it.

Signed-off-by: Marc-André Lureau 
Acked-by: Gerd Hoffmann 
---
 include/ui/console.h   |  6 +++
 include/ui/spice-display.h |  4 --
 hw/display/qxl.c   |  7 +++-
 ui/spice-core.c| 50 -
 ui/spice-display.c |  5 ++-
 ui/util.c  | 75 ++
 ui/meson.build |  1 +
 7 files changed, 92 insertions(+), 56 deletions(-)
 create mode 100644 ui/util.c

diff --git a/include/ui/console.h b/include/ui/console.h
index fe08b4dd040f..eefd7e4dc1f4 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 a2fbf62c528e..e271e011da1a 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/hw/display/qxl.c b/hw/display/qxl.c
index 29c80b4289b7..e2d6e317da5d 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),
+ )) {
 spice_qxl_set_device_info(>ssd.qxl,
   device_address,
   0,
   qxl->max_outputs);
+} else {
+error_report_err(err);
 }
 #endif
 
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 31974b8d6c44..c3ac20ad4306 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",
-   _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/", 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 798e0f6167e7..1043f47f9456 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(>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, 

[PULL v2 06/36] ui/clipboard: add a clipboard reset serial event

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

Signed-off-by: Marc-André Lureau 
Acked-by: Gerd Hoffmann 
---
 include/ui/clipboard.h |  9 +
 ui/clipboard.c |  7 +++
 ui/gtk-clipboard.c |  3 +++
 ui/vdagent.c   | 12 
 ui/vnc-clipboard.c |  3 +++
 ui/cocoa.m |  3 +++
 6 files changed, 37 insertions(+)

diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h
index 2c6488c1eec8..ce76aa451f64 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 ffbd80e5c60e..82572ea1169b 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(_notifiers, );
+}
+
 void qemu_clipboard_set_data(QemuClipboardPeer *peer,
  QemuClipboardInfo *info,
  QemuClipboardType type,
diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c
index 44ff810234ff..e0b8b283fef8 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 b4fdae69177f..7ea4bc5d9a26 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 6a0b1058840e..d48f75eb1ab4 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;
 }
 }
 
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 6640a2e80ebb..7ca429fa8078 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;
 }
 }
 
-- 
2.34.1.8.g35151cf07204




[PULL v2 10/36] ui: factor out qemu_console_set_display_gl_ctx()

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 65e6bbcab8ae..fb10e6d60cd7 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 dcc21eb5b244..7b83e6cdea77 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) {
-- 
2.34.1.8.g35151cf07204




[PULL v2 14/36] ui: simplify gl unblock & flush

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 
---
 include/ui/console.h |  2 --
 hw/display/vhost-user-gpu.c  |  2 +-
 hw/display/virtio-gpu-base.c |  5 -
 hw/display/virtio-vga.c  | 11 ---
 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/include/ui/console.h b/include/ui/console.h
index fb10e6d60cd7..3ff51b492e5b 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/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index 49df56cd14e9..09818231bd24 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 c8da4806e0bb..fff0fb4a828a 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 9e57f61e9edb..b23a75a04b9d 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/ui/console.c b/ui/console.c
index fcc4fe6a0aa0..6f21007737e5 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 45cb67712df0..e891b61048a8 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -119,8 +119,6 @@ void 

[PULL v2 12/36] ui: make gl_block use a counter

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 87f897e46dc4..39f7b66baf54 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)
-- 
2.34.1.8.g35151cf07204




[PULL v2 03/36] ui: generalize clipboard notifier

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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/gtk-clipboard.c | 20 
 ui/vdagent.c   | 27 ++-
 ui/vnc-clipboard.c | 20 +++-
 ui/vnc.c   |  2 +-
 ui/cocoa.m | 17 +
 7 files changed, 101 insertions(+), 29 deletions(-)

diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h
index 6298986b15c3..d82cf314811c 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 d7b008d62a07..743b39edf424 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(_notifiers, >update);
+notifier_list_add(_notifiers, >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(>update);
+notifier_remove(>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(_notifiers, info);
+notifier_list_notify(_notifiers, );
 
 old = cbinfo[info->selection];
 cbinfo[info->selection] = qemu_clipboard_info_ref(info);
diff --git a/ui/gtk-clipboard.c b/ui/gtk-clipboard.c
index 35b7a2c22838..44ff810234ff 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 == >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(>cbpeer);
 
diff --git 

[PULL v2 08/36] virtio-gpu: use VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 0d87de65d79a..73cb92c8d5c6 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 {
-- 
2.34.1.8.g35151cf07204




[PULL v2 13/36] ui: add a gl-unblock warning timer

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 39f7b66baf54..fcc4fe6a0aa0 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;
 }
 
-- 
2.34.1.8.g35151cf07204




[PULL v2 05/36] ui/clipboard: add qemu_clipboard_check_serial()

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 e590b453c8b7..2c6488c1eec8 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 743b39edf424..ffbd80e5c60e 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 = {
-- 
2.34.1.8.g35151cf07204




[PULL v2 02/36] ui/vdagent: replace #if 0 with protocol version check

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 1f8fc77ee8f3..64e00170017f 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
 };
-- 
2.34.1.8.g35151cf07204




[PULL v2 07/36] hw/display: report an error if virgl initialization failed

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 18d054922fea..0d87de65d79a 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, _gpu_3d_cbs);
 if (ret != 0) {
+error_report("virgl could not be initialized: %d", ret);
 return ret;
 }
 
-- 
2.34.1.8.g35151cf07204




[PULL v2 09/36] ui: do not delay further remote resize

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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/console.c | 5 +++--
 ui/gtk.c | 2 +-
 ui/sdl2.c| 2 +-
 ui/spice-display.c   | 2 +-
 ui/vnc.c | 2 +-
 ui/cocoa.m   | 2 +-
 7 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index 6d678924f6fd..65e6bbcab8ae 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/console.c b/ui/console.c
index 29a3e3f0f51c..dcc21eb5b244 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1538,7 +1538,7 @@ const QemuUIInfo *dpy_get_ui_info(const QemuConsole *con)
 return >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 428f02f2dfe1..c0d8a9f061ee 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(, 0, sizeof(info));
 info.width = width;
 info.height = height;
-dpy_set_ui_info(vc->gfx.dcl.con, );
+dpy_set_ui_info(vc->gfx.dcl.con, , true);
 }
 
 #if defined(CONFIG_OPENGL)
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 17c0ec30ebff..9ba3bc49e798 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -561,7 +561,7 @@ static void handle_windowevent(SDL_Event *ev)
 memset(, 0, sizeof(info));
 info.width = ev->window.data1;
 info.height = ev->window.data2;
-dpy_set_ui_info(scon->dcl.con, );
+dpy_set_ui_info(scon->dcl.con, , true);
 }
 sdl2_redraw(scon);
 break;
diff --git a/ui/spice-display.c b/ui/spice-display.c
index f59c69882d91..52d9f3260aab 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, );
+dpy_set_ui_info(ssd->dcl.con, , false);
 return 1;
 }
 
diff --git a/ui/vnc.c b/ui/vnc.c
index 9b603382e75e..1ed1c7efc688 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(, 0, sizeof(info));
 info.width = w;
 info.height = h;
-dpy_set_ui_info(vs->vd->dcl.con, );
+dpy_set_ui_info(vs->vd->dcl.con, , false);
 vnc_desktop_resize_ext(vs, 4 /* Request forwarded */);
 } else {
 vnc_desktop_resize_ext(vs, 3 /* Invalid screen layout */);
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 7ca429fa8078..69745c483b45 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, );
+dpy_set_ui_info(dcl.con, , TRUE);
 }
 
 - (void)viewDidMoveToWindow
-- 
2.34.1.8.g35151cf07204




[PULL v2 04/36] ui/vdagent: add serial capability support

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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/vdagent.c   | 39 ++-
 ui/trace-events|  1 +
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/include/ui/clipboard.h b/include/ui/clipboard.h
index d82cf314811c..e590b453c8b7 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/vdagent.c b/ui/vdagent.c
index de827aad27ab..b4fdae69177f 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(>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;
diff --git a/ui/trace-events b/ui/trace-events
index b9c0dd0fa11d..e832c3e3659d 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"
-- 
2.34.1.8.g35151cf07204




[PULL v2 01/36] ui/vdagent: add CHECK_SPICE_PROTOCOL_VERSION

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

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 f45ecf31bdbe..1c70839bbf17 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 19e8fbfc96f1..1f8fc77ee8f3 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
-- 
2.34.1.8.g35151cf07204




[PULL v2 00/36] ui: D-Bus display backend

2021-12-20 Thread marcandre . lureau
From: Marc-André Lureau 

The following changes since commit 2bf40d0841b942e7ba12953d515e62a436f0af84:

  Merge tag 'pull-user-20211220' of https://gitlab.com/rth7680/qemu into 
staging (2021-12-20 13:20:07 -0800)

are available in the Git repository at:

  https://gitlab.com/marcandre.lureau/qemu.git tags/dbus-pull-request

for you to fetch changes up to 89f4df9595e162ce4cc65f31a994a31e3e45ff3a:

  MAINTAINERS: update D-Bus section (2021-12-21 10:50:22 +0400)


Add D-Bus display backend



v2:
 - fix Cocoa build
 - fix 6.2->7.0 version annotations

Marc-André Lureau (36):
  ui/vdagent: add CHECK_SPICE_PROTOCOL_VERSION
  ui/vdagent: replace #if 0 with protocol version check
  ui: generalize clipboard notifier
  ui/vdagent: add serial capability support
  ui/clipboard: add qemu_clipboard_check_serial()
  ui/clipboard: add a clipboard reset serial event
  hw/display: report an error if virgl initialization failed
  virtio-gpu: use VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP
  ui: do not delay further remote resize
  ui: factor out qemu_console_set_display_gl_ctx()
  ui: associate GL context outside of display listener registration
  ui: make gl_block use a counter
  ui: add a gl-unblock warning timer
  ui: simplify gl unblock & flush
  ui: dispatch GL events to all listeners
  ui: split the GL context in a different object
  ui: move qemu_spice_fill_device_address to ui/util.c
  console: save current scanout details
  scripts: teach modinfo to skip non-C sources
  docs/sphinx: add sphinx modules to include D-Bus documentation
  backends: move dbus-vmstate1.xml to backends/
  docs: move D-Bus VMState documentation to source XML
  docs: add dbus-display documentation
  build-sys: set glib dependency version
  ui: add a D-Bus display backend
  ui/dbus: add p2p=on/off option
  tests/qtests: add qtest_qmp_add_client()
  tests: start dbus-display-test
  audio: add "dbus" audio backend
  ui/dbus: add clipboard interface
  chardev: teach socket to accept no addresses
  chardev: make socket derivable
  option: add g_auto for QemuOpts
  ui/dbus: add chardev backend & interface
  ui/dbus: register D-Bus VC handler
  MAINTAINERS: update D-Bus section

 docs/conf.py|   8 +
 docs/interop/dbus-display.rst   |  31 ++
 docs/interop/dbus-vmstate.rst   |  52 +--
 docs/interop/dbus.rst   |   2 +
 docs/interop/index.rst  |   1 +
 docs/sphinx/dbusdoc.py  | 166 +++
 docs/sphinx/dbusdomain.py   | 406 +
 docs/sphinx/dbusparser.py   | 373 
 docs/sphinx/fakedbusdoc.py  |  25 ++
 configure   |   1 +
 meson.build |  22 +-
 qapi/audio.json |   3 +-
 qapi/char.json  |  27 ++
 qapi/misc.json  |   4 +-
 qapi/ui.json|  34 +-
 audio/audio_int.h   |   7 +
 audio/audio_template.h  |   2 +
 include/chardev/char-socket.h   |  86 
 include/qemu/cutils.h   |   5 +
 include/qemu/dbus.h |  24 +
 include/qemu/option.h   |   2 +
 include/ui/clipboard.h  |  55 ++-
 include/ui/console.h|  70 ++-
 include/ui/dbus-display.h   |  17 +
 include/ui/dbus-module.h|  11 +
 include/ui/egl-context.h|   6 +-
 include/ui/gtk.h|  11 +-
 include/ui/sdl2.h   |   7 +-
 include/ui/spice-display.h  |   5 +-
 tests/qtest/libqos/libqtest.h   |  10 +
 ui/dbus.h   | 144 ++
 audio/audio.c   |   1 +
 audio/dbusaudio.c   | 654 +++
 chardev/char-socket.c   |  72 +--
 hw/display/qxl.c|   7 +-
 hw/display/vhost-user-gpu.c |   2 +-
 hw/display/virtio-gpu-base.c|   5 +-
 hw/display/virtio-gpu-virgl.c   |   3 +-
 hw/display/virtio-vga.c |  11 -
 monitor/qmp-cmds.c  |  13 +
 tests/qtest/dbus-display-test.c | 257 +++
 tests/qtest/libqtest.c  |  19 +
 ui/clipboard.c  |  34 +-
 ui/console.c| 305 +
 ui/dbus-chardev.c   | 296 +
 ui/dbus-clipboard.c | 457 +++
 ui/dbus-console.c   | 497 +
 ui/dbus-error.c |  48 ++
 ui/dbus-listener.c  | 486 
 ui/dbus-module.c|  35 ++
 ui/dbus.c   | 482 
 ui/egl-context.c|   6 +-
 ui/egl-headless.c   |  20 +-
 ui/gtk-clipboard.c  |  23 +-
 ui/gtk-egl.c|  12 +-
 ui/gtk-gl-area.c|  10 +-
 ui/gtk.c|  28 +-
 ui/sdl2-gl.c|  12 +-
 ui/sdl2.c   |  16 +-
 ui/spice-core.c |  50 --

Re: [PATCH v2 9/9] hw/riscv: virt: Set the clock-frequency

2021-12-20 Thread Bin Meng
On Tue, Dec 21, 2021 at 2:32 PM Alistair Francis  wrote:
>
> On Mon, Dec 20, 2021 at 5:52 PM Bin Meng  wrote:
> >
> > On Thu, Dec 16, 2021 at 12:55 PM Alistair Francis
> >  wrote:
> > >
> > > From: Alistair Francis 
> > >
> > > As per the device tree specification let's set the clock-frequency for
> > > the virt CPUs.
> > >
> > > QEMU doesn't really have an exact clock, so let's just 100 as it's a
> > > nice round number and matches the sifive_u CLINT_TIMEBASE_FREQ.
> > >
> > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/472 (RISC-V virt)
> >
> > I tend to think this issue is not valid, as the comment in the issue
> > says the value should reflect the running frequency.
> >
> > Note the "clock-frequency" was once in the codes but was intentionally
> > removed before because it is not needed:
> >
> > See commit 7ae05377b85f (" riscv: hw: Drop "clock-frequency" property
> > of cpu nodes")
>
> Hmmm... Good point.
>
> But if the device tree spec says it's required then I think we should
> include it. Even if it isn't super relevant for us

The Linux kernel upstream RISC-V DTS files also don't have
"clock-frequency" properties. I doubt there is benefit to provide one.

Regards,
Bin



Re: [PATCH v7 12/18] target/riscv: support for 128-bit shift instructions

2021-12-20 Thread Alistair Francis
On Tue, Dec 14, 2021 at 2:52 AM Frédéric Pétrot
 wrote:
>
> 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 

Alistair

> ---
>  target/riscv/insn32.decode  |  10 ++
>  target/riscv/translate.c|  58 --
>  target/riscv/insn_trans/trans_rvb.c.inc |  22 +--
>  target/riscv/insn_trans/trans_rvi.c.inc | 224 ++--
>  4 files changed, 270 insertions(+), 44 deletions(-)
>
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index 02889c6082..e338a803a0 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -22,6 +22,7 @@
>  %rs1   15:5
>  %rd7:5
>  %sh5   20:5
> +%sh6   20:6
>
>  %sh720:7
>  %csr20:12
> @@ -92,6 +93,9 @@
>  # Formats 64:
>  @sh5 ...  . .  ... . ...   shamt=%sh5  
> %rs1 %rd
>
> +# Formats 128:
> +@sh6   .. .. . ... . ...  shamt=%sh6 %rs1 %rd
> +
>  # *** Privileged Instructions ***
>  ecall    0 000 0 1110011
>  ebreak  0001 0 000 0 1110011
> @@ -167,6 +171,12 @@ sraw 010 .  . 101 . 0111011 @r
>  ldu     . 111 . 011 @i
>  lq      . 010 . 000 @i
>  sq      . 100 . 0100011 @s
> +sllid00 ..  . 001 . 1011011 @sh6
> +srlid00 ..  . 101 . 1011011 @sh6
> +sraid01 ..  . 101 . 1011011 @sh6
> +slld 000 . .  001 . 011 @r
> +srld 000 . .  101 . 011 @r
> +srad 010 . .  101 . 011 @r
>
>  # *** RV32M Standard Extension ***
>  mul  001 .  . 000 . 0110011 @r
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 0b87312dda..15e628308d 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -560,7 +560,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);
> @@ -572,26 +573,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,
> @@ -615,34 +628,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);
>
> -

Re: [PATCH v5 13/23] target/riscv: Implement AIA mtopi, stopi, and vstopi CSRs

2021-12-20 Thread Alistair Francis
On Sat, Dec 11, 2021 at 2:34 PM Anup Patel  wrote:
>
> The AIA specification introduces new [m|s|vs]topi CSRs for
> reporting pending local IRQ number and associated IRQ priority.
>
> Signed-off-by: Anup Patel 
> ---
>  target/riscv/csr.c | 155 +
>  1 file changed, 155 insertions(+)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 4b3edc1043..6f613d182d 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -189,6 +189,15 @@ static int smode32(CPURISCVState *env, int csrno)
>  return smode(env, csrno);
>  }
>
> +static int aia_smode(CPURISCVState *env, int csrno)
> +{
> +if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
> +return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
> +return smode(env, csrno);
> +}
> +
>  static int aia_smode32(CPURISCVState *env, int csrno)
>  {
>  if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
> @@ -833,6 +842,28 @@ static RISCVException rmw_mieh(CPURISCVState *env, int 
> csrno,
>  return ret;
>  }
>
> +static int read_mtopi(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +int irq;
> +uint8_t iprio;
> +
> +irq = riscv_cpu_mirq_pending(env);
> +if (irq <= 0 || irq > 63) {
> +   *val = 0;
> +} else {
> +   iprio = env->miprio[irq];
> +   if (!iprio) {
> +   if (riscv_cpu_default_priority(irq) > IPRIO_DEFAULT_M) {
> +   iprio = IPRIO_MMAXIPRIO;
> +   }
> +   }
> +   *val = (irq & TOPI_IID_MASK) << TOPI_IID_SHIFT;
> +   *val |= iprio;
> +}
> +
> +return RISCV_EXCP_NONE;
> +}
> +
>  static RISCVException read_mtvec(CPURISCVState *env, int csrno,
>   target_ulong *val)
>  {
> @@ -1362,6 +1393,121 @@ static RISCVException write_satp(CPURISCVState *env, 
> int csrno,
>  return RISCV_EXCP_NONE;
>  }
>
> +static int read_vstopi(CPURISCVState *env, int csrno, target_ulong *val)
> +{
> +int irq, ret;
> +target_ulong topei;
> +uint64_t vseip, vsgein;
> +uint32_t iid, iprio, hviid, hviprio, gein;
> +#define VSTOPI_NUM_SRCS 5

This should be defined at the top of the file.

Alistair



RE: [PATCH] tests/qtest: Make the filter tests independent from a specific NIC

2021-12-20 Thread Zhang, Chen



> -Original Message-
> From: Qemu-devel  bounces+chen.zhang=intel@nongnu.org> On Behalf Of Thomas Huth
> Sent: Monday, December 20, 2021 6:30 PM
> To: qemu-devel@nongnu.org; Laurent Vivier 
> Cc: Paolo Bonzini ; Yang Hongyang
> ; Zhang Chen 
> Subject: [PATCH] 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.
> 

Oh, It's my and Hongyang's abandoned mailbox.
Looks good to me.
By the way, should I add the test/qtest/test-filter* to the MAINTAINER file?

Reviewed-by: Zhang Chen 

Thanks
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
> ebeac59b3f..7811177f03 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'
> +  ]
> 
>  dbus_daemon = find_program('dbus-daemon', required: false)  if
> dbus_daemon.found() and config_host.has_key('GDBUS_CODEGEN')
> @@ -109,31 +110,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'] :
> []) +\
>

Re: [PATCH] target/riscv/pmp: fix no pmp illegal intrs

2021-12-20 Thread Alistair Francis
On Wed, Dec 15, 2021 at 1:00 AM Nikita Shubin  wrote:
>
> From: Nikita Shubin 
>
> 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 

Whoops!

I sent a patch to fix the exact same issue :)

I'll drop mine and we can merge yours. Do you mind adding this and
resending the patch

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/585

Reviewed-by: Alistair Francis 

Alistair

> ---
>  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());
>  }
>
> --
> 2.31.1
>
>



Re: [PATCH v2 9/9] hw/riscv: virt: Set the clock-frequency

2021-12-20 Thread Alistair Francis
On Mon, Dec 20, 2021 at 5:52 PM Bin Meng  wrote:
>
> On Thu, Dec 16, 2021 at 12:55 PM Alistair Francis
>  wrote:
> >
> > From: Alistair Francis 
> >
> > As per the device tree specification let's set the clock-frequency for
> > the virt CPUs.
> >
> > QEMU doesn't really have an exact clock, so let's just 100 as it's a
> > nice round number and matches the sifive_u CLINT_TIMEBASE_FREQ.
> >
> > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/472 (RISC-V virt)
>
> I tend to think this issue is not valid, as the comment in the issue
> says the value should reflect the running frequency.
>
> Note the "clock-frequency" was once in the codes but was intentionally
> removed before because it is not needed:
>
> See commit 7ae05377b85f (" riscv: hw: Drop "clock-frequency" property
> of cpu nodes")

Hmmm... Good point.

But if the device tree spec says it's required then I think we should
include it. Even if it isn't super relevant for us

Alistair

>
> > Signed-off-by: Alistair Francis 
> > ---
> >  hw/riscv/virt.c | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > index 3af074148e..41a85cfc60 100644
> > --- a/hw/riscv/virt.c
> > +++ b/hw/riscv/virt.c
> > @@ -202,6 +202,7 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, 
> > int socket,
> >  qemu_fdt_setprop_cell(mc->fdt, cpu_name, "reg",
> >  s->soc[socket].hartid_base + cpu);
> >  qemu_fdt_setprop_string(mc->fdt, cpu_name, "device_type", "cpu");
> > +qemu_fdt_setprop_cell(mc->fdt, cpu_name, "clock-frequency", 
> > 100);
> >  riscv_socket_fdt_write_id(mc, mc->fdt, cpu_name, socket);
> >  qemu_fdt_setprop_cell(mc->fdt, cpu_name, "phandle", cpu_phandle);
>
> Regards,
> Bin



[PATCH v11 31/31] tests/docker: Add gentoo-loongarch64-cross image and run cross builds in GitLab

2021-12-20 Thread WANG Xuerui
Normally this would be based on qemu/debian10 or qemu/ubuntu2004, but
after a week-long struggle, I still cannot build stage2 gcc with the
known-good LoongArch toolchain sources, so I chose the least-resistance
path with Gentoo as base image. As this image is not expected to be
re-built by CI, like hexagon, it should not take much maintenance
effort; also it's expected to be replaced as soon as Debian is
available.

As the LoongArch *target* has not been merged yet, a check-tcg job is
not added at the moment, but cross builds with the TCG *host* port are
already possible, and added to CI matrix.

Due to constant flux of the toolchain sources used (especially that of
glibc), the binaries built with this image may or may not work when
run on actual hardware, but still useful for ensuring things correctly
build. This image is expected to be updated every once in a while,
before everything settles down.

As a reference, the image takes about 25 minutes to rebuild on a
Threadripper 3990X system with Docker operating on HDD; YMMV but it
probably wouldn't become significantly shorter, as everything needs to
be built from source in our case.

Signed-off-by: WANG Xuerui 
Reviewed-by: Philippe Mathieu-Daudé 
---
 .gitlab-ci.d/container-cross.yml  |  27 
 .gitlab-ci.d/crossbuilds.yml  |  19 +++
 MAINTAINERS   |   2 +
 tests/docker/Makefile.include |  21 +++
 .../gentoo-loongarch64-cross.docker   |  21 +++
 .../build-toolchain.sh| 128 ++
 6 files changed, 218 insertions(+)
 create mode 100644 tests/docker/dockerfiles/gentoo-loongarch64-cross.docker
 create mode 100755 
tests/docker/dockerfiles/gentoo-loongarch64-cross.docker.d/build-toolchain.sh

diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml
index a3b5b90552..7a8cc556cc 100644
--- a/.gitlab-ci.d/container-cross.yml
+++ b/.gitlab-ci.d/container-cross.yml
@@ -82,6 +82,33 @@ hppa-debian-cross-container:
   variables:
 NAME: debian-hppa-cross
 
+# Similar to hexagon, we don't want to build loongarch64 in the CI either.
+loongarch64-cross-container:
+  image: docker:stable
+  stage: containers
+  rules:
+- if: '$CI_PROJECT_NAMESPACE == "qemu-project"'
+  when: never
+- when: always
+  variables:
+NAME: gentoo-loongarch64-cross
+GIT_DEPTH: 1
+  services:
+- docker:dind
+  before_script:
+- export TAG="$CI_REGISTRY_IMAGE/qemu/$NAME:latest"
+- export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/qemu/$NAME:latest"
+- docker info
+- docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p 
"$CI_REGISTRY_PASSWORD"
+  script:
+- echo "TAG:$TAG"
+- echo "COMMON_TAG:$COMMON_TAG"
+- docker pull $COMMON_TAG
+- docker tag $COMMON_TAG $TAG
+- docker push "$TAG"
+  after_script:
+- docker logout
+
 m68k-debian-cross-container:
   extends: .container_job_template
   stage: containers-layer2
diff --git a/.gitlab-ci.d/crossbuilds.yml b/.gitlab-ci.d/crossbuilds.yml
index 17d6cb3e45..b1cbc9cc43 100644
--- a/.gitlab-ci.d/crossbuilds.yml
+++ b/.gitlab-ci.d/crossbuilds.yml
@@ -68,6 +68,25 @@ cross-i386-tci:
 EXTRA_CONFIGURE_OPTS: 
--target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user
 MAKE_CHECK_ARGS: check check-tcg
 
+# Upstream LoongArch support is still incomplete, but toolchain is already
+# usable and partially merged, so the host support is already testable; but
+# don't let failures block CI.
+cross-loongarch64-system:
+  extends: .cross_system_build_job
+  allow_failure: true
+  needs:
+job: loongarch64-cross-container
+  variables:
+IMAGE: gentoo-loongarch64-cross
+
+cross-loongarch64-user:
+  extends: .cross_user_build_job
+  allow_failure: true
+  needs:
+job: loongarch64-cross-container
+  variables:
+IMAGE: gentoo-loongarch64-cross
+
 cross-mips-system:
   extends: .cross_system_build_job
   needs:
diff --git a/MAINTAINERS b/MAINTAINERS
index 4f6e0de3fb..8da7071b01 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3143,6 +3143,8 @@ LoongArch64 TCG target
 M: WANG Xuerui 
 S: Maintained
 F: tcg/loongarch64/
+F: tests/docker/dockerfiles/gentoo-loongarch64-cross.docker
+F: tests/docker/dockerfiles/gentoo-loongarch64-cross.docker.d/
 
 MIPS TCG target
 M: Philippe Mathieu-Daudé 
diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index f1a0c5db7a..a2cdf193bb 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -176,6 +176,27 @@ docker-image-debian-hexagon-cross: 
$(DOCKER_FILES_DIR)/debian-hexagon-cross.dock
qemu/debian-hexagon-cross --add-current-user,   
\
"PREPARE", "debian-hexagon-cross"))
 
+#
+# Same for loongarch64-cross.
+#
+docker-image-gentoo-loongarch64-cross: 
$(DOCKER_FILES_DIR)/gentoo-loongarch64-cross.docker
+   $(if $(NOCACHE),  

[PATCH v11 29/31] linux-user: Implement CPU-specific signal handler for loongarch64 hosts

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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 00..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) & 0b11) {
+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) & 0b) {
+case 0b0100: /* st.b */
+case 0b0101: /* st.h */
+case 0b0110: /* st.w */
+case 0b0111: /* st.d */
+case 0b1101: /* fst.s */
+case 0b: /* fst.d */
+return true;
+}
+break;
+case 0b001110: /* indexed, atomic, bounds-checking memory operations */
+uint32_t sel = (insn >> 15) & 0b111;
+
+switch (sel) {
+case 0b010: /* stx.b */
+case 0b0101000: /* stx.h */
+case 0b011: /* stx.w */
+case 0b0111000: /* stx.d */
+case 0b111: /* fstx.s */
+case 0b000: /* fstx.d */
+case 0b00011101100: /* fstgt.s */
+case 0b00011101101: /* fstgt.d */
+case 0b00011101110: /* fstle.s */
+case 0b0001110: /* fstle.d */
+case 0b0001000: /* stgt.b */
+case 0b0001001: /* stgt.h */
+case 0b0001010: /* stgt.w */
+case 0b0001011: /* stgt.d */
+case 0b0001100: /* stle.b */
+case 0b0001101: /* stle.h */
+case 0b0001110: /* stle.w */
+case 0b000: /* stle.d */
+case 0b0001100 ... 0b00011100011: /* am* insns */
+return true;
+}
+break;
+}
+
+return false;
+}
+
+#endif
-- 
2.34.0




Re: [PATCH] failover: Silence warning messages during qtest

2021-12-20 Thread Jason Wang
On Mon, Dec 20, 2021 at 10:53 PM Laurent Vivier  wrote:
>
> 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 
> ---

Acked-by: Jason Wang 

>  hw/net/virtio-net.c   | 3 ++-
>  migration/migration.c | 4 +++-
>  2 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index f2014d5ea0b3..c64a6b9d1745 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_VERSION11
>
> @@ -925,7 +926,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, 
> uint64_t features)
>  qapi_event_send_failover_negotiated(n->netclient_name);
>  qatomic_set(>failover_primary_hidden, false);
>  failover_add_primary(n, );
> -if (err) {
> +if (err && !qtest_enabled()) {
>  warn_report_err(err);
>  }
>  }
> diff --git a/migration/migration.c b/migration/migration.c
> index 3de11ae921e0..065216561063 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(>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");
>  }
> --
> 2.33.1
>




[PATCH v11 25/31] tcg/loongarch64: Implement exit_tb/goto_tb

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-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;
-- 
2.34.0




[PATCH v11 30/31] configure, meson.build: Mark support for loongarch64 hosts

2021-12-20 Thread WANG Xuerui
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é 
---
 configure   | 5 +
 meson.build | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index 8ccfe51673..9724631609 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
@@ -3719,6 +3721,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 f45ecf31bd..6d7c02bad7 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()
 
-- 
2.34.0




[PATCH v11 28/31] common-user: Add safe syscall handling for loongarch64 hosts

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-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 00..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 == _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
-- 
2.34.0




[PATCH v11 26/31] tcg/loongarch64: Implement tcg_target_init

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-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);
+}
-- 
2.34.0




[PATCH v11 24/31] tcg/loongarch64: Implement tcg_target_qemu_prologue

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-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);
+}
-- 
2.34.0




[PATCH v11 27/31] tcg/loongarch64: Register the JIT

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-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, _frame, sizeof(debug_frame));
+}
-- 
2.34.0




[PATCH v11 22/31] tcg/loongarch64: Implement simple load/store ops

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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 

[PATCH v11 19/31] tcg/loongarch64: Implement br/brcond ops

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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:
-- 
2.34.0




[PATCH v11 23/31] tcg/loongarch64: Add softmmu load/store helpers, implement qemu_ld/qemu_st ops

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-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 

[PATCH v11 20/31] tcg/loongarch64: Implement setcond ops

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-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 */
-- 
2.34.0




[PATCH v11 15/31] tcg/loongarch64: Implement clz/ctz ops

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-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_i320
 #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_i640
 #define TCG_TARGET_HAS_add2_i64 0
 #define TCG_TARGET_HAS_sub2_i64 0
-- 
2.34.0




[PATCH v11 16/31] tcg/loongarch64: Implement shl/shr/sar/rotl/rotr ops

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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
-- 
2.34.0




[PATCH v11 17/31] tcg/loongarch64: Implement add/sub ops

2021-12-20 Thread WANG Xuerui
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é 
---
 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();
 }
-- 
2.34.0




[PATCH v11 14/31] tcg/loongarch64: Implement bswap{16,32,64} ops

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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_i321
 #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_i641
 #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
-- 
2.34.0




[PATCH v11 21/31] tcg/loongarch64: Implement tcg_out_call

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-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();
 }
-- 
2.34.0




[PATCH v11 18/31] tcg/loongarch64: Implement mul/mulsh/muluh/div/divu/rem/remu ops

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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_i320
 #define TCG_TARGET_HAS_muls2_i320
-#define TCG_TARGET_HAS_muluh_i320
-#define TCG_TARGET_HAS_mulsh_i320
+#define TCG_TARGET_HAS_muluh_i321
+#define TCG_TARGET_HAS_mulsh_i321
 #define TCG_TARGET_HAS_ext8s_i321
 #define TCG_TARGET_HAS_ext16s_i32   1
 #define TCG_TARGET_HAS_ext8u_i321
@@ -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_i640
 #define TCG_TARGET_HAS_muls2_i640
-#define TCG_TARGET_HAS_muluh_i640
-#define TCG_TARGET_HAS_mulsh_i640
+#define TCG_TARGET_HAS_muluh_i641
+#define TCG_TARGET_HAS_mulsh_i641
 
 /* not defined -- call should be eliminated at compile time */
 void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
-- 
2.34.0




[PATCH v11 10/31] tcg/loongarch64: Implement goto_ptr

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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 00..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();
+}
+}
-- 
2.34.0




[PATCH v11 12/31] tcg/loongarch64: Implement not/and/or/xor/nor/andc/orc ops

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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_i320
@@ -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  

[PATCH v11 13/31] tcg/loongarch64: Implement deposit/extract ops

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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_i321
-- 
2.34.0




[PATCH v11 11/31] tcg/loongarch64: Implement sign-/zero-extension ops

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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_i320
 #define TCG_TARGET_HAS_muluh_i320
 #define TCG_TARGET_HAS_mulsh_i320
-#define TCG_TARGET_HAS_ext8s_i320
-#define TCG_TARGET_HAS_ext16s_i32   0
-#define TCG_TARGET_HAS_ext8u_i320
-#define TCG_TARGET_HAS_ext16u_i32   0
+#define TCG_TARGET_HAS_ext8s_i321
+#define TCG_TARGET_HAS_ext16s_i32   1
+#define TCG_TARGET_HAS_ext8u_i321
+#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_i320
-#define TCG_TARGET_HAS_extrh_i64_i320
-#define TCG_TARGET_HAS_ext8s_i640
-#define TCG_TARGET_HAS_ext16s_i64   0
-#define TCG_TARGET_HAS_ext32s_i64   0
-#define TCG_TARGET_HAS_ext8u_i640
-#define TCG_TARGET_HAS_ext16u_i64   0
-#define TCG_TARGET_HAS_ext32u_i64   0
+#define 

[PATCH v11 09/31] tcg/loongarch64: Implement tcg_out_mov and tcg_out_movi

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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,
 

[PATCH v11 06/31] tcg/loongarch64: Define the operand constraints

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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 00..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;
+}
-- 
2.34.0




[PATCH v11 07/31] tcg/loongarch64: Implement necessary relocation operations

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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();
+}
+}
-- 
2.34.0




[PATCH v11 08/31] tcg/loongarch64: Implement the memory barrier op

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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();
+}
+}
-- 
2.34.0




[PATCH v11 05/31] tcg/loongarch64: Add register names, allocation order and input/output sets

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-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 00..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,
+};
-- 
2.34.0




[PATCH v11 03/31] tcg/loongarch64: Add the tcg-target.h file

2021-12-20 Thread WANG Xuerui
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é 
---
 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 00..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_OFFSET0
+
+/* 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_i320
+#define TCG_TARGET_HAS_muls2_i320
+#define TCG_TARGET_HAS_muluh_i320
+#define TCG_TARGET_HAS_mulsh_i320
+#define TCG_TARGET_HAS_ext8s_i320
+#define TCG_TARGET_HAS_ext16s_i32   0
+#define TCG_TARGET_HAS_ext8u_i320
+#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_i320
+#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 

[PATCH v11 04/31] tcg/loongarch64: Add generated instruction opcodes and encoding helpers

2021-12-20 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Acked-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 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 00..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 = 0x1400,
+OPC_CTZ_W = 0x1c00,
+OPC_CLZ_D = 0x2400,
+OPC_CTZ_D = 0x2c00,
+OPC_REVB_2H = 0x3000,
+OPC_REVB_2W = 0x3800,
+OPC_REVB_D = 0x3c00,
+OPC_SEXT_H = 0x5800,
+OPC_SEXT_B = 0x5c00,
+OPC_ADD_W = 0x0010,
+OPC_ADD_D = 0x00108000,
+OPC_SUB_W = 0x0011,
+OPC_SUB_D = 0x00118000,
+OPC_SLT = 0x0012,
+OPC_SLTU = 0x00128000,
+OPC_MASKEQZ = 0x0013,
+OPC_MASKNEZ = 0x00138000,
+OPC_NOR = 0x0014,
+OPC_AND = 0x00148000,
+OPC_OR = 0x0015,
+OPC_XOR = 0x00158000,
+OPC_ORN = 0x0016,
+OPC_ANDN = 0x00168000,
+OPC_SLL_W = 0x0017,
+OPC_SRL_W = 0x00178000,
+OPC_SRA_W = 0x0018,
+OPC_SLL_D = 0x00188000,
+OPC_SRL_D = 0x0019,
+OPC_SRA_D = 0x00198000,
+OPC_ROTR_W = 0x001b,
+OPC_ROTR_D = 0x001b8000,
+OPC_MUL_W = 0x001c,
+OPC_MULH_W = 0x001c8000,
+OPC_MULH_WU = 0x001d,
+OPC_MUL_D = 0x001d8000,
+OPC_MULH_D = 0x001e,
+OPC_MULH_DU = 0x001e8000,
+OPC_DIV_W = 0x0020,
+OPC_MOD_W = 0x00208000,
+OPC_DIV_WU = 0x0021,
+OPC_MOD_WU = 0x00218000,
+OPC_DIV_D = 0x0022,
+OPC_MOD_D = 0x00228000,
+OPC_DIV_DU = 0x0023,
+OPC_MOD_DU = 0x00238000,
+OPC_SLLI_W = 0x00408000,
+OPC_SLLI_D = 0x0041,
+OPC_SRLI_W = 0x00448000,
+OPC_SRLI_D = 0x0045,
+OPC_SRAI_W = 0x00488000,
+OPC_SRAI_D = 0x0049,
+OPC_ROTRI_W = 0x004c8000,
+OPC_ROTRI_D = 0x004d,
+OPC_BSTRINS_W = 0x0060,
+OPC_BSTRPICK_W = 0x00608000,
+OPC_BSTRINS_D = 0x0080,
+OPC_BSTRPICK_D = 0x00c0,
+OPC_SLTI = 0x0200,
+OPC_SLTUI = 0x0240,
+OPC_ADDI_W = 0x0280,
+OPC_ADDI_D = 0x02c0,
+OPC_CU52I_D = 0x0300,
+OPC_ANDI = 0x0340,
+OPC_ORI = 0x0380,
+OPC_XORI = 0x03c0,
+OPC_LU12I_W = 0x1400,
+OPC_CU32I_D = 0x1600,
+OPC_PCADDU2I = 0x1800,
+OPC_PCALAU12I = 0x1a00,
+OPC_PCADDU12I = 0x1c00,
+OPC_PCADDU18I = 0x1e00,
+OPC_LD_B = 0x2800,
+OPC_LD_H = 0x2840,
+OPC_LD_W = 0x2880,
+OPC_LD_D = 0x28c0,
+OPC_ST_B = 0x2900,
+OPC_ST_H = 0x2940,
+OPC_ST_W = 0x2980,
+OPC_ST_D = 0x29c0,
+OPC_LD_BU = 0x2a00,
+OPC_LD_HU = 0x2a40,
+OPC_LD_WU = 0x2a80,
+OPC_LDX_B = 0x3800,
+OPC_LDX_H = 0x3804,
+OPC_LDX_W = 0x3808,
+OPC_LDX_D = 0x380c,
+OPC_STX_B = 0x3810,
+OPC_STX_H = 0x3814,
+OPC_STX_W = 0x3818,
+OPC_STX_D = 0x381c,
+OPC_LDX_BU = 0x3820,
+OPC_LDX_HU = 0x3824,
+OPC_LDX_WU = 0x3828,
+OPC_DBAR = 0x3872,
+OPC_JIRL = 0x4c00,
+OPC_B = 0x5000,
+OPC_BL = 0x5400,
+OPC_BEQ = 0x5800,
+OPC_BNE = 0x5c00,
+OPC_BGT = 0x6000,
+OPC_BLE = 0x6400,
+OPC_BGTU = 0x6800,
+OPC_BLEU = 0x6c00,
+} 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);
+

[PATCH v11 02/31] MAINTAINERS: Add tcg/loongarch64 entry with myself as maintainer

2021-12-20 Thread WANG Xuerui
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é 
---
 MAINTAINERS | 5 +
 1 file changed, 5 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1de6ce6e44..4f6e0de3fb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3139,6 +3139,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 
-- 
2.34.0




[PATCH v11 01/31] elf: Add machine type value for LoongArch

2021-12-20 Thread WANG Xuerui
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é 
---
 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_LOONGARCH258 /* LoongArch */
+
 /*
  * This is an interim value that we will use until the committee comes
  * up with a final number.
-- 
2.34.0




[PATCH v11 00/31] LoongArch64 port of QEMU TCG

2021-12-20 Thread WANG Xuerui
Hi all,

This is a port of QEMU TCG to the brand-new CPU architecture LoongArch,
introduced by Loongson with their 3A5000 chips.

Everything is tested on real 3A5000 board (system emulation, linux-user,
make check) and GitLab (CI jobs), and rebased to latest master branch.

## About the series

Only the LP64D ABI is supported, as this is the only one fully
implemented and supported by Loongson so far. 32-bit support is incomplete
from outset, and removed from the very latest upstream submissions, so you
can't even configure for that.

The architecture's documentation is already translated into English;
it can be browsed at https://loongson.github.io/LoongArch-Documentation/.
The LoongArch ELF psABI doc (version 1.00) could be found at [1];
if anything is missing there, it's most likely the same as RISC-V, but
you can always raise an issue over their issue tracker at [2].

[1]: 
https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html
[2]: https://github.com/loongson/LoongArch-Documentation/issues

In this series I made use of generated instruction encodings and
emitters from https://github.com/loongson-community/loongarch-opcodes
(a community project started by myself, something I must admit), as the
LoongArch encoding is highly irregular even for a fixed 32-bit ISA, and
I want to minimize the maintenance burden for future collaboration.

This series touches some of the same files as Song Gao's previous
submission of LoongArch *target* support, which is a bit unfortunate;
one of us will have to rebase after either series gets in. Actual
conflict should only happen on build system bits and include/elf.h,
though, as we're working on entirely different areas.

## How to build and test this

Upstream support for LoongArch is largely WIP for now, which means you
must apply a lot of patches if you want to even cross-build for this arch.
The main sources I used are as follows:

* binutils: (already upstream as of November 2021)
* gcc: https://github.com/xen0n/gcc/tree/for-gentoo-gcc-12-v5
  based on https://github.com/loongson/gcc/tree/loongarch_upstream_v3
* glibc: https://github.com/xen0n/glibc/tree/for-gentoo-glibc-2.34-v3
  based on https://github.com/loongson/glibc/tree/loongarch_2_34_dev
* Linux: https://github.com/xen0n/linux/tree/loongarch-playground-v7
  based on https://github.com/loongson/linux/tree/loongarch-next
* Gentoo overlay: https://github.com/xen0n/loongson-overlay

I have made ready-to-use Gentoo stage3 tarballs, but they're served with
CDN off my personal cloud account, and I don't want the link to be
exposed so that my bills skyrocket; you can reach me off-list to get the
links if you're interested.

As for the hardware availability, the boards can already be bought in
China on Taobao, and I think some people at Loongson might be able to
arrange for testing environments, if testing on real hardware other than
mine is required before merging; they have their in-house Debian spin-off
from the early days of this architecture. Their kernel is
ABI-incompatible with the version being upstreamed and used by me, but
QEMU should work there regardless.

Lastly, I'm new to QEMU development and this is my first patch series
here; apologizes if I get anything wrong, and any help or suggestion is
certainly appreciated!

## Changelog

v11 -> v10:

- Rebased to latest development branch

v10 -> v9:

- Collected Reviewed-by tags from last round
- Fixed Patch 28's register allocation for _pending and added
  explanatory comments per review
- Updated Docker image
- Updated a couple of places still mentioning the "LP64" ABI (properly
  disambiguated into LP64S/LP64F/LP64D in the latest ABI spec) to say
  "LP64*" instead

v9 -> v8:

- Rebased on top of Richard's lu-safesignal branch for eventual merge

v8 -> v7:

- Rebased to latest development branch
- Adjusted component field of Patch 29's subject line to say
  "linux-user" after rebase
- Adjusted Patch 31 slightly according to review (you can check out the
  Patchew diff between revisions for details)

v7 -> v6:

- Rebased to latest development branch
- Added Docker image for cross-compilation and cross-build CI jobs

v6 -> v5:

- Fixed many places using 0/1 to say false/true
- Tweaks to tcg_out_movi
  - Moved variable declarations to top of function, as per QEMU coding
style
  - Added ASCII art to better explain names like `hi12` `hi32` and `hi52`
- Added example `uname -a` outputs to commit message of Patch 30 to help
  people make sense of the change

v5 -> v4:

- Updated generated instruction definition to latest (added ldx/stx
  family of indexed load/stores)
- Incorporated Richard's suggestion for tcg_out_movi, tested to cover
  the cases it's supposed to improve
- Fixed a "size == MO_64" occurrence to just say "type"
- Used indexed load/stores to optimize qemu_ld/st
- Fixed zero-extension of address register for qemu_ld/st on 32-bit
  targets

v4 -> v3:

- Addressed all review comments from v3
  - Made MAX_CODE_GEN_BUFFER_SIZE 

Re: [PATCH v4 11/14] vfio-user: IOMMU support for remote device

2021-12-20 Thread Jag Raman


> On Dec 20, 2021, at 9:36 AM, Stefan Hajnoczi  wrote:
> 
> On Fri, Dec 17, 2021 at 08:00:35PM +, Jag Raman wrote:
>>> On Dec 16, 2021, at 9:40 AM, Stefan Hajnoczi  wrote:
>>> 
>>> On Wed, Dec 15, 2021 at 10:35:35AM -0500, Jagannathan Raman wrote:
 Assign separate address space for each device in the remote processes.
>>> 
>>> If I understand correctly this isn't really an IOMMU. It's abusing the
>>> IOMMU APIs to create isolated address spaces for each device. This way
>>> memory regions added by the vfio-user client do not conflict when there
>>> are multiple vfio-user servers.
>> 
>> Like you already figured out, having isolated DMA address space alone is not
>> sufficient for this application, we also needed to isolate the sysmem/RAM 
>> address
>> space. As such, the available IOMMU APIs alone were not sufficient, so we had
>> to improvise.
>> 
>>> 
>>> Calling pci_root_bus_new() and keeping one PCI bus per VfuObject might
>>> be a cleaner approach:
>>> - Lets you isolate both PCI Memory Space and IO Space.
>>> - Isolates the PCIDevices and their addresses on the bus.
>>> - Isolates irqs.
>>> - No more need to abuse the IOMMU API.
>> 
>> I believe we would still need to have an IOMMU. It’s because, devices use the
>> pci_dma_read()/_write() functions. These functions look up the address in DMA
>> address space (via pci_get_address_space() -> PCIDevice->bus_master_as ->
>> PCIDevice->bus_master_enable_region -> 
>> PCIDevice->bus_master_container_region).
>> bus_master_enable_region and bus_master_container_region are effectively 
>> aliases
>> to the DMA address space - without an IOMMU, the dma_as would be the shared
>> global sysmem/RAM space (address_space_mem, please see pci_init_bus_master())
> 
> Good point, that code assumes there is a global address space. Creating
> a fake IOMMU works around that assumption but it seems cleaner to
> eliminate it:
> 
>  AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
>  {
>  ...
>  if (!pci_bus_bypass_iommu(bus) && iommu_bus && iommu_bus->iommu_fn) {
>  return iommu_bus->iommu_fn(bus, iommu_bus->iommu_opaque, devfn);
>  }
>  return _space_memory;
>  
> 
> When creating a PCI root bus an AddressSpace argument could be provided,
> just like it already does for the address_space_memory and
> address_space_io MemoryRegions. Then the hardcoded return can be
> changed to something like:
> 
>  return bus->dma_address_space;

This approach should work when we are using separate PCIBus for each PCIDevice.

> 
 @@ -332,6 +336,12 @@ static void vfu_object_register_bars(vfu_ctx_t 
 *vfu_ctx, PCIDevice *pdev)
 vfu_object_bar_handlers[i],
 VFU_REGION_FLAG_RW, NULL, 0, -1, 0);
 
 +if ((o->pci_dev->io_regions[i].type & PCI_BASE_ADDRESS_SPACE) == 
 0) {
 +memory_region_unref(o->pci_dev->io_regions[i].address_space);
 +o->pci_dev->io_regions[i].address_space =
 +remote_iommu_get_ram(o->pci_dev);
 +}
>>> 
>>> This looks hacky. If you create a separate PCIHost for each device
>>> instead then the BARs will be created in the MemoryRegion (confusingly
>>> named "address_space" in the PCI code) of your choosing.
>> 
>> I was also not very comfortable with this - added it very grudgingly out of
>> necessity. Thank god this can go away with separate bus for each device.
> 
> I talked to Kevin Wolf about having separate busses. qdev currently
> requires each DeviceState to have a parent bus and each bus must have a
> parent DeviceState. There is only one exception: a special check that
> allows the global system bus (sysbus_get_default()) to be created
> without a parent DeviceState.
> 
> This restriction probably needs to be loosened in order to support an
> isolated PCIHost for each vfio-user server. The challenge is that
> qdev_find_recursive() and monitor commands like device_add currently
> only search the global system bus. Maybe new syntax is needed for the
> multiple root bus case or the behavior of existing monitor commands
> needs to be understood and extended without breaking anything.

Lemme check if it’s possible to create multiple PCIBuses within the global
system bus, something similar to what PCI expansion cards are doing. That
would help avoid the complexities you just mentioned.
> 
>>> 
>>> Also, why is PCI Memory Space isolated via VFUIOMMU but PCI IO Space is
>>> not?
>> 
>> If I understand correctly, the IO address space translates sysmem address to
>> direct device access (such as I2C). Once we are inside a device, we already
>> have access to all parts of the device (unlike RAM which sits outside the 
>> device).
>> So didn’t think device would go via IOMMU to access IO. Also didn’t see any
>> other IOMMU translating IO address space accesses.
> 
> I reviewed how BARs are configured with VFIO:
> 
> 1. When the guest writes to the vfio-pci 

Re: [RFC PATCH v3 16/27] hw/loongarch: Add LoongArch cpu interrupt support(CPUINTC)

2021-12-20 Thread yangxiaojuan
Hi,Mark

On 12/18/2021 07:54 AM, Mark Cave-Ayland wrote:
> On 04/12/2021 12:07, Xiaojuan Yang wrote:
> 
>> Loongson-3A5000 support 14 interrupts from 64 - 77(Timer->75 IPI->76)
>> Loongson-3A5000 and ls7a form a legacy model and extended model irq
>> hierarchy.Tcg mode emulate a simplified extended model which
>> has no Legacy I/O Interrupt Controller(LIOINTC) and LPC.
>> e.g:
>>
>>   |+-++-+ +---+ |
>>   || IPI |--> | CPUINTC | <-- | Timer | |
>>   |+-++-+ +---+ |
>>   |^|
>>   |||
>>   |   +-+
>>   |   | EIOINTC |
>>   |   +-+
>>   |^   ^|
>>   ||   ||
>>   | +-+ +-+ |
>>   | | PCH-PIC | | PCH-MSI | |
>>   | +-+ +-+ |
>>   |   ^ ^   ^   |
>>   |   | |   |   |
>>   |   +-+ +-+ +-+   |
>>   |   | UARTs | | Devices | | Devices | |
>>   |   +-+ +-+ +-+   |
>>   |^|
>>
>> The following series patch will realize the interrupt
>> controller in this model.
>>
>> More detailed info can be found at the kernel doc or manual
>> 1.https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/
>> linux-loongson.git/tree/Documentation/loongarch?h=loongarch-next
>> 2.https://github.com/loongson/LoongArch-Documentation
>>
>> Signed-off-by: Xiaojuan Yang 
>> Signed-off-by: Song Gao 
>> ---
>>   target/loongarch/cpu.c | 28 
>>   1 file changed, 28 insertions(+)
>>
>> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
>> index 62c2a4d813..afa550c950 100644
>> --- a/target/loongarch/cpu.c
>> +++ b/target/loongarch/cpu.c
>> @@ -504,11 +504,39 @@ static void loongarch_cpu_realizefn(DeviceState *dev, 
>> Error **errp)
>>   lacc->parent_realize(dev, errp);
>>   }
>>   +#ifndef CONFIG_USER_ONLY
>> +static void loongarch_cpu_set_irq(void *opaque, int irq, int level)
>> +{
>> +LoongArchCPU *cpu = opaque;
>> +CPULoongArchState *env = >env;
>> +CPUState *cs = CPU(cpu);
>> +
>> +if (irq < 0 || irq > N_IRQS) {
>> +return;
>> +}
>> +
>> +if (level) {
>> +env->CSR_ESTAT |= 1 << irq;
>> +} else {
>> +env->CSR_ESTAT &= ~(1 << irq);
>> +}
>> +
>> +if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
>> +cpu_interrupt(cs, CPU_INTERRUPT_HARD);
>> +} else {
>> +cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
>> +}
>> +}
>> +#endif
>> +
>>   static void loongarch_cpu_initfn(Object *obj)
>>   {
>>   LoongArchCPU *cpu = LOONGARCH_CPU(obj);
>> cpu_set_cpustate_pointers(cpu);
>> +#ifndef CONFIG_USER_ONLY
>> +qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS);
>> +#endif
>>   }
>> static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
> 
> Rather than use defines to split out user mode, I would suggest using a 
> separate function in a similar way to sparc64_cpu_devinit() in 
> hw/sparc64/sparc64.c to set up the parts of the CPU that are only required in 
> system mode. This function can then be called as part of the board setup.
> 
yes, put the code to the board setup stage is more suitable, thank you!
> 
> ATB,
> 
> Mark.




Re: [PATCH v4 07/14] vfio-user: run vfio-user context

2021-12-20 Thread Jag Raman


> On Dec 20, 2021, at 3:29 AM, Stefan Hajnoczi  wrote:
> 
> On Fri, Dec 17, 2021 at 05:59:48PM +, Jag Raman wrote:
>> 
>> 
>>> On Dec 16, 2021, at 6:17 AM, Stefan Hajnoczi  wrote:
>>> 
>>> On Wed, Dec 15, 2021 at 10:35:31AM -0500, Jagannathan Raman wrote:
 @@ -114,6 +118,62 @@ static void vfu_object_set_device(Object *obj, const 
 char *str, Error **errp)
vfu_object_init_ctx(o, errp);
 }
 
 +static void vfu_object_ctx_run(void *opaque)
 +{
 +VfuObject *o = opaque;
 +int ret = -1;
 +
 +while (ret != 0) {
 +ret = vfu_run_ctx(o->vfu_ctx);
 +if (ret < 0) {
 +if (errno == EINTR) {
 +continue;
 +} else if (errno == ENOTCONN) {
 +qemu_set_fd_handler(o->vfu_poll_fd, NULL, NULL, NULL);
 +o->vfu_poll_fd = -1;
 +object_unparent(OBJECT(o));
 +break;
>>> 
>>> If nothing else logs a message then I think that should be done here so
>>> users know why their vfio-user server object disappeared.
>> 
>> Sure will do.
>> 
>> Do you prefer a trace, or a message to the console? Trace makes sense to me.
>> Presently, the client could unplug the vfio-user device which would trigger 
>> the
>> deletion of this object. This process could happen quietly.
> 
> If there is no way to differentiate graceful disconnect from unexpected
> disconnect then logging might be too noisy.

I think that’s what happens in the regular VFIO case also.
vfio_put_base_device() closes the FD used for ioctls.

> 
> Regarding the automatic deletion of the object, that might not be
> desirable for two reasons:
> 1. It prevents reconnection or another client connecting.
> 2. Management tools are in the dark about it.
> 
> For #2 there are monitor events that QEMU emits to notify management
> tools about state changes like disconnections.

This is very interesting. I suppose you’re referring to something like
‘BLOCK_JOB_COMPLETED’ event.

It’d be good to inform the management tools about disconnection. Not
used this before, will check it out to gather ideas on how to use it.

> 
> It's worth thinking about current and future use cases before baking in
> a policy like automatically deleting VfuObject on disconnect because
> it's inflexible and would require a QEMU update in the future to support
> a different policy.
> 
> One approach is to emit a disconnect event but leave the VfuObject in a
> disconnected state. The management tool can then restart or clean up,
> depending on its policy.
> 
> I'm not sure what's best because it depends on the use cases, but maybe
> you and others have ideas here.
> 
 @@ -208,6 +284,8 @@ static void vfu_object_init(Object *obj)
   TYPE_VFU_OBJECT, TYPE_REMOTE_MACHINE);
return;
}
 +
 +o->vfu_poll_fd = -1;
 }
>>> 
>>> This must call qemu_set_fd_handler(o->vfu_poll_fd, NULL, NULL, NULL)
>>> when o->vfu_poll_fd != -1 to avoid leaving a dangling fd handler
>>> callback registered.
>> 
>> This is during the init phase, and the FD handlers are not set. Do you mean
>> to add this at finalize?
>> 
>> I agree it’s good to explicitly add this at finalize. But vfu_destroy_ctx() 
>> should
>> trigger a ENOTCONN, which would do it anyway.
> 
> I'm not sure my comment makes sense since this is the init function, not
> finalize.
> 
> However, it's not clear to me that the o->vfu_poll_fd fd handler is
> unregistered from the event loop when VfuObject is finalized (e.g. by
> the object-del monitor command). You say vfu_destroy_ctx() triggers
> ENOTCONN, but the VfuObject is freed after finalize returns so when is
> the fd handler deregistered?

That is correct - will remove the FD handler in finalize also.

Thank you!
--
Jag

> 
> Stefan



[PATCH v2 6/7] linux-user/nios2: Fix sigmask in setup_rt_frame

2021-12-20 Thread Richard Henderson
Do not cast the signal mask elements; trust __put_user.

Reviewed-by: Laurent Vivier 
Signed-off-by: Richard Henderson 
---
 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(>uc.tuc_stack, env);
 rt_setup_ucontext(>uc, env);
 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
-__put_user((abi_ulong)set->sig[i],
-   (abi_ulong *)>uc.tuc_sigmask.sig[i]);
+__put_user(set->sig[i], >uc.tuc_sigmask.sig[i]);
 }
 
 /* Set up to return from userspace; jump to fixed address sigreturn
-- 
2.25.1




[PATCH v2 4/7] linux-user/nios2: Map a real kuser page

2021-12-20 Thread Richard Henderson
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 
---
 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_PAGESIZE4096
 
 #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, );
 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]);
-   

[PATCH v2 7/7] linux-user/nios2: Use set_sigmask in do_rt_sigreturn

2021-12-20 Thread Richard Henderson
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 
---
 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(, >uc.tuc_sigmask);
-do_sigprocmask(SIG_SETMASK, , NULL);
+set_sigmask();
 
 if (rt_restore_ucontext(env, >uc, )) {
 goto badframe;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 6d5e5b698c..8cb33a351c 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 */
 
-- 
2.25.1




[PATCH v2 3/7] linux-user/elfload: Rename ARM_COMMPAGE to HI_COMMPAGE

2021-12-20 Thread Richard Henderson
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 
---
 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)0x0f00u
+#define HI_COMMPAGE (intptr_t)0x0f00u
 
 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 >= 0x8000u) {
 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;
-- 
2.25.1




[PATCH v2 2/7] linux-user/nios2: Fixes for signal frame setup

2021-12-20 Thread Richard Henderson
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 
---
 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], [25]);
 __put_user(env->regs[R_EA], [27]);
 __put_user(env->regs[R_SP], [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(>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(>info, info);
+
 /* Create the ucontext.  */
 __put_user(0, >uc.tuc_flags);
 __put_user(0, >uc.tuc_link);
 target_save_altstack(>uc.tuc_stack, env);
-err |= rt_setup_ucontext(>uc, env);
+rt_setup_ucontext(>uc, env);
 for (i = 0; i < TARGET_NSIG_WORDS; i++) {
 __put_user((abi_ulong)set->sig[i],
-(abi_ulong *)>uc.tuc_sigmask.sig[i]);
-}
-
-if (err) {
-goto give_sigsegv;
+   (abi_ulong *)>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) >info;
-env->regs[6] = (unsigned long) >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)
-- 
2.25.1




[PATCH v2 5/7] linux-user/nios2: Fix EA vs PC confusion

2021-12-20 Thread Richard Henderson
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 
---
 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], [23]);
 __put_user(env->regs[R_FP], [24]);
 __put_user(env->regs[R_GP], [25]);
-__put_user(env->regs[R_EA], [27]);
+__put_user(env->regs[R_PC], [27]);
 __put_user(env->regs[R_SP], [28]);
 }
 
@@ -122,7 +122,7 @@ static int rt_restore_ucontext(CPUNios2State *env, struct 
target_ucontext *uc,
 __get_user(env->regs[R_GP], [25]);
 /* Not really necessary no user settable bits */
 __get_user(temp, [26]);
-__get_user(env->regs[R_EA], [27]);
+__get_user(env->regs[R_PC], [27]);
 
 __get_user(env->regs[R_RA], [23]);
 __get_user(env->regs[R_SP], [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);
 }
-- 
2.25.1




[PATCH v2 1/7] linux-user/nios2: Properly emulate EXCP_TRAP

2021-12-20 Thread Richard Henderson
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 
---
 target/nios2/cpu.h  |  2 +-
 linux-user/nios2/cpu_loop.c | 40 -
 target/nios2/translate.c| 17 +++-
 3 files changed, 39 insertions(+), 20 deletions(-)

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/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 > 0xf000ULL);
-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 > 0xf000u;
 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, );
+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/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 */
-- 
2.25.1




[PATCH v2 0/7] linux-user: nios2 fixes

2021-12-20 Thread Richard Henderson
Fixes syscalls and signals for nios2.
Works with the docker cross-compile toolchain that has been committed.

r~

Richard Henderson (7):
  linux-user/nios2: Properly emulate EXCP_TRAP
  linux-user/nios2: Fixes for signal frame setup
  linux-user/elfload: Rename ARM_COMMPAGE to HI_COMMPAGE
  linux-user/nios2: Map a real kuser page
  linux-user/nios2: Fix EA vs PC confusion
  linux-user/nios2: Fix sigmask in setup_rt_frame
  linux-user/nios2: Use set_sigmask in do_rt_sigreturn

 target/nios2/cpu.h  |  2 +-
 linux-user/elfload.c| 66 ++
 linux-user/nios2/cpu_loop.c | 93 +++--
 linux-user/nios2/signal.c   | 56 +-
 linux-user/signal.c |  2 -
 target/nios2/translate.c| 26 +++
 6 files changed, 146 insertions(+), 99 deletions(-)

-- 
2.25.1




Re: [PULL 07/16] configure, meson: move ARCH to meson.build

2021-12-20 Thread Richard Henderson

On 12/19/21 6:17 AM, Paolo Bonzini wrote:

$ARCH and the HOST_* symbols are only used by the QEMU build; configure
uses $cpu instead.  Remove it from config-host.mak.

Reviewed-by: Richard Henderson 
Signed-off-by: Paolo Bonzini 
---
  configure   | 21 -
  meson.build | 26 +-
  2 files changed, 21 insertions(+), 26 deletions(-)


This broke the cross-compiler infrastructure for tests, because tests/tcg/configure.sh 
uses $ARCH, which is no longer defined.



r~




diff --git a/configure b/configure
index 108b7621e2..6e06ac6161 100755
--- a/configure
+++ b/configure
@@ -635,11 +635,9 @@ else
cpu=$(uname -m)
  fi
  
-ARCH=

-# Normalise host CPU name, set ARCH and multilib cflags
+# Normalise host CPU name, set multilib cflags
  # Note that this case should only have supported host CPUs, not guests.
  case "$cpu" in
-  aarch64|riscv) ;;
armv*b|armv*l|arm)
  cpu="arm" ;;
  
@@ -668,8 +666,7 @@ case "$cpu" in

  CPU_CFLAGS="-m64 -mlittle" ;;
  
s390)

-CPU_CFLAGS="-m31"
-ARCH=unknown ;;
+CPU_CFLAGS="-m31" ;;
s390x)
  CPU_CFLAGS="-m64" ;;
  
@@ -678,15 +675,7 @@ case "$cpu" in

  CPU_CFLAGS="-m32 -mv8plus -mcpu=ultrasparc" ;;
sparc64)
  CPU_CFLAGS="-m64 -mcpu=ultrasparc" ;;
-
-  *)
-# This will result in either an error or falling back to TCI later
-ARCH=unknown
-  ;;
  esac
-if test -z "$ARCH"; then
-  ARCH="$cpu"
-fi
  
  : ${make=${MAKE-make}}
  
@@ -3406,8 +3395,6 @@ echo "GIT=$git" >> $config_host_mak

  echo "GIT_SUBMODULES=$git_submodules" >> $config_host_mak
  echo "GIT_SUBMODULES_ACTION=$git_submodules_action" >> $config_host_mak
  
-echo "ARCH=$ARCH" >> $config_host_mak

-
  if test "$debug_tcg" = "yes" ; then
echo "CONFIG_DEBUG_TCG=y" >> $config_host_mak
  fi
@@ -3898,12 +3885,12 @@ if test "$skip_meson" = no; then
  cross_arg="--cross-file config-meson.cross"
  echo "[host_machine]" >> $cross
  echo "system = '$targetos'" >> $cross
-case "$ARCH" in
+case "$cpu" in
  i386)
  echo "cpu_family = 'x86'" >> $cross
  ;;
  *)
-echo "cpu_family = '$ARCH'" >> $cross
+echo "cpu_family = '$cpu'" >> $cross
  ;;
  esac
  echo "cpu = '$cpu'" >> $cross
diff --git a/meson.build b/meson.build
index 4fdaa65b05..2495360fd0 100644
--- a/meson.build
+++ b/meson.build
@@ -67,6 +67,14 @@ endif
  
  targetos = host_machine.system()
  
+if cpu not in supported_cpus

+  host_arch = 'unknown'
+elif cpu == 'x86'
+  host_arch = 'i386'
+else
+  host_arch = cpu
+endif
+
  if cpu in ['x86', 'x86_64']
kvm_targets = ['i386-softmmu', 'x86_64-softmmu']
  elif cpu == 'aarch64'
@@ -335,9 +343,9 @@ if targetos == 'netbsd'
endif
  endif
  
-tcg_arch = config_host['ARCH']

+tcg_arch = host_arch
  if not get_option('tcg').disabled()
-  if cpu not in supported_cpus
+  if host_arch == 'unknown'
  if get_option('tcg_interpreter')
warning('Unsupported CPU @0@, will use TCG with TCI (slow)'.format(cpu))
  else
@@ -353,11 +361,11 @@ if not get_option('tcg').disabled()
endif
if get_option('tcg_interpreter')
  tcg_arch = 'tci'
-  elif config_host['ARCH'] == 'sparc64'
+  elif host_arch == 'sparc64'
  tcg_arch = 'sparc'
-  elif config_host['ARCH'] == 'x86_64'
+  elif host_arch == 'x86_64'
  tcg_arch = 'i386'
-  elif config_host['ARCH'] == 'ppc64'
+  elif host_arch == 'ppc64'
  tcg_arch = 'ppc'
endif
add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / 
tcg_arch,
@@ -1426,6 +1434,8 @@ config_host_data.set_quoted('CONFIG_QEMU_LOCALSTATEDIR', 
get_option('prefix') /
  config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') / 
qemu_moddir)
  config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') / 
get_option('sysconfdir'))
  
+config_host_data.set('HOST_' + host_arch.to_upper(), 1)

+
  config_host_data.set('CONFIG_ATTR', libattr.found())
  config_host_data.set('CONFIG_BRLAPI', brlapi.found())
  config_host_data.set('CONFIG_COCOA', cocoa.found())
@@ -1775,8 +1785,6 @@ foreach k, v: config_host
v = '"' + '", "'.join(v.split()) + '", '
  endif
  config_host_data.set(k, v)
-  elif k == 'ARCH'
-config_host_data.set('HOST_' + v.to_upper(), 1)
elif strings.contains(k)
  config_host_data.set_quoted(k, v)
elif k.startswith('CONFIG_')
@@ -1919,7 +1927,7 @@ foreach target : target_dirs
endif
  
foreach k, v: disassemblers

-if config_host['ARCH'].startswith(k) or 
config_target['TARGET_BASE_ARCH'].startswith(k)
+if host_arch.startswith(k) or 
config_target['TARGET_BASE_ARCH'].startswith(k)
foreach sym: v
  config_target += { sym: 'y' }
  config_all_disas += { sym: 'y' }
@@ -2888,7 +2896,7 @@ foreach target : target_dirs
  endif
  if 'CONFIG_LINUX_USER' in config_target
base_dir = 'linux-user'
-  target_inc += include_directories('linux-user/host/' / 

Re: powernv gitlab ci regression

2021-12-20 Thread Daniel Henrique Barboza

Hey,

On 12/20/21 18:35, Richard Henderson wrote:

Hi guys,

Somewhere within


Merge tag 'pull-ppc-20211217' of https://github.com/legoater/qemu into staging
ppc 7.0 queue:

* General cleanup for Mac machines (Peter)
* Fixes for FPU exceptions (Lucas)
* Support for new ISA31 instructions (Matheus)
* Fixes for ivshmem (Daniel)
* Cleanups for PowerNV PHB (Christophe and Cedric)
* Updates of PowerNV and pSeries documentation (Leonardo and Daniel)
* Fixes for PowerNV (Daniel)
* Large cleanup of FPU implementation (Richard)
* Removal of SoftTLBs support for PPC74x CPUs (Fabiano)
* Fixes for exception models in MPCx and 60x CPUs (Fabiano)
* Removal of 401/403 CPUs (Cedric)
* Deprecation of taihu machine (Thomas)
* Large rework of PPC405 machine (Cedric)
* Fixes for VSX instructions (Victor and Matheus)
* Fix for e6500 CPU (Fabiano)
* Initial support for PMU (Daniel)


is something that has caused a timeout regression in avocado-system-centos:


 (047/171) 
tests/avocado/boot_linux_console.py:BootLinuxConsole.test_ppc_powernv8:  
INTERRUPTED: Test interrupted by SIGTERM\nRunner error occurred: Timeout 
reached\nOriginal status: ERROR\n{'name': 
'047-tests/avocado/boot_linux_console.py:BootLinuxConsole.test_ppc_powernv8', 
'logdir': 
'/builds/qemu-project/qemu/build/tests/results/job-2021-12-17T19.23-... (90.46 
s)
 (048/171) 
tests/avocado/boot_linux_console.py:BootLinuxConsole.test_ppc_powernv9:  
INTERRUPTED: Test interrupted by SIGTERM\nRunner error occurred: Timeout 
reached\nOriginal status: ERROR\n{'name': 
'048-tests/avocado/boot_linux_console.py:BootLinuxConsole.test_ppc_powernv9', 
'logdir': 
'/builds/qemu-project/qemu/build/tests/results/job-2021-12-17T19.23-... (90.55 
s)


See e.g. https://gitlab.com/qemu-project/qemu/-/jobs/1898304074


Thanks for letting us know. I bisected it and the culprit is this patch:


commit 4db3907a40a087e2cc1839d19a3642539d36610b
Author: Daniel Henrique Barboza 
Date:   Fri Dec 17 17:57:18 2021 +0100

target/ppc: enable PMU instruction count


This is a patch where I added instruction count in the ppc64 PMU. After this 
patch the
performance of these 2 tests are degraded to the point where we're hitting 
timeouts in
gitlab (didn't hit timeouts in my machine but the performance is noticeable 
worse).

I'll need to see the serial console of the VM booting up to evaluate if there's 
some kernel
module during boot time that is using the PMU and causing the delay. I'll also 
take a look
into improving the performance as well (e.g. using more TCG code and avoid 
calling helpers).

It might be the case that the performance gain is enough to make these tests 
happy again,
although my initial guess is that there's something during boot that is 
starting the PMU and
leaving it running.


Thanks,


Daniel











Timeouts are especially tedious with gitlab, because they're not usually 
consistent, and often go away with a retry.  If I don't see the same failure on 
my local machine, I often let it go.

But in this case, the gitlab ci regression has been consistent, not passing a 
single time since.  Which makes me think this is not just a ci artifact, but 
that there's a real slowdown.  Could you please have a look?


r~




[PATCH] ps2: Initial horizontal scroll support

2021-12-20 Thread Dmitry Petrov
This patch introduces horizontal scroll support for the ps/2 mouse.
It includes changes in the ps/2 device driver as well as support
for three display options - cocoa, gtk and sdl, tested and working
on all of them against guest ubuntu system.

The patch is based on the previous work by Brad Jorsch done in 2010
but never merge, see
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=579968

Signed-off-by: Dmitry Petrov 
---
 hw/input/ps2.c| 54 ---
 qapi/ui.json  |  2 +-
 ui/cocoa.m| 18 ++--
 ui/gtk.c  | 54 ---
 ui/input-legacy.c | 16 ++
 ui/sdl2.c |  5 +
 6 files changed, 122 insertions(+), 27 deletions(-)

diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index 9376a8f4ce..9e42284cd9 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,38 @@ static int ps2_mouse_send_packet(PS2MouseState *s)
 else if (dz1 < -127)
 dz1 = -127;
 ps2_queue_noirq(>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 > 15) {
+dw1 = 15;
+} else if (dw1 < -15) {
+dw1 = -15;
+}
+
+/* 0x3f was found by trial and error vs ubuntu instance */
+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(>common, b);
 break;
 }
@@ -764,7 +794,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 +835,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 +868,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 +1073,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 d7567ac866..9dac1bf548 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -905,7 +905,7 @@
 ##
 { 'enum'  : 'InputButton',
   'data'  : [ 

Re: [PULL 00/15] *-user: simplify safe signal handling

2021-12-20 Thread Richard Henderson

On 12/20/21 12:24 PM, Richard Henderson wrote:

The following changes since commit 212a33d3b0c65ae2583bb1d06cb140cd0890894c:

   Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging 
(2021-12-19 16:36:10 -0800)

are available in the Git repository at:

   https://gitlab.com/rth7680/qemu.git tags/pull-user-20211220

for you to fetch changes up to 3363615a65af8a09d8adbd19ed3ae6b52f26ca7a:

   meson: Move bsd_user_ss to bsd-user/ (2021-12-20 10:13:43 -0800)


Move errno processing from safe_syscall() to safe_syscall_base().
Move safe_syscall() from linux-user to common-user.
Add FreeBSD support to safe_syscall_base().
Tidy top-level meson.build wrt {bsd,linux}-user.


Richard Henderson (15):
   linux-user: Untabify all safe-syscall.inc.S
   linux-user: Move syscall error detection into safe_syscall_base
   linux-user/host/mips: Add safe-syscall.inc.S
   linux-user/host/sparc64: Add safe-syscall.inc.S
   linux-user: Remove HAVE_SAFE_SYSCALL and hostdep.h
   linux-user: Rename TARGET_ERESTARTSYS to QEMU_ERESTARTSYS
   bsd-user: Rename TARGET_ERESTARTSYS to QEMU_ERESTARTSYS
   linux-user: Rename TARGET_QEMU_ESIGRETURN to QEMU_ESIGRETURN
   linux-user: Create special-errno.h
   bsd-user: Create special-errno.h
   common-user: Move safe-syscall.* from linux-user
   common-user: Adjust system call return on FreeBSD
   linux-user: Move thunk.c from top-level
   meson: Move linux_user_ss to linux-user/
   meson: Move bsd_user_ss to bsd-user/

  meson.build|  23 +++-
  bsd-user/errno_defs.h  |   6 +-
  bsd-user/special-errno.h   |  24 
  {linux-user => include/user}/safe-syscall.h|  37 ++
  linux-user/cpu_loop-common.h   |   1 +
  linux-user/generic/target_errno_defs.h |  17 ---
  linux-user/host/aarch64/hostdep.h  |  18 ---
  linux-user/host/arm/hostdep.h  |  18 ---
  linux-user/host/i386/hostdep.h |  18 ---
  linux-user/host/ia64/hostdep.h |  15 ---
  linux-user/host/mips/hostdep.h |  15 ---
  linux-user/host/ppc/hostdep.h  |  15 ---
  linux-user/host/ppc64/hostdep.h|  18 ---
  linux-user/host/riscv/hostdep.h|  14 --
  linux-user/host/s390/hostdep.h |  15 ---
  linux-user/host/s390x/hostdep.h|  18 ---
  linux-user/host/sparc/hostdep.h|  15 ---
  linux-user/host/sparc64/hostdep.h  |  15 ---
  linux-user/host/x32/hostdep.h  |  15 ---
  linux-user/host/x86_64/hostdep.h   |  18 ---
  linux-user/signal-common.h |   4 +-
  linux-user/special-errno.h |  32 +
  linux-user/user-internals.h|   1 -
  common-user/safe-syscall-error.c   |  25 
  linux-user/aarch64/cpu_loop.c  |   4 +-
  linux-user/aarch64/signal.c|   4 +-
  linux-user/alpha/cpu_loop.c|   4 +-
  linux-user/alpha/signal.c  |   8 +-
  linux-user/arm/cpu_loop.c  |   4 +-
  linux-user/arm/signal.c|   8 +-
  linux-user/cris/cpu_loop.c |   4 +-
  linux-user/cris/signal.c   |   4 +-
  linux-user/hexagon/cpu_loop.c  |   4 +-
  linux-user/hexagon/signal.c|   2 +-
  linux-user/hppa/cpu_loop.c |   4 +-
  linux-user/hppa/signal.c   |   4 +-
  linux-user/i386/cpu_loop.c |  12 +-
  linux-user/i386/signal.c   |   8 +-
  linux-user/m68k/cpu_loop.c |   4 +-
  linux-user/m68k/signal.c   |   8 +-
  linux-user/microblaze/cpu_loop.c   |   4 +-
  linux-user/microblaze/signal.c |   4 +-
  linux-user/mips/cpu_loop.c |   4 +-
  linux-user/mips/signal.c   |   8 +-
  linux-user/openrisc/cpu_loop.c |   4 +-
  linux-user/ppc/cpu_loop.c  |   4 +-
  linux-user/ppc/signal.c|  10 +-
  linux-user/riscv/cpu_loop.c|   4 +-
  linux-user/riscv/signal.c  |   2 +-
  linux-user/s390x/cpu_loop.c|   4 +-
  linux-user/s390x/signal.c  |   8 +-
  linux-user/sh4/cpu_loop.c  |   4 +-
  linux-user/sh4/signal.c|   8 +-
  linux-user/signa

Re: [PATCH 00/47] Patch Round-up for stable 6.1.1, freeze on 2021-12-21

2021-12-20 Thread Michael Roth via
On Tue, Dec 14, 2021 at 06:00:38PM -0600, Michael Roth wrote:
> Hi everyone,
> 
> The following new patches are queued for QEMU stable v6.1.1:
> 
>   https://gitlab.com/qemu-project/qemu/-/commits/stable-6.1-staging/
> 
> Patch freeze is 2021-12-21, and the release is planned for 2021-12-23:
> 
>   https://wiki.qemu.org/Planning/6.1
> 
> Please respond here or CC qemu-sta...@nongnu.org on any additional patches
> you think should (or shouldn't) be included in the release.

Thank you for the suggestions so far. The following additional patches have
been pushed to the staging tree:

  fddd169de5 tests: tcg: Fix PVH test with binutils 2.36+
  711bd602cc tcg/arm: Reduce vector alignment requirement for NEON
  e88636b4d4 target/i386: add missing bits to CR4_RESERVED_MASK
  34833f361b qxl: fix pre-save logic

  https://gitlab.com/mdroth/qemu/-/commits/stable-6.1-staging/

Patch freeze is 2021-21-21 EOD.

-Mike

> 
> Thanks!
> 
> 
> Ani Sinha (6):
>   bios-tables-test: allow changes in DSDT ACPI tables for q35
>   hw/i386/acpi: fix conflicting IO address range for acpi pci hotplug in 
> q35
>   bios-tables-test: Update ACPI DSDT table golden blobs for q35
>   tests/acpi/bios-tables-test: add and allow changes to a new q35 DSDT 
> table blob
>   tests/acpi/pcihp: add unit tests for hotplug on multifunction bridges 
> for q35
>   tests/acpi/bios-tables-test: update DSDT blob for multifunction bridge 
> test
> 
> Ari Sundholm (1):
>   block/file-posix: Fix return value translation for AIO discards
> 
> Christian Schoenebeck (1):
>   9pfs: fix crash in v9fs_walk()
> 
> Daniil Tatianin (1):
>   chardev/wctable: don't free the instance in wctablet_chr_finalize
> 
> David Hildenbrand (3):
>   virtio-balloon: don't start free page hinting if postcopy is possible
>   virtio-mem-pci: Fix memory leak when creating MEMORY_DEVICE_SIZE_CHANGE 
> event
>   libvhost-user: fix VHOST_USER_REM_MEM_REG skipping mmap_addr
> 
> Eric Blake (1):
>   nbd/server: Don't complain on certain client disconnects
> 
> Gerd Hoffmann (1):
>   uas: add stream number sanity checks.
> 
> Greg Kurz (2):
>   rcu: Introduce force_rcu notifier
>   accel/tcg: Register a force_rcu notifier
> 
> Helge Deller (1):
>   hw/display/artist: Fix bug in coordinate extraction in 
> artist_vram_read() and artist_vram_write()
> 
> Igor Mammedov (1):
>   pcie: rename 'native-hotplug' to 'x-native-hotplug'
> 
> Jason Wang (3):
>   virtio-net: fix use after unmap/free for sg
>   virtio: use virtio accessor to access packed descriptor flags
>   virtio: use virtio accessor to access packed event
> 
> Jean-Philippe Brucker (2):
>   hw/arm/virt: Rename default_bus_bypass_iommu
>   hw/i386: Rename default_bus_bypass_iommu
> 
> Jessica Clarke (1):
>   Partially revert "build: -no-pie is no functional linker flag"
> 
> Jon Maloy (1):
>   e1000: fix tx re-entrancy problem
> 
> Klaus Jensen (1):
>   hw/nvme: fix buffer overrun in nvme_changed_nslist (CVE-2021-3947)
> 
> Laurent Vivier (1):
>   hw: m68k: virt: Add compat machine for 6.1
> 
> Mahmoud Mandour (1):
>   plugins/execlog: removed unintended "s" at the end of log lines.
> 
> Mark Mielke (1):
>   virtio-blk: Fix clean up of host notifiers for single MR transaction.
> 
> Markus Armbruster (1):
>   hmp: Unbreak "change vnc"
> 
> Mauro Matteo Cascella (1):
>   hw/scsi/scsi-disk: MODE_PAGE_ALLS not allowed in MODE SELECT commands
> 
> Michael S. Tsirkin (1):
>   pci: fix PCI resource reserve capability on BE
> 
> Michael Tokarev (1):
>   qemu-sockets: fix unix socket path copy (again)
> 
> Nir Soffer (1):
>   qemu-nbd: Change default cache mode to writeback
> 
> Paolo Bonzini (4):
>   plugins: do not limit exported symbols if modules are active
>   block: introduce max_hw_iov for use in scsi-generic
>   target-i386: mmu: use pg_mode instead of HF_LMA_MASK
>   target-i386: mmu: fix handling of noncanonical virtual addresses
> 
> Peng Liang (1):
>   vfio: Fix memory leak of hostwin
> 
> Peter Maydell (1):
>   target/arm: Don't skip M-profile reset entirely in user mode
> 
> Philippe Mathieu-Daudé (3):
>   hw/block/fdc: Extract blk_create_empty_drive()
>   hw/block/fdc: Kludge missing floppy drive to fix CVE-2021-20196
>   tests/qtest/fdc-test: Add a regression test for CVE-2021-20196
> 
> Prasad J Pandit (1):
>   net: vmxnet3: validate configuration values during activate 
> (CVE-2021-20203)
> 
> Stefano Garzarella (1):
>   vhost-vsock: fix migration issue when seqpacket is supported
> 
> Xueming Li (1):
>   vhost-user: fix duplicated notifier MR init
> 
> Yang Zhong (1):
>   i386/cpu: Remove AVX_VNNI feature from Cooperlake cpu model
> 
>  accel/tcg/tcg-accel-ops-mttcg.c   |  26 
>  accel/tcg/tcg-accel-ops-rr.c  |  10 
>  

Re: [PATCH] pci: Skip power-off reset when pending unplug

2021-12-20 Thread Michael S. Tsirkin
On Mon, Dec 20, 2021 at 11:26:59AM -0700, Alex Williamson wrote:
> The below referenced commit introduced a change where devices under a
> root port slot are reset in response to removing power to the slot.
> This improves emulation relative to bare metal when the slot is powered
> off, but introduces an unnecessary step when devices under that slot
> are slated for removal.
> 
> In the case of an assigned device, there are mandatory delays
> associated with many device reset mechanisms which can stall the hot
> unplug operation.  Also, in cases where the unplug request is triggered
> via a release operation of the host driver, internal device locking in
> the host kernel may result in a failure of the device reset mechanism,
> which generates unnecessary log warnings.
> 
> Skip the reset for devices that are slated for unplug.
> 
> Cc: qemu-sta...@nongnu.org
> Fixes: d5daff7d3126 ("pcie: implement slot power control for pcie root ports")
> Signed-off-by: Alex Williamson 

I am not sure this is safe. IIUC pending_deleted_event
is normally set after host admin requested device removal,
while the reset could be triggered by guest for its own reasons
such as suspend or driver reload.

Looking at this some more, I am not sure I understand the
issue completely.
We have:

if ((sltsta & PCI_EXP_SLTSTA_PDS) && (val & PCI_EXP_SLTCTL_PCC) &&
(val & PCI_EXP_SLTCTL_PIC_OFF) == PCI_EXP_SLTCTL_PIC_OFF &&
(!(old_slt_ctl & PCI_EXP_SLTCTL_PCC) ||
(old_slt_ctl & PCI_EXP_SLTCTL_PIC_OFF) != PCI_EXP_SLTCTL_PIC_OFF)) {
pcie_cap_slot_do_unplug(dev);
}
pcie_cap_update_power(dev);

so device unplug triggers first, reset follows and by that time
there should be no devices under the bus, if there are then
it's because guest did not clear the power indicator.


So I am not sure how to fix the assignment issues as I'm not sure how do
they trigger, but here is a wild idea: maybe it should support an API
for starting reset asynchronously, then if the following access is
trying to reset again that second reset can just be skipped, while any
other access will stall.





> ---
>  hw/pci/pci.c |2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index e5993c1ef52b..f594da410797 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c
> @@ -2869,7 +2869,7 @@ void pci_set_power(PCIDevice *d, bool state)
>  memory_region_set_enabled(>bus_master_enable_region,
>(pci_get_word(d->config + PCI_COMMAND)
> & PCI_COMMAND_MASTER) && d->has_power);
> -if (!d->has_power) {
> +if (!d->has_power && !d->qdev.pending_deleted_event) {
>  pci_device_reset(d);
>  }
>  }
> 




RE: [PATCH v7 01/13] target/hexagon: update MAINTAINERS for idef-parser

2021-12-20 Thread Taylor Simpson



> -Original Message-
> From: Anton Johansson 
> Sent: Friday, December 17, 2021 2:01 AM
> To: qemu-devel@nongnu.org
> Cc: a...@rev.ng; Taylor Simpson ; Brian Cain
> ; bab...@rev.ng; ni...@rev.ng;
> richard.hender...@linaro.org
> Subject: [PATCH v7 01/13] target/hexagon: update MAINTAINERS for idef-
> parser
> 
> From: Alessandro Di Federico 
> 
> Signed-off-by: Alessandro Di Federico 
> Signed-off-by: Anton Johansson 
> Reviewed-by: Richard Henderson 
> ---
>  MAINTAINERS | 11 ++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7543eb4d59..f6fbc5f664 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS


> @@ -2788,7 +2797,7 @@ R: Paolo Bonzini 
>  R: Bandan Das 
>  R: Stefan Hajnoczi 
>  R: Thomas Huth 
> -R: Darren Kenny 
> +R: Darren Kenny 

This change looks spurious.  Otherwise
Reviewed-by: Taylor Simpson 



Re: [PATCH v4 07/24] linux-user: Remove TARGET_NSIGFPE

2021-12-20 Thread Philippe Mathieu-Daudé
On 12/20/21 22:05, Richard Henderson wrote:
> This define is unused, and we have no similar define for
> the other signal sub-codes.
> 
> Signed-off-by: Richard Henderson 
> ---
>  linux-user/syscall_defs.h | 1 -
>  1 file changed, 1 deletion(-)

Reviewed-by: Philippe Mathieu-Daudé 




  1   2   3   4   >