summary refs log tree commit diff stats
path: root/linux-user/xtensa/signal.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-09-12 16:17:26 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-09-12 16:17:26 +0100
commita30cb4b1f22c58aa3b933ee9e1d7611399b57b5b (patch)
treef31eb44f95cfcee9525b4ba0a9fd5656c3ed6041 /linux-user/xtensa/signal.c
parent6d2fdde42c3344099262431df6a3f429c509291d (diff)
parent5eea942900536b76ad13bef35e1d8f276566ae9e (diff)
downloadfocaccia-qemu-a30cb4b1f22c58aa3b933ee9e1d7611399b57b5b.tar.gz
focaccia-qemu-a30cb4b1f22c58aa3b933ee9e1d7611399b57b5b.zip
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-4.2-pull-request' into staging
Add several floppy drive ioctl,
xtensa call0 ABI support, arm MAX_RESERVED_VA for M-profile,
aarch64 AT_HWCAP2, qOffsets' query for ELF, memfd_create,
and some code cleanup

# gpg: Signature made Wed 11 Sep 2019 07:48:45 BST
# gpg:                using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg:                issuer "laurent@vivier.eu"
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full]
# gpg:                 aka "Laurent Vivier <laurent@vivier.eu>" [full]
# gpg:                 aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full]
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F  5173 F30C 38BD 3F2F BE3C

* remotes/vivier2/tags/linux-user-for-4.2-pull-request:
  linux-user: Add support for FDRESET, FDRAWCMD, FDTWADDLE, and FDEJECT ioctls
  linux-user: Add support for FDMSGON and FDMSGOFF ioctls
  linux-user: Add support for FDFLUSH ioctl
  linux-user: Add support for FIOGETOWN and FIOSETOWN ioctls
  linux-user: Add support for RNDRESEEDCRNG ioctl
  linux-user: drop redundant handling of environment variables
  target/xtensa: linux-user: add call0 ABI support
  linux-user: Support gdb 'qOffsets' query for ELF
  linux-user/arm: Adjust MAX_RESERVED_VA for M-profile
  linux-user: Pass CPUState to MAX_RESERVED_VA
  linux-user: add memfd_create
  linux-user: fail and report on bad dfilter specs
  linux-user: erroneous fd_trans_unregister call
  linux-user: Add AT_HWCAP2 for aarch64-linux-user
  linux-user: remove useless variable

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user/xtensa/signal.c')
-rw-r--r--linux-user/xtensa/signal.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c
index 8d54ef3ae3..590f0313ff 100644
--- a/linux-user/xtensa/signal.c
+++ b/linux-user/xtensa/signal.c
@@ -134,6 +134,8 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
     abi_ulong frame_addr;
     struct target_rt_sigframe *frame;
     uint32_t ra;
+    bool abi_call0;
+    unsigned base;
     int i;
 
     frame_addr = get_sigframe(ka, env, sizeof(*frame));
@@ -182,20 +184,27 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
         __put_user(0x00, &frame->retcode[5]);
 #endif
     }
-    env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT);
-    if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER)) {
-        env->sregs[PS] |= PS_WOE | (1 << PS_CALLINC_SHIFT);
-    }
     memset(env->regs, 0, sizeof(env->regs));
     env->pc = ka->_sa_handler;
     env->regs[1] = frame_addr;
     env->sregs[WINDOW_BASE] = 0;
     env->sregs[WINDOW_START] = 1;
 
-    env->regs[4] = (ra & 0x3fffffff) | 0x40000000;
-    env->regs[6] = sig;
-    env->regs[7] = frame_addr + offsetof(struct target_rt_sigframe, info);
-    env->regs[8] = frame_addr + offsetof(struct target_rt_sigframe, uc);
+    abi_call0 = (env->sregs[PS] & PS_WOE) == 0;
+    env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT);
+
+    if (abi_call0) {
+        base = 0;
+        env->regs[base] = ra;
+    } else {
+        env->sregs[PS] |= PS_WOE | (1 << PS_CALLINC_SHIFT);
+        base = 4;
+        env->regs[base] = (ra & 0x3fffffff) | 0x40000000;
+    }
+    env->regs[base + 2] = sig;
+    env->regs[base + 3] = frame_addr + offsetof(struct target_rt_sigframe,
+                                                info);
+    env->regs[base + 4] = frame_addr + offsetof(struct target_rt_sigframe, uc);
     unlock_user_struct(frame, frame_addr, 1);
     return;