[PATCH] Fixes rtl8139 driver for old kernels.

2024-05-11 Thread Hans
Old linux kernel rtl8139 drivers (ex. debian 2.1) uses outb to set the rx
mode for RxConfig. Unfortunatelly qemu does not support outb for RxConfig.

Signed-off-by: Hans 
---
 hw/net/rtl8139.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index 897c86ec41..e6244cfd7f 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -2738,7 +2738,10 @@ static void rtl8139_io_writeb(void *opaque, uint8_t 
addr, uint32_t val)
 }
 
 break;
-
+case RxConfig:
+DPRINTF("RxConfig write(b) val=0x%02x\n", val);
+rtl8139_RxConfig_write(s, (rtl8139_RxConfig_read(s) & 0xFF00) 
| val );
+break;
 default:
 DPRINTF("not implemented write(b) addr=0x%x val=0x%02x\n", addr,
 val);
-- 
2.34.1




[PATCH] mips64el-softmmu: Enable MTTCG

2024-05-11 Thread Jiaxun Yang
MTTCG was disabled in a092a9554771 ("configure: disable MTTCG
for MIPS guests") due to test case instability.

I was able to reproduce this issue with in latest QEMU and look
into reason behind that.

What actually happend is kernel's CP0 timer synchronisation
mechanism assumed a consistent latency in memory access between
cores, which TCG can't guarantee. Thus there is a huge drift in
count value between cores, and in early kernel versions CP0 timer
is always used as sched_clock.

sched_clock drift back on some cores triggered RCU watchdog in
some extreme cases.

This can be resolved by setting clocksource to MIPS, which allows
clocksource to drift together with sched_clock. However this will
leed to other problems after boot.

Another option would beupdating kernel to later version, which
will use GIC as sched_clock.

In non-MTTCG build, the execution is slow enough so kernel won't
observe back drifts.

Test results:

With clocksource=MIPS
```
 ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \
-display none -vga none -serial mon:stdio \
-machine malta -kernel ./vmlinux-4.7.0-rc1.I6400 \
-cpu I6400 -smp 8 -vga std \
-append "printk.time=0 clocksource=MIPS console=tty0 console=ttyS0 
panic=-1" \
--no-reboot

100, 0, PASS, 5.258126, 100, 100, -
Results summary:
0: 100 times (100.00%), avg time 6.508 (55.53 varience/7.45 deviation)
Ran command 100 times, 100 passes
```

With linux-next:
```
 ~/tmp/retry/retry.py -n 100 -c -- ./qemu-system-mips64el \
-display none -vga none -serial mon:stdio \
-machine malta -kernel ~/linux-next/vmlinux \
-cpu I6400 -smp 8 -vga std \
-append "printk.time=0 console=tty0 console=ttyS0 panic=-1" \
--no-reboot

100, 0, PASS, 4.507921, 100, 100, -
Results summary:
0: 100 times (100.00%), avg time 4.233 (0.04 varience/0.21 deviation)
Ran command 100 times, 100 passes
```

Signed-off-by: Jiaxun Yang 
---
I'll leave the test case alone as it's already marked as QEMU_TEST_FLAKY_TESTS
---
 configs/targets/mips64el-softmmu.mak | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/targets/mips64el-softmmu.mak 
b/configs/targets/mips64el-softmmu.mak
index 8d9ab3ddc4b1..199b1d909a7d 100644
--- a/configs/targets/mips64el-softmmu.mak
+++ b/configs/targets/mips64el-softmmu.mak
@@ -1,3 +1,4 @@
 TARGET_ARCH=mips64
 TARGET_BASE_ARCH=mips
+TARGET_SUPPORTS_MTTCG=y
 TARGET_NEED_FDT=y

---
base-commit: 248f6f62df073a3b4158fd0093863ab885feabb5
change-id: 20240511-mips_mttcg-47a6b19074b3

Best regards,
-- 
Jiaxun Yang 




[PATCH v11 04/10] virtio-gpu: Don't require udmabuf when blobs and virgl are enabled

2024-05-11 Thread Dmitry Osipenko
The udmabuf usage is mandatory when virgl is disabled and blobs feature
enabled in the Qemu machine configuration. If virgl and blobs are enabled,
then udmabuf requirement is optional. Since udmabuf isn't widely supported
by a popular Linux distros today, let's relax the udmabuf requirement for
blobs=on,virgl=on. Now, a full-featured virtio-gpu acceleration is
available to Qemu users without a need to have udmabuf available in the
system.

Reviewed-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Reviewed-by: Marc-André Lureau 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index ae831b6b3e3e..dac272ecadb1 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1472,6 +1472,7 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 
 if (virtio_gpu_blob_enabled(g->parent_obj.conf)) {
 if (!virtio_gpu_rutabaga_enabled(g->parent_obj.conf) &&
+!virtio_gpu_virgl_enabled(g->parent_obj.conf) &&
 !virtio_gpu_have_udmabuf()) {
 error_setg(errp, "need rutabaga or udmabuf for blob resources");
 return;
-- 
2.44.0




[PATCH v11 02/10] virtio-gpu: Use pkgconfig version to decide which virgl features are available

2024-05-11 Thread Dmitry Osipenko
New virglrerenderer features were stabilized with release of v1.0.0.
Presence of symbols in virglrenderer.h doesn't guarantee ABI compatibility
with pre-release development versions of libvirglerender. Use virglrenderer
version to decide reliably which virgl features are available.

Signed-off-by: Dmitry Osipenko 
---
 meson.build | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/meson.build b/meson.build
index 83ae4347c7f9..ca2798dbac37 100644
--- a/meson.build
+++ b/meson.build
@@ -2286,11 +2286,8 @@ config_host_data.set('CONFIG_PNG', png.found())
 config_host_data.set('CONFIG_VNC', vnc.found())
 config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
-if virgl.found()
-  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT',
-   cc.has_member('struct 
virgl_renderer_resource_info_ext', 'd3d_tex2d',
- prefix: '#include ',
- dependencies: virgl))
+if virgl.version().version_compare('>=1.0.0')
+  config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT', 1)
 endif
 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
 config_host_data.set('CONFIG_VTE', vte.found())
-- 
2.44.0




[PATCH v11 00/10] Support blob memory and venus on qemu

2024-05-11 Thread Dmitry Osipenko
Hello,

This series enables Vulkan Venus context support on virtio-gpu.

All virglrender and almost all Linux kernel prerequisite changes
needed by Venus are already in upstream. For kernel there is a pending
KVM patchset that fixes mapping of compound pages needed for DRM drivers
using TTM [1], othewrwise hostmem blob mapping will fail with a KVM error
from Qemu.

[1] https://lore.kernel.org/kvm/20240229025759.1187910-1-steve...@google.com/

You'll need to use recent Mesa version containing patch that removes
dependency on cross-device feature from Venus that isn't supported by
Qemu [2].

[2] 
https://gitlab.freedesktop.org/mesa/mesa/-/commit/087e9a96d13155e26987befae78b6ccbb7ae242b

Example Qemu cmdline that enables Venus:

  qemu-system-x86_64 -device virtio-vga-gl,hostmem=4G,blob=true,venus=true \
  -machine q35,accel=kvm,memory-backend=mem1 \
  -object memory-backend-memfd,id=mem1,size=8G -m 8G


Changes from V10 to V11

- Replaced cmd_resume bool in struct ctrl_command with
  "cmd->finished + !VIRTIO_GPU_FLAG_FENCE" checking as was requested
  by Akihiko Odaki.

- Reworked virgl_cmd_resource_unmap/unref_blob() to avoid re-adding
  the 'async_unmap_in_progress' flag that was dropped in v9:

1. virgl_cmd_resource_[un]map_blob() now doesn't check itself whether
   resource was previously mapped and lets virglrenderer to do the
   checking.

2. error returned by virgl_renderer_resource_unmap() is now handled
   and reported properly, previously the error wasn't checked. The
   virgl_renderer_resource_unmap() fails if resource wasn't mapped.

3. virgl_cmd_resource_unref_blob() now doesn't allow to unref resource
   that is mapped, it's a error condition if guest didn't unmap resource
   before doing the unref. Previously unref was implicitly unmapping
   resource.

Changes from V9 to V10

- Dropped 'async_unmap_in_progress' variable and switched to use
  aio_bh_new() isntead of oneshot variant in the "blob commands" patch.

- Further improved error messages by printing error code when actual error
  occurrs and using ERR_UNSPEC instead of ERR_ENOMEM when we don't really
  know if it was ENOMEM for sure.

- Added vdc->unrealize for the virtio GL device and freed virgl data.

- Dropped UUID and doc/migration patches. UUID feature isn't needed
  anymore, instead we changed Mesa Venus driver to not require UUID.

- Renamed virtio-gpu-gl "vulkan" property name back to "venus".

Changes from V8 to V9

- Added resuming of cmdq processing when hostmem MR is freed,
  as was suggested by Akihiko Odaki.

- Added more error messages, suggested by Akihiko Odaki

- Dropped superfluous 'res->async_unmap_completed', suggested
  by Akihiko Odaki.

- Kept using cmd->suspended flag. Akihiko Odaki suggested to make
  virtio_gpu_virgl_process_cmd() return false if cmd processing is
  suspended, but it's not easy to implement due to ubiquitous
  VIRTIO_GPU_FILL_CMD() macros that returns void, requiring to change
  all the virtio-gpu processing code.

- Added back virtio_gpu_virgl_resource as was requested by Akihiko Odaki,
  though I'm not convinced it's really needed.

- Switched to use GArray, renamed capset2_max_ver/size vars and moved
  "vulkan" property definition to the virtio-gpu-gl device in the Venus
  patch, like was suggested by Akihiko Odaki.

- Moved UUID to virtio_gpu_virgl_resource and dropped UUID save/restore
  since it will require bumping VM version and virgl device isn't miratable
  anyways.

- Fixed exposing UUID feature with Rutabaga

- Dropped linux-headers update patch because headers were already updated
  in Qemu/staging.

- Added patch that updates virtio migration doc with a note about virtio-gpu
  migration specifics, suggested by Akihiko Odaki.

- Addressed coding style issue noticed by Akihiko Odaki

Changes from V7 to V8

- Supported suspension of virtio-gpu commands processing and made
  unmapping of hostmem region asynchronous by blocking/suspending
  cmd processing until region is unmapped. Suggested by Akihiko Odaki.

- Fixed arm64 building of x86 targets using updated linux-headers.
  Corrected the update script. Thanks to Rob Clark for reporting
  the issue.

- Added new patch that makes registration of virgl capsets dynamic.
  Requested by Antonio Caggiano and Pierre-Eric Pelloux-Prayer.

- Venus capset now isn't advertised if Vulkan is disabled with vulkan=false

Changes from V6 to V7

- Used scripts/update-linux-headers.sh to update Qemu headers based
  on Linux v6.8-rc3 that adds Venus capset definition to virtio-gpu
  protocol, was requested by Peter Maydel

- Added r-bs that were given to v6 patches. Corrected missing s-o-bs

- Dropped context_init Qemu's virtio-gpu device configuration flag,
  was suggested by Marc-André Lureau

- Added missing error condition checks spotted by Marc-André Lureau
  and Akihiko Odaki, and few more

- Returned back res->mr referencing to memory_region_init_ram_ptr() like
  was suggested by Akihiko Odaki. 

[PATCH v11 06/10] virtio-gpu: Support blob scanout using dmabuf fd

2024-05-11 Thread Dmitry Osipenko
From: Robert Beckett 

Support displaying blob resources by handling SET_SCANOUT_BLOB
command.

Signed-by: Antonio Caggiano 
Signed-off-by: Robert Beckett 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 109 +
 hw/display/virtio-gpu.c|  12 ++--
 include/hw/virtio/virtio-gpu.h |   7 +++
 meson.build|   1 +
 4 files changed, 123 insertions(+), 6 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index c6c63ca1c373..524f15220b7f 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -17,6 +17,8 @@
 #include "trace.h"
 #include "hw/virtio/virtio.h"
 #include "hw/virtio/virtio-gpu.h"
+#include "hw/virtio/virtio-gpu-bswap.h"
+#include "hw/virtio/virtio-gpu-pixman.h"
 
 #include "ui/egl-helpers.h"
 
@@ -78,6 +80,7 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
 res->base.height = c2d.height;
 res->base.format = c2d.format;
 res->base.resource_id = c2d.resource_id;
+res->base.dmabuf_fd = -1;
 QTAILQ_INSERT_HEAD(>reslist, >base, next);
 
 args.handle = c2d.resource_id;
@@ -125,6 +128,7 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 res->base.height = c3d.height;
 res->base.format = c3d.format;
 res->base.resource_id = c3d.resource_id;
+res->base.dmabuf_fd = -1;
 QTAILQ_INSERT_HEAD(>reslist, >base, next);
 
 args.handle = c3d.resource_id;
@@ -509,6 +513,106 @@ static void virgl_cmd_get_capset(VirtIOGPU *g,
 g_free(resp);
 }
 
+#ifdef HAVE_VIRGL_RESOURCE_BLOB
+static void virgl_cmd_set_scanout_blob(VirtIOGPU *g,
+   struct virtio_gpu_ctrl_command *cmd)
+{
+struct virtio_gpu_framebuffer fb = { 0 };
+struct virgl_renderer_resource_info info;
+struct virtio_gpu_virgl_resource *res;
+struct virtio_gpu_set_scanout_blob ss;
+uint64_t fbend;
+
+VIRTIO_GPU_FILL_CMD(ss);
+virtio_gpu_scanout_blob_bswap();
+trace_virtio_gpu_cmd_set_scanout_blob(ss.scanout_id, ss.resource_id,
+  ss.r.width, ss.r.height, ss.r.x,
+  ss.r.y);
+
+if (ss.scanout_id >= g->parent_obj.conf.max_outputs) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
+  __func__, ss.scanout_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+return;
+}
+
+if (ss.resource_id == 0) {
+virtio_gpu_disable_scanout(g, ss.scanout_id);
+return;
+}
+
+if (ss.width < 16 ||
+ss.height < 16 ||
+ss.r.x + ss.r.width > ss.width ||
+ss.r.y + ss.r.height > ss.height) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
+  " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
+  __func__, ss.scanout_id, ss.resource_id,
+  ss.r.x, ss.r.y, ss.r.width, ss.r.height,
+  ss.width, ss.height);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, ss.resource_id);
+if (!res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+if (virgl_renderer_resource_get_info(ss.resource_id, )) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not have info %d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+if (res->base.dmabuf_fd < 0) {
+res->base.dmabuf_fd = info.fd;
+}
+if (res->base.dmabuf_fd < 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource not backed by dmabuf 
%d\n",
+  __func__, ss.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+fb.format = virtio_gpu_get_pixman_format(ss.format);
+if (!fb.format) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: pixel format not supported %d\n",
+  __func__, ss.format);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+return;
+}
+
+fb.bytes_pp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(fb.format), 8);
+fb.width = ss.width;
+fb.height = ss.height;
+fb.stride = ss.strides[0];
+fb.offset = ss.offsets[0] + ss.r.x * fb.bytes_pp + ss.r.y * fb.stride;
+
+fbend = fb.offset;
+fbend += fb.stride * (ss.r.height - 1);
+fbend += fb.bytes_pp * ss.r.width;
+if (fbend > res->base.blob_size) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: fb end out of range\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+return;
+}
+
+g->parent_obj.enable 

[PATCH v11 08/10] virtio-gpu: Handle resource blob commands

2024-05-11 Thread Dmitry Osipenko
From: Antonio Caggiano 

Support BLOB resources creation, mapping and unmapping by calling the
new stable virglrenderer 0.10 interface. Only enabled when available and
via the blob config. E.g. -device virtio-vga-gl,blob=true

Signed-off-by: Antonio Caggiano 
Signed-off-by: Xenia Ragiadakou 
Signed-off-by: Huang Rui 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c  | 274 -
 hw/display/virtio-gpu.c|   4 +-
 include/hw/virtio/virtio-gpu.h |   2 +
 3 files changed, 277 insertions(+), 3 deletions(-)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 524f15220b7f..3f2e406be3a4 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -26,6 +26,7 @@
 
 struct virtio_gpu_virgl_resource {
 struct virtio_gpu_simple_resource base;
+MemoryRegion *mr;
 };
 
 static struct virtio_gpu_virgl_resource *
@@ -49,6 +50,117 @@ virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
 }
 #endif
 
+#ifdef HAVE_VIRGL_RESOURCE_BLOB
+struct virtio_gpu_virgl_hostmem_region {
+MemoryRegion mr;
+struct VirtIOGPU *g;
+struct virtio_gpu_virgl_resource *res;
+};
+
+static void virtio_gpu_virgl_resume_cmdq_bh(void *opaque)
+{
+VirtIOGPU *g = opaque;
+
+virtio_gpu_process_cmdq(g);
+}
+
+static void virtio_gpu_virgl_hostmem_region_free(void *obj)
+{
+MemoryRegion *mr = MEMORY_REGION(obj);
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b;
+
+vmr = container_of(mr, struct virtio_gpu_virgl_hostmem_region, mr);
+vmr->res->mr = NULL;
+
+b = VIRTIO_GPU_BASE(vmr->g);
+b->renderer_blocked--;
+
+/*
+ * memory_region_unref() is executed from RCU thread context, while
+ * virglrenderer works only on the main-loop thread that's holding GL
+ * context.
+ */
+qemu_bh_schedule(vmr->g->cmdq_resume_bh);
+g_free(vmr);
+}
+
+static int
+virtio_gpu_virgl_map_resource_blob(VirtIOGPU *g,
+   struct virtio_gpu_virgl_resource *res,
+   uint64_t offset)
+{
+struct virtio_gpu_virgl_hostmem_region *vmr;
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr;
+uint64_t size;
+void *data;
+int ret;
+
+if (!virtio_gpu_hostmem_enabled(b->conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: hostmem disabled\n", __func__);
+return -EOPNOTSUPP;
+}
+
+ret = virgl_renderer_resource_map(res->base.resource_id, , );
+if (ret) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map virgl resource: 
%s\n",
+  __func__, strerror(-ret));
+return ret;
+}
+
+vmr = g_new0(struct virtio_gpu_virgl_hostmem_region, 1);
+vmr->res = res;
+vmr->g = g;
+
+mr = >mr;
+memory_region_init_ram_ptr(mr, OBJECT(mr), "blob", size, data);
+memory_region_add_subregion(>hostmem, offset, mr);
+memory_region_set_enabled(mr, true);
+
+/*
+ * MR could outlive the resource if MR's reference is held outside of
+ * virtio-gpu. In order to prevent unmapping resource while MR is alive,
+ * and thus, making the data pointer invalid, we will block virtio-gpu
+ * command processing until MR is fully unreferenced and freed.
+ */
+OBJECT(mr)->free = virtio_gpu_virgl_hostmem_region_free;
+
+res->mr = mr;
+
+return 0;
+}
+
+static int
+virtio_gpu_virgl_async_unmap_resource_blob(VirtIOGPU *g,
+   struct virtio_gpu_virgl_resource 
*res)
+{
+VirtIOGPUBase *b = VIRTIO_GPU_BASE(g);
+MemoryRegion *mr = res->mr;
+int ret;
+
+if (mr) {
+/* render will be unblocked once MR is freed */
+b->renderer_blocked++;
+
+/* memory region owns self res->mr object and frees it by itself */
+memory_region_set_enabled(mr, false);
+memory_region_del_subregion(>hostmem, mr);
+object_unparent(OBJECT(mr));
+} else {
+ret = virgl_renderer_resource_unmap(res->base.resource_id);
+if (ret) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: failed to unmap virgl resource: %s\n",
+  __func__, strerror(-ret));
+return ret;
+}
+}
+
+return 0;
+}
+#endif /* HAVE_VIRGL_RESOURCE_BLOB */
+
 static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
  struct virtio_gpu_ctrl_command *cmd)
 {
@@ -146,7 +258,8 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 }
 
 static void virgl_cmd_resource_unref(VirtIOGPU *g,
- struct virtio_gpu_ctrl_command *cmd)
+ struct virtio_gpu_ctrl_command *cmd,
+ bool *cmd_suspended)
 {
 struct virtio_gpu_resource_unref unref;
 struct virtio_gpu_virgl_resource *res;
@@ -164,6 +277,12 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
 return;
 }

[PATCH v11 07/10] virtio-gpu: Support suspension of commands processing

2024-05-11 Thread Dmitry Osipenko
Check whether command processing has been finished; otherwise, stop
processing commands and retry the command again next time. This allows
us to support asynchronous execution of non-fenced commands needed for
unmapping host blobs safely.

Suggested-by: Akihiko Odaki 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 1e57a53d346c..6c8c7213bafa 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1054,6 +1054,11 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g)
 /* process command */
 vgc->process_cmd(g, cmd);
 
+/* command suspended */
+if (!cmd->finished && !(cmd->cmd_hdr.flags & VIRTIO_GPU_FLAG_FENCE)) {
+break;
+}
+
 QTAILQ_REMOVE(>cmdq, cmd, next);
 if (virtio_gpu_stats_enabled(g->parent_obj.conf)) {
 g->stats.requests++;
-- 
2.44.0




[PATCH v11 10/10] virtio-gpu: Support Venus context

2024-05-11 Thread Dmitry Osipenko
From: Antonio Caggiano 

Request Venus when initializing VirGL and if venus=true flag is set for
virtio-gpu-gl device.

Signed-off-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |  2 ++
 hw/display/virtio-gpu-virgl.c  | 22 ++
 hw/display/virtio-gpu.c| 13 +
 include/hw/virtio/virtio-gpu.h |  3 +++
 meson.build|  1 +
 5 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 431fc2881a00..1deb3e64b781 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -137,6 +137,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_BIT("stats", VirtIOGPU, parent_obj.conf.flags,
 VIRTIO_GPU_FLAG_STATS_ENABLED, false),
+DEFINE_PROP_BIT("venus", VirtIOGPU, parent_obj.conf.flags,
+VIRTIO_GPU_FLAG_VENUS_ENABLED, false),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 135974431492..f1cad005dd8f 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -1094,6 +1094,11 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 flags |= VIRGL_RENDERER_D3D11_SHARE_TEXTURE;
 }
 #endif
+#ifdef VIRGL_RENDERER_VENUS
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+flags |= VIRGL_RENDERER_VENUS | VIRGL_RENDERER_RENDER_SERVER;
+}
+#endif
 
 ret = virgl_renderer_init(g, flags, _gpu_3d_cbs);
 if (ret != 0) {
@@ -1124,7 +1129,7 @@ static void virtio_gpu_virgl_add_capset(GArray 
*capset_ids, uint32_t capset_id)
 
 GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
-uint32_t capset2_max_ver, capset2_max_size;
+uint32_t capset_max_ver, capset_max_size;
 GArray *capset_ids;
 
 capset_ids = g_array_new(false, false, sizeof(uint32_t));
@@ -1133,12 +1138,21 @@ GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
 
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
-  _max_ver,
-  _max_size);
-if (capset2_max_ver) {
+   _max_ver,
+   _max_size);
+if (capset_max_ver) {
 virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VENUS,
+   _max_ver,
+   _max_size);
+if (capset_max_size) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VENUS);
+}
+}
+
 return capset_ids;
 }
 
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 052ab493a00b..0518bb858e88 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1491,6 +1491,19 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error 
**errp)
 #endif
 }
 
+if (virtio_gpu_venus_enabled(g->parent_obj.conf)) {
+#ifdef HAVE_VIRGL_VENUS
+if (!virtio_gpu_blob_enabled(g->parent_obj.conf) ||
+!virtio_gpu_hostmem_enabled(g->parent_obj.conf)) {
+error_setg(errp, "venus requires enabled blob and hostmem 
options");
+return;
+}
+#else
+error_setg(errp, "old virglrenderer, venus unsupported");
+return;
+#endif
+}
+
 if (!virtio_gpu_base_device_realize(qdev,
 virtio_gpu_handle_ctrl_cb,
 virtio_gpu_handle_cursor_cb,
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 7bbc6ef268eb..9940bbcbaacc 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -99,6 +99,7 @@ enum virtio_gpu_base_conf_flags {
 VIRTIO_GPU_FLAG_BLOB_ENABLED,
 VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED,
 VIRTIO_GPU_FLAG_RUTABAGA_ENABLED,
+VIRTIO_GPU_FLAG_VENUS_ENABLED,
 };
 
 #define virtio_gpu_virgl_enabled(_cfg) \
@@ -117,6 +118,8 @@ enum virtio_gpu_base_conf_flags {
 (_cfg.flags & (1 << VIRTIO_GPU_FLAG_RUTABAGA_ENABLED))
 #define virtio_gpu_hostmem_enabled(_cfg) \
 (_cfg.hostmem > 0)
+#define virtio_gpu_venus_enabled(_cfg) \
+(_cfg.flags & (1 << VIRTIO_GPU_FLAG_VENUS_ENABLED))
 
 struct virtio_gpu_base_conf {
 uint32_t max_outputs;
diff --git a/meson.build b/meson.build
index 0433ea200dd7..20241931730f 100644
--- a/meson.build
+++ b/meson.build
@@ -2290,6 +2290,7 @@ if virgl.version().version_compare('>=1.0.0')
   config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT', 1)
   config_host_data.set('HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS', 1)
   config_host_data.set('HAVE_VIRGL_RESOURCE_BLOB', 1)
+  config_host_data.set('HAVE_VIRGL_VENUS', 1)
 endif
 

[PATCH v11 05/10] virtio-gpu: Add virgl resource management

2024-05-11 Thread Dmitry Osipenko
From: Huang Rui 

In a preparation to adding host blobs support to virtio-gpu, add virgl
resource management that allows to retrieve resource based on its ID
and virgl resource wrapper on top of simple resource that will be contain
fields specific to virgl.

Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-virgl.c | 76 +++
 1 file changed, 76 insertions(+)

diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 8306961ad502..c6c63ca1c373 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -22,6 +22,23 @@
 
 #include 
 
+struct virtio_gpu_virgl_resource {
+struct virtio_gpu_simple_resource base;
+};
+
+static struct virtio_gpu_virgl_resource *
+virtio_gpu_virgl_find_resource(VirtIOGPU *g, uint32_t resource_id)
+{
+struct virtio_gpu_simple_resource *res;
+
+res = virtio_gpu_find_resource(g, resource_id);
+if (!res) {
+return NULL;
+}
+
+return container_of(res, struct virtio_gpu_virgl_resource, base);
+}
+
 #if VIRGL_RENDERER_CALLBACKS_VERSION >= 4
 static void *
 virgl_get_egl_display(G_GNUC_UNUSED void *cookie)
@@ -35,11 +52,34 @@ static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_2d c2d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c2d);
 trace_virtio_gpu_cmd_res_create_2d(c2d.resource_id, c2d.format,
c2d.width, c2d.height);
 
+if (c2d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c2d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c2d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c2d.width;
+res->base.height = c2d.height;
+res->base.format = c2d.format;
+res->base.resource_id = c2d.resource_id;
+QTAILQ_INSERT_HEAD(>reslist, >base, next);
+
 args.handle = c2d.resource_id;
 args.target = 2;
 args.format = c2d.format;
@@ -59,11 +99,34 @@ static void virgl_cmd_create_resource_3d(VirtIOGPU *g,
 {
 struct virtio_gpu_resource_create_3d c3d;
 struct virgl_renderer_resource_create_args args;
+struct virtio_gpu_virgl_resource *res;
 
 VIRTIO_GPU_FILL_CMD(c3d);
 trace_virtio_gpu_cmd_res_create_3d(c3d.resource_id, c3d.format,
c3d.width, c3d.height, c3d.depth);
 
+if (c3d.resource_id == 0) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = virtio_gpu_virgl_find_resource(g, c3d.resource_id);
+if (res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+  __func__, c3d.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
+res = g_new0(struct virtio_gpu_virgl_resource, 1);
+res->base.width = c3d.width;
+res->base.height = c3d.height;
+res->base.format = c3d.format;
+res->base.resource_id = c3d.resource_id;
+QTAILQ_INSERT_HEAD(>reslist, >base, next);
+
 args.handle = c3d.resource_id;
 args.target = c3d.target;
 args.format = c3d.format;
@@ -82,12 +145,21 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
  struct virtio_gpu_ctrl_command *cmd)
 {
 struct virtio_gpu_resource_unref unref;
+struct virtio_gpu_virgl_resource *res;
 struct iovec *res_iovs = NULL;
 int num_iovs = 0;
 
 VIRTIO_GPU_FILL_CMD(unref);
 trace_virtio_gpu_cmd_res_unref(unref.resource_id);
 
+res = virtio_gpu_virgl_find_resource(g, unref.resource_id);
+if (!res) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: resource does not exist %d\n",
+  __func__, unref.resource_id);
+cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+return;
+}
+
 virgl_renderer_resource_detach_iov(unref.resource_id,
_iovs,
_iovs);
@@ -95,6 +167,10 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g,
 virtio_gpu_cleanup_mapping_iov(g, res_iovs, num_iovs);
 }
 virgl_renderer_resource_unref(unref.resource_id);
+
+QTAILQ_REMOVE(>reslist, >base, next);
+
+g_free(res);
 }
 
 static void virgl_cmd_context_create(VirtIOGPU *g,
-- 
2.44.0




[PATCH v11 03/10] virtio-gpu: Support context-init feature with virglrenderer

2024-05-11 Thread Dmitry Osipenko
From: Huang Rui 

Patch "virtio-gpu: CONTEXT_INIT feature" has added the context_init
feature flags. Expose this feature and support creating virglrenderer
context with flags using context_id if libvirglrenderer is new enough.

Originally-by: Antonio Caggiano 
Signed-off-by: Huang Rui 
Reviewed-by: Antonio Caggiano 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c|  4 
 hw/display/virtio-gpu-virgl.c | 20 ++--
 meson.build   |  1 +
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 0c0a8d136954..95806999189e 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -127,6 +127,10 @@ static void virtio_gpu_gl_device_realize(DeviceState 
*qdev, Error **errp)
 VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
 virtio_gpu_virgl_get_num_capsets(g);
 
+#ifdef HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS
+g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
+#endif
+
 virtio_gpu_device_realize(qdev, errp);
 }
 
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index b0500eccf8e0..8306961ad502 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -106,8 +106,24 @@ static void virgl_cmd_context_create(VirtIOGPU *g,
 trace_virtio_gpu_cmd_ctx_create(cc.hdr.ctx_id,
 cc.debug_name);
 
-virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen,
-  cc.debug_name);
+if (cc.context_init) {
+if (!virtio_gpu_context_init_enabled(g->parent_obj.conf)) {
+qemu_log_mask(LOG_GUEST_ERROR, "%s: context_init disabled",
+  __func__);
+cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+return;
+}
+
+#ifdef HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS
+virgl_renderer_context_create_with_flags(cc.hdr.ctx_id,
+ cc.context_init,
+ cc.nlen,
+ cc.debug_name);
+return;
+#endif
+}
+
+virgl_renderer_context_create(cc.hdr.ctx_id, cc.nlen, cc.debug_name);
 }
 
 static void virgl_cmd_context_destroy(VirtIOGPU *g,
diff --git a/meson.build b/meson.build
index ca2798dbac37..5448eb17f39b 100644
--- a/meson.build
+++ b/meson.build
@@ -2288,6 +2288,7 @@ config_host_data.set('CONFIG_VNC_JPEG', jpeg.found())
 config_host_data.set('CONFIG_VNC_SASL', sasl.found())
 if virgl.version().version_compare('>=1.0.0')
   config_host_data.set('HAVE_VIRGL_D3D_INFO_EXT', 1)
+  config_host_data.set('HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS', 1)
 endif
 config_host_data.set('CONFIG_VIRTFS', have_virtfs)
 config_host_data.set('CONFIG_VTE', vte.found())
-- 
2.44.0




[PATCH v11 09/10] virtio-gpu: Register capsets dynamically

2024-05-11 Thread Dmitry Osipenko
From: Pierre-Eric Pelloux-Prayer 

virtio_gpu_virgl_get_num_capsets will return "num_capsets", but we can't
assume that capset_index 1 is always VIRGL2 once we'll support more capsets,
like Venus and DRM capsets. Register capsets dynamically to avoid that problem.

Signed-off-by: Pierre-Eric Pelloux-Prayer 
Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c |  6 --
 hw/display/virtio-gpu-virgl.c  | 33 +
 include/hw/virtio/virtio-gpu.h |  4 +++-
 3 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index 95806999189e..431fc2881a00 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -124,8 +124,8 @@ static void virtio_gpu_gl_device_realize(DeviceState *qdev, 
Error **errp)
 }
 
 g->parent_obj.conf.flags |= (1 << VIRTIO_GPU_FLAG_VIRGL_ENABLED);
-VIRTIO_GPU_BASE(g)->virtio_config.num_capsets =
-virtio_gpu_virgl_get_num_capsets(g);
+g->capset_ids = virtio_gpu_virgl_get_capsets(g);
+VIRTIO_GPU_BASE(g)->virtio_config.num_capsets = g->capset_ids->len;
 
 #ifdef HAVE_VIRGL_CONTEXT_CREATE_WITH_FLAGS
 g->parent_obj.conf.flags |= 1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED;
@@ -148,6 +148,8 @@ static void virtio_gpu_gl_device_unrealize(DeviceState 
*qdev)
 if (gl->renderer_inited) {
 virtio_gpu_virgl_deinit(g);
 }
+
+g_array_unref(g->capset_ids);
 }
 
 static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 3f2e406be3a4..135974431492 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -590,19 +590,13 @@ static void virgl_cmd_get_capset_info(VirtIOGPU *g,
 VIRTIO_GPU_FILL_CMD(info);
 
 memset(, 0, sizeof(resp));
-if (info.capset_index == 0) {
-resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL;
-virgl_renderer_get_cap_set(resp.capset_id,
-   _max_version,
-   _max_size);
-} else if (info.capset_index == 1) {
-resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL2;
+
+if (info.capset_index < g->capset_ids->len) {
+resp.capset_id = g_array_index(g->capset_ids, uint32_t,
+   info.capset_index);
 virgl_renderer_get_cap_set(resp.capset_id,
_max_version,
_max_size);
-} else {
-resp.capset_max_version = 0;
-resp.capset_max_size = 0;
 }
 resp.hdr.type = VIRTIO_GPU_RESP_OK_CAPSET_INFO;
 virtio_gpu_ctrl_response(g, cmd, , sizeof(resp));
@@ -1123,14 +1117,29 @@ int virtio_gpu_virgl_init(VirtIOGPU *g)
 return 0;
 }
 
-int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
+static void virtio_gpu_virgl_add_capset(GArray *capset_ids, uint32_t capset_id)
+{
+g_array_append_val(capset_ids, capset_id);
+}
+
+GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g)
 {
 uint32_t capset2_max_ver, capset2_max_size;
+GArray *capset_ids;
+
+capset_ids = g_array_new(false, false, sizeof(uint32_t));
+
+/* VIRGL is always supported. */
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL);
+
 virgl_renderer_get_cap_set(VIRTIO_GPU_CAPSET_VIRGL2,
   _max_ver,
   _max_size);
+if (capset2_max_ver) {
+virtio_gpu_virgl_add_capset(capset_ids, VIRTIO_GPU_CAPSET_VIRGL2);
+}
 
-return capset2_max_ver ? 2 : 1;
+return capset_ids;
 }
 
 void virtio_gpu_virgl_deinit(VirtIOGPU *g)
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index c0b0b0eac08b..7bbc6ef268eb 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -212,6 +212,8 @@ struct VirtIOGPU {
 } dmabuf;
 
 QEMUBH *cmdq_resume_bh;
+
+GArray *capset_ids;
 };
 
 struct VirtIOGPUClass {
@@ -346,6 +348,6 @@ void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
 void virtio_gpu_virgl_reset(VirtIOGPU *g);
 int virtio_gpu_virgl_init(VirtIOGPU *g);
 void virtio_gpu_virgl_deinit(VirtIOGPU *g);
-int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
+GArray *virtio_gpu_virgl_get_capsets(VirtIOGPU *g);
 
 #endif
-- 
2.44.0




[PATCH v11 01/10] virtio-gpu: Unrealize GL device

2024-05-11 Thread Dmitry Osipenko
Even though GL GPU doesn't support hotplugging today, free virgl
resources when GL device is unrealized. For consistency.

Signed-off-by: Dmitry Osipenko 
---
 hw/display/virtio-gpu-gl.c | 11 +++
 hw/display/virtio-gpu-virgl.c  |  9 +
 include/hw/virtio/virtio-gpu.h |  1 +
 3 files changed, 21 insertions(+)

diff --git a/hw/display/virtio-gpu-gl.c b/hw/display/virtio-gpu-gl.c
index e06be60dfbfc..0c0a8d136954 100644
--- a/hw/display/virtio-gpu-gl.c
+++ b/hw/display/virtio-gpu-gl.c
@@ -136,6 +136,16 @@ static Property virtio_gpu_gl_properties[] = {
 DEFINE_PROP_END_OF_LIST(),
 };
 
+static void virtio_gpu_gl_device_unrealize(DeviceState *qdev)
+{
+VirtIOGPU *g = VIRTIO_GPU(qdev);
+VirtIOGPUGL *gl = VIRTIO_GPU_GL(qdev);
+
+if (gl->renderer_inited) {
+virtio_gpu_virgl_deinit(g);
+}
+}
+
 static void virtio_gpu_gl_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
@@ -149,6 +159,7 @@ static void virtio_gpu_gl_class_init(ObjectClass *klass, 
void *data)
 vgc->update_cursor_data = virtio_gpu_gl_update_cursor_data;
 
 vdc->realize = virtio_gpu_gl_device_realize;
+vdc->unrealize = virtio_gpu_gl_device_unrealize;
 vdc->reset = virtio_gpu_gl_reset;
 device_class_set_props(dc, virtio_gpu_gl_properties);
 }
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 9f34d0e6619c..b0500eccf8e0 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -665,3 +665,12 @@ int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g)
 
 return capset2_max_ver ? 2 : 1;
 }
+
+void virtio_gpu_virgl_deinit(VirtIOGPU *g)
+{
+if (g->fence_poll) {
+timer_free(g->fence_poll);
+}
+
+virgl_renderer_cleanup(NULL);
+}
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index ed44cdad6b34..b657187159d9 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -336,6 +336,7 @@ void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
 void virtio_gpu_virgl_reset_scanout(VirtIOGPU *g);
 void virtio_gpu_virgl_reset(VirtIOGPU *g);
 int virtio_gpu_virgl_init(VirtIOGPU *g);
+void virtio_gpu_virgl_deinit(VirtIOGPU *g);
 int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g);
 
 #endif
-- 
2.44.0




Re: [PATCH RESEND] target/riscv/cpu.c: fix Zvkb extension config

2024-05-11 Thread Yangyu Chen
Note: This patch should also backport to stable-v8.2.

> On May 11, 2024, at 19:26, Yangyu Chen  wrote:
> 
> This code has a typo that writes zvkb to zvkg, causing users can't
> enable zvkb through the config. This patch gets this fixed.
> 
> Signed-off-by: Yangyu Chen 
> Fixes: ea61ef7097d0 ("target/riscv: Move vector crypto extensions to 
> riscv_cpu_extensions")
> Reviewed-by: LIU Zhiwei 
> ---
> target/riscv/cpu.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index eb1a2e7d6d..13cd34adbd 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1535,7 +1535,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
> /* Vector cryptography extensions */
> MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
> MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
> -MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
> +MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
> MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
> MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
> MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),
> -- 
> 2.43.0
> 




Re: [PATCH RESEND] target/riscv/cpu.c: fix Zvkb extension config

2024-05-11 Thread Max Chou

Reviewed-by: Max Chou 

Max

On 2024/5/11 7:26 PM, Yangyu Chen wrote:

This code has a typo that writes zvkb to zvkg, causing users can't
enable zvkb through the config. This patch gets this fixed.

Signed-off-by: Yangyu Chen 
Fixes: ea61ef7097d0 ("target/riscv: Move vector crypto extensions to 
riscv_cpu_extensions")
Reviewed-by: LIU Zhiwei 
---
  target/riscv/cpu.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index eb1a2e7d6d..13cd34adbd 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1535,7 +1535,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
  /* Vector cryptography extensions */
  MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
  MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
-MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
+MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
  MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
  MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
  MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),




Re: [PATCH 3/5] target/riscv: Add 'P1P13' bit in SMSTATEEN0

2024-05-11 Thread liwei



On 2024/5/10 14:58, Fea.Wang wrote:

Based on privilege 1.13 spec, there should be a bit56 for 'P1P13' in
SMSTATEEN0 that controls access to the hedeleg.

Signed-off-by: Fea.Wang 
Reviewed-by: Frank Chang 
---
  target/riscv/cpu_bits.h |  1 +
  target/riscv/csr.c  | 10 ++
  2 files changed, 11 insertions(+)

Reviewed-by:  Weiwei Li 

Weiwei Li


diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 74318a925c..28bd3fb0b4 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -315,6 +315,7 @@
  #define SMSTATEEN0_CS   (1ULL << 0)
  #define SMSTATEEN0_FCSR (1ULL << 1)
  #define SMSTATEEN0_JVT  (1ULL << 2)
+#define SMSTATEEN0_P1P13(1ULL << 56)
  #define SMSTATEEN0_HSCONTXT (1ULL << 57)
  #define SMSTATEEN0_IMSIC(1ULL << 58)
  #define SMSTATEEN0_AIA  (1ULL << 59)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 6b460ee0e8..d844ce770e 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2248,6 +2248,11 @@ static RISCVException write_mstateen0(CPURISCVState 
*env, int csrno,
  wr_mask |= SMSTATEEN0_FCSR;
  }
  
+RISCVCPU *cpu = env_archcpu(env);

+if (cpu->env.priv_ver >= PRIV_VERSION_1_13_0) {
+wr_mask |= SMSTATEEN0_P1P13;
+}
+
  return write_mstateen(env, csrno, wr_mask, new_val);
  }
  
@@ -2283,6 +2288,11 @@ static RISCVException write_mstateen0h(CPURISCVState *env, int csrno,

  {
  uint64_t wr_mask = SMSTATEEN_STATEEN | SMSTATEEN0_HSENVCFG;
  
+RISCVCPU *cpu = env_archcpu(env);

+if (cpu->env.priv_ver >= PRIV_VERSION_1_13_0) {
+wr_mask |= SMSTATEEN0_P1P13;
+}
+
  return write_mstateenh(env, csrno, wr_mask, new_val);
  }
  




Re: [PATCH 2/5] target/riscv: Support the version for ss1p13

2024-05-11 Thread liwei



On 2024/5/10 14:58, Fea.Wang wrote:

Add RISC-V privilege 1.13 support.

Signed-off-by: Fea.Wang 
Reviewed-by: Frank Chang 
---
  target/riscv/cpu.c | 6 +-
  target/riscv/cpu.h | 4 +++-
  target/riscv/cpu_cfg.h | 1 +
  target/riscv/tcg/tcg-cpu.c | 4 
  4 files changed, 13 insertions(+), 2 deletions(-)

Reviewed-by:  Weiwei Li 

Weiwei Li


diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index b6b48e5620..a6298c3298 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1773,7 +1773,9 @@ int priv_spec_from_str(const char *priv_spec_str)
  {
  int priv_version = -1;
  
-if (!g_strcmp0(priv_spec_str, PRIV_VER_1_12_0_STR)) {

+if (!g_strcmp0(priv_spec_str, PRIV_VER_1_13_0_STR)) {
+priv_version = PRIV_VERSION_1_13_0;
+} else if (!g_strcmp0(priv_spec_str, PRIV_VER_1_12_0_STR)) {
  priv_version = PRIV_VERSION_1_12_0;
  } else if (!g_strcmp0(priv_spec_str, PRIV_VER_1_11_0_STR)) {
  priv_version = PRIV_VERSION_1_11_0;
@@ -1793,6 +1795,8 @@ const char *priv_spec_to_str(int priv_version)
  return PRIV_VER_1_11_0_STR;
  case PRIV_VERSION_1_12_0:
  return PRIV_VER_1_12_0_STR;
+case PRIV_VERSION_1_13_0:
+return PRIV_VER_1_13_0_STR;
  default:
  return NULL;
  }
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 7696102697..776939b56b 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -96,12 +96,14 @@ extern RISCVCPUProfile *riscv_profiles[];
  #define PRIV_VER_1_10_0_STR "v1.10.0"
  #define PRIV_VER_1_11_0_STR "v1.11.0"
  #define PRIV_VER_1_12_0_STR "v1.12.0"
+#define PRIV_VER_1_13_0_STR "v1.13.0"
  enum {
  PRIV_VERSION_1_10_0 = 0,
  PRIV_VERSION_1_11_0,
  PRIV_VERSION_1_12_0,
+PRIV_VERSION_1_13_0,
  
-PRIV_VERSION_LATEST = PRIV_VERSION_1_12_0,

+PRIV_VERSION_LATEST = PRIV_VERSION_1_13_0,
  };
  
  #define VEXT_VERSION_1_00_0 0x0001

diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index e1e4f32698..fb7eebde52 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -136,6 +136,7 @@ struct RISCVCPUConfig {
   * TCG always implement/can't be user disabled,
   * based on spec version.
   */
+bool has_priv_1_13;
  bool has_priv_1_12;
  bool has_priv_1_11;
  
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c

index faa8de9b83..a9d188a9fd 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -320,6 +320,10 @@ static void riscv_cpu_update_named_features(RISCVCPU *cpu)
  cpu->cfg.has_priv_1_12 = true;
  }
  
+if (cpu->env.priv_ver >= PRIV_VERSION_1_13_0) {

+cpu->cfg.has_priv_1_13 = true;
+}
+
  /* zic64b is 1.12 or later */
  cpu->cfg.ext_zic64b = cpu->cfg.cbom_blocksize == 64 &&
cpu->cfg.cbop_blocksize == 64 &&




Re: [PATCH v9 2/6] target/riscv: Add new CSR fields for S{sn, mn, m}pm extensions as part of Zjpm v0.8

2024-05-11 Thread liwei



On 2024/5/11 18:10, Alexey Baturo wrote:

From: Alexey Baturo 

Signed-off-by: Alexey Baturo 

Reviewed-by: Alistair Francis 
---
  target/riscv/cpu.h  |  8 
  target/riscv/cpu_bits.h |  3 +++
  target/riscv/cpu_cfg.h  |  3 +++
  target/riscv/csr.c  | 11 +++
  target/riscv/machine.c  | 10 +++---
  target/riscv/pmp.c  | 13 ++---
  target/riscv/pmp.h  | 11 ++-
  7 files changed, 48 insertions(+), 11 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 232521bb87..52b6ba73c8 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -121,6 +121,14 @@ typedef enum {
  EXT_STATUS_DIRTY,
  } RISCVExtStatus;
  
+/* Enum holds PMM field values for Zjpm v0.8 extension */

+typedef enum {
+PMM_FIELD_DISABLED = 0,
+PMM_FIELD_RESERVED = 1,
+PMM_FIELD_PMLEN7   = 2,
+PMM_FIELD_PMLEN16  = 3,
+} RISCVPmPmm;
+
  #define MMU_USER_IDX 3
  
  #define MAX_RISCV_PMPS (16)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index da16ba236a..13ce2218d1 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -708,6 +708,7 @@ typedef enum RISCVException {
  #define MENVCFG_CBIE   (3UL << 4)
  #define MENVCFG_CBCFE  BIT(6)
  #define MENVCFG_CBZE   BIT(7)
+#define MENVCFG_PMM(3ULL << 32)
  #define MENVCFG_ADUE   (1ULL << 61)
  #define MENVCFG_PBMTE  (1ULL << 62)
  #define MENVCFG_STCE   (1ULL << 63)
@@ -721,11 +722,13 @@ typedef enum RISCVException {
  #define SENVCFG_CBIE   MENVCFG_CBIE
  #define SENVCFG_CBCFE  MENVCFG_CBCFE
  #define SENVCFG_CBZE   MENVCFG_CBZE
+#define SENVCFG_PMMMENVCFG_PMM
  
  #define HENVCFG_FIOM   MENVCFG_FIOM

  #define HENVCFG_CBIE   MENVCFG_CBIE
  #define HENVCFG_CBCFE  MENVCFG_CBCFE
  #define HENVCFG_CBZE   MENVCFG_CBZE
+#define HENVCFG_PMMMENVCFG_PMM
  #define HENVCFG_ADUE   MENVCFG_ADUE
  #define HENVCFG_PBMTE  MENVCFG_PBMTE
  #define HENVCFG_STCE   MENVCFG_STCE
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index e1e4f32698..9ecdc792c5 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -120,6 +120,9 @@ struct RISCVCPUConfig {
  bool ext_ssaia;
  bool ext_sscofpmf;
  bool ext_smepmp;
+bool ext_ssnpm;
+bool ext_smnpm;
+bool ext_smmpm;
  bool rvv_ta_all_1s;
  bool rvv_ma_all_1s;
  
diff --git a/target/riscv/csr.c b/target/riscv/csr.c

index 4b2c932564..45b548eb0b 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -530,6 +530,9 @@ static RISCVException have_mseccfg(CPURISCVState *env, int 
csrno)
  if (riscv_cpu_cfg(env)->ext_zkr) {
  return RISCV_EXCP_NONE;
  }
+if (riscv_cpu_cfg(env)->ext_smmpm) {
+return RISCV_EXCP_NONE;
+}
  
  return RISCV_EXCP_ILLEGAL_INST;

  }
@@ -2083,6 +2086,10 @@ static RISCVException write_menvcfg(CPURISCVState *env, 
int csrno,
  (cfg->ext_sstc ? MENVCFG_STCE : 0) |
  (cfg->ext_svadu ? MENVCFG_ADUE : 0);
  }
+/* Update PMM field only if the value is valid according to Zjpm v0.8 */
+if (((val & MENVCFG_PMM) >> 32) != PMM_FIELD_RESERVED) {
+mask |= MENVCFG_PMM;
+}


Extension and RV64 check seems missed here.This field is added by smnpm, 
So I think it's can only be changed only when smnpm is enabled.



  env->menvcfg = (env->menvcfg & ~mask) | (val & mask);
  
  return RISCV_EXCP_NONE;

@@ -2127,6 +2134,10 @@ static RISCVException write_senvcfg(CPURISCVState *env, 
int csrno,
  target_ulong val)
  {
  uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE | 
SENVCFG_CBZE;
+/* Update PMM field only if the value is valid according to Zjpm v0.8 */
+if (((val & SENVCFG_PMM) >> 32) != PMM_FIELD_RESERVED) {
+mask |= SENVCFG_PMM;
+}
  RISCVException ret

similar to above.

;
  
  ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);

diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 64ab66e332..28f373 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -152,15 +152,19 @@ static const VMStateDescription vmstate_vector = {
  
  static bool pointermasking_needed(void *opaque)

  {
-return false;
+RISCVCPU *cpu = opaque;
+return cpu->cfg.ext_ssnpm || cpu->cfg.ext_smnpm || cpu->cfg.ext_smmpm;
  }
  
  static const VMStateDescription vmstate_pointermasking = {

  .name = "cpu/pointer_masking",
-.version_id = 1,
-.minimum_version_id = 1,
+.version_id = 2,
+.minimum_version_id = 2,
  .needed = pointermasking_needed,
  .fields = (const VMStateField[]) {
+

Re: [PATCH v9 0/6] Pointer Masking update for Zjpm v1.0

2024-05-11 Thread liwei



On 2024/5/11 18:10, Alexey Baturo wrote:

From: Alexey Baturo 

Hi,

It looks like Pointer Masking spec has reached v1.0 and been frozen,
rebasing on riscv-to-apply.next branch and resubmitting patches.


Hi, any change from v0.8 to v1.0?

Regards,

Weiwei Li



Thanks.

[v8]:
Rebasing patches on current qemu branch and resubmitting them.


[v7]:
I'm terribly sorry, but previous rebase went wrong and somehow I missed it.
This time I double-checked rebased version.
This patch series is properly rebased on 
https://github.com/alistair23/qemu/tree/riscv-to-apply.next

[v6]:
This patch series is rebased on 
https://github.com/alistair23/qemu/tree/riscv-to-apply.next

[v5]:
This patch series targets Zjpm v0.8 extension.
The spec itself could be found here: 
https://github.com/riscv/riscv-j-extension/blob/8088461d8d66a7676872b61c908cbeb7cf5c5d1d/zjpm-spec.pdf
This patch series is updated after the suggested comments:
- add "x-" to the extension names to indicate experimental

[v4]:
Patch series updated after the suggested comments:
- removed J-letter extension as it's unused
- renamed and fixed function to detect if address should be sign-extended
- zeroed unused context variables and moved computation logic to another patch
- bumped pointer masking version_id and minimum_version_id by 1

[v3]:
There patches are updated after Richard's comments:
- moved new tb flags to the end
- used tcg_gen_(s)extract to get the final address
- properly handle CONFIG_USER_ONLY

[v2]:
As per Richard's suggestion I made pmm field part of tb_flags.
It allowed to get rid of global variable to store pmlen.
Also it allowed to simplify all the machinery around it.

[v1]:
It looks like Zjpm v0.8 is almost frozen and we don't expect it change 
drastically anymore.
Compared to the original implementation with explicit base and mask CSRs, we 
now only have
several fixed options for number of masked bits which are set using existing 
CSRs.
The changes have been tested with handwritten assembly tests and LLVM HWASAN
test suite.

Alexey Baturo (6):
   target/riscv: Remove obsolete pointer masking  extension code.
   target/riscv: Add new CSR fields for S{sn,mn,m}pm extensions as part
 of Zjpm v0.8
   target/riscv: Add helper functions to calculate current number of
 masked bits for pointer masking
   target/riscv: Add pointer masking tb flags
   target/riscv: Update address modify functions to take into account
 pointer masking
   target/riscv: Enable updates for pointer masking variables and thus
 enable pointer masking extension

  target/riscv/cpu.c   |  21 +--
  target/riscv/cpu.h   |  46 +++--
  target/riscv/cpu_bits.h  |  90 +-
  target/riscv/cpu_cfg.h   |   3 +
  target/riscv/cpu_helper.c|  97 +-
  target/riscv/csr.c   | 337 ++-
  target/riscv/machine.c   |  20 +--
  target/riscv/pmp.c   |  13 +-
  target/riscv/pmp.h   |  11 +-
  target/riscv/tcg/tcg-cpu.c   |   5 +-
  target/riscv/translate.c |  46 ++---
  target/riscv/vector_helper.c |  15 +-
  12 files changed, 158 insertions(+), 546 deletions(-)





Re: [PATCH RESEND] target/riscv/cpu.c: fix Zvkb extension config

2024-05-11 Thread liwei



On 2024/5/11 19:26, Yangyu Chen wrote:

This code has a typo that writes zvkb to zvkg, causing users can't
enable zvkb through the config. This patch gets this fixed.

Signed-off-by: Yangyu Chen 
Fixes: ea61ef7097d0 ("target/riscv: Move vector crypto extensions to 
riscv_cpu_extensions")
Reviewed-by: LIU Zhiwei 
---
  target/riscv/cpu.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)


Reviewed-by:  Weiwei Li 

Weiwei Li



diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index eb1a2e7d6d..13cd34adbd 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1535,7 +1535,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
  /* Vector cryptography extensions */
  MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
  MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
-MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
+MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
  MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
  MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
  MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),




Re: [PATCH 1/5] target/riscv: Reuse the conversion function of priv_spec and string

2024-05-11 Thread liwei



On 2024/5/10 14:58, Fea.Wang wrote:

From: Jim Shu 

Public the conversion function of priv_spec and string in cpu.h, so that
tcg-cpu.c could also use it.

Signed-off-by: Jim Shu 
Signed-off-by: Fea.Wang 
Reviewed-by: Frank Chang 
---
  target/riscv/cpu.c |  4 ++--
  target/riscv/cpu.h |  3 +++
  target/riscv/tcg/tcg-cpu.c | 13 +
  3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a74f0eb29c..b6b48e5620 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1769,7 +1769,7 @@ static const PropertyInfo prop_pmp = {
  .set = prop_pmp_set,
  };
  
-static int priv_spec_from_str(const char *priv_spec_str)

+int priv_spec_from_str(const char *priv_spec_str)


This change seems unnecessary in this patch.

Regards,

Weiwei Li


  {
  int priv_version = -1;
  
@@ -1784,7 +1784,7 @@ static int priv_spec_from_str(const char *priv_spec_str)

  return priv_version;
  }
  
-static const char *priv_spec_to_str(int priv_version)

+const char *priv_spec_to_str(int priv_version)
  {
  switch (priv_version) {
  case PRIV_VERSION_1_10_0:
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index e0dd1828b5..7696102697 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -829,4 +829,7 @@ target_ulong riscv_new_csr_seed(target_ulong new_value,
  uint8_t satp_mode_max_from_map(uint32_t map);
  const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
  
+const char *priv_spec_to_str(int priv_version);

+int priv_spec_from_str(const char *priv_spec_str);
+
  #endif /* RISCV_CPU_H */
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 4ebebebe09..faa8de9b83 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -76,16 +76,13 @@ static void riscv_cpu_write_misa_bit(RISCVCPU *cpu, 
uint32_t bit,
  
  static const char *cpu_priv_ver_to_str(int priv_ver)

  {
-switch (priv_ver) {
-case PRIV_VERSION_1_10_0:
-return "v1.10.0";
-case PRIV_VERSION_1_11_0:
-return "v1.11.0";
-case PRIV_VERSION_1_12_0:
-return "v1.12.0";
+const char *priv_spec_str = priv_spec_to_str(priv_ver);
+
+if (priv_spec_str == NULL) {
+g_assert_not_reached();
  }
  
-g_assert_not_reached();

+return priv_spec_str;
  }
  
  static void riscv_cpu_synchronize_from_tb(CPUState *cs,




[PATCH] target/riscv/cpu.c: fix Zvkb extension config

2024-05-11 Thread Yangyu Chen
This code has a typo that writes zvkb to zvkg, causing users can't
enable zvkb through the config. This patch gets this fixed.

Signed-off-by: Yangyu Chen 
Fixes: ea61ef7097d0 ("target/riscv: Move vector crypto extensions to 
riscv_cpu_extensions")
---
 target/riscv/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index eb1a2e7d6d..13cd34adbd 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1535,7 +1535,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 /* Vector cryptography extensions */
 MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
 MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
-MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
+MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
 MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
 MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
 MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),
-- 
2.43.0




RE: [PATCH v6 5/7] migration/multifd: implement initialization of qpl compression

2024-05-11 Thread Liu, Yuan1
> -Original Message-
> From: Fabiano Rosas 
> Sent: Saturday, May 11, 2024 4:45 AM
> To: Liu, Yuan1 ; pet...@redhat.com
> Cc: qemu-devel@nongnu.org; Liu, Yuan1 ; Zou, Nanhai
> 
> Subject: Re: [PATCH v6 5/7] migration/multifd: implement initialization of
> qpl compression
> 
> Yuan Liu  writes:
> 
> > the qpl initialization includes memory allocation for compressed
> > data and the qpl job initialization.
> >
> > the qpl job initialization will check if the In-Memory Analytics
> > Accelerator(IAA) device is available and use the IAA device first.
> > If the platform does not have IAA device or the IAA device is not
> > available, the qpl compression will fallback to the software path.
> >
> > Signed-off-by: Yuan Liu 
> > Reviewed-by: Nanhai Zou 
> 
> Looks good, just some nits below.
> 
> > ---
> >  migration/multifd-qpl.c | 272 +++-
> >  1 file changed, 271 insertions(+), 1 deletion(-)
> >
> > diff --git a/migration/multifd-qpl.c b/migration/multifd-qpl.c
> > index 056a68a060..89fa51091a 100644
> > --- a/migration/multifd-qpl.c
> > +++ b/migration/multifd-qpl.c
> > @@ -9,12 +9,282 @@
> >   * This work is licensed under the terms of the GNU GPL, version 2 or
> later.
> >   * See the COPYING file in the top-level directory.
> >   */
> > +
> >  #include "qemu/osdep.h"
> >  #include "qemu/module.h"
> > +#include "qapi/error.h"
> > +#include "migration.h"
> > +#include "multifd.h"
> > +#include "qpl/qpl.h"
> > +
> > +typedef struct {
> > +qpl_job **job_array;
> > +/* the number of allocated jobs */
> > +uint32_t total_job_num;
> > +/* compressed data buffer */
> > +uint8_t *zbuf;
> > +/* the length of compressed data */
> 
> array of lenghts

Thanks for the comment, I will improve the comment next version.

> > +uint32_t *zbuf_hdr;
> 
> Why the _hdr suffix if the lengths are the only data stored here?

This zbuf_hdr is confusing, I will use lens instead of zbuf_hdr next version

> > +/* the status of IAA device */
> > +bool iaa_avail;
> > +} QplData;
> > +
> > +/**
> > + * check_iaa_avail: check if IAA device is available
> > + *
> > + * If the system does not have an IAA device, the IAA device is
> > + * not enabled or the IAA work queue is not configured as a shared
> > + * mode, the QPL hardware path initialization will fail.
> > + *
> > + * Returns true if IAA device is available, otherwise false.
> > + */
> > +static bool check_iaa_avail(void)
> > +{
> > +qpl_job *job = NULL;
> > +uint32_t job_size = 0;
> > +qpl_path_t path = qpl_path_hardware;
> > +
> > +if (qpl_get_job_size(path, _size) != QPL_STS_OK) {
> > +return false;
> > +}
> > +job = g_malloc0(job_size);
> > +if (qpl_init_job(path, job) != QPL_STS_OK) {
> > +g_free(job);
> > +return false;
> > +}
> > +g_free(job);
> > +return true;
> > +}
> > +
> > +/**
> > + * multifd_qpl_free_jobs: cleanup jobs
> > + *
> > + * Free all job resources.
> > + *
> > + * @qpl: pointer to the QplData structure
> > + */
> > +static void multifd_qpl_free_jobs(QplData *qpl)
> > +{
> > +assert(qpl != NULL);
> > +for (int i = 0; i < qpl->total_job_num; i++) {
> > +qpl_fini_job(qpl->job_array[i]);
> > +g_free(qpl->job_array[i]);
> > +qpl->job_array[i] = NULL;
> > +}
> > +g_free(qpl->job_array);
> > +qpl->job_array = NULL;
> > +}
> > +
> > +/**
> > + * multifd_qpl_init_jobs: initialize jobs
> > + *
> > + * Initialize all jobs
> > + *
> > + * @qpl: pointer to the QplData structure
> > + * @chan_id: multifd channel number
> > + * @errp: pointer to an error
> > + */
> > +static int multifd_qpl_init_jobs(QplData *qpl, uint8_t chan_id, Error
> **errp)
> > +{
> > +qpl_path_t path;
> > +qpl_status status;
> > +uint32_t job_size = 0;
> > +qpl_job *job = NULL;
> > +
> > +path = qpl->iaa_avail ? qpl_path_hardware : qpl_path_software;
> > +status = qpl_get_job_size(path, _size);
> > +if (status != QPL_STS_OK) {
> > +error_setg(errp, "multifd: %u: qpl_get_job_size failed with
> error %d",
> > +   chan_id, status);
> > +return -1;
> > +}
> > +qpl->job_array = g_new0(qpl_job *, qpl->total_job_num);
> > +for (int i = 0; i < qpl->total_job_num; i++) {
> > +job = g_malloc0(job_size);
> > +status = qpl_init_job(path, job);
> > +if (status != QPL_STS_OK) {
> > +error_setg(errp, "multifd: %u: qpl_init_job failed with
> error %d",
> > +   chan_id, status);
> > +multifd_qpl_free_jobs(qpl);
> > +return -1;
> > +}
> > +qpl->job_array[i] = job;
> > +}
> > +return 0;
> > +}
> > +
> > +/**
> > + * multifd_qpl_init: initialize QplData structure
> > + *
> > + * Allocate and initialize a QplData structure
> > + *
> > + * Returns QplData pointer for success or NULL for error
> > + *
> > + * @job_num: pointer to the QplData structure
> 
> This needs 

RE: [PATCH v6 5/7] migration/multifd: implement initialization of qpl compression

2024-05-11 Thread Liu, Yuan1
> -Original Message-
> From: Fabiano Rosas 
> Sent: Saturday, May 11, 2024 4:53 AM
> To: Liu, Yuan1 ; pet...@redhat.com
> Cc: qemu-devel@nongnu.org; Liu, Yuan1 ; Zou, Nanhai
> 
> Subject: Re: [PATCH v6 5/7] migration/multifd: implement initialization of
> qpl compression
> 
> Yuan Liu  writes:
> 
> > the qpl initialization includes memory allocation for compressed
> > data and the qpl job initialization.
> >
> > the qpl job initialization will check if the In-Memory Analytics
> > Accelerator(IAA) device is available and use the IAA device first.
> > If the platform does not have IAA device or the IAA device is not
> > available, the qpl compression will fallback to the software path.
> >
> > Signed-off-by: Yuan Liu 
> > Reviewed-by: Nanhai Zou 
> > ---
> >  migration/multifd-qpl.c | 272 +++-
> >  1 file changed, 271 insertions(+), 1 deletion(-)
> >
> > diff --git a/migration/multifd-qpl.c b/migration/multifd-qpl.c
> > index 056a68a060..89fa51091a 100644
> > --- a/migration/multifd-qpl.c
> > +++ b/migration/multifd-qpl.c
> > @@ -9,12 +9,282 @@
> >   * This work is licensed under the terms of the GNU GPL, version 2 or
> later.
> >   * See the COPYING file in the top-level directory.
> >   */
> > +
> >  #include "qemu/osdep.h"
> >  #include "qemu/module.h"
> > +#include "qapi/error.h"
> > +#include "migration.h"
> 
> Where is this used? I think you only need qapi/qapi-types-migration.h

Yes, the qapi/qapi-types-migration.h is enough, no need to include migration.h
I will fix this next version.

> > +#include "multifd.h"
> > +#include "qpl/qpl.h"
> > +
> > +typedef struct {
> > +qpl_job **job_array;
> > +/* the number of allocated jobs */
> > +uint32_t total_job_num;
> > +/* compressed data buffer */
> > +uint8_t *zbuf;
> > +/* the length of compressed data */
> > +uint32_t *zbuf_hdr;
> > +/* the status of IAA device */
> > +bool iaa_avail;
> > +} QplData;
> > +
> > +/**
> > + * check_iaa_avail: check if IAA device is available
> > + *
> > + * If the system does not have an IAA device, the IAA device is
> > + * not enabled or the IAA work queue is not configured as a shared
> > + * mode, the QPL hardware path initialization will fail.
> > + *
> > + * Returns true if IAA device is available, otherwise false.
> > + */
> > +static bool check_iaa_avail(void)
> > +{
> > +qpl_job *job = NULL;
> > +uint32_t job_size = 0;
> > +qpl_path_t path = qpl_path_hardware;
> > +
> > +if (qpl_get_job_size(path, _size) != QPL_STS_OK) {
> > +return false;
> > +}
> > +job = g_malloc0(job_size);
> > +if (qpl_init_job(path, job) != QPL_STS_OK) {
> > +g_free(job);
> > +return false;
> > +}
> > +g_free(job);
> > +return true;
> > +}
> > +
> > +/**
> > + * multifd_qpl_free_jobs: cleanup jobs
> > + *
> > + * Free all job resources.
> > + *
> > + * @qpl: pointer to the QplData structure
> > + */
> > +static void multifd_qpl_free_jobs(QplData *qpl)
> > +{
> > +assert(qpl != NULL);
> > +for (int i = 0; i < qpl->total_job_num; i++) {
> > +qpl_fini_job(qpl->job_array[i]);
> > +g_free(qpl->job_array[i]);
> > +qpl->job_array[i] = NULL;
> > +}
> > +g_free(qpl->job_array);
> > +qpl->job_array = NULL;
> > +}
> > +
> > +/**
> > + * multifd_qpl_init_jobs: initialize jobs
> > + *
> > + * Initialize all jobs
> > + *
> > + * @qpl: pointer to the QplData structure
> > + * @chan_id: multifd channel number
> > + * @errp: pointer to an error
> > + */
> > +static int multifd_qpl_init_jobs(QplData *qpl, uint8_t chan_id, Error
> **errp)
> > +{
> > +qpl_path_t path;
> > +qpl_status status;
> > +uint32_t job_size = 0;
> > +qpl_job *job = NULL;
> > +
> > +path = qpl->iaa_avail ? qpl_path_hardware : qpl_path_software;
> > +status = qpl_get_job_size(path, _size);
> > +if (status != QPL_STS_OK) {
> > +error_setg(errp, "multifd: %u: qpl_get_job_size failed with
> error %d",
> > +   chan_id, status);
> > +return -1;
> > +}
> > +qpl->job_array = g_new0(qpl_job *, qpl->total_job_num);
> > +for (int i = 0; i < qpl->total_job_num; i++) {
> > +job = g_malloc0(job_size);
> > +status = qpl_init_job(path, job);
> > +if (status != QPL_STS_OK) {
> > +error_setg(errp, "multifd: %u: qpl_init_job failed with
> error %d",
> > +   chan_id, status);
> > +multifd_qpl_free_jobs(qpl);
> > +return -1;
> > +}
> > +qpl->job_array[i] = job;
> > +}
> > +return 0;
> > +}
> > +
> > +/**
> > + * multifd_qpl_init: initialize QplData structure
> > + *
> > + * Allocate and initialize a QplData structure
> > + *
> > + * Returns QplData pointer for success or NULL for error
> > + *
> > + * @job_num: pointer to the QplData structure
> > + * @job_size: the buffer size of the job
> > + * @chan_id: multifd channel number
> > + * @errp: pointer 

[PATCH 10/17] aarch64: Tidy reginfo dumping ahead of ZA state

2024-05-11 Thread Richard Henderson
A misalignment for sve_vl, plus add a bit more space
on the left for the ZA[n] field name.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 risu_reginfo_aarch64.c | 29 ++---
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/risu_reginfo_aarch64.c b/risu_reginfo_aarch64.c
index 0161044..86e70ab 100644
--- a/risu_reginfo_aarch64.c
+++ b/risu_reginfo_aarch64.c
@@ -183,6 +183,18 @@ static int sve_preg_is_eq(int vq, const void *p1, const 
void *p2)
 return memcmp(p1, p2, vq * 2) == 0;
 }
 
+static void sve_dump_zreg(FILE *f, int vq, const uint64_t *z)
+{
+const char *pad = "";
+int q;
+
+for (q = 0; q < vq; q++) {
+fprintf(f, "%s[%-2d] %016" PRIx64 "%016" PRIx64 "\n",
+pad, q, z[2 * q + 1], z[2 * q]);
+pad = "   "; /* 11 spaces */
+}
+}
+
 static void sve_dump_preg(FILE *f, int vq, const uint16_t *p)
 {
 int q;
@@ -211,10 +223,10 @@ static void sve_dump_zreg_diff(FILE *f, int vq, const 
uint64_t *za,
 uint64_t zb0 = zb[2 * q], zb1 = zb[2 * q + 1];
 
 if (za0 != zb0 || za1 != zb1) {
-fprintf(f, "%sq%-2d: %016" PRIx64 "%016" PRIx64
+fprintf(f, "%s[%-2d]: %016" PRIx64 "%016" PRIx64
 " vs %016" PRIx64 "%016" PRIx64"\n",
 pad, q, za1, za0, zb1, zb0);
-pad = "  ";
+pad = "   "; /* 11 spaces */
 }
 }
 }
@@ -237,19 +249,14 @@ void reginfo_dump(struct reginfo *ri, FILE * f)
 
 if (ri->sve_vl) {
 int vq = sve_vq_from_vl(ri->sve_vl);
-int q;
 
 fprintf(f, "  vl : %d\n", ri->sve_vl);
 
 for (i = 0; i < SVE_NUM_ZREGS; i++) {
 uint64_t *z = reginfo_zreg(ri, vq, i);
 
-fprintf(f, "  Z%-2d q%-2d: %016" PRIx64 "%016" PRIx64 "\n",
-i, 0, z[1], z[0]);
-for (q = 1; q < vq; ++q) {
-fprintf(f, "  q%-2d: %016" PRIx64 "%016" PRIx64 "\n",
-q, z[q * 2 + 1], z[q * 2]);
-}
+fprintf(f, "  Z%-2d: ", i);
+sve_dump_zreg(f, vq, z);
 }
 
 for (i = 0; i < SVE_NUM_PREGS + 1; i++) {
@@ -312,7 +319,7 @@ void reginfo_dump_mismatch(struct reginfo *m, struct 
reginfo *a, FILE * f)
 }
 
 if (m->sve_vl != a->sve_vl) {
-fprintf(f, "  vl: %d vs %d\n", m->sve_vl, a->sve_vl);
+fprintf(f, "  vl : %d vs %d\n", m->sve_vl, a->sve_vl);
 }
 
 if (m->sve_vl) {
@@ -323,7 +330,7 @@ void reginfo_dump_mismatch(struct reginfo *m, struct 
reginfo *a, FILE * f)
 uint64_t *za = reginfo_zreg(a, vq, i);
 
 if (!sve_zreg_is_eq(vq, zm, za)) {
-fprintf(f, "  Z%-2d ", i);
+fprintf(f, "  Z%-2d: ", i);
 sve_dump_zreg_diff(f, vq, zm, za);
 }
 }
-- 
2.34.1




[PATCH 11/17] aarch64: Add support for ZA storage

2024-05-11 Thread Richard Henderson
Require NVL == SVL on startup, to make it easier to manage reginfo.
Most of the time PSTATE.SM would be active with PSTATE.ZA anyway,
for any non-trivial SME testing.

Extend saved storage only when PSTATE.ZA is active.
Use a carefully reserved uint16_t for saving SVCR.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 risu_reginfo_aarch64.h |  52 -
 risu_reginfo_aarch64.c | 161 -
 2 files changed, 191 insertions(+), 22 deletions(-)

diff --git a/risu_reginfo_aarch64.h b/risu_reginfo_aarch64.h
index 536c12b..097b7ad 100644
--- a/risu_reginfo_aarch64.h
+++ b/risu_reginfo_aarch64.h
@@ -21,6 +21,43 @@
 #define SVE_VQ_MAX 16
 
 #define ROUND_UP(SIZE, POW2)(((SIZE) + (POW2) - 1) & -(POW2))
+
+#ifdef ZA_MAGIC
+/* System headers have all Streaming SVE definitions. */
+typedef struct sve_context risu_sve_context;
+typedef struct za_context  risu_za_context;
+#else
+#define ZA_MAGIC 0x54366345
+#define SVE_SIG_FLAG_SM  1
+
+/* System headers missing flags field. */
+typedef struct {
+struct _aarch64_ctx head;
+uint16_t vl;
+uint16_t flags;
+uint16_t reserved[2];
+} risu_sve_context;
+
+typedef struct {
+struct _aarch64_ctx head;
+uint16_t vl;
+uint16_t reserved[3];
+} risu_za_context;
+
+#define ZA_SIG_REGS_OFFSET \
+ROUND_UP(sizeof(risu_za_context), SVE_VQ_BYTES)
+
+#define ZA_SIG_REGS_SIZE(vq) \
+((vq) * (vq) * SVE_VQ_BYTES * SVE_VQ_BYTES)
+
+#define ZA_SIG_ZAV_OFFSET(vq, n) \
+(ZA_SIG_REGS_OFFSET + (SVE_SIG_ZREG_SIZE(vq) * n))
+
+#define ZA_SIG_CONTEXT_SIZE(vq) \
+(ZA_SIG_REGS_OFFSET + ZA_SIG_REGS_SIZE(vq))
+
+#endif /* ZA_MAGIC */
+
 #define RISU_SVE_REGS_SIZE(VQ)  ROUND_UP(SVE_SIG_REGS_SIZE(VQ), 16)
 #define RISU_SIMD_REGS_SIZE (32 * 16)
 
@@ -36,12 +73,16 @@ struct reginfo {
 uint32_t fpsr;
 uint32_t fpcr;
 uint16_t sve_vl;
-uint16_t reserved;
+uint16_t svcr;
 
-char extra[RISU_SVE_REGS_SIZE(SVE_VQ_MAX)]
+char extra[RISU_SVE_REGS_SIZE(SVE_VQ_MAX) +
+   ZA_SIG_REGS_SIZE(SVE_VQ_MAX)]
 __attribute__((aligned(16)));
 };
 
+#define SVCR_SM  1
+#define SVCR_ZA  2
+
 static inline uint64_t *reginfo_vreg(struct reginfo *ri, int i)
 {
 return (uint64_t *)>extra[i * 16];
@@ -59,4 +100,11 @@ static inline uint16_t *reginfo_preg(struct reginfo *ri, 
int vq, int i)
   SVE_SIG_REGS_OFFSET];
 }
 
+static inline uint64_t *reginfo_zav(struct reginfo *ri, int vq, int i)
+{
+return (uint64_t *)>extra[RISU_SVE_REGS_SIZE(vq) +
+  ZA_SIG_ZAV_OFFSET(vq, i) -
+  ZA_SIG_REGS_OFFSET];
+}
+
 #endif /* RISU_REGINFO_AARCH64_H */
diff --git a/risu_reginfo_aarch64.c b/risu_reginfo_aarch64.c
index 86e70ab..67a2999 100644
--- a/risu_reginfo_aarch64.c
+++ b/risu_reginfo_aarch64.c
@@ -25,25 +25,44 @@
 #include "risu.h"
 #include "risu_reginfo_aarch64.h"
 
+#ifndef PR_SME_SET_VL
+#define PR_SME_SET_VL 63
+#endif
+
 /* Should we test SVE register state */
 static int test_sve;
+static int test_za;
 static const struct option extra_opts[] = {
 {"test-sve", required_argument, NULL, FIRST_ARCH_OPT },
+{"test-za", required_argument, NULL, FIRST_ARCH_OPT + 1 },
 {0, 0, 0, 0}
 };
 
 const struct option * const arch_long_opts = _opts[0];
 const char * const arch_extra_help
-= "  --test-sve=Compare SVE registers with VQ\n";
+= "  --test-sve=Compare SVE registers with VQ\n"
+  "  --test-za= Compare ZA storage with VQ\n";
 
 void process_arch_opt(int opt, const char *arg)
 {
-assert(opt == FIRST_ARCH_OPT);
-test_sve = strtol(arg, 0, 10);
-
-if (test_sve <= 0 || test_sve > SVE_VQ_MAX) {
-fprintf(stderr, "Invalid value for VQ (1-%d)\n", SVE_VQ_MAX);
-exit(EXIT_FAILURE);
+switch (opt) {
+case FIRST_ARCH_OPT:
+test_sve = strtol(arg, 0, 10);
+if (test_sve <= 0 || test_sve > SVE_VQ_MAX) {
+fprintf(stderr, "Invalid value for SVE VQ (1-%d)\n", SVE_VQ_MAX);
+exit(EXIT_FAILURE);
+}
+break;
+case FIRST_ARCH_OPT + 1:
+test_za = strtol(arg, 0, 10);
+if (test_za <= 0 || test_za > SVE_VQ_MAX
+|| (test_za & (test_za - 1))) {
+fprintf(stderr, "Invalid value for ZA VQ (1-%d)\n", SVE_VQ_MAX);
+exit(EXIT_FAILURE);
+}
+break;
+default:
+abort();
 }
 }
 
@@ -51,6 +70,31 @@ void arch_init(void)
 {
 long want, got;
 
+if (test_za) {
+/*
+ * For now, reginfo requires NVL == SVL.
+ * There doesn't seem to be much advantage to differing.
+ */
+if (test_sve && test_sve != test_za) {
+fprintf(stderr, "Mismatched values for SVE and ZA VQ\n");
+exit(EXIT_FAILURE);
+}
+
+want = sve_vl_from_vq(test_za);
+got = prctl(PR_SME_SET_VL, want);
+if (want != got) {
+if (got >= 0) 

[PATCH 06/17] ppc64: Clean register values in reginfo_init

2024-05-11 Thread Richard Henderson
Smash the stack and thread pointers to deadbeef, as is common
for the other architectures.  This allows us to drop these
special cases within reginfo_is_eq and reginfo_dump_mismatch.

Do not copy the unused special registers that are packed into gregs[].
Most of these are related to system instructions and thus are not
manipulable via the user-mode instructions targeted by RISU.  LNK and
CTR are not initialized by risugen, and since in general we cannot
test branches with risugen these can be ignored.  This leaves only
XER and CCR as the only special registers to be copied.

Signed-off-by: Richard Henderson 
---
 risu_reginfo_ppc64.c | 17 +
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/risu_reginfo_ppc64.c b/risu_reginfo_ppc64.c
index fc69805..67ea3ce 100644
--- a/risu_reginfo_ppc64.c
+++ b/risu_reginfo_ppc64.c
@@ -44,16 +44,16 @@ int reginfo_size(struct reginfo *ri)
 /* reginfo_init: initialize with a ucontext */
 void reginfo_init(struct reginfo *ri, ucontext_t *uc, void *siaddr)
 {
-int i;
-
 memset(ri, 0, sizeof(*ri));
 
 ri->faulting_insn = *((uint32_t *) uc->uc_mcontext.regs->nip);
 ri->nip = uc->uc_mcontext.regs->nip - image_start_address;
 
-for (i = 0; i < NGREG; i++) {
-ri->gregs[i] = uc->uc_mcontext.gp_regs[i];
-}
+memcpy(ri->gregs, uc->uc_mcontext.gp_regs, 32 * sizeof(ri->gregs[0]));
+ri->gregs[1] = 0xdeadbeefdeadbeef;   /* sp */
+ri->gregs[13] = 0xdeadbeefdeadbeef;  /* tp */
+ri->gregs[XER] = uc->uc_mcontext.gp_regs[XER];
+ri->gregs[CCR] = uc->uc_mcontext.gp_regs[CCR];
 
 memcpy(ri->fpregs, uc->uc_mcontext.fp_regs, 32 * sizeof(double));
 ri->fpscr = uc->uc_mcontext.fp_regs[32];
@@ -69,10 +69,6 @@ int reginfo_is_eq(struct reginfo *m, struct reginfo *a)
 {
 int i;
 for (i = 0; i < 32; i++) {
-if (i == 1 || i == 13) {
-continue;
-}
-
 if (m->gregs[i] != a->gregs[i]) {
 return 0;
 }
@@ -150,9 +146,6 @@ void reginfo_dump_mismatch(struct reginfo *m, struct 
reginfo *a, FILE *f)
 int i;
 
 for (i = 0; i < 32; i++) {
-if (i == 1 || i == 13) {
-continue;
-}
 if (m->gregs[i] != a->gregs[i]) {
 fprintf(f, "%*s%d: %016lx vs %016lx\n",
 6 - (1 < 10 ? 1 : 2), "r", i,
-- 
2.34.1




[PATCH 15/17] risu: Allow use of ELF test files

2024-05-11 Thread Richard Henderson
By using elf files, we make it easier to disassemble
the test file, to match comparison failures to code.

Signed-off-by: Richard Henderson 
---
 risu.c | 53 +
 1 file changed, 53 insertions(+)

diff --git a/risu.c b/risu.c
index c28b4a5..e3845f6 100644
--- a/risu.c
+++ b/risu.c
@@ -24,6 +24,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "config.h"
 #include "risu.h"
@@ -371,6 +373,57 @@ static void load_image(const char *imgfile)
 close(fd);
 image_start = addr;
 image_start_address = (uintptr_t) addr;
+
+/*
+ * TODO: More complete parsing of ELF file, verify assumtion, namely:
+ * Single PT_LOAD covering the ELF header, code and data.
+ * For now, simply update image_start from the elf header.
+ */
+if (memcmp(addr, ELFMAG, SELFMAG) == 0) {
+const unsigned char *e_ident = addr;
+bool swap, is_64;
+
+switch (e_ident[EI_DATA]) {
+case ELFDATA2LSB:
+swap = __BYTE_ORDER != __LITTLE_ENDIAN;
+break;
+case ELFDATA2MSB:
+swap = __BYTE_ORDER == __LITTLE_ENDIAN;
+break;
+default:
+fprintf(stderr, "%s: Bad elf header: EI_DATA = %x\n",
+imgfile, e_ident[EI_DATA]);
+exit(1);
+}
+switch (e_ident[EI_CLASS]) {
+case ELFCLASS32:
+is_64 = false;
+break;
+case ELFCLASS64:
+is_64 = true;
+break;
+default:
+fprintf(stderr, "%s: Bad elf header: EI_CLASS = %x\n",
+imgfile, e_ident[EI_CLASS]);
+exit(1);
+}
+
+if (is_64) {
+const Elf64_Ehdr *h64 = addr;
+Elf64_Addr e64 = h64->e_entry;
+if (swap) {
+e64 = __builtin_bswap64(e64);
+}
+image_start = addr + e64;
+} else {
+const Elf32_Ehdr *h32 = addr;
+Elf32_Addr e32 = h32->e_entry;
+if (swap) {
+e32 = __builtin_bswap32(e32);
+}
+image_start = addr + e32;
+}
+}
 }
 
 static int master(void)
-- 
2.34.1




[PATCH 14/17] aarch64: Use bool for sve_{z,p}reg_is_eq

2024-05-11 Thread Richard Henderson
The functions results are more naturally boolean.

Signed-off-by: Richard Henderson 
---
 risu_reginfo_aarch64.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/risu_reginfo_aarch64.c b/risu_reginfo_aarch64.c
index 55a9ef6..6323eef 100644
--- a/risu_reginfo_aarch64.c
+++ b/risu_reginfo_aarch64.c
@@ -268,12 +268,12 @@ bool reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
 return memcmp(r1, r2, reginfo_size(r1)) == 0;
 }
 
-static int sve_zreg_is_eq(int vq, const void *z1, const void *z2)
+static bool sve_zreg_is_eq(int vq, const void *z1, const void *z2)
 {
 return memcmp(z1, z2, vq * 16) == 0;
 }
 
-static int sve_preg_is_eq(int vq, const void *p1, const void *p2)
+static bool sve_preg_is_eq(int vq, const void *p1, const void *p2)
 {
 return memcmp(p1, p2, vq * 2) == 0;
 }
-- 
2.34.1




[PATCH 03/17] Standardize reginfo_dump_mismatch printing

2024-05-11 Thread Richard Henderson
Hoist the "master vs apprentice" label to apprentice(), since
we will want different labels for dumping.  Remove all of the
"mismatch" text from reginfo_dump_mismatch -- just print "vs".

Signed-off-by: Richard Henderson 
---
 risu.h |  4 ++--
 risu.c |  1 +
 risu_reginfo_aarch64.c | 12 +---
 risu_reginfo_arm.c | 18 +-
 risu_reginfo_i386.c|  6 +-
 risu_reginfo_loongarch64.c | 11 ---
 risu_reginfo_m68k.c| 23 +++
 risu_reginfo_ppc64.c   | 25 -
 risu_reginfo_s390x.c   | 18 +++---
 9 files changed, 48 insertions(+), 70 deletions(-)

diff --git a/risu.h b/risu.h
index 2c43384..1b87af2 100644
--- a/risu.h
+++ b/risu.h
@@ -123,8 +123,8 @@ int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2);
 /* print reginfo state to a stream, returns 1 on success, 0 on failure */
 int reginfo_dump(struct reginfo *ri, FILE * f);
 
-/* reginfo_dump_mismatch: print mismatch details to a stream, ret nonzero=ok */
-int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f);
+/* reginfo_dump_mismatch: print mismatch details to a stream */
+void reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f);
 
 /* return size of reginfo */
 int reginfo_size(struct reginfo *ri);
diff --git a/risu.c b/risu.c
index 6b6295c..9c31b8c 100644
--- a/risu.c
+++ b/risu.c
@@ -448,6 +448,7 @@ static int apprentice(void)
 reginfo_dump([MASTER], stderr);
 fprintf(stderr, "apprentice reginfo:\n");
 reginfo_dump([APPRENTICE], stderr);
+fprintf(stderr, "mismatch detail (master : apprentice):\n");
 reginfo_dump_mismatch([MASTER], [APPRENTICE], stderr);
 return EXIT_FAILURE;
 
diff --git a/risu_reginfo_aarch64.c b/risu_reginfo_aarch64.c
index 1244454..da221d5 100644
--- a/risu_reginfo_aarch64.c
+++ b/risu_reginfo_aarch64.c
@@ -275,15 +275,15 @@ int reginfo_dump(struct reginfo *ri, FILE * f)
 return !ferror(f);
 }
 
-/* reginfo_dump_mismatch: print mismatch details to a stream, ret nonzero=ok */
-int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE * f)
+void reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE * f)
 {
 int i;
-fprintf(f, "mismatch detail (master : apprentice):\n");
+
 if (m->faulting_insn != a->faulting_insn) {
-fprintf(f, "  faulting insn mismatch %08x vs %08x\n",
+fprintf(f, "  faulting insn: %08x vs %08x\n",
 m->faulting_insn, a->faulting_insn);
 }
+
 for (i = 0; i < 31; i++) {
 if (m->regs[i] != a->regs[i]) {
 fprintf(f, "  X%-2d: %016" PRIx64 " vs %016" PRIx64 "\n",
@@ -342,7 +342,7 @@ int reginfo_dump_mismatch(struct reginfo *m, struct reginfo 
*a, FILE * f)
 sve_dump_preg_diff(f, vq, pm, pa);
 }
 }
-return !ferror(f);
+return;
 }
 
 for (i = 0; i < 32; i++) {
@@ -356,6 +356,4 @@ int reginfo_dump_mismatch(struct reginfo *m, struct reginfo 
*a, FILE * f)
 i, mv[1], mv[0], av[1], av[0]);
 }
 }
-
-return !ferror(f);
 }
diff --git a/risu_reginfo_arm.c b/risu_reginfo_arm.c
index 85a39ac..221bd8a 100644
--- a/risu_reginfo_arm.c
+++ b/risu_reginfo_arm.c
@@ -183,32 +183,33 @@ int reginfo_dump(struct reginfo *ri, FILE *f)
 return !ferror(f);
 }
 
-int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f)
+void reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f)
 {
 int i;
-fprintf(f, "mismatch detail (master : apprentice):\n");
 
 if (m->faulting_insn_size != a->faulting_insn_size) {
-fprintf(f, "  faulting insn size mismatch %d vs %d\n",
+fprintf(f, "  faulting insn size: %d vs %d\n",
 m->faulting_insn_size, a->faulting_insn_size);
 } else if (m->faulting_insn != a->faulting_insn) {
 if (m->faulting_insn_size == 2) {
-fprintf(f, "  faulting insn mismatch %04x vs %04x\n",
+fprintf(f, "  faulting insn: %04x vs %04x\n",
 m->faulting_insn, a->faulting_insn);
 } else {
-fprintf(f, "  faulting insn mismatch %08x vs %08x\n",
+fprintf(f, "  faulting insn: %08x vs %08x\n",
 m->faulting_insn, a->faulting_insn);
 }
 }
+
 for (i = 0; i < 16; i++) {
 if (m->gpreg[i] != a->gpreg[i]) {
-fprintf(f, "  r%d: %08x vs %08x\n", i, m->gpreg[i],
-a->gpreg[i]);
+fprintf(f, "  r%d: %08x vs %08x\n", i, m->gpreg[i], a->gpreg[i]);
 }
 }
+
 if (m->cpsr != a->cpsr) {
 fprintf(f, "  cpsr: %08x vs %08x\n", m->cpsr, a->cpsr);
 }
+
 for (i = 0; i < 32; i++) {
 if (m->fpregs[i] != a->fpregs[i]) {
 fprintf(f, "  d%d: %016llx vs %016llx\n", i,
@@ -216,9 +217,8 @@ int reginfo_dump_mismatch(struct reginfo *m, struct reginfo 
*a, FILE *f)

[PATCH 12/17] aarch64: Trivial SME test

2024-05-11 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 test_sme_aarch64.s | 63 ++
 1 file changed, 63 insertions(+)
 create mode 100644 test_sme_aarch64.s

diff --git a/test_sme_aarch64.s b/test_sme_aarch64.s
new file mode 100644
index 000..acd08d4
--- /dev/null
+++ b/test_sme_aarch64.s
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2022 Linaro Limited
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+
+   .arch_extension sme
+
+   mov w0, #0
+   mov w1, #0
+   mov w2, #0
+   mov w3, #0
+   mov w4, #0
+   mov w5, #0
+   mov w6, #0
+   mov w7, #0
+   mov w8, #0
+   mov w9, #0
+   mov w10, #0
+   mov w11, #0
+   mov w12, #0
+   mov w13, #0
+   mov w14, #0
+   mov w15, #0
+   mov w16, #0
+   mov w17, #0
+   mov w18, #0
+   mov w19, #0
+   mov w20, #0
+   mov w21, #0
+   mov w22, #0
+   mov w23, #0
+   mov w24, #0
+   mov w25, #0
+   mov w26, #0
+   mov w27, #0
+   mov w28, #0
+   mov w29, #0
+   mov w30, #0
+
+   smstart
+
+   ptrue   p0.b
+   rdsvl   x12, #1
+
+0: subsw12, w12, #1
+   lsl w13, w12, #4
+   index   z0.b, w13, #1
+   movaza0h.b[w12, #0], p0/m, z0.b
+   b.ne0b
+
+   .inst 0x5af0/* compare */
+
+   rdsvl   x12, #1
+0: subsw12, w12, #1
+   lsl w13, w12, #4
+   index   z0.b, w13, #1
+   movaza0v.b[w12, #0], p0/m, z0.b
+   b.ne0b
+
+   .inst 0x5af1/* exit */
-- 
2.34.1




[PATCH 05/17] Remove return value from reginfo_dump

2024-05-11 Thread Richard Henderson
No uses actually checked the error indication.  Even if we wanted
to check ferror on the stream, we should do that generically rather
than per arch.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 risu.h | 4 ++--
 risu_reginfo_aarch64.c | 8 +++-
 risu_reginfo_arm.c | 6 ++
 risu_reginfo_i386.c| 6 ++
 risu_reginfo_loongarch64.c | 6 ++
 risu_reginfo_m68k.c| 6 ++
 risu_reginfo_ppc64.c   | 6 ++
 risu_reginfo_s390x.c   | 6 ++
 8 files changed, 17 insertions(+), 31 deletions(-)

diff --git a/risu.h b/risu.h
index 1b87af2..aa8cc22 100644
--- a/risu.h
+++ b/risu.h
@@ -120,8 +120,8 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc, void 
*siaddr);
 /* return 1 if structs are equal, 0 otherwise. */
 int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2);
 
-/* print reginfo state to a stream, returns 1 on success, 0 on failure */
-int reginfo_dump(struct reginfo *ri, FILE * f);
+/* print reginfo state to a stream */
+void reginfo_dump(struct reginfo *ri, FILE *f);
 
 /* reginfo_dump_mismatch: print mismatch details to a stream */
 void reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f);
diff --git a/risu_reginfo_aarch64.c b/risu_reginfo_aarch64.c
index da221d5..0161044 100644
--- a/risu_reginfo_aarch64.c
+++ b/risu_reginfo_aarch64.c
@@ -219,8 +219,8 @@ static void sve_dump_zreg_diff(FILE *f, int vq, const 
uint64_t *za,
 }
 }
 
-/* reginfo_dump: print state to a stream, returns nonzero on success */
-int reginfo_dump(struct reginfo *ri, FILE * f)
+/* reginfo_dump: print state to a stream */
+void reginfo_dump(struct reginfo *ri, FILE * f)
 {
 int i;
 fprintf(f, "  faulting insn %08x\n", ri->faulting_insn);
@@ -263,7 +263,7 @@ int reginfo_dump(struct reginfo *ri, FILE * f)
 sve_dump_preg(f, vq, p);
 fprintf(f, "\n");
 }
-return !ferror(f);
+return;
 }
 
 for (i = 0; i < 32; i++) {
@@ -271,8 +271,6 @@ int reginfo_dump(struct reginfo *ri, FILE * f)
 fprintf(f, "  V%-2d: %016" PRIx64 "%016" PRIx64 "\n",
 i, v[1], v[0]);
 }
-
-return !ferror(f);
 }
 
 void reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE * f)
diff --git a/risu_reginfo_arm.c b/risu_reginfo_arm.c
index 221bd8a..0e179be 100644
--- a/risu_reginfo_arm.c
+++ b/risu_reginfo_arm.c
@@ -161,8 +161,8 @@ int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
 return memcmp(r1, r2, sizeof(*r1)) == 0;/* ok since we memset 0 */
 }
 
-/* reginfo_dump: print the state to a stream, returns nonzero on success */
-int reginfo_dump(struct reginfo *ri, FILE *f)
+/* reginfo_dump: print the state to a stream */
+void reginfo_dump(struct reginfo *ri, FILE *f)
 {
 int i;
 if (ri->faulting_insn_size == 2) {
@@ -179,8 +179,6 @@ int reginfo_dump(struct reginfo *ri, FILE *f)
 i, (unsigned long long) ri->fpregs[i]);
 }
 fprintf(f, "  fpscr: %08x\n", ri->fpscr);
-
-return !ferror(f);
 }
 
 void reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f)
diff --git a/risu_reginfo_i386.c b/risu_reginfo_i386.c
index 18d15ca..f4cf9a3 100644
--- a/risu_reginfo_i386.c
+++ b/risu_reginfo_i386.c
@@ -310,8 +310,8 @@ static char get_vecletter(uint64_t features)
 }
 }
 
-/* reginfo_dump: print state to a stream, returns nonzero on success */
-int reginfo_dump(struct reginfo *ri, FILE *f)
+/* reginfo_dump: print state to a stream */
+void reginfo_dump(struct reginfo *ri, FILE *f)
 {
 uint64_t features;
 int i, j, n, w;
@@ -345,8 +345,6 @@ int reginfo_dump(struct reginfo *ri, FILE *f)
 fprintf(f, "  k%-5d: %016" PRIx64 "\n", i, ri->kregs[i]);
 }
 }
-
-return !ferror(f);
 }
 
 void reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE *f)
diff --git a/risu_reginfo_loongarch64.c b/risu_reginfo_loongarch64.c
index 630d6b2..060715f 100644
--- a/risu_reginfo_loongarch64.c
+++ b/risu_reginfo_loongarch64.c
@@ -159,8 +159,8 @@ int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
 return !memcmp(r1, r2, sizeof(*r1));
 }
 
-/* reginfo_dump: print state to a stream, returns nonzero on success */
-int reginfo_dump(struct reginfo *ri, FILE * f)
+/* reginfo_dump: print state to a stream */
+void reginfo_dump(struct reginfo *ri, FILE * f)
 {
 int i;
 fprintf(f, "  faulting insn %08x\n", ri->faulting_insn);
@@ -191,8 +191,6 @@ int reginfo_dump(struct reginfo *ri, FILE * f)
 fprintf(f, "  vreg%-2d: %016lx\n", i, ri->vregs[4 * i]);
 }
 }
-
-return !ferror(f);
 }
 
 /* reginfo_dump_mismatch: print mismatch details to a stream */
