All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/3] MIPS64 user mode emulation in QEMU
@ 2011-12-08  5:25 khansa
  2011-12-08  5:25 ` [Qemu-devel] [PATCH 1/3] linux-user:Support for " khansa
                   ` (3 more replies)
  0 siblings, 4 replies; 16+ messages in thread
From: khansa @ 2011-12-08  5:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, riku.voipio, Khansa Butt, aurelien

From: Khansa Butt <khansa@kics.edu.pk>

This is the team work of Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed, Khansa Butt
from HPCN Lab KICS UET Lahore.
In previous patch set we were including Cavium specific instructions along with 
Cavium specifc registers in UME. Because of these register fields we had to bump
the cpu version up but I noticed that cpu_save() and cpu_load() are not called in
UME so we decided to postpone Octeon specific changes ( registers and instructions)
and will include them in our SME work( we are currently working on system mode 
emulation of Octeon board) so we closing the following thread
http://lists.gnu.org/archive/html/qemu-devel/2011-10/msg02665.html
Please review this new patch set which is without cavium instruction support. 

 configure                             |    1 +
 default-configs/mips64-linux-user.mak |    1 +
 linux-user/main.c                     |   21 ++-
 linux-user/mips64/syscall.h           |    2 +
 linux-user/signal.c                   |  429 ++++++++++++++++++++++++++++++++-
 target-mips/translate.c               |    4 +
 6 files changed, 444 insertions(+), 14 deletions(-)
 create mode 100644 default-configs/mips64-linux-user.mak

-- 
1.7.3.4

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 1/3] linux-user:Support for MIPS64 user mode emulation in QEMU
  2011-12-08  5:25 [Qemu-devel] [PATCH 0/3] MIPS64 user mode emulation in QEMU khansa
@ 2011-12-08  5:25 ` khansa
  2011-12-08 15:15   ` Andreas Färber
  2011-12-08  5:25 ` [Qemu-devel] [PATCH 2/3] target-mips:enabling of 64 bit user mode and floating point operations MIPS_HFLAG_UX is included in env->hflags so that the address computation for LD instruction does not treated as 32 bit code see gen_op_addr_add() in translate.c khansa
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 16+ messages in thread
From: khansa @ 2011-12-08  5:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, riku.voipio, Khansa Butt, aurelien

From: Khansa Butt <khansa@kics.edu.pk>


Signed-off-by: Khansa Butt <khansa@kics.edu.pk>
---
 configure                             |    1 +
 default-configs/mips64-linux-user.mak |    1 +
 linux-user/main.c                     |   21 +++++++++++++++++++--
 linux-user/mips64/syscall.h           |    2 ++
 4 files changed, 23 insertions(+), 2 deletions(-)
 create mode 100644 default-configs/mips64-linux-user.mak

diff --git a/configure b/configure
index ac4840d..e31229b 100755
--- a/configure
+++ b/configure
@@ -914,6 +914,7 @@ m68k-linux-user \
 microblaze-linux-user \
 microblazeel-linux-user \
 mips-linux-user \
+mips64-linux-user \
 mipsel-linux-user \
 ppc-linux-user \
 ppc64-linux-user \
diff --git a/default-configs/mips64-linux-user.mak b/default-configs/mips64-linux-user.mak
new file mode 100644
index 0000000..1598bfc
--- /dev/null
+++ b/default-configs/mips64-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for mips64-linux-user
diff --git a/linux-user/main.c b/linux-user/main.c
index d1bbc57..17a74cd 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2157,7 +2157,8 @@ static int do_store_exclusive(CPUMIPSState *env)
 void cpu_loop(CPUMIPSState *env)
 {
     target_siginfo_t info;
-    int trapnr, ret;
+    int trapnr;
+    abi_long ret;
     unsigned int syscall_num;
 
     for(;;) {
@@ -2166,8 +2167,23 @@ void cpu_loop(CPUMIPSState *env)
         cpu_exec_end(env);
         switch(trapnr) {
         case EXCP_SYSCALL:
-            syscall_num = env->active_tc.gpr[2] - 4000;
             env->active_tc.PC += 4;
+#if defined(TARGET_MIPS64)
+            syscall_num = env->active_tc.gpr[2] - 5000;
+            /* MIPS64 has eight argument registers so there is
+             * no need to get arguments from stack
+             */
+            ret = do_syscall(env, env->active_tc.gpr[2],
+                             env->active_tc.gpr[4],
+                             env->active_tc.gpr[5],
+                             env->active_tc.gpr[6],
+                             env->active_tc.gpr[7],
+                             env->active_tc.gpr[8],
+                             env->active_tc.gpr[9],
+                             env->active_tc.gpr[10],
+                             env->active_tc.gpr[11]);
+#else
+            syscall_num = env->active_tc.gpr[2] - 4000;
             if (syscall_num >= sizeof(mips_syscall_args)) {
                 ret = -TARGET_ENOSYS;
             } else {
@@ -2205,6 +2221,7 @@ void cpu_loop(CPUMIPSState *env)
                                  env->active_tc.gpr[7],
                                  arg5, arg6, arg7, arg8);
             }
+#endif
 done_syscall:
             if (ret == -TARGET_QEMU_ESIGRETURN) {
                 /* Returning from a successful sigreturn syscall.
diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h
index 668a2b9..96f03da 100644
--- a/linux-user/mips64/syscall.h
+++ b/linux-user/mips64/syscall.h
@@ -218,4 +218,6 @@ struct target_pt_regs {
 
 
 
+#define TARGET_QEMU_ESIGRETURN 255
+
 #define UNAME_MACHINE "mips64"
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 2/3] target-mips:enabling of 64 bit user mode and floating point operations MIPS_HFLAG_UX is included in env->hflags so that the address computation for LD instruction does not treated as 32 bit code see gen_op_addr_add() in translate.c
  2011-12-08  5:25 [Qemu-devel] [PATCH 0/3] MIPS64 user mode emulation in QEMU khansa
  2011-12-08  5:25 ` [Qemu-devel] [PATCH 1/3] linux-user:Support for " khansa
@ 2011-12-08  5:25 ` khansa
  2011-12-09  0:04   ` Andreas Färber
  2011-12-08  5:25 ` [Qemu-devel] [PATCH 3/3] linux-user:Signal handling for MIPS64 khansa
  2011-12-08 13:22 ` [Qemu-devel] [PATCH 0/3] MIPS64 user mode emulation in QEMU Andreas Färber
  3 siblings, 1 reply; 16+ messages in thread
From: khansa @ 2011-12-08  5:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, riku.voipio, Khansa Butt, aurelien

From: Khansa Butt <khansa@kics.edu.pk>


Signed-off-by: Abdul Qadeer <qadeer@kics.edu.pk>
---
 target-mips/translate.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index d5b1c76..452a63b 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -12779,6 +12779,10 @@ void cpu_reset (CPUMIPSState *env)
         env->hflags |= MIPS_HFLAG_FPU;
     }
 #ifdef TARGET_MIPS64
+    env->hflags |=  MIPS_HFLAG_UX;
+    /* if cpu has FPU, MIPS_HFLAG_F64 must be included in env->hflags
+       so that floating point operations can be emulated */
+    env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
     if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
         env->hflags |= MIPS_HFLAG_F64;
     }
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 3/3] linux-user:Signal handling for MIPS64
  2011-12-08  5:25 [Qemu-devel] [PATCH 0/3] MIPS64 user mode emulation in QEMU khansa
  2011-12-08  5:25 ` [Qemu-devel] [PATCH 1/3] linux-user:Support for " khansa
  2011-12-08  5:25 ` [Qemu-devel] [PATCH 2/3] target-mips:enabling of 64 bit user mode and floating point operations MIPS_HFLAG_UX is included in env->hflags so that the address computation for LD instruction does not treated as 32 bit code see gen_op_addr_add() in translate.c khansa
@ 2011-12-08  5:25 ` khansa
  2011-12-14 16:20   ` Richard Henderson
  2011-12-08 13:22 ` [Qemu-devel] [PATCH 0/3] MIPS64 user mode emulation in QEMU Andreas Färber
  3 siblings, 1 reply; 16+ messages in thread
From: khansa @ 2011-12-08  5:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, riku.voipio, Khansa Butt, aurelien

From: Khansa Butt <khansa@kics.edu.pk>


Signed-off-by: Ehsan Ul Haq <ehsan.ulhaq@kics.edu.pk>
---
 linux-user/signal.c |  429 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 417 insertions(+), 12 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 78e3380..0f4091d 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -596,7 +596,13 @@ 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_MIPS64)
+        /* tswapal() do 64 bit swap in case of MIPS64 but
+           we need 32 bit swap as sa_flags is 32 bit */
+        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
@@ -2416,31 +2422,430 @@ void sparc64_get_context(CPUSPARCState *env)
 #endif
 #elif defined(TARGET_ABI_MIPSN64)
 
-# warning signal handling not implemented
+struct target_sigcontext {
+    uint32_t   sc_regmask;     /* Unused */
+    uint32_t   sc_status;
+    uint64_t   sc_pc;
+    uint64_t   sc_regs[32];
+    uint64_t   sc_fpregs[32];
+    uint32_t   sc_ownedfp;     /* Unused */
+    uint32_t   sc_fpc_csr;
+    uint32_t   sc_fpc_eir;     /* Unused */
+    uint32_t   sc_used_math;
+    uint32_t   sc_dsp;         /* dsp status, was sc_ssflags */
+    uint32_t   pad0;
+    uint64_t   sc_mdhi;
+    uint64_t   sc_mdlo;
+    target_ulong   sc_hi1;         /* Was sc_cause */
+    target_ulong   sc_lo1;         /* Was sc_badvaddr */
+    target_ulong   sc_hi2;         /* Was sc_sigset[4] */
+    target_ulong   sc_lo2;
+    target_ulong   sc_hi3;
+    target_ulong   sc_lo3;
+};
+
+struct sigframe {
+    uint32_t sf_ass[4];         /* argument save space for o32 */
+    uint32_t sf_code[2];            /* signal trampoline */
+    struct target_sigcontext sf_sc;
+    target_sigset_t sf_mask;
+};
+
+struct target_ucontext {
+    target_ulong tuc_flags;
+    target_ulong tuc_link;
+    target_stack_t tuc_stack;
+    target_ulong pad0;
+    struct target_sigcontext tuc_mcontext;
+    target_sigset_t tuc_sigmask;
+};
+
+struct target_rt_sigframe {
+    uint32_t rs_ass[4];               /* argument save space for o32 */
+    uint32_t rs_code[2];              /* signal trampoline */
+    struct target_siginfo rs_info;
+    struct target_ucontext rs_uc;
+};
+
+/* Install trampoline to jump back from signal handler */
+static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall)
+{
+    int err;
+
+    /*
+     * Set up the return code ...
+     *
+     *         li      v0, __NR__foo_sigreturn
+     *         syscall
+     */
+
+    err = __put_user(0x24020000 + syscall, tramp + 0);
+    err |= __put_user(0x0000000c          , tramp + 1);
+    /* flush_cache_sigtramp((unsigned long) tramp); */
+    return err;
+}
+
+static inline int
+setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
+{
+    int err = 0;
+
+    err |= __put_user(regs->active_tc.PC, &sc->sc_pc);
+
+#define save_gp_reg(i) do {                         \
+        err |= __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); \
+} while (0)
+    __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
+    save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
+    save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
+    save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
+    save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
+    save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
+    save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
+    save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
+    save_gp_reg(31);
+#undef save_gp_reg
+
+    err |= __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
+    err |= __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
+
+    /* Not used yet, but might be useful if we ever have DSP suppport */
+#if 0
+    if (cpu_has_dsp) {
+        err |= __put_user(mfhi1(), &sc->sc_hi1);
+        err |= __put_user(mflo1(), &sc->sc_lo1);
+        err |= __put_user(mfhi2(), &sc->sc_hi2);
+        err |= __put_user(mflo2(), &sc->sc_lo2);
+        err |= __put_user(mfhi3(), &sc->sc_hi3);
+        err |= __put_user(mflo3(), &sc->sc_lo3);
+        err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+    }
+    /* same with 64 bit */
+#ifdef CONFIG_64BIT
+    err |= __put_user(regs->hi, &sc->sc_hi[0]);
+    err |= __put_user(regs->lo, &sc->sc_lo[0]);
+    if (cpu_has_dsp) {
+        err |= __put_user(mfhi1(), &sc->sc_hi[1]);
+        err |= __put_user(mflo1(), &sc->sc_lo[1]);
+        err |= __put_user(mfhi2(), &sc->sc_hi[2]);
+        err |= __put_user(mflo2(), &sc->sc_lo[2]);
+        err |= __put_user(mfhi3(), &sc->sc_hi[3]);
+        err |= __put_user(mflo3(), &sc->sc_lo[3]);
+        err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+    }
+#endif
+#endif
+
+#if 0
+    err |= __put_user(!!used_math(), &sc->sc_used_math);
+
+    if (!used_math())
+        goto out;
+
+    /*
+     * Save FPU state to signal context.  Signal handler will "inherit"
+     * current FPU state.
+     */
+    preempt_disable();
+
+    if (!is_fpu_owner()) {
+        own_fpu();
+        restore_fp(current);
+    }
+    err |= save_fp_context(sc);
+
+    preempt_enable();
+    out:
+#endif
+    return err;
+}
+
+static inline int
+restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
+{
+    int err = 0;
+
+    err |= __get_user(regs->CP0_EPC, &sc->sc_pc);
+
+    err |= __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
+    err |= __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
+
+#define restore_gp_reg(i) do {                               \
+        err |= __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);     \
+} while (0)
+    restore_gp_reg(1); restore_gp_reg(2); restore_gp_reg(3);
+    restore_gp_reg(4); restore_gp_reg(5); restore_gp_reg(6);
+    restore_gp_reg(7); restore_gp_reg(8); restore_gp_reg(9);
+    restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
+    restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
+    restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
+    restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
+    restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
+    restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
+    restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
+    restore_gp_reg(31);
+#undef restore_gp_reg
+
+#if 0
+    if (cpu_has_dsp) {
+        err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
+        err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
+        err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
+        err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
+        err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
+        err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
+        err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+    }
+#ifdef CONFIG_64BIT
+    err |= __get_user(regs->hi, &sc->sc_hi[0]);
+    err |= __get_user(regs->lo, &sc->sc_lo[0]);
+    if (cpu_has_dsp) {
+        err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
+        err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
+        err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
+        err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
+        err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
+        err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
+        err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+    }
+#endif
+
+    err |= __get_user(used_math, &sc->sc_used_math);
+    conditional_used_math(used_math);
+
+    preempt_disable();
+
+    if (used_math()) {
+        /* restore fpu context if we have used it before */
+        own_fpu();
+        err |= restore_fp_context(sc);
+    } else {
+        /* signal handler may have used FPU.  Give it up. */
+        lose_fpu();
+    }
+
+    preempt_enable();
+#endif
+    return err;
+}
+/*
+ * Determine which stack to use..
+ */
+static inline abi_ulong
+get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
+{
+    unsigned long sp;
+
+    /* Default to using normal stack */
+    sp = regs->active_tc.gpr[29];
 
+    /*
+     * FPU emulator may have it's own trampoline active just
+     * above the user stack, 16-bytes before the next lowest
+     * 16 byte boundary.  Try to avoid trashing it.
+     */
+    sp -= 32;
+
+    /* This is the X/Open sanctioned signal stack switching.  */
+    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
+        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_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 *env)
+        target_sigset_t *set, CPUState *regs)
 {
-    fprintf(stderr, "setup_frame: not implemented\n");
+    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_rt_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;
 }
 
-static void setup_rt_frame(int sig, struct target_sigaction *ka,
-                           target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
+long do_sigreturn(CPUState *regs)
 {
-    fprintf(stderr, "setup_rt_frame: not implemented\n");
+    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;
 }
 
-long do_sigreturn(CPUState *env)
+static void setup_rt_frame(int sig, struct target_sigaction *ka,
+        target_siginfo_t *info,
+        target_sigset_t *set, CPUState *env)
 {
-    fprintf(stderr, "do_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
+    struct target_rt_sigframe *frame;
+    abi_ulong frame_addr;
+    int i;
+
+    frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+        goto give_sigsegv;
+
+    install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
+
+    copy_siginfo_to_user(&frame->rs_info, info);
+
+    __put_user(0, &frame->rs_uc.tuc_flags);
+    __put_user(0, &frame->rs_uc.tuc_link);
+    __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
+    __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
+    __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
+            &frame->rs_uc.tuc_stack.ss_flags);
+
+    setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
+
+    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+        __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
+    }
+
+    /*
+     * Arguments to signal handler:
+     *
+     *   a0 = signal number
+     *   a1 = pointer to struct siginfo
+     *   a2 = pointer to struct ucontext
+     *
+     * $25 and PC point to the signal handler, $29 points to the
+     * struct sigframe.
+     */
+    env->active_tc.gpr[4] = sig;
+    env->active_tc.gpr[5] = frame_addr
+            + offsetof(struct target_rt_sigframe, rs_info);
+    env->active_tc.gpr[6] = frame_addr
+            + offsetof(struct target_rt_sigframe, rs_uc);
+    env->active_tc.gpr[29] = frame_addr;
+    env->active_tc.gpr[31] = frame_addr
+            + offsetof(struct target_rt_sigframe, rs_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 */
+    env->active_tc.PC = env->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_rt_sigreturn(CPUState *env)
 {
-    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
+        struct target_rt_sigframe *frame;
+        abi_ulong frame_addr;
+        sigset_t blocked;
+
+#if defined(DEBUG_SIGNAL)
+        fprintf(stderr, "do_rt_sigreturn\n");
+#endif
+        frame_addr = env->active_tc.gpr[29];
+        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
+            goto badframe;
+
+        target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
+        sigprocmask(SIG_SETMASK, &blocked, NULL);
+
+        if (restore_sigcontext(env, &frame->rs_uc.tuc_mcontext))
+            goto badframe;
+
+        if (do_sigaltstack(frame_addr +
+                offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
+                0, get_sp_from_cpustate(env)) == -EFAULT)
+            goto badframe;
+
+        env->active_tc.PC = env->CP0_EPC;
+        /* I am not sure this is right, but it seems to work
+         * maybe a problem with nested signals ? */
+        env->CP0_EPC = 0;
+        return -TARGET_QEMU_ESIGRETURN;
+
+        badframe:
+        force_sig(TARGET_SIGSEGV/*, current*/);
+        return 0;
 }
 
 #elif defined(TARGET_ABI_MIPSN32)
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 0/3] MIPS64 user mode emulation in QEMU
  2011-12-08  5:25 [Qemu-devel] [PATCH 0/3] MIPS64 user mode emulation in QEMU khansa
                   ` (2 preceding siblings ...)
  2011-12-08  5:25 ` [Qemu-devel] [PATCH 3/3] linux-user:Signal handling for MIPS64 khansa
@ 2011-12-08 13:22 ` Andreas Färber
  3 siblings, 0 replies; 16+ messages in thread
