summary refs log tree commit diff stats
path: root/linux-user/signal.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-10-19 14:39:30 +0100
committerPeter Maydell <peter.maydell@linaro.org>2017-10-19 14:39:30 +0100
commitf2a48d696c12aaac12993364371daae9f6233c37 (patch)
tree57a2098280251432d049b2f7f963894f2eae3def /linux-user/signal.c
parentba6f0fc25e3c14fbb36f4b5a616a89cd3f1de6d0 (diff)
parentf443e3960d9d3340dd286e5fc0b661bb165a8b22 (diff)
downloadfocaccia-qemu-f2a48d696c12aaac12993364371daae9f6233c37.tar.gz
focaccia-qemu-f2a48d696c12aaac12993364371daae9f6233c37.zip
Merge remote-tracking branch 'remotes/riku/tags/pull-linux-user-20171018' into staging
Linux-user updates for Qemu 2.11

# gpg: Signature made Wed 18 Oct 2017 13:20:14 BST
# gpg:                using RSA key 0xB44890DEDE3C9BC0
# gpg: Good signature from "Riku Voipio <riku.voipio@iki.fi>"
# gpg:                 aka "Riku Voipio <riku.voipio@linaro.org>"
# Primary key fingerprint: FF82 03C8 C391 98AE 0581  41EF B448 90DE DE3C 9BC0

* remotes/riku/tags/pull-linux-user-20171018:
  linux-user: Fix TARGET_MTIOCTOP/MTIOCGET/MTIOCPOS values
  linux-user/main: support dfilter
  linux-user: Fix target FS_IOC_GETFLAGS and FS_IOC_SETFLAGS numbers
  linux-user/sh4: Reduce TARGET_VIRT_ADDR_SPACE_BITS to 31
  linux-user: Tidy and enforce reserved_va initialization
  tcg: Fix off-by-one in assert in page_set_flags
  linux-user: Allow -R values up to 0xffff0000 for 32-bit ARM guests
  linux-user: remove duplicate break in syscall
  target/m68k,linux-user: manage FP registers in ucontext
  linux-user: fix O_TMPFILE handling

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user/signal.c')
-rw-r--r--linux-user/signal.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/linux-user/signal.c b/linux-user/signal.c
index cc0c3fcee9..7a238aaea1 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5704,6 +5704,24 @@ give_sigsegv:
     force_sigsegv(sig);
 }
 
+static inline void target_rt_save_fpu_state(struct target_ucontext *uc,
+                                           CPUM68KState *env)
+{
+    int i;
+    target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
+
+    __put_user(env->fpcr, &fpregs->f_fpcntl[0]);
+    __put_user(env->fpsr, &fpregs->f_fpcntl[1]);
+    /* fpiar is not emulated */
+
+    for (i = 0; i < 8; i++) {
+        uint32_t high = env->fregs[i].d.high << 16;
+        __put_user(high, &fpregs->f_fpregs[i * 3]);
+        __put_user(env->fregs[i].d.low,
+                   (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
+    }
+}
+
 static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
                                            CPUM68KState *env)
 {
@@ -5730,9 +5748,32 @@ static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
     __put_user(env->pc, &gregs[16]);
     __put_user(sr, &gregs[17]);
 
+    target_rt_save_fpu_state(uc, env);
+
     return 0;
 }
 
+static inline void target_rt_restore_fpu_state(CPUM68KState *env,
+                                               struct target_ucontext *uc)
+{
+    int i;
+    target_fpregset_t *fpregs = &uc->tuc_mcontext.fpregs;
+    uint32_t fpcr;
+
+    __get_user(fpcr, &fpregs->f_fpcntl[0]);
+    cpu_m68k_set_fpcr(env, fpcr);
+    __get_user(env->fpsr, &fpregs->f_fpcntl[1]);
+    /* fpiar is not emulated */
+
+    for (i = 0; i < 8; i++) {
+        uint32_t high;
+        __get_user(high, &fpregs->f_fpregs[i * 3]);
+        env->fregs[i].d.high = high >> 16;
+        __get_user(env->fregs[i].d.low,
+                   (uint64_t *)&fpregs->f_fpregs[i * 3 + 1]);
+    }
+}
+
 static inline int target_rt_restore_ucontext(CPUM68KState *env,
                                              struct target_ucontext *uc)
 {
@@ -5764,6 +5805,8 @@ static inline int target_rt_restore_ucontext(CPUM68KState *env,
     __get_user(temp, &gregs[17]);
     cpu_m68k_set_ccr(env, temp);
 
+    target_rt_restore_fpu_state(env, uc);
+
     return 0;
 
 badframe: