Re: [PATCH v2 23/23] test-clone-visitor: Correct an accidental rename

2021-09-24 Thread Markus Armbruster
Philippe Mathieu-Daudé  writes:

> On 9/17/21 16:31, Markus Armbruster wrote:
>> Commit b359f4b203 "tests: Rename UserDefNativeListUnion to
>> UserDefListUnion" renamed test_clone_native_list() to
>> test_clone_list_union().  The function has nothing to do with unions.
>> Rename it to test_clone_list().
>> 
>> Signed-off-by: Markus Armbruster 
>> Reviewed-by: Eric Blake 
>> ---
>>  tests/unit/test-clone-visitor.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> Maybe nitpicking, while this patch is related to the series,
> although I understand you noticed the mistake while working
> on this series, I'd move this cleanup as 1/23.

Not worth a respin.  Next time!

> Reviewed-by: Philippe Mathieu-Daudé 

Thanks!




Re: [PATCH v5 04/30] tcg/loongarch64: Add generated instruction opcodes and encoding helpers

2021-09-24 Thread WANG Xuerui

Hi all,

On 9/25/21 01:25, WANG Xuerui wrote:

Signed-off-by: WANG Xuerui 
Acked-by: Richard Henderson 
---
  tcg/loongarch64/tcg-insn-defs.c.inc | 979 
  1 file changed, 979 insertions(+)
  create mode 100644 tcg/loongarch64/tcg-insn-defs.c.inc
This patch series is only lacking Reviewed-by tag for this commit now; 
may I ask whose review do I additionally need to get this across the 
finish line? Or is this series waiting for upstream merge of toolchain 
and kernel support too?




Re: [PATCH v5 23/30] tcg/loongarch64: Add softmmu load/store helpers, implement qemu_ld/qemu_st ops

2021-09-24 Thread Richard Henderson

On 9/24/21 1:25 PM, WANG Xuerui wrote:

Signed-off-by: WANG Xuerui
---
  tcg/loongarch64/tcg-target-con-set.h |   2 +
  tcg/loongarch64/tcg-target.c.inc | 353 +++
  2 files changed, 355 insertions(+)


Reviewed-by: Richard Henderson 

r~



Re: [PATCH 14/14] bsd-user/signal: Create a dummy signal queueing function

2021-09-24 Thread Richard Henderson

On 9/24/21 4:11 PM, Warner Losh wrote:

It brings to mind something else... There's times it might be easier
to refactor between bsd-user and linux-user rather than upstream
something that's largely copied from linux-user. Is there a good
way to do that and talk about the design before I sink a ton of time
into something that's the wrong direction?


I certainly wouldn't mind a top-level user-only/ or posix-only/ in which we could share 
code between {linux,bsd}-user/, but I don't have a good idea of what that would look like.


Already you have code for MAP_EXCL that doesn't exist for linux (though there is a new, 
related, MAP_FIXED_NOREPLACE, which linux-user/ does not yet support).  So even with 
"obvious" routines I'm not sure how much real sharing we can get away with.


All I can say is: patches welcome, and we'll bike-shed them as they come.


r~



[PATCH v2] ui/gtk: skip any extra draw of same guest scanout blob res

2021-09-24 Thread Dongwon Kim
Any extra draw call for the same blob resource representing guest scanout
before the previous drawing is not finished can break synchronous draw
sequence. To prevent this, drawing is now done only once for each draw
submission (when draw_submitted == true).

v2:
 - removed mutex
 - updated commit msg

Cc: Gerd Hoffmann 
Cc: Vivek Kasireddy 
Signed-off-by: Dongwon Kim 
---
 hw/display/virtio-gpu-udmabuf.c |  2 +-
 include/ui/console.h|  1 +
 ui/gtk-egl.c| 40 ++-
 ui/gtk-gl-area.c| 49 -
 4 files changed, 59 insertions(+), 33 deletions(-)

diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
index c6f7f58784..60ea7f8f49 100644
--- a/hw/display/virtio-gpu-udmabuf.c
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -186,7 +186,7 @@ static VGPUDMABuf
 dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format);
 dmabuf->buf.fd = res->dmabuf_fd;
 dmabuf->buf.allow_fences = true;
-
+dmabuf->buf.draw_submitted = false;
 dmabuf->scanout_id = scanout_id;
 QTAILQ_INSERT_HEAD(>dmabuf.bufs, dmabuf, next);
 
diff --git a/include/ui/console.h b/include/ui/console.h
index 244664d727..b6bedc5f41 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -171,6 +171,7 @@ typedef struct QemuDmaBuf {
 void  *sync;
 int   fence_fd;
 bool  allow_fences;
+bool  draw_submitted;
 } QemuDmaBuf;
 
 typedef struct DisplayState DisplayState;
diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c
index 72ce5e1f8f..e912b20075 100644
--- a/ui/gtk-egl.c
+++ b/ui/gtk-egl.c
@@ -63,6 +63,9 @@ void gd_egl_init(VirtualConsole *vc)
 void gd_egl_draw(VirtualConsole *vc)
 {
 GdkWindow *window;
+#ifdef CONFIG_GBM
+QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+#endif
 int ww, wh;
 
 if (!vc->gfx.gls) {
@@ -74,10 +77,31 @@ void gd_egl_draw(VirtualConsole *vc)
 wh = gdk_window_get_height(window);
 
 if (vc->gfx.scanout_mode) {
+#ifdef CONFIG_GBM
+if (dmabuf) {
+if (!dmabuf->draw_submitted) {
+return;
+} else {
+dmabuf->draw_submitted = false;
+}
+}
+#endif
 gd_egl_scanout_flush(>gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h);
 
 vc->gfx.scale_x = (double)ww / vc->gfx.w;
 vc->gfx.scale_y = (double)wh / vc->gfx.h;
+
+glFlush();
+#ifdef CONFIG_GBM
+if (dmabuf) {
+egl_dmabuf_create_fence(dmabuf);
+if (dmabuf->fence_fd > 0) {
+qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, 
vc);
+return;
+}
+graphic_hw_gl_block(vc->gfx.dcl.con, false);
+}
+#endif
 } else {
 if (!vc->gfx.ds) {
 return;
@@ -92,21 +116,10 @@ void gd_egl_draw(VirtualConsole *vc)
 
 vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds);
 vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds);
-}
-
-glFlush();
-#ifdef CONFIG_GBM
-if (vc->gfx.guest_fb.dmabuf) {
-QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
 
-egl_dmabuf_create_fence(dmabuf);
-if (dmabuf->fence_fd > 0) {
-qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc);
-return;
-}
-graphic_hw_gl_block(vc->gfx.dcl.con, false);
+glFlush();
 }
-#endif
+
 graphic_hw_gl_flushed(vc->gfx.dcl.con);
 }
 
@@ -317,6 +330,7 @@ void gd_egl_flush(DisplayChangeListener *dcl,
 
 if (vc->gfx.guest_fb.dmabuf) {
 graphic_hw_gl_block(vc->gfx.dcl.con, true);
+vc->gfx.guest_fb.dmabuf->draw_submitted = true;
 gtk_widget_queue_draw_area(area, x, y, w, h);
 return;
 }
diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c
index b23523748e..20035aae38 100644
--- a/ui/gtk-gl-area.c
+++ b/ui/gtk-gl-area.c
@@ -38,6 +38,9 @@ static void gtk_gl_area_set_scanout_mode(VirtualConsole *vc, 
bool scanout)
 
 void gd_gl_area_draw(VirtualConsole *vc)
 {
+#ifdef CONFIG_GBM
+QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf;
+#endif
 int ww, wh, y1, y2;
 
 if (!vc->gfx.gls) {
@@ -53,6 +56,16 @@ void gd_gl_area_draw(VirtualConsole *vc)
 return;
 }
 
+#ifdef CONFIG_GBM
+if (dmabuf) {
+if (!dmabuf->draw_submitted) {
+return;
+} else {
+dmabuf->draw_submitted = false;
+}
+}
+#endif
+
 glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer);
 /* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */
 
@@ -62,6 +75,22 @@ void gd_gl_area_draw(VirtualConsole *vc)
 glBlitFramebuffer(0, y1, vc->gfx.w, y2,
   0, 0, ww, wh,
   GL_COLOR_BUFFER_BIT, GL_NEAREST);
+#ifdef CONFIG_GBM
+if (dmabuf) {
+egl_dmabuf_create_sync(dmabuf);
+}
+#endif
+glFlush();
+#ifdef CONFIG_GBM
+if (dmabuf) {

Re: [PATCH v2 2/6] qapi/parser: Allow empty QAPIDoc Sections

2021-09-24 Thread John Snow
On Tue, Sep 7, 2021 at 4:28 AM Markus Armbruster  wrote:

> John Snow  writes:
>
> > It simplifies the typing to say that _section is always a
> > QAPIDoc.Section().
>
> If you say so
>
>
I mean, I thought so at the time. I have an aversion to making optional
types and then littering isinstance() checks in places. I like keeping as
much of the typing statically provable as I can without adding runtime
checks. I'm re-evaluating this patch now, and I'll see if there's anything
I can do, but it's hard to predict differences in matters of taste and
style.

One thing an Optional[T] class instance variable can do that might be
helpful is to remind users that they need to check to see if it's present
or not. If I see a path to eliminate those checks, though, I will generally
always take it - eliminates the need to check everywhere else and puts all
the information you need into the static typing. As a habit, I prefer that
when feasible.

> To accommodate this change, we must allow for this object to evaluate to
> > False for functions like _end_section which behave differently based on
> > whether or not a Section has been started.
> >
> > Signed-off-by: John Snow 
> >
> > ---
> >
> > Probably a better fix is to restructure the code to prevent empty
> > sections from being "ended", but that seems like a bigger whale than
> > what I'm after at the immediate moment.
>
> Do we have a TODO comment for that?
>
>
Nope. I'll either add one or just fix the root issue, because I want to go
back to writing the cross-referenceable QAPI symbol plugin for sphinx now.
At the time I thought I'd get to fixing some of the issues raised by pt5 a
lot sooner, but.


> >
> > Signed-off-by: John Snow 
> > ---
> >  scripts/qapi/parser.py | 5 -
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/scripts/qapi/parser.py b/scripts/qapi/parser.py
> > index b6a5e661215..3ddde318376 100644
> > --- a/scripts/qapi/parser.py
> > +++ b/scripts/qapi/parser.py
> > @@ -456,6 +456,9 @@ def __init__(self, parser, name=None, indent=0):
> >  # the expected indent level of the text of this section
> >  self._indent = indent
> >
> > +def __bool__(self) -> bool:
> > +return bool(self.name or self.text)
> > +
> >  def append(self, line):
> >  # Strip leading spaces corresponding to the expected indent
> level
> >  # Blank lines are always OK.
>
> Overriding __bool__() is the minimally invasive compensation for the
> next hunk's replacement of None by a QAPIDoc.Section
>
> However, I'm wary of overriding __bool__().  It creates a difference
> between "if object:" and "if object is not None:".  Gives me a queasy
> feeling, as shortening the latter to the former is pretty much
> automatic.
>
>
That's just Python, though. If collections are empty, they're falsey. If
QAPIDoc is a collection of documentation lines and we have no lines,
shouldn't that also be falsey?

Nah, I get the apprehension. It's not a strictly linear collection and I
didn't check *every* last field, just name and text. It's kind of a hack
because I'm trying to paper over some deeper(?) problem(??), but it felt
safe because the static typing means we're not likely to confuse the two
cases -- we don't need to distinguish "Absent" from "empty". Or at least,
after this patch we don't need to, anymore. (We'll always have a section,
so an empty section versus no section makes no difference.)

A boring .is_empty() would avoid that, but we'd have to adjust "if S" to
> "if S.is_empty()" wherever we changed S from Optional[Section] to
> Section.  Which S could be affected?
>
>
Feels deeply against the grain of how Python is written to go out of your
way to create an .is_empty() function.


> The following variables get assigned Section or ArgSection:
>
> QAPIDoc.body
> QAPIDoc._section
> QAPIDoc.args[NAME]
> QAPIDoc.features[NAME]
>
> .body, .args[NAME] and .features[NAME] are never None I believe.
>
> ._section is also assigned None, in ._end_section().  It remains None
> until the next ._start*_section().
>
> The only use of .section that doesn't dot into it is in ._end_section().
> That's the only spot to adjust.
>
> Confirm by testing: in all of "make check", Section.__bool__() is only
> ever called from QAPIDoc._end_section().  Checked by sticking
> traceback.print_stack() into .__bool__().
>
>
If that's the only caller, isn't it then perfectly safe to just use the
patch as written?


> > @@ -722,7 +725,7 @@ def _end_section(self):
> >  raise QAPIParseError(
> >  self._parser,
> >  "empty doc section '%s'" % self._section.name)
> > -self._section = None
> > +self._section = QAPIDoc.Section(self._parser)
> >
> >  def _append_freeform(self, line):
> >  match = re.match(r'(@\S+:)', line)
>
> Replacing None by QAPIDoc.Section doesn't just simplify the typing!  It
> also creates a bogus 

Re: [External] Re: [RFC v7] virtio/vsock: add two more queues for datagram types

2021-09-24 Thread Jiang Wang .
On Thu, Sep 23, 2021 at 2:18 AM Stefano Garzarella  wrote:
>
> On Wed, Sep 22, 2021 at 10:36:24AM -0700, Jiang Wang . wrote:
> >On Wed, Sep 22, 2021 at 2:23 AM Stefano Garzarella  
> >wrote:
> >>
> >> On Wed, Sep 22, 2021 at 12:00:24AM +, Jiang Wang wrote:
> >> >Datagram sockets are connectionless and unreliable.
> >> >The sender does not know the capacity of the receiver
> >> >and may send more packets than the receiver can handle.
> >> >
> >> >Add two more dedicate virtqueues for datagram sockets,
> >> >so that it will not unfairly steal resources from
> >> >stream and future connection-oriented sockets.
> >> >
> >> >The two new virtqueues are enabled by default and will
> >> >be removed if the guest does not support. This will help
> >> >migration work.
> >> >
> >> >btw: enable_dgram argument in vhost_vsock_common_realize
> >> >is redundant for now, but will be used later when we
> >> >want to disable DGRAM feature bit for old versions.
> >> >
> >> >Signed-off-by: Jiang Wang 
> >> >---
> >> >v1 -> v2: use qemu cmd option to control number of queues,
> >> >removed configuration settings for dgram.
> >> >v2 -> v3: use ioctl to get features and decide number of
> >> >virt queues, instead of qemu cmd option.
> >> >v3 -> v4: change DGRAM feature bit value to 2. Add an argument
> >> >in vhost_vsock_common_realize to indicate dgram is supported or 
> >> > not.
> >> >v4 -> v5: don't open dev to get vhostfd. Removed leftover definition of
> >> >enable_dgram
> >> >v5 -> v6: fix style errors. Imporve error handling of
> >> >vhost_vsock_dgram_supported. Rename MAX_VQS_WITH_DGRAM and 
> >> > another one.
> >> >v6 -> v7: Always enable dgram for vhost-user and vhost kernel.
> >> >Delete unused virtqueues at the beginning of
> >> >vhost_vsock_common_start for migration. Otherwise, migration will 
> >> > fail.
> >> >
> >> > hw/virtio/vhost-user-vsock.c  |  2 +-
> >> > hw/virtio/vhost-vsock-common.c| 32 +--
> >> > hw/virtio/vhost-vsock.c   |  6 +++-
> >> > include/hw/virtio/vhost-vsock-common.h|  6 ++--
> >> > include/hw/virtio/vhost-vsock.h   |  3 ++
> >> > include/standard-headers/linux/virtio_vsock.h |  1 +
> >> > 6 files changed, 43 insertions(+), 7 deletions(-)
> >> >
> >> >diff --git a/hw/virtio/vhost-user-vsock.c b/hw/virtio/vhost-user-vsock.c
> >> >index 6095ed7349..9823a2f3bd 100644
> >> >--- a/hw/virtio/vhost-user-vsock.c
> >> >+++ b/hw/virtio/vhost-user-vsock.c
> >> >@@ -105,7 +105,7 @@ static void vuv_device_realize(DeviceState *dev, 
> >> >Error **errp)
> >> > return;
> >> > }
> >> >
> >> >-vhost_vsock_common_realize(vdev, "vhost-user-vsock");
> >> >+vhost_vsock_common_realize(vdev, "vhost-user-vsock", true);
> >> >
> >> > vhost_dev_set_config_notifier(>vhost_dev, _ops);
> >> >
> >> >diff --git a/hw/virtio/vhost-vsock-common.c 
> >> >b/hw/virtio/vhost-vsock-common.c
> >> >index 4ad6e234ad..7d89b4d242 100644
> >> >--- a/hw/virtio/vhost-vsock-common.c
> >> >+++ b/hw/virtio/vhost-vsock-common.c
> >> >@@ -26,6 +26,18 @@ int vhost_vsock_common_start(VirtIODevice *vdev)
> >> > int ret;
> >> > int i;
> >> >
> >> >+if (!virtio_has_feature(vdev->guest_features, VIRTIO_VSOCK_F_DGRAM)) 
> >> >{
> >> >+struct vhost_virtqueue *vqs;
> >> >+virtio_delete_queue(vvc->dgram_recv_vq);
> >> >+virtio_delete_queue(vvc->dgram_trans_vq);
> >> >+
> >>
> >> Are you sure it works removing queues here?
> >> The event_queue would always be #4, but the guest will use #2 which
> >> we're removing.
> >>
> >Yes, this works. In fact, I should include this in v6 and my tests done
> >in my previous emails have these changes. But before I submitted the patch,
> >I thought this code was redundant and removed it without further testing.
>
> Just tried on an host that doesn't support F_DGRAM and I have the
> following errors:
> qemu-system-x86_64: -device vhost-vsock-pci,guest-cid=6: vhost_set_vring_call 
> failed: No buffer space available (105)
> qemu-system-x86_64: -device vhost-vsock-pci,guest-cid=6: Failed to initialize 
> virtqueue 2: No buffer space available
>
> I thinks we should re-add the feature discovery before call
> vhost_dev_init().
>

Yes. You are right. I will add it back.

> >
> >To explain it, I think the event queue number does not matter for the
> >vhost and qemu. The vhost-vsock kernel module does not allocate any
> >data structure for the event queue.  Qemu also only allocates an array of
> >size 2 or 4 for the tx, rx queues. The event queue is handled separately.
> >
> >The event queue number only shows up in the spec, but in real code, I don't
> >see anywhere that the event queue number is used explicitly or implicitly.
> >The Event queue looks independent of tx, rx queues.
>
> Yep, it is used in the linux driver. Look at
> virtio_transport_event_work(), it uses VSOCK_VQ_EVENT (2).
>
Agree, it is used in virtio 

Re: [PATCH v4 01/35] acpi: add helper routines to initialize ACPI tables

2021-09-24 Thread Stefan Berger



On 9/24/21 8:27 AM, Igor Mammedov wrote:

Patch introduces acpi_table_begin()/ acpi_table_end() API
that hides pointer/offset arithmetic from user as opposed
to build_header(), to prevent errors caused by it [1].

  acpi_table_begin():
  initializes table header and keeps track of
  table data/offsets
  acpi_table_end():
  sets actual table length and tells bios loader
  where table is for the later initialization on
  guest side.

1) commits
bb9feea43179 x86: acpi: use offset instead of pointer when using 
build_header()
4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data 
address

Signed-off-by: Igor Mammedov 
Reviewed-by: Eric Auger 


Tested-by: Stefan Berger 



---
CC: eric.au...@redhat.com
---
  include/hw/acpi/aml-build.h | 31 +++
  hw/acpi/aml-build.c | 62 +
  2 files changed, 93 insertions(+)

diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 471266d739..4242382399 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -413,6 +413,37 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml 
*target);
  Aml *aml_object_type(Aml *object);

  void build_append_int_noprefix(GArray *table, uint64_t value, int size);
+
+typedef struct AcpiTable {
+const char *sig;
+const uint8_t rev;
+const char *oem_id;
+const char *oem_table_id;
+/* private vars tracking table state */
+GArray *array;
+unsigned table_offset;
+} AcpiTable;
+
+/**
+ * acpi_table_begin:
+ * initializes table header and keeps track of
+ * table data/offsets
+ * @desc: ACPI table descriptor
+ * @array: blob where the ACPI table will be composed/stored.
+ */
+void acpi_table_begin(AcpiTable *desc, GArray *array);
+
+/**
+ * acpi_table_end:
+ * sets actual table length and tells bios loader
+ * where table is for the later initialization on
+ * guest side.
+ * @linker: reference to BIOSLinker object to use for the table
+ * @table: ACPI table descriptor that was used with @acpi_table_begin
+ * counterpart
+ */
+void acpi_table_end(BIOSLinker *linker, AcpiTable *table);
+
  void
  build_header(BIOSLinker *linker, GArray *table_data,
   AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index d5103e6d7b..229a3eb654 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -52,6 +52,19 @@ static void build_append_byte(GArray *array, uint8_t val)
  g_array_append_val(array, val);
  }

+static void build_append_padded_str(GArray *array, const char *str,
+size_t maxlen, char pad)
+{
+size_t i;
+size_t len = strlen(str);
+
+g_assert(len <= maxlen);
+g_array_append_vals(array, str, len);
+for (i = maxlen - len; i > 0; i--) {
+g_array_append_val(array, pad);
+}
+}
+
  static void build_append_array(GArray *array, GArray *val)
  {
  g_array_append_vals(array, val->data, val->len);
@@ -1692,6 +1705,55 @@ Aml *aml_object_type(Aml *object)
  return var;
  }

+void acpi_table_begin(AcpiTable *desc, GArray *array)
+{
+
+desc->array = array;
+desc->table_offset = array->len;
+
+/*
+ * ACPI spec 1.0b
+ * 5.2.3 System Description Table Header
+ */
+g_assert(strlen(desc->sig) == 4);
+g_array_append_vals(array, desc->sig, 4); /* Signature */
+/*
+ * reserve space for Length field, which will be patched by
+ * acpi_table_end() when the table creation is finished.
+ */
+build_append_int_noprefix(array, 0, 4); /* Length */
+build_append_int_noprefix(array, desc->rev, 1); /* Revision */
+build_append_int_noprefix(array, 0, 1); /* Checksum */
+build_append_padded_str(array, desc->oem_id, 6, ' '); /* OEMID */
+/* OEM Table ID */
+build_append_padded_str(array, desc->oem_table_id, 8, ' ');
+build_append_int_noprefix(array, 1, 4); /* OEM Revision */
+g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */
+build_append_int_noprefix(array, 1, 4); /* Creator Revision */
+}
+
+void acpi_table_end(BIOSLinker *linker, AcpiTable *desc)
+{
+/*
+ * ACPI spec 1.0b
+ * 5.2.3 System Description Table Header
+ * Table 5-2 DESCRIPTION_HEADER Fields
+ */
+const unsigned checksum_offset = 9;
+uint32_t table_len = desc->array->len - desc->table_offset;
+uint32_t table_len_le = cpu_to_le32(table_len);
+gchar *len_ptr = >array->data[desc->table_offset + 4];
+
+/* patch "Length" field that has been reserved by acpi_table_begin()
+ * to the actual length, i.e. accumulated table length from
+ * acpi_table_begin() till acpi_table_end()
+ */
+memcpy(len_ptr, _len_le, sizeof table_len_le);
+
+bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
+desc->table_offset, table_len, desc->table_offset + checksum_offset);
+}
+
  void
  build_header(BIOSLinker *linker, GArray *table_data,

Re: [PATCH v4 15/35] acpi: build_tpm_tcpa: use acpi_table_begin()/acpi_table_end() instead of build_header()

2021-09-24 Thread Stefan Berger

On 9/24/21 8:27 AM, Igor Mammedov wrote:


it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

While at it switch to build_append_int_noprefix() to build
table entries (which also removes some manual offset
calculations).

Signed-off-by: Igor Mammedov 
Reviewed-by: Eric Auger 


Tested-by: Stefan Berger 



---
v2:
   * fix assert when starting QEMU with TPM 1.2
   Stefan Berger 
v3:
  * fix invalid checksum, by putting acpi_table_composed()
after pointer patching
  * s/acpi_init_table|acpi_table_composed/acpi_table_begin|acpi_table_end/

CC: stef...@linux.vnet.ibm.com
---
  include/hw/acpi/acpi-defs.h | 14 --
  hw/i386/acpi-build.c| 38 ++---
  2 files changed, 23 insertions(+), 29 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 4d8f8b34b0..3b42b138f0 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -418,20 +418,6 @@ struct AcpiSratProcessorGiccAffinity {

  typedef struct AcpiSratProcessorGiccAffinity AcpiSratProcessorGiccAffinity;

-/*
- * TCPA Description Table
- *
- * Following Level 00, Rev 00.37 of specs:
- * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
- */
-struct Acpi20Tcpa {
-ACPI_TABLE_HEADER_DEF/* ACPI common table header */
-uint16_t platform_class;
-uint32_t log_area_minimum_length;
-uint64_t log_area_start_address;
-} QEMU_PACKED;
-typedef struct Acpi20Tcpa Acpi20Tcpa;
-
  /* DMAR - DMA Remapping table r2.2 */
  struct AcpiTableDmar {
  ACPI_TABLE_HEADER_DEF
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 1587fe5a20..9fa6d7665b 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1878,31 +1878,39 @@ build_hpet(GArray *table_data, BIOSLinker *linker, 
const char *oem_id,
  }

  #ifdef CONFIG_TPM
+/*
+ * TCPA Description Table
+ *
+ * Following Level 00, Rev 00.37 of specs:
+ * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
+ * 7.1.2 ACPI Table Layout
+ */
  static void
  build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
 const char *oem_id, const char *oem_table_id)
  {
-int tcpa_start = table_data->len;
-Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa);
-unsigned log_addr_size = sizeof(tcpa->log_area_start_address);
-unsigned log_addr_offset =
-(char *)>log_area_start_address - table_data->data;
+unsigned log_addr_offset;
+AcpiTable table = { .sig = "TCPA", .rev = 2,
+.oem_id = oem_id, .oem_table_id = oem_table_id };

-tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT);
-tcpa->log_area_minimum_length = cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
-acpi_data_push(tcpalog, le32_to_cpu(tcpa->log_area_minimum_length));
+acpi_table_begin(, table_data);
+/* Platform Class */
+build_append_int_noprefix(table_data, TPM_TCPA_ACPI_CLASS_CLIENT, 2);
+/* Log Area Minimum Length (LAML) */
+build_append_int_noprefix(table_data, TPM_LOG_AREA_MINIMUM_SIZE, 4);
+/* Log Area Start Address (LASA) */
+log_addr_offset = table_data->len;
+build_append_int_noprefix(table_data, 0, 8);

+/* allocate/reserve space for TPM log area */
+acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
  bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, tcpalog, 1,
   false /* high memory */);
-
  /* log area start address to be filled by Guest linker */
-bios_linker_loader_add_pointer(linker,
-ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size,
-ACPI_BUILD_TPMLOG_FILE, 0);
+bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+log_addr_offset, 8, ACPI_BUILD_TPMLOG_FILE, 0);

-build_header(linker, table_data,
- (void *)(table_data->data + tcpa_start),
- "TCPA", sizeof(*tcpa), 2, oem_id, oem_table_id);
+acpi_table_end(linker, );
  }
  #endif





Re: [PATCH 14/14] bsd-user/signal: Create a dummy signal queueing function

2021-09-24 Thread Kyle Evans
On Fri, Sep 24, 2021 at 3:11 PM Warner Losh  wrote:
>
>
>
> On Fri, Sep 24, 2021 at 6:00 AM Richard Henderson 
>  wrote:
>>
>> On 9/21/21 11:14 PM, Warner Losh wrote:
>> > Create dummy signal queueing function so we can start to integrate other
>> > architectures (at the cost of signals remaining broken) to tame the
>> > dependency graph a bit and to bring in signals in a more controlled
>> > fashion.
>> >
>> > Signed-off-by: Warner Losh 
>> > ---
>> >   bsd-user/qemu.h   | 1 +
>> >   bsd-user/signal.c | 8 
>> >   2 files changed, 9 insertions(+)
>> >
>> > diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
>> > index 5a2fd87e44..85d1f8fd2a 100644
>> > --- a/bsd-user/qemu.h
>> > +++ b/bsd-user/qemu.h
>> > @@ -209,6 +209,7 @@ void process_pending_signals(CPUArchState *cpu_env);
>> >   void signal_init(void);
>> >   long do_sigreturn(CPUArchState *env);
>> >   long do_rt_sigreturn(CPUArchState *env);
>> > +int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
>> >   abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, 
>> > abi_ulong sp);
>> >
>> >   /* mmap.c */
>> > diff --git a/bsd-user/signal.c b/bsd-user/signal.c
>> > index ad6d935569..4e7f618944 100644
>> > --- a/bsd-user/signal.c
>> > +++ b/bsd-user/signal.c
>> > @@ -19,6 +19,14 @@
>> >   #include "qemu/osdep.h"
>> >
>> >   #include "qemu.h"
>> > +/*
>>
>> Whacky whitespace.
>
>
> fixed.
>
>>
>> > + * Queue a signal so that it will be send to the virtual CPU as soon as
>> > + * possible.
>> > + */
>> > +int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
>> > +{
>> > +return 1;
>> > +}
>>
>> Both here and in linux-user, there are no error conditions.  We should 
>> change the return
>> to void.
>
>
> I'll prep a patch to follow up for both linux and bsd user.
>
>>
>> Also, consider folding in the signal-common.h cleanup soon.
>> But don't let either hold you up too much with rebasing.
>
>
> It's on my list. This 'dummy' routine is just to get things linking to
> help simplify the rather tangled dependency tree to get things
> in, still have them compile and still have at least simple hello
> world continue to work. Behind these reviews are three streams
> of patches for 3 more architectures: arm, aarch64 and riscv64.
>
> I'll create a patch for both linux-user and fix in bsd-user as part of the
> signal.c upstreaming I'm working on.
>
> It brings to mind something else... There's times it might be easier
> to refactor between bsd-user and linux-user rather than upstream
> something that's largely copied from linux-user. Is there a good
> way to do that and talk about the design before I sink a ton of time
> into something that's the wrong direction?
>

I had a proposal on this list a long while back to refactor some stuff
into a top-level qemu-user that could be shared between the two,
starting with safe_syscall (which syscall can be substantially
shared), but it hadn't received any traction at that time.

Thanks,

Kyle Evans



Re: [PATCH 14/14] bsd-user/signal: Create a dummy signal queueing function

2021-09-24 Thread Warner Losh
On Fri, Sep 24, 2021 at 6:00 AM Richard Henderson <
richard.hender...@linaro.org> wrote:

> On 9/21/21 11:14 PM, Warner Losh wrote:
> > Create dummy signal queueing function so we can start to integrate other
> > architectures (at the cost of signals remaining broken) to tame the
> > dependency graph a bit and to bring in signals in a more controlled
> > fashion.
> >
> > Signed-off-by: Warner Losh 
> > ---
> >   bsd-user/qemu.h   | 1 +
> >   bsd-user/signal.c | 8 
> >   2 files changed, 9 insertions(+)
> >
> > diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
> > index 5a2fd87e44..85d1f8fd2a 100644
> > --- a/bsd-user/qemu.h
> > +++ b/bsd-user/qemu.h
> > @@ -209,6 +209,7 @@ void process_pending_signals(CPUArchState *cpu_env);
> >   void signal_init(void);
> >   long do_sigreturn(CPUArchState *env);
> >   long do_rt_sigreturn(CPUArchState *env);
> > +int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info);
> >   abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr,
> abi_ulong sp);
> >
> >   /* mmap.c */
> > diff --git a/bsd-user/signal.c b/bsd-user/signal.c
> > index ad6d935569..4e7f618944 100644
> > --- a/bsd-user/signal.c
> > +++ b/bsd-user/signal.c
> > @@ -19,6 +19,14 @@
> >   #include "qemu/osdep.h"
> >
> >   #include "qemu.h"
> > +/*
>
> Whacky whitespace.
>

fixed.


> > + * Queue a signal so that it will be send to the virtual CPU as soon as
> > + * possible.
> > + */
> > +int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
> > +{
> > +return 1;
> > +}
>
> Both here and in linux-user, there are no error conditions.  We should
> change the return
> to void.
>

I'll prep a patch to follow up for both linux and bsd user.


> Also, consider folding in the signal-common.h cleanup soon.
> But don't let either hold you up too much with rebasing.
>

It's on my list. This 'dummy' routine is just to get things linking to
help simplify the rather tangled dependency tree to get things
in, still have them compile and still have at least simple hello
world continue to work. Behind these reviews are three streams
of patches for 3 more architectures: arm, aarch64 and riscv64.

I'll create a patch for both linux-user and fix in bsd-user as part of the
signal.c upstreaming I'm working on.

It brings to mind something else... There's times it might be easier
to refactor between bsd-user and linux-user rather than upstream
something that's largely copied from linux-user. Is there a good
way to do that and talk about the design before I sink a ton of time
into something that's the wrong direction?

Thanks for the reviews and feedback.

Warner


> Reviewed-by: Richard Henderson 
>
> r~
>


[PATCH 1/5] fuse: Header file changes for FUSE_SECURITY_CTX

2021-09-24 Thread Vivek Goyal
These are just header file changes which should show up in qemu if
corresponding kernel changes get merged.

Signed-off-by: Vivek Goyal 
---
 include/standard-headers/linux/fuse.h | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/include/standard-headers/linux/fuse.h 
b/include/standard-headers/linux/fuse.h
index cce105bfba..9e1672fbb2 100644
--- a/include/standard-headers/linux/fuse.h
+++ b/include/standard-headers/linux/fuse.h
@@ -181,6 +181,10 @@
  *  - add FUSE_OPEN_KILL_SUIDGID
  *  - extend fuse_setxattr_in, add FUSE_SETXATTR_EXT
  *  - add FUSE_SETXATTR_ACL_KILL_SGID
+ *
+ *  7.35
+ *  - add FUSE_SECURITY_CTX flag for fuse_init_out
+ *  - add security context to create, mkdir, symlink, and mknod requests
  */
 
 #ifndef _LINUX_FUSE_H
@@ -212,7 +216,7 @@
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 33
+#define FUSE_KERNEL_MINOR_VERSION 35
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -329,6 +333,8 @@ struct fuse_file_lock {
  * write/truncate sgid is killed only if file has group
  * execute permission. (Same as Linux VFS behavior).
  * FUSE_SETXATTR_EXT:  Server supports extended struct fuse_setxattr_in
+ * FUSE_SECURITY_CTX:  add security context to create, mkdir, symlink, and
+ * mknod
  */
 #define FUSE_ASYNC_READ(1 << 0)
 #define FUSE_POSIX_LOCKS   (1 << 1)
@@ -360,6 +366,7 @@ struct fuse_file_lock {
 #define FUSE_SUBMOUNTS (1 << 27)
 #define FUSE_HANDLE_KILLPRIV_V2(1 << 28)
 #define FUSE_SETXATTR_EXT  (1 << 29)
+#define FUSE_SECURITY_CTX  (1 << 30)
 
 /**
  * CUSE INIT request/reply flags
@@ -967,4 +974,9 @@ struct fuse_removemapping_one {
 #define FUSE_REMOVEMAPPING_MAX_ENTRY   \
(PAGE_SIZE / sizeof(struct fuse_removemapping_one))
 
+struct fuse_secctx {
+   uint32_tsize;
+   uint32_tpadding;
+};
+
 #endif /* _LINUX_FUSE_H */
-- 
2.31.1




[PATCH 2/5] fuse_lowlevel.c: Add capability to parse security context

2021-09-24 Thread Vivek Goyal
Add capability to enable and parse security context as sent by client
and put into fuse_req. Filesystems now can get security context from
request and set it on files during creation.

Signed-off-by: Vivek Goyal 
---
 tools/virtiofsd/fuse_common.h   |  5 +++
 tools/virtiofsd/fuse_i.h|  7 
 tools/virtiofsd/fuse_lowlevel.c | 74 +
 3 files changed, 86 insertions(+)

diff --git a/tools/virtiofsd/fuse_common.h b/tools/virtiofsd/fuse_common.h
index 0c2665b977..6f3485d1dc 100644
--- a/tools/virtiofsd/fuse_common.h
+++ b/tools/virtiofsd/fuse_common.h
@@ -377,6 +377,11 @@ struct fuse_file_info {
  */
 #define FUSE_CAP_SETXATTR_EXT (1 << 29)
 
+/**
+ * Indicates that file server supports creating file security context
+ */
+#define FUSE_CAP_SECURITY_CTX (1 << 30)
+
 /**
  * Ioctl flags
  *
diff --git a/tools/virtiofsd/fuse_i.h b/tools/virtiofsd/fuse_i.h
index 492e002181..a5572fa4ae 100644
--- a/tools/virtiofsd/fuse_i.h
+++ b/tools/virtiofsd/fuse_i.h
@@ -15,6 +15,12 @@
 struct fv_VuDev;
 struct fv_QueueInfo;
 
+struct fuse_security_context {
+const char *name;
+uint32_t ctxlen;
+const void *ctx;
+};
+
 struct fuse_req {
 struct fuse_session *se;
 uint64_t unique;
@@ -35,6 +41,7 @@ struct fuse_req {
 } u;
 struct fuse_req *next;
 struct fuse_req *prev;
+struct fuse_security_context secctx;
 };
 
 struct fuse_notify_req {
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c
index e4679c73ab..fae92e0f3f 100644
--- a/tools/virtiofsd/fuse_lowlevel.c
+++ b/tools/virtiofsd/fuse_lowlevel.c
@@ -886,11 +886,41 @@ static void do_readlink(fuse_req_t req, fuse_ino_t nodeid,
 }
 }
 
+static int parse_secctx_fill_req(fuse_req_t req, struct fuse_mbuf_iter *iter)
+{
+struct fuse_secctx *fsecctx;
+const void *secctx;
+
+fsecctx = fuse_mbuf_iter_advance(iter, sizeof(*fsecctx));
+if (!fsecctx) {
+return -EINVAL;
+}
+
+if (fsecctx->size) {
+const char *name = fuse_mbuf_iter_advance_str(iter);
+if (!name) {
+return -EINVAL;
+}
+
+secctx = fuse_mbuf_iter_advance(iter, fsecctx->size);
+if (!secctx) {
+return -EINVAL;
+}
+
+req->secctx.name = name;
+req->secctx.ctx = secctx;
+req->secctx.ctxlen = fsecctx->size;
+}
+return 0;
+}
+
 static void do_mknod(fuse_req_t req, fuse_ino_t nodeid,
  struct fuse_mbuf_iter *iter)
 {
 struct fuse_mknod_in *arg;
 const char *name;
+bool secctx_enabled = req->se->conn.want & FUSE_CAP_SECURITY_CTX;
+int err;
 
 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
 name = fuse_mbuf_iter_advance_str(iter);
@@ -901,6 +931,13 @@ static void do_mknod(fuse_req_t req, fuse_ino_t nodeid,
 
 req->ctx.umask = arg->umask;
 
+if (secctx_enabled) {
+err = parse_secctx_fill_req(req, iter);
+if (err) {
+fuse_reply_err(req, -err);
+}
+}
+
 if (req->se->op.mknod) {
 req->se->op.mknod(req, nodeid, name, arg->mode, arg->rdev);
 } else {
@@ -913,6 +950,8 @@ static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid,
 {
 struct fuse_mkdir_in *arg;
 const char *name;
+bool secctx_enabled = req->se->conn.want & FUSE_CAP_SECURITY_CTX;
+int err;
 
 arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
 name = fuse_mbuf_iter_advance_str(iter);
@@ -923,6 +962,13 @@ static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid,
 
 req->ctx.umask = arg->umask;
 
+if (secctx_enabled) {
+err = parse_secctx_fill_req(req, iter);
+if (err) {
+fuse_reply_err(req, err);
+}
+}
+
 if (req->se->op.mkdir) {
 req->se->op.mkdir(req, nodeid, name, arg->mode);
 } else {
@@ -969,12 +1015,21 @@ static void do_symlink(fuse_req_t req, fuse_ino_t nodeid,
 {
 const char *name = fuse_mbuf_iter_advance_str(iter);
 const char *linkname = fuse_mbuf_iter_advance_str(iter);
+bool secctx_enabled = req->se->conn.want & FUSE_CAP_SECURITY_CTX;
+int err;
 
 if (!name || !linkname) {
 fuse_reply_err(req, EINVAL);
 return;
 }
 
+if (secctx_enabled) {
+err = parse_secctx_fill_req(req, iter);
+if (err) {
+fuse_reply_err(req, err);
+}
+}
+
 if (req->se->op.symlink) {
 req->se->op.symlink(req, linkname, nodeid, name);
 } else {
@@ -1048,6 +1103,8 @@ static void do_link(fuse_req_t req, fuse_ino_t nodeid,
 static void do_create(fuse_req_t req, fuse_ino_t nodeid,
   struct fuse_mbuf_iter *iter)
 {
+bool secctx_enabled = req->se->conn.want & FUSE_CAP_SECURITY_CTX;
+
 if (req->se->op.create) {
 struct fuse_create_in *arg;
 struct fuse_file_info fi;
@@ -1060,6 +1117,15 @@ static void do_create(fuse_req_t req, fuse_ino_t nodeid,
 return;
 }
 
+if (secctx_enabled) {
+int 

[PATCH 3/5] virtiofsd: Move core file creation code in separate function

2021-09-24 Thread Vivek Goyal
Move core file creation bits in a separate function. Soon this is going
to get more complex as file creation need to set security context also.
And there will be multiple modes of file creation in next patch.

Signed-off-by: Vivek Goyal 
---
 tools/virtiofsd/passthrough_ll.c | 36 ++--
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index 64b5b4fbb1..54978b7fae 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -1976,6 +1976,30 @@ static int lo_do_open(struct lo_data *lo, struct 
lo_inode *inode,
 return 0;
 }
 
+static int do_lo_create(fuse_req_t req, struct lo_inode *parent_inode,
+const char *name, mode_t mode,
+struct fuse_file_info *fi, int* open_fd)
+{
+int err = 0, fd;
+struct lo_cred old = {};
+struct lo_data *lo = lo_data(req);
+
+err = lo_change_cred(req, , lo->change_umask);
+if (err) {
+return err;
+}
+
+/* Try to create a new file but don't open existing files */
+fd = openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mode);
+if (fd == -1) {
+err = errno;
+} else {
+*open_fd = fd;
+}
+lo_restore_cred(, lo->change_umask);
+return err;
+}
+
 static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
   mode_t mode, struct fuse_file_info *fi)
 {
@@ -1985,7 +2009,6 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, 
const char *name,
 struct lo_inode *inode = NULL;
 struct fuse_entry_param e;
 int err;
-struct lo_cred old = {};
 
 fuse_log(FUSE_LOG_DEBUG, "lo_create(parent=%" PRIu64 ", name=%s)"
  " kill_priv=%d\n", parent, name, fi->kill_priv);
@@ -2001,18 +2024,9 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, 
const char *name,
 return;
 }
 
-err = lo_change_cred(req, , lo->change_umask);
-if (err) {
-goto out;
-}
-
 update_open_flags(lo->writeback, lo->allow_direct_io, fi);
 