From: Andreas Färber @ 2011-12-08 13:22 UTC (permalink / raw)
  To: khansa; +Cc: peter.maydell, riku.voipio, qemu-devel, aurelien

Am 08.12.2011 06:25, schrieb khansa@kics.edu.pk:
> From: Khansa Butt <khansa@kics.edu.pk>
> 
> This is the team work of Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed, Khansa Butt
> from HPCN Lab KICS UET Lahore.
> In previous patch set we were including Cavium specific instructions along with 
> Cavium specifc registers in UME. Because of these register fields we had to bump
> the cpu version up but I noticed that cpu_save() and cpu_load() are not called in
> UME so we decided to postpone Octeon specific changes ( registers and instructions)
> and will include them in our SME work( we are currently working on system mode 
> emulation of Octeon board) so we closing the following thread
> http://lists.gnu.org/archive/html/qemu-devel/2011-10/msg02665.html
> Please review this new patch set which is without cavium instruction support.

I really hate to repeat myself... We receive lots of patches per day, so
please make your patches easy to read, easy to understand and easy to
review. If you check qemu-devel or the archives, you'll find many good
examples that get committed - most people get this right on second try.
Please don't ignore our comments from previous series:

You previously sent a v3 series, now there's two unversioned series
again. These should be v4 and v5 and should ALWAYS include a bulleted
change log since initial version. This is to tell apart which is the
latest series and which is superseded. v4 should include something like:

"Changes since v3" (or short "v3 -> v4"):
* Drop CPU load/save from series

v2 -> v3:
...

v1 -> v2:
...

If v5 changed nothing but the cover letter, there would be no need to
resend it, explanations for us can be added as a normal email reply.

If you're missing feedback, best just reply to your cover letter with
"Ping?" so that we have a chance of reviewing the email thread with
previous comments.

More in the individual patches.

Andreas

> 
>  configure                             |    1 +
>  default-configs/mips64-linux-user.mak |    1 +
>  linux-user/main.c                     |   21 ++-
>  linux-user/mips64/syscall.h           |    2 +
>  linux-user/signal.c                   |  429 ++++++++++++++++++++++++++++++++-
>  target-mips/translate.c               |    4 +
>  6 files changed, 444 insertions(+), 14 deletions(-)
>  create mode 100644 default-configs/mips64-linux-user.mak
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 1/3] linux-user:Support for MIPS64 user mode emulation in QEMU
  2011-12-08  5:25 ` [Qemu-devel] [PATCH 1/3] linux-user:Support for " khansa
@ 2011-12-08 15:15   ` Andreas Färber
  2011-12-09  0:18     ` Andreas Färber
  2011-12-14 16:04     ` Richard Henderson
  0 siblings, 2 replies; 16+ messages in thread
From: Andreas Färber @ 2011-12-08 15:15 UTC (permalink / raw)
  To: khansa; +Cc: peter.maydell, riku.voipio, qemu-devel, aurelien

This is about QEMU and linux-user is the user mode emulation, so please
change the subject to "linux-user: Add support for MIPS64" (note the
space that I reminded you of earlier, it looks weird without on Western
left-to-right screens).

Am 08.12.2011 06:25, schrieb khansa@kics.edu.pk:
> From: Khansa Butt <khansa@kics.edu.pk>
> 

As requested earlier, since this is a non-trivial change, please include
a summary here of what the patch does below. Should mention that people
can use it via "mips64-linux-user" and should describe syscall differences.

> 
> Signed-off-by: Khansa Butt <khansa@kics.edu.pk>
> ---
>  configure                             |    1 +
>  default-configs/mips64-linux-user.mak |    1 +
>  linux-user/main.c                     |   21 +++++++++++++++++++--
>  linux-user/mips64/syscall.h           |    2 ++
>  4 files changed, 23 insertions(+), 2 deletions(-)
>  create mode 100644 default-configs/mips64-linux-user.mak
> 
> diff --git a/configure b/configure
> index ac4840d..e31229b 100755
> --- a/configure
> +++ b/configure
> @@ -914,6 +914,7 @@ m68k-linux-user \
>  microblaze-linux-user \
>  microblazeel-linux-user \
>  mips-linux-user \
> +mips64-linux-user \
>  mipsel-linux-user \

I would suggest to move your addition one line down, so that mips and
mipsel stay together.

For linux-user IIUC the ABI is relevant, so shouldn't this be
mipsn64-linux-user? We have a patch for mipsn32/mipsn32el. What about
mipsn64el?

>  ppc-linux-user \
>  ppc64-linux-user \
> diff --git a/default-configs/mips64-linux-user.mak b/default-configs/mips64-linux-user.mak
> new file mode 100644
> index 0000000..1598bfc
> --- /dev/null
> +++ b/default-configs/mips64-linux-user.mak
> @@ -0,0 +1 @@
> +# Default configuration for mips64-linux-user

