summary refs log tree commit diff stats
path: root/linux-user/syscall.c
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2025-03-20 08:41:10 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2025-03-20 08:41:10 -0400
commit17e9c9094400afefa0c802b903186a730c148c49 (patch)
tree73dc87594ee068fbedf4477a5aa3af5915856c57 /linux-user/syscall.c
parent1dae461a913f9da88df05de6e2020d3134356f2e (diff)
parentffe4db11f8aed79c7ec7d3ebd92674a1cfab4fe7 (diff)
downloadfocaccia-qemu-17e9c9094400afefa0c802b903186a730c148c49.tar.gz
focaccia-qemu-17e9c9094400afefa0c802b903186a730c148c49.zip
Merge tag 'pull-riscv-to-apply-20250319' of https://github.com/alistair23/qemu into staging
Fourth RISC-V PR for 10.0

* Fix broken emulation link
* Optimize the memory probing for vector fault-only-first loads
* Fix access permission checks for CSR_SSP
* Fixes a bug against `ssamoswap` behavior in M-mode
* Fix IOMMU process directory table walk
* Fix OVERFLOW_BEFORE_WIDEN in rmw_sctrdepth()
* Enhance VSTART and VL checks for vector instructions
* Fix handling of cpu mask in riscv_hwprobe syscall
* Add check for 16-bit aligned PC for different priv versions

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEaukCtqfKh31tZZKWr3yVEwxTgBMFAmfaehkACgkQr3yVEwxT
# gBOagRAAsSC/0Fof5EpXc14zmaw7CtoqSCTHVYXYxIEFjRu2Nj89z1HSlB00ptjZ
# g/x5gxJRW8pGarYL6EAKKhk7BpswZ87DbsM/3kQwGraWN/or4SLj12E1V6+UhDi6
# e8qV3oHT8/dMoi/cUc9sM2FNah6gWckxy4QwLzX41jI6wkHe72IC52u9OP6b2ny5
# iky1ThDeQiZmGfj13se9cK1XFNPZgSnJFYD6k9OQTmaMzSShcM64ewv95RfiJbjA
# s8kDmXYrrSQbjWyrjf2JIWhm6dFagFW4u/ho5481gZ1ntw1DnqlHXKCEWSPhIBOm
# WzvfK0dEkmgtOW0DJ7aBdbDJWNRcYCW3xiuUlHrQ7QDRmwreTrF1mo9sD9KifwIo
# NPzScf/O+GPuqDKcV6SfT6rV/Jpr8yaK9WaB/KeDsmhrmsDBn4GCrxu6Z/bLadCy
# AnLItH8BCssSIA989VzwN0V3AsJK8cDQiRzM3/Mq8zp2yNvaBbuGLFxvAzV4sFZY
# PIc7jhWek8Dw1SxIwuXvh/04iNkQNbnowzCQo7q7Cokf4vQtcTSuLblq3IgAJyDn
# eCNXY0SgHNvA6DCxF+ZYAjpgo6ZFusGq1Yq9KzbaH+a3vYOOHhFix4wrFyyApu7+
# 1nBgETtewKfHqo2+GtYr/g1O+WYruf1TC5bCdiWpvvPDR/a7zJM=
# =SqiB
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 19 Mar 2025 04:02:33 EDT
# gpg:                using RSA key 6AE902B6A7CA877D6D659296AF7C95130C538013
# gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 6AE9 02B6 A7CA 877D 6D65  9296 AF7C 9513 0C53 8013

* tag 'pull-riscv-to-apply-20250319' of https://github.com/alistair23/qemu:
  target/riscv: Add check for 16-bit aligned PC for different priv versions.
  linux-user/riscv: Fix handling of cpu mask in riscv_hwprobe syscall
  target/riscv: fix handling of nop for vstart >= vl in some vector instruction
  target/riscv: refactor VSTART_CHECK_EARLY_EXIT() to accept vl as a parameter
  target/riscv/csr.c: fix OVERFLOW_BEFORE_WIDEN in rmw_sctrdepth()
  hw/riscv/riscv-iommu: Fix process directory table walk
  target/riscv: fixes a bug against `ssamoswap` behavior in M-mode
  target/riscv: fix access permission checks for CSR_SSP
  optimize the memory probing for vector fault-only-first loads.
  docs/about/emulation: Fix broken link

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'linux-user/syscall.c')
-rw-r--r--linux-user/syscall.c55
1 files changed, 29 insertions, 26 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b32de763f7..8bfe4912e1 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -9119,35 +9119,38 @@ static void risc_hwprobe_fill_pairs(CPURISCVState *env,
     }
 }
 
-static int cpu_set_valid(abi_long arg3, abi_long arg4)
+/*
+ * If the cpumask_t of (target_cpus, cpusetsize) cannot be read: -EFAULT.
+ * If the cpumast_t has no bits set: -EINVAL.
+ * Otherwise the cpumask_t contains some bit set: 0.
+ * Unlike the kernel, we do not mask cpumask_t by the set of online cpus,
+ * nor bound the search by cpumask_size().
+ */
+static int nonempty_cpu_set(abi_ulong cpusetsize, abi_ptr target_cpus)
 {
-    int ret, i, tmp;
-    size_t host_mask_size, target_mask_size;
-    unsigned long *host_mask;
-
-    /*
-     * cpu_set_t represent CPU masks as bit masks of type unsigned long *.
-     * arg3 contains the cpu count.
-     */
-    tmp = (8 * sizeof(abi_ulong));
-    target_mask_size = ((arg3 + tmp - 1) / tmp) * sizeof(abi_ulong);
-    host_mask_size = (target_mask_size + (sizeof(*host_mask) - 1)) &
-                     ~(sizeof(*host_mask) - 1);
-
-    host_mask = alloca(host_mask_size);
-
-    ret = target_to_host_cpu_mask(host_mask, host_mask_size,
-                                  arg4, target_mask_size);
-    if (ret != 0) {
-        return ret;
-    }
+    unsigned char *p = lock_user(VERIFY_READ, target_cpus, cpusetsize, 1);
+    int ret = -TARGET_EFAULT;
 
-    for (i = 0 ; i < host_mask_size / sizeof(*host_mask); i++) {
-        if (host_mask[i] != 0) {
-            return 0;
+    if (p) {
+        ret = -TARGET_EINVAL;
+        /*
+         * Since we only care about the empty/non-empty state of the cpumask_t
+         * not the individual bits, we do not need to repartition the bits
+         * from target abi_ulong to host unsigned long.
+         *
+         * Note that the kernel does not round up cpusetsize to a multiple of
+         * sizeof(abi_ulong).  After bounding cpusetsize by cpumask_size(),
+         * it copies exactly cpusetsize bytes into a zeroed buffer.
+         */
+        for (abi_ulong i = 0; i < cpusetsize; ++i) {
+            if (p[i]) {
+                ret = 0;
+                break;
+            }
         }
+        unlock_user(p, target_cpus, 0);
     }
-    return -TARGET_EINVAL;
+    return ret;
 }
 
 static abi_long do_riscv_hwprobe(CPUArchState *cpu_env, abi_long arg1,
@@ -9164,7 +9167,7 @@ static abi_long do_riscv_hwprobe(CPUArchState *cpu_env, abi_long arg1,
 
     /* check cpu_set */
     if (arg3 != 0) {
-        ret = cpu_set_valid(arg3, arg4);
+        ret = nonempty_cpu_set(arg3, arg4);
         if (ret != 0) {
             return ret;
         }