-/* Try to create a new file but don't open existing files */
-fd = openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mode);
-err = fd == -1 ? errno : 0;
-
-lo_restore_cred(, lo->change_umask);
+err = do_lo_create(req, parent_inode, name, mode, fi, );
 
 /* Ignore the error if file exists and O_EXCL was not given */
 if (err && (err != EEXIST || (fi->flags & O_EXCL))) {
-- 
2.31.1




[PATCH 0/5] virtiofsd: Add support for file security context at creation

2021-09-24 Thread Vivek Goyal
Hi,

These patches add support to receive and set file security context at
the time of file creation. This is one of the components needed to
support SELinux on virtiofs.

I have posted kernel patches here just now.

https://lore.kernel.org/linux-fsdevel/20210924192442.916927-1-vgo...@redhat.com/T/#m971f9001dd622b3f7a96a65899e3f146d2185841

These patches will allow users to configure virtiofsd in multiple modes
to set security context.

A. Guest and host selinux policies can work with each other.
- virtiofsd will use /proc/thread-self/attr/fscreate knob to
  set security context before file creation.

B. Remap guest selinux security xattr to something else say,
   trusted.virtiofs.security.selinux.
- Give CAP_SYS_ADMIN to virtiofsd.
- "-o -o xattrmap=:map:security.selinux:trusted.virtiofsd.:"

C. If no SELinux on host.
- Give CAP_SYS_ADMIN to virtiofsd. 

I have tested mode A and B but yet to test mode C.

I think either mode B or mode C will be most commonly used mode when
guest does need SELinux support in virtiofs.

With these patches, I am able to boot a guest VM with rootfs on virtiofs
and with SELinux enabled in guest. 

Please review.

Thanks
Vivek


Vivek Goyal (5):
  fuse: Header file changes for FUSE_SECURITY_CTX
  fuse_lowlevel.c: Add capability to parse security context
  virtiofsd: Move core file creation code in separate function
  virtiofsd: Create new file with fscreate set
  virtiofsd: Create new file using O_TMPFILE and set security context

 include/standard-headers/linux/fuse.h |  14 +-
 tools/virtiofsd/fuse_common.h |   5 +
 tools/virtiofsd/fuse_i.h  |   7 +
 tools/virtiofsd/fuse_lowlevel.c   |  74 ++
 tools/virtiofsd/passthrough_ll.c  | 366 --
 5 files changed, 436 insertions(+), 30 deletions(-)

-- 
2.31.1




[PATCH 4/5] virtiofsd: Create new file with fscreate set

2021-09-24 Thread Vivek Goyal
This patch adds support to set /proc/thread-self/attr/fscreate before
file creation. It is set to a value as sent by client. This will allow
for atomic creation of security context on files w.r.t file creation.

This is primarily useful when either there is no SELinux enabled on
host or host and guest policies are in sync and don't conflict.

Signed-off-by: Vivek Goyal 
---
 tools/virtiofsd/passthrough_ll.c | 284 ---
 1 file changed, 257 insertions(+), 27 deletions(-)

diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index 54978b7fae..d8c14d3220 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -172,6 +172,8 @@ struct lo_data {
 
 /* An O_PATH file descriptor to /proc/self/fd/ */
 int proc_self_fd;
+/* An O_PATH file descriptor to /proc/self/task/ */
+int proc_self_task;
 int user_killpriv_v2, killpriv_v2;
 /* If set, virtiofsd is responsible for setting umask during creation */
 bool change_umask;
@@ -229,6 +231,11 @@ static struct lo_inode *lo_find(struct lo_data *lo, struct 
stat *st,
 static int xattr_map_client(const struct lo_data *lo, const char *client_name,
 char **out_name);
 
+#define FCHDIR_NOFAIL(fd) do { \
+int fchdir_res = fchdir(fd);   \
+assert(fchdir_res == 0);   \
+} while (0)
+
 static bool is_dot_or_dotdot(const char *name)
 {
 return name[0] == '.' &&
@@ -1259,16 +1266,140 @@ static void lo_restore_cred_gain_cap(struct lo_cred 
*old, bool restore_umask,
 }
 }
 
+/* Helpers to set/reset fscreate */
+static int open_set_proc_fscreate(struct lo_data *lo, const void *ctx,
+  size_t ctxlen, int *fd)
+{
+char procname[64];
+int fscreate_fd, err = 0;
+size_t written;
+
+sprintf(procname, "%d/attr/fscreate", gettid());
+fscreate_fd = openat(lo->proc_self_task, procname, O_WRONLY);
+err = fscreate_fd == -1 ? errno : 0;
+if (err) {
+return err;
+}
+
+written = write(fscreate_fd, ctx, ctxlen);
+err = written == -1 ? errno : 0;
+if (err) {
+goto out;
+}
+
+*fd = fscreate_fd;
+return 0;
+out:
+close(fscreate_fd);
+return err;
+}
+
+static void close_reset_proc_fscreate(int fd)
+{
+if ((write(fd, NULL, 0)) == -1) {
+fuse_log(FUSE_LOG_WARNING, "Failed to reset fscreate. err=%d\n", 
errno);
+}
+close(fd);
+return;
+}
+
+static int do_mknod_symlink_secctx(fuse_req_t req, struct lo_inode *dir,
+   const char *name, const char *secctx_name)
+{
+int path_fd, err;
+char procname[64];
+struct lo_data *lo = lo_data(req);
+
+if (!req->secctx.ctxlen) {
+return 0;
+}
+
+/* Open newly created element with O_PATH */
+path_fd = openat(dir->fd, name, O_PATH | O_NOFOLLOW);
+err = path_fd == -1 ? errno : 0;
+if (err) {
+return err;
+}
+sprintf(procname, "%i", path_fd);
+FCHDIR_NOFAIL(lo->proc_self_fd);
+/* Set security context. This is not atomic w.r.t file creation */
+err = setxattr(procname, secctx_name, req->secctx.ctx, req->secctx.ctxlen,
+   0);
+if (err) {
+err = errno;
+}
+FCHDIR_NOFAIL(lo->root.fd);
+close(path_fd);
+return err;
+}
+
+static int do_mknod_symlink(fuse_req_t req, struct lo_inode *dir,
+const char *name, mode_t mode, dev_t rdev,
+const char *link)
+{
+int err, fscreate_fd = -1;
+const char *secctx_name = req->secctx.name;
+struct lo_cred old = {};
+struct lo_data *lo = lo_data(req);
+char *mapped_name = NULL;
+bool secctx_enabled = req->secctx.ctxlen;
+bool do_fscreate = false;
+
+if (secctx_enabled && lo->xattrmap) {
+err = xattr_map_client(lo, req->secctx.name, _name);
+if (err < 0) {
+return -err;
+}
+secctx_name = mapped_name;
+}
+
+/*
+ * If security xattr has not been remapped, set fscreate and no
+ * need to do a setxattr() after file creation
+ */
+if (secctx_enabled && !mapped_name) {
+do_fscreate = true;
+err = open_set_proc_fscreate(lo, req->secctx.ctx, req->secctx.ctxlen,
+ _fd);
+if (err) {
+goto out;
+}
+}
+
+err = lo_change_cred(req, , lo->change_umask && !S_ISLNK(mode));
+if (err) {
+goto out;
+}
+
+err = mknod_wrapper(dir->fd, name, link, mode, rdev);
+err = err == -1 ? errno : 0;
+lo_restore_cred(, lo->change_umask && !S_ISLNK(mode));
+if (err) {
+goto out;
+}
+
+if (!do_fscreate) {
+err = do_mknod_symlink_secctx(req, dir, name, secctx_name);
+if (err) {
+unlinkat(dir->fd, name, S_ISDIR(mode) ? AT_REMOVEDIR : 0);
+}
+}
+out:
+if 

[PATCH 5/5] virtiofsd: Create new file using O_TMPFILE and set security context

2021-09-24 Thread Vivek Goyal
If guest and host policies can't work with each other, then guest security
context (selinux label) needs to be set into an xattr. Say remap guest
security.selinux xattr to trusted.virtiofs.security.selinux.

That means setting "fscreate" is not going to help as that's ony useful
for security.selinux xattr on host.

So we need another method which is atomic. Use O_TMPFILE to create new
file, set xattr and then linkat() to proper place.

But this works only for regular files. So dir, symlinks will continue
to be non-atomic.

Also if host filesystem does not support O_TMPFILE, we fallback to
non-atomic behavior.

Signed-off-by: Vivek Goyal 
---
 tools/virtiofsd/passthrough_ll.c | 78 +---
 1 file changed, 71 insertions(+), 7 deletions(-)

diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index d8c14d3220..f5c3746510 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -2099,14 +2099,29 @@ static int lo_do_open(struct lo_data *lo, struct 
lo_inode *inode,
 
 static int do_create_nosecctx(fuse_req_t req, struct lo_inode *parent_inode,
const char *name, mode_t mode,
-   struct fuse_file_info *fi, int *open_fd)
+   struct fuse_file_info *fi, int *open_fd,
+  bool tmpfile)
 {
 int err, fd;
 struct lo_cred old = {};
 struct lo_data *lo = lo_data(req);
 int flags;
 
-flags = fi->flags | O_CREAT | O_EXCL;
+if (tmpfile) {
+flags = fi->flags | O_TMPFILE;
+/*
+ * Don't use O_EXCL as we want to link file later. Also reset O_CREAT
+ * otherwise openat() returns -EINVAL.
+ */
+flags &= ~(O_CREAT | O_EXCL);
+
+/* O_TMPFILE needs either O_RDWR or O_WRONLY */
+if ((flags & O_ACCMODE) == O_RDONLY) {
+flags |= O_RDWR;
+}
+} else {
+flags = fi->flags | O_CREAT | O_EXCL;
+}
 
 err = lo_change_cred(req, , lo->change_umask);
 if (err) {
@@ -2137,7 +2152,7 @@ static int do_create_secctx_fscreate(fuse_req_t req,
 return err;
 }
 
-err = do_create_nosecctx(req, parent_inode, name, mode, fi, );
+err = do_create_nosecctx(req, parent_inode, name, mode, fi, , false);
 
 close_reset_proc_fscreate(fscreate_fd);
 if (!err) {
@@ -2146,6 +2161,44 @@ static int do_create_secctx_fscreate(fuse_req_t req,
 return err;
 }
 
+static int do_create_secctx_tmpfile(fuse_req_t req,
+struct lo_inode *parent_inode,
+const char *name, mode_t mode,
+struct fuse_file_info *fi,
+const char *secctx_name, int *open_fd)
+{
+int err, fd = -1;
+struct lo_data *lo = lo_data(req);
+char procname[64];
+
+err = do_create_nosecctx(req, parent_inode, ".", mode, fi, , true);
+if (err) {
+return err;
+}
+
+err = fsetxattr(fd, secctx_name, req->secctx.ctx, req->secctx.ctxlen, 0);
+if (err) {
+err = errno;
+goto out;
+}
+
+/* Security context set on file. Link it in place */
+sprintf(procname, "%d", fd);
+FCHDIR_NOFAIL(lo->proc_self_fd);
+err = linkat(AT_FDCWD, procname, parent_inode->fd, name,
+ AT_SYMLINK_FOLLOW);
+err = err == -1 ? errno : 0;
+FCHDIR_NOFAIL(lo->root.fd);
+
+out:
+if (!err) {
+*open_fd = fd;
+} else if (fd != -1) {
+close(fd);
+}
+return err;
+}
+
 static int do_create_secctx_noatomic(fuse_req_t req,
  struct lo_inode *parent_inode,
  const char *name, mode_t mode,
@@ -2154,7 +2207,7 @@ static int do_create_secctx_noatomic(fuse_req_t req,
 {
 int err = 0, fd = -1;
 
-err = do_create_nosecctx(req, parent_inode, name, mode, fi, );
+err = do_create_nosecctx(req, parent_inode, name, mode, fi, , false);
 if (err) {
 goto out;
 }
@@ -2196,20 +2249,31 @@ static int do_lo_create(fuse_req_t req, struct lo_inode 
*parent_inode,
 if (secctx_enabled) {
 /*
  * If security.selinux has not been remapped. Use fscreate to set
- * context before file creation.
- * Otherwise fallback to non-atomic method of file creation
+ * context before file creation. Use tempfile method for regular
+ * files. Otherwise fallback to non-atomic method of file creation
  * and xattr settting.
  */
 if (!mapped_name) {
 err = do_create_secctx_fscreate(req, parent_inode, name, mode, fi,
 open_fd);
 goto out;
+} else if (S_ISREG(mode)) {
+err = do_create_secctx_tmpfile(req, parent_inode, name, mode, fi,
+   ctxname, open_fd);
+/*
+ * 

Re: [PATCH 05/16] Acceptance Tests: add standard clean up at test tearDown()

2021-09-24 Thread Willian Rampazzo
Hi, Cleber,

On Fri, Sep 24, 2021 at 3:57 PM Cleber Rosa  wrote:
>
> The avocado.Test class, used as the basis of the avocado_qemu.Test
> class, performs a clean of temporary directories up as part of its own
> tearDown() implementation.
>
> But the avocado_qemu.Test class is currently missing the same clean
> up, as it implemented its own tearDown() method without resorting to
> the upper class behavior.
>
> This brings avocado_qemu.Test behavior in sync with the standard
> avocado.Test behavior and prevents temporary directories from
> cluttering the test results directory (unless instructed to do so with
> Avocado's "--keep-tmp" option).
>
> Reported-by: Peter Maydell 
> Signed-off-by: Cleber Rosa 
> ---
>  tests/acceptance/avocado_qemu/__init__.py | 1 +
>  1 file changed, 1 insertion(+)
>

There was a comment from Wainer in the original patch and as you were
on vacation I submitted a respin last Monday:

https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg05117.html

I also did some refactoring/fixes to the avocado_qemu here:

https://lists.gnu.org/archive/html/qemu-devel/2021-09/msg05212.html




Re: [PATCH v3 1/9] nbd/client-connection: nbd_co_establish_connection(): fix non set errp

2021-09-24 Thread Eric Blake
On Tue, Sep 07, 2021 at 12:44:53PM -0500, Eric Blake wrote:
> On Mon, Sep 06, 2021 at 10:06:46PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> > When we don't have a connection and blocking is false, we return NULL
> > but don't set errp. That's wrong.
> 
> Oops...
> 
> > 
> > We have two paths for calling nbd_co_establish_connection():
> > 
> > 1. nbd_open() -> nbd_do_establish_connection() -> ...
> >   but that will never set blocking=false
> > 
> > 2. nbd_reconnect_attempt() -> nbd_co_do_establish_connection() -> ...
> >   but that uses errp=NULL
> > 
> > So, we are safe with our wrong errp policy in
> > nbd_co_establish_connection(). Still let's fix it.
> 
> ...phew!  Thus, it's not critical to backport.
> 
> Reviewed-by: Eric Blake 

Queuing this one through my NBD tree.  Given the discussion on 2/9,
I'll leave the rest of the series for later.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH] nbd/server: Allow LIST_META_CONTEXT without STRUCTURED_REPLY

2021-09-24 Thread Eric Blake
On Tue, Sep 14, 2021 at 05:19:42PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> 07.09.2021 20:35, Eric Blake wrote:
> > The NBD protocol just relaxed the requirements on
> > NBD_OPT_LIST_META_CONTEXT:
> > 
> > https://github.com/NetworkBlockDevice/nbd/commit/13a4e33a87
> > 
> > Since listing is not stateful (unlike SET_META_CONTEXT), we don't care
> > if a client asks for meta contexts without first requesting structured
> > replies.  Well-behaved clients will still ask for structured reply
> > first (if for no other reason than for back-compat to older servers),
> > but that's no reason to avoid this change.
> > 
> > Signed-off-by: Eric Blake
> 
> Reviewed-by: Vladimir Sementsov-Ogievskiy 

Thanks; queuing this one through my NBD tree.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




[PATCH 14/16] tests/acceptance/ppc_prep_40p.py: NetBSD 7.1.2 location update

2021-09-24 Thread Cleber Rosa
The NetBSD-7.1.2-prep.iso is no longer available on the CDN, but it's
still available in the archive.

Let's update its location so that users without the file on cache can
still fetch it and run the test.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/ppc_prep_40p.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/acceptance/ppc_prep_40p.py b/tests/acceptance/ppc_prep_40p.py
index 2993ee3b07..6b28a69ea5 100644
--- a/tests/acceptance/ppc_prep_40p.py
+++ b/tests/acceptance/ppc_prep_40p.py
@@ -67,8 +67,8 @@ def test_openbios_and_netbsd(self):
 :avocado: tags=machine:40p
 :avocado: tags=os:netbsd
 """
-drive_url = ('https://cdn.netbsd.org/pub/NetBSD/iso/7.1.2/'
- 'NetBSD-7.1.2-prep.iso')
+drive_url = ('https://archive.netbsd.org/pub/NetBSD-archive/'
+ 'NetBSD-7.1.2/iso/NetBSD-7.1.2-prep.iso')
 drive_hash = 'ac6fa2707d888b36d6fa64de6e7fe48e'
 drive_path = self.fetch_asset(drive_url, asset_hash=drive_hash,
   algorithm='md5')
-- 
2.31.1




Re: [PATCH v2] nbd/server: Add --selinux-label option

2021-09-24 Thread Eric Blake
Ping

On Wed, Aug 25, 2021 at 02:35:04PM -0500, Eric Blake wrote:
> On Fri, Jul 23, 2021 at 05:38:06PM +0100, Daniel P. Berrangé wrote:
> > On Fri, Jul 23, 2021 at 06:18:55PM +0200, Kevin Wolf wrote:
> > > Am 23.07.2021 um 12:33 hat Richard W.M. Jones geschrieben:
> > > > Under SELinux, Unix domain sockets have two labels.  One is on the
> > > > disk and can be set with commands such as chcon(1).  There is a
> > > > different label stored in memory (called the process label).  This can
> > > > only be set by the process creating the socket.  When using SELinux +
> > > > SVirt and wanting qemu to be able to connect to a qemu-nbd instance,
> > > > you must set both labels correctly first.
> > > > 
> > > > For qemu-nbd the options to set the second label are awkward.  You can
> > > > create the socket in a wrapper program and then exec into qemu-nbd.
> > > > Or you could try something with LD_PRELOAD.
> > > > 
> > > > This commit adds the ability to set the label straightforwardly on the
> > > > command line, via the new --selinux-label flag.  (The name of the flag
> > > > is the same as the equivalent nbdkit option.)
> > > > 
> > > > A worked example showing how to use the new option can be found in
> > > > this bug: https://bugzilla.redhat.com/show_bug.cgi?id=1984938
> > > > 
> > > > Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1984938
> > > > Signed-off-by: Richard W.M. Jones 
> > > 
> > > I suppose this would also be relevant for the built-in NBD server,
> > > especially in the context of qemu-storage-daemon?
> > 
> > It depends on the usage scenario really. nbdkit / qemu-nbd are
> > not commonly run under any SELinux policy, so then end up being
> > unconfined_t. A QEMU NBD client can't connect to an unconfined_t
> > socket, so we need to override it with this arg.
> > 
> > In the case of qemu system emulator, under libvirt, it will
> > already have a svirt_t type, so in that case there is no need
> > to override the type for the socket.
> > 
> > For qsd there's not really any strong practice established
> > but i expect most current usage is unconfined_t too and
> > would benefit from setting label.
> > 
> > > If so, is this something specific to NBD sockets, or would it actually
> > > make sense to have it as a generic option in UnixSocketAddress?
> > 
> > It is applicable to inet sockets too in fact.
> 
> So now that 6.2 is open, should I queue the patch as is, or wait for a
> v3 that makes the option more generic to all socket usage?
> 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




[PATCH 16/16] tests/acceptance/ppc_prep_40p.py: unify tags

2021-09-24 Thread Cleber Rosa
The arch and machine tags apply to all tests, so let's define them
only once.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/ppc_prep_40p.py | 12 
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/tests/acceptance/ppc_prep_40p.py b/tests/acceptance/ppc_prep_40p.py
index 5e61e686bd..d1e5674673 100644
--- a/tests/acceptance/ppc_prep_40p.py
+++ b/tests/acceptance/ppc_prep_40p.py
@@ -13,6 +13,10 @@
 
 
 class IbmPrep40pMachine(Test):
+"""
+:avocado: tags=arch:ppc
+:avocado: tags=machine:40p
+"""
 
 timeout = 60
 
@@ -24,8 +28,6 @@ class IbmPrep40pMachine(Test):
 @skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
 def test_factory_firmware_and_netbsd(self):
 """
-:avocado: tags=arch:ppc
-:avocado: tags=machine:40p
 :avocado: tags=os:netbsd
 :avocado: tags=slowness:high
 """
@@ -48,10 +50,6 @@ def test_factory_firmware_and_netbsd(self):
 wait_for_console_pattern(self, 'Model: IBM PPS Model 6015')
 
 def test_openbios_192m(self):
-"""
-:avocado: tags=arch:ppc
-:avocado: tags=machine:40p
-"""
 self.vm.set_console()
 self.vm.add_args('-m', '192') # test fw_cfg
 
@@ -62,8 +60,6 @@ def test_openbios_192m(self):
 
 def test_openbios_and_netbsd(self):
 """
-:avocado: tags=arch:ppc
-:avocado: tags=machine:40p
 :avocado: tags=os:netbsd
 """
 drive_url = ('https://archive.netbsd.org/pub/NetBSD-archive/'
-- 
2.31.1




[PATCH 13/16] tests/acceptance/boot_xen.py: use class attribute

2021-09-24 Thread Cleber Rosa
Rather than defining a single use variable, let's just use the class
attribute directly.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_xen.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py
index 66621fd14d..8eec465414 100644
--- a/tests/acceptance/boot_xen.py
+++ b/tests/acceptance/boot_xen.py
@@ -49,11 +49,10 @@ def launch_xen(self, xen_path):
 
 self.vm.set_console()
 
-xen_command_line = self.XEN_COMMON_COMMAND_LINE
 self.vm.add_args('-machine', 'virtualization=on',
  '-m', '768',
  '-kernel', xen_path,
- '-append', xen_command_line,
+ '-append', self.XEN_COMMON_COMMAND_LINE,
  '-device',
  
'guest-loader,addr=0x4700,kernel=%s,bootargs=console=hvc0'
  % (self.kernel_path))
-- 
2.31.1




Re: [PATCH 10/11] vl: Enable JSON syntax for -device

2021-09-24 Thread Eric Blake
On Fri, Sep 24, 2021 at 11:04:26AM +0200, Kevin Wolf wrote:
> Like we already do for -object, introduce support for JSON syntax in
> -device, which can be kept stable in the long term and guarantees that a
> single code path with identical behaviour is used for both QMP and the
> command line. Compared to the QemuOpts based code, the parser contains
> less surprises and has support for non-scalar options (lists and
> structs). Switching management tools to JSON means that we can more
> easily change the "human" CLI syntax from QemuOpts to the keyval parser
> later.
> 
> In the QAPI schema, a feature flag is added to the device-add command to
> allow management tools to detect support for this.
> 
> Signed-off-by: Kevin Wolf 
> ---
>  qapi/qdev.json | 15 +
>  softmmu/vl.c   | 58 --
>  2 files changed, 62 insertions(+), 11 deletions(-)
> 
> diff --git a/qapi/qdev.json b/qapi/qdev.json
> index b83178220b..cdc8f911b5 100644
> --- a/qapi/qdev.json
> +++ b/qapi/qdev.json
> @@ -32,17 +32,23 @@
>  ##
>  # @device_add:
>  #
> +# Add a device.
> +#
>  # @driver: the name of the new device's driver
>  #
>  # @bus: the device's parent bus (device tree path)
>  #
>  # @id: the device's ID, must be unique
>  #
> -# Additional arguments depend on the type.
> -#
> -# Add a device.
> +# Features:
> +# @json-cli: If present, the "-device" command line option supports JSON
> +#syntax with a structure identical to the arguments of this
> +#command.
>  #
>  # Notes:
> +#
> +# Additional arguments depend on the type.
> +#
>  # 1. For detailed information about this command, please refer to the
>  #'docs/qdev-device-use.txt' file.
>  #
> @@ -67,7 +73,8 @@
>  ##
>  { 'command': 'device_add',
>'data': {'driver': 'str', '*bus': 'str', '*id': 'str'},
> -  'gen': false } # so we can get the additional arguments
> +  'gen': false, # so we can get the additional arguments
> +  'features': ['json-cli'] }

Eventually, we'll get rid of this 'gen':false, but this patch series
is already an improvement towards that goal.

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




[PATCH 04/16] Acceptance Tests: keep track and disable tests with known issues

2021-09-24 Thread Cleber Rosa
This introduces a convention, under which tests with known open
issues, will be automatically excluded from execution via "make
check-acceptance".  It should by itself improve the reliability
of test jobs, even those with rare failures.

Those tests can still be run with:

  ./tests/venv/bin/avocado run $TEST_ID

With the test identification are obtainable via:

  ./tests/venv/bin/avocado list tests/acceptance

And for tests with known issues:

  ./tests/venv/bin/avocado list -t issue tests/acceptance

A list of tests that are enabled (that is, match the currently
configured targets, and do not have known issues) can be obtained
with:

  make list-acceptance

As a future improvement, a tool can be added to sync the "issue" tags
with issues that end up being resolved closed.

Signed-off-by: Cleber Rosa 
---
 docs/devel/testing.rst | 28 ++
 tests/Makefile.include |  3 ++-
 tests/acceptance/boot_linux_console.py |  3 +++
 tests/acceptance/machine_rx_gdbsim.py  |  3 +++
 4 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
index 2818c58ff8..f93a9bed3f 100644
--- a/docs/devel/testing.rst
+++ b/docs/devel/testing.rst
@@ -1147,6 +1147,34 @@ variable as shown on the code snippet below to skip the 
test:
   def test(self):
   do_something()
 
+Disabling tests
+---
+
+If you want to have a test temporarily disabled (from ``make
+check-acceptance``), you can add an Avocado ``issue`` tag to the test.  
Example::
+
+  class Feature(Test):
+
+  def test(self):
+"""
+:avocado: tags=issue
+"""
+do_something()
+
+Rather than simply adding an ``issue`` tag, it may be helpful to point
+to an actual issue on the project's issue tracker::
+
+  class Feature(Test):
+
+  def test(self):
+"""
+Reason for disabling this test is documented and tracked at
+https://gitlab.com/qemu-project/qemu/-/issues/
+
+:avocado: tags=issue:
+"""
+do_something()
+
 Uninstalling Avocado
 
 
diff --git a/tests/Makefile.include b/tests/Makefile.include
index d1f90572a7..eb3e5d2aa6 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -94,7 +94,8 @@ TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results
 # information please refer to "avocado --help".
 AVOCADO_SHOW=app
 AVOCADO_RUNNER=runner
-AVOCADO_TAGS=$(patsubst %-softmmu,-t arch:%, $(filter %-softmmu,$(TARGETS)))
+comma := ,
+AVOCADO_TAGS=$(patsubst %-softmmu,--filter-by-tags=-issue$(comma)arch:%, 
$(filter %-softmmu,$(TARGETS)))
 
 $(TESTS_VENV_DIR): $(TESTS_VENV_REQ)
$(call quiet-command, \
diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py
index 0a49c0e276..4c824bc161 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -485,6 +485,9 @@ def test_arm_raspi2_initrd(self):
 """
 :avocado: tags=arch:arm
 :avocado: tags=machine:raspi2b
+
+# https://gitlab.com/qemu-project/qemu/-/issues/636
+:avocado: tags=issue:636
 """
 deb_url = ('http://archive.raspberrypi.org/debian/'
'pool/main/r/raspberrypi-firmware/'
diff --git a/tests/acceptance/machine_rx_gdbsim.py 
b/tests/acceptance/machine_rx_gdbsim.py
index 32b737b6d8..62893a9989 100644
--- a/tests/acceptance/machine_rx_gdbsim.py
+++ b/tests/acceptance/machine_rx_gdbsim.py
@@ -54,6 +54,9 @@ def test_linux_sash(self):
 :avocado: tags=arch:rx
 :avocado: tags=machine:gdbsim-r5f562n7
 :avocado: tags=endian:little
+
+# https://gitlab.com/qemu-project/qemu/-/issues/507
+:avocado: tags=issue:507
 """
 dtb_url = ('https://acc.dl.osdn.jp/users/23/23887/rx-virt.dtb')
 dtb_hash = '7b4e4e2c71905da44e86ce47adee2210b026ac18'
-- 
2.31.1




[PATCH 12/16] tests/acceptance/boot_xen.py: removed unused import

2021-09-24 Thread Cleber Rosa
Just a clean up for an unused import.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_xen.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py
index cd916ddba4..66621fd14d 100644
--- a/tests/acceptance/boot_xen.py
+++ b/tests/acceptance/boot_xen.py
@@ -13,7 +13,6 @@
 
 import os
 
-from avocado import skipIf
 from avocado_qemu import wait_for_console_pattern
 from boot_linux_console import LinuxKernelTest
 
-- 
2.31.1




[PATCH 02/16] Acceptance Tests: improve check-acceptance description

2021-09-24 Thread Cleber Rosa
The "check-acceptance" make rule won't necessarily run *all* available
tests, because it employs a filter based on the currently configured
targets.  This change in the description of the rule makes that
behavior extra clear.

Signed-off-by: Cleber Rosa 
---
 tests/Makefile.include | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/Makefile.include b/tests/Makefile.include
index ac289a2e41..2c03256ae8 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -16,7 +16,7 @@ ifneq ($(filter $(all-check-targets), check-softfloat),)
@echo " $(MAKE) check-tcgRun TCG tests"
@echo " $(MAKE) check-softfloat  Run FPU emulation tests"
 endif
-   @echo " $(MAKE) check-acceptance Run all acceptance (functional) 
tests"
+   @echo " $(MAKE) check-acceptance Run acceptance (functional) tests 
for currently configured targets"
@echo
@echo " $(MAKE) check-report.tap Generates an aggregated TAP test 
report"
@echo " $(MAKE) check-venv   Creates a Python venv for tests"
-- 
2.31.1




[PATCH 15/16] tests/acceptance/ppc_prep_40p.py: clean up unused import

2021-09-24 Thread Cleber Rosa
Just a removal of an unused imported symbol.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/ppc_prep_40p.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tests/acceptance/ppc_prep_40p.py b/tests/acceptance/ppc_prep_40p.py
index 6b28a69ea5..5e61e686bd 100644
--- a/tests/acceptance/ppc_prep_40p.py
+++ b/tests/acceptance/ppc_prep_40p.py
@@ -7,7 +7,6 @@
 
 import os
 
-from avocado import skipIf
 from avocado import skipUnless
 from avocado_qemu import Test
 from avocado_qemu import wait_for_console_pattern
-- 
2.31.1




[PATCH 11/16] tests/acceptance/boot_xen.py: fetch kernel during test setUp()

2021-09-24 Thread Cleber Rosa
The kernel is a common blob used in all tests.  By moving it to the
setUp() method, the "fetch asset" plugin will recognize the kernel and
attempt to fetch it and cache it before the tests are started.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_xen.py | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py
index e2c59f6592..cd916ddba4 100644
--- a/tests/acceptance/boot_xen.py
+++ b/tests/acceptance/boot_xen.py
@@ -31,23 +31,22 @@ class BootXen(LinuxKernelTest):
 timeout = 90
 XEN_COMMON_COMMAND_LINE = 'dom0_mem=128M loglvl=all guest_loglvl=all'
 
-def fetch_guest_kernel(self):
+def setUp(self):
+super(BootXen, self).setUp()
+
 # Using my own built kernel - which works
 kernel_url = ('https://fileserver.linaro.org/'
   's/JSsewXGZ6mqxPr5/download?path=%2F='
   'linux-5.9.9-arm64-ajb')
 kernel_sha1 = '4f92bc4b9f88d5ab792fa7a43a68555d344e1b83'
-kernel_path = self.fetch_asset(kernel_url,
-   asset_hash=kernel_sha1)
-
-return kernel_path
+self.kernel_path = self.fetch_asset(kernel_url,
+asset_hash=kernel_sha1)
 
 def launch_xen(self, xen_path):
 """
 Launch Xen with a dom0 guest kernel
 """
 self.log.info("launch with xen_path: %s", xen_path)
-kernel_path = self.fetch_guest_kernel()
 
 self.vm.set_console()
 
@@ -58,7 +57,7 @@ def launch_xen(self, xen_path):
  '-append', xen_command_line,
  '-device',
  
'guest-loader,addr=0x4700,kernel=%s,bootargs=console=hvc0'
- % (kernel_path))
+ % (self.kernel_path))
 
 self.vm.launch()
 
-- 
2.31.1




[PATCH 10/16] tests/acceptance/boot_xen.py: unify tags

2021-09-24 Thread Cleber Rosa
Because all tests share the same tags, it's possible to have all of
them at the class level.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_xen.py | 26 +-
 1 file changed, 5 insertions(+), 21 deletions(-)

diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py
index 4c14f9e2e7..e2c59f6592 100644
--- a/tests/acceptance/boot_xen.py
+++ b/tests/acceptance/boot_xen.py
@@ -21,6 +21,11 @@
 class BootXen(LinuxKernelTest):
 """
 Boots a Xen hypervisor with a Linux DomU kernel.
+
+:avocado: tags=arch:aarch64
+:avocado: tags=accel:tcg
+:avocado: tags=cpu:cortex-a57
+:avocado: tags=machine:virt
 """
 
 timeout = 90
@@ -61,13 +66,6 @@ def launch_xen(self, xen_path):
 wait_for_console_pattern(self, console_pattern, "Panic on CPU 0:")
 
 def test_arm64_xen_411_and_dom0(self):
-"""
-:avocado: tags=arch:aarch64
-:avocado: tags=accel:tcg
-:avocado: tags=cpu:cortex-a57
-:avocado: tags=machine:virt
-"""
-
 # archive of file from https://deb.debian.org/debian/pool/main/x/xen/
 xen_url = ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/'
'download?path=%2F='
@@ -79,13 +77,6 @@ def test_arm64_xen_411_and_dom0(self):
 self.launch_xen(xen_path)
 
 def test_arm64_xen_414_and_dom0(self):
-"""
-:avocado: tags=arch:aarch64
-:avocado: tags=accel:tcg
-:avocado: tags=cpu:cortex-a57
-:avocado: tags=machine:virt
-"""
-
 # archive of file from https://deb.debian.org/debian/pool/main/x/xen/
 xen_url = ('https://fileserver.linaro.org/s/JSsewXGZ6mqxPr5/'
'download?path=%2F='
@@ -97,13 +88,6 @@ def test_arm64_xen_414_and_dom0(self):
 self.launch_xen(xen_path)
 
 def test_arm64_xen_415_and_dom0(self):
-"""
-:avocado: tags=arch:aarch64
-:avocado: tags=accel:tcg
-:avocado: tags=cpu:cortex-a57
-:avocado: tags=machine:virt
-"""
-
 xen_url = ('https://fileserver.linaro.org/'
's/JSsewXGZ6mqxPr5/download'
'?path=%2F=xen-upstream-4.15-unstable.deb')
-- 
2.31.1




[PATCH 07/16] Acceptance Tests: workaround expired mipsdistros.mips.com HTTPS cert

2021-09-24 Thread Cleber Rosa
The certficiate at https://mipsdistros.mips.com/ is currently
expired (since Jan 23, 2021).

Instead of failing to obtaining the files, let's downgrade to HTTP
instead, given that the integrity of the files are already performed
locally, after the download, using the recorded hash.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_linux_console.py | 6 +++---
 tests/acceptance/replay_kernel.py  | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py
index 80e3a2f7a6..bc0caa1099 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -278,7 +278,7 @@ def test_mips_malta32el_nanomips_4k(self):
 :avocado: tags=endian:little
 :avocado: tags=cpu:I7200
 """
-kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
+kernel_url = ('http://mipsdistros.mips.com/LinuxDistro/nanomips/'
   'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
   'generic_nano32r6el_page4k.xz')
 kernel_hash = '477456aafd2a0f1ddc9482727f20fe9575565dd6'
@@ -291,7 +291,7 @@ def test_mips_malta32el_nanomips_16k_up(self):
 :avocado: tags=endian:little
 :avocado: tags=cpu:I7200
 """
-kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
+kernel_url = ('http://mipsdistros.mips.com/LinuxDistro/nanomips/'
   'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
   'generic_nano32r6el_page16k_up.xz')
 kernel_hash = 'e882868f944c71c816e832e2303b7874d044a7bc'
@@ -304,7 +304,7 @@ def test_mips_malta32el_nanomips_64k_dbg(self):
 :avocado: tags=endian:little
 :avocado: tags=cpu:I7200
 """
-kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
+kernel_url = ('http://mipsdistros.mips.com/LinuxDistro/nanomips/'
   'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
   'generic_nano32r6el_page64k_dbg.xz')
 kernel_hash = '18d1c68f2e23429e266ca39ba5349ccd0aeb7180'
diff --git a/tests/acceptance/replay_kernel.py 
b/tests/acceptance/replay_kernel.py
index cfca71e65f..cac795ab4f 100644
--- a/tests/acceptance/replay_kernel.py
+++ b/tests/acceptance/replay_kernel.py
@@ -434,7 +434,7 @@ def test_mips_malta32el_nanomips_4k(self):
 :avocado: tags=endian:little
 :avocado: tags=cpu:I7200
 """
-kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
+kernel_url = ('http://mipsdistros.mips.com/LinuxDistro/nanomips/'
   'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
   'generic_nano32r6el_page4k.xz')
 kernel_hash = '477456aafd2a0f1ddc9482727f20fe9575565dd6'
@@ -448,7 +448,7 @@ def test_mips_malta32el_nanomips_16k_up(self):
 :avocado: tags=endian:little
 :avocado: tags=cpu:I7200
 """
-kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
+kernel_url = ('http://mipsdistros.mips.com/LinuxDistro/nanomips/'
   'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
   'generic_nano32r6el_page16k_up.xz')
 kernel_hash = 'e882868f944c71c816e832e2303b7874d044a7bc'
@@ -462,7 +462,7 @@ def test_mips_malta32el_nanomips_64k_dbg(self):
 :avocado: tags=endian:little
 :avocado: tags=cpu:I7200
 """
-kernel_url = ('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
+kernel_url = ('http://mipsdistros.mips.com/LinuxDistro/nanomips/'
   'kernels/v4.15.18-432-gb2eb9a8b07a1-20180627102142/'
   'generic_nano32r6el_page64k_dbg.xz')
 kernel_hash = '18d1c68f2e23429e266ca39ba5349ccd0aeb7180'
-- 
2.31.1




[PATCH 09/16] tests/acceptance/boot_xen.py: merge base classes

2021-09-24 Thread Cleber Rosa
While it's a good practice to have reusable base classes, in this
specific case there's no other user of the BootXenBase class.

By unifying the class used in this test, we can improve readability
and have the opportunity to add some future improvements in a clearer
fashion.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_xen.py | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/tests/acceptance/boot_xen.py b/tests/acceptance/boot_xen.py
index b5860b7d88..4c14f9e2e7 100644
--- a/tests/acceptance/boot_xen.py
+++ b/tests/acceptance/boot_xen.py
@@ -18,7 +18,7 @@
 from boot_linux_console import LinuxKernelTest
 
 
-class BootXenBase(LinuxKernelTest):
+class BootXen(LinuxKernelTest):
 """
 Boots a Xen hypervisor with a Linux DomU kernel.
 """
@@ -60,9 +60,6 @@ def launch_xen(self, xen_path):
 console_pattern = 'VFS: Cannot open root device'
 wait_for_console_pattern(self, console_pattern, "Panic on CPU 0:")
 
-
-class BootXen(BootXenBase):
-
 def test_arm64_xen_411_and_dom0(self):
 """
 :avocado: tags=arch:aarch64
-- 
2.31.1




[PATCH 03/16] Acceptance Tests: add mechanism for listing tests

2021-09-24 Thread Cleber Rosa
It is helpful to know the tests that would be executed with a "make
check-acceptance" without executing them.  Let's introduce a "make
list-acceptance" rule for that purpose.

Signed-off-by: Cleber Rosa 
---
 tests/Makefile.include | 8 
 1 file changed, 8 insertions(+)

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 2c03256ae8..d1f90572a7 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -17,6 +17,7 @@ ifneq ($(filter $(all-check-targets), check-softfloat),)
@echo " $(MAKE) check-softfloat  Run FPU emulation tests"
 endif
@echo " $(MAKE) check-acceptance Run acceptance (functional) tests 
for currently configured targets"
+   @echo " $(MAKE) check-acceptance List acceptance (functional) tests 
for currently configured targets"
@echo
@echo " $(MAKE) check-report.tap Generates an aggregated TAP test 
report"
@echo " $(MAKE) check-venv   Creates a Python venv for tests"
@@ -135,6 +136,13 @@ check-acceptance: check-venv $(TESTS_RESULTS_DIR) 
get-vm-images
 $(if $(GITLAB_CI),,--failfast) tests/acceptance, \
 "AVOCADO", "tests/acceptance")
 
+list-acceptance: check-venv
+   $(call quiet-command, \
+$(TESTS_VENV_DIR)/bin/python -m avocado list \
+--filter-by-tags-include-empty --filter-by-tags-include-empty-key \
+$(AVOCADO_TAGS) tests/acceptance, \
+"AVOCADO", "list tests/acceptance")
+
 # Consolidated targets
 
 .PHONY: check-block check check-clean get-vm-images
-- 
2.31.1




Re: [PATCH v3 03/15] target/ppc: PMU basic cycle count for pseries TCG

2021-09-24 Thread Daniel Henrique Barboza




On 9/24/21 15:34, Matheus K. Ferst wrote:

On 24/09/2021 11:41, Daniel Henrique Barboza wrote:

On 9/22/21 08:24, Matheus K. Ferst wrote:

On 03/09/2021 17:31, Daniel Henrique Barboza wrote:

[E-MAIL EXTERNO] Não clique em links ou abra anexos, a menos que você possa 
confirmar o remetente e saber que o conteúdo é seguro. Em caso de e-mail 
suspeito entre imediatamente em contato com o DTI.

This patch adds the barebones of the PMU logic by enabling cycle
counting, done via the performance monitor counter 6. The overall logic
goes as follows:

- a helper is added to control the PMU state on each MMCR0 write. This
allows for the PMU to start/stop as the frozen counter bit (MMCR0_FC)
is cleared or set;

- MMCR0 reg initial value is set to 0x8000 (MMCR0_FC set) to avoid
having to spin the PMU right at system init;

- the intended usage is to freeze the counters by setting MMCR0_FC, do
any additional setting of events to be counted via MMCR1 (not
implemented yet) and enable the PMU by zeroing MMCR0_FC. Software must
freeze counters to read the results - on the fly reading of the PMCs
will return the starting value of each one.

Since there will be more PMU exclusive code to be added next, put the
PMU logic in its own helper to keep all in the same place. The name of
the new helper file, power8_pmu.c, is an indicative that the PMU logic
has been tested with the IBM POWER chip family, POWER8 being the oldest
version tested. This doesn't mean that this PMU logic will break with
any other PPC64 chip that implements Book3s, but since we can't assert
that this PMU will work with all available Book3s emulated processors
we're choosing to be explicit.

Signed-off-by: Daniel Henrique Barboza 
---





diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 0babde3131..c3e2e3d329 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -401,6 +401,24 @@ void spr_write_generic(DisasContext *ctx, int sprn, int 
gprn)
  spr_store_dump_spr(sprn);
  }

+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn)
+{
+    /*
+ * helper_store_mmcr0 will make clock based operations that
+ * will cause 'bad icount read' errors if we do not execute
+ * gen_icount_io_start() beforehand.
+ */
+    gen_icount_io_start(ctx);
+    gen_helper_store_mmcr0(cpu_env, cpu_gpr[gprn]);
+}
+#else
+void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn)
+{
+    spr_write_generic(ctx, sprn, gprn);
+}
+#endif
+
  #if !defined(CONFIG_USER_ONLY)
  void spr_write_generic32(DisasContext *ctx, int sprn, int gprn)
  {
@@ -596,7 +614,10 @@ void spr_write_MMCR0_ureg(DisasContext *ctx, int sprn, int 
gprn)
  tcg_gen_andi_tl(t1, t1, ~(MMCR0_UREG_MASK));
  /* Keep all other bits intact */
  tcg_gen_or_tl(t1, t1, t0);
-    gen_store_spr(SPR_POWER_MMCR0, t1);
+
+    /* Overwrite cpu_gpr[gprn] and use spr_write_MMCR0() */
+    tcg_gen_mov_tl(cpu_gpr[gprn], t1);
+    spr_write_MMCR0(ctx, sprn + 0x10, gprn);


IIUC, this makes writing to MMCR0 change the GPR value and expose the 
unfiltered content of the SPR to problem state. It might be better to call the 
helper directly or create another method that takes a TCGv as an argument and 
call it from spr_write_MMCR0_ureg and spr_write_MMCR0.


I'm overwriting cpu_gpr[gprn] with t1, which is filtered by MMCR0_REG_MASK
right before, to re-use spr_write_MMCR0() since its API requires a gprn
index. The reason I'm re-using spr_write_MMCR0() here is to avoid code 
repetition
in spr_write_MMCR0_ureg(), which would need to repeat the same steps as
spr_write_MMCR0 (calling icount_io_start(), calling the helper, and then setting
DISAS_EXIT_UPDATE in a later patch).

The idea behind is that all PMU user_write() functions works the same as its
privileged counterparts but with some form of filtering done beforehand. Note
that this is kind of true in the previous patch as well - gen_store_spr() is
similar to the privileged function MMCR0 was using (spr_write_generic()) with
the exception of an optional qemu_log().

Maybe I should've made this clear in the previous patch, using 
spr_write_generic()
and overwriting cpu_gpr[gprn] with the filtered t1 content back there.

Speaking of which, since t1 is being filtered by MMCR0_REG_MASK before being 
used to
overwrite cpu_gpr[gprn], I'm not sure how this is exposing unfiltered content to
problem state. Can you elaborate?


Suppose MMCR0 has the value 0x8001 (FC and FCH) and problem state executes 
an mtspr with the value 0x400 (unset FC and set PMAE) in the GPR. The 
proposed code will do the following:

 > tcg_gen_andi_tl(t0, cpu_gpr[gprn], MMCR0_UREG_MASK);

t0 = GPR & MMCR0_UREG_MASK = 0x400 & 0x8480 = 0x400

 > gen_load_spr(t1, SPR_POWER_MMCR0);

t1 = MMCR0 = 0x8001

 > tcg_gen_andi_tl(t1, t1, ~(MMCR0_UREG_MASK));

t1 = t1 & ~MMCR0_UREG_MASK = 0x8001 & ~0x8480 = 0x1

 > tcg_gen_or_tl(t1, t1, t0);

t1 = t1 | t0 = 0x400 | 0x1 

[PATCH 06/16] Acceptance Tests: use extract from package from avocado.utils

2021-09-24 Thread Cleber Rosa
There's code in avocado.utils to handle package extractions in various
(currently rpm, and deb) formats.  Let's use it.

Reference: 
https://avocado-framework.readthedocs.io/en/91.0/api/utils/avocado.utils.software_manager.html#avocado.utils.software_manager.SoftwareManager.extract_from_package
Signed-off-by: Cleber Rosa 
---
 tests/acceptance/boot_linux_console.py | 84 ++
 tests/acceptance/boot_xen.py   |  6 +-
 tests/acceptance/replay_kernel.py  | 12 ++--
 tests/acceptance/tcg_plugins.py|  2 +-
 4 files changed, 41 insertions(+), 63 deletions(-)

diff --git a/tests/acceptance/boot_linux_console.py 
b/tests/acceptance/boot_linux_console.py
index 4c824bc161..80e3a2f7a6 100644
--- a/tests/acceptance/boot_linux_console.py
+++ b/tests/acceptance/boot_linux_console.py
@@ -23,6 +23,7 @@
 from avocado.utils import process
 from avocado.utils import archive
 from avocado.utils.path import find_command, CmdNotFoundError
+from avocado.utils.software_manager import SoftwareManager
 
 P7ZIP_AVAILABLE = True
 try:
@@ -54,42 +55,19 @@ def wait_for_console_pattern(self, success_message, 
vm=None):
  failure_message='Kernel panic - not syncing',
  vm=vm)
 
-def extract_from_deb(self, deb, path):
+def extract_from_pkg(self, pkg, path):
 """
-Extracts a file from a deb package into the test workdir
+Extracts a file from a DEB or RPM package into the test workdir
 
-:param deb: path to the deb archive
-:param path: path within the deb archive of the file to be extracted
+:param pkg: path to the DEB or RPM package
+:param path: path within the DEB or RPM archive of the file to
+  be extracted
 :returns: path of the extracted file
 """
-cwd = os.getcwd()
-os.chdir(self.workdir)
-file_path = process.run("ar t %s" % deb).stdout_text.split()[2]
-process.run("ar x %s %s" % (deb, file_path))
-archive.extract(file_path, self.workdir)
-os.chdir(cwd)
-# Return complete path to extracted file.  Because callers to
-# extract_from_deb() specify 'path' with a leading slash, it is
-# necessary to use os.path.relpath() as otherwise os.path.join()
-# interprets it as an absolute path and drops the self.workdir part.
+SoftwareManager.extract_from_package(pkg, self.workdir)
 return os.path.normpath(os.path.join(self.workdir,
  os.path.relpath(path, '/')))
 
-def extract_from_rpm(self, rpm, path):
-"""
-Extracts a file from an RPM package into the test workdir.
-
-:param rpm: path to the rpm archive
-:param path: path within the rpm archive of the file to be extracted
- needs to be a relative path (starting with './') because
- cpio(1), which is used to extract the file, expects that.
-:returns: path of the extracted file
-"""
-cwd = os.getcwd()
-os.chdir(self.workdir)
-process.run("rpm2cpio %s | cpio -id %s" % (rpm, path), shell=True)
-os.chdir(cwd)
-return os.path.normpath(os.path.join(self.workdir, path))
 
 class BootLinuxConsole(LinuxKernelTest):
 """
@@ -128,7 +106,7 @@ def test_mips_malta(self):
'linux-image-2.6.32-5-4kc-malta_2.6.32-48_mips.deb')
 deb_hash = 'a8cfc28ad8f45f54811fc6cf74fc43ffcfe0ba04'
 deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
-kernel_path = self.extract_from_deb(deb_path,
+kernel_path = self.extract_from_pkg(deb_path,
 '/boot/vmlinux-2.6.32-5-4kc-malta')
 
 self.vm.set_console()
@@ -160,7 +138,7 @@ def test_mips64el_malta(self):
'linux-image-2.6.32-5-5kc-malta_2.6.32-48_mipsel.deb')
 deb_hash = '1aaec92083bf22fda31e0d27fa8d9a388e5fc3d5'
 deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
-kernel_path = self.extract_from_deb(deb_path,
+kernel_path = self.extract_from_pkg(deb_path,
 '/boot/vmlinux-2.6.32-5-5kc-malta')
 
 self.vm.set_console()
@@ -181,7 +159,7 @@ def test_mips64el_fuloong2e(self):

'linux-image-3.16.0-6-loongson-2e_3.16.56-1+deb8u1_mipsel.deb')
 deb_hash = 'd04d446045deecf7b755ef576551de0c4184dd44'
 deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
-kernel_path = self.extract_from_deb(deb_path,
+kernel_path = self.extract_from_pkg(deb_path,
 
'/boot/vmlinux-3.16.0-6-loongson-2e')
 
 self.vm.set_console()
@@ -203,7 +181,7 @@ def test_mips_malta_cpio(self):
'linux-image-4.5.0-2-4kc-malta_4.5.5-1_mips.deb')
 deb_hash = 'a3c84f3e88b54e06107d65a410d1d1e8e0f340f8'

Re: [PATCH 11/11] Deprecate stable non-JSON -device and -object

2021-09-24 Thread Eric Blake
On Fri, Sep 24, 2021 at 11:04:27AM +0200, Kevin Wolf wrote:
> We want to switch both from QemuOpts to the keyval parser in the future,
> which results in some incompatibilities, mainly around list handling.
> Mark the non-JSON version of both as unstable syntax so that management
> tools switch to JSON and we can later make the change without breaking
> things.
> 
> Signed-off-by: Kevin Wolf 
> ---
>  docs/about/deprecated.rst | 11 +++
>  1 file changed, 11 insertions(+)

Reviewed-by: Eric Blake 

> 
> diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
> index 3c2be84d80..42f6a478fb 100644
> --- a/docs/about/deprecated.rst
> +++ b/docs/about/deprecated.rst
> @@ -160,6 +160,17 @@ Use ``-display sdl`` instead.
>  
>  Use ``-display curses`` instead.
>  
> +Stable non-JSON ``-device`` and ``-object`` syntax (since 6.2)
> +''
> +
> +If you rely on a stable interface for ``-device`` and ``-object`` that 
> doesn't
> +change incompatibly between QEMU versions (e.g. because you are using the 
> QEMU
> +command line as a machine interface in scripts rather than interactively), 
> use
> +JSON syntax for these options instead.
> +
> +There is no intention to remove support for non-JSON syntax entirely, but
> +future versions may change the way to spell some options.
> +
>  
>  Plugin argument passing through ``arg=`` (since 6.1)
>  
> -- 
> 2.31.1
> 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




[PATCH 01/16] Acceptance Tests: bump Avocado requirement to 91.0

2021-09-24 Thread Cleber Rosa
Avocado 91.0, brings, among other changes, a switch to a new runner
implementation, known as "nrunner".  While my personal testing shows
that it's suitable for running the QEMU tests, there are some
considerations that should be addressed before the change.

For instance, the "nrunner" implementation will run tests in parallel
by default.  With more tests running, and resources shared, some tests
may fail with timeouts on some environments.

So, for now, let's bump the Avocado version to allow for the other
features to be used.  And the "nrunner" implementation to be used by
those that choose to do so.

More information can be found at the release notes at:
   https://avocado-framework.readthedocs.io/en/latest/releases/91_0.html

Signed-off-by: Cleber Rosa 
---
 docs/devel/testing.rst | 12 
 tests/Makefile.include |  2 ++
 tests/requirements.txt |  2 +-
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
index 4a0abbf23d..2818c58ff8 100644
--- a/docs/devel/testing.rst
+++ b/docs/devel/testing.rst
@@ -740,6 +740,18 @@ may be invoked by running:
 
   tests/venv/bin/avocado run $OPTION1 $OPTION2 tests/acceptance/
 
+Running tests in parallel
+-
+
+The current ``make check-acceptance`` target continues to use the
+Avocado runner implementation simply known as "runner".  But, it's now
+possible to opt-in and choose the "nrunner" implementation, which,
+among other things, allows for parallel execution of tests:
+
+.. code::
+
+  make AVOCADO_RUNNER=nrunner check-acceptance
+
 Manual Installation
 ---
 
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 6e16c05f10..ac289a2e41 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -92,6 +92,7 @@ TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results
 # Any number of command separated loggers are accepted.  For more
 # information please refer to "avocado --help".
 AVOCADO_SHOW=app
+AVOCADO_RUNNER=runner
 AVOCADO_TAGS=$(patsubst %-softmmu,-t arch:%, $(filter %-softmmu,$(TARGETS)))
 
 $(TESTS_VENV_DIR): $(TESTS_VENV_REQ)
@@ -128,6 +129,7 @@ check-acceptance: check-venv $(TESTS_RESULTS_DIR) 
get-vm-images
$(call quiet-command, \
 $(TESTS_VENV_DIR)/bin/python -m avocado \
 --show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \
+--test-runner=$(AVOCADO_RUNNER) \
 --filter-by-tags-include-empty --filter-by-tags-include-empty-key \
 $(AVOCADO_TAGS) \
 $(if $(GITLAB_CI),,--failfast) tests/acceptance, \
diff --git a/tests/requirements.txt b/tests/requirements.txt
index a21b59b443..40af24c664 100644
--- a/tests/requirements.txt
+++ b/tests/requirements.txt
@@ -1,5 +1,5 @@
 # Add Python module requirements, one per line, to be installed
 # in the tests/venv Python virtual environment. For more info,
 # refer to: https://pip.pypa.io/en/stable/user_guide/#id1
-avocado-framework==88.1
+avocado-framework==91.0
 pycdlib==1.11.0
-- 
2.31.1




[PATCH 08/16] acceptance/tests/vnc.py: use explicit syntax for enabling passwords

2021-09-24 Thread Cleber Rosa
This matches the command line on 82a17d1d67, where the "on" or "off"
should be explicitly given.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/vnc.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/acceptance/vnc.py b/tests/acceptance/vnc.py
index 22656bbcc2..f301fbb4f5 100644
--- a/tests/acceptance/vnc.py
+++ b/tests/acceptance/vnc.py
@@ -45,7 +45,7 @@ def test_change_password_requires_a_password(self):
  'Could not set password')
 
 def test_change_password(self):
-self.vm.add_args('-nodefaults', '-S', '-vnc', ':0,password')
+self.vm.add_args('-nodefaults', '-S', '-vnc', ':0,password=on')
 self.vm.launch()
 self.assertTrue(self.vm.qmp('query-vnc')['return']['enabled'])
 set_password_response = self.vm.qmp('change-vnc-password',
-- 
2.31.1




[PATCH 00/16] Acceptance Tests: use Avocado 91.0 features and other improvements

2021-09-24 Thread Cleber Rosa
This is a collection of patches for the Acceptance Tests to leverage
some of the features of Avocado 91.0.  With the Avocado version bump
by itself, there would be a change in the default "test runner"
implementation that Avocado uses, from the one simply known as
"runner" to the new one called "nrunner".

Among the changes from one implementation to the other, is the fact
that "nrunner" will run tests in parallel by default.  This is *not
yet* enabled by default on "make check-acceptance", but users can
choose to use simply by setting the "AVOCADO_RUNNER" variable, that
is:

  make AVOCADO_RUNNER=nrunner check-acceptance

If you are curious about the architectural differences of the nrunner,
please refer to:

  
https://avocado-framework.readthedocs.io/en/91.0/guides/contributor/chapters/runners.html

One other noteworthy proposal is a convention to tag tests that either
have known issues, or that touch on QEMU features that have known
issues.  By tagging those tests accordingly, they will be
automatically excluded from the regular execution with "make
check-acceptance".

Finally, some updates to assets locations and some tests refactors and
cleanups.

Cleber Rosa (16):
  Acceptance Tests: bump Avocado requirement to 91.0
  Acceptance Tests: improve check-acceptance description
  Acceptance Tests: add mechanism for listing tests
  Acceptance Tests: keep track and disable tests with known issues
  Acceptance Tests: add standard clean up at test tearDown()
  Acceptance Tests: use extract from package from avocado.utils
  Acceptance Tests: workaround expired mipsdistros.mips.com HTTPS cert
  acceptance/tests/vnc.py: use explicit syntax for enabling passwords
  tests/acceptance/boot_xen.py: merge base classes
  tests/acceptance/boot_xen.py: unify tags
  tests/acceptance/boot_xen.py: fetch kernel during test setUp()
  tests/acceptance/boot_xen.py: removed unused import
  tests/acceptance/boot_xen.py: use class attribute
  tests/acceptance/ppc_prep_40p.py: NetBSD 7.1.2 location update
  tests/acceptance/ppc_prep_40p.py: clean up unused import
  tests/acceptance/ppc_prep_40p.py: unify tags

 docs/devel/testing.rst| 40 ++
 tests/Makefile.include| 15 +++-
 tests/acceptance/avocado_qemu/__init__.py |  1 +
 tests/acceptance/boot_linux_console.py| 93 +--
 tests/acceptance/boot_xen.py  | 54 -
 tests/acceptance/machine_rx_gdbsim.py |  3 +
 tests/acceptance/ppc_prep_40p.py  | 17 ++---
 tests/acceptance/replay_kernel.py | 18 ++---
 tests/acceptance/tcg_plugins.py   |  2 +-
 tests/acceptance/vnc.py   |  2 +-
 tests/requirements.txt|  2 +-
 11 files changed, 128 insertions(+), 119 deletions(-)

-- 
2.31.1





Re: [PATCH 09/11] qdev: Avoid QemuOpts in QMP device_add

2021-09-24 Thread Eric Blake
On Fri, Sep 24, 2021 at 11:04:25AM +0200, Kevin Wolf wrote:
> Directly call qdev_device_add_from_qdict() for QMP device_add instead of
> first going through QemuOpts and converting back to QDict.
> 
> Note that this changes the behaviour of device_add, though in ways that
> should be considered bug fixes:
> 
> QemuOpts ignores differences between data types, so you could
> successfully pass a string "123" for an integer property, or a string
> "on" for a boolean property (and vice versa).  After this change, the
> correct data type for the property must be used in the JSON input.
> 
> qemu_opts_from_qdict() also silently ignores any options whose value is
> a QDict, QList or QNull.
> 
> To illustrate, the following QMP command was accepted before and is now
> rejected for both reasons:
> 
> { "execute": "device_add",
>   "arguments": { "driver": "scsi-cd",
>  "drive": { "completely": "invalid" },
>  "physical_block_size": "4096" } }
> 
> Signed-off-by: Kevin Wolf 
> ---
>  softmmu/qdev-monitor.c | 18 +++---
>  1 file changed, 11 insertions(+), 7 deletions(-)
>

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




[PATCH 05/16] Acceptance Tests: add standard clean up at test tearDown()

2021-09-24 Thread Cleber Rosa
The avocado.Test class, used as the basis of the avocado_qemu.Test
class, performs a clean of temporary directories up as part of its own
tearDown() implementation.

But the avocado_qemu.Test class is currently missing the same clean
up, as it implemented its own tearDown() method without resorting to
the upper class behavior.

This brings avocado_qemu.Test behavior in sync with the standard
avocado.Test behavior and prevents temporary directories from
cluttering the test results directory (unless instructed to do so with
Avocado's "--keep-tmp" option).

Reported-by: Peter Maydell 
Signed-off-by: Cleber Rosa 
---
 tests/acceptance/avocado_qemu/__init__.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/acceptance/avocado_qemu/__init__.py 
b/tests/acceptance/avocado_qemu/__init__.py
index 2c4fef3e14..1e807e2e55 100644
--- a/tests/acceptance/avocado_qemu/__init__.py
+++ b/tests/acceptance/avocado_qemu/__init__.py
@@ -276,6 +276,7 @@ def tearDown(self):
 for vm in self._vms.values():
 vm.shutdown()
 self._sd = None
+super(Test, self).tearDown()
 
 def fetch_asset(self, name,
 asset_hash=None, algorithm=None,
-- 
2.31.1




Re: [PATCH 08/11] qdev: Base object creation on QDict rather than QemuOpts

2021-09-24 Thread Eric Blake
On Fri, Sep 24, 2021 at 11:04:24AM +0200, Kevin Wolf wrote:
> QDicts are both what QMP natively uses and what the keyval parser
> produces. Going through QemuOpts isn't useful for either one, so switch
> the main device creation function to QDicts. By sharing more code with
> the -object/object-add code path, we can even reduce the code size a
> bit.
> 
> This commit doesn't remove the detour through QemuOpts from any code
> path yet, but it allows the following commits to do so.
> 
> Signed-off-by: Kevin Wolf 
> ---
>  include/hw/qdev-core.h |  8 ++---
>  hw/core/qdev.c |  5 ++--
>  hw/net/virtio-net.c|  4 +--
>  hw/vfio/pci.c  |  4 +--
>  softmmu/qdev-monitor.c | 67 +++---
>  5 files changed, 41 insertions(+), 47 deletions(-)
>

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




RE: [PATCH v3 08/27] linux-user/hexagon: Implement setup_sigtramp

2021-09-24 Thread Taylor Simpson


> -Original Message-
> From: Richard Henderson 
> Sent: Friday, September 24, 2021 11:59 AM
> To: qemu-devel@nongnu.org
> Cc: laur...@vivier.eu; peter.mayd...@linaro.org; Taylor Simpson
> ; Philippe Mathieu-Daudé 
> Subject: [PATCH v3 08/27] linux-user/hexagon: Implement setup_sigtramp
> 
> Continue to initialize the words on the stack, as documented.
> However, use the off-stack trampoline.
> 
> Cc: Taylor Simpson 
> Reviewed-by: Philippe Mathieu-Daudé 
> Signed-off-by: Richard Henderson 
> ---
>  linux-user/hexagon/target_signal.h |  2 ++
>  linux-user/hexagon/signal.c| 19 +--
>  2 files changed, 19 insertions(+), 2 deletions(-)

Reviewed-by: Taylor Simpson 


RE: [PATCH v6 21/40] target/hexagon: Remove unused has_work() handler

2021-09-24 Thread Taylor Simpson


> -Original Message-
> From: Philippe Mathieu-Daudé  On
> Behalf Of Philippe Mathieu-Daudé
> Sent: Friday, September 24, 2021 4:38 AM
> To: qemu-devel@nongnu.org
> Cc: Richard Henderson ; Philippe Mathieu-
> Daudé ; Taylor Simpson 
> Subject: [PATCH v6 21/40] target/hexagon: Remove unused has_work()
> handler
> 
> has_work() is sysemu specific, and Hexagon target only provides a linux-user
> implementation. Remove the unused hexagon_cpu_has_work().
> 
> Reviewed-by: Richard Henderson 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  target/hexagon/cpu.c | 6 --
>  1 file changed, 6 deletions(-)
> 
> diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c index
> 3338365c16e..aa01974807c 100644
> --- a/target/hexagon/cpu.c
> +++ b/target/hexagon/cpu.c
> @@ -189,11 +189,6 @@ static void
> hexagon_cpu_synchronize_from_tb(CPUState *cs,
>  env->gpr[HEX_REG_PC] = tb->pc;
>  }
> 
> -static bool hexagon_cpu_has_work(CPUState *cs) -{
> -return true;
> -}
> -
>  void restore_state_to_opc(CPUHexagonState *env, TranslationBlock *tb,
>target_ulong *data)  { @@ -287,7 +282,6 @@ static 
> void
> hexagon_cpu_class_init(ObjectClass *c, void *data)
>  device_class_set_parent_reset(dc, hexagon_cpu_reset, 
> >parent_reset);
> 
>  cc->class_by_name = hexagon_cpu_class_by_name;
> -cc->has_work = hexagon_cpu_has_work;
>  cc->dump_state = hexagon_dump_state;
>  cc->set_pc = hexagon_cpu_set_pc;
>  cc->gdb_read_register = hexagon_gdb_read_register;


Reviewed-by: Taylor Simpson 



Re: [PATCH] hw/misc: Add an iBT device model

2021-09-24 Thread Titus Rwantare
On Fri, 24 Sept 2021 at 03:55, Cédric Le Goater  wrote:
>
> Hello Titus,
>
> On 9/24/21 10:42, Philippe Mathieu-Daudé wrote:
> > On 9/24/21 01:48, Titus Rwantare wrote:
> >> Hello all,
> >>
> >> I'd like some clarification on how the following code transfers irqs
> >> back and forth:
> >>> b/hw/arm/aspeed_soc.c
> >>> +/* iBT */
> >>> +if (!sysbus_realize(SYS_BUS_DEVICE(>ibt), errp)) {
> >>> +return;
> >>> +}
> >>> +memory_region_add_subregion(>lpc.iomem,
> >>> +   sc->memmap[ASPEED_DEV_IBT] - 
> >>> sc->memmap[ASPEED_DEV_LPC],
> >>> +   >ibt.iomem);
> >>> +sysbus_connect_irq(SYS_BUS_DEVICE(>lpc), 1 + aspeed_lpc_ibt,
>
>
> The iBT device IRQ is connected to a subdevice irq of the LPC device.
> See aspeed_lpc_realize(). And triggered in aspeed_lpc_set_irq()

Yes, that side makes sense. I tried to get at that irq from
aspeed_ibt.c as follows:

qemu_irq_lower(ibt->lpc->subdevice_irqs[aspeed_lpc_ibt]); // or raise

static void aspeed_ibt_realize(DeviceState *dev, Error **errp)
{
AspeedIBTState *ibt = ASPEED_IBT(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
IPMIInterface *ii = IPMI_INTERFACE(dev);
ibt->lpc = ASPEED_LPC(dev);
...

but this doesn't work and maybe I'm misusing the dynamic cast?

> >>> +   qdev_get_gpio_in(DEVICE(>lpc), 
> >>> aspeed_lpc_ibt));
> >>> }
> >>
> >> and
> >>
> >>> hw/misc/aspeed_ibt.c
> >>> +static void aspeed_ibt_realize(DeviceState *dev, Error **errp)
> >>> +{
> >>> +SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> >>> +AspeedIBTState *ibt = ASPEED_IBT(dev);
> >> ...
> >>> +
> >>> +sysbus_init_irq(sbd, >irq);
> >>
> >> I ask because the code in aspeed_soc.c seems to connect to the
> >> lpc->subdevice_irqs[aspeed_lpc_ibt], initialised on
> >> hw/misc/aspeed_lpc.c:408.
> >> I noticed that bmc firmware running in qemu was checking the BT_CTRL
> >> register less frequently than I'd like while editing this patch to use
> >> the IPMIInterface.
>
> OK.
>
> This might be a problem in aspeed_ibt_update_irq(). This patch is
> an experiment from some few years ago. It still works good enough
> for the witherspoon-bmc and powernv9 machines for simple IPMI
> commands: fru, sdr, lan, power off (to be checked).
>
> Could you share your BMC and host command line ?
>

Host:
-chardev socket,id=ipmichr1,host=localhost,port=,reconnect=10 \
-device ipmi-bmc-extern,chardev=ipmichr1,id=bmc0 \
-device isa-ipmi-bt,bmc=bmc0,irq=10 -nodefaults

BMC:
-chardev socket,id=ipmichr1,host=localhost,port=,server=on,wait=off \
-device ipmi-host-extern,chardev=ipmichr1,responder=/machine/soc/ibt

But for this to work you need Hao's patch as well: [PATCH 7/8]
hw/ipmi: Add an IPMI external host device.



Re: [PATCH 04/11] qdev: Avoid using string visitor for properties

2021-09-24 Thread Eric Blake
On Fri, Sep 24, 2021 at 11:04:20AM +0200, Kevin Wolf wrote:
> The only thing the string visitor adds compared to a keyval visitor is
> list support. git grep for 'visit_start_list' and 'visit.*List' shows
> that devices don't make use of this.
> 
> In a world with a QAPIfied command line interface, the keyval visitor is
> used to parse the command line. In order to make sure that no devices
> start using this feature that would make backwards compatibility harder,
> just switch away from object_property_parse(), which internally uses the
> string visitor, to a keyval visitor and object_property_set().
> 
> Signed-off-by: Kevin Wolf 
> ---
>  softmmu/qdev-monitor.c | 20 +---
>  1 file changed, 17 insertions(+), 3 deletions(-)

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v3 03/15] target/ppc: PMU basic cycle count for pseries TCG

2021-09-24 Thread Matheus K. Ferst

On 24/09/2021 11:41, Daniel Henrique Barboza wrote:

On 9/22/21 08:24, Matheus K. Ferst wrote:

On 03/09/2021 17:31, Daniel Henrique Barboza wrote:
[E-MAIL EXTERNO] Não clique em links ou abra anexos, a menos que você 
possa confirmar o remetente e saber que o conteúdo é seguro. Em caso 
de e-mail suspeito entre imediatamente em contato com o DTI.


This patch adds the barebones of the PMU logic by enabling cycle
counting, done via the performance monitor counter 6. The overall logic
goes as follows:

- a helper is added to control the PMU state on each MMCR0 write. This
allows for the PMU to start/stop as the frozen counter bit (MMCR0_FC)
is cleared or set;

- MMCR0 reg initial value is set to 0x8000 (MMCR0_FC set) to avoid
having to spin the PMU right at system init;

- the intended usage is to freeze the counters by setting MMCR0_FC, do
any additional setting of events to be counted via MMCR1 (not
implemented yet) and enable the PMU by zeroing MMCR0_FC. Software must
freeze counters to read the results - on the fly reading of the PMCs
will return the starting value of each one.

Since there will be more PMU exclusive code to be added next, put the
PMU logic in its own helper to keep all in the same place. The name of
the new helper file, power8_pmu.c, is an indicative that the PMU logic
has been tested with the IBM POWER chip family, POWER8 being the oldest
version tested. This doesn't mean that this PMU logic will break with
any other PPC64 chip that implements Book3s, but since we can't assert
that this PMU will work with all available Book3s emulated processors
we're choosing to be explicit.

Signed-off-by: Daniel Henrique Barboza 
---





diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 0babde3131..c3e2e3d329 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -401,6 +401,24 @@ void spr_write_generic(DisasContext *ctx, int 
sprn, int gprn)

  spr_store_dump_spr(sprn);
  }

+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn)
+{
+    /*
+ * helper_store_mmcr0 will make clock based operations that
+ * will cause 'bad icount read' errors if we do not execute
+ * gen_icount_io_start() beforehand.
+ */
+    gen_icount_io_start(ctx);
+    gen_helper_store_mmcr0(cpu_env, cpu_gpr[gprn]);
+}
+#else
+void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn)
+{
+    spr_write_generic(ctx, sprn, gprn);
+}
+#endif
+
  #if !defined(CONFIG_USER_ONLY)
  void spr_write_generic32(DisasContext *ctx, int sprn, int gprn)
  {
@@ -596,7 +614,10 @@ void spr_write_MMCR0_ureg(DisasContext *ctx, int 
sprn, int gprn)

  tcg_gen_andi_tl(t1, t1, ~(MMCR0_UREG_MASK));
  /* Keep all other bits intact */
  tcg_gen_or_tl(t1, t1, t0);
-    gen_store_spr(SPR_POWER_MMCR0, t1);
+
+    /* Overwrite cpu_gpr[gprn] and use spr_write_MMCR0() */
+    tcg_gen_mov_tl(cpu_gpr[gprn], t1);
+    spr_write_MMCR0(ctx, sprn + 0x10, gprn);


IIUC, this makes writing to MMCR0 change the GPR value and expose the 
unfiltered content of the SPR to problem state. It might be better to 
call the helper directly or create another method that takes a TCGv as 
an argument and call it from spr_write_MMCR0_ureg and spr_write_MMCR0.


I'm overwriting cpu_gpr[gprn] with t1, which is filtered by MMCR0_REG_MASK
right before, to re-use spr_write_MMCR0() since its API requires a gprn
index. The reason I'm re-using spr_write_MMCR0() here is to avoid code 
repetition

in spr_write_MMCR0_ureg(), which would need to repeat the same steps as
spr_write_MMCR0 (calling icount_io_start(), calling the helper, and then 
setting

DISAS_EXIT_UPDATE in a later patch).

The idea behind is that all PMU user_write() functions works the same as 
its
privileged counterparts but with some form of filtering done beforehand. 
Note
that this is kind of true in the previous patch as well - 
gen_store_spr() is
similar to the privileged function MMCR0 was using (spr_write_generic()) 
with

the exception of an optional qemu_log().

Maybe I should've made this clear in the previous patch, using 
spr_write_generic()

and overwriting cpu_gpr[gprn] with the filtered t1 content back there.

Speaking of which, since t1 is being filtered by MMCR0_REG_MASK before 
being used to
overwrite cpu_gpr[gprn], I'm not sure how this is exposing unfiltered 
content to

problem state. Can you elaborate?


Suppose MMCR0 has the value 0x8001 (FC and FCH) and problem state 
executes an mtspr with the value 0x400 (unset FC and set PMAE) in 
the GPR. The proposed code will do the following:


> tcg_gen_andi_tl(t0, cpu_gpr[gprn], MMCR0_UREG_MASK);

t0 = GPR & MMCR0_UREG_MASK = 0x400 & 0x8480 = 0x400

> gen_load_spr(t1, SPR_POWER_MMCR0);

t1 = MMCR0 = 0x8001

> tcg_gen_andi_tl(t1, t1, ~(MMCR0_UREG_MASK));

t1 = t1 & ~MMCR0_UREG_MASK = 0x8001 & ~0x8480 = 0x1

> tcg_gen_or_tl(t1, t1, t0);

t1 = t1 | t0 = 0x400 | 0x1 = 0x401

> 

Re: Ping: [PATCH 0/2] cocoa.m: keyboard quality of life reborn

2021-09-24 Thread Programmingkid



> On Sep 24, 2021, at 5:26 AM, Peter Maydell  wrote:
> 
> On Fri, 24 Sept 2021 at 00:08, Programmingkid  
> wrote:
>> 
>> Hi Peter, are you reviewing cocoa patches? Should someone else see these 
>> patches?
> 
> Gerd sent out a message a while back suggesting that people interested
> in the cocoa UI (we have had several people recently submit patches)
> ought to start reviewing each others' patches. I would certainly
> prefer it if those people who are actively using and working on
> the cocoa UI could take on more of this review work.
> 
> -- PMM

Problem is there isn't anyone else who does actually review cocoa patches. Even 
if there were others, there is no guarantee their suggestions would be 
something you agree with. Since you are the cocoa maintainer the only opinion 
that ultimately matters is yours .





Re: [PATCH 01/11] qom: Reduce use of error_propagate()

2021-09-24 Thread Eric Blake
On Fri, Sep 24, 2021 at 11:04:17AM +0200, Kevin Wolf wrote:
> ERRP_GUARD() makes debugging easier by making sure that _abort
> still fails at the real origin of the error instead of
> error_propagate().
> 
> Signed-off-by: Kevin Wolf 
> ---
>  qom/object.c|  7 +++
>  qom/object_interfaces.c | 17 ++---
>  2 files changed, 9 insertions(+), 15 deletions(-)

Reviewed-by: Eric Blake 

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3266
Virtualization:  qemu.org | libvirt.org




Re: [PATCH v2 0/6] iotests: update environment and linting configuration

2021-09-24 Thread John Snow
On Thu, Sep 23, 2021 at 2:07 PM John Snow  wrote:

> GitLab: https://gitlab.com/jsnow/qemu/-/commits/python-package-iotest-pt1
> CI: https://gitlab.com/jsnow/qemu/-/pipelines/376236687
>
> This series partially supersedes:
>   [PATCH v3 00/16] python/iotests: Run iotest linters during Python CI'
>
> Howdy, this is good stuff we want even if we aren't yet in agreement
> about the best way to run iotest 297 from CI.
>
> - Update linting config to tolerate pylint 2.11.1
> - Eliminate sys.path hacking in individual test files
> - make mypy execution in test 297 faster
>
> The rest of the actual "run at CI time" stuff can get handled separately
> and later pending some discussion on the other series.
>
> V2:
>
> 001/6:[0011] [FC] 'iotests: add 'qemu' package location to PYTHONPATH in
> testenv'
> 002/6:[0025] [FC] 'iotests: add warning for rogue 'qemu' packages'
>
> - Squashed in a small optimization from Vladimir to 001, kept R-Bs.
> - Fixed the package detection logic to not panic if it can't find
>   'qemu' at all (kwolf)
> - Updated commit messages for the first two patches.
>
> --js
>
> John Snow (6):
>   iotests: add 'qemu' package location to PYTHONPATH in testenv
>   iotests: add warning for rogue 'qemu' packages
>   iotests/linters: check mypy files all at once
>   iotests/mirror-top-perms: Adjust imports
>   iotests/migrate-bitmaps-test: delint
>   iotests: Update for pylint 2.11.1
>
>  tests/qemu-iotests/235|  2 -
>  tests/qemu-iotests/297| 50 ---
>  tests/qemu-iotests/300|  7 ++-
>  tests/qemu-iotests/iotests.py |  2 -
>  tests/qemu-iotests/pylintrc   |  6 ++-
>  tests/qemu-iotests/testenv.py | 39 ---
>  tests/qemu-iotests/testrunner.py  |  7 +--
>  tests/qemu-iotests/tests/migrate-bitmaps-test | 50 +++
>  tests/qemu-iotests/tests/mirror-top-perms | 12 ++---
>  9 files changed, 99 insertions(+), 76 deletions(-)
>
> --
> 2.31.1
>
>
>
Patch 2 can just be dropped, and everything else is reviewed, so I think
this can be staged at your leisure.

--js


Re: [PATCH v2 2/6] iotests: add warning for rogue 'qemu' packages

2021-09-24 Thread John Snow
On Thu, Sep 23, 2021 at 4:27 PM Vladimir Sementsov-Ogievskiy <
vsement...@virtuozzo.com> wrote:

> 23.09.2021 21:44, John Snow wrote:
> >
> >
> > On Thu, Sep 23, 2021 at 2:32 PM Vladimir Sementsov-Ogievskiy <
> vsement...@virtuozzo.com > wrote:
> >
> > 23.09.2021 21:07, John Snow wrote:
> >  > Add a warning for when 'iotests' runs against a qemu namespace
> that
> >  > isn't the one in the source tree. This might occur if you have
> >  > (accidentally) installed the Python namespace package to your
> local
> >  > packages.
> >  >
> >  > (I'm not going to say that this is because I bit myself with this,
> >  > but you can fill in the blanks.)
> >  >
> >  > In the future, we will pivot to always preferring a specific
> installed
> >  > instance of qemu python packages managed directly by iotests. For
> now
> >  > simply warn if there is an ambiguity over which instance that
> iotests
> >  > might use.
> >  >
> >  > Example: If a user has navigated to ~/src/qemu/python and executed
> >  > `pip install .`, you will see output like this when running
> `./check`:
> >  >
> >  > WARNING: 'qemu' python packages will be imported from outside the
> source tree ('/home/jsnow/src/qemu/python')
> >  >   Importing instead from
> '/home/jsnow/.local/lib/python3.9/site-packages/qemu'
> >  >
> >  > Signed-off-by: John Snow  js...@redhat.com>>
> >  > ---
> >  >   tests/qemu-iotests/testenv.py | 24 
> >  >   1 file changed, 24 insertions(+)
> >  >
> >  > diff --git a/tests/qemu-iotests/testenv.py
> b/tests/qemu-iotests/testenv.py
> >  > index 99a57a69f3a..1c0f6358538 100644
> >  > --- a/tests/qemu-iotests/testenv.py
> >  > +++ b/tests/qemu-iotests/testenv.py
> >  > @@ -16,6 +16,8 @@
> >  >   # along with this program.  If not, see <
> http://www.gnu.org/licenses/ >.
> >  >   #
> >  >
> >  > +import importlib.util
> >  > +import logging
> >  >   import os
> >  >   import sys
> >  >   import tempfile
> >  > @@ -112,6 +114,27 @@ def init_directories(self) -> None:
> >  >   # Path where qemu goodies live in this source tree.
> >  >   qemu_srctree_path = Path(__file__,
> '../../../python').resolve()
> >  >
> >  > +# Warn if we happen to be able to find qemu namespace
> packages
> >  > +# (using qemu.qmp as a bellwether) from an unexpected
> location.
> >  > +# i.e. the package is already installed in the user's
> environment.
> >  > +try:
> >  > +qemu_spec = importlib.util.find_spec('qemu.qmp')
> >  > +except ModuleNotFoundError:
> >  > +qemu_spec = None
> >  > +
> >  > +if qemu_spec and qemu_spec.origin:
> >  > +spec_path = Path(qemu_spec.origin)
> >  > +try:
> >  > +_ = spec_path.relative_to(qemu_srctree_path)
> >
> > It took some time and looking at specification trying to understand
> what's going on here :)
> >
> > Could we just use:
> >
> > if not Path(qemu_spec.origin).is_relative_to(qemu_srctree_path):
> >  ... logging ...
> >
> >
> > Nope, that's 3.9+ only. (I made the same mistake.)
>
> Oh :(
>
> OK
>
> >
> >
> >  > +except ValueError:
> >
> >  > +self._logger.warning(
> >  > +"WARNING: 'qemu' python packages will be
> imported from"
> >  > +" outside the source tree ('%s')",
> >  > +qemu_srctree_path)
>
> why not use f-strings ? :)
>
>
The logging subsystem still uses % formatting by default, you can see I'm
not actually using the % operator to apply the values -- the Python docs
claim this is for "efficiency" because the string doesn't have to be
evaluated unless the logging statement is actually emitted, but that gain
sounds mostly theoretical to me, because Python still has eager evaluation
of passed arguments ... unless I've missed something.

Either way, using f-strings on logging calls gives you a pylint warning
that I'd just have to then disable, so I just skip the hassle.

Now, the logging system *does* allow you to use new-style python strings [
https://docs.python.org/3/howto/logging-cookbook.html#formatting-styles ]
but given that the default is still %-style and virtually every library
uses that style, I thought it might cause more problems than it creates by
trying to use a different style for just one portion of the codebase. Mind
you, I've never even bothered to try, so my apprehensions might not be
strictly factual ;)


> >  > +self._logger.warning(
> >  > +" Importing instead from '%s'",
> >  > +spec_path.parents[1])
> >  > +
> >
> > Also, I'd move this new chunk 

Re: [PATCH v6 4/5] block/nbd: drop connection_co

2021-09-24 Thread Eric Blake
On Thu, Sep 02, 2021 at 01:38:04PM +0300, Vladimir Sementsov-Ogievskiy wrote:
> OK, that's a big rewrite of the logic.

And a time-consuming review on my part!

> 
> Pre-patch we have an always running coroutine - connection_co. It does
> reply receiving and reconnecting. And it leads to a lot of difficult
> and unobvious code around drained sections and context switch. We also
> abuse bs->in_flight counter which is increased for connection_co and
> temporary decreased in points where we want to allow drained section to
> begin. One of these place is in another file: in nbd_read_eof() in
> nbd/client.c.
> 
> We also cancel reconnect and requests waiting for reconnect on drained
> begin which is not correct. And this patch fixes that.
> 
> Let's finally drop this always running coroutine and go another way:
> do both reconnect and receiving in request coroutines.
> 
> The detailed list of changes below (in the sequence of diff hunks).

Well, depending on the git order file in use ;)

> 
> 1. receiving coroutines are woken directly from nbd_channel_error, when
>we change s->state
> 
> 2. nbd_co_establish_connection_cancel(): we don't have drain_begin now,
>and in nbd_teardown_connection() all requests should already be
>finished (and reconnect is done from request). So
>nbd_co_establish_connection_cancel() is called from
>nbd_cancel_in_flight() (to cancel the request that is doing
>nbd_co_establish_connection()) and from reconnect_delay_timer_cb()
>(previously we didn't need it, as reconnect delay only should cancel
>active requests not the reconnection itself. But now reconnection

Missing )

>itself is done in the separate thread (we now call
>nbd_client_connection_enable_retry() in nbd_open()), and we need to
>cancel the requests that waits in nbd_co_establish_connection()

Singular/plural disagreement. I think the intended meaning is
'requests that wait' and not 'request that waits'.

>now).
> 
> 2. We do receive headers in request coroutine. But we also should

Second point 2; I'll call it 2A below, because it looks related to
point 8.

>dispatch replies for another pending requests. So,

s/another/other/

>nbd_connection_entry() is turned into nbd_receive_replies(), which
>does reply dispatching until it receive another request headers, and

s/until/while/, s/another/other/

>returns when it receive the requested header.

receives

> 
> 3. All old staff around drained sections and context switch is dropped.
>In details:
>- we don't need to move connection_co to new aio context, as we
>  don't have connection_co anymore
>- we don't have a fake "request" of connection_co (extra increasing
>  in_flight), so don't care with it in drain_begin/end
>- we don't stop reconnection during drained section anymore. This
>  means that drain_begin may wait for a long time (up to
>  reconnect_delay). But that's an improvement and more correct
>  behavior see below[*]
> 
> 4. In nbd_teardown_connection() we don't have to wait for
>connection_co, as it is dropped. And cleanup for s->ioc and nbd_yank
>is moved here from removed connection_co.
> 
> 5. In nbd_co_do_establish_connection() we now should handle
>NBD_CLIENT_CONNECTING_NOWAIT: if new request comes when we are in
>NBD_CLIENT_CONNECTING_NOWAIT, it still should call
>nbd_co_establish_connection() (who knows, maybe connection already
>established by thread in background). But we shouldn't wait: if

maybe the connection was already established by another thread in the background

>nbd_co_establish_connection() can't return new channel immediately
>the request should fail (we are in NBD_CLIENT_CONNECTING_NOWAIT
>state).
> 
> 6. nbd_reconnect_attempt() is simplified: it's now easier to wait for
>other requests in the caller, so here we just assert that fact.
>Also delay time is now initialized here: we can easily detect first
>attempt and start a timer.
> 
> 7. nbd_co_reconnect_loop() is dropped, we don't need it. Reconnect
>retries are fully handle by thread (nbd/client-connection.c), delay
>timer we initialize in nbd_reconnect_attempt(), we don't have to
>bother with s->drained and friends. nbd_reconnect_attempt() now
>called from nbd_co_send_request().

A lot going on there, but it's making sense so far.

> 
> 8. nbd_connection_entry is dropped: reconnect is now handled by
>nbd_co_send_request(), receiving reply is now handled by
>nbd_receive_replies(): all handled from request coroutines.
> 
> 9. So, welcome new nbd_receive_replies() called from request coroutine,
>that receives reply header instead of nbd_connection_entry().
>Like with sending requests, only one coroutine may receive in a
>moment. So we introduce receive_mutex, which is locked around
>nbd_receive_reply(). It also protects some related fields. Still,
>full audit of thread-safety in nbd driver is a separate 

Re: [PATCH v3 20/27] linux-user/ppc: Simplify encode_trampoline

2021-09-24 Thread Philippe Mathieu-Daudé

On 9/24/21 18:59, Richard Henderson wrote:

The sigret parameter is never 0, and even if it was the encoding
of the LI instruction would still work.

Reported-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
  linux-user/ppc/signal.c | 6 ++
  1 file changed, 2 insertions(+), 4 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 



Re: [PATCH v3 2/3] QIOChannelSocket: Implement io_async_write & io_async_flush

2021-09-24 Thread Daniel P . Berrangé
On Wed, Sep 22, 2021 at 07:24:22PM -0300, Leonardo Bras wrote:
> Implement the new optional callbacks io_async_write and io_async_flush on
> QIOChannelSocket, but enables it only when MSG_ZEROCOPY feature is
> available in the host kernel, and TCP sockets are used.
> 
> qio_channel_socket_writev() contents were moved to a helper function
> __qio_channel_socket_writev() which accepts an extra 'flag' argument.
> This helper function is used to implement qio_channel_socket_writev(), with
> flags = 0, keeping it's behavior unchanged, and
> qio_channel_socket_async_writev() with flags = MSG_ZEROCOPY.
> 
> qio_channel_socket_async_flush() was implemented by reading the socket's error
> queue, which will have information on MSG_ZEROCOPY send completion.
> There is no need to worry with re-sending packets in case any error happens, 
> as
> MSG_ZEROCOPY only works with TCP and it will re-tranmsmit if any error ocurs.
> 
> Notes on using async_write():
> - As MSG_ZEROCOPY tells the kernel to use the same user buffer to avoid 
> copying,
> some caution is necessary to avoid overwriting any buffer before it's sent.
> If something like this happen, a newer version of the buffer may be sent 
> instead.
> - If this is a problem, it's recommended to use async_flush() before freeing 
> or
> re-using the buffer.
> - When using MSG_ZERCOCOPY, the buffer memory will be locked, so it may 
> require
> a larger amount than usually available to non-root user.
> - If the required amount of locked memory is not available, it falls-back to
> buffer copying behavior, and synchronous sending.
> 
> Signed-off-by: Leonardo Bras 
> ---
>  include/io/channel-socket.h |   2 +
>  include/io/channel.h|   1 +
>  io/channel-socket.c | 176 ++--
>  3 files changed, 169 insertions(+), 10 deletions(-)
> 
> diff --git a/include/io/channel-socket.h b/include/io/channel-socket.h
> index e747e63514..4d1be0637a 100644
> --- a/include/io/channel-socket.h
> +++ b/include/io/channel-socket.h
> @@ -47,6 +47,8 @@ struct QIOChannelSocket {
>  socklen_t localAddrLen;
>  struct sockaddr_storage remoteAddr;
>  socklen_t remoteAddrLen;
> +ssize_t async_queued;
> +ssize_t async_sent;
>  };
>  
>  
> diff --git a/include/io/channel.h b/include/io/channel.h
> index 74f2e3ae8a..611bb2ea26 100644
> --- a/include/io/channel.h
> +++ b/include/io/channel.h
> @@ -31,6 +31,7 @@ OBJECT_DECLARE_TYPE(QIOChannel, QIOChannelClass,
>  
>  
>  #define QIO_CHANNEL_ERR_BLOCK -2
> +#define QIO_CHANNEL_ERR_NOBUFS -3
>  
>  typedef enum QIOChannelFeature QIOChannelFeature;
>  
> diff --git a/io/channel-socket.c b/io/channel-socket.c
> index 606ec97cf7..c67832d0bb 100644
> --- a/io/channel-socket.c
> +++ b/io/channel-socket.c
> @@ -26,9 +26,23 @@
>  #include "io/channel-watch.h"
>  #include "trace.h"
>  #include "qapi/clone-visitor.h"
> +#ifdef CONFIG_LINUX
> +#include 
> +#include 
> +#endif
>  
>  #define SOCKET_MAX_FDS 16
>  
> +static ssize_t qio_channel_socket_async_writev(QIOChannel *ioc,
> +   const struct iovec *iov,
> +   size_t niov,
> +   int *fds,
> +   size_t nfds,
> +   Error **errp);
> +
> +static void qio_channel_socket_async_flush(QIOChannel *ioc,
> +   Error **errp);
> +
>  SocketAddress *
>  qio_channel_socket_get_local_address(QIOChannelSocket *ioc,
>   Error **errp)
> @@ -55,6 +69,8 @@ qio_channel_socket_new(void)
>  
>  sioc = QIO_CHANNEL_SOCKET(object_new(TYPE_QIO_CHANNEL_SOCKET));
>  sioc->fd = -1;
> +sioc->async_queued = 0;
> +sioc->async_sent = 0;
>  
>  ioc = QIO_CHANNEL(sioc);
>  qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN);
> @@ -140,6 +156,7 @@ int qio_channel_socket_connect_sync(QIOChannelSocket *ioc,
>  Error **errp)
>  {
>  int fd;
> +int ret, v = 1;
>  
>  trace_qio_channel_socket_connect_sync(ioc, addr);
>  fd = socket_connect(addr, errp);
> @@ -154,6 +171,19 @@ int qio_channel_socket_connect_sync(QIOChannelSocket 
> *ioc,
>  return -1;
>  }
>  
> +#ifdef CONFIG_LINUX
> +if (addr->type != SOCKET_ADDRESS_TYPE_INET) {
> +return 0;
> +}
> +
> +ret = qemu_setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, , sizeof(v));
> +if (ret >= 0) {
> +QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc);
> +klass->io_async_writev = qio_channel_socket_async_writev;
> +klass->io_async_flush = qio_channel_socket_async_flush;
> +}
> +#endif

This is not write - the async APIs should not be tied 1:1 to ZEROCOPY
usage - we should have them take a flag to request ZEROCOPY behaviour.

> +
>  return 0;
>  }
>  
> @@ -520,12 +550,13 @@ static ssize_t 

Re: [PATCH v3 26/27] linux-user/xtensa: Implement setup_sigtramp

2021-09-24 Thread Philippe Mathieu-Daudé

On 9/24/21 18:59, Richard Henderson wrote:

Create and record the rt signal trampoline.
Use it when the guest does not use SA_RESTORER.

Reviewed-by: Max Filippov 
Signed-off-by: Richard Henderson 
---
  linux-user/xtensa/target_signal.h |  2 ++
  linux-user/xtensa/signal.c| 56 ---
  2 files changed, 38 insertions(+), 20 deletions(-)


Reviewed-by: Philippe Mathieu-Daudé 



[PATCH v5 27/30] tcg/loongarch64: Register the JIT

2021-09-24 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 c34683b2d0..39938fd5c2 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1603,3 +1603,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.33.0




Re: [PATCH v3 10/27] linux-user/i386: Implement setup_sigtramp

2021-09-24 Thread Philippe Mathieu-Daudé

On 9/24/21 18:59, Richard Henderson wrote:

Create and record the two signal trampolines.
Use them when the guest does not use SA_RESTORER.
Note that x86_64 does not use this code.

Signed-off-by: Richard Henderson 
---
  linux-user/i386/target_signal.h   |  2 ++
  linux-user/x86_64/target_signal.h |  3 ++
  linux-user/i386/signal.c  | 56 +--
  3 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/linux-user/i386/target_signal.h b/linux-user/i386/target_signal.h
index 50361af874..64d09f2e75 100644
--- a/linux-user/i386/target_signal.h
+++ b/linux-user/i386/target_signal.h
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
  #include "../generic/signal.h"
  
  #define TARGET_ARCH_HAS_SETUP_FRAME

+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
  #endif /* I386_TARGET_SIGNAL_H */
diff --git a/linux-user/x86_64/target_signal.h 
b/linux-user/x86_64/target_signal.h
index 4ea74f20dd..4673c5a886 100644
--- a/linux-user/x86_64/target_signal.h
+++ b/linux-user/x86_64/target_signal.h
@@ -21,4 +21,7 @@ typedef struct target_sigaltstack {
  
  #include "../generic/signal.h"
  
+/* For x86_64, use of SA_RESTORER is mandatory. */

+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
+
  #endif /* X86_64_TARGET_SIGNAL_H */
diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c
index 3b4b55fc0a..94ab6396a0 100644
--- a/linux-user/i386/signal.c
+++ b/linux-user/i386/signal.c
@@ -310,6 +310,22 @@ get_sigframe(struct target_sigaction *ka, CPUX86State 
*env, size_t frame_size)
  }
  
  #ifndef TARGET_X86_64

+static void install_sigtramp(void *tramp)
+{
+/* This is popl %eax ; movl $syscall,%eax ; int $0x80 */
+__put_user(0xb858, (uint16_t *)(tramp + 0));
+__put_user(TARGET_NR_sigreturn, (int *)(tramp + 2));


I know this is mostly code movement, but using uint32_t would
make it easier to read.


+__put_user(0x80cd, (uint16_t *)(tramp + 6));
+}
+
+static void install_rt_sigtramp(void *tramp)
+{
+/* This is movl $syscall,%eax ; int $0x80 */
+__put_user(0xb8, (char *)(tramp + 0));


Ditto uint8_t,


+__put_user(TARGET_NR_rt_sigreturn, (int *)(tramp + 1));


and uint32_t.


+__put_user(0x80cd, (uint16_t *)(tramp + 5));
+}
+
  /* compare linux/arch/i386/kernel/signal.c:setup_frame() */
  void setup_frame(int sig, struct target_sigaction *ka,
   target_sigset_t *set, CPUX86State *env)
@@ -338,16 +354,9 @@ void setup_frame(int sig, struct target_sigaction *ka,
  if (ka->sa_flags & TARGET_SA_RESTORER) {
  __put_user(ka->sa_restorer, >pretcode);
  } else {
-uint16_t val16;
-abi_ulong retcode_addr;
-retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
-__put_user(retcode_addr, >pretcode);
-/* This is popl %eax ; movl $,%eax ; int $0x80 */
-val16 = 0xb858;
-__put_user(val16, (uint16_t *)(frame->retcode+0));
-__put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
-val16 = 0x80cd;
-__put_user(val16, (uint16_t *)(frame->retcode+6));
+/* This is no longer used, but is retained for ABI compatibility. */
+install_sigtramp(frame->retcode);
+__put_user(default_sigreturn, >pretcode);
  }
  
  /* Set up registers for signal handler */

@@ -416,14 +425,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
  if (ka->sa_flags & TARGET_SA_RESTORER) {
  __put_user(ka->sa_restorer, >pretcode);
  } else {
-uint16_t val16;
-addr = frame_addr + offsetof(struct rt_sigframe, retcode);
-__put_user(addr, >pretcode);
-/* This is movl $,%eax ; int $0x80 */
-__put_user(0xb8, (char *)(frame->retcode+0));
-__put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
-val16 = 0x80cd;
-__put_user(val16, (uint16_t *)(frame->retcode+5));
+/* This is no longer used, but is retained for ABI compatibility. */
+install_rt_sigtramp(frame->retcode);
+__put_user(default_rt_sigreturn, >pretcode);
  }
  #else
  /* XXX: Would be slightly better to return -EFAULT here if test fails
@@ -592,3 +596,19 @@ badframe:
  force_sig(TARGET_SIGSEGV);
  return -TARGET_QEMU_ESIGRETURN;
  }
+
+#ifndef TARGET_X86_64
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);


Shouldn't this be 8 + 7?


+assert(tramp != NULL);
+
+default_sigreturn = sigtramp_page;
+install_sigtramp(tramp);
+
+default_rt_sigreturn = sigtramp_page + 8;
+install_rt_sigtramp(tramp + 8);
+
+unlock_user(tramp, sigtramp_page, 2 * 8);
+}
+#endif






Re: [PATCH v3 3/3] multifd: Send using asynchronous write on nocomp to send RAM pages.

2021-09-24 Thread Daniel P . Berrangé
On Wed, Sep 22, 2021 at 07:24:23PM -0300, Leonardo Bras wrote:
> Change multifd nocomp version to use asynchronous write for RAM pages, and
> benefit of MSG_ZEROCOPY when it's available.
> 
> The asynchronous flush happens on cleanup only, before destroying the 
> QIOChannel.
> 
> This will work fine on RAM migration because the RAM pages are not usually 
> freed,
> and there is no problem on changing the pages content between async_send() and
> the actual sending of the buffer, because this change will dirty the page and
> cause it to be re-sent on a next iteration anyway.
> 
> Signed-off-by: Leonardo Bras 
> ---
>  migration/multifd.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/migration/multifd.c b/migration/multifd.c
> index 377da78f5b..d247207a0a 100644
> --- a/migration/multifd.c
> +++ b/migration/multifd.c
> @@ -105,7 +105,7 @@ static int nocomp_send_prepare(MultiFDSendParams *p, 
> uint32_t used,
>   */
>  static int nocomp_send_write(MultiFDSendParams *p, uint32_t used, Error 
> **errp)
>  {
> -return qio_channel_writev_all(p->c, p->pages->iov, used, errp);
> +return qio_channel_async_writev_all(p->c, p->pages->iov, used, errp);
>  }

This needs to be made conditional so zeroopy is only used if rquested
by the mgmt app, and it isn't going to work in all cases (eg TLS) so
silently enabling it is not good.

>  
>  /**
> @@ -546,6 +546,7 @@ void multifd_save_cleanup(void)
>  MultiFDSendParams *p = _send_state->params[i];
>  Error *local_err = NULL;
>  
> +qio_channel_async_flush(p->c, NULL);
>  socket_send_channel_destroy(p->c);
>  p->c = NULL;
>  qemu_mutex_destroy(>mutex);

This isn't reliable beucase qio_channel_async_flush will return early
even if not everything is flushed.

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




[PATCH v5 28/30] linux-user: Add safe syscall handling for loongarch64 hosts

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 linux-user/host/loongarch64/hostdep.h | 34 
 .../host/loongarch64/safe-syscall.inc.S   | 80 +++
 2 files changed, 114 insertions(+)
 create mode 100644 linux-user/host/loongarch64/hostdep.h
 create mode 100644 linux-user/host/loongarch64/safe-syscall.inc.S

diff --git a/linux-user/host/loongarch64/hostdep.h 
b/linux-user/host/loongarch64/hostdep.h
new file mode 100644
index 00..e3d5fa703f
--- /dev/null
+++ b/linux-user/host/loongarch64/hostdep.h
@@ -0,0 +1,34 @@
+/*
+ * hostdep.h : things which are dependent on the host architecture
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LOONGARCH64_HOSTDEP_H
+#define LOONGARCH64_HOSTDEP_H
+
+/* We have a safe-syscall.inc.S */
+#define HAVE_SAFE_SYSCALL
+
+#ifndef __ASSEMBLER__
+
+/* These are defined by the safe-syscall.inc.S file */
+extern char safe_syscall_start[];
+extern char safe_syscall_end[];
+
+/* Adjust the signal context to rewind out of safe-syscall if we're in it */
+static inline void rewind_if_in_safe_syscall(void *puc)
+{
+ucontext_t *uc = puc;
+unsigned long long *pcreg = >uc_mcontext.__pc;
+
+if (*pcreg > (uintptr_t)safe_syscall_start
+&& *pcreg < (uintptr_t)safe_syscall_end) {
+*pcreg = (uintptr_t)safe_syscall_start;
+}
+}
+
+#endif /* __ASSEMBLER__ */
+
+#endif
diff --git a/linux-user/host/loongarch64/safe-syscall.inc.S 
b/linux-user/host/loongarch64/safe-syscall.inc.S
new file mode 100644
index 00..bb530248b3
--- /dev/null
+++ b/linux-user/host/loongarch64/safe-syscall.inc.S
@@ -0,0 +1,80 @@
+/*
+ * 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 linux-user/safe-syscall.S
+ *
+ * Ported to LoongArch by WANG Xuerui 
+ *
+ * Based on safe-syscall.inc.S code for every other architecture,
+ * 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').
+* We return a long which is the syscall's return value, which
+* may be negative-errno on failure. Conversion to the
+* -1-and-errno-set convention is done by the calling wrapper.
+*/
+safe_syscall_base:
+   .cfi_startproc
+   /*
+* The syscall calling convention is nearly the same as C:
+* we enter with a0 == *signal_pending
+*   a1 == syscall number
+*   a2 ... a7 == syscall arguments
+*   and return the result in a0
+* and the syscall instruction needs
+*   a7 == syscall number
+*   a0 ... a5 == syscall arguments
+*   and returns the result in a0
+* Shuffle everything around appropriately.
+*/
+   move$t0, $a0/* signal_pending pointer */
+   move$t1, $a1/* syscall number */
+   move$a0, $a2/* syscall arguments */
+   move$a1, $a3
+   move$a2, $a4
+   move$a3, $a5
+   move$a4, $a6
+   move$a5, $a7
+   move$a7, $t1
+
+   /*
+* 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, $t0, 0
+   bnez$t1, 0f
+   syscall 0
+safe_syscall_end:
+   /* code path for having successfully executed the syscall */
+   jr  $ra
+
+0:
+   /* code path when we didn't execute the syscall */
+   li.w$a0, -TARGET_ERESTARTSYS
+   jr  $ra
+   .cfi_endproc
+
+   .size   safe_syscall_base, .-safe_syscall_base
-- 
2.33.0




[PATCH v5 29/30] accel/tcg/user-exec: Implement CPU-specific signal handler for loongarch64 hosts

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 accel/tcg/user-exec.c | 73 +++
 1 file changed, 73 insertions(+)

diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 8fed542622..38d4ad8a7d 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -878,6 +878,79 @@ int cpu_signal_handler(int host_signum, void *pinfo,
 return handle_cpu_signal(pc, info, is_write, >uc_sigmask);
 }
 
+#elif defined(__loongarch64)
+
+int cpu_signal_handler(int host_signum, void *pinfo,
+   void *puc)
+{
+siginfo_t *info = pinfo;
+ucontext_t *uc = puc;
+greg_t pc = uc->uc_mcontext.__pc;
+uint32_t insn = *(uint32_t *)pc;
+int is_write = 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 */
+is_write = 1;
+break;
+}
+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) */
+is_write = 1;
+break;
+}
+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 */
+is_write = 1;
+break;
+}
+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 */
+is_write = 1;
+break;
+}
+break;
+}
+
+return handle_cpu_signal(pc, info, is_write, >uc_sigmask);
+}
+
 #else
 
 #error host CPU specific signal handler needed
-- 
2.33.0




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

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
---
 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 c4dcb120cf..d4f1fe5d58 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
@@ -604,6 +609,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,
+ * TCGMemOpIdx 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, TCGMemOpIdx 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, TCGMemOpIdx 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, TCGMemOpIdx 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 v5 25/30] tcg/loongarch64: Implement exit_tb/goto_tb

2021-09-24 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 4900af1853..4437b07541 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -952,6 +952,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.33.0




[PATCH v5 16/30] tcg/loongarch64: Implement shl/shr/sar/rotl/rotr ops

2021-09-24 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 | 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 1ab690bab6..32676e83af 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -580,6 +580,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:
@@ -629,6 +708,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 ef489cbc86..e59c2a7bec 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.33.0




[PATCH v5 24/30] tcg/loongarch64: Implement tcg_target_qemu_prologue

2021-09-24 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 d4f1fe5d58..4900af1853 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -940,6 +940,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])
@@ -1489,3 +1491,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.33.0




[PATCH v5 11/30] tcg/loongarch64: Implement sign-/zero-extension ops

2021-09-24 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 | 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 d23be24211..00dff8b8aa 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -354,6 +354,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
  */
@@ -363,6 +393,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:
@@ -373,6 +404,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:
@@ -386,6 +452,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 5fc097b3c1..2b7d5a19b9 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 TCG_TARGET_HAS_extrl_i64_i321

[PATCH v5 22/30] tcg/loongarch64: Implement simple load/store ops

2021-09-24 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 | 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 0f02f4be04..c4dcb120cf 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -537,6 +537,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
  */
@@ -885,6 +952,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.  */
@@ -899,6 +1009,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);
@@ -926,6 +1045,18 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode 
op)
 case INDEX_op_bswap32_i32:
 case 

[PATCH v5 15/30] tcg/loongarch64: Implement clz/ctz ops

2021-09-24 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 51f0e3b1f1..1ab690bab6 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -384,6 +384,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
  */
@@ -544,6 +566,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:
@@ -604,6 +640,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 02d17d2f6d..ef489cbc86 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.33.0




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

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 configure   | 7 ++-
 meson.build | 2 +-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 1043ccce4f..3a9035385d 100755
--- a/configure
+++ b/configure
@@ -659,6 +659,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
@@ -667,7 +669,7 @@ ARCH=
 # Normalise host CPU name and set ARCH.
 # Note that this case should only have supported host CPUs, not guests.
 case "$cpu" in
-  ppc|ppc64|s390x|sparc64|x32|riscv32|riscv64)
+  ppc|ppc64|s390x|sparc64|x32|riscv32|riscv64|loongarch64)
   ;;
   ppc64le)
 ARCH="ppc64"
@@ -4969,6 +4971,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 15ef4d3c41..fc55712ac3 100644
--- a/meson.build
+++ b/meson.build
@@ -57,7 +57,7 @@ python = import('python').find_installation()
 
 supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 
'sunos', 'linux']
 supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 
'x86_64',
-  'arm', 'aarch64', 'mips', 'mips64', 'sparc', 'sparc64']
+  'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc', 'sparc64']
 
 cpu = host_machine.cpu_family()
 targetos = host_machine.system()
-- 
2.33.0




[PATCH v5 21/30] tcg/loongarch64: Implement tcg_out_call

2021-09-24 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 4e34f4ac97..0f02f4be04 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -504,6 +504,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
  */
@@ -854,6 +887,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.33.0




[PATCH v5 10/30] tcg/loongarch64: Implement goto_ptr

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target-con-set.h | 17 +
 tcg/loongarch64/tcg-target.c.inc | 15 +++
 2 files changed, 32 insertions(+)
 create mode 100644 tcg/loongarch64/tcg-target-con-set.h

diff --git a/tcg/loongarch64/tcg-target-con-set.h 
b/tcg/loongarch64/tcg-target-con-set.h
new file mode 100644
index 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 f1d0047f5b..d23be24211 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -369,9 +369,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.33.0




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

2021-09-24 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 | 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 6ad3cddcee..e3aac6c3de 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -689,6 +689,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:
@@ -780,6 +829,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 e59c2a7bec..2ac2c342c7 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.33.0




[PATCH v5 07/30] tcg/loongarch64: Implement necessary relocation operations

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 66 
 1 file changed, 66 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index f0930f77ef..6967f143e9 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 0;
 }
+
+/*
+ * 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.33.0




[PATCH v5 26/30] tcg/loongarch64: Implement tcg_target_init

2021-09-24 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 4437b07541..c34683b2d0 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1576,3 +1576,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.33.0




[PATCH v5 19/30] tcg/loongarch64: Implement br/brcond ops

2021-09-24 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 | 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 e3aac6c3de..d2339d823d 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -406,6 +406,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
  */
@@ -428,6 +466,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);
@@ -751,6 +800,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.33.0




[PATCH v5 20/30] tcg/loongarch64: Implement setcond ops

2021-09-24 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 d2339d823d..4e34f4ac97 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -406,6 +406,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
  */
@@ -787,6 +847,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:
@@ -873,6 +938,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.33.0




[PATCH v5 17/30] tcg/loongarch64: Implement add/sub ops

2021-09-24 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 
---
 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 32676e83af..6ad3cddcee 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -659,6 +659,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:
@@ -720,6 +750,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:
@@ -742,6 +776,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.33.0




[PATCH v5 04/30] tcg/loongarch64: Add generated instruction opcodes and encoding helpers

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Acked-by: Richard Henderson 
---
 tcg/loongarch64/tcg-insn-defs.c.inc | 979 
 1 file changed, 979 insertions(+)
 create mode 100644 tcg/loongarch64/tcg-insn-defs.c.inc

diff --git a/tcg/loongarch64/tcg-insn-defs.c.inc 
b/tcg/loongarch64/tcg-insn-defs.c.inc
new file mode 100644
index 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);
+tcg_debug_assert(j >= 0 && j <= 0x1f);
+

[PATCH v5 13/30] tcg/loongarch64: Implement deposit/extract ops

2021-09-24 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 | 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 fd77afdd90..c9554936fc 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -503,6 +503,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:
@@ -532,6 +546,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:
@@ -556,6 +572,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 cb1739a54a..084d635a8e 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.33.0




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

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 32 
 tcg/loongarch64/tcg-target.h | 10 +-
 2 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index c9554936fc..51f0e3b1f1 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -517,6 +517,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:
@@ -548,6 +575,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 084d635a8e..02d17d2f6d 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.33.0




[PATCH v5 08/30] tcg/loongarch64: Implement the memory barrier op

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 32 
 1 file changed, 32 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 6967f143e9..8f7c556c37 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.33.0




[PATCH v5 00/30] LoongArch64 port of QEMU TCG

2021-09-24 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.

Tests (run with `ninja test`) all passed, as usual; I also boot-tested
x86_64 (Debian and Gentoo installation CDs) and install-tested aarch64
(Debian netboot installer), and ran riscv64 linux-user emulation with a
chroot; everything seems fine.

## About the series

Only the LP64 ABI is supported, as this is the only one fully
implemented and supported by Loongson. 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
is something not seen in any of the other TCG ports out there, so I'd
like to see if this is acceptable practice (and also maybe bikeshed the
file name).

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: https://github.com/xen0n/binutils-gdb/tree/for-gentoo-2.37-v2
  based on 
https://github.com/loongson/binutils-gdb/tree/loongarch/upstream_v6_a1d65b3
* gcc: https://github.com/xen0n/gcc/tree/for-gentoo-gcc-12-v2
  based on https://github.com/loongson/gcc/tree/loongarch_upstream
* glibc: https://github.com/xen0n/glibc/tree/for-gentoo-glibc-2.34
  based on https://github.com/loongson/glibc/tree/loongarch_2_34_for_upstream
* Linux: https://github.com/xen0n/linux/tree/loongarch-playground
  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

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 to be just SIZE_MAX (but kept
TCG_TARGET_NB_REGS as macro definition)
  - Updated generated instruction definition, made it clear that the
whole file is generated
  - Used deposit64 for hand-written relocation code
  - Reworked tcg_out_movi
- Use pcalau12i + ori for PC-relative values whose offset fits in
  32-bit
- Every individual insn in the slow path (lu12i.w + ori + cu32i.d +
  cu52i.d) can be suppressed if not needed
  - Fixed constraint of setcond ops, don't allow constant zero for 1st
operand

v3 -> v2:

- Addressed all review comments from v2
  - Re-organized changes to tcg-target.h so that it's incrementally
updated in each commit implementing ops
  - Removed support for the eqv op
  - Added support for bswap16_i{32,64} ops
  - Fixed and refactored various places as pointed out 

[PATCH v5 09/30] tcg/loongarch64: Implement tcg_out_mov and tcg_out_movi

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target.c.inc | 109 +++
 1 file changed, 109 insertions(+)

diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 8f7c556c37..f1d0047f5b 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -247,6 +247,113 @@ 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)
+{
+/* Single-instruction cases.  */
+tcg_target_long lo = sextreg(val, 0, 12);
+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_target_long hi12 = sextreg(val, 12, 20);
+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)
+{
+if (type == TCG_TYPE_I32 || val == (int32_t)val) {
+tcg_out_movi_i32(s, rd, val);
+return;
+}
+
+/* PC-relative cases.  */
+intptr_t 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.  */
+tcg_target_long lo = sextreg(val, 0, 12);
+tcg_target_long pc_hi = (val - pc_offset) >> 12;
+tcg_target_long val_hi = val >> 12;
+tcg_target_long 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 (lo != 0) {
+tcg_out_opc_ori(s, rd, rd, lo & 0xfff);
+}
+return;
+}
+
+/* Single cu52i.d case.  */
+if (ctz64(val) >= 52) {
+tcg_out_opc_cu52i_d(s, rd, TCG_REG_ZERO, val >> 52);
+return;
+}
+
+/* Slow path.  Initialize the low 32 bits, then concat high bits.  */
+tcg_out_movi_i32(s, rd, val);
+
+bool rd_high_bits_are_ones = (int32_t)val < 0;
+tcg_target_long hi32 = sextreg(val, 32, 20);
+tcg_target_long hi52 = sextreg(val, 52, 12);
+
+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 +369,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
 tcg_out_mb(s, a0);
 break;
 
+case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
+case INDEX_op_mov_i64:
 default:
 g_assert_not_reached();
 }
-- 
2.33.0




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

2021-09-24 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 | 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 00dff8b8aa..fd77afdd90 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -394,6 +394,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:
@@ -439,6 +441,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:
@@ -466,8 +530,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 2b7d5a19b9..cb1739a54a 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  0
+#define 

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

2021-09-24 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..42eebef78e
--- /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.33.0




[PATCH v5 06/30] tcg/loongarch64: Define the operand constraints

2021-09-24 Thread WANG Xuerui
Signed-off-by: WANG Xuerui 
Reviewed-by: Richard Henderson 
---
 tcg/loongarch64/tcg-target-con-str.h | 28 +++
 tcg/loongarch64/tcg-target.c.inc | 52 
 2 files changed, 80 insertions(+)
 create mode 100644 tcg/loongarch64/tcg-target-con-str.h

diff --git a/tcg/loongarch64/tcg-target-con-str.h 
b/tcg/loongarch64/tcg-target-con-str.h
new file mode 100644
index 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 42eebef78e..f0930f77ef 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 1;
+}
+if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
+return 1;
+}
+if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) {
+return 1;
+}
+if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) {
+return 1;
+}
+if ((ct & TCG_CT_CONST_U12) && val >= 0 && val <= 0xfff) {
+return 1;
+}
+if ((ct & TCG_CT_CONST_C12) && ~val >= 0 && ~val <= 0xfff) {
+return 1;
+}
+if ((ct & TCG_CT_CONST_WSZ) && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
+return 1;
+}
+return 0;
+}
-- 
2.33.0




[PATCH v5 01/30] elf: Add machine type value for LoongArch

2021-09-24 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.33.0




Re: [PATCH v3 1/3] QIOChannel: Add io_async_writev & io_async_flush callbacks

2021-09-24 Thread Daniel P . Berrangé
On Wed, Sep 22, 2021 at 07:24:21PM -0300, Leonardo Bras wrote:
> Adds io_async_writev and io_async_flush as optional callback to 
> QIOChannelClass,
> allowing the implementation of asynchronous writes by subclasses.
> 
> How to use them:
> - Write data using qio_channel_async_writev(),
> - Wait write completion with qio_channel_async_flush().
> 
> Notes:
> Some asynchronous implementations may benefit from zerocopy mechanisms, so 
> it's
> recommended to keep the write buffer untouched until the return of
> qio_channel_async_flush().
> 
> As the new callbacks are optional, if a subclass does not implement them
> there will be a fallback to the mandatory synchronous implementation:
> - io_async_writev will fallback to io_writev,
> - io_async_flush will return without changing anything.
> This makes simpler for the user to make use of the asynchronous 
> implementation.
> 
> Also, some functions like qio_channel_writev_full_all() were adapted to
> offer an async version, and make better use of the new callbacks.
> 
> Signed-off-by: Leonardo Bras 
> ---
>  include/io/channel.h | 93 +---
>  io/channel.c | 66 ---
>  2 files changed, 129 insertions(+), 30 deletions(-)
> 
> diff --git a/include/io/channel.h b/include/io/channel.h
> index 88988979f8..74f2e3ae8a 100644
> --- a/include/io/channel.h
> +++ b/include/io/channel.h
> @@ -136,6 +136,14 @@ struct QIOChannelClass {
>IOHandler *io_read,
>IOHandler *io_write,
>void *opaque);
> +ssize_t (*io_async_writev)(QIOChannel *ioc,
> +   const struct iovec *iov,
> +   size_t niov,
> +   int *fds,
> +   size_t nfds,
> +   Error **errp);
> +   void (*io_async_flush)(QIOChannel *ioc,
> +  Error **errp);
>  };
>  
>  /* General I/O handling functions */
> @@ -255,12 +263,17 @@ ssize_t qio_channel_readv_full(QIOChannel *ioc,
>   * or QIO_CHANNEL_ERR_BLOCK if no data is can be sent
>   * and the channel is non-blocking
>   */
> -ssize_t qio_channel_writev_full(QIOChannel *ioc,
> -const struct iovec *iov,
> -size_t niov,
> -int *fds,
> -size_t nfds,
> -Error **errp);
> +ssize_t __qio_channel_writev_full(QIOChannel *ioc,

Using "__" is undesirable as that namespace is reserved.

> +  const struct iovec *iov,
> +  size_t niov,
> +  int *fds,
> +  size_t nfds,
> +  bool async,
> +  Error **errp);
> +#define qio_channel_writev_full(ioc, iov, niov, fds, nfds, errp) \
> +__qio_channel_writev_full(ioc, iov, niov, fds, nfds, false, errp)
> +#define qio_channel_async_writev_full(ioc, iov, niov, fds, nfds, errp) \
> +__qio_channel_writev_full(ioc, iov, niov, fds, nfds, true, errp)

The API docs only cover the first function, not the second.


>  /**
>   * qio_channel_readv_all_eof:
> @@ -339,10 +352,15 @@ int qio_channel_readv_all(QIOChannel *ioc,
>   *
>   * Returns: 0 if all bytes were written, or -1 on error
>   */
> -int qio_channel_writev_all(QIOChannel *ioc,
> -   const struct iovec *iov,
> -   size_t niov,
> -   Error **erp);
> +int __qio_channel_writev_all(QIOChannel *ioc,
> + const struct iovec *iov,
> + size_t niov,
> + bool async,
> + Error **erp);
> +#define qio_channel_writev_all(ioc, iov, niov, erp) \
> +__qio_channel_writev_all(ioc, iov, niov, false, erp)
> +#define qio_channel_async_writev_all(ioc, iov, niov, erp) \
> +__qio_channel_writev_all(ioc, iov, niov, true, erp)


>  
>  /**
>   * qio_channel_readv:
> @@ -849,10 +867,55 @@ int qio_channel_readv_full_all(QIOChannel *ioc,
>   * Returns: 0 if all bytes were written, or -1 on error
>   */
>  
> -int qio_channel_writev_full_all(QIOChannel *ioc,
> -const struct iovec *iov,
> -size_t niov,
> -int *fds, size_t nfds,
> -Error **errp);
> +int __qio_channel_writev_full_all(QIOChannel *ioc,
> +  const struct iovec *iov,
> +  size_t niov,
> +  int *fds, size_t nfds,
> +  bool async, Error **errp);
> +#define qio_channel_writev_full_all(ioc, iov, niov, fds, nfds, errp) \
> +

[PATCH v5 03/30] tcg/loongarch64: Add the tcg-target.h file

2021-09-24 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..5fc097b3c1
--- /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 v3 24/27] linux-user/sh4: Implement setup_sigtramp

2021-09-24 Thread Richard Henderson
Create and record the two signal trampolines.
Use them when the guest does not use SA_RESTORER.

Cc: Yoshinori Sato 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/sh4/target_signal.h |  2 ++
 linux-user/sh4/signal.c| 40 +++---
 2 files changed, 24 insertions(+), 18 deletions(-)

diff --git a/linux-user/sh4/target_signal.h b/linux-user/sh4/target_signal.h
index d7309b7136..04069cba66 100644
--- a/linux-user/sh4/target_signal.h
+++ b/linux-user/sh4/target_signal.h
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
 #include "../generic/signal.h"
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* SH4_TARGET_SIGNAL_H */
diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c
index d70d744bef..faa869fb19 100644
--- a/linux-user/sh4/signal.c
+++ b/linux-user/sh4/signal.c
@@ -52,7 +52,6 @@ struct target_sigframe
 {
 struct target_sigcontext sc;
 target_ulong extramask[TARGET_NSIG_WORDS-1];
-uint16_t retcode[3];
 };
 
 
@@ -68,7 +67,6 @@ struct target_rt_sigframe
 {
 struct target_siginfo info;
 struct target_ucontext uc;
-uint16_t retcode[3];
 };
 
 
@@ -190,15 +188,9 @@ void setup_frame(int sig, struct target_sigaction *ka,
 /* Set up to return from userspace.  If provided, use a stub
already in userspace.  */
 if (ka->sa_flags & TARGET_SA_RESTORER) {
-regs->pr = (unsigned long) ka->sa_restorer;
+regs->pr = ka->sa_restorer;
 } else {
-/* Generate return code (system call to sigreturn) */
-abi_ulong retcode_addr = frame_addr +
- offsetof(struct target_sigframe, retcode);
-__put_user(MOVW(2), >retcode[0]);
-__put_user(TRAP_NOARG, >retcode[1]);
-__put_user((TARGET_NR_sigreturn), >retcode[2]);
-regs->pr = (unsigned long) retcode_addr;
+regs->pr = default_sigreturn;
 }
 
 /* Set up registers for signal handler */
@@ -248,15 +240,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 /* Set up to return from userspace.  If provided, use a stub
already in userspace.  */
 if (ka->sa_flags & TARGET_SA_RESTORER) {
-regs->pr = (unsigned long) ka->sa_restorer;
+regs->pr = ka->sa_restorer;
 } else {
-/* Generate return code (system call to sigreturn) */
-abi_ulong retcode_addr = frame_addr +
- offsetof(struct target_rt_sigframe, retcode);
-__put_user(MOVW(2), >retcode[0]);
-__put_user(TRAP_NOARG, >retcode[1]);
-__put_user((TARGET_NR_rt_sigreturn), >retcode[2]);
-regs->pr = (unsigned long) retcode_addr;
+regs->pr = default_rt_sigreturn;
 }
 
 /* Set up registers for signal handler */
@@ -334,3 +320,21 @@ badframe:
 force_sig(TARGET_SIGSEGV);
 return -TARGET_QEMU_ESIGRETURN;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 6, 0);
+assert(tramp != NULL);
+
+default_sigreturn = sigtramp_page;
+__put_user(MOVW(2), [0]);
+__put_user(TRAP_NOARG, [1]);
+__put_user(TARGET_NR_sigreturn, [2]);
+
+default_rt_sigreturn = sigtramp_page + 6;
+__put_user(MOVW(2), [3]);
+__put_user(TRAP_NOARG, [4]);
+__put_user(TARGET_NR_rt_sigreturn, [5]);
+
+unlock_user(tramp, sigtramp_page, 2 * 6);
+}
-- 
2.25.1




[PATCH v5 02/30] MAINTAINERS: Add tcg/loongarch64 entry with myself as maintainer

2021-09-24 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 d7915ec128..859e5b5ba2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3114,6 +3114,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.33.0




Re: [RFC PATCH] spapr/xive: Allocate vCPU IPIs from local context

2021-09-24 Thread Greg Kurz
On Fri, 24 Sep 2021 16:58:00 +0200
Cédric Le Goater  wrote:

> [ ... ]
> 
> >> The changes only impact KVM support since we are deferring the IRQ
> >> initialization at the KVM level. What we have to be careful about is not
> >> accessing an ESB page of an interrupt that would not have been initiliazed
> >> in the KVM device, else QEMU gets a sigbus.
> >>
> > 
> > Ok, so this is just needed on a path that leads to xive_esb_rw() or
> > kvmppc_xive_esb_trigger(), right ?
> > 
> > It seems that
> > 
> > h_int_esb()
> >   kvmppc_xive_esb_rw()
> > 
> > can get there with an lisn provided by the guest, and I don't see any
> > such check on the way : h_int_esb() only checks xive_eas_is_valid().
> 
> This call is for LSI interrupts (device only) and not vCPU IPIs. see hcall
> h_int_get_source_info(). I agree a hcall fuzzer could reach it.
> 

Yes we tell the guest to use H_INT_ESB for LSIs only but I don't have
the impression that it is forbidden for the guest to call H_INT_ESB
for arbitrary interrupts.

> An alternative solution would be to claim the vCPU IPIs on demand, like
> we do for the MSIs, and not in spapr_irq_init(). It's a much bigger change
> tough, because the H_INT hcalls consider that the interrupt numbers have
> been claimed.
> 

Maybe it would be simpler to call xive_source_is_initialized() instead of
xive_eas_is_valid() in cases like this, e.g. hcall code since it is shared
between emulation and KVM ?

> C.




[PATCH v3 21/27] linux-user/ppc: Implement setup_sigtramp

2021-09-24 Thread Richard Henderson
Create and record the two signal trampolines.

Cc: qemu-...@nongnu.org
Signed-off-by: Richard Henderson 
---
 linux-user/ppc/target_signal.h |  2 ++
 linux-user/ppc/signal.c| 34 ++
 2 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/linux-user/ppc/target_signal.h b/linux-user/ppc/target_signal.h
index 72fcdd9bfa..82184ab8f2 100644
--- a/linux-user/ppc/target_signal.h
+++ b/linux-user/ppc/target_signal.h
@@ -24,4 +24,6 @@ typedef struct target_sigaltstack {
 #if !defined(TARGET_PPC64)
 #define TARGET_ARCH_HAS_SETUP_FRAME
 #endif
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* PPC_TARGET_SIGNAL_H */
diff --git a/linux-user/ppc/signal.c b/linux-user/ppc/signal.c
index 77f37b9f01..c37744c8fc 100644
--- a/linux-user/ppc/signal.c
+++ b/linux-user/ppc/signal.c
@@ -203,9 +203,6 @@ struct target_func_ptr {
 
 #endif
 
-/* We use the mc_pad field for the signal return trampoline.  */
-#define tramp mc_pad
-
 /* See arch/powerpc/kernel/signal.c.  */
 static target_ulong get_sigframe(struct target_sigaction *ka,
  CPUPPCState *env,
@@ -436,12 +433,7 @@ void setup_frame(int sig, struct target_sigaction *ka,
 /* Save user regs.  */
 save_user_regs(env, >mctx);
 
-/* Construct the trampoline code on the stack. */
-encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)>mctx.tramp);
-
-/* The kernel checks for the presence of a VDSO here.  We don't
-   emulate a vdso, so use a sigreturn system call.  */
-env->lr = (target_ulong) h2g(frame->mctx.tramp);
+env->lr = default_sigreturn;
 
 /* Turn off all fp exceptions.  */
 env->fpscr = 0;
@@ -477,7 +469,6 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 target_sigset_t *set, CPUPPCState *env)
 {
 struct target_rt_sigframe *rt_sf;
-uint32_t *trampptr = 0;
 struct target_mcontext *mctx = 0;
 target_ulong rt_sf_addr, newsp = 0;
 int i, err = 0;
@@ -507,22 +498,17 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 
 #if defined(TARGET_PPC64)
 mctx = _sf->uc.tuc_sigcontext.mcontext;
-trampptr = _sf->trampoline[0];
 
 sc = _sf->uc.tuc_sigcontext;
 __put_user(h2g(mctx), >regs);
 __put_user(sig, >signal);
 #else
 mctx = _sf->uc.tuc_mcontext;
-trampptr = (uint32_t *)_sf->uc.tuc_mcontext.tramp;
 #endif
 
 save_user_regs(env, mctx);
-encode_trampoline(TARGET_NR_rt_sigreturn, trampptr);
 
-/* The kernel checks for the presence of a VDSO here.  We don't
-   emulate a vdso, so use a sigreturn system call.  */
-env->lr = (target_ulong) h2g(trampptr);
+env->lr = default_rt_sigreturn;
 
 /* Turn off all fp exceptions.  */
 env->fpscr = 0;
@@ -720,3 +706,19 @@ abi_long do_swapcontext(CPUArchState *env, abi_ulong 
uold_ctx,
 
 return 0;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
+assert(tramp != NULL);
+
+#ifdef TARGET_ARCH_HAS_SETUP_FRAME
+default_sigreturn = sigtramp_page;
+encode_trampoline(TARGET_NR_sigreturn, tramp + 0);
+#endif
+
+default_rt_sigreturn = sigtramp_page + 8;
+encode_trampoline(TARGET_NR_rt_sigreturn, tramp + 2);
+
+unlock_user(tramp, sigtramp_page, 2 * 8);
+}
-- 
2.25.1




[PATCH v3 23/27] linux-user/s390x: Implement setup_sigtramp

2021-09-24 Thread Richard Henderson
Create and record the two signal trampolines.
Use them when the guest does not use SA_RESTORER.

Cc: qemu-s3...@nongnu.org
Tested-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/s390x/target_signal.h |  2 ++
 linux-user/s390x/signal.c| 24 
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/linux-user/s390x/target_signal.h b/linux-user/s390x/target_signal.h
index bbfc464d44..64f5f42201 100644
--- a/linux-user/s390x/target_signal.h
+++ b/linux-user/s390x/target_signal.h
@@ -19,4 +19,6 @@ typedef struct target_sigaltstack {
 #include "../generic/signal.h"
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* S390X_TARGET_SIGNAL_H */
diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c
index 80f34086d7..676b948147 100644
--- a/linux-user/s390x/signal.c
+++ b/linux-user/s390x/signal.c
@@ -68,7 +68,6 @@ typedef struct {
 target_sigregs sregs;
 int signo;
 target_sigregs_ext sregs_ext;
-uint16_t retcode;
 } sigframe;
 
 #define TARGET_UC_VXRS 2
@@ -85,7 +84,6 @@ struct target_ucontext {
 
 typedef struct {
 uint8_t callee_used_stack[__SIGNAL_FRAMESIZE];
-uint16_t retcode;
 struct target_siginfo info;
 struct target_ucontext uc;
 } rt_sigframe;
@@ -209,9 +207,7 @@ void setup_frame(int sig, struct target_sigaction *ka,
 if (ka->sa_flags & TARGET_SA_RESTORER) {
 restorer = ka->sa_restorer;
 } else {
-restorer = frame_addr + offsetof(sigframe, retcode);
-__put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
-   >retcode);
+restorer = default_sigreturn;
 }
 
 /* Set up registers for signal handler */
@@ -262,9 +258,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 if (ka->sa_flags & TARGET_SA_RESTORER) {
 restorer = ka->sa_restorer;
 } else {
-restorer = frame_addr + offsetof(typeof(*frame), retcode);
-__put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn,
-   >retcode);
+restorer = default_rt_sigreturn;
 }
 
 /* Create siginfo on the signal stack. */
@@ -405,3 +399,17 @@ long do_rt_sigreturn(CPUS390XState *env)
 unlock_user_struct(frame, frame_addr, 0);
 return -TARGET_QEMU_ESIGRETURN;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 + 2, 0);
+assert(tramp != NULL);
+
+default_sigreturn = sigtramp_page;
+__put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn, [0]);
+
+default_rt_sigreturn = sigtramp_page + 2;
+__put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn, [1]);
+
+unlock_user(tramp, sigtramp_page, 2 + 2);
+}
-- 
2.25.1




[PATCH v3 19/27] linux-user/openrisc: Implement setup_sigtramp

2021-09-24 Thread Richard Henderson
Create and record the rt signal trampoline.

Reviewed-by: Stafford Horne 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/openrisc/target_signal.h |  2 ++
 linux-user/openrisc/signal.c| 22 ++
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/linux-user/openrisc/target_signal.h 
b/linux-user/openrisc/target_signal.h
index 8283eaf544..077ec3d5e8 100644
--- a/linux-user/openrisc/target_signal.h
+++ b/linux-user/openrisc/target_signal.h
@@ -26,4 +26,6 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* OPENRISC_TARGET_SIGNAL_H */
diff --git a/linux-user/openrisc/signal.c b/linux-user/openrisc/signal.c
index ca2532bf50..be8b68784a 100644
--- a/linux-user/openrisc/signal.c
+++ b/linux-user/openrisc/signal.c
@@ -38,7 +38,6 @@ typedef struct target_ucontext {
 typedef struct target_rt_sigframe {
 struct target_siginfo info;
 target_ucontext uc;
-uint32_t retcode[4];  /* trampoline code */
 } target_rt_sigframe;
 
 static void restore_sigcontext(CPUOpenRISCState *env, target_sigcontext *sc)
@@ -116,14 +115,8 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 __put_user(set->sig[i], >uc.tuc_sigmask.sig[i]);
 }
 
-/* This is l.ori r11,r0,__NR_sigreturn; l.sys 1; l.nop; l.nop */
-__put_user(0xa960 | TARGET_NR_rt_sigreturn, frame->retcode + 0);
-__put_user(0x2001, frame->retcode + 1);
-__put_user(0x1500, frame->retcode + 2);
-__put_user(0x1500, frame->retcode + 3);
-
 /* Set up registers for signal handler */
-cpu_set_gpr(env, 9, frame_addr + offsetof(target_rt_sigframe, retcode));
+cpu_set_gpr(env, 9, default_rt_sigreturn);
 cpu_set_gpr(env, 3, sig);
 cpu_set_gpr(env, 4, frame_addr + offsetof(target_rt_sigframe, info));
 cpu_set_gpr(env, 5, frame_addr + offsetof(target_rt_sigframe, uc));
@@ -169,3 +162,16 @@ long do_rt_sigreturn(CPUOpenRISCState *env)
 force_sig(TARGET_SIGSEGV);
 return 0;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 8, 0);
+assert(tramp != NULL);
+
+/* This is l.ori r11,r0,__NR_sigreturn; l.sys 1 */
+__put_user(0xa960 | TARGET_NR_rt_sigreturn, tramp + 0);
+__put_user(0x2001, tramp + 1);
+
+default_rt_sigreturn = sigtramp_page;
+unlock_user(tramp, sigtramp_page, 8);
+}
-- 
2.25.1




[PATCH v3 17/27] linux-user/nios2: Map a real kuser page

2021-09-24 Thread Richard Henderson
The first word of page1 is data, so the whole thing
can't be implemented with emulation of addresses.

Hijack trap number 31 to implement cmpxchg.

Set default_rt_sigreturn based on the kuser page.

Signed-off-by: Richard Henderson 
---
 linux-user/nios2/target_signal.h |  3 ++
 linux-user/elfload.c | 35 ++
 linux-user/nios2/cpu_loop.c  | 51 +---
 linux-user/nios2/signal.c|  2 +-
 target/nios2/translate.c |  9 --
 5 files changed, 66 insertions(+), 34 deletions(-)

diff --git a/linux-user/nios2/target_signal.h b/linux-user/nios2/target_signal.h
index aebf749f12..fe266c4c51 100644
--- a/linux-user/nios2/target_signal.h
+++ b/linux-user/nios2/target_signal.h
@@ -19,4 +19,7 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+/* Nios2 uses a fixed address on the kuser page for sigreturn. */
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
+
 #endif /* NIOS2_TARGET_SIGNAL_H */
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 459a26ef1d..7b3a91b3ed 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1100,6 +1100,41 @@ static void elf_core_copy_regs(target_elf_gregset_t 
*regs, const CPUMBState *env
 
 static void init_thread(struct target_pt_regs *regs, struct image_info *infop)
 {
+static const uint8_t kuser_page[4 + 2 * 64] = {
+/* __kuser_helper_version */
+[0x00] = 0x02, 0x00, 0x00, 0x00,
+
+/* __kuser_cmpxchg */
+[0x04] = 0xfa, 0x6f, 0x3b, 0x00,  /* trap 31 */
+ 0x3a, 0x28, 0x00, 0xf8,  /* ret */
+
+/* __kuser_sigtramp */
+[0x44] = 0xc4, 0x22, 0x80, 0x00,  /* movi r2, __NR_rt_sigreturn */
+ 0x3a, 0x68, 0x3b, 0x00,  /* trap 0 */
+};
+
+abi_ulong pg;
+uint8_t *ph;
+
+pg = target_mmap(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0);
+
+/*
+ * If the mmap doesn't give us exactly page 1, there's nothing
+ * we can do, and it's unlikely that the program will be able
+ * to continue.  FIXME: Error out now?
+ */
+assert(pg == TARGET_PAGE_SIZE);
+
+ph = lock_user(VERIFY_WRITE, pg, sizeof(kuser_page), 0);
+memcpy(ph, kuser_page, sizeof(kuser_page));
+unlock_user(ph, pg, sizeof(kuser_page));
+target_mprotect(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC);
+
+/* Install __kuser_sigtramp */
+default_rt_sigreturn = TARGET_PAGE_SIZE + 0x44;
+
 regs->ea = infop->entry;
 regs->sp = infop->start_stack;
 regs->estatus = 0x3;
diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
index 246293a501..12070c8a3c 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;
 
@@ -73,6 +72,32 @@ void cpu_loop(CPUNios2State *env)
 force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP,
 env->regs[R_PC]);
 break;
+
+case 31: /* 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;
 
@@ -83,29 +108,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] == 

[PATCH v3 14/27] linux-user/mips: Tidy install_sigtramp

2021-09-24 Thread Richard Henderson
The return value is constant 0, and unused as well -- change to void.
Drop inline marker.  Change tramp type to uint32_t* for clarity.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/mips/signal.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/linux-user/mips/signal.c b/linux-user/mips/signal.c
index d174b3453c..64072779b9 100644
--- a/linux-user/mips/signal.c
+++ b/linux-user/mips/signal.c
@@ -87,10 +87,8 @@ struct target_rt_sigframe {
 };
 
 /* Install trampoline to jump back from signal handler */
-static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall)
+static void install_sigtramp(uint32_t *tramp, unsigned int syscall)
 {
-int err = 0;
-
 /*
  * Set up the return code ...
  *
@@ -100,7 +98,6 @@ static inline int install_sigtramp(unsigned int *tramp,   
unsigned int syscall)
 
 __put_user(0x2402 + syscall, tramp + 0);
 __put_user(0x000c  , tramp + 1);
-return err;
 }
 
 static inline void setup_sigcontext(CPUMIPSState *regs,
-- 
2.25.1




[PATCH v3 15/27] linux-user/mips: Implement setup_sigtramp

2021-09-24 Thread Richard Henderson
Create and record the two signal trampolines.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
---
 linux-user/mips/target_signal.h   |  1 +
 linux-user/mips64/target_signal.h |  2 ++
 linux-user/mips/signal.c  | 34 ++-
 3 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/linux-user/mips/target_signal.h b/linux-user/mips/target_signal.h
index d521765f6b..780a4ddf29 100644
--- a/linux-user/mips/target_signal.h
+++ b/linux-user/mips/target_signal.h
@@ -73,6 +73,7 @@ typedef struct target_sigaltstack {
 /* compare linux/arch/mips/kernel/signal.c:setup_frame() */
 #define TARGET_ARCH_HAS_SETUP_FRAME
 #endif
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
 
 /* bit-flags */
 #define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
diff --git a/linux-user/mips64/target_signal.h 
b/linux-user/mips64/target_signal.h
index d857c55e4c..275e9b7f9a 100644
--- a/linux-user/mips64/target_signal.h
+++ b/linux-user/mips64/target_signal.h
@@ -76,4 +76,6 @@ typedef struct target_sigaltstack {
 /* compare linux/arch/mips/kernel/signal.c:setup_frame() */
 #define TARGET_ARCH_HAS_SETUP_FRAME
 #endif
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* MIPS64_TARGET_SIGNAL_H */
diff --git a/linux-user/mips/signal.c b/linux-user/mips/signal.c
index 64072779b9..8f79e405ec 100644
--- a/linux-user/mips/signal.c
+++ b/linux-user/mips/signal.c
@@ -209,8 +209,6 @@ void setup_frame(int sig, struct target_sigaction * ka,
 goto give_sigsegv;
 }
 
-install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
-
 setup_sigcontext(regs, >sf_sc);
 
 for(i = 0; i < TARGET_NSIG_WORDS; i++) {
@@ -231,7 +229,7 @@ void setup_frame(int sig, struct target_sigaction * ka,
 regs->active_tc.gpr[ 5] = 0;
 regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
 regs->active_tc.gpr[29] = frame_addr;
-regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
+regs->active_tc.gpr[31] = default_sigreturn;
 /* The original kernel code sets CP0_EPC to the handler
 * since it returns to userland using eret
 * we cannot do this here, and we must set PC directly */
@@ -305,8 +303,6 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 goto give_sigsegv;
 }
 
-install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
-
 tswap_siginfo(>rs_info, info);
 
 __put_user(0, >rs_uc.tuc_flags);
@@ -335,11 +331,13 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 env->active_tc.gpr[ 6] = frame_addr
  + offsetof(struct target_rt_sigframe, rs_uc);
 env->active_tc.gpr[29] = frame_addr;
-env->active_tc.gpr[31] = frame_addr
- + offsetof(struct target_rt_sigframe, rs_code);
-/* The original kernel code sets CP0_EPC to the handler
-* since it returns to userland using eret
-* we cannot do this here, and we must set PC directly */
+env->active_tc.gpr[31] = default_rt_sigreturn;
+
+/*
+ * The original kernel code sets CP0_EPC to the handler
+ * since it returns to userland using eret
+ * we cannot do this here, and we must set PC directly
+ */
 env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
 mips_set_hflags_isa_mode_from_pc(env);
 unlock_user_struct(frame, frame_addr, 1);
@@ -379,3 +377,19 @@ badframe:
 force_sig(TARGET_SIGSEGV);
 return -TARGET_QEMU_ESIGRETURN;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
+assert(tramp != NULL);
+
+#ifdef TARGET_ARCH_HAS_SETUP_FRAME
+default_sigreturn = sigtramp_page;
+install_sigtramp(tramp, TARGET_NR_sigreturn);
+#endif
+
+default_rt_sigreturn = sigtramp_page + 8;
+install_sigtramp(tramp + 2, TARGET_NR_rt_sigreturn);
+
+unlock_user(tramp, sigtramp_page, 2 * 8);
+}
-- 
2.25.1




[PATCH v3 26/27] linux-user/xtensa: Implement setup_sigtramp

2021-09-24 Thread Richard Henderson
Create and record the rt signal trampoline.
Use it when the guest does not use SA_RESTORER.

Reviewed-by: Max Filippov 
Signed-off-by: Richard Henderson 
---
 linux-user/xtensa/target_signal.h |  2 ++
 linux-user/xtensa/signal.c| 56 ---
 2 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/linux-user/xtensa/target_signal.h 
b/linux-user/xtensa/target_signal.h
index c60bf656f6..1c7ee73154 100644
--- a/linux-user/xtensa/target_signal.h
+++ b/linux-user/xtensa/target_signal.h
@@ -20,4 +20,6 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif
diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c
index 7a3bfb92ca..81572a5fc7 100644
--- a/linux-user/xtensa/signal.c
+++ b/linux-user/xtensa/signal.c
@@ -128,6 +128,29 @@ static int setup_sigcontext(struct target_rt_sigframe 
*frame,
 return 1;
 }
 
+static void install_sigtramp(uint8_t *tramp)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+/* Generate instruction:  MOVI a2, __NR_rt_sigreturn */
+__put_user(0x22, [0]);
+__put_user(0x0a, [1]);
+__put_user(TARGET_NR_rt_sigreturn, [2]);
+/* Generate instruction:  SYSCALL */
+__put_user(0x00, [3]);
+__put_user(0x05, [4]);
+__put_user(0x00, [5]);
+#else
+/* Generate instruction:  MOVI a2, __NR_rt_sigreturn */
+__put_user(0x22, [0]);
+__put_user(0xa0, [1]);
+__put_user(TARGET_NR_rt_sigreturn, [2]);
+/* Generate instruction:  SYSCALL */
+__put_user(0x00, [3]);
+__put_user(0x50, [4]);
+__put_user(0x00, [5]);
+#endif
+}
+
 void setup_rt_frame(int sig, struct target_sigaction *ka,
 target_siginfo_t *info,
 target_sigset_t *set, CPUXtensaState *env)
@@ -164,26 +187,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 if (ka->sa_flags & TARGET_SA_RESTORER) {
 ra = ka->sa_restorer;
 } else {
-ra = frame_addr + offsetof(struct target_rt_sigframe, retcode);
-#ifdef TARGET_WORDS_BIGENDIAN
-/* Generate instruction:  MOVI a2, __NR_rt_sigreturn */
-__put_user(0x22, >retcode[0]);
-__put_user(0x0a, >retcode[1]);
-__put_user(TARGET_NR_rt_sigreturn, >retcode[2]);
-/* Generate instruction:  SYSCALL */
-__put_user(0x00, >retcode[3]);
-__put_user(0x05, >retcode[4]);
-__put_user(0x00, >retcode[5]);
-#else
-/* Generate instruction:  MOVI a2, __NR_rt_sigreturn */
-__put_user(0x22, >retcode[0]);
-__put_user(0xa0, >retcode[1]);
-__put_user(TARGET_NR_rt_sigreturn, >retcode[2]);
-/* Generate instruction:  SYSCALL */
-__put_user(0x00, >retcode[3]);
-__put_user(0x50, >retcode[4]);
-__put_user(0x00, >retcode[5]);
-#endif
+/* Not used, but retain for ABI compatibility. */
+install_sigtramp(frame->retcode);
+ra = default_rt_sigreturn;
 }
 memset(env->regs, 0, sizeof(env->regs));
 env->pc = ka->_sa_handler;
@@ -264,3 +270,13 @@ badframe:
 force_sig(TARGET_SIGSEGV);
 return -TARGET_QEMU_ESIGRETURN;
 }
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+uint8_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 6, 0);
+assert(tramp != NULL);
+
+default_rt_sigreturn = sigtramp_page;
+install_sigtramp(tramp);
+unlock_user(tramp, sigtramp_page, 6);
+}
-- 
2.25.1




[PATCH v3 10/27] linux-user/i386: Implement setup_sigtramp

2021-09-24 Thread Richard Henderson
Create and record the two signal trampolines.
Use them when the guest does not use SA_RESTORER.
Note that x86_64 does not use this code.

Signed-off-by: Richard Henderson 
---
 linux-user/i386/target_signal.h   |  2 ++
 linux-user/x86_64/target_signal.h |  3 ++
 linux-user/i386/signal.c  | 56 +--
 3 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/linux-user/i386/target_signal.h b/linux-user/i386/target_signal.h
index 50361af874..64d09f2e75 100644
--- a/linux-user/i386/target_signal.h
+++ b/linux-user/i386/target_signal.h
@@ -22,4 +22,6 @@ typedef struct target_sigaltstack {
 #include "../generic/signal.h"
 
 #define TARGET_ARCH_HAS_SETUP_FRAME
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
+
 #endif /* I386_TARGET_SIGNAL_H */
diff --git a/linux-user/x86_64/target_signal.h 
b/linux-user/x86_64/target_signal.h
index 4ea74f20dd..4673c5a886 100644
--- a/linux-user/x86_64/target_signal.h
+++ b/linux-user/x86_64/target_signal.h
@@ -21,4 +21,7 @@ typedef struct target_sigaltstack {
 
 #include "../generic/signal.h"
 
+/* For x86_64, use of SA_RESTORER is mandatory. */
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
+
 #endif /* X86_64_TARGET_SIGNAL_H */
diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c
index 3b4b55fc0a..94ab6396a0 100644
--- a/linux-user/i386/signal.c
+++ b/linux-user/i386/signal.c
@@ -310,6 +310,22 @@ get_sigframe(struct target_sigaction *ka, CPUX86State 
*env, size_t frame_size)
 }
 
 #ifndef TARGET_X86_64
+static void install_sigtramp(void *tramp)
+{
+/* This is popl %eax ; movl $syscall,%eax ; int $0x80 */
+__put_user(0xb858, (uint16_t *)(tramp + 0));
+__put_user(TARGET_NR_sigreturn, (int *)(tramp + 2));
+__put_user(0x80cd, (uint16_t *)(tramp + 6));
+}
+
+static void install_rt_sigtramp(void *tramp)
+{
+/* This is movl $syscall,%eax ; int $0x80 */
+__put_user(0xb8, (char *)(tramp + 0));
+__put_user(TARGET_NR_rt_sigreturn, (int *)(tramp + 1));
+__put_user(0x80cd, (uint16_t *)(tramp + 5));
+}
+
 /* compare linux/arch/i386/kernel/signal.c:setup_frame() */
 void setup_frame(int sig, struct target_sigaction *ka,
  target_sigset_t *set, CPUX86State *env)
@@ -338,16 +354,9 @@ void setup_frame(int sig, struct target_sigaction *ka,
 if (ka->sa_flags & TARGET_SA_RESTORER) {
 __put_user(ka->sa_restorer, >pretcode);
 } else {
-uint16_t val16;
-abi_ulong retcode_addr;
-retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
-__put_user(retcode_addr, >pretcode);
-/* This is popl %eax ; movl $,%eax ; int $0x80 */
-val16 = 0xb858;
-__put_user(val16, (uint16_t *)(frame->retcode+0));
-__put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
-val16 = 0x80cd;
-__put_user(val16, (uint16_t *)(frame->retcode+6));
+/* This is no longer used, but is retained for ABI compatibility. */
+install_sigtramp(frame->retcode);
+__put_user(default_sigreturn, >pretcode);
 }
 
 /* Set up registers for signal handler */
@@ -416,14 +425,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
 if (ka->sa_flags & TARGET_SA_RESTORER) {
 __put_user(ka->sa_restorer, >pretcode);
 } else {
-uint16_t val16;
-addr = frame_addr + offsetof(struct rt_sigframe, retcode);
-__put_user(addr, >pretcode);
-/* This is movl $,%eax ; int $0x80 */
-__put_user(0xb8, (char *)(frame->retcode+0));
-__put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
-val16 = 0x80cd;
-__put_user(val16, (uint16_t *)(frame->retcode+5));
+/* This is no longer used, but is retained for ABI compatibility. */
+install_rt_sigtramp(frame->retcode);
+__put_user(default_rt_sigreturn, >pretcode);
 }
 #else
 /* XXX: Would be slightly better to return -EFAULT here if test fails
@@ -592,3 +596,19 @@ badframe:
 force_sig(TARGET_SIGSEGV);
 return -TARGET_QEMU_ESIGRETURN;
 }
+
+#ifndef TARGET_X86_64
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+uint16_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
+assert(tramp != NULL);
+
+default_sigreturn = sigtramp_page;
+install_sigtramp(tramp);
+
+default_rt_sigreturn = sigtramp_page + 8;
+install_rt_sigtramp(tramp + 8);
+
+unlock_user(tramp, sigtramp_page, 2 * 8);
+}
+#endif
-- 
2.25.1




  1   2   3   4   >