> diff --git a/linux-user/main.c b/linux-user/main.c
> index d1bbc57..17a74cd 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -2157,7 +2157,8 @@ static int do_store_exclusive(CPUMIPSState *env)
>  void cpu_loop(CPUMIPSState *env)
>  {
>      target_siginfo_t info;
> -    int trapnr, ret;
> +    int trapnr;
> +    abi_long ret;
>      unsigned int syscall_num;
>  
>      for(;;) {
> @@ -2166,8 +2167,23 @@ void cpu_loop(CPUMIPSState *env)
>          cpu_exec_end(env);
>          switch(trapnr) {
>          case EXCP_SYSCALL:
> -            syscall_num = env->active_tc.gpr[2] - 4000;
>              env->active_tc.PC += 4;
> +#if defined(TARGET_MIPS64)

TARGET_ABI_MIPSN64?

> +            syscall_num = env->active_tc.gpr[2] - 5000;
> +            /* MIPS64 has eight argument registers so there is
> +             * no need to get arguments from stack
> +             */
> +            ret = do_syscall(env, env->active_tc.gpr[2],
> +                             env->active_tc.gpr[4],
> +                             env->active_tc.gpr[5],
> +                             env->active_tc.gpr[6],
> +                             env->active_tc.gpr[7],
> +                             env->active_tc.gpr[8],
> +                             env->active_tc.gpr[9],
> +                             env->active_tc.gpr[10],
> +                             env->active_tc.gpr[11]);
> +#else
> +            syscall_num = env->active_tc.gpr[2] - 4000;
>              if (syscall_num >= sizeof(mips_syscall_args)) {
>                  ret = -TARGET_ENOSYS;
>              } else {
> @@ -2205,6 +2221,7 @@ void cpu_loop(CPUMIPSState *env)
>                                   env->active_tc.gpr[7],
>                                   arg5, arg6, arg7, arg8);
>              }
> +#endif
>  done_syscall:
>              if (ret == -TARGET_QEMU_ESIGRETURN) {
>                  /* Returning from a successful sigreturn syscall.

> diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h
> index 668a2b9..96f03da 100644
> --- a/linux-user/mips64/syscall.h
> +++ b/linux-user/mips64/syscall.h
> @@ -218,4 +218,6 @@ struct target_pt_regs {
>  
>  
>  
> +#define TARGET_QEMU_ESIGRETURN 255
> +
>  #define UNAME_MACHINE "mips64"

Andreas

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 2/3] target-mips:enabling of 64 bit user mode and floating point operations MIPS_HFLAG_UX is included in env->hflags so that the address computation for LD instruction does not treated as 32 bit code see gen_op_addr_add() in translate.c
  2011-12-08  5:25 ` [Qemu-devel] [PATCH 2/3] target-mips:enabling of 64 bit user mode and floating point operations MIPS_HFLAG_UX is included in env->hflags so that the address computation for LD instruction does not treated as 32 bit code see gen_op_addr_add() in translate.c khansa
@ 2011-12-09  0:04   ` Andreas Färber
  2011-12-14 17:05     ` Richard Henderson
  0 siblings, 1 reply; 16+ messages in thread
From: Andreas Färber @ 2011-12-09  0:04 UTC (permalink / raw)
  To: khansa
  Cc: peter.maydell, Nathan Froyd, Stefan Weil, riku.voipio,
	qemu-devel, aurelien

Thanks for extending the commit description. Please see this for a
template though:

http://live.gnome.org/Git/CommitMessages

Looks like there's an empty line missing between subject and description
(and the space after "target-mips:").

Am 08.12.2011 06:25, schrieb khansa@kics.edu.pk:
> From: Khansa Butt <khansa@kics.edu.pk>
> 
> 
> Signed-off-by: Abdul Qadeer <qadeer@kics.edu.pk>
> ---
>  target-mips/translate.c |    4 ++++
>  1 files changed, 4 insertions(+), 0 deletions(-)
> 
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index d5b1c76..452a63b 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -12779,6 +12779,10 @@ void cpu_reset (CPUMIPSState *env)
>          env->hflags |= MIPS_HFLAG_FPU;
>      }
>  #ifdef TARGET_MIPS64
> +    env->hflags |=  MIPS_HFLAG_UX;

So for those of us not knowing mips, it's defined as:

#define MIPS_HFLAG_UX     0x00200 /* 64-bit user mode                 */

The code above is inside CONFIG_USER_ONLY, so this looks right for n64
but not for n32 ABI.

If you put this into its own patch with a description of

---8<---
target-mips: Enable 64 bit user mode for n64

For user mode n64 ABI emulation, MIPS_HFLAG_UX is included in
env->hflags so that the address computation for LD instruction does not
get treated as 32 bit code, see gen_op_addr_add() in translate.c.

Signed-off-by: Abdul Qadeer <qadeer@kics.edu.pk>
Signed-off-by: (you)
---8<---

and make it depend on TARGET_ABI_MIPSN64 then I will happily add my
Acked-by.


> +    /* if cpu has FPU, MIPS_HFLAG_F64 must be included in env->hflags
> +       so that floating point operations can be emulated */
> +    env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
>      if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
>          env->hflags |= MIPS_HFLAG_F64;
>      }

Nack. env->active_fpu.fcr0 gets initialized in translate_init.c based on
cpu_model->CR1_fcr0, where FCR0_F64 is set only for 24Kf, 34Kf,
MIPS64R2-generic. TARGET_ABI_MIPSN64 linux-user defaults to 20Kc. So it
seems to rather be an issue of using the right -cpu parameter or
changing the default for n64. [cc'ing Nathan, who introduced the if]

Andreas

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 1/3] linux-user:Support for MIPS64 user mode emulation in QEMU
  2011-12-08 15:15   ` Andreas Färber
@ 2011-12-09  0:18     ` Andreas Färber
  2011-12-14 16:04     ` Richard Henderson
  1 sibling, 0 replies; 16+ messages in thread
From: Andreas Färber @ 2011-12-09  0:18 UTC (permalink / raw)
  To: khansa; +Cc: peter.maydell, riku.voipio, qemu-devel, aurelien

Am 08.12.2011 16:15, schrieb Andreas Färber:
>> diff --git a/configure b/configure
>> index ac4840d..e31229b 100755
>> --- a/configure
>> +++ b/configure
>> @@ -914,6 +914,7 @@ m68k-linux-user \
>>  microblaze-linux-user \
>>  microblazeel-linux-user \
>>  mips-linux-user \
>> +mips64-linux-user \
>>  mipsel-linux-user \

> For linux-user IIUC the ABI is relevant, so shouldn't this be
> mipsn64-linux-user?

Self-nack. "mips64" already sets TARGET_ABI_MIPSN64 so the naming is OK.

> What about mipsn64el?

Question still applies, be it mipsel64 or mips64el.

Andreas

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 1/3] linux-user:Support for MIPS64 user mode emulation in QEMU
  2011-12-08 15:15   ` Andreas Färber
  2011-12-09  0:18     ` Andreas Färber
@ 2011-12-14 16:04     ` Richard Henderson
  1 sibling, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2011-12-14 16:04 UTC (permalink / raw)
  To: Andreas Färber
  Cc: peter.maydell, riku.voipio, khansa, qemu-devel, aurelien

On 12/08/2011 07:15 AM, Andreas Färber wrote:
> For linux-user IIUC the ABI is relevant, so shouldn't this be
> mipsn64-linux-user? We have a patch for mipsn32/mipsn32el. What about
> mipsn64el?

The compiler flags are -mabi={32,n32,64,o64}, so no, not "n64".
But yes, we should have an "el" version.

>> +#if defined(TARGET_MIPS64)
> TARGET_ABI_MIPSN64?
> 

Definitely.


r~

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 3/3] linux-user:Signal handling for MIPS64
  2011-12-08  5:25 ` [Qemu-devel] [PATCH 3/3] linux-user:Signal handling for MIPS64 khansa
@ 2011-12-14 16:20   ` Richard Henderson
  2011-12-28 11:09     ` Khansa Butt
  2011-12-29 10:58     ` Khansa Butt
  0 siblings, 2 replies; 16+ messages in thread
From: Richard Henderson @ 2011-12-14 16:20 UTC (permalink / raw)
  To: khansa; +Cc: peter.maydell, riku.voipio, qemu-devel, aurelien

On 12/07/2011 09:25 PM, khansa@kics.edu.pk wrote:
> +#if defined(TARGET_MIPS64)
> +        /* tswapal() do 64 bit swap in case of MIPS64 but
> +           we need 32 bit swap as sa_flags is 32 bit */
> +        k->sa_flags = bswap32(act->sa_flags);
> +#else
>          k->sa_flags = tswapal(act->sa_flags);
> +#endif

The condition in syscall_defs.h is TARGET_MIPS, not TARGET_MIPS64.
They should match, despite the fact that it doesn't actually matter
for the 32-bit abis.

>  #elif defined(TARGET_ABI_MIPSN64)
>  
> -# warning signal handling not implemented
> +struct target_sigcontext {
> +    uint32_t   sc_regmask;     /* Unused */
> +    uint32_t   sc_status;

There's no reason to duplicate all this code.  Yes, when someone wrote
this in the first place, they wrote separate sectons for each mips abi.
However, as you can see that huge portions of this block are identical,
this was obviously a mistake.

Start by changing the original section to #elif defined(TARGET_MIPS)
and see what needs changing specifically for the ABIs.  I'm not even
sure there are any differences at all.


r~

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 2/3] target-mips:enabling of 64 bit user mode and floating point operations MIPS_HFLAG_UX is included in env->hflags so that the address computation for LD instruction does not treated as 32 bit code see gen_op_addr_add() in translate.c
  2011-12-09  0:04   ` Andreas Färber
@ 2011-12-14 17:05     ` Richard Henderson
  0 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2011-12-14 17:05 UTC (permalink / raw)
  To: Andreas Färber
  Cc: peter.maydell, Nathan Froyd, Stefan Weil, riku.voipio,
	qemu-devel, khansa, aurelien

On 12/08/2011 04:04 PM, Andreas Färber wrote:
>> > +    /* if cpu has FPU, MIPS_HFLAG_F64 must be included in env->hflags
>> > +       so that floating point operations can be emulated */
>> > +    env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
>> >      if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
>> >          env->hflags |= MIPS_HFLAG_F64;
>> >      }
> Nack. env->active_fpu.fcr0 gets initialized in translate_init.c based on
> cpu_model->CR1_fcr0, where FCR0_F64 is set only for 24Kf, 34Kf,
> MIPS64R2-generic. TARGET_ABI_MIPSN64 linux-user defaults to 20Kc. So it
> seems to rather be an issue of using the right -cpu parameter or
> changing the default for n64. [cc'ing Nathan, who introduced the if]

That said, there's still something missing, e.g. MIPS_HFLAG_COP1X.
My first guess is simply

    if (env->insn_flags & (ISA_MIPS32 | ISA_MIPS4)) {
        env->hflags |= MIPS_HFLAG_COP1X;
    }

immediately after this MIPS64 hunk.


r~

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 3/3] linux-user:Signal handling for MIPS64
  2011-12-14 16:20   ` Richard Henderson
@ 2011-12-28 11:09     ` Khansa Butt
  2011-12-29 10:58     ` Khansa Butt
  1 sibling, 0 replies; 16+ messages in thread
From: Khansa Butt @ 2011-12-28 11:09 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel

On Wed, Dec 14, 2011 at 9:20 PM, Richard Henderson <rth@twiddle.net> wrote:
> On 12/07/2011 09:25 PM, khansa@kics.edu.pk wrote:
>> +#if defined(TARGET_MIPS64)
>> +        /* tswapal() do 64 bit swap in case of MIPS64 but
>> +           we need 32 bit swap as sa_flags is 32 bit */
>> +        k->sa_flags = bswap32(act->sa_flags);
>> +#else
>>          k->sa_flags = tswapal(act->sa_flags);
>> +#endif
>
> The condition in syscall_defs.h is TARGET_MIPS, not TARGET_MIPS64.
> They should match, despite the fact that it doesn't actually matter
> for the 32-bit abis.
>

actually sa_flags is 32 bit for MIPS64 but tswapal calls tswap64() as
TARGET_LONG_SIZE != 4
in case of MIPS64( see cpu-all.h) hence sa_flags has wrong value at
the end so I used above hunk

>>  #elif defined(TARGET_ABI_MIPSN64)
>>
>> -# warning signal handling not implemented
>> +struct target_sigcontext {
>> +    uint32_t   sc_regmask;     /* Unused */
>> +    uint32_t   sc_status;
>
> There's no reason to duplicate all this code.  Yes, when someone wrote
> this in the first place, they wrote separate sectons for each mips abi.
> However, as you can see that huge portions of this block are identical,
> this was obviously a mistake.
>
> Start by changing the original section to #elif defined(TARGET_MIPS)
> and see what needs changing specifically for the ABIs.  I'm not even
> sure there are any differences at all.
>
>
> r~

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 3/3] linux-user:Signal handling for MIPS64
  2011-12-14 16:20   ` Richard Henderson
  2011-12-28 11:09     ` Khansa Butt
@ 2011-12-29 10:58     ` Khansa Butt
  2011-12-29 11:23       ` Andreas Färber
  1 sibling, 1 reply; 16+ messages in thread
From: Khansa Butt @ 2011-12-29 10:58 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Andreas Färber, qemu-devel

On Wed, Dec 14, 2011 at 9:20 PM, Richard Henderson <rth@twiddle.net> wrote:
> On 12/07/2011 09:25 PM, khansa@kics.edu.pk wrote:
>> +#if defined(TARGET_MIPS64)
>> +        /* tswapal() do 64 bit swap in case of MIPS64 but
>> +           we need 32 bit swap as sa_flags is 32 bit */
>> +        k->sa_flags = bswap32(act->sa_flags);
>> +#else
>>          k->sa_flags = tswapal(act->sa_flags);
>> +#endif
>
> The condition in syscall_defs.h is TARGET_MIPS, not TARGET_MIPS64.
> They should match, despite the fact that it doesn't actually matter
> for the 32-bit abis.
>
>>  #elif defined(TARGET_ABI_MIPSN64)
>>
>> -# warning signal handling not implemented
>> +struct target_sigcontext {
>> +    uint32_t   sc_regmask;     /* Unused */
>> +    uint32_t   sc_status;
>
> There's no reason to duplicate all this code.  Yes, when someone wrote
> this in the first place, they wrote separate sectons for each mips abi.
> However, as you can see that huge portions of this block are identical,
> this was obviously a mistake.
>
> Start by changing the original section to #elif defined(TARGET_MIPS)
> and see what needs changing specifically for the ABIs.  I'm not even
> sure there are any differences at all.

The difference lies in setup_frame(). the trampoline function needs
syscall number
    install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
sigreturn is not defined for MIPS64 instead it has only rt_sigreturn.
I tried with #elif defined(TARGET_MIPS). cross compile the following
small program and run it on
qemu-mips64
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

struct sigaction act;

void sighandler(int signum, siginfo_t *info, void *ptr)
{
    printf("Received signal %d\n", signum);
    printf("Signal originates from process %lu\n",(unsigned long)info->si_pid);
}

int main()
{
    printf("I am %lu\n", (unsigned long)getpid());

    memset(&act, 0, sizeof(act));

    act.sa_sigaction = sighandler;
    act.sa_flags = SA_SIGINFO;

    sigaction(SIGILL, &act, NULL);

    // Waiting
    sleep(100);

    return 0;
}

and again I found that only install_sigtramp line is needed to be changed.
keeping  #elif defined(TARGET_MIPS) above signal handling portion, can i use
 #if defined(TARGET_MIPS64)
 ....
#else
for install_sigtramp() difference
>
>
> r~

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH 3/3] linux-user:Signal handling for MIPS64
  2011-12-29 10:58     ` Khansa Butt
@ 2011-12-29 11:23       ` Andreas Färber
  0 siblings, 0 replies; 16+ messages in thread
From: Andreas Färber @ 2011-12-29 11:23 UTC (permalink / raw)
  To: Khansa Butt; +Cc: qemu-devel, Richard Henderson

Am 29.12.2011 11:58, schrieb Khansa Butt:
> On Wed, Dec 14, 2011 at 9:20 PM, Richard Henderson <rth@twiddle.net> wrote:
>> On 12/07/2011 09:25 PM, khansa@kics.edu.pk wrote:
>>> +#if defined(TARGET_MIPS64)
>>> +        /* tswapal() do 64 bit swap in case of MIPS64 but
>>> +           we need 32 bit swap as sa_flags is 32 bit */
>>> +        k->sa_flags = bswap32(act->sa_flags);
>>> +#else
>>>          k->sa_flags = tswapal(act->sa_flags);
>>> +#endif
>>
>> The condition in syscall_defs.h is TARGET_MIPS, not TARGET_MIPS64.
>> They should match, despite the fact that it doesn't actually matter
>> for the 32-bit abis.
>>
>>>  #elif defined(TARGET_ABI_MIPSN64)
>>>
>>> -# warning signal handling not implemented
>>> +struct target_sigcontext {
>>> +    uint32_t   sc_regmask;     /* Unused */
>>> +    uint32_t   sc_status;
>>
>> There's no reason to duplicate all this code.  Yes, when someone wrote
>> this in the first place, they wrote separate sectons for each mips abi.
>> However, as you can see that huge portions of this block are identical,
>> this was obviously a mistake.
>>
>> Start by changing the original section to #elif defined(TARGET_MIPS)
>> and see what needs changing specifically for the ABIs.  I'm not even
>> sure there are any differences at all.
> 
> The difference lies in setup_frame(). the trampoline function needs
> syscall number
>     install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
> sigreturn is not defined for MIPS64 instead it has only rt_sigreturn.
> I tried with #elif defined(TARGET_MIPS). cross compile the following
> small program and run it on
> qemu-mips64
> #include <stdio.h>
> #include <signal.h>
> #include <string.h>
> #include <unistd.h>
> 
> struct sigaction act;
> 
> void sighandler(int signum, siginfo_t *info, void *ptr)
> {
>     printf("Received signal %d\n", signum);
>     printf("Signal originates from process %lu\n",(unsigned long)info->si_pid);
> }
> 
> int main()
> {
>     printf("I am %lu\n", (unsigned long)getpid());
> 
>     memset(&act, 0, sizeof(act));
> 
>     act.sa_sigaction = sighandler;
>     act.sa_flags = SA_SIGINFO;
> 
>     sigaction(SIGILL, &act, NULL);
> 
>     // Waiting
>     sleep(100);
> 
>     return 0;
> }
> 
> and again I found that only install_sigtramp line is needed to be changed.
> keeping  #elif defined(TARGET_MIPS) above signal handling portion, can i use
>  #if defined(TARGET_MIPS64)
>  ....
> #else
> for install_sigtramp() difference

That's not the only difference - the sigcontext is different, too, for
instance. I hope to get something finished for n32 later today.

Andreas

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 3/3] linux-user:Signal handling for MIPS64
  2011-11-30 11:07 [Qemu-devel] [PATCH 0/3] MIPS64 user mode emulation in QEMU with Cavium specific instruction support khansa
@ 2011-11-30 11:07 ` khansa
  0 siblings, 0 replies; 16+ messages in thread
From: khansa @ 2011-11-30 11:07 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, riku.voipio, Khansa Butt, aurelien

From: Khansa Butt <khansa@kics.edu.pk>


Signed-off-by: Khansa Butt <khansa@kics.edu.pk>
---
 linux-user/signal.c |  429 +++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 417 insertions(+), 12 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 78e3380..0f4091d 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -596,7 +596,13 @@ 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_MIPS64)
+        /* tswapal() do 64 bit swap in case of MIPS64 but
+           we need 32 bit swap as sa_flags is 32 bit */
+        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
@@ -2416,31 +2422,430 @@ void sparc64_get_context(CPUSPARCState *env)
 #endif
 #elif defined(TARGET_ABI_MIPSN64)
 
-# warning signal handling not implemented
+struct target_sigcontext {
+    uint32_t   sc_regmask;     /* Unused */
+    uint32_t   sc_status;
+    uint64_t   sc_pc;
+    uint64_t   sc_regs[32];
+    uint64_t   sc_fpregs[32];
+    uint32_t   sc_ownedfp;     /* Unused */
+    uint32_t   sc_fpc_csr;
+    uint32_t   sc_fpc_eir;     /* Unused */
+    uint32_t   sc_used_math;
+    uint32_t   sc_dsp;         /* dsp status, was sc_ssflags */
+    uint32_t   pad0;
+    uint64_t   sc_mdhi;
+    uint64_t   sc_mdlo;
+    target_ulong   sc_hi1;         /* Was sc_cause */
+    target_ulong   sc_lo1;         /* Was sc_badvaddr */
+    target_ulong   sc_hi2;         /* Was sc_sigset[4] */
+    target_ulong   sc_lo2;
+    target_ulong   sc_hi3;
+    target_ulong   sc_lo3;
+};
+
+struct sigframe {
+    uint32_t sf_ass[4];         /* argument save space for o32 */
+    uint32_t sf_code[2];            /* signal trampoline */
+    struct target_sigcontext sf_sc;
+    target_sigset_t sf_mask;
+};
+
+struct target_ucontext {
+    target_ulong tuc_flags;
+    target_ulong tuc_link;
+    target_stack_t tuc_stack;
+    target_ulong pad0;
+    struct target_sigcontext tuc_mcontext;
+    target_sigset_t tuc_sigmask;
+};
+
+struct target_rt_sigframe {
+    uint32_t rs_ass[4];               /* argument save space for o32 */
+    uint32_t rs_code[2];              /* signal trampoline */
+    struct target_siginfo rs_info;
+    struct target_ucontext rs_uc;
+};
+
+/* Install trampoline to jump back from signal handler */
+static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall)
+{
+    int err;
+
+    /*
+     * Set up the return code ...
+     *
+     *         li      v0, __NR__foo_sigreturn
+     *         syscall
+     */
+
+    err = __put_user(0x24020000 + syscall, tramp + 0);
+    err |= __put_user(0x0000000c          , tramp + 1);
+    /* flush_cache_sigtramp((unsigned long) tramp); */
+    return err;
+}
+
+static inline int
+setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
+{
+    int err = 0;
+
+    err |= __put_user(regs->active_tc.PC, &sc->sc_pc);
+
+#define save_gp_reg(i) do {                         \
+        err |= __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); \
+} while (0)
+    __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
+    save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
+    save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
+    save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
+    save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
+    save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
+    save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
+    save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
+    save_gp_reg(31);
+#undef save_gp_reg
+
+    err |= __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
+    err |= __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
+
+    /* Not used yet, but might be useful if we ever have DSP suppport */
+#if 0
+    if (cpu_has_dsp) {
+        err |= __put_user(mfhi1(), &sc->sc_hi1);
+        err |= __put_user(mflo1(), &sc->sc_lo1);
+        err |= __put_user(mfhi2(), &sc->sc_hi2);
+        err |= __put_user(mflo2(), &sc->sc_lo2);
+        err |= __put_user(mfhi3(), &sc->sc_hi3);
+        err |= __put_user(mflo3(), &sc->sc_lo3);
+        err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+    }
+    /* same with 64 bit */
+#ifdef CONFIG_64BIT
+    err |= __put_user(regs->hi, &sc->sc_hi[0]);
+    err |= __put_user(regs->lo, &sc->sc_lo[0]);
+    if (cpu_has_dsp) {
+        err |= __put_user(mfhi1(), &sc->sc_hi[1]);
+        err |= __put_user(mflo1(), &sc->sc_lo[1]);
+        err |= __put_user(mfhi2(), &sc->sc_hi[2]);
+        err |= __put_user(mflo2(), &sc->sc_lo[2]);
+        err |= __put_user(mfhi3(), &sc->sc_hi[3]);
+        err |= __put_user(mflo3(), &sc->sc_lo[3]);
+        err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+    }
+#endif
+#endif
+
+#if 0
+    err |= __put_user(!!used_math(), &sc->sc_used_math);
+
+    if (!used_math())
+        goto out;
+
+    /*
+     * Save FPU state to signal context.  Signal handler will "inherit"
+     * current FPU state.
+     */
+    preempt_disable();
+
+    if (!is_fpu_owner()) {
+        own_fpu();
+        restore_fp(current);
+    }
+    err |= save_fp_context(sc);
+
+    preempt_enable();
+    out:
+#endif
+    return err;
+}
+
+static inline int
+restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
+{
+    int err = 0;
+
+    err |= __get_user(regs->CP0_EPC, &sc->sc_pc);
+
+    err |= __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
+    err |= __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
+
+#define restore_gp_reg(i) do {                               \
+        err |= __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);     \
+} while (0)
+    restore_gp_reg(1); restore_gp_reg(2); restore_gp_reg(3);
+    restore_gp_reg(4); restore_gp_reg(5); restore_gp_reg(6);
+    restore_gp_reg(7); restore_gp_reg(8); restore_gp_reg(9);
+    restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
+    restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
+    restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
+    restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
+    restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
+    restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
+    restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
+    restore_gp_reg(31);
+#undef restore_gp_reg
+
+#if 0
+    if (cpu_has_dsp) {
+        err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
+        err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
+        err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
+        err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
+        err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
+        err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
+        err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+    }
+#ifdef CONFIG_64BIT
+    err |= __get_user(regs->hi, &sc->sc_hi[0]);
+    err |= __get_user(regs->lo, &sc->sc_lo[0]);
+    if (cpu_has_dsp) {
+        err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
+        err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
+        err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
+        err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
+        err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
+        err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
+        err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+    }
+#endif
+
+    err |= __get_user(used_math, &sc->sc_used_math);
+    conditional_used_math(used_math);
+
+    preempt_disable();
+
+    if (used_math()) {
+        /* restore fpu context if we have used it before */
+        own_fpu();
+        err |= restore_fp_context(sc);
+    } else {
+        /* signal handler may have used FPU.  Give it up. */
+        lose_fpu();
+    }
+
+    preempt_enable();
+#endif
+    return err;
+}
+/*
+ * Determine which stack to use..
+ */
+static inline abi_ulong
+get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t frame_size)
+{
+    unsigned long sp;
+
+    /* Default to using normal stack */
+    sp = regs->active_tc.gpr[29];
 
+    /*
+     * FPU emulator may have it's own trampoline active just
+     * above the user stack, 16-bytes before the next lowest
+     * 16 byte boundary.  Try to avoid trashing it.
+     */
+    sp -= 32;
+
+    /* This is the X/Open sanctioned signal stack switching.  */
+    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
+        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_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 *env)
+        target_sigset_t *set, CPUState *regs)
 {
-    fprintf(stderr, "setup_frame: not implemented\n");
+    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_rt_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;
 }
 
-static void setup_rt_frame(int sig, struct target_sigaction *ka,
-                           target_siginfo_t *info,
-			   target_sigset_t *set, CPUState *env)
+long do_sigreturn(CPUState *regs)
 {
-    fprintf(stderr, "setup_rt_frame: not implemented\n");
+    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;
 }
 
-long do_sigreturn(CPUState *env)
+static void setup_rt_frame(int sig, struct target_sigaction *ka,
+        target_siginfo_t *info,
+        target_sigset_t *set, CPUState *env)
 {
-    fprintf(stderr, "do_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
+    struct target_rt_sigframe *frame;
+    abi_ulong frame_addr;
+    int i;
+
+    frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+        goto give_sigsegv;
+
+    install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
+
+    copy_siginfo_to_user(&frame->rs_info, info);
+
+    __put_user(0, &frame->rs_uc.tuc_flags);
+    __put_user(0, &frame->rs_uc.tuc_link);
+    __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp);
+    __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size);
+    __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
+            &frame->rs_uc.tuc_stack.ss_flags);
+
+    setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
+
+    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+        __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
+    }
+
+    /*
+     * Arguments to signal handler:
+     *
+     *   a0 = signal number
+     *   a1 = pointer to struct siginfo
+     *   a2 = pointer to struct ucontext
+     *
+     * $25 and PC point to the signal handler, $29 points to the
+     * struct sigframe.
+     */
+    env->active_tc.gpr[4] = sig;
+    env->active_tc.gpr[5] = frame_addr
+            + offsetof(struct target_rt_sigframe, rs_info);
+    env->active_tc.gpr[6] = frame_addr
+            + offsetof(struct target_rt_sigframe, rs_uc);
+    env->active_tc.gpr[29] = frame_addr;
+    env->active_tc.gpr[31] = frame_addr
+            + offsetof(struct target_rt_sigframe, rs_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 */
+    env->active_tc.PC = env->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_rt_sigreturn(CPUState *env)
 {
-    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
+        struct target_rt_sigframe *frame;
+        abi_ulong frame_addr;
+        sigset_t blocked;
+
+#if defined(DEBUG_SIGNAL)
+        fprintf(stderr, "do_rt_sigreturn\n");
+#endif
+        frame_addr = env->active_tc.gpr[29];
+        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
+            goto badframe;
+
+        target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
+        sigprocmask(SIG_SETMASK, &blocked, NULL);
+
+        if (restore_sigcontext(env, &frame->rs_uc.tuc_mcontext))
+            goto badframe;
+
+        if (do_sigaltstack(frame_addr +
+                offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
+                0, get_sp_from_cpustate(env)) == -EFAULT)
+            goto badframe;
+
+        env->active_tc.PC = env->CP0_EPC;
+        /* I am not sure this is right, but it seems to work
+         * maybe a problem with nested signals ? */
+        env->CP0_EPC = 0;
+        return -TARGET_QEMU_ESIGRETURN;
+
+        badframe:
+        force_sig(TARGET_SIGSEGV/*, current*/);
+        return 0;
 }
 
 #elif defined(TARGET_ABI_MIPSN32)
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [Qemu-devel] [PATCH 3/3] linux-user:Signal handling for MIPS64
@ 2011-04-29  6:20 Khansa Butt
  0 siblings, 0 replies; 16+ messages in thread
From: Khansa Butt @ 2011-04-29  6:20 UTC (permalink / raw)
  To: Riku Voipio, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 13287 bytes --]

>From 1ab1973118d9e676fcaaf234d153c8c7056aa82a Mon Sep 17 00:00:00 2001
From: Ehsan-ul-Haq, Abdul Qadeer, Abdul Waheed, Khansa Butt <
khansa@kics.edu.pk>
Date: Fri, 29 Apr 2011 10:52:38 +0500
Subject: [PATCH 3/3] linux-user:Signal handling for MIPS64


Signed-off-by: Khansa Butt <khansa@kics.edu.pk>
---
 linux-user/signal.c       |  331
+++++++++++++++++++++++++++++++++++++++++++--
 linux-user/syscall_defs.h |    4 +
 2 files changed, 325 insertions(+), 10 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 66786db..e387a5b 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -221,7 +221,11 @@ static inline void
host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
         /* XXX: potential problem if 64 bit */
         tinfo->_sifields._rt._sigval.sival_ptr =
             (abi_ulong)(unsigned long)info->si_value.sival_ptr;
+    } else {
+        tinfo->_sifields._kill._pid = info->si_pid;
+        tinfo->_sifields._kill._uid = info->si_uid;
     }
+
 }

 static void tswap_siginfo(target_siginfo_t *tinfo,
@@ -243,6 +247,9 @@ static void tswap_siginfo(target_siginfo_t *tinfo,
         tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid);
         tinfo->_sifields._rt._sigval.sival_ptr =
             tswapl(info->_sifields._rt._sigval.sival_ptr);
+    } else {
+        tinfo->_sifields._kill._pid = tswap32(info->_sifields._kill._pid);
+        tinfo->_sifields._kill._uid = tswap32(info->_sifields._kill._uid);
     }
 }

@@ -2413,28 +2420,332 @@ void sparc64_get_context(CPUSPARCState *env)
 #endif
 #elif defined(TARGET_ABI_MIPSN64)

-static void setup_frame(int sig, struct target_sigaction *ka,
- target_sigset_t *set, CPUState *env)
+struct target_sigcontext {
+    uint32_t   sc_regmask;     /* Unused */
+    uint32_t   sc_status;
+    uint64_t   sc_pc;
+    uint64_t   sc_regs[32];
+    uint64_t   sc_fpregs[32];
+    uint32_t   sc_ownedfp;     /* Unused */
+    uint32_t   sc_fpc_csr;
+    uint32_t   sc_fpc_eir;     /* Unused */
+    uint32_t   sc_used_math;
+    uint32_t   sc_dsp;         /* dsp status, was sc_ssflags */
+    uint32_t   pad0;
+    uint64_t   sc_mdhi;
+    uint64_t   sc_mdlo;
+    target_ulong   sc_hi1;         /* Was sc_cause */
+    target_ulong   sc_lo1;         /* Was sc_badvaddr */
+    target_ulong   sc_hi2;         /* Was sc_sigset[4] */
+    target_ulong   sc_lo2;
+    target_ulong   sc_hi3;
+    target_ulong   sc_lo3;
+};
+
+struct target_ucontext {
+    target_ulong tuc_flags;
+    target_ulong tuc_link;
+    target_stack_t tuc_stack;
+    struct target_sigcontext tuc_mcontext;
+    target_sigset_t tuc_sigmask;
+};
+
+struct target_rt_sigframe {
+    uint64_t rs_ass[8];               /* argument save space for n64 */
+    uint32_t rs_code[2];              /* signal trampoline */
+    struct target_siginfo rs_info;
+    struct target_ucontext rs_uc;
+};
+
+/* Install trampoline to jump back from signal handler */
+static inline int install_sigtramp(unsigned int *tramp,   unsigned int
syscall)
 {
-    fprintf(stderr, "setup_frame: not implemented\n");
+    int err;
+
+    /*
+    * Set up the return code ...
+    *
+    *         li      v0, __NR__foo_sigreturn
+    *         syscall
+    */
+
+    err = __put_user(0x24020000 + syscall, tramp + 0);
+    err |= __put_user(0x0000000c          , tramp + 1);
+    /* flush_cache_sigtramp((unsigned long) tramp); */
+    return err;
+}
+
+static inline int
+setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
+{
+    int err = 0;
+
+    err |= __put_user(regs->active_tc.PC, &sc->sc_pc);
+
+#define save_gp_reg(i) do {                         \
+        err |= __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); \
+    } while (0)
+    __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
+    save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
+    save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
+    save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
+    save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
+    save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
+    save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
+    save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
+    save_gp_reg(31);
+#undef save_gp_reg
+
+    err |= __put_user(regs->active_tc.HI[0], &sc->sc_mdhi);
+    err |= __put_user(regs->active_tc.LO[0], &sc->sc_mdlo);
+
+    /* Not used yet, but might be useful if we ever have DSP suppport */
+#if 0
+    if (cpu_has_dsp) {
+    err |= __put_user(mfhi1(), &sc->sc_hi1);
+    err |= __put_user(mflo1(), &sc->sc_lo1);
+    err |= __put_user(mfhi2(), &sc->sc_hi2);
+    err |= __put_user(mflo2(), &sc->sc_lo2);
+    err |= __put_user(mfhi3(), &sc->sc_hi3);
+    err |= __put_user(mflo3(), &sc->sc_lo3);
+    err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+    }
+    /* same with 64 bit */
+#ifdef CONFIG_64BIT
+    err |= __put_user(regs->hi, &sc->sc_hi[0]);
+    err |= __put_user(regs->lo, &sc->sc_lo[0]);
+    if (cpu_has_dsp) {
+    err |= __put_user(mfhi1(), &sc->sc_hi[1]);
+    err |= __put_user(mflo1(), &sc->sc_lo[1]);
+    err |= __put_user(mfhi2(), &sc->sc_hi[2]);
+    err |= __put_user(mflo2(), &sc->sc_lo[2]);
+    err |= __put_user(mfhi3(), &sc->sc_hi[3]);
+    err |= __put_user(mflo3(), &sc->sc_lo[3]);
+    err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+    }
+#endif
+#endif
+
+#if 0
+    err |= __put_user(!!used_math(), &sc->sc_used_math);
+
+    if (!used_math())
+    goto out;
+
+    /*
+    * Save FPU state to signal context.  Signal handler will "inherit"
+    * current FPU state.
+    */
+    preempt_disable();
+
+    if (!is_fpu_owner()) {
+    own_fpu();
+    restore_fp(current);
+    }
+    err |= save_fp_context(sc);
+
+    preempt_enable();
+    out:
+#endif
+    return err;
+}
+
+static inline int
+restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
+{
+    int err = 0;
+
+    err |= __get_user(regs->CP0_EPC, &sc->sc_pc);
+
+    err |= __get_user(regs->active_tc.HI[0], &sc->sc_mdhi);
+    err |= __get_user(regs->active_tc.LO[0], &sc->sc_mdlo);
+
+#define restore_gp_reg(i) do {                              \
+        err |= __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]);     \
+    } while (0)
+    restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
+    restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
+    restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
+    restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
+    restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
+    restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
+    restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
+    restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
+    restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
+    restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
+    restore_gp_reg(31);
+#undef restore_gp_reg
+
+#if 0
+    if (cpu_has_dsp) {
+    err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
+    err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
+    err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
+    err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
+    err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
+    err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
+    err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+    }
+#ifdef CONFIG_64BIT
+    err |= __get_user(regs->hi, &sc->sc_hi[0]);
+    err |= __get_user(regs->lo, &sc->sc_lo[0]);
+    if (cpu_has_dsp) {
+    err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
+    err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
+    err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
+    err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
+    err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
+    err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
+    err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+    }
+#endif
+
+    err |= __get_user(used_math, &sc->sc_used_math);
+    conditional_used_math(used_math);
+
+    preempt_disable();
+
+    if (used_math()) {
+    /* restore fpu context if we have used it before */
+    own_fpu();
+    err |= restore_fp_context(sc);
+    } else {
+    /* signal handler may have used FPU.  Give it up. */
+    lose_fpu();
+    }
+
+    preempt_enable();
+#endif
+    return err;
+}
+/*
+ * Determine which stack to use..
+ */
+static inline abi_ulong
+get_sigframe(struct target_sigaction *ka, CPUState *regs, size_t
frame_size)
+{
+    unsigned long sp;
+
+    /* Default to using normal stack */
+    sp = regs->active_tc.gpr[29];
+
+    /*
+     * FPU emulator may have it's own trampoline active just
+     * above the user stack, 16-bytes before the next lowest
+     * 16 byte boundary.  Try to avoid trashing it.
+     */
+    sp -= 32;
+
+    /* This is the X/Open sanctioned signal stack switching.  */
+    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) {
+        sp = target_sigaltstack_used.ss_sp +
target_sigaltstack_used.ss_size;
+    }
+
+    return (sp - frame_size) & ~7;
 }

 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-   target_sigset_t *set, CPUState *env)
+               target_sigset_t *set, CPUState *env)
 {
-    fprintf(stderr, "setup_rt_frame: not implemented\n");
+    struct target_rt_sigframe *frame;
+    abi_ulong frame_addr;
+    int i;
+
+    frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+    goto give_sigsegv;
+
+    install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
+
+    copy_siginfo_to_user(&frame->rs_info, info);
+
+    __put_user(0, &frame->rs_uc.tuc_flags);
+    __put_user(0, &frame->rs_uc.tuc_link);
+    __put_user(target_sigaltstack_used.ss_sp,
&frame->rs_uc.tuc_stack.ss_sp);
+    __put_user(target_sigaltstack_used.ss_size,
&frame->rs_uc.tuc_stack.ss_size);
+    __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
+               &frame->rs_uc.tuc_stack.ss_flags);
+
+    setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
+
+    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+        __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
+    }
+
+    /*
+    * Arguments to signal handler:
+    *
+    *   a0 = signal number
+    *   a1 = pointer to struct siginfo
+    *   a2 = pointer to struct ucontext
+    *
+    * $25 and PC point to the signal handler, $29 points to the
+    * struct sigframe.
+    */
+    env->active_tc.gpr[ 4] = sig;
+    env->active_tc.gpr[ 5] = frame_addr
+                             + offsetof(struct target_rt_sigframe,
rs_info);
+    env->active_tc.gpr[ 6] = frame_addr
+                             + offsetof(struct target_rt_sigframe, rs_uc);
+    env->active_tc.gpr[29] = frame_addr;
+    env->active_tc.gpr[31] = frame_addr
+                             + offsetof(struct target_rt_sigframe,
rs_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 */
+    env->active_tc.PC = env->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 *env)
+long do_rt_sigreturn(CPUState *env)
 {
-    fprintf(stderr, "do_sigreturn: not implemented\n");
-    return -TARGET_ENOSYS;
+    struct target_rt_sigframe *frame;
+    abi_ulong frame_addr;
+    sigset_t blocked;
+
+#if defined(DEBUG_SIGNAL)
+    fprintf(stderr, "do_rt_sigreturn\n");
+#endif
+    frame_addr = env->active_tc.gpr[29];
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
+    goto badframe;
+
+    target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
+    sigprocmask(SIG_SETMASK, &blocked, NULL);
+
+    if (restore_sigcontext(env, &frame->rs_uc.tuc_mcontext))
+        goto badframe;
+
+    if (do_sigaltstack(frame_addr +
+               offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
+               0, get_sp_from_cpustate(env)) == -EFAULT)
+        goto badframe;
+
+    env->active_tc.PC = env->CP0_EPC;
+    env->CP0_EPC = 0;
+    return -TARGET_QEMU_ESIGRETURN;
+
+badframe:
+    force_sig(TARGET_SIGSEGV/*, current*/);
+    return 0;
 }

-long do_rt_sigreturn(CPUState *env)
+static void setup_frame(int sig, struct target_sigaction *ka,
+            target_sigset_t *set, CPUState *env)
 {
-    fprintf(stderr, "do_rt_sigreturn: not implemented\n");
+    fprintf(stderr, "setup_frame: not implemented\n");
+}
+
+long do_sigreturn(CPUState *env)
+{
+    fprintf(stderr, "do_sigreturn: not implemented\n");
     return -TARGET_ENOSYS;
 }

diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index bde8921..50a8599 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -506,7 +506,11 @@ struct target_sigaction {
 };
 #elif defined(TARGET_MIPS)
 struct target_sigaction {
+#if defined(TARGET_ABI_MIPSN64)
+    abi_ulong sa_flags;
+#else
  uint32_t sa_flags;
+#endif
 #if defined(TARGET_ABI_MIPSN32)
  uint32_t _sa_handler;
 #else
-- 
1.7.3.4

[-- Attachment #2: Type: text/html, Size: 18509 bytes --]

^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2011-12-29 11:24 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-08  5:25 [Qemu-devel] [PATCH 0/3] MIPS64 user mode emulation in QEMU khansa
2011-12-08  5:25 ` [Qemu-devel] [PATCH 1/3] linux-user:Support for " khansa
2011-12-08 15:15   ` Andreas Färber
2011-12-09  0:18     ` Andreas Färber
2011-12-14 16:04     ` Richard Henderson
2011-12-08  5:25 ` [Qemu-devel] [PATCH 2/3] target-mips:enabling of 64 bit user mode and floating point operations MIPS_HFLAG_UX is included in env->hflags so that the address computation for LD instruction does not treated as 32 bit code see gen_op_addr_add() in translate.c khansa
2011-12-09  0:04   ` Andreas Färber
2011-12-14 17:05     ` Richard Henderson
2011-12-08  5:25 ` [Qemu-devel] [PATCH 3/3] linux-user:Signal handling for MIPS64 khansa
2011-12-14 16:20   ` Richard Henderson
2011-12-28 11:09     ` Khansa Butt
2011-12-29 10:58     ` Khansa Butt
2011-12-29 11:23       ` Andreas Färber
2011-12-08 13:22 ` [Qemu-devel] [PATCH 0/3] MIPS64 user mode emulation in QEMU Andreas Färber
  -- strict thread matches above, loose matches on Subject: below --
2011-11-30 11:07 [Qemu-devel] [PATCH 0/3] MIPS64 user mode emulation in QEMU with Cavium specific instruction support khansa
2011-11-30 11:07 ` [Qemu-devel] [PATCH 3/3] linux-user:Signal handling for MIPS64 khansa
2011-04-29  6:20 Khansa Butt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.