diff --git a/risu_reginfo_m68k.c b/risu_reginfo_m68k.c
index 18ae1d8..a53244d 100644
--- a/risu_reginfo_m68k.c
+++ b/risu_reginfo_m68k.c
@@ -92,8 +92,8 @@ int reginfo_is_eq(struct reginfo *m, struct reginfo *a)
 return 1;
 }
 
-/* reginfo_dump: print state to a stream, returns nonzero on 

[PATCH 08/17] ppc64: Simplify reginfo_is_eq

2024-05-11 Thread Richard Henderson
Since we now only copy into reginfo exactly what we want to compare,
and since we zero all unused padding and reserved space, we need not
enumerate each field for comparison, but defer to memcmp.

Signed-off-by: Richard Henderson 
---
 risu_reginfo_ppc64.c | 31 +--
 1 file changed, 1 insertion(+), 30 deletions(-)

diff --git a/risu_reginfo_ppc64.c b/risu_reginfo_ppc64.c
index 109b87b..e0c650b 100644
--- a/risu_reginfo_ppc64.c
+++ b/risu_reginfo_ppc64.c
@@ -67,36 +67,7 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc, void 
*siaddr)
 /* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
 int reginfo_is_eq(struct reginfo *m, struct reginfo *a)
 {
-int i;
-for (i = 0; i < 32; i++) {
-if (m->gregs[i] != a->gregs[i]) {
-return 0;
-}
-}
-
-if (m->gregs[XER] != a->gregs[XER]) {
-return 0;
-}
-
-if (m->gregs[CCR] != a->gregs[CCR]) {
-return 0;
-}
-
-for (i = 0; i < 32; i++) {
-if (m->fpregs[i] != a->fpregs[i]) {
-return 0;
-}
-}
-
-for (i = 0; i < 32; i++) {
-if (m->vrregs.vrregs[i][0] != a->vrregs.vrregs[i][0] ||
-m->vrregs.vrregs[i][1] != a->vrregs.vrregs[i][1] ||
-m->vrregs.vrregs[i][2] != a->vrregs.vrregs[i][2] ||
-m->vrregs.vrregs[i][3] != a->vrregs.vrregs[i][3]) {
-return 0;
-}
-}
-return 1;
+return memcmp(m, a, sizeof(*m)) == 0;
 }
 
 /* reginfo_dump: print state to a stream */
-- 
2.34.1




[PATCH 00/17] RISU misc updates

2024-05-11 Thread Richard Henderson
Some of these have been sitting on a branch for a couple of years.
Except perhaps the first, which I assume to be some sort of odd
build error from the time, they still seem reasonable.

There are some updates for SME1, but not yet the ZT register for SME2.
I'll get to that later after I've done the qemu linux-user work.

Finally, let's start phasing out raw binary test cases.  We can
make it much easier for ourselves if we package test cases in ELF,
which "objdump -d" can parse directly, without having to be given
all sorts of "-b binary -m some-arch-flags" etc.

For future work, I plan to make changes to risugen so that it writes
out asm files and invokes the assembler and linker to produce the
final output file.


r~


Richard Henderson (17):
  ppc64: Fix  include order
  Fix load_image error check for mmap
  Standardize reginfo_dump_mismatch printing
  Add --fulldump and --diffdup options
  Remove return value from reginfo_dump
  ppc64: Clean register values in reginfo_init
  ppc64: Compare all bits of CCR
  ppc64: Simplify reginfo_is_eq
  ppc64: Clean up reginfo_dump
  aarch64: Tidy reginfo dumping ahead of ZA state
  aarch64: Add support for ZA storage
  aarch64: Trivial SME test
  Use bool for reginfo_is_eq
  aarch64: Use bool for sve_{z,p}reg_is_eq
  risu: Allow use of ELF test files
  configure: Enable loongarch64
  Build elf test cases instead of raw binaries

 Makefile   |  19 ++--
 risu.h |  12 +-
 risu_reginfo_aarch64.h |  52 -
 risu.c | 178 ++
 risu_ppc64.c   |   3 +-
 risu_reginfo_aarch64.c | 218 +
 risu_reginfo_arm.c |  28 +++--
 risu_reginfo_i386.c|  16 +--
 risu_reginfo_loongarch64.c |  21 ++--
 risu_reginfo_m68k.c|  45 +++-
 risu_reginfo_ppc64.c   | 134 ---
 risu_reginfo_s390x.c   |  28 ++---
 configure  |   4 +-
 test.ld|  12 ++
 test_aarch64.s |   4 +-
 test_arm.s |  16 ++-
 test_i386.S|   4 +-
 test_sme_aarch64.s |  63 +++
 18 files changed, 588 insertions(+), 269 deletions(-)
 create mode 100644 test.ld
 create mode 100644 test_sme_aarch64.s

-- 
2.34.1




[PATCH 09/17] ppc64: Clean up reginfo_dump

2024-05-11 Thread Richard Henderson
Dump only the registers that we copied in reginfo_init.
Improve the formatting and layout of what we do dump.

Signed-off-by: Richard Henderson 
---
 risu_reginfo_ppc64.c | 51 ++--
 1 file changed, 21 insertions(+), 30 deletions(-)

diff --git a/risu_reginfo_ppc64.c b/risu_reginfo_ppc64.c
index e0c650b..730a565 100644
--- a/risu_reginfo_ppc64.c
+++ b/risu_reginfo_ppc64.c
@@ -75,38 +75,29 @@ void reginfo_dump(struct reginfo *ri, FILE * f)
 {
 int i;
 
-fprintf(f, "  faulting insn 0x%x\n", ri->faulting_insn);
-fprintf(f, "  prev insn 0x%x\n", ri->prev_insn);
-fprintf(f, "  prev addr0x%" PRIx64 "\n\n", ri->nip);
-
-for (i = 0; i < 16; i++) {
-fprintf(f, "\tr%2d: %16lx\tr%2d: %16lx\n", i, ri->gregs[i],
-i + 16, ri->gregs[i + 16]);
-}
-
-fprintf(f, "\n");
-fprintf(f, "\tnip: %16lx\n", ri->gregs[32]);
-fprintf(f, "\tmsr: %16lx\n", ri->gregs[33]);
-fprintf(f, "\torig r3: %16lx\n", ri->gregs[34]);
-fprintf(f, "\tctr: %16lx\n", ri->gregs[35]);
-fprintf(f, "\tlnk: %16lx\n", ri->gregs[36]);
-fprintf(f, "\txer: %16lx\n", ri->gregs[37]);
-fprintf(f, "\tccr: %16lx\n", ri->gregs[38]);
-fprintf(f, "\tmq : %16lx\n", ri->gregs[39]);
-fprintf(f, "\ttrap   : %16lx\n", ri->gregs[40]);
-fprintf(f, "\tdar: %16lx\n", ri->gregs[41]);
-fprintf(f, "\tdsisr  : %16lx\n", ri->gregs[42]);
-fprintf(f, "\tresult : %16lx\n", ri->gregs[43]);
-fprintf(f, "\tdscr   : %16lx\n\n", ri->gregs[44]);
-
-for (i = 0; i < 16; i++) {
-fprintf(f, "\tf%2d: %016lx\tf%2d: %016lx\n", i, ri->fpregs[i],
-i + 16, ri->fpregs[i + 16]);
-}
-fprintf(f, "\tfpscr: %016lx\n\n", ri->fpscr);
+fprintf(f, "%6s: %08x\n", "insn", ri->faulting_insn);
+fprintf(f, "%6s: %016lx\n", "pc", ri->nip);
 
 for (i = 0; i < 32; i++) {
-fprintf(f, "vr%02d: %8x, %8x, %8x, %8x\n", i,
+fprintf(f, "%*s%d: %016lx%s",
+6 - (i < 10 ? 1 : 2), "r", i, ri->gregs[i],
+i & 1 ? "\n" : "  ");
+}
+
+fprintf(f, "%6s: %016lx  %6s: %016lx\n",
+"xer", ri->gregs[XER],
+"ccr", ri->gregs[CCR]);
+
+for (i = 0; i < 32; i++) {
+fprintf(f, "%*s%d: %016lx%s",
+6 - (i < 10 ? 1 : 2), "f", i, ri->fpregs[i],
+i & 1 ? "\n" : "  ");
+}
+fprintf(f, "%6s: %016lx\n", "fpscr", ri->fpscr);
+
+for (i = 0; i < 32; i++) {
+fprintf(f, "%*s%d: %08x %08x %08x %08x\n",
+6 - (i < 10 ? 1 : 2), "vr", i,
 ri->vrregs.vrregs[i][0], ri->vrregs.vrregs[i][1],
 ri->vrregs.vrregs[i][2], ri->vrregs.vrregs[i][3]);
 }
-- 
2.34.1




[PATCH 17/17] Build elf test cases instead of raw binaries

2024-05-11 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 Makefile   | 19 ++-
 test.ld| 12 
 test_aarch64.s |  4 ++--
 test_arm.s | 16 +++-
 test_i386.S|  4 +++-
 5 files changed, 38 insertions(+), 17 deletions(-)
 create mode 100644 test.ld

diff --git a/Makefile b/Makefile
index ad7f879..2bd08aa 100644
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,8 @@ ALL_CFLAGS = -Wall -D_GNU_SOURCE -DARCH=$(ARCH) -U$(ARCH) 
$(BUILD_INC) $(CFLAGS)
 PROG=risu
 SRCS=risu.c comms.c risu_$(ARCH).c risu_reginfo_$(ARCH).c
 HDRS=risu.h risu_reginfo_$(ARCH).h
-BINS=test_$(ARCH).bin
+BINO=test_$(ARCH).o
+BINE=test_$(ARCH).elf
 
 # For dumping test patterns
 RISU_BINS=$(wildcard *.risu.bin)
@@ -30,7 +31,7 @@ RISU_ASMS=$(patsubst %.bin,%.asm,$(RISU_BINS))
 
 OBJS=$(SRCS:.c=.o)
 
-all: $(PROG) $(BINS)
+all: $(PROG) $(BINE)
 
 dump: $(RISU_ASMS)
 
@@ -43,17 +44,17 @@ $(PROG): $(OBJS)
 %.o: %.c $(HDRS)
$(CC) $(CPPFLAGS) $(ALL_CFLAGS) -o $@ -c $<
 
-%_$(ARCH).bin: %_$(ARCH).elf
-   $(OBJCOPY) -O binary $< $@
+%_$(ARCH).o: %_$(ARCH).s
+   $(CC) -o $@ -c $<
 
-%_$(ARCH).elf: %_$(ARCH).s
-   $(AS) -o $@ $<
-
-%_$(ARCH).elf: %_$(ARCH).S
+%_$(ARCH).o: %_$(ARCH).S
$(CC) $(CPPFLAGS) -o $@ -c $<
 
+%_$(ARCH).elf: test.ld %_$(ARCH).o
+   $(LD) -o $@ -T $^
+
 clean:
-   rm -f $(PROG) $(OBJS) $(BINS)
+   rm -f $(PROG) $(OBJS) $(BINO) $(BINE)
 
 distclean: clean
rm -f config.h Makefile.in
diff --git a/test.ld b/test.ld
new file mode 100644
index 000..eb0a76a
--- /dev/null
+++ b/test.ld
@@ -0,0 +1,12 @@
+ENTRY(start)
+
+PHDRS {
+text PT_LOAD FILEHDR PHDRS;
+}
+
+SECTIONS {
+. = SIZEOF_HEADERS;
+PROVIDE(start = .);
+.text : { *(.text) } :text
+.data : { *(.data) } :text
+}
diff --git a/test_aarch64.s b/test_aarch64.s
index f75d588..88902c6 100644
--- a/test_aarch64.s
+++ b/test_aarch64.s
@@ -80,6 +80,6 @@ fmov d31, #31.0
 /* do compare.
  * The manual says instr with bits (28,27) == 0 0 are UNALLOCATED
  */
-.int 0x5af0
+.inst 0x5af0
 /* exit test */
-.int 0x5af1
+.inst 0x5af1
diff --git a/test_arm.s b/test_arm.s
index 49552f2..62582e7 100644
--- a/test_arm.s
+++ b/test_arm.s
@@ -9,20 +9,26 @@
  * Peter Maydell (Linaro) - initial implementation
  
***/
 
+.text
+
 /* magic instruction to force ARM mode whether we were in ARM or Thumb before 
*/
-.int 0xe0004778
+.inst 0xe0004778
+
 /* Initialise the gp regs */
 add r0, pc, #4
 ldmia r0, {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r14}
-b next
+b 1f
+
 .int 0,1,2,3,4,5,6,7,8,9,10,11,12,14
-next:
+
+1:
 msr CPSR_fs, #0
+
 /* do compare.
  * The space 0xE7F___F_ is guaranteed to always UNDEF
  * and not to be allocated for insns in future architecture
  * revisions.
  */
-.int 0xe7fe5af0
+.inst 0xe7fe5af0
 /* exit test */
-.int 0xe7fe5af1
+.inst 0xe7fe5af1
diff --git a/test_i386.S b/test_i386.S
index 05344d7..2e2b090 100644
--- a/test_i386.S
+++ b/test_i386.S
@@ -13,6 +13,7 @@
 
 /* Initialise the registers to avoid spurious mismatches */
 
+.text
 #ifdef __x86_64__
 #define BASE   %rax
lea 2f(%rip), BASE
@@ -71,7 +72,8 @@
 /* exit test */
ud1 %ecx, %eax
 
-   .p2align 16
+.data
+   .balign 16
 2:
.seti, 0
.rept   256
-- 
2.34.1




[PATCH 16/17] configure: Enable loongarch64

2024-05-11 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 configure | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index 2f7c580..39275a2 100755
--- a/configure
+++ b/configure
@@ -54,6 +54,8 @@ guess_arch() {
 ARCH="arm"
 elif check_define __i386__ || check_define __x86_64__ ; then
 ARCH="i386"
+elif check_define __loongarch__ ; then
+ARCH="loongarch64"
 elif check_define __m68k__ ; then
 ARCH="m68k"
 elif check_define __powerpc64__ ; then
@@ -141,7 +143,7 @@ Some influential environment variables:
prefixed with the given string.
 
   ARCH force target architecture instead of trying to detect it.
-   Valid values=[arm|aarch64|m68k|ppc64|ppc64le|s390x]
+   Valid values=[arm|aarch64|loongarch64|m68k|ppc64|ppc64le|s390x]
 
   CC   C compiler command
   CFLAGS   C compiler flags
-- 
2.34.1




[PATCH 02/17] Fix load_image error check for mmap

2024-05-11 Thread Richard Henderson
mmap does not return null on failure, but MAP_FAILED.

Signed-off-by: Richard Henderson 
---
 risu.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/risu.c b/risu.c
index 36fc82a..6b6295c 100644
--- a/risu.c
+++ b/risu.c
@@ -362,10 +362,9 @@ static void load_image(const char *imgfile)
 /* Map writable because we include the memory area for store
  * testing in the image.
  */
-addr =
-mmap(0, len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd,
- 0);
-if (!addr) {
+addr = mmap(0, len, PROT_READ | PROT_WRITE | PROT_EXEC,
+MAP_PRIVATE, fd, 0);
+if (addr == MAP_FAILED) {
 perror("mmap");
 exit(EXIT_FAILURE);
 }
-- 
2.34.1




[PATCH 13/17] Use bool for reginfo_is_eq

2024-05-11 Thread Richard Henderson
The function result is more naturally boolean.

Signed-off-by: Richard Henderson 
---
 risu.h |  4 ++--
 risu_reginfo_aarch64.c |  4 ++--
 risu_reginfo_arm.c |  4 ++--
 risu_reginfo_i386.c|  4 ++--
 risu_reginfo_loongarch64.c |  4 ++--
 risu_reginfo_m68k.c| 16 
 risu_reginfo_ppc64.c   |  4 ++--
 risu_reginfo_s390x.c   |  4 ++--
 8 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/risu.h b/risu.h
index aa8cc22..4203178 100644
--- a/risu.h
+++ b/risu.h
@@ -117,8 +117,8 @@ uintptr_t get_pc(struct reginfo *ri);
 /* initialize structure from a ucontext */
 void reginfo_init(struct reginfo *ri, ucontext_t *uc, void *siaddr);
 
-/* return 1 if structs are equal, 0 otherwise. */
-int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2);
+/* return true if structs are equal, false otherwise. */
+bool reginfo_is_eq(struct reginfo *r1, struct reginfo *r2);
 
 /* print reginfo state to a stream */
 void reginfo_dump(struct reginfo *ri, FILE *f);
diff --git a/risu_reginfo_aarch64.c b/risu_reginfo_aarch64.c
index 67a2999..55a9ef6 100644
--- a/risu_reginfo_aarch64.c
+++ b/risu_reginfo_aarch64.c
@@ -262,8 +262,8 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc, void 
*siaddr)
 }
 }
 
-/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
-int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
+/* reginfo_is_eq: compare the reginfo structs, returns true if equal */
+bool reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
 {
 return memcmp(r1, r2, reginfo_size(r1)) == 0;
 }
diff --git a/risu_reginfo_arm.c b/risu_reginfo_arm.c
index 0e179be..d11e666 100644
--- a/risu_reginfo_arm.c
+++ b/risu_reginfo_arm.c
@@ -155,8 +155,8 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc, void 
*siaddr)
 reginfo_init_vfp(ri, uc);
 }
 
-/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
-int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
+/* reginfo_is_eq: compare the reginfo structs, returns true if equal */
+bool reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
 {
 return memcmp(r1, r2, sizeof(*r1)) == 0;/* ok since we memset 0 */
 }
diff --git a/risu_reginfo_i386.c b/risu_reginfo_i386.c
index f4cf9a3..1c579fa 100644
--- a/risu_reginfo_i386.c
+++ b/risu_reginfo_i386.c
@@ -234,8 +234,8 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc, void 
*siaddr)
 #endif
 }
 
-/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
-int reginfo_is_eq(struct reginfo *m, struct reginfo *a)
+/* reginfo_is_eq: compare the reginfo structs, returns true if equal */
+bool reginfo_is_eq(struct reginfo *m, struct reginfo *a)
 {
 return !memcmp(m, a, sizeof(*m));
 }
diff --git a/risu_reginfo_loongarch64.c b/risu_reginfo_loongarch64.c
index 060715f..6150a40 100644
--- a/risu_reginfo_loongarch64.c
+++ b/risu_reginfo_loongarch64.c
@@ -153,8 +153,8 @@ void reginfo_init(struct reginfo *ri, ucontext_t *context, 
void *siaddr)
 }
 }
 
-/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
-int reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
+/* reginfo_is_eq: compare the reginfo structs */
+bool reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
 {
 return !memcmp(r1, r2, sizeof(*r1));
 }
diff --git a/risu_reginfo_m68k.c b/risu_reginfo_m68k.c
index a53244d..7335195 100644
--- a/risu_reginfo_m68k.c
+++ b/risu_reginfo_m68k.c
@@ -55,13 +55,13 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc, void 
*siaddr)
 }
 }
 
-/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
-int reginfo_is_eq(struct reginfo *m, struct reginfo *a)
+/* reginfo_is_eq: compare the reginfo structs, returns true if equal */
+bool reginfo_is_eq(struct reginfo *m, struct reginfo *a)
 {
 int i;
 
 if (m->gregs[R_PS] != a->gregs[R_PS]) {
-return 0;
+return false;
 }
 
 for (i = 0; i < 16; i++) {
@@ -69,27 +69,27 @@ int reginfo_is_eq(struct reginfo *m, struct reginfo *a)
 continue;
 }
 if (m->gregs[i] != a->gregs[i]) {
-return 0;
+return false;
 }
 }
 
 if (m->fpregs.f_pcr != a->fpregs.f_pcr) {
-return 0;
+return false;
 }
 
 if (m->fpregs.f_psr != a->fpregs.f_psr) {
-return 0;
+return false;
 }
 
 for (i = 0; i < 8; i++) {
 if (m->fpregs.f_fpregs[i][0] != a->fpregs.f_fpregs[i][0] ||
 m->fpregs.f_fpregs[i][1] != a->fpregs.f_fpregs[i][1] ||
 m->fpregs.f_fpregs[i][2] != a->fpregs.f_fpregs[i][2]) {
-return 0;
+return false;
 }
 }
 
-return 1;
+return true;
 }
 
 /* reginfo_dump: print state to a stream */
diff --git a/risu_reginfo_ppc64.c b/risu_reginfo_ppc64.c
index 730a565..a8e5935 100644
--- a/risu_reginfo_ppc64.c
+++ b/risu_reginfo_ppc64.c
@@ -64,8 +64,8 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc, 

[PATCH 04/17] Add --fulldump and --diffdup options

2024-05-11 Thread Richard Henderson
These allow the inspection of the trace files.

Reviewed-by: Peter Maydell 
Signed-off-by: Richard Henderson 
---
 risu.c | 117 +
 1 file changed, 102 insertions(+), 15 deletions(-)

diff --git a/risu.c b/risu.c
index 9c31b8c..c28b4a5 100644
--- a/risu.c
+++ b/risu.c
@@ -483,23 +483,101 @@ static int apprentice(void)
 }
 }
 
