@samitouri / QOSamiQemu / commits / 5c6f4d7054

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: