linux-user/mips: implement sysmips(MIPS_ATOMIC_SET)
Implement the MIPS_ATOMIC_SET sysmips command as an aligned 32-bit atomic exchange in target memory. MIPS reports syscall errors through a separate register, so successful old values can overlap the errno range. Write the return value and error flag directly and return -QEMU_ESIGRETURN so the common syscall path leaves the registers unchanged. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: James Hilliard <james.hilliard1@gmail.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20260520172313.23777-3-philmd@linaro.org>
James Hilliard committed
May 8, 2026 at 09:14 UTC
5c6f4d7054c233dc45f636c6e4dea73a80ca0d78
3 files changed
+33
linux-user/mips/target_syscall.h
+1
@@ -11,6 +11,7 @@
11
12
#define TARGET_FORCE_SHMLBA
13
#define TARGET_SYSMIPS_FLUSH_CACHE 3
14
+#define TARGET_SYSMIPS_ATOMIC_SET 2001
15
16
static inline abi_ulong target_shmlba(CPUMIPSState *env)
17
{
linux-user/mips64/target_syscall.h
+1
@@ -11,6 +11,7 @@
11
12
#define TARGET_FORCE_SHMLBA
13
#define TARGET_SYSMIPS_FLUSH_CACHE 3
14
+#define TARGET_SYSMIPS_ATOMIC_SET 2001
15
16
static inline abi_ulong target_shmlba(CPUMIPSState *env)
17
{
linux-user/syscall.c
+31
@@ -6631,10 +6631,41 @@ static abi_long do_prctl_syscall_user_dispatch(CPUArchState *env,
6631
}
6632
6633
#ifdef TARGET_NR_sysmips
6634
+static abi_long do_sysmips_atomic_set(CPUArchState *env, abi_ulong addr,
6635
+ abi_long value)
6636
+{
6637
+ uint32_t *ptr;
6638
+ abi_long old;
6639
+
6640
+ if (addr & 3) {
6641
+ return -TARGET_EINVAL;
6642
+ }
6643
+
6644
+ ptr = lock_user(VERIFY_WRITE, addr, sizeof(*ptr), true);
6645
+ if (!ptr) {
6646
+ return -TARGET_EINVAL;
6647
+ }
6648
+
6649
+ old = tswap32(qatomic_xchg(ptr, tswap32((uint32_t)value)));
6650
+ unlock_user(ptr, addr, sizeof(*ptr));
6651
+
6652
+ /*
6653
+ * MIPS uses a separate error flag, but the common linux-user syscall
6654
+ * path infers that flag from the return value. Successful atomic_set
6655
+ * results can overlap the target errno range, so write the result
6656
+ * registers here and ask the CPU loop to leave them alone.
6657
+ */
6658
+ env->active_tc.gpr[2] = old;
6659
+ env->active_tc.gpr[7] = 0;
6660
+ return -QEMU_ESIGRETURN;
6661
+}
6662
+
6663
static abi_long do_sysmips(CPUArchState *env, abi_long cmd, abi_long arg1,
6664
abi_long arg2)
6665
{
6666
switch (cmd) {
6667
+ case TARGET_SYSMIPS_ATOMIC_SET:
6668
+ return do_sysmips_atomic_set(env, arg1, arg2);
6669
case TARGET_SYSMIPS_FLUSH_CACHE:
6670
return 0;
6671
default: