qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v4 4/4] linux-user: Implement signal handling for mi


From: khansa
Subject: [Qemu-devel] [PATCH v4 4/4] linux-user: Implement signal handling for mips64
Date: Tue, 3 Jan 2012 09:54:18 +0500

From: Khansa Butt <address@hidden>

This patch includes sigcontext for mips64 suggested by Andreas Färber and 
sa_flags byte
swap fix by Richard Henderson setup_frame() and do_sigreturn need non RT 
syscall numbers
which do not exist in linux 64 bit syscalls. so both function should have 
different implementation
for mips64. Actual signal.c of kernel does not use signal trampoline.
Other related functions have been put under #if defined(TARGET_MIPS).

Signed-off-by: Khansa Butt <address@hidden>
---
 linux-user/signal.c |  272 +++++++++++++++++++++++++++------------------------
 1 files changed, 142 insertions(+), 130 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index ded12ca..fc570cc 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -587,7 +587,11 @@ int do_sigaction(int sig, const struct target_sigaction 
*act,
 #endif
     if (oact) {
         oact->_sa_handler = tswapal(k->_sa_handler);
-        oact->sa_flags = tswapal(k->sa_flags);
+#if defined(TARGET_MIPS)
+        oact->sa_flags = bswap32(k->sa_flags);
+#else
+        oact->sa_flags = tswapal(act->sa_flags);
+#endif
 #if !defined(TARGET_MIPS)
         oact->sa_restorer = tswapal(k->sa_restorer);
 #endif
@@ -596,7 +600,11 @@ int do_sigaction(int sig, const struct target_sigaction 
*act,
     if (act) {
         /* FIXME: This is not threadsafe.  */
         k->_sa_handler = tswapal(act->_sa_handler);
+#if defined(TARGET_MIPS)
+        k->sa_flags = bswap32(act->sa_flags);
+#else
         k->sa_flags = tswapal(act->sa_flags);
+#endif
 #if !defined(TARGET_MIPS)
         k->sa_restorer = tswapal(act->sa_restorer);
 #endif
@@ -2414,35 +2422,6 @@ void sparc64_get_context(CPUSPARCState *env)
     force_sig(TARGET_SIGSEGV);
 }
 #endif
-#elif defined(TARGET_ABI_MIPSN64)
-
-# warning signal handling not implemented
-
-static void setup_frame(int sig, struct target_sigaction *ka,
-                       target_sigset_t *set, CPUState *env)
-{
-    fprintf(stderr, "setup_frame: not implemented\n");
-}
-
-static void setup_rt_frame(int sig, struct target_sigaction *ka,
-                           target_siginfo_t *info,
-                          target_sigset_t *set, CPUState *env)
-{
-    fprintf(stderr, "setup_rt_frame: not implemented\n");
-}
-
-long do_sigreturn(CPUState *env)
-{
-    fprintf(stderr, "do_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
-}
-
-long do_rt_sigreturn(CPUState *env)
-{
-    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
-}
-
 #elif defined(TARGET_ABI_MIPSN32)
 
 # warning signal handling not implemented
@@ -2472,7 +2451,9 @@ long do_rt_sigreturn(CPUState *env)
     return -TARGET_ENOSYS;
 }
 
-#elif defined(TARGET_ABI_MIPSO32)
+#elif defined(TARGET_MIPS)
+
+#if defined(TARGET_ABI_MIPSO32)
 
 struct target_sigcontext {
     uint32_t   sc_regmask;     /* Unused */
@@ -2496,6 +2477,136 @@ struct target_sigcontext {
     target_ulong   sc_lo3;
 };
 
+/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
+static void setup_frame(int sig, struct target_sigaction *ka,
+                        target_sigset_t *set, CPUState *regs)
+{
+    struct sigframe *frame;
+    abi_ulong frame_addr;
+    int i;
+
+    frame_addr = get_sigframe(ka, regs, sizeof(*frame));
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+        goto give_sigsegv;
+
+    install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
+
+    if (setup_sigcontext(regs, &frame->sf_sc))
+        goto give_sigsegv;
+
+    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+        if (__put_user(set->sig[i], &frame->sf_mask.sig[i]))
+            goto give_sigsegv;
+    }
+
+    /*
+    * Arguments to signal handler:
+    *
+    *   a0 = signal number
+    *   a1 = 0 (should be cause)
+    *   a2 = pointer to struct sigcontext
+    *
+    * $25 and PC point to the signal handler, $29 points to the
+    * struct sigframe.
+    */
+    regs->active_tc.gpr[4] = sig;
+    regs->active_tc.gpr[5] = 0;
+    regs->active_tc.gpr[6] = frame_addr + offsetof(struct sigframe, sf_sc);
+    regs->active_tc.gpr[29] = frame_addr;
+    regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
+    /* The original kernel code sets CP0_EPC to the handler
+    * since it returns to userland using eret
+    * we cannot do this here, and we must set PC directly */
+    regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
+    unlock_user_struct(frame, frame_addr, 1);
+    return;
+
+give_sigsegv:
+    unlock_user_struct(frame, frame_addr, 1);
+    force_sig(TARGET_SIGSEGV/*, current*/);
+    return;
+}
+
+long do_sigreturn(CPUState *regs)
+{
+    struct sigframe *frame;
+    abi_ulong frame_addr;
+    sigset_t blocked;
+    target_sigset_t target_set;
+    int i;
+
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "do_sigreturn\n");
+#endif
+    frame_addr = regs->active_tc.gpr[29];
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
+        goto badframe;
+
+    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+        if (__get_user(target_set.sig[i], &frame->sf_mask.sig[i]))
+            goto badframe;
+    }
+
+    target_to_host_sigset_internal(&blocked, &target_set);
+    sigprocmask(SIG_SETMASK, &blocked, NULL);
+
+    if (restore_sigcontext(regs, &frame->sf_sc))
+        goto badframe;
+
+#if 0
+    /*
+     * Don't let your children do this ...
+     */
+    __asm__ __volatile__(
+    "move\t$29, %0\n\t"
+    "j\tsyscall_exit"
+    :/* no outputs */
+    : "r" (&regs));
+    /* Unreached */
+#endif
+
+    regs->active_tc.PC = regs->CP0_EPC;
+    /* I am not sure this is right, but it seems to work
+    * maybe a problem with nested signals ? */
+    regs->CP0_EPC = 0;
+    return -TARGET_QEMU_ESIGRETURN;
+
+badframe:
+    force_sig(TARGET_SIGSEGV/*, current*/);
+    return 0;
+}
+
+#else
+
+struct target_sigcontext {
+        uint64_t   sc_regs[32];
+        uint64_t   sc_fpregs[32];
+        uint64_t   sc_mdhi;
+        uint64_t   sc_hi1;
+        uint64_t   sc_hi2;
+        uint64_t   sc_hi3;
+        uint64_t   sc_mdlo;
+        uint64_t   sc_lo1;
+        uint64_t   sc_lo2;
+        uint64_t   sc_lo3;
+        uint64_t   sc_pc;
+        uint32_t   sc_fpc_csr;
+        uint32_t   sc_used_math;
+        uint32_t   sc_dsp;
+        uint32_t   sc_reserved;
+};
+static void setup_frame(int sig, struct target_sigaction *ka,
+            target_sigset_t *set, CPUState *env)
+{
+    fprintf(stderr, "setup_frame: not implemented\n");
+}
+long do_sigreturn(CPUState *env)
+{
+    fprintf(stderr, "do_sigreturn: not implemented\n");
+    return -TARGET_ENOSYS;
+}
+#endif
+
 struct sigframe {
     uint32_t sf_ass[4];                        /* argument save space for o32 
*/
     uint32_t sf_code[2];                       /* signal trampoline */
@@ -2706,105 +2817,6 @@ get_sigframe(struct target_sigaction *ka, CPUState 
*regs, size_t frame_size)
     return (sp - frame_size) & ~7;
 }
 
-/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
-static void setup_frame(int sig, struct target_sigaction * ka,
-                        target_sigset_t *set, CPUState *regs)
-{
-    struct sigframe *frame;
-    abi_ulong frame_addr;
-    int i;
-
-    frame_addr = get_sigframe(ka, regs, sizeof(*frame));
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-       goto give_sigsegv;
-
-    install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
-
-    if(setup_sigcontext(regs, &frame->sf_sc))
-       goto give_sigsegv;
-
-    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
-       if(__put_user(set->sig[i], &frame->sf_mask.sig[i]))
-           goto give_sigsegv;
-    }
-
-    /*
-    * Arguments to signal handler:
-    *
-    *   a0 = signal number
-    *   a1 = 0 (should be cause)
-    *   a2 = pointer to struct sigcontext
-    *
-    * $25 and PC point to the signal handler, $29 points to the
-    * struct sigframe.
-    */
-    regs->active_tc.gpr[ 4] = sig;
-    regs->active_tc.gpr[ 5] = 0;
-    regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
-    regs->active_tc.gpr[29] = frame_addr;
-    regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
-    /* The original kernel code sets CP0_EPC to the handler
-    * since it returns to userland using eret
-    * we cannot do this here, and we must set PC directly */
-    regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
-    unlock_user_struct(frame, frame_addr, 1);
-    return;
-
-give_sigsegv:
-    unlock_user_struct(frame, frame_addr, 1);
-    force_sig(TARGET_SIGSEGV/*, current*/);
-    return;
-}
-
-long do_sigreturn(CPUState *regs)
-{
-    struct sigframe *frame;
-    abi_ulong frame_addr;
-    sigset_t blocked;
-    target_sigset_t target_set;
-    int i;
-
-#if defined(DEBUG_SIGNAL)
-    fprintf(stderr, "do_sigreturn\n");
-#endif
-    frame_addr = regs->active_tc.gpr[29];
-    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
-       goto badframe;
-
-    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
-       if(__get_user(target_set.sig[i], &frame->sf_mask.sig[i]))
-           goto badframe;
-    }
-
-    target_to_host_sigset_internal(&blocked, &target_set);
-    sigprocmask(SIG_SETMASK, &blocked, NULL);
-
-    if (restore_sigcontext(regs, &frame->sf_sc))
-       goto badframe;
-
-#if 0
-    /*
-     * Don't let your children do this ...
-     */
-    __asm__ __volatile__(
-       "move\t$29, %0\n\t"
-       "j\tsyscall_exit"
-       :/* no outputs */
-       :"r" (&regs));
-    /* Unreached */
-#endif
-
-    regs->active_tc.PC = regs->CP0_EPC;
-    /* I am not sure this is right, but it seems to work
-    * maybe a problem with nested signals ? */
-    regs->CP0_EPC = 0;
-    return -TARGET_QEMU_ESIGRETURN;
-
-badframe:
-    force_sig(TARGET_SIGSEGV/*, current*/);
-    return 0;
-}
-
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
                           target_sigset_t *set, CPUState *env)
-- 
1.7.3.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]