-static int ismaster;
+static int dump_trace(bool isfull)
+{
+RisuResult res;
+int tick = 0;
+
+while (1) {
+struct reginfo *this_ri;
+
+this_ri = [tick & 1];
+res = recv_register_info(this_ri);
+
+switch (res) {
+case RES_OK:
+switch (header.risu_op) {
+case OP_COMPARE:
+case OP_TESTEND:
+case OP_SIGILL:
+printf("%s: (pc %#lx)\n", op_name(header.risu_op),
+   (unsigned long)header.pc);
+
+if (isfull || tick == 0) {
+reginfo_dump(this_ri, stdout);
+} else {
+struct reginfo *prev_ri = [(tick - 1) & 1];
+
+if (reginfo_is_eq(prev_ri, this_ri)) {
+/*
+ * ??? There should never be no change -- at minimum
+ * PC should have advanced.  But for completeness...
+ */
+printf("change detail: none\n");
+} else {
+printf("change detail (prev : next):\n");
+reginfo_dump_mismatch(prev_ri, this_ri, stdout);
+}
+}
+putchar('\n');
+if (header.risu_op == OP_TESTEND) {
+return EXIT_SUCCESS;
+}
+tick++;
+break;
+
+case OP_COMPAREMEM:
+/* TODO: Dump 8k of data? */
+/* fall through */
+default:
+printf("%s\n", op_name(header.risu_op));
+break;
+}
+break;
+
+case RES_BAD_IO:
+fprintf(stderr, "I/O error\n");
+return EXIT_FAILURE;
+case RES_BAD_MAGIC:
+fprintf(stderr, "Unexpected magic number: %#08x\n", header.magic);
+return EXIT_FAILURE;
+case RES_BAD_SIZE:
+fprintf(stderr, "Unexpected payload size: %u\n", header.size);
+return EXIT_FAILURE;
+case RES_BAD_OP:
+fprintf(stderr, "Unexpected opcode: %d\n", header.risu_op);
+return EXIT_FAILURE;
+default:
+fprintf(stderr, "Unexpected recv result %d\n", res);
+return EXIT_FAILURE;
+}
+}
+}
+
+enum {
+DO_APPRENTICE,
+DO_MASTER,
+DO_FULLDUMP,
+DO_DIFFDUMP,
+};
+
+static int operation = DO_APPRENTICE;
 
 static void usage(void)
 {
 fprintf(stderr,
-"Usage: risu [--master] [--host ] [--port ] "
-"\n\n");
-fprintf(stderr,
-"Run through the pattern file verifying each instruction\n");
-fprintf(stderr, "between master and apprentice risu processes.\n\n");
-fprintf(stderr, "Options:\n");
-fprintf(stderr, "  --master  Be the master (server)\n");
-fprintf(stderr, "  -t, --trace=FILE  Record/playback " TRACE_TYPE " trace 
file\n");
-fprintf(stderr,
-"  -h, --host=HOST   Specify master host machine (apprentice only)"
-"\n");
-fprintf(stderr,
+"Usage: risu [--master|--fulldump|--diffdump]\n"
+"[--host ] [--port ] \n"
+"\n"
+"Run through the pattern file verifying each instruction\n"
+"between master and apprentice risu processes.\n"
+"\n"
+"Options:\n"
+"  --master  Be the master (server)\n"
+"  --fulldumpDump each record\n"
+"  --diffdumpDump difference between each record\n"
+"  -t, --trace=FILE  Record/playback " TRACE_TYPE " trace file\n"
+"  -h, --host=HOST   Specify master host machine\n"
 "  -p, --port=PORT   Specify the port to connect to/listen on "
 "(default 9191)\n");
 if (arch_extra_help) {
@@ -511,7 +589,9 @@ static struct option * setup_options(char **short_opts)
 {
 static struct option default_longopts[] = {
 {"help", no_argument, 0, '?'},
-{"master", no_argument, , 1},
+{"master", no_argument, , DO_MASTER},
+{"fulldump", no_argument, , DO_FULLDUMP},
+{"diffdump", no_argument, , DO_DIFFDUMP},
 {"host", required_argument, 0, 'h'},
 {"port", required_argument, 0, 'p'},
 {"trace", required_argument, 0, 't'},
@@ -519,7 +599,7 @@ static struct option * setup_options(char **short_opts)
 };
 struct option *lopts = _longopts[0];
 
-*short_opts = "h:p:t:";
+*short_opts = "d:h:p:t:";
 
 

[PATCH 07/17] ppc64: Compare all bits of CCR

2024-05-11 Thread Richard Henderson
There are 32 bits in this register, and they are all valid
comparision destinations.

Signed-off-by: Richard Henderson 
---
 risu_reginfo_ppc64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/risu_reginfo_ppc64.c b/risu_reginfo_ppc64.c
index 67ea3ce..109b87b 100644
--- a/risu_reginfo_ppc64.c
+++ b/risu_reginfo_ppc64.c
@@ -78,7 +78,7 @@ int reginfo_is_eq(struct reginfo *m, struct reginfo *a)
 return 0;
 }
 
-if ((m->gregs[CCR] & 0x10) != (a->gregs[CCR] & 0x10)) {
+if (m->gregs[CCR] != a->gregs[CCR]) {
 return 0;
 }
 
-- 
2.34.1




[PATCH 01/17] ppc64: Fix include order

2024-05-11 Thread Richard Henderson
Signed-off-by: Richard Henderson 
---
 risu_ppc64.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/risu_ppc64.c b/risu_ppc64.c
index 9df8d58..62cf6aa 100644
--- a/risu_ppc64.c
+++ b/risu_ppc64.c
@@ -11,9 +11,8 @@
  * based on Peter Maydell's risu_arm.c
  */
 
-#include 
-
 #include "risu.h"
+#include 
 
 void advance_pc(void *vuc)
 {
-- 
2.34.1




[PATCH RESEND] target/riscv/cpu.c: fix Zvkb extension config

2024-05-11 Thread Yangyu Chen
This code has a typo that writes zvkb to zvkg, causing users can't
enable zvkb through the config. This patch gets this fixed.

Signed-off-by: Yangyu Chen 
Fixes: ea61ef7097d0 ("target/riscv: Move vector crypto extensions to 
riscv_cpu_extensions")
Reviewed-by: LIU Zhiwei 
---
 target/riscv/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index eb1a2e7d6d..13cd34adbd 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1535,7 +1535,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 /* Vector cryptography extensions */
 MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
 MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
-MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
+MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
 MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
 MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
 MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),
-- 
2.43.0




Re: [PATCH 1/1] tests/fp/meson: don't build fp-bench test if fenv.h is missing

2024-05-11 Thread Dario Binacchi
On Sat, May 11, 2024 at 12:25 PM Richard Henderson
 wrote:
>
> On 5/11/24 12:11, Dario Binacchi wrote:
> > Gentle ping.
>
> Gentle reminder that I strongly suspect that your buildroot is corrupt.
> There *should* be a  present.

I don't think so. In fact, the patch has already been merged into Buildroot:
https://patchwork.ozlabs.org/project/buildroot/patch/20240502072327.741463-1-dario.binac...@amarulasolutions.com/

As mentioned earlier:
"The fenv support is not enabled in our default uClibc configurations"
https://lists.buildroot.org/pipermail/buildroot/2013-May/072440.html

Thanks and regards,
Dario


>
>
> r~
>
> >
> > Thanks,
> > Dario
> >
> > On Wed, May 1, 2024 at 4:17 PM Dario Binacchi
> >  wrote:
> >>
> >> Hello Richard,
> >>
> >> On Wed, May 1, 2024 at 3:31 PM Richard Henderson
> >>  wrote:
> >>>
> >>> On 5/1/24 05:18, Dario Binacchi wrote:
>  Hello Richard,
> 
>  On Tue, Apr 30, 2024 at 8:15 PM Richard Henderson
>   wrote:
> >
> > On 4/30/24 09:47, Dario Binacchi wrote:
> >> The fp-bench test (i. e. tests/fp/fp-bench.c) use fenv.h that is not
> >> always provided by the libc (uClibc). The patch disables its 
> >> compilation
> >> in case the header is not available.
> >
> > Since uclibc has had fenv.h since 2008, are you sure this isn't simply 
> > a case of a corrupt
> > installation?
> 
> >
> >
> > r~
> 
>  It's not an issue of corrupted installation but rather of compilation:
> >>>
> >>> Installation of your cross-compiler or buildroot, I mean.
> >>>
> 
>  ../tests/fp/fp-bench.c:15:10: fatal error: fenv.h: No such file or 
>  directory
>   15 | #include 
>  |  ^~~~
>  compilation terminated.
> >>>
> >>> Yes, yes.  However,  is present in uclibc-ng, and has been since 
> >>> 2008.
> >>> So *why* is fenv.h not present?
> >>
> >> I found the fenv.h files here:
> >> out/emulator/host/opt/ext-toolchain/i686-buildroot-linux-uclibc/include/c++/11.3.0/tr1/fenv.h
> >> out/emulator/host/opt/ext-toolchain/i686-buildroot-linux-uclibc/include/c++/11.3.0/fenv.h
> >>
> >> But the compiler expects them in:
> >> out/emulator/host/i686-buildroot-linux-uclibc/sysroot/usr/include/
> >>
> >> So, I think that the fenv support has not been enabled in uClibc
> >> configuration of Buildroot.
> >>
> >> Thanks and regards,
> >> Dario
> >>
> >>>
> >>>
> >>> r~
> >>
> >>
> >>
> >> --
> >>
> >> Dario Binacchi
> >>
> >> Senior Embedded Linux Developer
> >>
> >> dario.binac...@amarulasolutions.com
> >>
> >> __
> >>
> >>
> >> Amarula Solutions SRL
> >>
> >> Via Le Canevare 30, 31100 Treviso, Veneto, IT
> >>
> >> T. +39 042 243 5310
> >> i...@amarulasolutions.com
> >>
> >> www.amarulasolutions.com
> >
> >
> >
>


-- 

Dario Binacchi

Senior Embedded Linux Developer

dario.binac...@amarulasolutions.com

__


Amarula Solutions SRL

Via Le Canevare 30, 31100 Treviso, Veneto, IT

T. +39 042 243 5310
i...@amarulasolutions.com

www.amarulasolutions.com



Re: hw/usb/hcd-ohci: Fix #1510, #303: pid not IN or OUT

2024-05-11 Thread Peter Maydell
On Thu, 9 May 2024 at 19:17, Cord Amfmgm  wrote:
>
>
>
> On Thu, May 9, 2024 at 12:48 PM Peter Maydell  
> wrote:
>>
>> On Wed, 8 May 2024 at 16:29, Cord Amfmgm  wrote:
>> > On Wed, May 8, 2024 at 3:45 AM Thomas Huth  wrote:
>> >>
>> >> Your Signed-off-by line does not match the From: line ... could you please
>> >> fix this? (see
>> >> https://www.qemu.org/docs/master/devel/submitting-a-patch.html#patch-emails-must-include-a-signed-off-by-line
>> >> , too)
>> >
>> >
>> > I'll submit the new patch request with my pseudonym in the From: and 
>> > Signed-off-by: lines, per your request. Doesn't matter to me. However, 
>> > this arises simply because I don't give gmail my real name - 
>> > https://en.wikipedia.org/wiki/Nymwars
>>
>> I'm confused now. Of the two names you've used in this
>> patch (Cord Amfmgm and David Hubbard), are they both
>> pseudonyms, or is one a pseudonym and one your real name?
>>
>
> Hi Peter,
>
> I am attempting to submit a small patch. For context, I'm getting broader 
> attention now because apparently OHCI is one of the less used components of 
> qemu and maybe the review process was taking a while. That's relevant because 
> I wasn't able to get prompt feedback and am now choosing what appears to be 
> the most expeditious approach -- all I want is to get this patch done and be 
> out of your hair. If Thomas Huth wants me to use a consistent name, have I 
> not complied? Are you asking out of curiosity or is there a valid reason why 
> I should answer your question in order to get the patch submitted? Would you 
> like to have a friendly chat over virtual coffee sometime (but off-list)?
>
> If you could please clarify I'm sure the answer is an easy one.

I'm asking because our basic expected position is "commits
are from the submitter's actual name, not a pseudonym". Obviously
we can't tell if people use a consistent plausible looking
pseudonym whether that corresponds to their real-world name
or not, but if you have a real name you're happy to attach
to this patch and are merely using a pseudonym for Google
email, then the resubmit of this patch didn't seem to me
to do that. i.e. I was expecting the change to be "make the
patch From: match the Signed-off-by line", not "make the
Signed-off-by line match the patch From:". (For avoidance
of doubt, we don't care about the email From: line, which
is distinct from the commit message From: i.e. author.)
So I was essentially asking "did you mean to do this, or did
you misunderstand what we were asking for?".

On the question of the actual patch, I'll try to get to it
if Gerd doesn't first (though I have a conference next week
so it might be the week after). The main thing I need to chase
down is whether it's OK to call usb_packet_addbuf() with a
zero length or not.

thanks
-- PMM



Re: [PATCH 1/1] tests/fp/meson: don't build fp-bench test if fenv.h is missing

2024-05-11 Thread Richard Henderson

On 5/11/24 12:11, Dario Binacchi wrote:

Gentle ping.


Gentle reminder that I strongly suspect that your buildroot is corrupt.
There *should* be a  present.


r~



Thanks,
Dario

On Wed, May 1, 2024 at 4:17 PM Dario Binacchi
 wrote:


Hello Richard,

On Wed, May 1, 2024 at 3:31 PM Richard Henderson
 wrote:


On 5/1/24 05:18, Dario Binacchi wrote:

Hello Richard,

On Tue, Apr 30, 2024 at 8:15 PM Richard Henderson
 wrote:


On 4/30/24 09:47, Dario Binacchi wrote:

The fp-bench test (i. e. tests/fp/fp-bench.c) use fenv.h that is not
always provided by the libc (uClibc). The patch disables its compilation
in case the header is not available.


Since uclibc has had fenv.h since 2008, are you sure this isn't simply a case 
of a corrupt
installation?





r~


It's not an issue of corrupted installation but rather of compilation:


Installation of your cross-compiler or buildroot, I mean.



../tests/fp/fp-bench.c:15:10: fatal error: fenv.h: No such file or directory
 15 | #include 
|  ^~~~
compilation terminated.


Yes, yes.  However,  is present in uclibc-ng, and has been since 2008.
So *why* is fenv.h not present?


I found the fenv.h files here:
out/emulator/host/opt/ext-toolchain/i686-buildroot-linux-uclibc/include/c++/11.3.0/tr1/fenv.h
out/emulator/host/opt/ext-toolchain/i686-buildroot-linux-uclibc/include/c++/11.3.0/fenv.h

But the compiler expects them in:
out/emulator/host/i686-buildroot-linux-uclibc/sysroot/usr/include/

So, I think that the fenv support has not been enabled in uClibc
configuration of Buildroot.

Thanks and regards,
Dario




r~




--

Dario Binacchi

Senior Embedded Linux Developer

dario.binac...@amarulasolutions.com

__


Amarula Solutions SRL

Via Le Canevare 30, 31100 Treviso, Veneto, IT

T. +39 042 243 5310
i...@amarulasolutions.com

www.amarulasolutions.com









[PATCH v9 5/6] target/riscv: Update address modify functions to take into account pointer masking

2024-05-11 Thread Alexey Baturo
From: Alexey Baturo 

Signed-off-by: Alexey Baturo 

Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/translate.c | 22 --
 target/riscv/vector_helper.c | 13 +
 2 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 3f578d6dd8..da46e636f8 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -580,8 +580,10 @@ static TCGv get_address(DisasContext *ctx, int rs1, int 
imm)
 TCGv src1 = get_gpr(ctx, rs1, EXT_NONE);
 
 tcg_gen_addi_tl(addr, src1, imm);
-if (get_address_xl(ctx) == MXL_RV32) {
-tcg_gen_ext32u_tl(addr, addr);
+if (ctx->addr_signed) {
+tcg_gen_sextract_tl(addr, addr, 0, ctx->addr_width);
+} else {
+tcg_gen_extract_tl(addr, addr, 0, ctx->addr_width);
 }
 
 return addr;
@@ -594,8 +596,10 @@ static TCGv get_address_indexed(DisasContext *ctx, int 
rs1, TCGv offs)
 TCGv src1 = get_gpr(ctx, rs1, EXT_NONE);
 
 tcg_gen_add_tl(addr, src1, offs);
-if (get_xl(ctx) == MXL_RV32) {
-tcg_gen_ext32u_tl(addr, addr);
+if (ctx->addr_signed) {
+tcg_gen_sextract_tl(addr, addr, 0, ctx->addr_width);
+} else {
+tcg_gen_extract_tl(addr, addr, 0, ctx->addr_width);
 }
 return addr;
 }
@@ -1188,8 +1192,14 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
 ctx->address_xl = FIELD_EX32(tb_flags, TB_FLAGS, AXL);
 ctx->cs = cs;
-ctx->addr_width = 0;
-ctx->addr_signed = false;
+if (get_xl(ctx) == MXL_RV32) {
+ctx->addr_width = 32;
+ctx->addr_signed = false;
+} else {
+int pm_pmm = FIELD_EX32(tb_flags, TB_FLAGS, PM_PMM);
+ctx->addr_width = 64 - riscv_pm_get_pmlen(pm_pmm);
+ctx->addr_signed = FIELD_EX32(tb_flags, TB_FLAGS, PM_SIGNEXTEND);
+}
 ctx->ztso = cpu->cfg.ext_ztso;
 ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
 ctx->zero = tcg_constant_tl(0);
diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
index 39ba2a09dd..28861cc509 100644
--- a/target/riscv/vector_helper.c
+++ b/target/riscv/vector_helper.c
@@ -104,6 +104,19 @@ static inline uint32_t vext_max_elems(uint32_t desc, 
uint32_t log2_esz)
 
 static inline target_ulong adjust_addr(CPURISCVState *env, target_ulong addr)
 {
+RISCVPmPmm pmm = riscv_pm_get_pmm(env);
+if (pmm == PMM_FIELD_DISABLED) {
+return addr;
+}
+int pmlen = riscv_pm_get_pmlen(pmm);
+bool signext = riscv_cpu_virt_mem_enabled(env);
+addr = addr << pmlen;
+/* sign/zero extend masked address by N-1 bit */
+if (signext) {
+addr = (target_long)addr >> pmlen;
+} else {
+addr = addr >> pmlen;
+}
 return addr;
 }
 
-- 
2.34.1




[PATCH v9 4/6] target/riscv: Add pointer masking tb flags

2024-05-11 Thread Alexey Baturo
From: Alexey Baturo 

Signed-off-by: Alexey Baturo 

Reviewed-by: Richard Henderson 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h| 3 +++
 target/riscv/cpu_helper.c | 3 +++
 target/riscv/translate.c  | 5 +
 3 files changed, 11 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 9cac723b19..bbf3a0f64e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -564,6 +564,9 @@ FIELD(TB_FLAGS, ITRIGGER, 20, 1)
 FIELD(TB_FLAGS, VIRT_ENABLED, 21, 1)
 FIELD(TB_FLAGS, PRIV, 22, 2)
 FIELD(TB_FLAGS, AXL, 24, 2)
+/* If pointer masking should be applied and address sign extended */
+FIELD(TB_FLAGS, PM_PMM, 26, 2)
+FIELD(TB_FLAGS, PM_SIGNEXTEND, 28, 1)
 
 #ifdef TARGET_RISCV32
 #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index e4a127ca84..3f2473bd73 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -68,6 +68,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
 RISCVCPU *cpu = env_archcpu(env);
 RISCVExtStatus fs, vs;
 uint32_t flags = 0;
+bool pm_signext = riscv_cpu_virt_mem_enabled(env);
 
 *pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
 *cs_base = 0;
@@ -138,6 +139,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
 flags = FIELD_DP32(flags, TB_FLAGS, VS, vs);
 flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
 flags = FIELD_DP32(flags, TB_FLAGS, AXL, cpu_address_xl(env));
+flags = FIELD_DP32(flags, TB_FLAGS, PM_PMM, riscv_pm_get_pmm(env));
+flags = FIELD_DP32(flags, TB_FLAGS, PM_SIGNEXTEND, pm_signext);
 
 *pflags = flags;
 }
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index e5b339b1fa..3f578d6dd8 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -103,6 +103,9 @@ typedef struct DisasContext {
 bool vl_eq_vlmax;
 CPUState *cs;
 TCGv zero;
+/* actual address width */
+uint8_t addr_width;
+bool addr_signed;
 /* Ztso */
 bool ztso;
 /* Use icount trigger for native debug */
@@ -1185,6 +1188,8 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
 ctx->address_xl = FIELD_EX32(tb_flags, TB_FLAGS, AXL);
 ctx->cs = cs;
+ctx->addr_width = 0;
+ctx->addr_signed = false;
 ctx->ztso = cpu->cfg.ext_ztso;
 ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
 ctx->zero = tcg_constant_tl(0);
-- 
2.34.1




[PATCH v9 1/6] target/riscv: Remove obsolete pointer masking extension code.

2024-05-11 Thread Alexey Baturo
From: Alexey Baturo 

Zjpm v0.8 is almost frozen and it's much simplier compared to the existing one:
The newer version doesn't allow to specify custom mask or base for masking.
Instead it allows only certain options for masking top bits.

Signed-off-by: Alexey Baturo 

Acked-by: Alistair Francis 
---
 target/riscv/cpu.c   |  13 +-
 target/riscv/cpu.h   |  30 +---
 target/riscv/cpu_bits.h  |  87 --
 target/riscv/cpu_helper.c|  52 --
 target/riscv/csr.c   | 326 ---
 target/riscv/machine.c   |  14 +-
 target/riscv/tcg/tcg-cpu.c   |   5 +-
 target/riscv/translate.c |  27 +--
 target/riscv/vector_helper.c |   2 +-
 9 files changed, 13 insertions(+), 543 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a74f0eb29c..1e350e9bd8 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -42,7 +42,7 @@
 /* RISC-V CPU definitions */
 static const char riscv_single_letter_exts[] = "IEMAFDQCBPVH";
 const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV,
-  RVC, RVS, RVU, RVH, RVJ, RVG, RVB, 0};
+  RVC, RVS, RVU, RVH, RVG, RVB, 0};
 
 /*
  * From vector_helper.c
@@ -795,13 +795,6 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, 
int flags)
 CSR_MSCRATCH,
 CSR_SSCRATCH,
 CSR_SATP,
-CSR_MMTE,
-CSR_UPMBASE,
-CSR_UPMMASK,
-CSR_SPMBASE,
-CSR_SPMMASK,
-CSR_MPMBASE,
-CSR_MPMMASK,
 };
 
 for (i = 0; i < ARRAY_SIZE(dump_csrs); ++i) {
@@ -981,8 +974,6 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType 
type)
 }
 i++;
 }
-/* mmte is supposed to have pm.current hardwired to 1 */
-env->mmte |= (EXT_STATUS_INITIAL | MMTE_M_PM_CURRENT);
 
 /*
  * Bits 10, 6, 2 and 12 of mideleg are read only 1 when the Hypervisor
@@ -1004,7 +995,6 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType 
type)
 pmp_unlock_entries(env);
 #endif
 env->xl = riscv_cpu_mxl(env);
-riscv_cpu_update_mask(env);
 cs->exception_index = RISCV_EXCP_NONE;
 env->load_res = -1;
 set_default_nan_mode(1, >fp_status);
@@ -1395,7 +1385,6 @@ static const MISAExtInfo misa_ext_info_arr[] = {
 MISA_EXT_INFO(RVS, "s", "Supervisor-level instructions"),
 MISA_EXT_INFO(RVU, "u", "User-level instructions"),
 MISA_EXT_INFO(RVH, "h", "Hypervisor"),
-MISA_EXT_INFO(RVJ, "x-j", "Dynamic translated languages"),
 MISA_EXT_INFO(RVV, "v", "Vector operations"),
 MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
 MISA_EXT_INFO(RVB, "x-b", "Bit manipulation (Zba_Zbb_Zbs)")
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index e0dd1828b5..232521bb87 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -66,7 +66,6 @@ typedef struct CPUArchState CPURISCVState;
 #define RVS RV('S')
 #define RVU RV('U')
 #define RVH RV('H')
-#define RVJ RV('J')
 #define RVG RV('G')
 #define RVB RV('B')
 
@@ -393,17 +392,6 @@ struct CPUArchState {
 /* True if in debugger mode.  */
 bool debugger;
 
-/*
- * CSRs for PointerMasking extension
- */
-target_ulong mmte;
-target_ulong mpmmask;
-target_ulong mpmbase;
-target_ulong spmmask;
-target_ulong spmbase;
-target_ulong upmmask;
-target_ulong upmbase;
-
 /* CSRs for execution environment configuration */
 uint64_t menvcfg;
 uint64_t mstateen[SMSTATEEN_MAX_COUNT];
@@ -412,9 +400,6 @@ struct CPUArchState {
 target_ulong senvcfg;
 uint64_t henvcfg;
 #endif
-target_ulong cur_pmmask;
-target_ulong cur_pmbase;
-
 /* Fields from here on are preserved across CPU reset. */
 QEMUTimer *stimer; /* Internal timer for S-mode interrupt */
 QEMUTimer *vstimer; /* Internal timer for VS-mode interrupt */
@@ -563,16 +548,14 @@ FIELD(TB_FLAGS, VSTART_EQ_ZERO, 15, 1)
 /* The combination of MXL/SXL/UXL that applies to the current cpu mode. */
 FIELD(TB_FLAGS, XL, 16, 2)
 /* If PointerMasking should be applied */
-FIELD(TB_FLAGS, PM_MASK_ENABLED, 18, 1)
-FIELD(TB_FLAGS, PM_BASE_ENABLED, 19, 1)
-FIELD(TB_FLAGS, VTA, 20, 1)
-FIELD(TB_FLAGS, VMA, 21, 1)
+FIELD(TB_FLAGS, VTA, 18, 1)
+FIELD(TB_FLAGS, VMA, 19, 1)
 /* Native debug itrigger */
-FIELD(TB_FLAGS, ITRIGGER, 22, 1)
+FIELD(TB_FLAGS, ITRIGGER, 20, 1)
 /* Virtual mode enabled */
-FIELD(TB_FLAGS, VIRT_ENABLED, 23, 1)
-FIELD(TB_FLAGS, PRIV, 24, 2)
-FIELD(TB_FLAGS, AXL, 26, 2)
+FIELD(TB_FLAGS, VIRT_ENABLED, 21, 1)
+FIELD(TB_FLAGS, PRIV, 22, 2)
+FIELD(TB_FLAGS, AXL, 24, 2)
 
 #ifdef TARGET_RISCV32
 #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
@@ -705,7 +688,6 @@ static inline uint32_t vext_get_vlmax(uint32_t vlenb, 
uint32_t vsew,
 void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
   uint64_t *cs_base, uint32_t *pflags);
 
-void riscv_cpu_update_mask(CPURISCVState *env);
 bool 

[PATCH v9 6/6] target/riscv: Enable updates for pointer masking variables and thus enable pointer masking extension

2024-05-11 Thread Alexey Baturo
From: Alexey Baturo 

Signed-off-by: Alexey Baturo 

Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1e350e9bd8..b3b3a6275f 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -192,6 +192,9 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval),
 ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
 ISA_EXT_DATA_ENTRY(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt),
+ISA_EXT_DATA_ENTRY(ssnpm, PRIV_VERSION_1_12_0, ext_ssnpm),
+ISA_EXT_DATA_ENTRY(smnpm, PRIV_VERSION_1_12_0, ext_smnpm),
+ISA_EXT_DATA_ENTRY(smmpm, PRIV_VERSION_1_12_0, ext_smmpm),
 ISA_EXT_DATA_ENTRY(xtheadba, PRIV_VERSION_1_11_0, ext_xtheadba),
 ISA_EXT_DATA_ENTRY(xtheadbb, PRIV_VERSION_1_11_0, ext_xtheadbb),
 ISA_EXT_DATA_ENTRY(xtheadbs, PRIV_VERSION_1_11_0, ext_xtheadbs),
@@ -1565,6 +1568,11 @@ const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
 
 /* These are experimental so mark with 'x-' */
 const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
+/* Zjpm v0.8 extensions */
+MULTI_EXT_CFG_BOOL("x-ssnpm", ext_ssnpm, false),
+MULTI_EXT_CFG_BOOL("x-smnpm", ext_smnpm, false),
+MULTI_EXT_CFG_BOOL("x-smmpm", ext_smmpm, false),
+
 DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
2.34.1




[PATCH v9 3/6] target/riscv: Add helper functions to calculate current number of masked bits for pointer masking

2024-05-11 Thread Alexey Baturo
From: Alexey Baturo 

Signed-off-by: Alexey Baturo 

Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h|  5 
 target/riscv/cpu_helper.c | 58 +++
 2 files changed, 63 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 52b6ba73c8..9cac723b19 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -698,8 +698,13 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
 
 bool riscv_cpu_is_32bit(RISCVCPU *cpu);
 
+bool riscv_cpu_virt_mem_enabled(CPURISCVState *env);
+RISCVPmPmm riscv_pm_get_pmm(CPURISCVState *env);
+int riscv_pm_get_pmlen(RISCVPmPmm pmm);
+
 RISCVException riscv_csrr(CPURISCVState *env, int csrno,
   target_ulong *ret_value);
+
 RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask);
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index bf58350669..e4a127ca84 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -142,6 +142,64 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
 *pflags = flags;
 }
 
+RISCVPmPmm riscv_pm_get_pmm(CPURISCVState *env)
+{
+int pmm = 0;
+#ifndef CONFIG_USER_ONLY
+int priv_mode = cpu_address_mode(env);
+/* Get current PMM field */
+switch (priv_mode) {
+case PRV_M:
+pmm = riscv_cpu_cfg(env)->ext_smmpm ?
+  get_field(env->mseccfg, MSECCFG_PMM) : PMM_FIELD_DISABLED;
+break;
+case PRV_S:
+pmm = riscv_cpu_cfg(env)->ext_smnpm ?
+  get_field(env->menvcfg, MENVCFG_PMM) : PMM_FIELD_DISABLED;
+break;
+case PRV_U:
+pmm = riscv_cpu_cfg(env)->ext_ssnpm ?
+  get_field(env->senvcfg, SENVCFG_PMM) : PMM_FIELD_DISABLED;
+break;
+default:
+g_assert_not_reached();
+}
+#endif
+return pmm;
+}
+
+bool riscv_cpu_virt_mem_enabled(CPURISCVState *env)
+{
+bool virt_mem_en = false;
+#ifndef CONFIG_USER_ONLY
+int satp_mode = 0;
+int priv_mode = cpu_address_mode(env);
+/* Get current PMM field */
+if (riscv_cpu_mxl(env) == MXL_RV32) {
+satp_mode = get_field(env->satp, SATP32_MODE);
+} else {
+satp_mode = get_field(env->satp, SATP64_MODE);
+}
+virt_mem_en = ((satp_mode != VM_1_10_MBARE) && (priv_mode != PRV_M));
+#endif
+return virt_mem_en;
+}
+
+int riscv_pm_get_pmlen(RISCVPmPmm pmm)
+{
+switch (pmm) {
+case PMM_FIELD_DISABLED:
+return 0;
+case PMM_FIELD_PMLEN7:
+return 7;
+case PMM_FIELD_PMLEN16:
+return 16;
+default:
+g_assert_not_reached();
+}
+return -1;
+}
+
 #ifndef CONFIG_USER_ONLY
 
 /*
-- 
2.34.1




Re: [PATCH 1/1] tests/fp/meson: don't build fp-bench test if fenv.h is missing

2024-05-11 Thread Dario Binacchi
Gentle ping.

Thanks,
Dario

On Wed, May 1, 2024 at 4:17 PM Dario Binacchi
 wrote:
>
> Hello Richard,
>
> On Wed, May 1, 2024 at 3:31 PM Richard Henderson
>  wrote:
> >
> > On 5/1/24 05:18, Dario Binacchi wrote:
> > > Hello Richard,
> > >
> > > On Tue, Apr 30, 2024 at 8:15 PM Richard Henderson
> > >  wrote:
> > >>
> > >> On 4/30/24 09:47, Dario Binacchi wrote:
> > >>> The fp-bench test (i. e. tests/fp/fp-bench.c) use fenv.h that is not
> > >>> always provided by the libc (uClibc). The patch disables its compilation
> > >>> in case the header is not available.
> > >>
> > >> Since uclibc has had fenv.h since 2008, are you sure this isn't simply a 
> > >> case of a corrupt
> > >> installation?
> > >
> > >>
> > >>
> > >> r~
> > >
> > > It's not an issue of corrupted installation but rather of compilation:
> >
> > Installation of your cross-compiler or buildroot, I mean.
> >
> > >
> > > ../tests/fp/fp-bench.c:15:10: fatal error: fenv.h: No such file or 
> > > directory
> > > 15 | #include 
> > >|  ^~~~
> > > compilation terminated.
> >
> > Yes, yes.  However,  is present in uclibc-ng, and has been since 
> > 2008.
> > So *why* is fenv.h not present?
>
> I found the fenv.h files here:
> out/emulator/host/opt/ext-toolchain/i686-buildroot-linux-uclibc/include/c++/11.3.0/tr1/fenv.h
> out/emulator/host/opt/ext-toolchain/i686-buildroot-linux-uclibc/include/c++/11.3.0/fenv.h
>
> But the compiler expects them in:
> out/emulator/host/i686-buildroot-linux-uclibc/sysroot/usr/include/
>
> So, I think that the fenv support has not been enabled in uClibc
> configuration of Buildroot.
>
> Thanks and regards,
> Dario
>
> >
> >
> > r~
>
>
>
> --
>
> Dario Binacchi
>
> Senior Embedded Linux Developer
>
> dario.binac...@amarulasolutions.com
>
> __
>
>
> Amarula Solutions SRL
>
> Via Le Canevare 30, 31100 Treviso, Veneto, IT
>
> T. +39 042 243 5310
> i...@amarulasolutions.com
>
> www.amarulasolutions.com



-- 

Dario Binacchi

Senior Embedded Linux Developer

dario.binac...@amarulasolutions.com

__


Amarula Solutions SRL

Via Le Canevare 30, 31100 Treviso, Veneto, IT

T. +39 042 243 5310
i...@amarulasolutions.com

www.amarulasolutions.com



[PATCH v9 0/6] Pointer Masking update for Zjpm v1.0

2024-05-11 Thread Alexey Baturo
From: Alexey Baturo 

Hi,

It looks like Pointer Masking spec has reached v1.0 and been frozen,
rebasing on riscv-to-apply.next branch and resubmitting patches. 

Thanks.

[v8]:
Rebasing patches on current qemu branch and resubmitting them.


[v7]:
I'm terribly sorry, but previous rebase went wrong and somehow I missed it.
This time I double-checked rebased version.
This patch series is properly rebased on 
https://github.com/alistair23/qemu/tree/riscv-to-apply.next 

[v6]:
This patch series is rebased on 
https://github.com/alistair23/qemu/tree/riscv-to-apply.next 

[v5]:
This patch series targets Zjpm v0.8 extension.
The spec itself could be found here: 
https://github.com/riscv/riscv-j-extension/blob/8088461d8d66a7676872b61c908cbeb7cf5c5d1d/zjpm-spec.pdf
This patch series is updated after the suggested comments:
- add "x-" to the extension names to indicate experimental

[v4]:
Patch series updated after the suggested comments:
- removed J-letter extension as it's unused
- renamed and fixed function to detect if address should be sign-extended
- zeroed unused context variables and moved computation logic to another patch
- bumped pointer masking version_id and minimum_version_id by 1

[v3]:
There patches are updated after Richard's comments:
- moved new tb flags to the end
- used tcg_gen_(s)extract to get the final address
- properly handle CONFIG_USER_ONLY

[v2]:
As per Richard's suggestion I made pmm field part of tb_flags.
It allowed to get rid of global variable to store pmlen.
Also it allowed to simplify all the machinery around it.

[v1]:
It looks like Zjpm v0.8 is almost frozen and we don't expect it change 
drastically anymore.
Compared to the original implementation with explicit base and mask CSRs, we 
now only have
several fixed options for number of masked bits which are set using existing 
CSRs.
The changes have been tested with handwritten assembly tests and LLVM HWASAN
test suite.

Alexey Baturo (6):
  target/riscv: Remove obsolete pointer masking  extension code.
  target/riscv: Add new CSR fields for S{sn,mn,m}pm extensions as part
of Zjpm v0.8
  target/riscv: Add helper functions to calculate current number of
masked bits for pointer masking
  target/riscv: Add pointer masking tb flags
  target/riscv: Update address modify functions to take into account
pointer masking
  target/riscv: Enable updates for pointer masking variables and thus
enable pointer masking extension

 target/riscv/cpu.c   |  21 +--
 target/riscv/cpu.h   |  46 +++--
 target/riscv/cpu_bits.h  |  90 +-
 target/riscv/cpu_cfg.h   |   3 +
 target/riscv/cpu_helper.c|  97 +-
 target/riscv/csr.c   | 337 ++-
 target/riscv/machine.c   |  20 +--
 target/riscv/pmp.c   |  13 +-
 target/riscv/pmp.h   |  11 +-
 target/riscv/tcg/tcg-cpu.c   |   5 +-
 target/riscv/translate.c |  46 ++---
 target/riscv/vector_helper.c |  15 +-
 12 files changed, 158 insertions(+), 546 deletions(-)

-- 
2.34.1




[PATCH v9 2/6] target/riscv: Add new CSR fields for S{sn, mn, m}pm extensions as part of Zjpm v0.8

2024-05-11 Thread Alexey Baturo
From: Alexey Baturo 

Signed-off-by: Alexey Baturo 

Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h  |  8 
 target/riscv/cpu_bits.h |  3 +++
 target/riscv/cpu_cfg.h  |  3 +++
 target/riscv/csr.c  | 11 +++
 target/riscv/machine.c  | 10 +++---
 target/riscv/pmp.c  | 13 ++---
 target/riscv/pmp.h  | 11 ++-
 7 files changed, 48 insertions(+), 11 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 232521bb87..52b6ba73c8 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -121,6 +121,14 @@ typedef enum {
 EXT_STATUS_DIRTY,
 } RISCVExtStatus;
 
+/* Enum holds PMM field values for Zjpm v0.8 extension */
+typedef enum {
+PMM_FIELD_DISABLED = 0,
+PMM_FIELD_RESERVED = 1,
+PMM_FIELD_PMLEN7   = 2,
+PMM_FIELD_PMLEN16  = 3,
+} RISCVPmPmm;
+
 #define MMU_USER_IDX 3
 
 #define MAX_RISCV_PMPS (16)
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index da16ba236a..13ce2218d1 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -708,6 +708,7 @@ typedef enum RISCVException {
 #define MENVCFG_CBIE   (3UL << 4)
 #define MENVCFG_CBCFE  BIT(6)
 #define MENVCFG_CBZE   BIT(7)
+#define MENVCFG_PMM(3ULL << 32)
 #define MENVCFG_ADUE   (1ULL << 61)
 #define MENVCFG_PBMTE  (1ULL << 62)
 #define MENVCFG_STCE   (1ULL << 63)
@@ -721,11 +722,13 @@ typedef enum RISCVException {
 #define SENVCFG_CBIE   MENVCFG_CBIE
 #define SENVCFG_CBCFE  MENVCFG_CBCFE
 #define SENVCFG_CBZE   MENVCFG_CBZE
+#define SENVCFG_PMMMENVCFG_PMM
 
 #define HENVCFG_FIOM   MENVCFG_FIOM
 #define HENVCFG_CBIE   MENVCFG_CBIE
 #define HENVCFG_CBCFE  MENVCFG_CBCFE
 #define HENVCFG_CBZE   MENVCFG_CBZE
+#define HENVCFG_PMMMENVCFG_PMM
 #define HENVCFG_ADUE   MENVCFG_ADUE
 #define HENVCFG_PBMTE  MENVCFG_PBMTE
 #define HENVCFG_STCE   MENVCFG_STCE
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index e1e4f32698..9ecdc792c5 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -120,6 +120,9 @@ struct RISCVCPUConfig {
 bool ext_ssaia;
 bool ext_sscofpmf;
 bool ext_smepmp;
+bool ext_ssnpm;
+bool ext_smnpm;
+bool ext_smmpm;
 bool rvv_ta_all_1s;
 bool rvv_ma_all_1s;
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 4b2c932564..45b548eb0b 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -530,6 +530,9 @@ static RISCVException have_mseccfg(CPURISCVState *env, int 
csrno)
 if (riscv_cpu_cfg(env)->ext_zkr) {
 return RISCV_EXCP_NONE;
 }
+if (riscv_cpu_cfg(env)->ext_smmpm) {
+return RISCV_EXCP_NONE;
+}
 
 return RISCV_EXCP_ILLEGAL_INST;
 }
@@ -2083,6 +2086,10 @@ static RISCVException write_menvcfg(CPURISCVState *env, 
int csrno,
 (cfg->ext_sstc ? MENVCFG_STCE : 0) |
 (cfg->ext_svadu ? MENVCFG_ADUE : 0);
 }
+/* Update PMM field only if the value is valid according to Zjpm v0.8 */
+if (((val & MENVCFG_PMM) >> 32) != PMM_FIELD_RESERVED) {
+mask |= MENVCFG_PMM;
+}
 env->menvcfg = (env->menvcfg & ~mask) | (val & mask);
 
 return RISCV_EXCP_NONE;
@@ -2127,6 +2134,10 @@ static RISCVException write_senvcfg(CPURISCVState *env, 
int csrno,
 target_ulong val)
 {
 uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE | SENVCFG_CBZE;
+/* Update PMM field only if the value is valid according to Zjpm v0.8 */
+if (((val & SENVCFG_PMM) >> 32) != PMM_FIELD_RESERVED) {
+mask |= SENVCFG_PMM;
+}
 RISCVException ret;
 
 ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 64ab66e332..28f373 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -152,15 +152,19 @@ static const VMStateDescription vmstate_vector = {
 
 static bool pointermasking_needed(void *opaque)
 {
-return false;
+RISCVCPU *cpu = opaque;
+return cpu->cfg.ext_ssnpm || cpu->cfg.ext_smnpm || cpu->cfg.ext_smmpm;
 }
 
 static const VMStateDescription vmstate_pointermasking = {
 .name = "cpu/pointer_masking",
-.version_id = 1,
-.minimum_version_id = 1,
+.version_id = 2,
+.minimum_version_id = 2,
 .needed = pointermasking_needed,
 .fields = (const VMStateField[]) {
+VMSTATE_UINTTL(env.mseccfg, RISCVCPU),
+VMSTATE_UINTTL(env.senvcfg, RISCVCPU),
+VMSTATE_UINTTL(env.menvcfg, RISCVCPU),
 VMSTATE_END_OF_LIST()
 }
 };
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 2a76b611a0..7ddb9dbf0b 100644
--- a/target/riscv/pmp.c

Re: [PATCH 3/4] virtio-gpu: use a VMState variant for the scanout field

2024-05-11 Thread Marc-André Lureau
Hi Peter

On Fri, May 10, 2024 at 9:33 PM Peter Xu  wrote:
>
> Hi, Marc-André,
>
> On Fri, May 10, 2024 at 12:39:34PM +0400, Marc-André Lureau wrote:
> > Since we don't have per VMSD version information on the wire, nested
> > struct versioning is quite limited and cumbersome. I am not sure it
> > can be changed without breaking the stream format, and whether it's
> > worthwhile.
>
> Right that's a major pain, and actually I just notice it..
>
> I think it'll be much, much simpler if we keep vmsd version on the wire for
> each VMSD (including struct fields), then it makes more sense to me.
>
> Then when I went back and see again the VSTRUCT thing...  I can hardly
> understand what it is doing, and also how it works at all.
>
> Look at the current only IPMI user, who has:
>
> VMSTATE_VSTRUCT_V(kcs, ISAIPMIKCSDevice, 2, vmstate_IPMIKCS,
>   IPMIKCS, 2),
>
> It is setting both vmsd version and struct_version to 2.  I can't tell why
> it matters then if anyway both of the fields are the same..
>
> When we do save(), there is:
>
> } else if (field->flags & VMS_STRUCT) {
> ret = vmstate_save_state(f, field->vmsd, curr_elem,
>  vmdesc_loop);
> } else if (field->flags & VMS_VSTRUCT) {
> ret = vmstate_save_state_v(f, field->vmsd, curr_elem,
>vmdesc_loop,
>field->struct_version_id, 
> errp);
>
> When we load():
>
> } else if (field->flags & VMS_STRUCT) {
> ret = vmstate_load_state(f, field->vmsd, curr_elem,
>  field->vmsd->version_id);
> } else if (field->flags & VMS_VSTRUCT) {
> ret = vmstate_load_state(f, field->vmsd, curr_elem,
>  field->struct_version_id);
> } else {
>
> In this case, passing in struct_version==version should have zero effect
> afaict, because the default behavior is passing in vmsd->version_id anyway.

IPMI KCS being a top-level section, the fields with an unsupported
version are filtered before reaching this code.

But since I can't see how a machine will have a specific version, it
only helps for backward migration, which is quite limited.

>
> Moreover, now I highly doubt whether the VMS_STRUCT whole thing makes sense
> at all as you mentioned.  Especially on the load side, here we should rely
> on vmstate_load_state() taking the last parameter as version_id on the
> wire.  Here we're passing in the struct's version_id or struct_version_id,
> and neither of them makes sense to me... if we miss that version_id
> information, afaiu we should simply fix it and put it on the wire..  It'll
> break migration, we may need to work that out, but I don't see a better
> way.  Keeping it like this like a nightmare to me.. :-(

Ack.

Do you think we should add a version on the wire for each VMSD? that
will likely be a format change.

>
> Irrelevant of all these mess.. For this specific problem, what I meant is
> exactly what Michael was requesting too (hopefully), I'd want to avoid
> further extending the complexity in this area.  I have a patch attached at
> last which I also tested 8.2<->9.0 bi-directional migrations and it worked
> for me when I smoked it.  Please have a look to see whether that makes
> sense and at the meantime avoid most of the tricks.

Works for me! thanks for figuring out how to get back the VirtioGPU* !

I'll send v2 with your patch.

>
> I'd also like to mention one more thing just in case this can cause some
> more attention to virtio guys..
>
> Normally I ran vmstate-static-checker.py before softfreeze, and I did it
> for 9.0 too without seeing this problem.  It isn't raised because all
> virtio devices are using the "self managed" VMSTATE_VIRTIO_DEVICE to
> migrate.  In that case I am out of luck.  We can further extend what
> Fabiano mentioned in the other thread to cover migration stream validations
> in the future, but just to mention IMHO that needs extra work, and may work
> most likely the same as vmstate static checker but just waste many more cpu
> resources.  It'll be good if someone could still help move virtio towards
> like most of the rest devices, or at least get covered by the static
> checker, too.  But that definitely is a separate topic too.. so we can
> address the immediate breakage first.
>
> Thanks,
>
> ==8<==
> From a24ef99670fa7102da461d795aed4a957bad86b1 Mon Sep 17 00:00:00 2001
> From: Peter Xu 
> Date: Fri, 10 May 2024 12:33:34 -0400
> Subject: [PATCH] fix gpu
>
> Signed-off-by: Peter Xu 
> ---
>  include/hw/virtio/virtio-gpu.h |  2 +-
>  hw/core/machine.c  |  1 +
>  hw/display/virtio-gpu.c| 21 +++--
>  3 files changed, 17 insertions(+), 7 deletions(-)
>
> diff --git a/include/hw/virtio/virtio-gpu.h