All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART
@ 2015-09-05 23:56 Timothy E Baldwin
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 01/34] linux-user: Fix array bounds in errno conversion Timothy E Baldwin
                   ` (34 more replies)
  0 siblings, 35 replies; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

There are many races with signals in linux user:

 - Multiple host signals in quick succession, fixed by keeping host signals
   blocked, and checking if target signals are blocked before calling
   target signal handler.
 - Signal shortly before blocking system call, fixed by either:
   - Block hosts signals, check and use host system call with
     sigset_t parameter.
   - Or check if signals are pending immediately before host system call
     and if a signal arrives between the check and system call rewind
     host instruction pointer to before the check. Also fixes SA_RESTART.
 - Signal before or during sensitive system call, fixed in a similar manner.
 - Close host and synchronous signals, partly fixed by implementing a separate
   queue for synchronous signals which are dispatched first. The asynchronous
   signal may still be delayed or lost rather than dispatched to another thread
   or handled after exec().

Also fixed:
 - Errno array bounds.
 - Default fatal actions occurring in the middle of target instructions.
 
I have major problems testing the system call restarting:
 - x86, ARM MIPS, PowerPC and SPARC sucessful tested.
 - Microblaze and SH4 works without signals, but signal test case
   crashes with or without my changes.
 - Alpha works without signals, but don't have a toolchain.
   to compile the signal test case.
 - I have been unable to test UniCore32, OpenRISC, M68K, S390
   and CRIS due to a lack of binaries and toolchains.
   
Help would be appreciated - this is the only change I intend to make
to unshared code to all targets.

Outstanding issues:
 - The remaining blocking target system calls.
 - Fatal default actions may be delayed in a broken blocking target
   system call.
 
Timothy E Baldwin (34):
  linux-user: Fix array bounds in errno conversion
  linux-user: Reindent signal handling
  linux-user: Support for restarting system calls
  linux-user: Support for restarting system calls for x86 targets
  linux-user: Support for restarting system calls for ARM targets
  linux-user: Support for restarting system calls for MIPS targets
  linux-user: Support for restarting system calls for PPC targets
  linux-user: Support for restarting system calls for SPARC targets
  linux-user: Test for restarting system calls
  linux-user: Support for restarting system calls for Microblaze targets
  linux-user: Support for restarting system calls for SH4 targets
  linux-user: Support for restarting system calls for APLHA targets
  linux-user: Fix signal before blocking system calls race and
    SA_RESTART
  linux-user: Use safe_syscall for read and write system calls
  linux-user: Remove redundant get_errno() calls
  linux-user: Use safe_syscall for open and openat system calls
  linux-user: Use safe_syscall for wait system calls
  linux-user: Fix race between multiple signals
  linux-user: Restart fork() if signals pending
  linux-user: Remove redundant default action check in queue_signal()
  linux-user: Remove redundant gdb_queuesig()
  linux-user: Remove real-time signal queuing
  linux-user: Queue synchronous signals separately
  linux-user: Restart execve() if signal pending
  linux-user: Restart exit() if signal pending
  linux-user: Restart kill() if signal pending
  linux-user: pause() should not pause if signal pending
  linux-user: Restart sigaction() if signal pending
  linux-user: Support for restarting system calls for UniCore32 targets
  linux-user: Support for restarting system calls for OpenRISC targets
  linux-user: Support for restarting system calls for M68K targets
  linux-user: Support for restarting system calls for S390 targets
  linux-user: Support for restarting system calls for CRIS targets
  linux-user: Remove TARGET_USE_ERESTARTSYS

 configure                        |   13 +
 gdbstub.c                        |   13 -
 include/exec/gdbstub.h           |    1 -
 linux-user/Makefile.objs         |    3 +-
 linux-user/errno_defs.h          |    3 +
 linux-user/main.c                |  210 ++--
 linux-user/mips/syscall.h        |    4 -
 linux-user/mips64/syscall.h      |    4 -
 linux-user/ppc/syscall.h         |    2 -
 linux-user/qemu.h                |   37 +-
 linux-user/safe_syscall/x86_64.S |   34 +
 linux-user/signal.c              | 2012 +++++++++++++++++++-------------------
 linux-user/syscall.c             |  247 ++++-
 13 files changed, 1422 insertions(+), 1161 deletions(-)
 create mode 100644 linux-user/safe_syscall/x86_64.S

-- 
2.1.4

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

* [Qemu-devel] [PATCH 01/34] linux-user: Fix array bounds in errno conversion
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
@ 2015-09-05 23:56 ` Timothy E Baldwin
  2015-09-10 18:04   ` Peter Maydell
  2015-09-11 10:59   ` Peter Maydell
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 02/34] linux-user: Reindent signal handling Timothy E Baldwin
                   ` (33 subsequent siblings)
  34 siblings, 2 replies; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Check array bounds in host_to_target_errno() and target_to_host_errno().

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/syscall.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 264debc..4e40dc6 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -566,14 +566,14 @@ static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
 
 static inline int host_to_target_errno(int err)
 {
-    if(host_to_target_errno_table[err])
+    if(err < ERRNO_TABLE_SIZE && host_to_target_errno_table[err])
         return host_to_target_errno_table[err];
     return err;
 }
 
 static inline int target_to_host_errno(int err)
 {
-    if (target_to_host_errno_table[err])
+    if (err < ERRNO_TABLE_SIZE && target_to_host_errno_table[err])
         return target_to_host_errno_table[err];
     return err;
 }
-- 
2.1.4

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

* [Qemu-devel] [PATCH 02/34] linux-user: Reindent signal handling
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 01/34] linux-user: Fix array bounds in errno conversion Timothy E Baldwin
@ 2015-09-05 23:56 ` Timothy E Baldwin
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 03/34] linux-user: Support for restarting system calls Timothy E Baldwin
                   ` (32 subsequent siblings)
  34 siblings, 0 replies; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Some of the signal handling was a mess with a mixture of tabs and 8 space
indents.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/signal.c | 1691 ++++++++++++++++++++++++++-------------------------
 1 file changed, 867 insertions(+), 824 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 9d4cef4..7c846c0 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -164,7 +164,7 @@ static void target_to_host_sigset_internal(sigset_t *d,
         if (target_sigismember(s, i)) {
             sigaddset(d, target_to_host_signal(i));
         }
-     }
+    }
 }
 
 void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
@@ -257,18 +257,18 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
     tinfo->si_code = info->si_code;
 
     if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV
-        || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
+            || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) {
         /* Should never come here, but who knows. The information for
            the target is irrelevant.  */
         tinfo->_sifields._sigfault._addr = 0;
     } else if (sig == TARGET_SIGIO) {
         tinfo->_sifields._sigpoll._band = info->si_band;
-	tinfo->_sifields._sigpoll._fd = info->si_fd;
+        tinfo->_sifields._sigpoll._fd = info->si_fd;
     } else if (sig == TARGET_SIGCHLD) {
         tinfo->_sifields._sigchld._pid = info->si_pid;
         tinfo->_sifields._sigchld._uid = info->si_uid;
         tinfo->_sifields._sigchld._status
-            = host_to_target_waitstatus(info->si_status);
+                = host_to_target_waitstatus(info->si_status);
         tinfo->_sifields._sigchld._utime = info->si_utime;
         tinfo->_sifields._sigchld._stime = info->si_stime;
     } else if (sig >= TARGET_SIGRTMIN) {
@@ -276,7 +276,7 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
         tinfo->_sifields._rt._uid = info->si_uid;
         /* XXX: potential problem if 64 bit */
         tinfo->_sifields._rt._sigval.sival_ptr
-            = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
+                = (abi_ulong)(unsigned long)info->si_value.sival_ptr;
     }
 }
 
@@ -737,75 +737,75 @@ int do_sigaction(int sig, const struct target_sigaction *act,
 /* from the Linux kernel */
 
 struct target_fpreg {
-	uint16_t significand[4];
-	uint16_t exponent;
+    uint16_t significand[4];
+    uint16_t exponent;
 };
 
 struct target_fpxreg {
-	uint16_t significand[4];
-	uint16_t exponent;
-	uint16_t padding[3];
+    uint16_t significand[4];
+    uint16_t exponent;
+    uint16_t padding[3];
 };
 
 struct target_xmmreg {
-	abi_ulong element[4];
+    abi_ulong element[4];
 };
 
 struct target_fpstate {
-	/* Regular FPU environment */
-        abi_ulong       cw;
-        abi_ulong       sw;
-        abi_ulong       tag;
-        abi_ulong       ipoff;
-        abi_ulong       cssel;
-        abi_ulong       dataoff;
-        abi_ulong       datasel;
-	struct target_fpreg	_st[8];
-	uint16_t	status;
-	uint16_t	magic;		/* 0xffff = regular FPU data only */
-
-	/* FXSR FPU environment */
-        abi_ulong       _fxsr_env[6];   /* FXSR FPU env is ignored */
-        abi_ulong       mxcsr;
-        abi_ulong       reserved;
-	struct target_fpxreg	_fxsr_st[8];	/* FXSR FPU reg data is ignored */
-	struct target_xmmreg	_xmm[8];
-        abi_ulong       padding[56];
+    /* Regular FPU environment */
+    abi_ulong cw;
+    abi_ulong sw;
+    abi_ulong tag;
+    abi_ulong ipoff;
+    abi_ulong cssel;
+    abi_ulong dataoff;
+    abi_ulong datasel;
+    struct target_fpreg _st[8];
+    uint16_t  status;
+    uint16_t  magic;          /* 0xffff = regular FPU data only */
+
+    /* FXSR FPU environment */
+    abi_ulong _fxsr_env[6];   /* FXSR FPU env is ignored */
+    abi_ulong mxcsr;
+    abi_ulong reserved;
+    struct target_fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */
+    struct target_xmmreg _xmm[8];
+    abi_ulong padding[56];
 };
 
 #define X86_FXSR_MAGIC		0x0000
 
 struct target_sigcontext {
-	uint16_t gs, __gsh;
-	uint16_t fs, __fsh;
-	uint16_t es, __esh;
-	uint16_t ds, __dsh;
-        abi_ulong edi;
-        abi_ulong esi;
-        abi_ulong ebp;
-        abi_ulong esp;
-        abi_ulong ebx;
-        abi_ulong edx;
-        abi_ulong ecx;
-        abi_ulong eax;
-        abi_ulong trapno;
-        abi_ulong err;
-        abi_ulong eip;
-	uint16_t cs, __csh;
-        abi_ulong eflags;
-        abi_ulong esp_at_signal;
-	uint16_t ss, __ssh;
-        abi_ulong fpstate; /* pointer */
-        abi_ulong oldmask;
-        abi_ulong cr2;
+    uint16_t gs, __gsh;
+    uint16_t fs, __fsh;
+    uint16_t es, __esh;
+    uint16_t ds, __dsh;
+    abi_ulong edi;
+    abi_ulong esi;
+    abi_ulong ebp;
+    abi_ulong esp;
+    abi_ulong ebx;
+    abi_ulong edx;
+    abi_ulong ecx;
+    abi_ulong eax;
+    abi_ulong trapno;
+    abi_ulong err;
+    abi_ulong eip;
+    uint16_t cs, __csh;
+    abi_ulong eflags;
+    abi_ulong esp_at_signal;
+    uint16_t ss, __ssh;
+    abi_ulong fpstate; /* pointer */
+    abi_ulong oldmask;
+    abi_ulong cr2;
 };
 
 struct target_ucontext {
-        abi_ulong         tuc_flags;
-        abi_ulong         tuc_link;
-	target_stack_t	  tuc_stack;
-	struct target_sigcontext tuc_mcontext;
-	target_sigset_t	  tuc_sigmask;	/* mask last for extensibility */
+    abi_ulong         tuc_flags;
+    abi_ulong         tuc_link;
+    target_stack_t    tuc_stack;
+    struct target_sigcontext tuc_mcontext;
+    target_sigset_t   tuc_sigmask;  /* mask last for extensibility */
 };
 
 struct sigframe
@@ -842,7 +842,7 @@ static void setup_sigcontext(struct target_sigcontext *sc,
     CPUState *cs = CPU(x86_env_get_cpu(env));
     uint16_t magic;
 
-	/* already locked in setup_frame() */
+    /* already locked in setup_frame() */
     __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs);
     __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs);
     __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es);
@@ -863,13 +863,13 @@ static void setup_sigcontext(struct target_sigcontext *sc,
     __put_user(env->regs[R_ESP], &sc->esp_at_signal);
     __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss);
 
-        cpu_x86_fsave(env, fpstate_addr, 1);
-        fpstate->status = fpstate->sw;
-        magic = 0xffff;
+    cpu_x86_fsave(env, fpstate_addr, 1);
+    fpstate->status = fpstate->sw;
+    magic = 0xffff;
     __put_user(magic, &fpstate->magic);
     __put_user(fpstate_addr, &sc->fpstate);
 
-	/* non-iBCS2 extensions.. */
+    /* non-iBCS2 extensions.. */
     __put_user(mask, &sc->oldmask);
     __put_user(env->cr[2], &sc->cr2);
 }
@@ -881,108 +881,110 @@ static void setup_sigcontext(struct target_sigcontext *sc,
 static inline abi_ulong
 get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size)
 {
-	unsigned long esp;
+    unsigned long esp;
 
-	/* Default to using normal stack */
-	esp = env->regs[R_ESP];
-	/* This is the X/Open sanctioned signal stack switching.  */
-        if (ka->sa_flags & TARGET_SA_ONSTACK) {
-            if (sas_ss_flags(esp) == 0)
-                esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+    /* Default to using normal stack */
+    esp = env->regs[R_ESP];
+    /* This is the X/Open sanctioned signal stack switching.  */
+    if (ka->sa_flags & TARGET_SA_ONSTACK) {
+        if (sas_ss_flags(esp) == 0) {
+            esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
         }
+    } else {
 
-	/* This is the legacy signal stack switching. */
-	else
+        /* This is the legacy signal stack switching. */
         if ((env->segs[R_SS].selector & 0xffff) != __USER_DS &&
-            !(ka->sa_flags & TARGET_SA_RESTORER) &&
-            ka->sa_restorer) {
+                !(ka->sa_flags & TARGET_SA_RESTORER) &&
+                ka->sa_restorer) {
             esp = (unsigned long) ka->sa_restorer;
-	}
-        return (esp - frame_size) & -8ul;
+        }
+    }
+    return (esp - frame_size) & -8ul;
 }
 
 /* compare linux/arch/i386/kernel/signal.c:setup_frame() */
 static void setup_frame(int sig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUX86State *env)
+                        target_sigset_t *set, CPUX86State *env)
 {
-	abi_ulong frame_addr;
-	struct sigframe *frame;
-	int i;
+    abi_ulong frame_addr;
+    struct sigframe *frame;
+    int i;
 
-	frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    frame_addr = get_sigframe(ka, env, sizeof(*frame));
 
-	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-		goto give_sigsegv;
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+        goto give_sigsegv;
 
     __put_user(sig, &frame->sig);
 
-	setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
-                         frame_addr + offsetof(struct sigframe, fpstate));
+    setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0],
+            frame_addr + offsetof(struct sigframe, fpstate));
 
     for(i = 1; i < TARGET_NSIG_WORDS; i++) {
         __put_user(set->sig[i], &frame->extramask[i - 1]);
     }
 
-	/* Set up to return from userspace.  If provided, use a stub
-	   already in userspace.  */
-	if (ka->sa_flags & TARGET_SA_RESTORER) {
+    /* Set up to return from userspace.  If provided, use a stub
+       already in userspace.  */
+    if (ka->sa_flags & TARGET_SA_RESTORER) {
         __put_user(ka->sa_restorer, &frame->pretcode);
-	} else {
-                uint16_t val16;
-                abi_ulong retcode_addr;
-                retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
+    } else {
+        uint16_t val16;
+        abi_ulong retcode_addr;
+        retcode_addr = frame_addr + offsetof(struct sigframe, retcode);
         __put_user(retcode_addr, &frame->pretcode);
-		/* This is popl %eax ; movl $,%eax ; int $0x80 */
-                val16 = 0xb858;
+        /* This is popl %eax ; movl $,%eax ; int $0x80 */
+        val16 = 0xb858;
         __put_user(val16, (uint16_t *)(frame->retcode+0));
         __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2));
-                val16 = 0x80cd;
+        val16 = 0x80cd;
         __put_user(val16, (uint16_t *)(frame->retcode+6));
-	}
+    }
 
 
-	/* Set up registers for signal handler */
-	env->regs[R_ESP] = frame_addr;
-	env->eip = ka->_sa_handler;
+    /* Set up registers for signal handler */
+    env->regs[R_ESP] = frame_addr;
+    env->eip = ka->_sa_handler;
 
-        cpu_x86_load_seg(env, R_DS, __USER_DS);
-        cpu_x86_load_seg(env, R_ES, __USER_DS);
-        cpu_x86_load_seg(env, R_SS, __USER_DS);
-        cpu_x86_load_seg(env, R_CS, __USER_CS);
-	env->eflags &= ~TF_MASK;
+    cpu_x86_load_seg(env, R_DS, __USER_DS);
+    cpu_x86_load_seg(env, R_ES, __USER_DS);
+    cpu_x86_load_seg(env, R_SS, __USER_DS);
+    cpu_x86_load_seg(env, R_CS, __USER_CS);
+    env->eflags &= ~TF_MASK;
 
-	unlock_user_struct(frame, frame_addr, 1);
+    unlock_user_struct(frame, frame_addr, 1);
 
-	return;
+    return;
 
 give_sigsegv:
-	if (sig == TARGET_SIGSEGV)
-		ka->_sa_handler = TARGET_SIG_DFL;
-	force_sig(TARGET_SIGSEGV /* , current */);
+    if (sig == TARGET_SIGSEGV) {
+        ka->_sa_handler = TARGET_SIG_DFL;
+    }
+    force_sig(TARGET_SIGSEGV /* , current */);
 }
 
 /* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
                            target_siginfo_t *info,
-			   target_sigset_t *set, CPUX86State *env)
+                           target_sigset_t *set, CPUX86State *env)
 {
-        abi_ulong frame_addr, addr;
-	struct rt_sigframe *frame;
-	int i;
+    abi_ulong frame_addr, addr;
+    struct rt_sigframe *frame;
+    int i;
 
-	frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    frame_addr = get_sigframe(ka, env, sizeof(*frame));
 
-	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-		goto give_sigsegv;
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
+        goto give_sigsegv;
 
     __put_user(sig, &frame->sig);
-        addr = frame_addr + offsetof(struct rt_sigframe, info);
+    addr = frame_addr + offsetof(struct rt_sigframe, info);
     __put_user(addr, &frame->pinfo);
-        addr = frame_addr + offsetof(struct rt_sigframe, uc);
+    addr = frame_addr + offsetof(struct rt_sigframe, uc);
     __put_user(addr, &frame->puc);
     tswap_siginfo(&frame->info, info);
 
-	/* Create the ucontext.  */
+    /* Create the ucontext.  */
     __put_user(0, &frame->uc.tuc_flags);
     __put_user(0, &frame->uc.tuc_link);
     __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
@@ -997,81 +999,82 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
         __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
     }
 
-	/* Set up to return from userspace.  If provided, use a stub
-	   already in userspace.  */
-	if (ka->sa_flags & TARGET_SA_RESTORER) {
+    /* Set up to return from userspace.  If provided, use a stub
+       already in userspace.  */
+    if (ka->sa_flags & TARGET_SA_RESTORER) {
         __put_user(ka->sa_restorer, &frame->pretcode);
-	} else {
-                uint16_t val16;
-                addr = frame_addr + offsetof(struct rt_sigframe, retcode);
+    } else {
+        uint16_t val16;
+        addr = frame_addr + offsetof(struct rt_sigframe, retcode);
         __put_user(addr, &frame->pretcode);
-		/* This is movl $,%eax ; int $0x80 */
+        /* This is movl $,%eax ; int $0x80 */
         __put_user(0xb8, (char *)(frame->retcode+0));
         __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1));
-                val16 = 0x80cd;
+        val16 = 0x80cd;
         __put_user(val16, (uint16_t *)(frame->retcode+5));
-	}
+    }
 
-	/* Set up registers for signal handler */
-	env->regs[R_ESP] = frame_addr;
-	env->eip = ka->_sa_handler;
+    /* Set up registers for signal handler */
+    env->regs[R_ESP] = frame_addr;
+    env->eip = ka->_sa_handler;
 
-        cpu_x86_load_seg(env, R_DS, __USER_DS);
-        cpu_x86_load_seg(env, R_ES, __USER_DS);
-        cpu_x86_load_seg(env, R_SS, __USER_DS);
-        cpu_x86_load_seg(env, R_CS, __USER_CS);
-	env->eflags &= ~TF_MASK;
+    cpu_x86_load_seg(env, R_DS, __USER_DS);
+    cpu_x86_load_seg(env, R_ES, __USER_DS);
+    cpu_x86_load_seg(env, R_SS, __USER_DS);
+    cpu_x86_load_seg(env, R_CS, __USER_CS);
+    env->eflags &= ~TF_MASK;
 
-	unlock_user_struct(frame, frame_addr, 1);
+    unlock_user_struct(frame, frame_addr, 1);
 
-	return;
+    return;
 
 give_sigsegv:
-	if (sig == TARGET_SIGSEGV)
-		ka->_sa_handler = TARGET_SIG_DFL;
-	force_sig(TARGET_SIGSEGV /* , current */);
+    if (sig == TARGET_SIGSEGV) {
+        ka->_sa_handler = TARGET_SIG_DFL;
+    }
+    force_sig(TARGET_SIGSEGV /* , current */);
 }
 
 static int
 restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
 {
-	unsigned int err = 0;
-        abi_ulong fpstate_addr;
-        unsigned int tmpflags;
-
-        cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
-        cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
-        cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
-        cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
-
-        env->regs[R_EDI] = tswapl(sc->edi);
-        env->regs[R_ESI] = tswapl(sc->esi);
-        env->regs[R_EBP] = tswapl(sc->ebp);
-        env->regs[R_ESP] = tswapl(sc->esp);
-        env->regs[R_EBX] = tswapl(sc->ebx);
-        env->regs[R_EDX] = tswapl(sc->edx);
-        env->regs[R_ECX] = tswapl(sc->ecx);
-        env->eip = tswapl(sc->eip);
-
-        cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
-        cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
-
-        tmpflags = tswapl(sc->eflags);
-        env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
-        //		regs->orig_eax = -1;		/* disable syscall checks */
-
-        fpstate_addr = tswapl(sc->fpstate);
-	if (fpstate_addr != 0) {
-                if (!access_ok(VERIFY_READ, fpstate_addr, 
-                               sizeof(struct target_fpstate)))
-                        goto badframe;
-                cpu_x86_frstor(env, fpstate_addr, 1);
-	}
+    unsigned int err = 0;
+    abi_ulong fpstate_addr;
+    unsigned int tmpflags;
+
+    cpu_x86_load_seg(env, R_GS, tswap16(sc->gs));
+    cpu_x86_load_seg(env, R_FS, tswap16(sc->fs));
+    cpu_x86_load_seg(env, R_ES, tswap16(sc->es));
+    cpu_x86_load_seg(env, R_DS, tswap16(sc->ds));
+
+    env->regs[R_EDI] = tswapl(sc->edi);
+    env->regs[R_ESI] = tswapl(sc->esi);
+    env->regs[R_EBP] = tswapl(sc->ebp);
+    env->regs[R_ESP] = tswapl(sc->esp);
+    env->regs[R_EBX] = tswapl(sc->ebx);
+    env->regs[R_EDX] = tswapl(sc->edx);
+    env->regs[R_ECX] = tswapl(sc->ecx);
+    env->eip = tswapl(sc->eip);
+
+    cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
+    cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3);
+
+    tmpflags = tswapl(sc->eflags);
+    env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
+    //		regs->orig_eax = -1;		/* disable syscall checks */
+
+    fpstate_addr = tswapl(sc->fpstate);
+    if (fpstate_addr != 0) {
+        if (!access_ok(VERIFY_READ, fpstate_addr,
+                       sizeof(struct target_fpstate)))
+            goto badframe;
+        cpu_x86_frstor(env, fpstate_addr, 1);
+    }
 
-        *peax = tswapl(sc->eax);
-	return err;
+    *peax = tswapl(sc->eax);
+    return err;
 badframe:
-	return 1;
+    return 1;
 }
 
 long do_sigreturn(CPUX86State *env)
@@ -1110,31 +1113,34 @@ badframe:
 
 long do_rt_sigreturn(CPUX86State *env)
 {
-        abi_ulong frame_addr;
-	struct rt_sigframe *frame;
-        sigset_t set;
-	int eax;
+    abi_ulong frame_addr;
+    struct rt_sigframe *frame;
+    sigset_t set;
+    int eax;
 
-        frame_addr = env->regs[R_ESP] - 4;
-        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
-                goto badframe;
-        target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
-        do_sigprocmask(SIG_SETMASK, &set, NULL);
+    frame_addr = env->regs[R_ESP] - 4;
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
+    target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
+    do_sigprocmask(SIG_SETMASK, &set, NULL);
 
-	if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax))
-		goto badframe;
+    if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) {
+        goto badframe;
+    }
 
-	if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0, 
-                           get_sp_from_cpustate(env)) == -EFAULT)
-		goto badframe;
+    if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
+                       get_sp_from_cpustate(env)) == -EFAULT) {
+        goto badframe;
+    }
 
-        unlock_user_struct(frame, frame_addr, 0);
-	return eax;
+    unlock_user_struct(frame, frame_addr, 0);
+    return eax;
 
 badframe:
-        unlock_user_struct(frame, frame_addr, 0);
-        force_sig(TARGET_SIGSEGV);
-	return 0;
+    unlock_user_struct(frame, frame_addr, 0);
+    force_sig(TARGET_SIGSEGV);
+    return 0;
 }
 
 #elif defined(TARGET_AARCH64)
@@ -1413,27 +1419,27 @@ long do_sigreturn(CPUARMState *env)
 #elif defined(TARGET_ARM)
 
 struct target_sigcontext {
-	abi_ulong trap_no;
-	abi_ulong error_code;
-	abi_ulong oldmask;
-	abi_ulong arm_r0;
-	abi_ulong arm_r1;
-	abi_ulong arm_r2;
-	abi_ulong arm_r3;
-	abi_ulong arm_r4;
-	abi_ulong arm_r5;
-	abi_ulong arm_r6;
-	abi_ulong arm_r7;
-	abi_ulong arm_r8;
-	abi_ulong arm_r9;
-	abi_ulong arm_r10;
-	abi_ulong arm_fp;
-	abi_ulong arm_ip;
-	abi_ulong arm_sp;
-	abi_ulong arm_lr;
-	abi_ulong arm_pc;
-	abi_ulong arm_cpsr;
-	abi_ulong fault_address;
+    abi_ulong trap_no;
+    abi_ulong error_code;
+    abi_ulong oldmask;
+    abi_ulong arm_r0;
+    abi_ulong arm_r1;
+    abi_ulong arm_r2;
+    abi_ulong arm_r3;
+    abi_ulong arm_r4;
+    abi_ulong arm_r5;
+    abi_ulong arm_r6;
+    abi_ulong arm_r7;
+    abi_ulong arm_r8;
+    abi_ulong arm_r9;
+    abi_ulong arm_r10;
+    abi_ulong arm_fp;
+    abi_ulong arm_ip;
+    abi_ulong arm_sp;
+    abi_ulong arm_lr;
+    abi_ulong arm_pc;
+    abi_ulong arm_cpsr;
+    abi_ulong fault_address;
 };
 
 struct target_ucontext_v1 {
@@ -1547,82 +1553,83 @@ static void
 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
                  CPUARMState *env, abi_ulong mask)
 {
-	__put_user(env->regs[0], &sc->arm_r0);
-	__put_user(env->regs[1], &sc->arm_r1);
-	__put_user(env->regs[2], &sc->arm_r2);
-	__put_user(env->regs[3], &sc->arm_r3);
-	__put_user(env->regs[4], &sc->arm_r4);
-	__put_user(env->regs[5], &sc->arm_r5);
-	__put_user(env->regs[6], &sc->arm_r6);
-	__put_user(env->regs[7], &sc->arm_r7);
-	__put_user(env->regs[8], &sc->arm_r8);
-	__put_user(env->regs[9], &sc->arm_r9);
-	__put_user(env->regs[10], &sc->arm_r10);
-	__put_user(env->regs[11], &sc->arm_fp);
-	__put_user(env->regs[12], &sc->arm_ip);
-	__put_user(env->regs[13], &sc->arm_sp);
-	__put_user(env->regs[14], &sc->arm_lr);
-	__put_user(env->regs[15], &sc->arm_pc);
+    __put_user(env->regs[0], &sc->arm_r0);
+    __put_user(env->regs[1], &sc->arm_r1);
+    __put_user(env->regs[2], &sc->arm_r2);
+    __put_user(env->regs[3], &sc->arm_r3);
+    __put_user(env->regs[4], &sc->arm_r4);
+    __put_user(env->regs[5], &sc->arm_r5);
+    __put_user(env->regs[6], &sc->arm_r6);
+    __put_user(env->regs[7], &sc->arm_r7);
+    __put_user(env->regs[8], &sc->arm_r8);
+    __put_user(env->regs[9], &sc->arm_r9);
+    __put_user(env->regs[10], &sc->arm_r10);
+    __put_user(env->regs[11], &sc->arm_fp);
+    __put_user(env->regs[12], &sc->arm_ip);
+    __put_user(env->regs[13], &sc->arm_sp);
+    __put_user(env->regs[14], &sc->arm_lr);
+    __put_user(env->regs[15], &sc->arm_pc);
 #ifdef TARGET_CONFIG_CPU_32
-	__put_user(cpsr_read(env), &sc->arm_cpsr);
+    __put_user(cpsr_read(env), &sc->arm_cpsr);
 #endif
 
-	__put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
-	__put_user(/* current->thread.error_code */ 0, &sc->error_code);
-	__put_user(/* current->thread.address */ 0, &sc->fault_address);
-	__put_user(mask, &sc->oldmask);
+    __put_user(/* current->thread.trap_no */ 0, &sc->trap_no);
+    __put_user(/* current->thread.error_code */ 0, &sc->error_code);
+    __put_user(/* current->thread.address */ 0, &sc->fault_address);
+    __put_user(mask, &sc->oldmask);
 }
 
 static inline abi_ulong
 get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize)
 {
-	unsigned long sp = regs->regs[13];
+    unsigned long sp = regs->regs[13];
 
-	/*
-	 * This is the X/Open sanctioned signal stack switching.
-	 */
-	if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp))
-            sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
-	/*
-	 * ATPCS B01 mandates 8-byte alignment
-	 */
-	return (sp - framesize) & ~7;
+    /*
+     * This is the X/Open sanctioned signal stack switching.
+     */
+    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
+        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+    }
+    /*
+     * ATPCS B01 mandates 8-byte alignment
+     */
+    return (sp - framesize) & ~7;
 }
 
 static void
 setup_return(CPUARMState *env, struct target_sigaction *ka,
-	     abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
+             abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr)
 {
-	abi_ulong handler = ka->_sa_handler;
-	abi_ulong retcode;
-	int thumb = handler & 1;
-	uint32_t cpsr = cpsr_read(env);
+    abi_ulong handler = ka->_sa_handler;
+    abi_ulong retcode;
+    int thumb = handler & 1;
+    uint32_t cpsr = cpsr_read(env);
 
-	cpsr &= ~CPSR_IT;
-	if (thumb) {
-		cpsr |= CPSR_T;
-	} else {
-		cpsr &= ~CPSR_T;
-	}
+    cpsr &= ~CPSR_IT;
+    if (thumb) {
+        cpsr |= CPSR_T;
+    } else {
+        cpsr &= ~CPSR_T;
+    }
 
-	if (ka->sa_flags & TARGET_SA_RESTORER) {
-		retcode = ka->sa_restorer;
-	} else {
-		unsigned int idx = thumb;
+    if (ka->sa_flags & TARGET_SA_RESTORER) {
+        retcode = ka->sa_restorer;
+    } else {
+        unsigned int idx = thumb;
 
-		if (ka->sa_flags & TARGET_SA_SIGINFO)
-			idx += 2;
+        if (ka->sa_flags & TARGET_SA_SIGINFO)
+            idx += 2;
 
         __put_user(retcodes[idx], rc);
 
-		retcode = rc_addr + thumb;
-	}
+        retcode = rc_addr + thumb;
+    }
 
-	env->regs[0] = usig;
-	env->regs[13] = frame_addr;
-	env->regs[14] = retcode;
-	env->regs[15] = handler & (thumb ? ~1 : ~3);
-	cpsr_write(env, cpsr, 0xffffffff);
+    env->regs[0] = usig;
+    env->regs[13] = frame_addr;
+    env->regs[14] = retcode;
+    env->regs[15] = handler & (thumb ? ~1 : ~3);
+    cpsr_write(env, cpsr, 0xffffffff);
 }
 
 static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
@@ -1700,40 +1707,42 @@ static void setup_sigframe_v2(struct target_ucontext_v2 *uc,
 static void setup_frame_v1(int usig, struct target_sigaction *ka,
                            target_sigset_t *set, CPUARMState *regs)
 {
-	struct sigframe_v1 *frame;
-	abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
-	int i;
+    struct sigframe_v1 *frame;
+    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
+    int i;
 
-	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-		return;
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        return;
+    }
 
-	setup_sigcontext(&frame->sc, regs, set->sig[0]);
+    setup_sigcontext(&frame->sc, regs, set->sig[0]);
 
     for(i = 1; i < TARGET_NSIG_WORDS; i++) {
         __put_user(set->sig[i], &frame->extramask[i - 1]);
     }
 
-        setup_return(regs, ka, &frame->retcode, frame_addr, usig,
-                     frame_addr + offsetof(struct sigframe_v1, retcode));
+    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
+                 frame_addr + offsetof(struct sigframe_v1, retcode));
 
-	unlock_user_struct(frame, frame_addr, 1);
+    unlock_user_struct(frame, frame_addr, 1);
 }
 
 static void setup_frame_v2(int usig, struct target_sigaction *ka,
                            target_sigset_t *set, CPUARMState *regs)
 {
-	struct sigframe_v2 *frame;
-	abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
+    struct sigframe_v2 *frame;
+    abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame));
 
-	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-		return;
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        return;
+    }
 
-        setup_sigframe_v2(&frame->uc, set, regs);
+    setup_sigframe_v2(&frame->uc, set, regs);
 
-        setup_return(regs, ka, &frame->retcode, frame_addr, usig,
-                     frame_addr + offsetof(struct sigframe_v2, retcode));
+    setup_return(regs, ka, &frame->retcode, frame_addr, usig,
+                 frame_addr + offsetof(struct sigframe_v2, retcode));
 
-	unlock_user_struct(frame, frame_addr, 1);
+    unlock_user_struct(frame, frame_addr, 1);
 }
 
 static void setup_frame(int usig, struct target_sigaction *ka,
@@ -1751,68 +1760,70 @@ static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
                               target_siginfo_t *info,
                               target_sigset_t *set, CPUARMState *env)
 {
-	struct rt_sigframe_v1 *frame;
-	abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
-	struct target_sigaltstack stack;
-	int i;
-        abi_ulong info_addr, uc_addr;
+    struct rt_sigframe_v1 *frame;
+    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    struct target_sigaltstack stack;
+    int i;
+    abi_ulong info_addr, uc_addr;
 
-	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-            return /* 1 */;
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        return /* 1 */;
+    }
 
-        info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
-	__put_user(info_addr, &frame->pinfo);
-        uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
-	__put_user(uc_addr, &frame->puc);
-        tswap_siginfo(&frame->info, info);
+    info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info);
+    __put_user(info_addr, &frame->pinfo);
+    uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc);
+    __put_user(uc_addr, &frame->puc);
+    tswap_siginfo(&frame->info, info);
 
-	/* Clear all the bits of the ucontext we don't use.  */
-	memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
+    /* Clear all the bits of the ucontext we don't use.  */
+    memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext));
 
-        memset(&stack, 0, sizeof(stack));
-        __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
-        __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
-        __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
-        memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
+    memset(&stack, 0, sizeof(stack));
+    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp);
+    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size);
+    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags);
+    memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack));
 
-	setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
-        for(i = 0; i < TARGET_NSIG_WORDS; i++) {
-            __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
-        }
+    setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]);
+    for(i = 0; i < TARGET_NSIG_WORDS; i++) {
+        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
+    }
 
-        setup_return(env, ka, &frame->retcode, frame_addr, usig,
-                     frame_addr + offsetof(struct rt_sigframe_v1, retcode));
+    setup_return(env, ka, &frame->retcode, frame_addr, usig,
+                 frame_addr + offsetof(struct rt_sigframe_v1, retcode));
 
-        env->regs[1] = info_addr;
-        env->regs[2] = uc_addr;
+    env->regs[1] = info_addr;
+    env->regs[2] = uc_addr;
 
-	unlock_user_struct(frame, frame_addr, 1);
+    unlock_user_struct(frame, frame_addr, 1);
 }
 
 static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
                               target_siginfo_t *info,
                               target_sigset_t *set, CPUARMState *env)
 {
-	struct rt_sigframe_v2 *frame;
-	abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
-        abi_ulong info_addr, uc_addr;
+    struct rt_sigframe_v2 *frame;
+    abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame));
+    abi_ulong info_addr, uc_addr;
 
-	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-            return /* 1 */;
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        return /* 1 */;
+    }
 
-        info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
-        uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
-        tswap_siginfo(&frame->info, info);
+    info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info);
+    uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc);
+    tswap_siginfo(&frame->info, info);
 
-        setup_sigframe_v2(&frame->uc, set, env);
+    setup_sigframe_v2(&frame->uc, set, env);
 
-        setup_return(env, ka, &frame->retcode, frame_addr, usig,
-                     frame_addr + offsetof(struct rt_sigframe_v2, retcode));
+    setup_return(env, ka, &frame->retcode, frame_addr, usig,
+                 frame_addr + offsetof(struct rt_sigframe_v2, retcode));
 
-        env->regs[1] = info_addr;
-        env->regs[2] = uc_addr;
+    env->regs[1] = info_addr;
+    env->regs[2] = uc_addr;
 
-	unlock_user_struct(frame, frame_addr, 1);
+    unlock_user_struct(frame, frame_addr, 1);
 }
 
 static void setup_rt_frame(int usig, struct target_sigaction *ka,
@@ -1829,8 +1840,8 @@ static void setup_rt_frame(int usig, struct target_sigaction *ka,
 static int
 restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
 {
-	int err = 0;
-        uint32_t cpsr;
+    int err = 0;
+    uint32_t cpsr;
 
     __get_user(env->regs[0], &sc->arm_r0);
     __get_user(env->regs[1], &sc->arm_r1);
@@ -1850,57 +1861,59 @@ restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc)
     __get_user(env->regs[15], &sc->arm_pc);
 #ifdef TARGET_CONFIG_CPU_32
     __get_user(cpsr, &sc->arm_cpsr);
-        cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC);
+    cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC);
 #endif
 
-	err |= !valid_user_regs(env);
+    err |= !valid_user_regs(env);
 
-	return err;
+    return err;
 }
 
 static long do_sigreturn_v1(CPUARMState *env)
 {
-        abi_ulong frame_addr;
-        struct sigframe_v1 *frame = NULL;
-	target_sigset_t set;
-        sigset_t host_set;
-        int i;
-
-	/*
-	 * Since we stacked the signal on a 64-bit boundary,
-	 * then 'sp' should be word aligned here.  If it's
-	 * not, then the user is trying to mess with us.
-	 */
-        frame_addr = env->regs[13];
-        if (frame_addr & 7) {
-            goto badframe;
-        }
+    abi_ulong frame_addr;
+    struct sigframe_v1 *frame = NULL;
+    target_sigset_t set;
+    sigset_t host_set;
+    int i;
 
-	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
-                goto badframe;
+    /*
+     * Since we stacked the signal on a 64-bit boundary,
+     * then 'sp' should be word aligned here.  If it's
+     * not, then the user is trying to mess with us.
+     */
+    frame_addr = env->regs[13];
+    if (frame_addr & 7) {
+        goto badframe;
+    }
+
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
 
     __get_user(set.sig[0], &frame->sc.oldmask);
     for(i = 1; i < TARGET_NSIG_WORDS; i++) {
         __get_user(set.sig[i], &frame->extramask[i - 1]);
     }
 
-        target_to_host_sigset_internal(&host_set, &set);
-        do_sigprocmask(SIG_SETMASK, &host_set, NULL);
+    target_to_host_sigset_internal(&host_set, &set);
+    do_sigprocmask(SIG_SETMASK, &host_set, NULL);
 
-	if (restore_sigcontext(env, &frame->sc))
-		goto badframe;
+    if (restore_sigcontext(env, &frame->sc)) {
+        goto badframe;
+    }
 
 #if 0
-	/* Send SIGTRAP if we're single-stepping */
-	if (ptrace_cancel_bpt(current))
-		send_sig(SIGTRAP, current, 1);
+    /* Send SIGTRAP if we're single-stepping */
+    if (ptrace_cancel_bpt(current))
+        send_sig(SIGTRAP, current, 1);
 #endif
-	unlock_user_struct(frame, frame_addr, 0);
-        return env->regs[0];
+    unlock_user_struct(frame, frame_addr, 0);
+    return env->regs[0];
 
 badframe:
-        force_sig(TARGET_SIGSEGV /* , current */);
-	return 0;
+    force_sig(TARGET_SIGSEGV /* , current */);
+    return 0;
 }
 
 static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
@@ -1991,7 +2004,7 @@ static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
 #if 0
     /* Send SIGTRAP if we're single-stepping */
     if (ptrace_cancel_bpt(current))
-            send_sig(SIGTRAP, current, 1);
+        send_sig(SIGTRAP, current, 1);
 #endif
 
     return 0;
@@ -1999,32 +2012,34 @@ static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr,
 
 static long do_sigreturn_v2(CPUARMState *env)
 {
-        abi_ulong frame_addr;
-        struct sigframe_v2 *frame = NULL;
+    abi_ulong frame_addr;
+    struct sigframe_v2 *frame = NULL;
 
-	/*
-	 * Since we stacked the signal on a 64-bit boundary,
-	 * then 'sp' should be word aligned here.  If it's
-	 * not, then the user is trying to mess with us.
-	 */
-        frame_addr = env->regs[13];
-        if (frame_addr & 7) {
-            goto badframe;
-        }
+    /*
+     * Since we stacked the signal on a 64-bit boundary,
+     * then 'sp' should be word aligned here.  If it's
+     * not, then the user is trying to mess with us.
+     */
+    frame_addr = env->regs[13];
+    if (frame_addr & 7) {
+        goto badframe;
+    }
 
-	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
-                goto badframe;
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
 
-        if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
-                goto badframe;
+    if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
+        goto badframe;
+    }
 
-	unlock_user_struct(frame, frame_addr, 0);
-	return env->regs[0];
+    unlock_user_struct(frame, frame_addr, 0);
+    return env->regs[0];
 
 badframe:
-	unlock_user_struct(frame, frame_addr, 0);
-        force_sig(TARGET_SIGSEGV /* , current */);
-	return 0;
+    unlock_user_struct(frame, frame_addr, 0);
+    force_sig(TARGET_SIGSEGV /* , current */);
+    return 0;
 }
 
 long do_sigreturn(CPUARMState *env)
@@ -2038,74 +2053,78 @@ long do_sigreturn(CPUARMState *env)
 
 static long do_rt_sigreturn_v1(CPUARMState *env)
 {
-        abi_ulong frame_addr;
-        struct rt_sigframe_v1 *frame = NULL;
-        sigset_t host_set;
-
-	/*
-	 * Since we stacked the signal on a 64-bit boundary,
-	 * then 'sp' should be word aligned here.  If it's
-	 * not, then the user is trying to mess with us.
-	 */
-        frame_addr = env->regs[13];
-        if (frame_addr & 7) {
-            goto badframe;
-        }
+    abi_ulong frame_addr;
+    struct rt_sigframe_v1 *frame = NULL;
+    sigset_t host_set;
 
-	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
-                goto badframe;
+    /*
+     * Since we stacked the signal on a 64-bit boundary,
+     * then 'sp' should be word aligned here.  If it's
+     * not, then the user is trying to mess with us.
+     */
+    frame_addr = env->regs[13];
+    if (frame_addr & 7) {
+        goto badframe;
+    }
 
-        target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
-        do_sigprocmask(SIG_SETMASK, &host_set, NULL);
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
+
+    target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
+    do_sigprocmask(SIG_SETMASK, &host_set, NULL);
 
-	if (restore_sigcontext(env, &frame->uc.tuc_mcontext))
-		goto badframe;
+    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
+        goto badframe;
+    }
 
-	if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
-		goto badframe;
+    if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
+        goto badframe;
 
 #if 0
-	/* Send SIGTRAP if we're single-stepping */
-	if (ptrace_cancel_bpt(current))
-		send_sig(SIGTRAP, current, 1);
+    /* Send SIGTRAP if we're single-stepping */
+    if (ptrace_cancel_bpt(current))
+        send_sig(SIGTRAP, current, 1);
 #endif
-	unlock_user_struct(frame, frame_addr, 0);
-	return env->regs[0];
+    unlock_user_struct(frame, frame_addr, 0);
+    return env->regs[0];
 
 badframe:
-	unlock_user_struct(frame, frame_addr, 0);
-        force_sig(TARGET_SIGSEGV /* , current */);
-	return 0;
+    unlock_user_struct(frame, frame_addr, 0);
+    force_sig(TARGET_SIGSEGV /* , current */);
+    return 0;
 }
 
 static long do_rt_sigreturn_v2(CPUARMState *env)
 {
-        abi_ulong frame_addr;
-        struct rt_sigframe_v2 *frame = NULL;
+    abi_ulong frame_addr;
+    struct rt_sigframe_v2 *frame = NULL;
 
-	/*
-	 * Since we stacked the signal on a 64-bit boundary,
-	 * then 'sp' should be word aligned here.  If it's
-	 * not, then the user is trying to mess with us.
-	 */
-        frame_addr = env->regs[13];
-        if (frame_addr & 7) {
-            goto badframe;
-        }
+    /*
+     * Since we stacked the signal on a 64-bit boundary,
+     * then 'sp' should be word aligned here.  If it's
+     * not, then the user is trying to mess with us.
+     */
+    frame_addr = env->regs[13];
+    if (frame_addr & 7) {
+        goto badframe;
+    }
 
-	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
-                goto badframe;
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
 
-        if (do_sigframe_return_v2(env, frame_addr, &frame->uc))
-                goto badframe;
+    if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) {
+        goto badframe;
+    }
 
-	unlock_user_struct(frame, frame_addr, 0);
-	return env->regs[0];
+    unlock_user_struct(frame, frame_addr, 0);
+    return env->regs[0];
 
 badframe:
-	unlock_user_struct(frame, frame_addr, 0);
-        force_sig(TARGET_SIGSEGV /* , current */);
-	return 0;
+    unlock_user_struct(frame, frame_addr, 0);
+    force_sig(TARGET_SIGSEGV /* , current */);
+    return 0;
 }
 
 long do_rt_sigreturn(CPUARMState *env)
@@ -2123,83 +2142,83 @@ long do_rt_sigreturn(CPUARMState *env)
 
 /* This is what SunOS does, so shall I. */
 struct target_sigcontext {
-        abi_ulong sigc_onstack;      /* state to restore */
+    abi_ulong sigc_onstack;      /* state to restore */
 
-        abi_ulong sigc_mask;         /* sigmask to restore */
-        abi_ulong sigc_sp;           /* stack pointer */
-        abi_ulong sigc_pc;           /* program counter */
-        abi_ulong sigc_npc;          /* next program counter */
-        abi_ulong sigc_psr;          /* for condition codes etc */
-        abi_ulong sigc_g1;           /* User uses these two registers */
-        abi_ulong sigc_o0;           /* within the trampoline code. */
+    abi_ulong sigc_mask;         /* sigmask to restore */
+    abi_ulong sigc_sp;           /* stack pointer */
+    abi_ulong sigc_pc;           /* program counter */
+    abi_ulong sigc_npc;          /* next program counter */
+    abi_ulong sigc_psr;          /* for condition codes etc */
+    abi_ulong sigc_g1;           /* User uses these two registers */
+    abi_ulong sigc_o0;           /* within the trampoline code. */
 
-        /* Now comes information regarding the users window set
+    /* Now comes information regarding the users window set
          * at the time of the signal.
          */
-        abi_ulong sigc_oswins;       /* outstanding windows */
+    abi_ulong sigc_oswins;       /* outstanding windows */
 
-        /* stack ptrs for each regwin buf */
-        char *sigc_spbuf[__SUNOS_MAXWIN];
+    /* stack ptrs for each regwin buf */
+    char *sigc_spbuf[__SUNOS_MAXWIN];
 
-        /* Windows to restore after signal */
-        struct {
-                abi_ulong locals[8];
-                abi_ulong ins[8];
-        } sigc_wbuf[__SUNOS_MAXWIN];
+    /* Windows to restore after signal */
+    struct {
+        abi_ulong locals[8];
+        abi_ulong ins[8];
+    } sigc_wbuf[__SUNOS_MAXWIN];
 };
 /* A Sparc stack frame */
 struct sparc_stackf {
-        abi_ulong locals[8];
-        abi_ulong ins[8];
-        /* It's simpler to treat fp and callers_pc as elements of ins[]
+    abi_ulong locals[8];
+    abi_ulong ins[8];
+    /* It's simpler to treat fp and callers_pc as elements of ins[]
          * since we never need to access them ourselves.
          */
-        char *structptr;
-        abi_ulong xargs[6];
-        abi_ulong xxargs[1];
+    char *structptr;
+    abi_ulong xargs[6];
+    abi_ulong xxargs[1];
 };
 
 typedef struct {
-        struct {
-                abi_ulong psr;
-                abi_ulong pc;
-                abi_ulong npc;
-                abi_ulong y;
-                abi_ulong u_regs[16]; /* globals and ins */
-        }               si_regs;
-        int             si_mask;
+    struct {
+        abi_ulong psr;
+        abi_ulong pc;
+        abi_ulong npc;
+        abi_ulong y;
+        abi_ulong u_regs[16]; /* globals and ins */
+    }               si_regs;
+    int             si_mask;
 } __siginfo_t;
 
 typedef struct {
-        abi_ulong       si_float_regs[32];
-        unsigned   long si_fsr;
-        unsigned   long si_fpqdepth;
-        struct {
-                unsigned long *insn_addr;
-                unsigned long insn;
-        } si_fpqueue [16];
+    abi_ulong  si_float_regs[32];
+    unsigned   long si_fsr;
+    unsigned   long si_fpqdepth;
+    struct {
+        unsigned long *insn_addr;
+        unsigned long insn;
+    } si_fpqueue [16];
 } qemu_siginfo_fpu_t;
 
 
 struct target_signal_frame {
-	struct sparc_stackf	ss;
-	__siginfo_t		info;
-	abi_ulong               fpu_save;
-	abi_ulong		insns[2] __attribute__ ((aligned (8)));
-	abi_ulong		extramask[TARGET_NSIG_WORDS - 1];
-	abi_ulong		extra_size; /* Should be 0 */
-	qemu_siginfo_fpu_t	fpu_state;
+    struct sparc_stackf ss;
+    __siginfo_t         info;
+    abi_ulong           fpu_save;
+    abi_ulong           insns[2] __attribute__ ((aligned (8)));
+    abi_ulong           extramask[TARGET_NSIG_WORDS - 1];
+    abi_ulong           extra_size; /* Should be 0 */
+    qemu_siginfo_fpu_t fpu_state;
 };
 struct target_rt_signal_frame {
-	struct sparc_stackf	ss;
-	siginfo_t		info;
-	abi_ulong		regs[20];
-	sigset_t		mask;
-	abi_ulong               fpu_save;
-	unsigned int		insns[2];
-	stack_t			stack;
-	unsigned int		extra_size; /* Should be 0 */
-	qemu_siginfo_fpu_t	fpu_state;
+    struct sparc_stackf ss;
+    siginfo_t           info;
+    abi_ulong           regs[20];
+    sigset_t            mask;
+    abi_ulong           fpu_save;
+    unsigned int        insns[2];
+    stack_t             stack;
+    unsigned int        extra_size; /* Should be 0 */
+    qemu_siginfo_fpu_t  fpu_state;
 };
 
 #define UREG_O0        16
@@ -2220,36 +2239,37 @@ static inline abi_ulong get_sigframe(struct target_sigaction *sa,
                                      CPUSPARCState *env,
                                      unsigned long framesize)
 {
-	abi_ulong sp;
+    abi_ulong sp;
 
-	sp = env->regwptr[UREG_FP];
+    sp = env->regwptr[UREG_FP];
 
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if (sa->sa_flags & TARGET_SA_ONSTACK) {
-            if (!on_sig_stack(sp)
-                && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
-                sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
-	}
-	return sp - framesize;
+    /* This is the X/Open sanctioned signal stack switching.  */
+    if (sa->sa_flags & TARGET_SA_ONSTACK) {
+        if (!on_sig_stack(sp)
+                && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) {
+            sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+        }
+    }
+    return sp - framesize;
 }
 
 static int
 setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
 {
-	int err = 0, i;
+    int err = 0, i;
 
     __put_user(env->psr, &si->si_regs.psr);
     __put_user(env->pc, &si->si_regs.pc);
     __put_user(env->npc, &si->si_regs.npc);
     __put_user(env->y, &si->si_regs.y);
-	for (i=0; i < 8; i++) {
+    for (i=0; i < 8; i++) {
         __put_user(env->gregs[i], &si->si_regs.u_regs[i]);
-	}
-	for (i=0; i < 8; i++) {
+    }
+    for (i=0; i < 8; i++) {
         __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
-	}
+    }
     __put_user(mask, &si->si_mask);
-	return err;
+    return err;
 }
 
 #if 0
@@ -2257,7 +2277,7 @@ static int
 setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
                  CPUSPARCState *env, unsigned long mask)
 {
-	int err = 0;
+    int err = 0;
 
     __put_user(mask, &sc->sigc_mask);
     __put_user(env->regwptr[UREG_SP], &sc->sigc_sp);
@@ -2267,7 +2287,7 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
     __put_user(env->gregs[1], &sc->sigc_g1);
     __put_user(env->regwptr[UREG_O0], &sc->sigc_o0);
 
-	return err;
+    return err;
 }
 #endif
 #define NF_ALIGNEDSZ  (((sizeof(struct target_signal_frame) + 7) & (~7)))
@@ -2275,91 +2295,92 @@ setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/
 static void setup_frame(int sig, struct target_sigaction *ka,
                         target_sigset_t *set, CPUSPARCState *env)
 {
-        abi_ulong sf_addr;
-	struct target_signal_frame *sf;
-	int sigframe_size, err, i;
+    abi_ulong sf_addr;
+    struct target_signal_frame *sf;
+    int sigframe_size, err, i;
 
-	/* 1. Make sure everything is clean */
-	//synchronize_user_stack();
+    /* 1. Make sure everything is clean */
+    //synchronize_user_stack();
 
-        sigframe_size = NF_ALIGNEDSZ;
-	sf_addr = get_sigframe(ka, env, sigframe_size);
+    sigframe_size = NF_ALIGNEDSZ;
+    sf_addr = get_sigframe(ka, env, sigframe_size);
 
-        sf = lock_user(VERIFY_WRITE, sf_addr, 
-                       sizeof(struct target_signal_frame), 0);
-        if (!sf)
-		goto sigsegv;
-                
-	//fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
+    sf = lock_user(VERIFY_WRITE, sf_addr,
+                   sizeof(struct target_signal_frame), 0);
+    if (!sf) {
+        goto sigsegv;
+    }
+
+    //fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
 #if 0
-	if (invalid_frame_pointer(sf, sigframe_size))
-		goto sigill_and_return;
+    if (invalid_frame_pointer(sf, sigframe_size))
+        goto sigill_and_return;
 #endif
-	/* 2. Save the current process state */
-	err = setup___siginfo(&sf->info, env, set->sig[0]);
+    /* 2. Save the current process state */
+    err = setup___siginfo(&sf->info, env, set->sig[0]);
     __put_user(0, &sf->extra_size);
 
-	//save_fpu_state(regs, &sf->fpu_state);
-	//__put_user(&sf->fpu_state, &sf->fpu_save);
+    //save_fpu_state(regs, &sf->fpu_state);
+    //__put_user(&sf->fpu_state, &sf->fpu_save);
 
     __put_user(set->sig[0], &sf->info.si_mask);
-	for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
+    for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) {
         __put_user(set->sig[i + 1], &sf->extramask[i]);
-	}
+    }
 
-	for (i = 0; i < 8; i++) {
+    for (i = 0; i < 8; i++) {
         __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]);
-	}
-	for (i = 0; i < 8; i++) {
+    }
+    for (i = 0; i < 8; i++) {
         __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]);
-	}
-	if (err)
-		goto sigsegv;
-
-	/* 3. signal handler back-trampoline and parameters */
-	env->regwptr[UREG_FP] = sf_addr;
-	env->regwptr[UREG_I0] = sig;
-	env->regwptr[UREG_I1] = sf_addr + 
-                offsetof(struct target_signal_frame, info);
-	env->regwptr[UREG_I2] = sf_addr + 
-                offsetof(struct target_signal_frame, info);
-
-	/* 4. signal handler */
-	env->pc = ka->_sa_handler;
-	env->npc = (env->pc + 4);
-	/* 5. return to kernel instructions */
-	if (ka->sa_restorer)
-		env->regwptr[UREG_I7] = ka->sa_restorer;
-	else {
-                uint32_t val32;
-
-		env->regwptr[UREG_I7] = sf_addr + 
-                        offsetof(struct target_signal_frame, insns) - 2 * 4;
-
-		/* mov __NR_sigreturn, %g1 */
-                val32 = 0x821020d8;
+    }
+    if (err)
+        goto sigsegv;
+
+    /* 3. signal handler back-trampoline and parameters */
+    env->regwptr[UREG_FP] = sf_addr;
+    env->regwptr[UREG_I0] = sig;
+    env->regwptr[UREG_I1] = sf_addr +
+            offsetof(struct target_signal_frame, info);
+    env->regwptr[UREG_I2] = sf_addr +
+            offsetof(struct target_signal_frame, info);
+
+    /* 4. signal handler */
+    env->pc = ka->_sa_handler;
+    env->npc = (env->pc + 4);
+    /* 5. return to kernel instructions */
+    if (ka->sa_restorer) {
+        env->regwptr[UREG_I7] = ka->sa_restorer;
+    } else {
+        uint32_t val32;
+
+        env->regwptr[UREG_I7] = sf_addr +
+                offsetof(struct target_signal_frame, insns) - 2 * 4;
+
+        /* mov __NR_sigreturn, %g1 */
+        val32 = 0x821020d8;
         __put_user(val32, &sf->insns[0]);
 
-		/* t 0x10 */
-                val32 = 0x91d02010;
+        /* t 0x10 */
+        val32 = 0x91d02010;
         __put_user(val32, &sf->insns[1]);
-		if (err)
-			goto sigsegv;
+        if (err)
+            goto sigsegv;
 
-		/* Flush instruction space. */
-		//flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
-                //		tb_flush(CPU(sparc_env_get_cpu(env)));
-	}
-        unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
-	return;
+        /* Flush instruction space. */
+        // flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
+        // tb_flush(env);
+    }
+    unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
+    return;
 #if 0
 sigill_and_return:
-	force_sig(TARGET_SIGILL);
+    force_sig(TARGET_SIGILL);
 #endif
 sigsegv:
-	//fprintf(stderr, "force_sig\n");
-        unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
-	force_sig(TARGET_SIGSEGV);
+    //fprintf(stderr, "force_sig\n");
+    unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
+    force_sig(TARGET_SIGSEGV);
 }
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -2371,75 +2392,78 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
 
 long do_sigreturn(CPUSPARCState *env)
 {
-        abi_ulong sf_addr;
-        struct target_signal_frame *sf;
-        uint32_t up_psr, pc, npc;
-        target_sigset_t set;
-        sigset_t host_set;
-        int err=0, i;
+    abi_ulong sf_addr;
+    struct target_signal_frame *sf;
+    uint32_t up_psr, pc, npc;
+    target_sigset_t set;
+    sigset_t host_set;
+    int err=0, i;
 
-        sf_addr = env->regwptr[UREG_FP];
-        if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1))
-                goto segv_and_exit;
+    sf_addr = env->regwptr[UREG_FP];
+    if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
+        goto segv_and_exit;
+    }
 #if 0
-	fprintf(stderr, "sigreturn\n");
-	fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
+    fprintf(stderr, "sigreturn\n");
+    fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]);
 #endif
-	//cpu_dump_state(env, stderr, fprintf, 0);
+    //cpu_dump_state(env, stderr, fprintf, 0);
 
-        /* 1. Make sure we are not getting garbage from the user */
+    /* 1. Make sure we are not getting garbage from the user */
 
-        if (sf_addr & 3)
-                goto segv_and_exit;
+    if (sf_addr & 3)
+        goto segv_and_exit;
 
-        __get_user(pc,  &sf->info.si_regs.pc);
-        __get_user(npc, &sf->info.si_regs.npc);
+    __get_user(pc,  &sf->info.si_regs.pc);
+    __get_user(npc, &sf->info.si_regs.npc);
 
-        if ((pc | npc) & 3)
-                goto segv_and_exit;
+    if ((pc | npc) & 3) {
+        goto segv_and_exit;
+    }
 
-        /* 2. Restore the state */
-        __get_user(up_psr, &sf->info.si_regs.psr);
+    /* 2. Restore the state */
+    __get_user(up_psr, &sf->info.si_regs.psr);
 
-        /* User can only change condition codes and FPU enabling in %psr. */
-        env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
-                  | (env->psr & ~(PSR_ICC /* | PSR_EF */));
+    /* User can only change condition codes and FPU enabling in %psr. */
+    env->psr = (up_psr & (PSR_ICC /* | PSR_EF */))
+            | (env->psr & ~(PSR_ICC /* | PSR_EF */));
 
-	env->pc = pc;
-	env->npc = npc;
-        __get_user(env->y, &sf->info.si_regs.y);
-	for (i=0; i < 8; i++) {
-		__get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
-	}
-	for (i=0; i < 8; i++) {
-		__get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
-	}
+    env->pc = pc;
+    env->npc = npc;
+    __get_user(env->y, &sf->info.si_regs.y);
+    for (i=0; i < 8; i++) {
+        __get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
+    }
+    for (i=0; i < 8; i++) {
+        __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
+    }
 
-        /* FIXME: implement FPU save/restore:
+    /* FIXME: implement FPU save/restore:
          * __get_user(fpu_save, &sf->fpu_save);
          * if (fpu_save)
          *        err |= restore_fpu_state(env, fpu_save);
          */
 
-        /* This is pretty much atomic, no amount locking would prevent
+    /* This is pretty much atomic, no amount locking would prevent
          * the races which exist anyways.
          */
-        __get_user(set.sig[0], &sf->info.si_mask);
-        for(i = 1; i < TARGET_NSIG_WORDS; i++) {
-            __get_user(set.sig[i], &sf->extramask[i - 1]);
-        }
+    __get_user(set.sig[0], &sf->info.si_mask);
+    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
+        __get_user(set.sig[i], &sf->extramask[i - 1]);
+    }
 
-        target_to_host_sigset_internal(&host_set, &set);
-        do_sigprocmask(SIG_SETMASK, &host_set, NULL);
+    target_to_host_sigset_internal(&host_set, &set);
+    do_sigprocmask(SIG_SETMASK, &host_set, NULL);
 
-        if (err)
-                goto segv_and_exit;
-        unlock_user_struct(sf, sf_addr, 0);
-        return env->regwptr[0];
+    if (err) {
+        goto segv_and_exit;
+    }
+    unlock_user_struct(sf, sf_addr, 0);
+    return env->regwptr[0];
 
 segv_and_exit:
-        unlock_user_struct(sf, sf_addr, 0);
-	force_sig(TARGET_SIGSEGV);
+    unlock_user_struct(sf, sf_addr, 0);
+    force_sig(TARGET_SIGSEGV);
 }
 
 long do_rt_sigreturn(CPUSPARCState *env)
@@ -2527,13 +2551,15 @@ void sparc64_set_context(CPUSPARCState *env)
     unsigned int i;
 
     ucp_addr = env->regwptr[UREG_I0];
-    if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1))
+    if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
         goto do_sigsegv;
+    }
     grp  = &ucp->tuc_mcontext.mc_gregs;
     __get_user(pc, &((*grp)[MC_PC]));
     __get_user(npc, &((*grp)[MC_NPC]));
-    if ((pc | npc) & 3)
+    if ((pc | npc) & 3) {
         goto do_sigsegv;
+    }
     if (env->regwptr[UREG_I1]) {
         target_sigset_t target_set;
         sigset_t set;
@@ -2578,12 +2604,14 @@ void sparc64_set_context(CPUSPARCState *env)
     __get_user(i7, &(ucp->tuc_mcontext.mc_i7));
 
     w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
-    if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), 
-                 abi_ulong) != 0)
+    if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
+                 abi_ulong) != 0) {
         goto do_sigsegv;
-    if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), 
-                 abi_ulong) != 0)
+    }
+    if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
+                 abi_ulong) != 0) {
         goto do_sigsegv;
+    }
     /* FIXME this does not match how the kernel handles the FPU in
      * its sparc64_set_context implementation. In particular the FPU
      * is only restored if fenab is non-zero in:
@@ -2606,7 +2634,7 @@ void sparc64_set_context(CPUSPARCState *env)
                &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
     unlock_user_struct(ucp, ucp_addr, 0);
     return;
- do_sigsegv:
+do_sigsegv:
     unlock_user_struct(ucp, ucp_addr, 0);
     force_sig(TARGET_SIGSEGV);
 }
@@ -2624,8 +2652,9 @@ void sparc64_get_context(CPUSPARCState *env)
     sigset_t set;
 
     ucp_addr = env->regwptr[UREG_I0];
-    if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0))
+    if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
         goto do_sigsegv;
+    }
     
     mcp = &ucp->tuc_mcontext;
     grp = &mcp->mc_gregs;
@@ -2675,12 +2704,14 @@ void sparc64_get_context(CPUSPARCState *env)
 
     w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
     fp = i7 = 0;
-    if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]), 
-                 abi_ulong) != 0)
+    if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
+                 abi_ulong) != 0) {
         goto do_sigsegv;
-    if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]), 
-                 abi_ulong) != 0)
+    }
+    if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),
+                 abi_ulong) != 0) {
         goto do_sigsegv;
+    }
     __put_user(fp, &(mcp->mc_fp));
     __put_user(i7, &(mcp->mc_i7));
 
@@ -2702,7 +2733,7 @@ void sparc64_get_context(CPUSPARCState *env)
         goto do_sigsegv;
     unlock_user_struct(ucp, ucp_addr, 1);
     return;
- do_sigsegv:
+do_sigsegv:
     unlock_user_struct(ucp, ucp_addr, 1);
     force_sig(TARGET_SIGSEGV);
 }
@@ -2792,7 +2823,7 @@ static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall)
 }
 
 static inline void setup_sigcontext(CPUMIPSState *regs,
-        struct target_sigcontext *sc)
+                                    struct target_sigcontext *sc)
 {
     int i;
 
@@ -2903,8 +2934,9 @@ static void setup_frame(int sig, struct target_sigaction * ka,
     int i;
 
     frame_addr = get_sigframe(ka, regs, sizeof(*frame));
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-	goto give_sigsegv;
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto give_sigsegv;
+    }
 
     install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
 
@@ -2954,7 +2986,7 @@ long do_sigreturn(CPUMIPSState *regs)
 #endif
     frame_addr = regs->active_tc.gpr[29];
     if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
-   	goto badframe;
+        goto badframe;
 
     for(i = 0; i < TARGET_NSIG_WORDS; i++) {
         __get_user(target_set.sig[i], &frame->sf_mask.sig[i]);
@@ -2999,8 +3031,9 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     int i;
 
     frame_addr = get_sigframe(ka, env, sizeof(*frame));
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-	goto give_sigsegv;
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto give_sigsegv;
+    }
 
     install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
 
@@ -3060,8 +3093,9 @@ long do_rt_sigreturn(CPUMIPSState *env)
     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;
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
 
     target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
     do_sigprocmask(SIG_SETMASK, &blocked, NULL);
@@ -3069,8 +3103,8 @@ long do_rt_sigreturn(CPUMIPSState *env)
     restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
 
     if (do_sigaltstack(frame_addr +
-		       offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
-		       0, get_sp_from_cpustate(env)) == -EFAULT)
+                       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;
@@ -3141,7 +3175,7 @@ struct target_rt_sigframe
 #define TRAP_NOARG 0xc310         /* Syscall w/no args (NR in R3) SH3/4 */
 
 static abi_ulong get_sigframe(struct target_sigaction *ka,
-                         unsigned long sp, size_t frame_size)
+                              unsigned long sp, size_t frame_size)
 {
     if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
         sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
@@ -3151,7 +3185,7 @@ static abi_ulong get_sigframe(struct target_sigaction *ka,
 }
 
 static void setup_sigcontext(struct target_sigcontext *sc,
-                            CPUSH4State *regs, unsigned long mask)
+                             CPUSH4State *regs, unsigned long mask)
 {
     int i;
 
@@ -3180,7 +3214,7 @@ static void setup_sigcontext(struct target_sigcontext *sc,
 }
 
 static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
-                              target_ulong *r0_p)
+                               target_ulong *r0_p)
 {
     int i;
 
@@ -3217,8 +3251,9 @@ static void setup_frame(int sig, struct target_sigaction *ka,
     int err = 0;
 
     frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-	goto give_sigsegv;
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto give_sigsegv;
+    }
 
     setup_sigcontext(&frame->sc, regs, set->sig[0]);
 
@@ -3266,8 +3301,9 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     int err = 0;
 
     frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame));
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-	goto give_sigsegv;
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto give_sigsegv;
+    }
 
     tswap_siginfo(&frame->info, info);
 
@@ -3281,7 +3317,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     __put_user(target_sigaltstack_used.ss_size,
                &frame->uc.tuc_stack.ss_size);
     setup_sigcontext(&frame->uc.tuc_mcontext,
-			    regs, set->sig[0]);
+                     regs, set->sig[0]);
     for(i = 0; i < TARGET_NSIG_WORDS; i++) {
         __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
     }
@@ -3330,8 +3366,9 @@ long do_sigreturn(CPUSH4State *regs)
     fprintf(stderr, "do_sigreturn\n");
 #endif
     frame_addr = regs->gregs[15];
-    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
-   	goto badframe;
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
 
     __get_user(target_set.sig[0], &frame->sc.oldmask);
     for(i = 1; i < TARGET_NSIG_WORDS; i++) {
@@ -3366,8 +3403,9 @@ long do_rt_sigreturn(CPUSH4State *regs)
     fprintf(stderr, "do_rt_sigreturn\n");
 #endif
     frame_addr = regs->gregs[15];
-    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
-   	goto badframe;
+    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
+        goto badframe;
+    }
 
     target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
     do_sigprocmask(SIG_SETMASK, &blocked, NULL);
@@ -3375,9 +3413,10 @@ long do_rt_sigreturn(CPUSH4State *regs)
     restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0);
 
     if (do_sigaltstack(frame_addr +
-		       offsetof(struct target_rt_sigframe, uc.tuc_stack),
-		       0, get_sp_from_cpustate(regs)) == -EFAULT)
+                       offsetof(struct target_rt_sigframe, uc.tuc_stack),
+                       0, get_sp_from_cpustate(regs)) == -EFAULT) {
         goto badframe;
+    }
 
     unlock_user_struct(frame, frame_addr, 0);
     return r0;
@@ -3560,7 +3599,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
 
     unlock_user_struct(frame, frame_addr, 1);
     return;
-  badframe:
+badframe:
     force_sig(TARGET_SIGSEGV);
 }
 
@@ -3587,7 +3626,7 @@ long do_sigreturn(CPUMBState *env)
     /* Restore blocked signals */
     __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask);
     for(i = 1; i < TARGET_NSIG_WORDS; i++) {
-       __get_user(target_set.sig[i], &frame->extramask[i - 1]);
+        __get_user(target_set.sig[i], &frame->extramask[i - 1]);
     }
     target_to_host_sigset_internal(&set, &target_set);
     do_sigprocmask(SIG_SETMASK, &set, NULL);
@@ -3596,10 +3635,10 @@ long do_sigreturn(CPUMBState *env)
     /* We got here through a sigreturn syscall, our path back is via an
        rtb insn so setup r14 for that.  */
     env->regs[14] = env->sregs[SR_PC];
- 
+
     unlock_user_struct(frame, frame_addr, 0);
     return env->regs[10];
-  badframe:
+badframe:
     force_sig(TARGET_SIGSEGV);
 }
 
@@ -3612,123 +3651,124 @@ long do_rt_sigreturn(CPUMBState *env)
 #elif defined(TARGET_CRIS)
 
 struct target_sigcontext {
-        struct target_pt_regs regs;  /* needs to be first */
-        uint32_t oldmask;
-        uint32_t usp;    /* usp before stacking this gunk on it */
+    struct target_pt_regs regs;  /* needs to be first */
+    uint32_t oldmask;
+    uint32_t usp;    /* usp before stacking this gunk on it */
 };
 
 /* Signal frames. */
 struct target_signal_frame {
-        struct target_sigcontext sc;
-        uint32_t extramask[TARGET_NSIG_WORDS - 1];
-        uint16_t retcode[4];      /* Trampoline code. */
+    struct target_sigcontext sc;
+    uint32_t extramask[TARGET_NSIG_WORDS - 1];
+    uint16_t retcode[4];      /* Trampoline code. */
 };
 
 struct rt_signal_frame {
-        siginfo_t *pinfo;
-        void *puc;
-        siginfo_t info;
-        struct ucontext uc;
-        uint16_t retcode[4];      /* Trampoline code. */
+    siginfo_t *pinfo;
+    void *puc;
+    siginfo_t info;
+    struct ucontext uc;
+    uint16_t retcode[4];      /* Trampoline code. */
 };
 
 static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
 {
-	__put_user(env->regs[0], &sc->regs.r0);
-	__put_user(env->regs[1], &sc->regs.r1);
-	__put_user(env->regs[2], &sc->regs.r2);
-	__put_user(env->regs[3], &sc->regs.r3);
-	__put_user(env->regs[4], &sc->regs.r4);
-	__put_user(env->regs[5], &sc->regs.r5);
-	__put_user(env->regs[6], &sc->regs.r6);
-	__put_user(env->regs[7], &sc->regs.r7);
-	__put_user(env->regs[8], &sc->regs.r8);
-	__put_user(env->regs[9], &sc->regs.r9);
-	__put_user(env->regs[10], &sc->regs.r10);
-	__put_user(env->regs[11], &sc->regs.r11);
-	__put_user(env->regs[12], &sc->regs.r12);
-	__put_user(env->regs[13], &sc->regs.r13);
-	__put_user(env->regs[14], &sc->usp);
-	__put_user(env->regs[15], &sc->regs.acr);
-	__put_user(env->pregs[PR_MOF], &sc->regs.mof);
-	__put_user(env->pregs[PR_SRP], &sc->regs.srp);
-	__put_user(env->pc, &sc->regs.erp);
+    __put_user(env->regs[0], &sc->regs.r0);
+    __put_user(env->regs[1], &sc->regs.r1);
+    __put_user(env->regs[2], &sc->regs.r2);
+    __put_user(env->regs[3], &sc->regs.r3);
+    __put_user(env->regs[4], &sc->regs.r4);
+    __put_user(env->regs[5], &sc->regs.r5);
+    __put_user(env->regs[6], &sc->regs.r6);
+    __put_user(env->regs[7], &sc->regs.r7);
+    __put_user(env->regs[8], &sc->regs.r8);
+    __put_user(env->regs[9], &sc->regs.r9);
+    __put_user(env->regs[10], &sc->regs.r10);
+    __put_user(env->regs[11], &sc->regs.r11);
+    __put_user(env->regs[12], &sc->regs.r12);
+    __put_user(env->regs[13], &sc->regs.r13);
+    __put_user(env->regs[14], &sc->usp);
+    __put_user(env->regs[15], &sc->regs.acr);
+    __put_user(env->pregs[PR_MOF], &sc->regs.mof);
+    __put_user(env->pregs[PR_SRP], &sc->regs.srp);
+    __put_user(env->pc, &sc->regs.erp);
 }
 
 static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env)
 {
-	__get_user(env->regs[0], &sc->regs.r0);
-	__get_user(env->regs[1], &sc->regs.r1);
-	__get_user(env->regs[2], &sc->regs.r2);
-	__get_user(env->regs[3], &sc->regs.r3);
-	__get_user(env->regs[4], &sc->regs.r4);
-	__get_user(env->regs[5], &sc->regs.r5);
-	__get_user(env->regs[6], &sc->regs.r6);
-	__get_user(env->regs[7], &sc->regs.r7);
-	__get_user(env->regs[8], &sc->regs.r8);
-	__get_user(env->regs[9], &sc->regs.r9);
-	__get_user(env->regs[10], &sc->regs.r10);
-	__get_user(env->regs[11], &sc->regs.r11);
-	__get_user(env->regs[12], &sc->regs.r12);
-	__get_user(env->regs[13], &sc->regs.r13);
-	__get_user(env->regs[14], &sc->usp);
-	__get_user(env->regs[15], &sc->regs.acr);
-	__get_user(env->pregs[PR_MOF], &sc->regs.mof);
-	__get_user(env->pregs[PR_SRP], &sc->regs.srp);
-	__get_user(env->pc, &sc->regs.erp);
+    __get_user(env->regs[0], &sc->regs.r0);
+    __get_user(env->regs[1], &sc->regs.r1);
+    __get_user(env->regs[2], &sc->regs.r2);
+    __get_user(env->regs[3], &sc->regs.r3);
+    __get_user(env->regs[4], &sc->regs.r4);
+    __get_user(env->regs[5], &sc->regs.r5);
+    __get_user(env->regs[6], &sc->regs.r6);
+    __get_user(env->regs[7], &sc->regs.r7);
+    __get_user(env->regs[8], &sc->regs.r8);
+    __get_user(env->regs[9], &sc->regs.r9);
+    __get_user(env->regs[10], &sc->regs.r10);
+    __get_user(env->regs[11], &sc->regs.r11);
+    __get_user(env->regs[12], &sc->regs.r12);
+    __get_user(env->regs[13], &sc->regs.r13);
+    __get_user(env->regs[14], &sc->usp);
+    __get_user(env->regs[15], &sc->regs.acr);
+    __get_user(env->pregs[PR_MOF], &sc->regs.mof);
+    __get_user(env->pregs[PR_SRP], &sc->regs.srp);
+    __get_user(env->pc, &sc->regs.erp);
 }
 
 static abi_ulong get_sigframe(CPUCRISState *env, int framesize)
 {
-	abi_ulong sp;
-	/* Align the stack downwards to 4.  */
-	sp = (env->regs[R_SP] & ~3);
-	return sp - framesize;
+    abi_ulong sp;
+    /* Align the stack downwards to 4.  */
+    sp = (env->regs[R_SP] & ~3);
+    return sp - framesize;
 }
 
 static void setup_frame(int sig, struct target_sigaction *ka,
                         target_sigset_t *set, CPUCRISState *env)
 {
-	struct target_signal_frame *frame;
-	abi_ulong frame_addr;
-	int i;
-
-	frame_addr = get_sigframe(env, sizeof *frame);
-	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-		goto badframe;
-
-	/*
-	 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
-	 * use this trampoline anymore but it sets it up for GDB.
-	 * In QEMU, using the trampoline simplifies things a bit so we use it.
-	 *
-	 * This is movu.w __NR_sigreturn, r9; break 13;
-	 */
+    struct target_signal_frame *frame;
+    abi_ulong frame_addr;
+    int i;
+
+    frame_addr = get_sigframe(env, sizeof *frame);
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto badframe;
+    }
+
+    /*
+     * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't
+     * use this trampoline anymore but it sets it up for GDB.
+     * In QEMU, using the trampoline simplifies things a bit so we use it.
+     *
+     * This is movu.w __NR_sigreturn, r9; break 13;
+     */
     __put_user(0x9c5f, frame->retcode+0);
     __put_user(TARGET_NR_sigreturn,
                frame->retcode + 1);
     __put_user(0xe93d, frame->retcode + 2);
 
-	/* Save the mask.  */
+    /* Save the mask.  */
     __put_user(set->sig[0], &frame->sc.oldmask);
 
     for(i = 1; i < TARGET_NSIG_WORDS; i++) {
         __put_user(set->sig[i], &frame->extramask[i - 1]);
     }
 
-	setup_sigcontext(&frame->sc, env);
+    setup_sigcontext(&frame->sc, env);
 
-	/* Move the stack and setup the arguments for the handler.  */
-	env->regs[R_SP] = frame_addr;
-	env->regs[10] = sig;
-	env->pc = (unsigned long) ka->_sa_handler;
-	/* Link SRP so the guest returns through the trampoline.  */
-	env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
+    /* Move the stack and setup the arguments for the handler.  */
+    env->regs[R_SP] = frame_addr;
+    env->regs[10] = sig;
+    env->pc = (unsigned long) ka->_sa_handler;
+    /* Link SRP so the guest returns through the trampoline.  */
+    env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode);
 
-	unlock_user_struct(frame, frame_addr, 1);
-	return;
-  badframe:
-	force_sig(TARGET_SIGSEGV);
+    unlock_user_struct(frame, frame_addr, 1);
+    return;
+badframe:
+    force_sig(TARGET_SIGSEGV);
 }
 
 static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -3740,30 +3780,31 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
 
 long do_sigreturn(CPUCRISState *env)
 {
-	struct target_signal_frame *frame;
-	abi_ulong frame_addr;
-	target_sigset_t target_set;
-	sigset_t set;
-	int i;
+    struct target_signal_frame *frame;
+    abi_ulong frame_addr;
+    target_sigset_t target_set;
+    sigset_t set;
+    int i;
 
-	frame_addr = env->regs[R_SP];
-	/* Make sure the guest isn't playing games.  */
-	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1))
-		goto badframe;
+    frame_addr = env->regs[R_SP];
+    /* Make sure the guest isn't playing games.  */
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) {
+        goto badframe;
+    }
 
-	/* Restore blocked signals */
+    /* Restore blocked signals */
     __get_user(target_set.sig[0], &frame->sc.oldmask);
-	for(i = 1; i < TARGET_NSIG_WORDS; i++) {
+    for(i = 1; i < TARGET_NSIG_WORDS; i++) {
         __get_user(target_set.sig[i], &frame->extramask[i - 1]);
-	}
-	target_to_host_sigset_internal(&set, &target_set);
-        do_sigprocmask(SIG_SETMASK, &set, NULL);
+    }
+    target_to_host_sigset_internal(&set, &target_set);
+    do_sigprocmask(SIG_SETMASK, &set, NULL);
 
-	restore_sigcontext(&frame->sc, env);
-	unlock_user_struct(frame, frame_addr, 0);
-	return env->regs[10];
-  badframe:
-	force_sig(TARGET_SIGSEGV);
+    restore_sigcontext(&frame->sc, env);
+    unlock_user_struct(frame, frame_addr, 0);
+    return env->regs[10];
+badframe:
+    force_sig(TARGET_SIGSEGV);
 }
 
 long do_rt_sigreturn(CPUCRISState *env)
@@ -3848,8 +3889,8 @@ badframe:
 /* Set up a signal frame.  */
 
 static void setup_sigcontext(struct target_sigcontext *sc,
-                            CPUOpenRISCState *regs,
-                            unsigned long mask)
+                             CPUOpenRISCState *regs,
+                             unsigned long mask)
 {
     unsigned long usp = regs->gpr[1];
 
@@ -4112,7 +4153,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
     qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__,
              (unsigned long long)frame_addr);
     if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
-            goto give_sigsegv;
+        goto give_sigsegv;
     }
 
     qemu_log("%s: 1\n", __FUNCTION__);
@@ -4126,13 +4167,13 @@ static void setup_frame(int sig, struct target_sigaction *ka,
     /* Set up to return from userspace.  If provided, use a stub
        already in userspace.  */
     if (ka->sa_flags & TARGET_SA_RESTORER) {
-            env->regs[14] = (unsigned long)
-                    ka->sa_restorer | PSW_ADDR_AMODE;
+        env->regs[14] = (unsigned long)
+                ka->sa_restorer | PSW_ADDR_AMODE;
     } else {
-            env->regs[14] = (unsigned long)
-                    frame->retcode | PSW_ADDR_AMODE;
-            __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
-                       (uint16_t *)(frame->retcode));
+        env->regs[14] = (unsigned long)
+                frame->retcode | PSW_ADDR_AMODE;
+        __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn,
+                   (uint16_t *)(frame->retcode));
     }
 
     /* Set up backchain. */
@@ -4183,12 +4224,12 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link);
     __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp);
     __put_user(sas_ss_flags(get_sp_from_cpustate(env)),
-                      &frame->uc.tuc_stack.ss_flags);
+               &frame->uc.tuc_stack.ss_flags);
     __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size);
     save_sigregs(env, &frame->uc.tuc_mcontext);
     for (i = 0; i < TARGET_NSIG_WORDS; i++) {
         __put_user((abi_ulong)set->sig[i],
-        (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
+                   (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
     }
 
     /* Set up to return from userspace.  If provided, use a stub
@@ -4443,15 +4484,15 @@ struct target_sigframe {
 #define TARGET_TRAMP_SIZE 6
 
 struct target_rt_sigframe {
-        /* sys_rt_sigreturn requires the ucontext be the first field */
-        struct target_ucontext uc;
-        target_ulong  _unused[2];
-        uint32_t trampoline[TARGET_TRAMP_SIZE];
-        target_ulong pinfo; /* struct siginfo __user * */
-        target_ulong puc; /* void __user * */
-        struct target_siginfo info;
-        /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
-        char abigap[288];
+    /* sys_rt_sigreturn requires the ucontext be the first field */
+    struct target_ucontext uc;
+    target_ulong  _unused[2];
+    uint32_t trampoline[TARGET_TRAMP_SIZE];
+    target_ulong pinfo; /* struct siginfo __user * */
+    target_ulong puc; /* void __user * */
+    struct target_siginfo info;
+    /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */
+    char abigap[288];
 } __attribute__((aligned(16)));
 
 #else
@@ -4486,7 +4527,7 @@ static target_ulong get_sigframe(struct target_sigaction *ka,
     oldsp = env->gpr[1];
 
     if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
-        (sas_ss_flags(oldsp) == 0)) {
+            (sas_ss_flags(oldsp) == 0)) {
         oldsp = (target_sigaltstack_used.ss_sp
                  + target_sigaltstack_used.ss_size);
     }
@@ -4508,7 +4549,7 @@ static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame)
 
     /* Save general registers.  */
     for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
-       __put_user(env->gpr[i], &frame->mc_gregs[i]);
+        __put_user(env->gpr[i], &frame->mc_gregs[i]);
     }
     __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]);
     __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]);
@@ -4948,7 +4989,7 @@ struct target_sigframe
     abi_ulong extramask[TARGET_NSIG_WORDS-1];
     struct target_sigcontext sc;
 };
- 
+
 typedef int target_greg_t;
 #define TARGET_NGREG 18
 typedef target_greg_t target_gregset_t[TARGET_NGREG];
@@ -4987,7 +5028,7 @@ struct target_rt_sigframe
 };
 
 static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
-        abi_ulong mask)
+                             abi_ulong mask)
 {
     __put_user(mask, &sc->sc_mask);
     __put_user(env->aregs[7], &sc->sc_usp);
@@ -5044,8 +5085,9 @@ static void setup_frame(int sig, struct target_sigaction *ka,
     int i;
 
     frame_addr = get_sigframe(ka, env, sizeof *frame);
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-	goto give_sigsegv;
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto give_sigsegv;
+    }
 
     __put_user(sig, &frame->sig);
 
@@ -5066,7 +5108,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
     /* moveq #,d0; trap #0 */
 
     __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16),
-                      (uint32_t *)(frame->retcode));
+               (uint32_t *)(frame->retcode));
 
     /* Set up to return from userspace */
 
@@ -5107,7 +5149,7 @@ static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
 
     return 0;
 }
- 
+
 static inline int target_rt_restore_ucontext(CPUM68KState *env,
                                              struct target_ucontext *uc,
                                              int *pd0)
@@ -5160,8 +5202,9 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     int i;
 
     frame_addr = get_sigframe(ka, env, sizeof *frame);
-    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0))
-	goto give_sigsegv;
+    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
+        goto give_sigsegv;
+    }
 
     __put_user(sig, &frame->sig);
 
@@ -5180,13 +5223,13 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     __put_user(target_sigaltstack_used.ss_sp,
                &frame->uc.tuc_stack.ss_sp);
     __put_user(sas_ss_flags(env->aregs[7]),
-               &frame->uc.tuc_stack.ss_flags);
+            &frame->uc.tuc_stack.ss_flags);
     __put_user(target_sigaltstack_used.ss_size,
                &frame->uc.tuc_stack.ss_size);
     err |= target_rt_setup_ucontext(&frame->uc, env);
 
     if (err)
-            goto give_sigsegv;
+        goto give_sigsegv;
 
     for(i = 0; i < TARGET_NSIG_WORDS; i++) {
         __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
@@ -5335,7 +5378,7 @@ struct target_rt_sigframe {
 #define INSN_CALLSYS            0x00000083
 
 static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
-                            abi_ulong frame_addr, target_sigset_t *set)
+                             abi_ulong frame_addr, target_sigset_t *set)
 {
     int i;
 
@@ -5361,7 +5404,7 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env,
 }
 
 static void restore_sigcontext(CPUAlphaState *env,
-                              struct target_sigcontext *sc)
+                               struct target_sigcontext *sc)
 {
     uint64_t fpcr;
     int i;
@@ -5420,7 +5463,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
     unlock_user_struct(frame, frame_addr, 1);
 
     if (err) {
-    give_sigsegv:
+give_sigsegv:
         if (sig == TARGET_SIGSEGV) {
             ka->_sa_handler = TARGET_SIG_DFL;
         }
@@ -5476,8 +5519,8 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
     }
 
     if (err) {
-    give_sigsegv:
-       if (sig == TARGET_SIGSEGV) {
+give_sigsegv:
+        if (sig == TARGET_SIGSEGV) {
             ka->_sa_handler = TARGET_SIG_DFL;
         }
         force_sig(TARGET_SIGSEGV);
@@ -5512,7 +5555,7 @@ long do_sigreturn(CPUAlphaState *env)
     unlock_user_struct(sc, sc_addr, 0);
     return env->ir[IR_V0];
 
- badframe:
+badframe:
     force_sig(TARGET_SIGSEGV);
 }
 
@@ -5539,7 +5582,7 @@ long do_rt_sigreturn(CPUAlphaState *env)
     return env->ir[IR_V0];
 
 
- badframe:
+badframe:
     unlock_user_struct(frame, frame_addr, 0);
     force_sig(TARGET_SIGSEGV);
 }
@@ -5547,14 +5590,14 @@ long do_rt_sigreturn(CPUAlphaState *env)
 #else
 
 static void setup_frame(int sig, struct target_sigaction *ka,
-			target_sigset_t *set, CPUArchState *env)
+                        target_sigset_t *set, CPUArchState *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, CPUArchState *env)
+                           target_sigset_t *set, CPUArchState *env)
 {
     fprintf(stderr, "setup_rt_frame: not implemented\n");
 }
-- 
2.1.4

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

* [Qemu-devel] [PATCH 03/34] linux-user: Support for restarting system calls
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 01/34] linux-user: Fix array bounds in errno conversion Timothy E Baldwin
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 02/34] linux-user: Reindent signal handling Timothy E Baldwin
@ 2015-09-05 23:56 ` Timothy E Baldwin
  2015-09-10 18:08   ` Peter Maydell
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 04/34] linux-user: Support for restarting system calls for x86 targets Timothy E Baldwin
                   ` (31 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

This allows SA_RESTART to be supported along with various case
where pending signals need to be handled before a system call.

New macro TARGET_ERESTARTSYS which is the error code used by Linux
to indicate that system call should be restarted.

TARGET_QEMU_ESIGRETURN moved into errno_defs.h and renumbered to
513 which is safe from future use as a system call return value
as it is used for system call restarting in Linux and exposed only
via ptrace.

do_sigreturn() and do_rt_sigreturn() will be amended to return
-TARGET_QEMU_ESIGRETURN rather than the value of result register to
avoid confusion with -TARGET_ERESTARTSYS and cpu_loop() will be
altered to act upon the return value accordingly.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/errno_defs.h     | 3 +++
 linux-user/mips/syscall.h   | 4 ----
 linux-user/mips64/syscall.h | 4 ----
 linux-user/ppc/syscall.h    | 2 --
 4 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/linux-user/errno_defs.h b/linux-user/errno_defs.h
index 8a1cf76..a385f50 100644
--- a/linux-user/errno_defs.h
+++ b/linux-user/errno_defs.h
@@ -139,3 +139,6 @@
 /* for robust mutexes */
 #define TARGET_EOWNERDEAD      130     /* Owner died */
 #define TARGET_ENOTRECOVERABLE 131     /* State not recoverable */
+
+#define TARGET_ERESTARTSYS     512  /* Restart system call */
+#define TARGET_QEMU_ESIGRETURN 513  /* Return from signal */
diff --git a/linux-user/mips/syscall.h b/linux-user/mips/syscall.h
index 35ca23b..e34f80c 100644
--- a/linux-user/mips/syscall.h
+++ b/linux-user/mips/syscall.h
@@ -220,10 +220,6 @@ struct target_pt_regs {
 #define TARGET_ENOTRECOVERABLE 166     /* State not recoverable */
 
 
-
-/* Nasty hack: define a fake errno value for use by sigreturn.  */
-#define TARGET_QEMU_ESIGRETURN 255
-
 #define UNAME_MACHINE "mips"
 #define UNAME_MINIMUM_RELEASE "2.6.32"
 
diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h
index 6733107..33afb8d 100644
--- a/linux-user/mips64/syscall.h
+++ b/linux-user/mips64/syscall.h
@@ -217,10 +217,6 @@ struct target_pt_regs {
 #define TARGET_ENOTRECOVERABLE 166     /* State not recoverable */
 
 
-
-/* Nasty hack: define a fake errno value for use by sigreturn. */
-#define TARGET_QEMU_ESIGRETURN 255
-
 #define UNAME_MACHINE "mips64"
 #define UNAME_MINIMUM_RELEASE "2.6.32"
 
diff --git a/linux-user/ppc/syscall.h b/linux-user/ppc/syscall.h
index 0daf5cd..532cbbd 100644
--- a/linux-user/ppc/syscall.h
+++ b/linux-user/ppc/syscall.h
@@ -50,8 +50,6 @@ struct target_revectored_struct {
 	abi_ulong __map[8];			/* 256 bits */
 };
 
-/* Nasty hack: define a fake errno value for use by sigreturn.  */
-#define TARGET_QEMU_ESIGRETURN 255
 
 /*
  * flags masks
-- 
2.1.4

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

* [Qemu-devel] [PATCH 04/34] linux-user: Support for restarting system calls for x86 targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (2 preceding siblings ...)
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 03/34] linux-user: Support for restarting system calls Timothy E Baldwin
@ 2015-09-05 23:56 ` Timothy E Baldwin
  2015-09-10 18:08   ` Peter Maydell
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 05/34] linux-user: Support for restarting system calls for ARM targets Timothy E Baldwin
                   ` (30 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/i386/syscall.h   |  2 ++
 linux-user/main.c           | 47 ++++++++++++++++++++++++++++-----------------
 linux-user/signal.c         | 15 +++++++--------
 linux-user/syscall.c        |  2 --
 linux-user/x86_64/syscall.h |  2 ++
 5 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/linux-user/i386/syscall.h b/linux-user/i386/syscall.h
index 906aaac..f7d9fbe 100644
--- a/linux-user/i386/syscall.h
+++ b/linux-user/i386/syscall.h
@@ -150,3 +150,5 @@ struct target_vm86plus_struct {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
+
+#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/main.c b/linux-user/main.c
index 2c9658e..99fe591 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -274,6 +274,7 @@ void cpu_loop(CPUX86State *env)
     CPUState *cs = CPU(x86_env_get_cpu(env));
     int trapnr;
     abi_ulong pc;
+    abi_ulong ret;
     target_siginfo_t info;
 
     for(;;) {
@@ -283,28 +284,38 @@ void cpu_loop(CPUX86State *env)
         switch(trapnr) {
         case 0x80:
             /* linux syscall from int $0x80 */
-            env->regs[R_EAX] = do_syscall(env,
-                                          env->regs[R_EAX],
-                                          env->regs[R_EBX],
-                                          env->regs[R_ECX],
-                                          env->regs[R_EDX],
-                                          env->regs[R_ESI],
-                                          env->regs[R_EDI],
-                                          env->regs[R_EBP],
-                                          0, 0);
+            ret = do_syscall(env,
+                             env->regs[R_EAX],
+                             env->regs[R_EBX],
+                             env->regs[R_ECX],
+                             env->regs[R_EDX],
+                             env->regs[R_ESI],
+                             env->regs[R_EDI],
+                             env->regs[R_EBP],
+                             0, 0);
+            if (ret == -TARGET_ERESTARTSYS) {
+                env->eip -= 2;
+            } else if (ret != -TARGET_QEMU_ESIGRETURN) {
+                env->regs[R_EAX] = ret;
+            }
             break;
 #ifndef TARGET_ABI32
         case EXCP_SYSCALL:
             /* linux syscall from syscall instruction */
-            env->regs[R_EAX] = do_syscall(env,
-                                          env->regs[R_EAX],
-                                          env->regs[R_EDI],
-                                          env->regs[R_ESI],
-                                          env->regs[R_EDX],
-                                          env->regs[10],
-                                          env->regs[8],
-                                          env->regs[9],
-                                          0, 0);
+            ret = do_syscall(env,
+                             env->regs[R_EAX],
+                             env->regs[R_EDI],
+                             env->regs[R_ESI],
+                             env->regs[R_EDX],
+                             env->regs[10],
+                             env->regs[8],
+                             env->regs[9],
+                             0, 0);
+            if (ret == -TARGET_ERESTARTSYS) {
+                env->eip -= 2;
+            } else if (ret != -TARGET_QEMU_ESIGRETURN) {
+                env->regs[R_EAX] = ret;
+            }
             break;
 #endif
         case EXCP0B_NOSEG:
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 7c846c0..0186147 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1036,7 +1036,7 @@ give_sigsegv:
 }
 
 static int
-restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
+restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc)
 {
     unsigned int err = 0;
     abi_ulong fpstate_addr;
@@ -1054,6 +1054,7 @@ restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
     env->regs[R_EBX] = tswapl(sc->ebx);
     env->regs[R_EDX] = tswapl(sc->edx);
     env->regs[R_ECX] = tswapl(sc->ecx);
+    env->regs[R_EAX] = tswapl(sc->eax);
     env->eip = tswapl(sc->eip);
 
     cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3);
@@ -1071,7 +1072,6 @@ restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax)
         cpu_x86_frstor(env, fpstate_addr, 1);
     }
 
-    *peax = tswapl(sc->eax);
     return err;
 badframe:
     return 1;
@@ -1083,7 +1083,7 @@ long do_sigreturn(CPUX86State *env)
     abi_ulong frame_addr = env->regs[R_ESP] - 8;
     target_sigset_t target_set;
     sigset_t set;
-    int eax, i;
+    int i;
 
 #if defined(DEBUG_SIGNAL)
     fprintf(stderr, "do_sigreturn\n");
@@ -1100,10 +1100,10 @@ long do_sigreturn(CPUX86State *env)
     do_sigprocmask(SIG_SETMASK, &set, NULL);
 
     /* restore registers */
-    if (restore_sigcontext(env, &frame->sc, &eax))
+    if (restore_sigcontext(env, &frame->sc))
         goto badframe;
     unlock_user_struct(frame, frame_addr, 0);
-    return eax;
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     unlock_user_struct(frame, frame_addr, 0);
@@ -1116,7 +1116,6 @@ long do_rt_sigreturn(CPUX86State *env)
     abi_ulong frame_addr;
     struct rt_sigframe *frame;
     sigset_t set;
-    int eax;
 
     frame_addr = env->regs[R_ESP] - 4;
     if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
@@ -1125,7 +1124,7 @@ long do_rt_sigreturn(CPUX86State *env)
     target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
     do_sigprocmask(SIG_SETMASK, &set, NULL);
 
-    if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) {
+    if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
         goto badframe;
     }
 
@@ -1135,7 +1134,7 @@ long do_rt_sigreturn(CPUX86State *env)
     }
 
     unlock_user_struct(frame, frame_addr, 0);
-    return eax;
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     unlock_user_struct(frame, frame_addr, 0);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4e40dc6..04c91fb 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6601,12 +6601,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #ifdef TARGET_NR_sigreturn
     case TARGET_NR_sigreturn:
-        /* NOTE: ret is eax, so not transcoding must be done */
         ret = do_sigreturn(cpu_env);
         break;
 #endif
     case TARGET_NR_rt_sigreturn:
-        /* NOTE: ret is eax, so not transcoding must be done */
         ret = do_rt_sigreturn(cpu_env);
         break;
     case TARGET_NR_sethostname:
diff --git a/linux-user/x86_64/syscall.h b/linux-user/x86_64/syscall.h
index 88b3c3f..d41a93a 100644
--- a/linux-user/x86_64/syscall.h
+++ b/linux-user/x86_64/syscall.h
@@ -100,3 +100,5 @@ struct target_msqid64_ds {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
+
+#define TARGET_USE_ERESTARTSYS 1
-- 
2.1.4

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

* [Qemu-devel] [PATCH 05/34] linux-user: Support for restarting system calls for ARM targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (3 preceding siblings ...)
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 04/34] linux-user: Support for restarting system calls for x86 targets Timothy E Baldwin
@ 2015-09-05 23:56 ` Timothy E Baldwin
  2015-09-10 18:09   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 06/34] linux-user: Support for restarting system calls for MIPS targets Timothy E Baldwin
                   ` (29 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/aarch64/syscall.h |  2 ++
 linux-user/arm/syscall.h     |  2 ++
 linux-user/main.c            | 47 +++++++++++++++++++++++++++-----------------
 linux-user/signal.c          | 10 +++++-----
 4 files changed, 38 insertions(+), 23 deletions(-)

diff --git a/linux-user/aarch64/syscall.h b/linux-user/aarch64/syscall.h
index dc72a15..bc1f01b 100644
--- a/linux-user/aarch64/syscall.h
+++ b/linux-user/aarch64/syscall.h
@@ -11,3 +11,5 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ       2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
+
+#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/arm/syscall.h b/linux-user/arm/syscall.h
index 3844a96..38c925a 100644
--- a/linux-user/arm/syscall.h
+++ b/linux-user/arm/syscall.h
@@ -48,3 +48,5 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
+
+#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/main.c b/linux-user/main.c
index 99fe591..9653155 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -820,15 +820,20 @@ void cpu_loop(CPUARMState *env)
                             break;
                         }
                     } else {
-                        env->regs[0] = do_syscall(env,
-                                                  n,
-                                                  env->regs[0],
-                                                  env->regs[1],
-                                                  env->regs[2],
-                                                  env->regs[3],
-                                                  env->regs[4],
-                                                  env->regs[5],
-                                                  0, 0);
+                        abi_ulong ret = do_syscall(env,
+                                                   n,
+                                                   env->regs[0],
+                                                   env->regs[1],
+                                                   env->regs[2],
+                                                   env->regs[3],
+                                                   env->regs[4],
+                                                   env->regs[5],
+                                                   0, 0);
+                        if (ret == -TARGET_ERESTARTSYS) {
+                            env->regs[15] -= env->thumb ? 2 : 4;
+                        } else if (ret != -TARGET_QEMU_ESIGRETURN) {
+                            env->regs[0] = ret;
+                        }
                     }
                 } else {
                     goto error;
@@ -1010,6 +1015,7 @@ void cpu_loop(CPUARMState *env)
 {
     CPUState *cs = CPU(arm_env_get_cpu(env));
     int trapnr, sig;
+    abi_long ret;
     target_siginfo_t info;
 
     for (;;) {
@@ -1019,15 +1025,20 @@ void cpu_loop(CPUARMState *env)
 
         switch (trapnr) {
         case EXCP_SWI:
-            env->xregs[0] = do_syscall(env,
-                                       env->xregs[8],
-                                       env->xregs[0],
-                                       env->xregs[1],
-                                       env->xregs[2],
-                                       env->xregs[3],
-                                       env->xregs[4],
-                                       env->xregs[5],
-                                       0, 0);
+            ret = do_syscall(env,
+                             env->xregs[8],
+                             env->xregs[0],
+                             env->xregs[1],
+                             env->xregs[2],
+                             env->xregs[3],
+                             env->xregs[4],
+                             env->xregs[5],
+                             0, 0);
+            if (ret == -TARGET_ERESTARTSYS) {
+                env->pc -= 4;
+            } else if (ret != -TARGET_QEMU_ESIGRETURN) {
+                env->xregs[0] = ret;
+            }
             break;
         case EXCP_INTERRUPT:
             /* just indicate that signals should be handled asap */
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 0186147..c8f288b 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1402,7 +1402,7 @@ long do_rt_sigreturn(CPUARMState *env)
     }
 
     unlock_user_struct(frame, frame_addr, 0);
-    return env->xregs[0];
+    return -TARGET_QEMU_ESIGRETURN;
 
  badframe:
     unlock_user_struct(frame, frame_addr, 0);
@@ -1908,7 +1908,7 @@ static long do_sigreturn_v1(CPUARMState *env)
         send_sig(SIGTRAP, current, 1);
 #endif
     unlock_user_struct(frame, frame_addr, 0);
-    return env->regs[0];
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     force_sig(TARGET_SIGSEGV /* , current */);
@@ -2033,7 +2033,7 @@ static long do_sigreturn_v2(CPUARMState *env)
     }
 
     unlock_user_struct(frame, frame_addr, 0);
-    return env->regs[0];
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     unlock_user_struct(frame, frame_addr, 0);
@@ -2086,7 +2086,7 @@ static long do_rt_sigreturn_v1(CPUARMState *env)
         send_sig(SIGTRAP, current, 1);
 #endif
     unlock_user_struct(frame, frame_addr, 0);
-    return env->regs[0];
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     unlock_user_struct(frame, frame_addr, 0);
@@ -2118,7 +2118,7 @@ static long do_rt_sigreturn_v2(CPUARMState *env)
     }
 
     unlock_user_struct(frame, frame_addr, 0);
-    return env->regs[0];
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     unlock_user_struct(frame, frame_addr, 0);
-- 
2.1.4

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

* [Qemu-devel] [PATCH 06/34] linux-user: Support for restarting system calls for MIPS targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (4 preceding siblings ...)
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 05/34] linux-user: Support for restarting system calls for ARM targets Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 18:09   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 07/34] linux-user: Support for restarting system calls for PPC targets Timothy E Baldwin
                   ` (28 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/main.c           | 4 ++++
 linux-user/mips/syscall.h   | 2 ++
 linux-user/mips64/syscall.h | 2 ++
 3 files changed, 8 insertions(+)

diff --git a/linux-user/main.c b/linux-user/main.c
index 9653155..124e9cc 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2489,6 +2489,10 @@ done_syscall:
                              env->active_tc.gpr[8], env->active_tc.gpr[9],
                              env->active_tc.gpr[10], env->active_tc.gpr[11]);
 # endif /* O32 */
+            if (ret == -TARGET_ERESTARTSYS) {
+                env->active_tc.PC -= 4;
+                break;
+            }
             if (ret == -TARGET_QEMU_ESIGRETURN) {
                 /* Returning from a successful sigreturn syscall.
                    Avoid clobbering register state.  */
diff --git a/linux-user/mips/syscall.h b/linux-user/mips/syscall.h
index e34f80c..cede30c 100644
--- a/linux-user/mips/syscall.h
+++ b/linux-user/mips/syscall.h
@@ -227,3 +227,5 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
+
+#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h
index 33afb8d..88716c1 100644
--- a/linux-user/mips64/syscall.h
+++ b/linux-user/mips64/syscall.h
@@ -224,3 +224,5 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ      2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
+
+#define TARGET_USE_ERESTARTSYS 1
-- 
2.1.4

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

* [Qemu-devel] [PATCH 07/34] linux-user: Support for restarting system calls for PPC targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (5 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 06/34] linux-user: Support for restarting system calls for MIPS targets Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 18:10   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 08/34] linux-user: Support for restarting system calls for SPARC targets Timothy E Baldwin
                   ` (27 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/main.c        | 4 ++++
 linux-user/ppc/syscall.h | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/linux-user/main.c b/linux-user/main.c
index 124e9cc..5e9e3a8 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1948,6 +1948,10 @@ void cpu_loop(CPUPPCState *env)
             ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
                              env->gpr[5], env->gpr[6], env->gpr[7],
                              env->gpr[8], 0, 0);
+            if (ret == (target_ulong)(-TARGET_ERESTARTSYS)) {
+                env->nip -= 4;
+                break;
+            }
             if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
                 /* Returning from a successful sigreturn syscall.
                    Avoid corrupting register state.  */
diff --git a/linux-user/ppc/syscall.h b/linux-user/ppc/syscall.h
index 532cbbd..e75da7f 100644
--- a/linux-user/ppc/syscall.h
+++ b/linux-user/ppc/syscall.h
@@ -71,3 +71,5 @@ struct target_revectored_struct {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 0x2000
 #define TARGET_MLOCKALL_MCL_FUTURE  0x4000
+
+#define TARGET_USE_ERESTARTSYS 1
-- 
2.1.4

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

* [Qemu-devel] [PATCH 08/34] linux-user: Support for restarting system calls for SPARC targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (6 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 07/34] linux-user: Support for restarting system calls for PPC targets Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 18:10   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 09/34] linux-user: Test for restarting system calls Timothy E Baldwin
                   ` (26 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/main.c            | 3 +++
 linux-user/signal.c          | 2 +-
 linux-user/sparc/syscall.h   | 2 ++
 linux-user/sparc64/syscall.h | 2 ++
 4 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 5e9e3a8..d47e33f 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1326,6 +1326,9 @@ void cpu_loop (CPUSPARCState *env)
                               env->regwptr[2], env->regwptr[3],
                               env->regwptr[4], env->regwptr[5],
                               0, 0);
+            if (ret == -TARGET_ERESTARTSYS || ret == -TARGET_QEMU_ESIGRETURN) {
+                break;
+            }
             if ((abi_ulong)ret >= (abi_ulong)(-515)) {
 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
                 env->xcc |= PSR_CARRY;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index c8f288b..e432f97 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -2458,7 +2458,7 @@ long do_sigreturn(CPUSPARCState *env)
         goto segv_and_exit;
     }
     unlock_user_struct(sf, sf_addr, 0);
-    return env->regwptr[0];
+    return -TARGET_QEMU_ESIGRETURN;
 
 segv_and_exit:
     unlock_user_struct(sf, sf_addr, 0);
diff --git a/linux-user/sparc/syscall.h b/linux-user/sparc/syscall.h
index 58573b9..3844b59 100644
--- a/linux-user/sparc/syscall.h
+++ b/linux-user/sparc/syscall.h
@@ -18,3 +18,5 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ      4096
 #define TARGET_MLOCKALL_MCL_CURRENT 0x2000
 #define TARGET_MLOCKALL_MCL_FUTURE  0x4000
+
+#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/sparc64/syscall.h b/linux-user/sparc64/syscall.h
index 8398d3f..0adc5ad 100644
--- a/linux-user/sparc64/syscall.h
+++ b/linux-user/sparc64/syscall.h
@@ -19,3 +19,5 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ      4096
 #define TARGET_MLOCKALL_MCL_CURRENT 0x2000
 #define TARGET_MLOCKALL_MCL_FUTURE  0x4000
+
+#define TARGET_USE_ERESTARTSYS 1
-- 
2.1.4

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

* [Qemu-devel] [PATCH 09/34] linux-user: Test for restarting system calls
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (7 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 08/34] linux-user: Support for restarting system calls for SPARC targets Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 18:12   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 10/34] linux-user: Support for restarting system calls for Microblaze targets Timothy E Baldwin
                   ` (25 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

If DEBUG_ERESTARTSYS is set restart all system calls once.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/syscall.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 04c91fb..80b8fa8 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5585,6 +5585,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     struct statfs stfs;
     void *p;
 
+#if defined(DEBUG_ERESTARTSYS) && defined(TARGET_USE_ERESTARTSYS)
+    {
+        static int flag;
+        flag = !flag;
+        if (flag) {
+            return -TARGET_ERESTARTSYS;
+        }
+    }
+#endif
+
 #ifdef DEBUG
     gemu_log("syscall %d", num);
 #endif
-- 
2.1.4

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

* [Qemu-devel] [PATCH 10/34] linux-user: Support for restarting system calls for Microblaze targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (8 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 09/34] linux-user: Test for restarting system calls Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 18:14   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 11/34] linux-user: Support for restarting system calls for SH4 targets Timothy E Baldwin
                   ` (24 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---

Works without signals, but my signal test case
crashes with or without my changes.

 linux-user/main.c               | 14 +++++++++-----
 linux-user/microblaze/syscall.h |  2 ++
 linux-user/signal.c             |  2 +-
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index d47e33f..3eacc9c 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2911,14 +2911,14 @@ void cpu_loop(CPUMBState *env)
                 queue_signal(env, info.si_signo, &info);
             }
             break;
-	case EXCP_INTERRUPT:
-	  /* just indicate that signals should be handled asap */
-	  break;
+        case EXCP_INTERRUPT:
+            /* just indicate that signals should be handled asap */
+            break;
         case EXCP_BREAK:
             /* Return address is 4 bytes after the call.  */
             env->regs[14] += 4;
             env->sregs[SR_PC] = env->regs[14];
-            ret = do_syscall(env, 
+            ret = do_syscall(env,
                              env->regs[12], 
                              env->regs[5], 
                              env->regs[6], 
@@ -2927,7 +2927,11 @@ void cpu_loop(CPUMBState *env)
                              env->regs[9], 
                              env->regs[10],
                              0, 0);
-            env->regs[3] = ret;
+            if (ret == -TARGET_ERESTARTSYS) {
+                env->sregs[SR_PC] -= 4;
+            } else if (ret != -TARGET_QEMU_ESIGRETURN) {
+                env->regs[3] = ret;
+            }
             break;
         case EXCP_HW_EXCP:
             env->regs[17] = env->sregs[SR_PC] + 4;
diff --git a/linux-user/microblaze/syscall.h b/linux-user/microblaze/syscall.h
index 3c1ed27..c38e700 100644
--- a/linux-user/microblaze/syscall.h
+++ b/linux-user/microblaze/syscall.h
@@ -54,3 +54,5 @@ struct target_pt_regs {
 #define TARGET_MLOCKALL_MCL_FUTURE  2
 
 #endif
+
+#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/signal.c b/linux-user/signal.c
index e432f97..abc7e30 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -3636,7 +3636,7 @@ long do_sigreturn(CPUMBState *env)
     env->regs[14] = env->sregs[SR_PC];
 
     unlock_user_struct(frame, frame_addr, 0);
-    return env->regs[10];
+    return -TARGET_QEMU_ESIGRETURN;
 badframe:
     force_sig(TARGET_SIGSEGV);
 }
-- 
2.1.4

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

* [Qemu-devel] [PATCH 11/34] linux-user: Support for restarting system calls for SH4 targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (9 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 10/34] linux-user: Support for restarting system calls for Microblaze targets Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 18:15   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 12/34] linux-user: Support for restarting system calls for APLHA targets Timothy E Baldwin
                   ` (23 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---

Works without signals, but my signal test case
crashes with or without my changes.

linux-user/main.c        |  6 +++++-
 linux-user/sh4/syscall.h |  2 ++
 linux-user/signal.c      | 16 ++++++----------
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 3eacc9c..b239097 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2790,7 +2790,11 @@ void cpu_loop(CPUSH4State *env)
                              env->gregs[0],
                              env->gregs[1],
                              0, 0);
-            env->gregs[0] = ret;
+            if (ret == -TARGET_ERESTARTSYS) {
+                env->pc -= 2;
+            } else if (ret != -TARGET_QEMU_ESIGRETURN) {
+                env->gregs[0] = ret;
+            }
             break;
         case EXCP_INTERRUPT:
             /* just indicate that signals should be handled asap */
diff --git a/linux-user/sh4/syscall.h b/linux-user/sh4/syscall.h
index 7aa4f23..1c0bdfd 100644
--- a/linux-user/sh4/syscall.h
+++ b/linux-user/sh4/syscall.h
@@ -15,3 +15,5 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
+
+#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/signal.c b/linux-user/signal.c
index abc7e30..9629c72 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -3212,13 +3212,12 @@ static void setup_sigcontext(struct target_sigcontext *sc,
     __put_user(mask, &sc->oldmask);
 }
 
-static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
-                               target_ulong *r0_p)
+static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc)
 {
     int i;
 
 #define COPY(x)         __get_user(regs->x, &sc->sc_##x)
-    COPY(gregs[1]);
+    COPY(gregs[0]); COPY(gregs[1]);
     COPY(gregs[2]); COPY(gregs[3]);
     COPY(gregs[4]); COPY(gregs[5]);
     COPY(gregs[6]); COPY(gregs[7]);
@@ -3238,7 +3237,6 @@ static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc,
     __get_user(regs->fpul, &sc->sc_fpul);
 
     regs->tra = -1;         /* disable syscall checks */
-    __get_user(*r0_p, &sc->sc_gregs[0]);
 }
 
 static void setup_frame(int sig, struct target_sigaction *ka,
@@ -3357,7 +3355,6 @@ long do_sigreturn(CPUSH4State *regs)
     abi_ulong frame_addr;
     sigset_t blocked;
     target_sigset_t target_set;
-    target_ulong r0;
     int i;
     int err = 0;
 
@@ -3380,10 +3377,10 @@ long do_sigreturn(CPUSH4State *regs)
     target_to_host_sigset_internal(&blocked, &target_set);
     do_sigprocmask(SIG_SETMASK, &blocked, NULL);
 
-    restore_sigcontext(regs, &frame->sc, &r0);
+    restore_sigcontext(regs, &frame->sc);
 
     unlock_user_struct(frame, frame_addr, 0);
-    return r0;
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     unlock_user_struct(frame, frame_addr, 0);
@@ -3396,7 +3393,6 @@ long do_rt_sigreturn(CPUSH4State *regs)
     struct target_rt_sigframe *frame;
     abi_ulong frame_addr;
     sigset_t blocked;
-    target_ulong r0;
 
 #if defined(DEBUG_SIGNAL)
     fprintf(stderr, "do_rt_sigreturn\n");
@@ -3409,7 +3405,7 @@ long do_rt_sigreturn(CPUSH4State *regs)
     target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
     do_sigprocmask(SIG_SETMASK, &blocked, NULL);
 
-    restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0);
+    restore_sigcontext(regs, &frame->uc.tuc_mcontext);
 
     if (do_sigaltstack(frame_addr +
                        offsetof(struct target_rt_sigframe, uc.tuc_stack),
@@ -3418,7 +3414,7 @@ long do_rt_sigreturn(CPUSH4State *regs)
     }
 
     unlock_user_struct(frame, frame_addr, 0);
-    return r0;
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     unlock_user_struct(frame, frame_addr, 0);
-- 
2.1.4

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

* [Qemu-devel] [PATCH 12/34] linux-user: Support for restarting system calls for APLHA targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (10 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 11/34] linux-user: Support for restarting system calls for SH4 targets Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 18:16   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 13/34] linux-user: Fix signal before blocking system calls race and SA_RESTART Timothy E Baldwin
                   ` (22 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---

Signal handling NOT TESTED

 linux-user/alpha/syscall.h | 2 ++
 linux-user/main.c          | 7 +++++--
 linux-user/signal.c        | 4 ++--
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/linux-user/alpha/syscall.h b/linux-user/alpha/syscall.h
index 245cff2..554a4bf 100644
--- a/linux-user/alpha/syscall.h
+++ b/linux-user/alpha/syscall.h
@@ -255,3 +255,5 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ              4096
 #define TARGET_MLOCKALL_MCL_CURRENT     0x2000
 #define TARGET_MLOCKALL_MCL_FUTURE      0x4000
+
+#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/main.c b/linux-user/main.c
index b239097..349abe2 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3237,8 +3237,11 @@ void cpu_loop(CPUAlphaState *env)
                                     env->ir[IR_A2], env->ir[IR_A3],
                                     env->ir[IR_A4], env->ir[IR_A5],
                                     0, 0);
-                if (trapnr == TARGET_NR_sigreturn
-                    || trapnr == TARGET_NR_rt_sigreturn) {
+                if (sysret == -TARGET_ERESTARTSYS) {
+                    env->ir[IR_PV] -= 4;
+                    break;
+                }
+                if (sysret == -TARGET_QEMU_ESIGRETURN) {
                     break;
                 }
                 /* Syscall writes 0 to V0 to bypass error check, similar
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 9629c72..5cf75a4 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5548,7 +5548,7 @@ long do_sigreturn(CPUAlphaState *env)
 
     restore_sigcontext(env, sc);
     unlock_user_struct(sc, sc_addr, 0);
-    return env->ir[IR_V0];
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     force_sig(TARGET_SIGSEGV);
@@ -5574,7 +5574,7 @@ long do_rt_sigreturn(CPUAlphaState *env)
     }
 
     unlock_user_struct(frame, frame_addr, 0);
-    return env->ir[IR_V0];
+    return -TARGET_QEMU_ESIGRETURN;
 
 
 badframe:
-- 
2.1.4

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

* [Qemu-devel] [PATCH 13/34] linux-user: Fix signal before blocking system calls race and SA_RESTART
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (11 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 12/34] linux-user: Support for restarting system calls for APLHA targets Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 18:46   ` Peter Maydell
  2015-09-11 10:57   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 14/34] linux-user: Use safe_syscall for read and write system calls Timothy E Baldwin
                   ` (21 subsequent siblings)
  34 siblings, 2 replies; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

If a signal is delivered immediately before a blocking system calls the
handler will only be called after the system call returns, which may be a
long time later or never.

This is fixed by using a function (safe_syscall_base) that checks  if a guest
signal is pending prior to making a system call, and if so does not call the
system call and returns -TARGET_ERESTARTSYS. If a signal is received between
the check and the system call host_signal_handler() rewinds execution to
before the check. If the system call returns an error a guest error code
is returned.

safe_syscall_base is implemented in assembly language with initially
only a x86-64 version, a fall back is provided keep the old behaviour.

Also setting the SA_RESTART flag would result in host system calls being
restarted and the guest signal handler only being called when they have
completed. This is also fixed.

This commit contains general infrastructure and safe_syscall_base for x86-64.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 configure                        |  13 +++++
 linux-user/Makefile.objs         |   3 +-
 linux-user/qemu.h                |  17 +++++++
 linux-user/safe_syscall/x86_64.S |  34 +++++++++++++
 linux-user/signal.c              |  12 +++++
 linux-user/syscall.c             | 107 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 185 insertions(+), 1 deletion(-)
 create mode 100644 linux-user/safe_syscall/x86_64.S

diff --git a/configure b/configure
index 21c4089..d7c115a 100755
--- a/configure
+++ b/configure
@@ -5219,6 +5219,19 @@ if test "$gcov" = "yes" ; then
   echo "GCOV=$gcov_tool" >> $config_host_mak
 fi
 
+# Which safe_syscall_base implmentation?
+if test "$linux" = "yes" ; then
+  case "$cpu" in
+  x86_64)
+    echo "SAFE_SYSCALL_BASE=safe_syscall/x86_64.o" >> $config_host_mak
+    echo "CONFIG_SAFE_SYSCALL=y" >> $config_host_mak
+    ;;
+  *)
+    echo "SAFE_SYSCALL_BASE=" >> $config_host_mak
+    ;;
+  esac
+fi
+
 # use included Linux headers
 if test "$linux" = "yes" ; then
   mkdir -p linux-headers
diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs
index fd50217..56f9937 100644
--- a/linux-user/Makefile.objs
+++ b/linux-user/Makefile.objs
@@ -1,5 +1,6 @@
 obj-y = main.o syscall.o strace.o mmap.o signal.o \
-	elfload.o linuxload.o uaccess.o uname.o
+	elfload.o linuxload.o uaccess.o uname.o \
+	$(SAFE_SYSCALL_BASE)
 
 obj-$(TARGET_HAS_BFLT) += flatload.o
 obj-$(TARGET_I386) += vm86.o
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 8012cc2..57c7e43 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -216,8 +216,25 @@ unsigned long init_guest_space(unsigned long host_start,
 
 #include "qemu/log.h"
 
+/* safe_syscall.S */
+
+/* Call a system call if guest signal not pending.
+ * Returns -TARGET_ESIGRETURN if signal pending.
+ * Returns guest error code on error.
+ */
+
+extern long safe_syscall_base(volatile int *pending, long number, ...);
+#define safe_syscall(...) \
+    safe_syscall_base(&((TaskState *)thread_cpu->opaque)->signal_pending, \
+    __VA_ARGS__)
+
+/* For host_signal_handler() */
+extern char safe_syscall_start[];
+extern char safe_syscall_end[];
+
 /* syscall.c */
 int host_to_target_waitstatus(int status);
+abi_long convert_syscall_return_value(abi_long ret);
 
 /* strace.c */
 void print_syscall(int num,
diff --git a/linux-user/safe_syscall/x86_64.S b/linux-user/safe_syscall/x86_64.S
new file mode 100644
index 0000000..2e32563
--- /dev/null
+++ b/linux-user/safe_syscall/x86_64.S
@@ -0,0 +1,34 @@
+#include "errno_defs.h"
+
+        .global safe_syscall_base
+        .global safe_syscall_start
+        .global safe_syscall_end
+        .type   safe_syscall_base, @function
+
+safe_syscall_base:
+        push    %rbp
+        mov     %rsi, %rax // Move syscall number
+        mov     %rdi, %rbp // Move signal_pending pointer
+
+        mov     %rdx, %rdi // Move syscall arguments
+        mov     %rcx, %rsi
+        mov     %r8,  %rdx
+        mov     %r9,  %r10
+        mov     16(%rsp), %r8
+        mov     24(%rsp), %r9
+
+safe_syscall_start:
+        testl   $1, (%rbp) // Check signal_pending
+        jnz     return_ERESTARTSYS
+        syscall
+safe_syscall_end:
+        pop     %rbp
+        mov     %rax, %rdi
+        jmp     convert_syscall_return_value
+
+return_ERESTARTSYS:
+        mov     $-TARGET_ERESTARTSYS, %rax
+        pop     %rbp
+        ret
+
+        .size   safe_syscall_base, .-safe_syscall_base
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 5cf75a4..09551ba 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -569,6 +569,10 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
     }
 }
 
+#if defined(__x86_64__)
+#define PC_SIG (uc->uc_mcontext.gregs[REG_RIP])
+#endif
+
 static void host_signal_handler(int host_signum, siginfo_t *info,
                                 void *puc)
 {
@@ -591,6 +595,14 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
 #if defined(DEBUG_SIGNAL)
     fprintf(stderr, "qemu: got signal %d\n", sig);
 #endif
+
+    struct ucontext *uc = puc;
+#ifdef CONFIG_SAFE_SYSCALL
+    if (PC_SIG > (uintptr_t)safe_syscall_start
+            && PC_SIG < (uintptr_t)safe_syscall_end)
+        PC_SIG = (uintptr_t)safe_syscall_start;
+#endif
+
     host_to_target_siginfo_noswap(&tinfo, info);
     if (queue_signal(env, sig, &tinfo) == 1) {
         /* interrupt the virtual CPU as soon as possible */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 80b8fa8..b9ad7b6 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -599,6 +599,113 @@ char *target_strerror(int err)
     return strerror(target_to_host_errno(err));
 }
 
+abi_long convert_syscall_return_value(abi_long ret) {
+    if (is_error(ret)) {
+        ret = host_to_target_errno(ret);
+    }
+    return ret;
+}
+
+#if defined(CONFIG_SAFE_SYSCALL) && defined(TARGET_USE_ERESTARTSYS)
+
+#define safe_syscall0(type, name) \
+static type safe_##name (void) \
+{ \
+    return safe_syscall(__NR_##name); \
+}
+
+#define safe_syscall1(type, name, type1, arg1) \
+static type safe_##name (type1 arg1) \
+{ \
+    return safe_syscall(__NR_##name, arg1); \
+}
+
+#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
+static type safe_##name (type1 arg1, type2 arg2) \
+{ \
+    return safe_syscall(__NR_##name, arg1, arg2); \
+}
+
+#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+static type safe_##name (type1 arg1, type2 arg2, type3 arg3) \
+{ \
+    return safe_syscall(__NR_##name, arg1, arg2, arg3); \
+}
+
+#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
+    type4, arg4) \
+static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+{ \
+    return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
+}
+
+#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
+    type4, arg4, type5, arg5) \
+static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+    type5 arg5) \
+{ \
+    return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
+}
+
+#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
+    type4, arg4, type5, arg5, type6, arg6) \
+static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+    type5 arg5, type6 arg6) \
+{ \
+    return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
+}
+
+#else
+
+#define safe_syscall0(type, name) \
+static type safe_##name (void) \
+{ \
+    return get_errno(name()); \
+}
+
+#define safe_syscall1(type, name, type1, arg1) \
+static type safe_##name (type1 arg1) \
+{ \
+    return get_errno(name(arg1)); \
+}
+
+#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
+static type safe_##name (type1 arg1, type2 arg2) \
+{ \
+    return get_errno(name(arg1, arg2)); \
+}
+
+#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+static type safe_##name (type1 arg1, type2 arg2, type3 arg3) \
+{ \
+    return get_errno(name(arg1, arg2, arg3)); \
+}
+
+#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
+    type4, arg4) \
+static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+{ \
+    return get_errno(name(arg1, arg2, arg3, arg4)); \
+}
+
+#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
+    type4, arg4, type5, arg5) \
+static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+    type5 arg5) \
+{ \
+    return get_errno(name(arg1, arg2, arg3, arg4, arg5)); \
+}
+
+#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
+    type4, arg4, type5, arg5, type6, arg6) \
+static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+    type5 arg5, type6 arg6)  \
+{ \
+    return get_errno(name(arg1, arg2, arg3, arg4, arg5, arg6)); \
+}
+
+#endif
+
 static inline int host_to_target_sock_type(int host_type)
 {
     int target_type;
-- 
2.1.4

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

* [Qemu-devel] [PATCH 14/34] linux-user: Use safe_syscall for read and write system calls
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (12 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 13/34] linux-user: Fix signal before blocking system calls race and SA_RESTART Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 18:48   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 15/34] linux-user: Remove redundant get_errno() calls Timothy E Baldwin
                   ` (20 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Restart read() and write() if signals occur before, or during with SA_RESTART

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/syscall.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index b9ad7b6..c213588 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -706,6 +706,10 @@ static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
 
 #endif
 
+safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
+safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
+
+
 static inline int host_to_target_sock_type(int host_type)
 {
     int target_type;
@@ -5747,14 +5751,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         else {
             if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
                 goto efault;
-            ret = get_errno(read(arg1, p, arg3));
+            ret = safe_read(arg1, p, arg3);
             unlock_user(p, arg2, ret);
         }
         break;
     case TARGET_NR_write:
         if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
             goto efault;
-        ret = get_errno(write(arg1, p, arg3));
+        ret = safe_write(arg1, p, arg3);
         unlock_user(p, arg2, 0);
         break;
     case TARGET_NR_open:
-- 
2.1.4

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

* [Qemu-devel] [PATCH 15/34] linux-user: Remove redundant get_errno() calls
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (13 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 14/34] linux-user: Use safe_syscall for read and write system calls Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 18:50   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 16/34] linux-user: Use safe_syscall for open and openat system calls Timothy E Baldwin
                   ` (19 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

The return value of openat was being translated by get_errno() twice.
Fixed by removing calls of get_errno() in do_syscall() and keeping those
in do_openat().

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/syscall.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c213588..df9b2ca 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5764,17 +5764,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_open:
         if (!(p = lock_user_string(arg1)))
             goto efault;
-        ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
-                                  target_to_host_bitmask(arg2, fcntl_flags_tbl),
-                                  arg3));
+        ret = do_openat(cpu_env, AT_FDCWD, p,
+                        target_to_host_bitmask(arg2, fcntl_flags_tbl),
+                        arg3);
         unlock_user(p, arg1, 0);
         break;
     case TARGET_NR_openat:
         if (!(p = lock_user_string(arg2)))
             goto efault;
-        ret = get_errno(do_openat(cpu_env, arg1, p,
-                                  target_to_host_bitmask(arg3, fcntl_flags_tbl),
-                                  arg4));
+        ret = do_openat(cpu_env, arg1, p,
+                        target_to_host_bitmask(arg3, fcntl_flags_tbl),
+                        arg4);
         unlock_user(p, arg2, 0);
         break;
     case TARGET_NR_close:
-- 
2.1.4

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

* [Qemu-devel] [PATCH 16/34] linux-user: Use safe_syscall for open and openat system calls
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (14 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 15/34] linux-user: Remove redundant get_errno() calls Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 18:54   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 17/34] linux-user: Use safe_syscall for wait " Timothy E Baldwin
                   ` (18 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Restart open() and openat() if signals occur before,
or during with SA_RESTART.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/syscall.c | 18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index df9b2ca..e68eddb 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -303,18 +303,6 @@ static int sys_getcwd1(char *buf, size_t size)
   return strlen(buf)+1;
 }
 
-static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode)
-{
-  /*
-   * open(2) has extra parameter 'mode' when called with
-   * flag O_CREAT.
-   */
-  if ((flags & O_CREAT) != 0) {
-      return (openat(dirfd, pathname, flags, mode));
-  }
-  return (openat(dirfd, pathname, flags));
-}
-
 #ifdef TARGET_NR_utimensat
 #ifdef CONFIG_UTIMENSAT
 static int sys_utimensat(int dirfd, const char *pathname,
@@ -708,6 +696,8 @@ static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
 
 safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
 safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
+safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
+    int, flags, mode_t, mode)
 
 
 static inline int host_to_target_sock_type(int host_type)
@@ -5624,7 +5614,7 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags,
 
     if (is_proc_myself(pathname, "exe")) {
         int execfd = qemu_getauxval(AT_EXECFD);
-        return execfd ? execfd : get_errno(sys_openat(dirfd, exec_path, flags, mode));
+        return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode);
     }
 
     for (fake_open = fakes; fake_open->filename; fake_open++) {
@@ -5658,7 +5648,7 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags,
         return fd;
     }
 
-    return get_errno(sys_openat(dirfd, path(pathname), flags, mode));
+    return safe_openat(dirfd, path(pathname), flags, mode);
 }
 
 #define TIMER_MAGIC 0x0caf0000
-- 
2.1.4

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

* [Qemu-devel] [PATCH 17/34] linux-user: Use safe_syscall for wait system calls
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (15 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 16/34] linux-user: Use safe_syscall for open and openat system calls Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 18:58   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 18/34] linux-user: Fix race between multiple signals Timothy E Baldwin
                   ` (17 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/syscall.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e68eddb..281fa2d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -698,6 +698,10 @@ safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
 safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
 safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
     int, flags, mode_t, mode)
+safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
+    struct rusage *, rusage)
+safe_syscall4(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
+    int, options)
 
 
 static inline int host_to_target_sock_type(int host_type)
@@ -5780,7 +5784,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_waitpid:
         {
             int status;
-            ret = get_errno(waitpid(arg1, &status, arg3));
+            ret = safe_wait4(arg1, &status, arg3, 0);
             if (!is_error(ret) && arg2 && ret
                 && put_user_s32(host_to_target_waitstatus(status), arg2))
                 goto efault;
@@ -5792,7 +5796,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         {
             siginfo_t info;
             info.si_pid = 0;
-            ret = get_errno(waitid(arg1, arg2, &info, arg4));
+            ret = safe_waitid(arg1, arg2, &info, arg4);
             if (!is_error(ret) && arg3 && info.si_pid != 0) {
                 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
                     goto efault;
@@ -7453,7 +7457,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 rusage_ptr = &rusage;
             else
                 rusage_ptr = NULL;
-            ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
+            ret = safe_wait4(arg1, &status, arg3, rusage_ptr);
             if (!is_error(ret)) {
                 if (status_ptr && ret) {
                     status = host_to_target_waitstatus(status);
-- 
2.1.4

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

* [Qemu-devel] [PATCH 18/34] linux-user: Fix race between multiple signals
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (16 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 17/34] linux-user: Use safe_syscall for wait " Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-11 14:30   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 19/34] linux-user: Restart fork() if signals pending Timothy E Baldwin
                   ` (16 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

If multiple host signals are recieved in quick succession they would
be queued in TaskState then delivered to the guest in spite of
signals being blocked. Fixed by keeping host signals blocked until
process_pending_signals() runs, this needs the guest signal state
to be maintained by Qemu.

Blocking host signals also ensures the correct behaviour with respect
to multiple threads and the overrun count of timer related signals.
Alas blocking and queuing in qemu is still needed because of virtual
processor exceptions, SIGSEGV and SIGBUS.

Blocking signals inside process_pending_signals() protects against
concurrency problems with respect to signal handlers.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>

Conflicts:
	linux-user/qemu.h
---
 linux-user/qemu.h    |   8 +++-
 linux-user/signal.c  | 111 ++++++++++++++++++++++++++++++++++-----------------
 linux-user/syscall.c |  49 +++++++++++++++--------
 3 files changed, 113 insertions(+), 55 deletions(-)

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 57c7e43..f2235eb3 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -127,14 +127,17 @@ typedef struct TaskState {
 #endif
     uint32_t stack_base;
     int used; /* non zero if used */
-    bool sigsegv_blocked; /* SIGSEGV blocked by guest */
     struct image_info *info;
     struct linux_binprm *bprm;
 
     struct emulated_sigtable sigtab[TARGET_NSIG];
     struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
     struct sigqueue *first_free; /* first free siginfo queue entry */
-    int signal_pending; /* non zero if a signal may be pending */
+    sigset_t signal_mask;
+
+    /* non zero if host signals blocked, bit 1 set if signal pending */
+    volatile int signal_pending;
+
 } __attribute__((aligned(16))) TaskState;
 
 extern char *exec_path;
@@ -255,6 +258,7 @@ long do_sigreturn(CPUArchState *env);
 long do_rt_sigreturn(CPUArchState *env);
 abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
 int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
+int block_signals(void); /* Returns non zero if signal pending */
 
 #ifdef TARGET_I386
 /* vm86.c */
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 09551ba..3e272a5 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -197,53 +197,66 @@ void target_to_host_old_sigset(sigset_t *sigset,
     target_to_host_sigset(sigset, &d);
 }
 
+int block_signals(void)
+{
+    TaskState *ts = (TaskState *)thread_cpu->opaque;
+    sigset_t set;
+    int pending;
+
+    sigfillset(&set);
+    sigdelset(&set, SIGSEGV);
+    sigdelset(&set, SIGBUS);
+    sigprocmask(SIG_SETMASK, &set, 0);
+
+    pending = ts->signal_pending;
+    pending |= 2;
+    ts->signal_pending = pending;
+
+#ifdef TARGET_USE_ERESTARTSYS
+    return pending & 1;
+#endif
+    return 0;
+}
+
 /* Wrapper for sigprocmask function
  * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
- * are host signal set, not guest ones. This wraps the sigprocmask host calls
- * that should be protected (calls originated from guest)
+ * are host signal set, not guest ones.
  */
 int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
 {
-    int ret;
-    sigset_t val;
-    sigset_t *temp = NULL;
-    CPUState *cpu = thread_cpu;
-    TaskState *ts = (TaskState *)cpu->opaque;
-    bool segv_was_blocked = ts->sigsegv_blocked;
+    TaskState *ts = (TaskState *)thread_cpu->opaque;
+
+    if (oldset) {
+        *oldset = ts->signal_mask;
+    }
 
     if (set) {
-        bool has_sigsegv = sigismember(set, SIGSEGV);
-        val = *set;
-        temp = &val;
+        int i;
 
-        sigdelset(temp, SIGSEGV);
+        if (block_signals()) {
+            return -TARGET_ERESTARTSYS;
+        }
 
         switch (how) {
         case SIG_BLOCK:
-            if (has_sigsegv) {
-                ts->sigsegv_blocked = true;
-            }
+            sigorset(&ts->signal_mask, &ts->signal_mask, set);
             break;
         case SIG_UNBLOCK:
-            if (has_sigsegv) {
-                ts->sigsegv_blocked = false;
+            for (i = 0; i != NSIG; ++i) {
+                if (sigismember(set, i)) {
+                    sigdelset(&ts->signal_mask, i);
+                }
             }
             break;
         case SIG_SETMASK:
-            ts->sigsegv_blocked = has_sigsegv;
+            ts->signal_mask = *set;
             break;
         default:
             g_assert_not_reached();
         }
-    }
-
-    ret = sigprocmask(how, temp, oldset);
 
-    if (oldset && segv_was_blocked) {
-        sigaddset(oldset, SIGSEGV);
     }
-
-    return ret;
+    return 0;
 }
 
 /* siginfo conversion */
@@ -374,6 +387,7 @@ static int core_dump_signal(int sig)
 
 void signal_init(void)
 {
+    TaskState *ts = (TaskState *)thread_cpu->opaque;
     struct sigaction act;
     struct sigaction oact;
     int i, j;
@@ -389,6 +403,9 @@ void signal_init(void)
         target_to_host_signal_table[j] = i;
     }
 
+    /* Set the signal mask from the host mask. */
+    sigprocmask(0, 0, &ts->signal_mask);
+
     /* set all host signal handlers. ALL signals are blocked during
        the handlers to serialize them. */
     memset(sigact_table, 0, sizeof(sigact_table));
@@ -508,7 +525,7 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
     queue = gdb_queuesig ();
     handler = sigact_table[sig - 1]._sa_handler;
 
-    if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
+    if (sig == TARGET_SIGSEGV && sigismember(&ts->signal_mask, SIGSEGV)) {
         /* Guest has blocked SIGSEGV but we got one anyway. Assume this
          * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
          * because it got a real MMU fault). A blocked SIGSEGV in that
@@ -605,6 +622,11 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
 
     host_to_target_siginfo_noswap(&tinfo, info);
     if (queue_signal(env, sig, &tinfo) == 1) {
+        /* Block host signals until target signal handler entered */
+        sigfillset(&uc->uc_sigmask);
+        sigdelset(&uc->uc_sigmask, SIGSEGV);
+        sigdelset(&uc->uc_sigmask, SIGBUS);
+
         /* interrupt the virtual CPU as soon as possible */
         cpu_exit(thread_cpu);
     }
@@ -5628,26 +5650,40 @@ void process_pending_signals(CPUArchState *cpu_env)
     CPUState *cpu = ENV_GET_CPU(cpu_env);
     int sig;
     abi_ulong handler;
-    sigset_t set, old_set;
+    sigset_t set;
     target_sigset_t target_old_set;
     struct emulated_sigtable *k;
     struct target_sigaction *sa;
     struct sigqueue *q;
     TaskState *ts = cpu->opaque;
 
-    if (!ts->signal_pending)
+restart:
+    if (!ts->signal_pending) {
         return;
+    }
 
     /* FIXME: This is not threadsafe.  */
+    sigfillset(&set);
+    sigprocmask(SIG_SETMASK, &set, 0);
+
+ next_signal:
     k = ts->sigtab;
     for(sig = 1; sig <= TARGET_NSIG; sig++) {
-        if (k->pending)
+        if (k->pending && (
+                    !sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
+                    || sig == TARGET_SIGSEGV)) {
             goto handle_signal;
+        }
         k++;
     }
-    /* if no signal is pending, just return */
+
+    /* if no signal is pending, unblock signals and restart */
     ts->signal_pending = 0;
-    return;
+    set = ts->signal_mask;
+    sigdelset(&set, SIGSEGV);
+    sigdelset(&set, SIGBUS);
+    sigprocmask(SIG_SETMASK, &set, 0);
+    goto restart; /* Another signal? */
 
  handle_signal:
 #ifdef DEBUG_SIGNAL
@@ -5668,7 +5704,7 @@ void process_pending_signals(CPUArchState *cpu_env)
         handler = sa->_sa_handler;
     }
 
-    if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
+    if (sig == TARGET_SIGSEGV && sigismember(&ts->signal_mask, SIGSEGV)) {
         /* Guest has blocked SIGSEGV but we got one anyway. Assume this
          * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
          * because it got a real MMU fault), and treat as if default handler.
@@ -5698,11 +5734,12 @@ void process_pending_signals(CPUArchState *cpu_env)
         if (!(sa->sa_flags & TARGET_SA_NODEFER))
             sigaddset(&set, target_to_host_signal(sig));
 
-        /* block signals in the handler using Linux */
-        do_sigprocmask(SIG_BLOCK, &set, &old_set);
         /* save the previous blocked signal state to restore it at the
            end of the signal execution (see do_sigreturn) */
-        host_to_target_sigset_internal(&target_old_set, &old_set);
+        host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
+
+        /* block signals in the handler */
+        sigorset(&ts->signal_mask, &ts->signal_mask, &set);
 
         /* if the CPU is in VM86 mode, we restore the 32 bit values */
 #if defined(TARGET_I386) && !defined(TARGET_X86_64)
@@ -5722,9 +5759,11 @@ void process_pending_signals(CPUArchState *cpu_env)
         else
             setup_frame(sig, sa, &target_old_set, cpu_env);
 #endif
-	if (sa->sa_flags & TARGET_SA_RESETHAND)
+        if (sa->sa_flags & TARGET_SA_RESETHAND)
             sa->_sa_handler = TARGET_SIG_DFL;
     }
     if (q != &k->info)
         free_sigqueue(cpu_env, q);
+
+    goto next_signal;
 }
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 281fa2d..682090d 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4676,6 +4676,7 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
         new_cpu->opaque = ts;
         ts->bprm = parent_ts->bprm;
         ts->info = parent_ts->info;
+        ts->signal_mask = parent_ts->signal_mask;
         nptl_flags = flags;
         flags &= ~CLONE_NPTL_FLAGS2;
 
@@ -6492,9 +6493,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         {
             sigset_t cur_set;
             abi_ulong target_set;
-            do_sigprocmask(0, NULL, &cur_set);
-            host_to_target_old_sigset(&target_set, &cur_set);
-            ret = target_set;
+            ret = do_sigprocmask(0, NULL, &cur_set);
+            if (!ret) {
+                host_to_target_old_sigset(&target_set, &cur_set);
+                ret = target_set;
+            }
         }
         break;
 #endif
@@ -6503,12 +6506,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         {
             sigset_t set, oset, cur_set;
             abi_ulong target_set = arg1;
-            do_sigprocmask(0, NULL, &cur_set);
-            target_to_host_old_sigset(&set, &target_set);
-            sigorset(&set, &set, &cur_set);
-            do_sigprocmask(SIG_SETMASK, &set, &oset);
-            host_to_target_old_sigset(&target_set, &oset);
-            ret = target_set;
+            ret = do_sigprocmask(0, NULL, &cur_set);
+            if (!ret) {
+                target_to_host_old_sigset(&set, &target_set);
+                sigorset(&set, &set, &cur_set);
+                do_sigprocmask(SIG_SETMASK, &set, &oset);
+                host_to_target_old_sigset(&target_set, &oset);
+                ret = target_set;
+            }
         }
         break;
 #endif
@@ -6537,7 +6542,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             mask = arg2;
             target_to_host_old_sigset(&set, &mask);
 
-            ret = get_errno(do_sigprocmask(how, &set, &oldset));
+            ret = do_sigprocmask(how, &set, &oldset);
             if (!is_error(ret)) {
                 host_to_target_old_sigset(&mask, &oldset);
                 ret = mask;
@@ -6571,7 +6576,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 how = 0;
                 set_ptr = NULL;
             }
-            ret = get_errno(do_sigprocmask(how, set_ptr, &oldset));
+            ret = do_sigprocmask(how, set_ptr, &oldset);
             if (!is_error(ret) && arg3) {
                 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
                     goto efault;
@@ -6611,7 +6616,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 how = 0;
                 set_ptr = NULL;
             }
-            ret = get_errno(do_sigprocmask(how, set_ptr, &oldset));
+            ret = do_sigprocmask(how, set_ptr, &oldset);
             if (!is_error(ret) && arg3) {
                 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
                     goto efault;
@@ -6716,11 +6721,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #ifdef TARGET_NR_sigreturn
     case TARGET_NR_sigreturn:
-        ret = do_sigreturn(cpu_env);
+        if (block_signals()) {
+            ret = -TARGET_ERESTARTSYS;
+        } else {
+            ret = do_sigreturn(cpu_env);
+        }
         break;
 #endif
     case TARGET_NR_rt_sigreturn:
-        ret = do_rt_sigreturn(cpu_env);
+        if (block_signals()) {
+            ret = -TARGET_ERESTARTSYS;
+        } else {
+            ret = do_rt_sigreturn(cpu_env);
+        }
         break;
     case TARGET_NR_sethostname:
         if (!(p = lock_user_string(arg1)))
@@ -8744,9 +8757,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             }
             mask = arg2;
             target_to_host_old_sigset(&set, &mask);
-            do_sigprocmask(how, &set, &oldset);
-            host_to_target_old_sigset(&mask, &oldset);
-            ret = mask;
+            ret = do_sigprocmask(how, &set, &oldset);
+            if (!ret) {
+                host_to_target_old_sigset(&mask, &oldset);
+                ret = mask;
+            }
         }
         break;
 #endif
-- 
2.1.4

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

* [Qemu-devel] [PATCH 19/34] linux-user: Restart fork() if signals pending
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (17 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 18/34] linux-user: Fix race between multiple signals Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-11 14:34   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 20/34] linux-user: Remove redundant default action check in queue_signal() Timothy E Baldwin
                   ` (15 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

If there is a signal pending during fork() the signal handler will
erroneously be called in both the parent and child, so handle any
pending signals first.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/syscall.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 682090d..1ce381e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4731,6 +4731,11 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
         if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) {
             return -TARGET_EINVAL;
         }
+
+        if (block_signals()) {
+            return -TARGET_ERESTARTSYS;
+        }
+
         fork_start();
         ret = fork();
         if (ret == 0) {
-- 
2.1.4

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

* [Qemu-devel] [PATCH 20/34] linux-user: Remove redundant default action check in queue_signal()
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (18 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 19/34] linux-user: Restart fork() if signals pending Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-11 14:41   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 21/34] linux-user: Remove redundant gdb_queuesig() Timothy E Baldwin
                   ` (14 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Both queue_signal() and process_pending_signals() did check for default
actions of signals, this is redundant and also causes fatal and stopping
signals to incorrectly cause guest system calls to be interrupted.

The code in queue_signal() is removed.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/signal.c | 37 -------------------------------------
 1 file changed, 37 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 3e272a5..f57dbf5 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -514,49 +514,13 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
     TaskState *ts = cpu->opaque;
     struct emulated_sigtable *k;
     struct sigqueue *q, **pq;
-    abi_ulong handler;
-    int queue;
 
 #if defined(DEBUG_SIGNAL)
     fprintf(stderr, "queue_signal: sig=%d\n",
             sig);
 #endif
     k = &ts->sigtab[sig - 1];
-    queue = gdb_queuesig ();
-    handler = sigact_table[sig - 1]._sa_handler;
 
-    if (sig == TARGET_SIGSEGV && sigismember(&ts->signal_mask, SIGSEGV)) {
-        /* Guest has blocked SIGSEGV but we got one anyway. Assume this
-         * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
-         * because it got a real MMU fault). A blocked SIGSEGV in that
-         * situation is treated as if using the default handler. This is
-         * not correct if some other process has randomly sent us a SIGSEGV
-         * via kill(), but that is not easy to distinguish at this point,
-         * so we assume it doesn't happen.
-         */
-        handler = TARGET_SIG_DFL;
-    }
-
-    if (!queue && handler == TARGET_SIG_DFL) {
-        if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
-            kill(getpid(),SIGSTOP);
-            return 0;
-        } else
-        /* default handler : ignore some signal. The other are fatal */
-        if (sig != TARGET_SIGCHLD &&
-            sig != TARGET_SIGURG &&
-            sig != TARGET_SIGWINCH &&
-            sig != TARGET_SIGCONT) {
-            force_sig(sig);
-        } else {
-            return 0; /* indicate ignored */
-        }
-    } else if (!queue && handler == TARGET_SIG_IGN) {
-        /* ignore signal */
-        return 0;
-    } else if (!queue && handler == TARGET_SIG_ERR) {
-        force_sig(sig);
-    } else {
         pq = &k->first;
         if (sig < TARGET_SIGRTMIN) {
             /* if non real time signal, we queue exactly one signal */
@@ -583,7 +547,6 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
         /* signal that a new signal is pending */
         ts->signal_pending = 1;
         return 1; /* indicates that the signal was queued */
-    }
 }
 
 #if defined(__x86_64__)
-- 
2.1.4

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

* [Qemu-devel] [PATCH 21/34] linux-user: Remove redundant gdb_queuesig()
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (19 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 20/34] linux-user: Remove redundant default action check in queue_signal() Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 22/34] linux-user: Remove real-time signal queuing Timothy E Baldwin
                   ` (13 subsequent siblings)
  34 siblings, 0 replies; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 gdbstub.c              | 13 -------------
 include/exec/gdbstub.h |  1 -
 2 files changed, 14 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index ffe7e6e..fd319af 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1472,19 +1472,6 @@ void gdb_exit(CPUArchState *env, int code)
 
 #ifdef CONFIG_USER_ONLY
 int
-gdb_queuesig (void)
-{
-    GDBState *s;
-
-    s = gdbserver_state;
-
-    if (gdbserver_fd < 0 || s->fd < 0)
-        return 0;
-    else
-        return 1;
-}
-
-int
 gdb_handlesig(CPUState *cpu, int sig)
 {
     GDBState *s;
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index 05f57c2..231ebdb 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -19,7 +19,6 @@ int use_gdb_syscalls(void);
 void gdb_set_stop_cpu(CPUState *cpu);
 void gdb_exit(CPUArchState *, int);
 #ifdef CONFIG_USER_ONLY
-int gdb_queuesig (void);
 int gdb_handlesig(CPUState *, int);
 void gdb_signalled(CPUArchState *, int);
 void gdbserver_fork(CPUState *);
-- 
2.1.4

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

* [Qemu-devel] [PATCH 22/34] linux-user: Remove real-time signal queuing
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (20 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 21/34] linux-user: Remove redundant gdb_queuesig() Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 23/34] linux-user: Queue synchronous signals separately Timothy E Baldwin
                   ` (12 subsequent siblings)
  34 siblings, 0 replies; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

As host signals are now blocked whenever guest signals are blocked, the
queue of realtime signals in now in Linux. The Qemu queue is now
redundant and removed.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>

Conflicts:
	linux-user/qemu.h
---
 linux-user/main.c   |  7 ------
 linux-user/qemu.h   | 11 +--------
 linux-user/signal.c | 70 ++++++++++-------------------------------------------
 3 files changed, 14 insertions(+), 74 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 349abe2..d86751a 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3474,14 +3474,7 @@ void stop_all_tasks(void)
 /* Assumes contents are already zeroed.  */
 void init_task_state(TaskState *ts)
 {
-    int i;
- 
     ts->used = 1;
-    ts->first_free = ts->sigqueue_table;
-    for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) {
-        ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1];
-    }
-    ts->sigqueue_table[i].next = NULL;
 }
 
 CPUArchState *cpu_copy(CPUArchState *env)
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index f2235eb3..5f43692 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -82,16 +82,9 @@ struct vm86_saved_state {
 
 #define MAX_SIGQUEUE_SIZE 1024
 
-struct sigqueue {
-    struct sigqueue *next;
-    target_siginfo_t info;
-};
-
 struct emulated_sigtable {
     int pending; /* true if signal is pending */
-    struct sigqueue *first;
-    struct sigqueue info; /* in order to always have memory for the
-                             first signal, we put it here */
+    target_siginfo_t info;
 };
 
 /* NOTE: we force a big alignment so that the stack stored after is
@@ -131,8 +124,6 @@ typedef struct TaskState {
     struct linux_binprm *bprm;
 
     struct emulated_sigtable sigtab[TARGET_NSIG];
-    struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
-    struct sigqueue *first_free; /* first free siginfo queue entry */
     sigset_t signal_mask;
 
     /* non zero if host signals blocked, bit 1 set if signal pending */
diff --git a/linux-user/signal.c b/linux-user/signal.c
index f57dbf5..aa08c72 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -432,27 +432,6 @@ void signal_init(void)
     }
 }
 
-/* signal queue handling */
-
-static inline struct sigqueue *alloc_sigqueue(CPUArchState *env)
-{
-    CPUState *cpu = ENV_GET_CPU(env);
-    TaskState *ts = cpu->opaque;
-    struct sigqueue *q = ts->first_free;
-    if (!q)
-        return NULL;
-    ts->first_free = q->next;
-    return q;
-}
-
-static inline void free_sigqueue(CPUArchState *env, struct sigqueue *q)
-{
-    CPUState *cpu = ENV_GET_CPU(env);
-    TaskState *ts = cpu->opaque;
-
-    q->next = ts->first_free;
-    ts->first_free = q;
-}
 
 /* abort execution with signal */
 static void QEMU_NORETURN force_sig(int target_sig)
@@ -513,7 +492,6 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
     CPUState *cpu = ENV_GET_CPU(env);
     TaskState *ts = cpu->opaque;
     struct emulated_sigtable *k;
-    struct sigqueue *q, **pq;
 
 #if defined(DEBUG_SIGNAL)
     fprintf(stderr, "queue_signal: sig=%d\n",
@@ -521,32 +499,16 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
 #endif
     k = &ts->sigtab[sig - 1];
 
-        pq = &k->first;
-        if (sig < TARGET_SIGRTMIN) {
-            /* if non real time signal, we queue exactly one signal */
-            if (!k->pending)
-                q = &k->info;
-            else
-                return 0;
-        } else {
-            if (!k->pending) {
-                /* first signal */
-                q = &k->info;
-            } else {
-                q = alloc_sigqueue(env);
-                if (!q)
-                    return -EAGAIN;
-                while (*pq != NULL)
-                    pq = &(*pq)->next;
-            }
-        }
-        *pq = q;
-        q->info = *info;
-        q->next = NULL;
-        k->pending = 1;
-        /* signal that a new signal is pending */
-        ts->signal_pending = 1;
-        return 1; /* indicates that the signal was queued */
+    /* we queue exactly one signal */
+    if (k->pending) {
+        return 0;
+    }
+
+    k->info = *info;
+    k->pending = 1;
+    /* signal that a new signal is pending */
+    ts->signal_pending = 1;
+    return 1; /* indicates that the signal was queued */
 }
 
 #if defined(__x86_64__)
@@ -5617,7 +5579,6 @@ void process_pending_signals(CPUArchState *cpu_env)
     target_sigset_t target_old_set;
     struct emulated_sigtable *k;
     struct target_sigaction *sa;
-    struct sigqueue *q;
     TaskState *ts = cpu->opaque;
 
 restart:
@@ -5653,10 +5614,7 @@ restart:
     fprintf(stderr, "qemu: process signal %d\n", sig);
 #endif
     /* dequeue signal */
-    q = k->first;
-    k->first = q->next;
-    if (!k->first)
-        k->pending = 0;
+    k->pending = 0;
 
     sig = gdb_handlesig(cpu, sig);
     if (!sig) {
@@ -5715,18 +5673,16 @@ restart:
         /* prepare the stack frame of the virtual CPU */
 #if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
         /* These targets do not have traditional signals.  */
-        setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
+        setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
 #else
         if (sa->sa_flags & TARGET_SA_SIGINFO)
-            setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env);
+            setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
         else
             setup_frame(sig, sa, &target_old_set, cpu_env);
 #endif
         if (sa->sa_flags & TARGET_SA_RESETHAND)
             sa->_sa_handler = TARGET_SIG_DFL;
     }
-    if (q != &k->info)
-        free_sigqueue(cpu_env, q);
 
     goto next_signal;
 }
-- 
2.1.4

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

* [Qemu-devel] [PATCH 23/34] linux-user: Queue synchronous signals separately
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (21 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 22/34] linux-user: Remove real-time signal queuing Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 24/34] linux-user: Restart execve() if signal pending Timothy E Baldwin
                   ` (11 subsequent siblings)
  34 siblings, 0 replies; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

If a synchronous signal and an asynchronous signal arrive near simultaneously,
and the signal number of the asynchronous signal is lower than that of the
synchronous signal the the handler for the asynchronous would be called first,
and then the handler for the synchronous signal would be called within or
after the first handler with an incorrect context.

This is fixed by queuing synchronous signals separately, however this still
risks delaying a asynchronous signal until the synchronous signal handler
returns rather than handling the signal on another thread.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>

Conflicts:
	linux-user/signal.c
---
 linux-user/qemu.h   |  1 +
 linux-user/signal.c | 63 +++++++++++++++++++++++++++++------------------------
 2 files changed, 35 insertions(+), 29 deletions(-)

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 5f43692..331c48f 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -123,6 +123,7 @@ typedef struct TaskState {
     struct image_info *info;
     struct linux_binprm *bprm;
 
+    struct emulated_sigtable sync_signal;
     struct emulated_sigtable sigtab[TARGET_NSIG];
     sigset_t signal_mask;
 
diff --git a/linux-user/signal.c b/linux-user/signal.c
index aa08c72..15bd082 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -491,22 +491,14 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
 {
     CPUState *cpu = ENV_GET_CPU(env);
     TaskState *ts = cpu->opaque;
-    struct emulated_sigtable *k;
 
 #if defined(DEBUG_SIGNAL)
     fprintf(stderr, "queue_signal: sig=%d\n",
             sig);
 #endif
-    k = &ts->sigtab[sig - 1];
-
-    /* we queue exactly one signal */
-    if (k->pending) {
-        return 0;
-    }
 
-    k->info = *info;
-    k->pending = 1;
-    /* signal that a new signal is pending */
+    ts->sync_signal.info = *info;
+    ts->sync_signal.pending = sig;
     ts->signal_pending = 1;
     return 1; /* indicates that the signal was queued */
 }
@@ -519,8 +511,12 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
                                 void *puc)
 {
     CPUArchState *env = thread_cpu->env_ptr;
+    CPUState *cpu = ENV_GET_CPU(env);
+    TaskState *ts = cpu->opaque;
+
     int sig;
     target_siginfo_t tinfo;
+    struct emulated_sigtable *k;
 
     /* the CPU emulator uses some host signals to detect exceptions,
        we forward to it some signals */
@@ -546,15 +542,18 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
 #endif
 
     host_to_target_siginfo_noswap(&tinfo, info);
-    if (queue_signal(env, sig, &tinfo) == 1) {
-        /* Block host signals until target signal handler entered */
-        sigfillset(&uc->uc_sigmask);
-        sigdelset(&uc->uc_sigmask, SIGSEGV);
-        sigdelset(&uc->uc_sigmask, SIGBUS);
+    k = &ts->sigtab[sig - 1];
+    k->info = tinfo;
+    k->pending = sig;
+    ts->signal_pending = 1;
 
-        /* interrupt the virtual CPU as soon as possible */
-        cpu_exit(thread_cpu);
-    }
+    /* Block host signals until target signal handler entered */
+    sigfillset(&uc->uc_sigmask);
+    sigdelset(&uc->uc_sigmask, SIGSEGV);
+    sigdelset(&uc->uc_sigmask, SIGBUS);
+
+    /* interrupt the virtual CPU as soon as possible */
+    cpu_exit(thread_cpu);
 }
 
 /* do_sigaltstack() returns target values and errnos. */
@@ -5590,12 +5589,26 @@ restart:
     sigfillset(&set);
     sigprocmask(SIG_SETMASK, &set, 0);
 
+    if (ts->sync_signal.pending) {
+        k = &ts->sync_signal;
+        sig = k->pending;
+
+        /* Synchronous signals are forced,
+         * see force_sig_info() and callers in Linux */
+        if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
+                || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
+            sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
+            sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
+        }
+
+       goto handle_signal;
+    }
+
  next_signal:
     k = ts->sigtab;
     for(sig = 1; sig <= TARGET_NSIG; sig++) {
-        if (k->pending && (
-                    !sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
-                    || sig == TARGET_SIGSEGV)) {
+        if (k->pending &&
+             !sigismember(&ts->signal_mask, target_to_host_signal_table[sig])) {
             goto handle_signal;
         }
         k++;
@@ -5625,14 +5638,6 @@ restart:
         handler = sa->_sa_handler;
     }
 
-    if (sig == TARGET_SIGSEGV && sigismember(&ts->signal_mask, SIGSEGV)) {
-        /* Guest has blocked SIGSEGV but we got one anyway. Assume this
-         * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
-         * because it got a real MMU fault), and treat as if default handler.
-         */
-        handler = TARGET_SIG_DFL;
-    }
-
     if (handler == TARGET_SIG_DFL) {
         /* default handler : ignore some signal. The other are job control or fatal */
         if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) {
-- 
2.1.4

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

* [Qemu-devel] [PATCH 24/34] linux-user: Restart execve() if signal pending
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (22 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 23/34] linux-user: Queue synchronous signals separately Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-11 14:36   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 25/34] linux-user: Restart exit() " Timothy E Baldwin
                   ` (10 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Without this SIGTERM could fail to terminate the process, as the
signal lost in QEMU's queue.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/syscall.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1ce381e..4839154 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -702,6 +702,7 @@ safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
     struct rusage *, rusage)
 safe_syscall4(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
     int, options)
+safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
 
 
 static inline int host_to_target_sock_type(int host_type)
@@ -5929,7 +5930,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             }
             if (!(p = lock_user_string(arg1)))
                 goto execve_efault;
-            ret = get_errno(execve(p, argp, envp));
+            ret = safe_execve(p, argp, envp);
             unlock_user(p, arg1, 0);
 
             goto execve_end;
-- 
2.1.4

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

* [Qemu-devel] [PATCH 25/34] linux-user: Restart exit() if signal pending
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (23 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 24/34] linux-user: Restart execve() if signal pending Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-11 14:36   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 26/34] linux-user: Restart kill() " Timothy E Baldwin
                   ` (9 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Without this a signal could vanish on thread exit.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/syscall.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4839154..efe61e3 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5719,8 +5719,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
            However in threaded applictions it is used for thread termination,
            and _exit_group is used for application termination.
            Do thread termination if we have more then one thread.  */
-        /* FIXME: This probably breaks if a signal arrives.  We should probably
-           be disabling signals.  */
+
+        if (block_signals()) {
+            ret = -TARGET_ERESTARTSYS;
+            break;
+        }
+
         if (CPU_NEXT(first_cpu)) {
             TaskState *ts;
 
-- 
2.1.4

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

* [Qemu-devel] [PATCH 26/34] linux-user: Restart kill() if signal pending
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (24 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 25/34] linux-user: Restart exit() " Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 27/34] linux-user: pause() should not pause " Timothy E Baldwin
                   ` (8 subsequent siblings)
  34 siblings, 0 replies; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Without this a signal could vanish if thread sends SIGKILL to itself.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/syscall.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index efe61e3..da6d140 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6205,7 +6205,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         ret = 0;
         break;
     case TARGET_NR_kill:
-        ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
+        if (block_signals()) {
+            ret = -TARGET_ERESTARTSYS;
+        } else {
+            ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
+        }
         break;
     case TARGET_NR_rename:
         {
-- 
2.1.4

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

* [Qemu-devel] [PATCH 27/34] linux-user: pause() should not pause if signal pending
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (25 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 26/34] linux-user: Restart kill() " Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-11 14:36   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 28/34] linux-user: Restart sigaction() " Timothy E Baldwin
                   ` (7 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/syscall.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index da6d140..f89b730 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6106,7 +6106,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 #ifdef TARGET_NR_pause /* not on alpha */
     case TARGET_NR_pause:
-        ret = get_errno(pause());
+        if (!block_signals()) {
+            sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
+        }
+        ret = -TARGET_EINTR;
         break;
 #endif
 #ifdef TARGET_NR_utime
-- 
2.1.4

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

* [Qemu-devel] [PATCH 28/34] linux-user: Restart sigaction() if signal pending
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (26 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 27/34] linux-user: pause() should not pause " Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-11 14:37   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 29/34] linux-user: Support for restarting system calls for UniCore32 targets Timothy E Baldwin
                   ` (6 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/signal.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 15bd082..fc37f3b 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -629,7 +629,7 @@ out:
     return ret;
 }
 
-/* do_sigaction() return host values and errnos */
+/* do_sigaction() return target values and host errnos */
 int do_sigaction(int sig, const struct target_sigaction *act,
                  struct target_sigaction *oact)
 {
@@ -638,8 +638,14 @@ int do_sigaction(int sig, const struct target_sigaction *act,
     int host_sig;
     int ret = 0;
 
-    if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
-        return -EINVAL;
+    if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
+        return -TARGET_EINVAL;
+    }
+
+    if (block_signals()) {
+        return -TARGET_ERESTARTSYS;
+    }
+
     k = &sigact_table[sig - 1];
 #if defined(DEBUG_SIGNAL)
     fprintf(stderr, "sigaction sig=%d act=0x%p, oact=0x%p\n",
-- 
2.1.4

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

* [Qemu-devel] [PATCH 29/34] linux-user: Support for restarting system calls for UniCore32 targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (27 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 28/34] linux-user: Restart sigaction() " Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 19:05   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 30/34] linux-user: Support for restarting system calls for OpenRISC targets Timothy E Baldwin
                   ` (5 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---

WARNING - NOT TESTED

 linux-user/main.c              | 7 ++++++-
 linux-user/unicore32/syscall.h | 2 ++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index d86751a..9ca1c99 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1120,7 +1120,7 @@ void cpu_loop(CPUUniCore32State *env)
                             cpu_set_tls(env, env->regs[0]);
                             env->regs[0] = 0;
                     } else {
-                        env->regs[0] = do_syscall(env,
+                        abi_long ret = do_syscall(env,
                                                   n,
                                                   env->regs[0],
                                                   env->regs[1],
@@ -1129,6 +1129,11 @@ void cpu_loop(CPUUniCore32State *env)
                                                   env->regs[4],
                                                   env->regs[5],
                                                   0, 0);
+                        if (ret == -TARGET_ERESTARTSYS) {
+                            env->regs[31] -= 4;
+                        } else if (ret != -TARGET_QEMU_ESIGRETURN) {
+                            env->regs[0] = ret;
+                        }
                     }
                 } else {
                     goto error;
diff --git a/linux-user/unicore32/syscall.h b/linux-user/unicore32/syscall.h
index 385a975..4887d06 100644
--- a/linux-user/unicore32/syscall.h
+++ b/linux-user/unicore32/syscall.h
@@ -58,3 +58,5 @@ struct target_pt_regs {
 #define TARGET_MLOCKALL_MCL_FUTURE  2
 
 #endif /* __UC32_SYSCALL_H__ */
+
+#define TARGET_USE_ERESTARTSYS 1
-- 
2.1.4

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

* [Qemu-devel] [PATCH 30/34] linux-user: Support for restarting system calls for OpenRISC targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (28 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 29/34] linux-user: Support for restarting system calls for UniCore32 targets Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 19:06   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 31/34] linux-user: Support for restarting system calls for M68K targets Timothy E Baldwin
                   ` (4 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---

WARNING - NOT TESTED

 linux-user/main.c             | 22 ++++++++++++++--------
 linux-user/openrisc/syscall.h |  2 ++
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 9ca1c99..b052e17 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2687,6 +2687,7 @@ void cpu_loop(CPUOpenRISCState *env)
 {
     CPUState *cs = CPU(openrisc_env_get_cpu(env));
     int trapnr, gdbsig;
+    abi_long ret;
 
     for (;;) {
         cpu_exec_start(cs);
@@ -2732,14 +2733,19 @@ void cpu_loop(CPUOpenRISCState *env)
             break;
         case EXCP_SYSCALL:
             env->pc += 4;   /* 0xc00; */
-            env->gpr[11] = do_syscall(env,
-                                      env->gpr[11], /* return value       */
-                                      env->gpr[3],  /* r3 - r7 are params */
-                                      env->gpr[4],
-                                      env->gpr[5],
-                                      env->gpr[6],
-                                      env->gpr[7],
-                                      env->gpr[8], 0, 0);
+            ret = do_syscall(env,
+                             env->gpr[11], /* return value       */
+                             env->gpr[3],  /* r3 - r7 are params */
+                             env->gpr[4],
+                             env->gpr[5],
+                             env->gpr[6],
+                             env->gpr[7],
+                             env->gpr[8], 0, 0);
+            if (ret == -TARGET_ERESTARTSYS) {
+                env->pc -= 4;
+            } else if (ret != -TARGET_QEMU_ESIGRETURN) {
+                env->gpr[11] = ret;
+            }
             break;
         case EXCP_FPE:
             qemu_log("\nFloating point error\n");
diff --git a/linux-user/openrisc/syscall.h b/linux-user/openrisc/syscall.h
index 8ac0365..74787ed 100644
--- a/linux-user/openrisc/syscall.h
+++ b/linux-user/openrisc/syscall.h
@@ -27,3 +27,5 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
+
+#define TARGET_USE_ERESTARTSYS 1
-- 
2.1.4

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

* [Qemu-devel] [PATCH 31/34] linux-user: Support for restarting system calls for M68K targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (29 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 30/34] linux-user: Support for restarting system calls for OpenRISC targets Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 19:06   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 32/34] linux-user: Support for restarting system calls for S390 targets Timothy E Baldwin
                   ` (3 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/m68k/syscall.h |  2 ++
 linux-user/main.c         | 24 +++++++++++++++---------
 linux-user/signal.c       | 20 ++++++++------------
 3 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/linux-user/m68k/syscall.h b/linux-user/m68k/syscall.h
index 9218493..c923e56 100644
--- a/linux-user/m68k/syscall.h
+++ b/linux-user/m68k/syscall.h
@@ -23,3 +23,5 @@ struct target_pt_regs {
 #define TARGET_MLOCKALL_MCL_FUTURE  2
 
 void do_m68k_simcall(CPUM68KState *, int);
+
+#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/main.c b/linux-user/main.c
index b052e17..0863945 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3054,18 +3054,24 @@ void cpu_loop(CPUM68KState *env)
             break;
         case EXCP_TRAP0:
             {
+                abi_long ret;
                 ts->sim_syscalls = 0;
                 n = env->dregs[0];
                 env->pc += 2;
-                env->dregs[0] = do_syscall(env,
-                                          n,
-                                          env->dregs[1],
-                                          env->dregs[2],
-                                          env->dregs[3],
-                                          env->dregs[4],
-                                          env->dregs[5],
-                                          env->aregs[0],
-                                          0, 0);
+                ret = do_syscall(env,
+                                 n,
+                                 env->dregs[1],
+                                 env->dregs[2],
+                                 env->dregs[3],
+                                 env->dregs[4],
+                                 env->dregs[5],
+                                 env->aregs[0],
+                                 0, 0);
+                if (ret == -TARGET_ERESTARTSYS) {
+                    env->pc -= 2;
+                } else if (ret != -TARGET_QEMU_ESIGRETURN) {
+                    env->dregs[0] = ret;
+                }
             }
             break;
         case EXCP_INTERRUPT:
diff --git a/linux-user/signal.c b/linux-user/signal.c
index fc37f3b..3bae33b 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -5000,19 +5000,18 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env,
 }
 
 static void
-restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc, int *pd0)
+restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc)
 {
     int temp;
 
     __get_user(env->aregs[7], &sc->sc_usp);
+    __get_user(env->dregs[0], &sc->sc_d0);
     __get_user(env->dregs[1], &sc->sc_d1);
     __get_user(env->aregs[0], &sc->sc_a0);
     __get_user(env->aregs[1], &sc->sc_a1);
     __get_user(env->pc, &sc->sc_pc);
     __get_user(temp, &sc->sc_sr);
     env->sr = (env->sr & 0xff00) | (temp & 0xff);
-
-    *pd0 = tswapl(sc->sc_d0);
 }
 
 /*
@@ -5110,8 +5109,7 @@ static inline int target_rt_setup_ucontext(struct target_ucontext *uc,
 }
 
 static inline int target_rt_restore_ucontext(CPUM68KState *env,
-                                             struct target_ucontext *uc,
-                                             int *pd0)
+                                             struct target_ucontext *uc)
 {
     int temp;
     target_greg_t *gregs = uc->tuc_mcontext.gregs;
@@ -5141,7 +5139,6 @@ static inline int target_rt_restore_ucontext(CPUM68KState *env,
     __get_user(temp, &gregs[17]);
     env->sr = (env->sr & 0xff00) | (temp & 0xff);
 
-    *pd0 = env->dregs[0];
     return 0;
 
 badframe:
@@ -5227,7 +5224,7 @@ long do_sigreturn(CPUM68KState *env)
     abi_ulong frame_addr = env->aregs[7] - 4;
     target_sigset_t target_set;
     sigset_t set;
-    int d0, i;
+    int i;
 
     if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
         goto badframe;
@@ -5245,10 +5242,10 @@ long do_sigreturn(CPUM68KState *env)
 
     /* restore registers */
 
-    restore_sigcontext(env, &frame->sc, &d0);
+    restore_sigcontext(env, &frame->sc);
 
     unlock_user_struct(frame, frame_addr, 0);
-    return d0;
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     force_sig(TARGET_SIGSEGV);
@@ -5261,7 +5258,6 @@ long do_rt_sigreturn(CPUM68KState *env)
     abi_ulong frame_addr = env->aregs[7] - 4;
     target_sigset_t target_set;
     sigset_t set;
-    int d0;
 
     if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
         goto badframe;
@@ -5271,7 +5267,7 @@ long do_rt_sigreturn(CPUM68KState *env)
 
     /* restore registers */
 
-    if (target_rt_restore_ucontext(env, &frame->uc, &d0))
+    if (target_rt_restore_ucontext(env, &frame->uc))
         goto badframe;
 
     if (do_sigaltstack(frame_addr +
@@ -5280,7 +5276,7 @@ long do_rt_sigreturn(CPUM68KState *env)
         goto badframe;
 
     unlock_user_struct(frame, frame_addr, 0);
-    return d0;
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     unlock_user_struct(frame, frame_addr, 0);
-- 
2.1.4

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

* [Qemu-devel] [PATCH 32/34] linux-user: Support for restarting system calls for S390 targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (30 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 31/34] linux-user: Support for restarting system calls for M68K targets Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 19:07   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 33/34] linux-user: Support for restarting system calls for CRIS targets Timothy E Baldwin
                   ` (2 subsequent siblings)
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---

WARNING - NOT TESTED

 linux-user/main.c          | 12 +++++++++---
 linux-user/s390x/syscall.h |  2 ++
 linux-user/signal.c        |  4 ++--
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 0863945..a59907e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3355,6 +3355,7 @@ void cpu_loop(CPUS390XState *env)
     int trapnr, n, sig;
     target_siginfo_t info;
     target_ulong addr;
+    abi_long ret;
 
     while (1) {
         cpu_exec_start(cs);
@@ -3372,9 +3373,14 @@ void cpu_loop(CPUS390XState *env)
                 n = env->regs[1];
             }
             env->psw.addr += env->int_svc_ilen;
-            env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3],
-                                      env->regs[4], env->regs[5],
-                                      env->regs[6], env->regs[7], 0, 0);
+            ret = do_syscall(env, n, env->regs[2], env->regs[3],
+                             env->regs[4], env->regs[5],
+                             env->regs[6], env->regs[7], 0, 0);
+            if (ret == -TARGET_ERESTARTSYS) {
+                env->psw.addr -= env->int_svc_ilen;;
+            } else if (ret != -TARGET_QEMU_ESIGRETURN) {
+                env->regs[2] = ret;
+            }
             break;
 
         case EXCP_DEBUG:
diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h
index 35f170a..914ec98 100644
--- a/linux-user/s390x/syscall.h
+++ b/linux-user/s390x/syscall.h
@@ -27,3 +27,5 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ        2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
+
+#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 3bae33b..e17514e 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4267,7 +4267,7 @@ long do_sigreturn(CPUS390XState *env)
     }
 
     unlock_user_struct(frame, frame_addr, 0);
-    return env->regs[2];
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     force_sig(TARGET_SIGSEGV);
@@ -4298,7 +4298,7 @@ long do_rt_sigreturn(CPUS390XState *env)
         goto badframe;
     }
     unlock_user_struct(frame, frame_addr, 0);
-    return env->regs[2];
+    return -TARGET_QEMU_ESIGRETURN;
 
 badframe:
     unlock_user_struct(frame, frame_addr, 0);
-- 
2.1.4

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

* [Qemu-devel] [PATCH 33/34] linux-user: Support for restarting system calls for CRIS targets
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (31 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 32/34] linux-user: Support for restarting system calls for S390 targets Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 19:12   ` Peter Maydell
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 34/34] linux-user: Remove TARGET_USE_ERESTARTSYS Timothy E Baldwin
  2015-09-10 18:00 ` [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Peter Maydell
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---

WARNING - NOT TESTED

 linux-user/cris/syscall.h | 2 ++
 linux-user/main.c         | 6 +++++-
 linux-user/signal.c       | 2 +-
 3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/linux-user/cris/syscall.h b/linux-user/cris/syscall.h
index 2957b0d..29218e2 100644
--- a/linux-user/cris/syscall.h
+++ b/linux-user/cris/syscall.h
@@ -44,3 +44,5 @@ struct target_pt_regs {
 #define TARGET_MLOCKALL_MCL_FUTURE  2
 
 #endif
+
+#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/main.c b/linux-user/main.c
index a59907e..a9eb15c 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2878,7 +2878,11 @@ void cpu_loop(CPUCRISState *env)
                              env->pregs[7], 
                              env->pregs[11],
                              0, 0);
-            env->regs[10] = ret;
+            if (ret == -TARGET_ERESTARTSYS) {
+                env->pc -= 2;
+            } else if (ret != -TARGET_QEMU_ESIGRETURN) {
+                env->regs[10] = ret;
+            }
             break;
         case EXCP_DEBUG:
             {
diff --git a/linux-user/signal.c b/linux-user/signal.c
index e17514e..3741517 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -3761,7 +3761,7 @@ long do_sigreturn(CPUCRISState *env)
 
     restore_sigcontext(&frame->sc, env);
     unlock_user_struct(frame, frame_addr, 0);
-    return env->regs[10];
+    return -TARGET_QEMU_ESIGRETURN;
 badframe:
     force_sig(TARGET_SIGSEGV);
 }
-- 
2.1.4

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

* [Qemu-devel] [PATCH 34/34] linux-user: Remove TARGET_USE_ERESTARTSYS
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (32 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 33/34] linux-user: Support for restarting system calls for CRIS targets Timothy E Baldwin
@ 2015-09-05 23:57 ` Timothy E Baldwin
  2015-09-10 19:13   ` Peter Maydell
  2015-09-10 18:00 ` [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Peter Maydell
  34 siblings, 1 reply; 76+ messages in thread
From: Timothy E Baldwin @ 2015-09-05 23:57 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio, Timothy E Baldwin

Now with system call restarting support by all targets remove
uneeded conditionals.

Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
---
 linux-user/aarch64/syscall.h    | 2 --
 linux-user/alpha/syscall.h      | 2 --
 linux-user/arm/syscall.h        | 2 --
 linux-user/cris/syscall.h       | 2 --
 linux-user/i386/syscall.h       | 2 --
 linux-user/m68k/syscall.h       | 2 --
 linux-user/microblaze/syscall.h | 2 --
 linux-user/mips/syscall.h       | 2 --
 linux-user/mips64/syscall.h     | 2 --
 linux-user/openrisc/syscall.h   | 2 --
 linux-user/ppc/syscall.h        | 2 --
 linux-user/s390x/syscall.h      | 2 --
 linux-user/sh4/syscall.h        | 2 --
 linux-user/signal.c             | 3 ---
 linux-user/sparc/syscall.h      | 2 --
 linux-user/sparc64/syscall.h    | 2 --
 linux-user/syscall.c            | 4 ++--
 linux-user/unicore32/syscall.h  | 2 --
 linux-user/x86_64/syscall.h     | 2 --
 19 files changed, 2 insertions(+), 39 deletions(-)

diff --git a/linux-user/aarch64/syscall.h b/linux-user/aarch64/syscall.h
index bc1f01b..dc72a15 100644
--- a/linux-user/aarch64/syscall.h
+++ b/linux-user/aarch64/syscall.h
@@ -11,5 +11,3 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ       2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/alpha/syscall.h b/linux-user/alpha/syscall.h
index 554a4bf..245cff2 100644
--- a/linux-user/alpha/syscall.h
+++ b/linux-user/alpha/syscall.h
@@ -255,5 +255,3 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ              4096
 #define TARGET_MLOCKALL_MCL_CURRENT     0x2000
 #define TARGET_MLOCKALL_MCL_FUTURE      0x4000
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/arm/syscall.h b/linux-user/arm/syscall.h
index 38c925a..3844a96 100644
--- a/linux-user/arm/syscall.h
+++ b/linux-user/arm/syscall.h
@@ -48,5 +48,3 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/cris/syscall.h b/linux-user/cris/syscall.h
index 29218e2..2957b0d 100644
--- a/linux-user/cris/syscall.h
+++ b/linux-user/cris/syscall.h
@@ -44,5 +44,3 @@ struct target_pt_regs {
 #define TARGET_MLOCKALL_MCL_FUTURE  2
 
 #endif
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/i386/syscall.h b/linux-user/i386/syscall.h
index f7d9fbe..906aaac 100644
--- a/linux-user/i386/syscall.h
+++ b/linux-user/i386/syscall.h
@@ -150,5 +150,3 @@ struct target_vm86plus_struct {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/m68k/syscall.h b/linux-user/m68k/syscall.h
index c923e56..9218493 100644
--- a/linux-user/m68k/syscall.h
+++ b/linux-user/m68k/syscall.h
@@ -23,5 +23,3 @@ struct target_pt_regs {
 #define TARGET_MLOCKALL_MCL_FUTURE  2
 
 void do_m68k_simcall(CPUM68KState *, int);
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/microblaze/syscall.h b/linux-user/microblaze/syscall.h
index c38e700..3c1ed27 100644
--- a/linux-user/microblaze/syscall.h
+++ b/linux-user/microblaze/syscall.h
@@ -54,5 +54,3 @@ struct target_pt_regs {
 #define TARGET_MLOCKALL_MCL_FUTURE  2
 
 #endif
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/mips/syscall.h b/linux-user/mips/syscall.h
index cede30c..e34f80c 100644
--- a/linux-user/mips/syscall.h
+++ b/linux-user/mips/syscall.h
@@ -227,5 +227,3 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h
index 88716c1..33afb8d 100644
--- a/linux-user/mips64/syscall.h
+++ b/linux-user/mips64/syscall.h
@@ -224,5 +224,3 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ      2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/openrisc/syscall.h b/linux-user/openrisc/syscall.h
index 74787ed..8ac0365 100644
--- a/linux-user/openrisc/syscall.h
+++ b/linux-user/openrisc/syscall.h
@@ -27,5 +27,3 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/ppc/syscall.h b/linux-user/ppc/syscall.h
index e75da7f..532cbbd 100644
--- a/linux-user/ppc/syscall.h
+++ b/linux-user/ppc/syscall.h
@@ -71,5 +71,3 @@ struct target_revectored_struct {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 0x2000
 #define TARGET_MLOCKALL_MCL_FUTURE  0x4000
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h
index 914ec98..35f170a 100644
--- a/linux-user/s390x/syscall.h
+++ b/linux-user/s390x/syscall.h
@@ -27,5 +27,3 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ        2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/sh4/syscall.h b/linux-user/sh4/syscall.h
index 1c0bdfd..7aa4f23 100644
--- a/linux-user/sh4/syscall.h
+++ b/linux-user/sh4/syscall.h
@@ -15,5 +15,3 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 3741517..c247626 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -212,10 +212,7 @@ int block_signals(void)
     pending |= 2;
     ts->signal_pending = pending;
 
-#ifdef TARGET_USE_ERESTARTSYS
     return pending & 1;
-#endif
-    return 0;
 }
 
 /* Wrapper for sigprocmask function
diff --git a/linux-user/sparc/syscall.h b/linux-user/sparc/syscall.h
index 3844b59..58573b9 100644
--- a/linux-user/sparc/syscall.h
+++ b/linux-user/sparc/syscall.h
@@ -18,5 +18,3 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ      4096
 #define TARGET_MLOCKALL_MCL_CURRENT 0x2000
 #define TARGET_MLOCKALL_MCL_FUTURE  0x4000
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/sparc64/syscall.h b/linux-user/sparc64/syscall.h
index 0adc5ad..8398d3f 100644
--- a/linux-user/sparc64/syscall.h
+++ b/linux-user/sparc64/syscall.h
@@ -19,5 +19,3 @@ struct target_pt_regs {
 #define TARGET_MINSIGSTKSZ      4096
 #define TARGET_MLOCKALL_MCL_CURRENT 0x2000
 #define TARGET_MLOCKALL_MCL_FUTURE  0x4000
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f89b730..8d30854 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -594,7 +594,7 @@ abi_long convert_syscall_return_value(abi_long ret) {
     return ret;
 }
 
-#if defined(CONFIG_SAFE_SYSCALL) && defined(TARGET_USE_ERESTARTSYS)
+#ifdef CONFIG_SAFE_SYSCALL
 
 #define safe_syscall0(type, name) \
 static type safe_##name (void) \
@@ -5697,7 +5697,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     struct statfs stfs;
     void *p;
 
-#if defined(DEBUG_ERESTARTSYS) && defined(TARGET_USE_ERESTARTSYS)
+#ifdef DEBUG_ERESTARTSYS
     {
         static int flag;
         flag = !flag;
diff --git a/linux-user/unicore32/syscall.h b/linux-user/unicore32/syscall.h
index 4887d06..385a975 100644
--- a/linux-user/unicore32/syscall.h
+++ b/linux-user/unicore32/syscall.h
@@ -58,5 +58,3 @@ struct target_pt_regs {
 #define TARGET_MLOCKALL_MCL_FUTURE  2
 
 #endif /* __UC32_SYSCALL_H__ */
-
-#define TARGET_USE_ERESTARTSYS 1
diff --git a/linux-user/x86_64/syscall.h b/linux-user/x86_64/syscall.h
index d41a93a..88b3c3f 100644
--- a/linux-user/x86_64/syscall.h
+++ b/linux-user/x86_64/syscall.h
@@ -100,5 +100,3 @@ struct target_msqid64_ds {
 #define TARGET_MINSIGSTKSZ 2048
 #define TARGET_MLOCKALL_MCL_CURRENT 1
 #define TARGET_MLOCKALL_MCL_FUTURE  2
-
-#define TARGET_USE_ERESTARTSYS 1
-- 
2.1.4

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

* Re: [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART
  2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
                   ` (33 preceding siblings ...)
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 34/34] linux-user: Remove TARGET_USE_ERESTARTSYS Timothy E Baldwin
@ 2015-09-10 18:00 ` Peter Maydell
  2015-10-02 11:52   ` Riku Voipio
  34 siblings, 1 reply; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:00 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:56, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> There are many races with signals in linux user:
>
>  - Multiple host signals in quick succession, fixed by keeping host signals
>    blocked, and checking if target signals are blocked before calling
>    target signal handler.
>  - Signal shortly before blocking system call, fixed by either:
>    - Block hosts signals, check and use host system call with
>      sigset_t parameter.
>    - Or check if signals are pending immediately before host system call
>      and if a signal arrives between the check and system call rewind
>      host instruction pointer to before the check. Also fixes SA_RESTART.
>  - Signal before or during sensitive system call, fixed in a similar manner.
>  - Close host and synchronous signals, partly fixed by implementing a separate
>    queue for synchronous signals which are dispatched first. The asynchronous
>    signal may still be delayed or lost rather than dispatched to another thread
>    or handled after exec().
>
> Also fixed:
>  - Errno array bounds.
>  - Default fatal actions occurring in the middle of target instructions.

Thanks for sending this patchset. This is really cool and we've needed
it for a long time...

> I have major problems testing the system call restarting:
>  - x86, ARM MIPS, PowerPC and SPARC sucessful tested.
>  - Microblaze and SH4 works without signals, but signal test case
>    crashes with or without my changes.
>  - Alpha works without signals, but don't have a toolchain.
>    to compile the signal test case.
>  - I have been unable to test UniCore32, OpenRISC, M68K, S390
>    and CRIS due to a lack of binaries and toolchains.

If the relevant maintainers don't get round to testing the patches
I think we can go ahead and commit anyway -- some of our minor
architectures are somewhat unmaintained. It's probably worth cc'ing
the architecture maintainers on the next round of this series
(look for who's listed for target-whatever in MAINTAINERS).

I ran this patchset through the Linux Test Project test suite for
the ARM target. Unfortunately it has a handful of extra test failures.
For instance:
open08      2  TFAIL  :  call succeeded unexpectedly
(a test which should have failed EISDIR)

read02      2  TFAIL  :  call succeeded unexpectedly
should also have failed EISDIR and didn't

The waitid01 and waitid02 tests also failed, as did a few others.
Some of the fcntl tests seemed to hang.

(http://wiki.qemu.org/Testing/LTP has the info on how to run the
tests if you want to try it yourself.)

You should probably run your patches through scripts/checkpatch.pl,
which will flag up formatting problems. (Don't worry about trying
to do that for the "reindent signal.c" patch, fixing the style
issues in the same commit there would make the patch hard to review
with diff -w.)

It might be wise to rearrange the patchseries a little, so all
the patches which do the 'support restarting syscalls' work
plus the 'safe_syscall' implementation go at the start. I think
these are more obviously correct and easier to review than the
changes to the signal handling code in 'Fix race between multiple
signals' and later patches. So they might be able to go into the
tree ahead of the rest if the later patches need to go through
further rounds of review.

I'll send out my comments on the first half or so of the
patchset in a moment; the second half I need to think about
in more detail first.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 01/34] linux-user: Fix array bounds in errno conversion
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 01/34] linux-user: Fix array bounds in errno conversion Timothy E Baldwin
@ 2015-09-10 18:04   ` Peter Maydell
  2015-09-11 10:59   ` Peter Maydell
  1 sibling, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:04 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:56, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Check array bounds in host_to_target_errno() and target_to_host_errno().
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/syscall.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 264debc..4e40dc6 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -566,14 +566,14 @@ static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
>
>  static inline int host_to_target_errno(int err)
>  {
> -    if(host_to_target_errno_table[err])
> +    if(err < ERRNO_TABLE_SIZE && host_to_target_errno_table[err])
>          return host_to_target_errno_table[err];
>      return err;
>  }
>
>  static inline int target_to_host_errno(int err)
>  {
> -    if (target_to_host_errno_table[err])
> +    if (err < ERRNO_TABLE_SIZE && target_to_host_errno_table[err])
>          return target_to_host_errno_table[err];
>      return err;
>  }

Checkpatch will tell you about the missing braces here (we like
to fix up style issues when we have to touch lines of code anyway).
Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 03/34] linux-user: Support for restarting system calls
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 03/34] linux-user: Support for restarting system calls Timothy E Baldwin
@ 2015-09-10 18:08   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:08 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:56, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> This allows SA_RESTART to be supported along with various case
> where pending signals need to be handled before a system call.
>
> New macro TARGET_ERESTARTSYS which is the error code used by Linux
> to indicate that system call should be restarted.
>
> TARGET_QEMU_ESIGRETURN moved into errno_defs.h and renumbered to
> 513 which is safe from future use as a system call return value
> as it is used for system call restarting in Linux and exposed only
> via ptrace.
>
> do_sigreturn() and do_rt_sigreturn() will be amended to return
> -TARGET_QEMU_ESIGRETURN rather than the value of result register to
> avoid confusion with -TARGET_ERESTARTSYS and cpu_loop() will be
> altered to act upon the return value accordingly.
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/errno_defs.h     | 3 +++
>  linux-user/mips/syscall.h   | 4 ----
>  linux-user/mips64/syscall.h | 4 ----
>  linux-user/ppc/syscall.h    | 2 --
>  4 files changed, 3 insertions(+), 10 deletions(-)

I feel like the commit message (especially the subject line) is
a bit askew from the actual contents of the patch, but codewise
it's OK.

> +#define TARGET_ERESTARTSYS     512  /* Restart system call */
> +#define TARGET_QEMU_ESIGRETURN 513  /* Return from signal */

I think these comments are not very useful -- they don't tell
you anything you couldn't have figured out from the constant name.
It would be better to provide a comment of a sentence or two
explaining how these are used (and also remarking that they are
not real target errnos but only visible internal to QEMU).

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 04/34] linux-user: Support for restarting system calls for x86 targets
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 04/34] linux-user: Support for restarting system calls for x86 targets Timothy E Baldwin
@ 2015-09-10 18:08   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:08 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:56, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/i386/syscall.h   |  2 ++
>  linux-user/main.c           | 47 ++++++++++++++++++++++++++++-----------------
>  linux-user/signal.c         | 15 +++++++--------
>  linux-user/syscall.c        |  2 --
>  linux-user/x86_64/syscall.h |  2 ++
>  5 files changed, 40 insertions(+), 28 deletions(-)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 05/34] linux-user: Support for restarting system calls for ARM targets
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 05/34] linux-user: Support for restarting system calls for ARM targets Timothy E Baldwin
@ 2015-09-10 18:09   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:09 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:56, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/aarch64/syscall.h |  2 ++
>  linux-user/arm/syscall.h     |  2 ++
>  linux-user/main.c            | 47 +++++++++++++++++++++++++++-----------------
>  linux-user/signal.c          | 10 +++++-----
>  4 files changed, 38 insertions(+), 23 deletions(-)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 06/34] linux-user: Support for restarting system calls for MIPS targets
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 06/34] linux-user: Support for restarting system calls for MIPS targets Timothy E Baldwin
@ 2015-09-10 18:09   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:09 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/main.c           | 4 ++++
>  linux-user/mips/syscall.h   | 2 ++
>  linux-user/mips64/syscall.h | 2 ++
>  3 files changed, 8 insertions(+)
>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 07/34] linux-user: Support for restarting system calls for PPC targets
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 07/34] linux-user: Support for restarting system calls for PPC targets Timothy E Baldwin
@ 2015-09-10 18:10   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:10 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/main.c        | 4 ++++
>  linux-user/ppc/syscall.h | 2 ++
>  2 files changed, 6 insertions(+)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 08/34] linux-user: Support for restarting system calls for SPARC targets
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 08/34] linux-user: Support for restarting system calls for SPARC targets Timothy E Baldwin
@ 2015-09-10 18:10   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:10 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/main.c            | 3 +++
>  linux-user/signal.c          | 2 +-
>  linux-user/sparc/syscall.h   | 2 ++
>  linux-user/sparc64/syscall.h | 2 ++
>  4 files changed, 8 insertions(+), 1 deletion(-)
>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 09/34] linux-user: Test for restarting system calls
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 09/34] linux-user: Test for restarting system calls Timothy E Baldwin
@ 2015-09-10 18:12   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:12 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> If DEBUG_ERESTARTSYS is set restart all system calls once.
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/syscall.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 04c91fb..80b8fa8 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -5585,6 +5585,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>      struct statfs stfs;
>      void *p;
>
> +#if defined(DEBUG_ERESTARTSYS) && defined(TARGET_USE_ERESTARTSYS)
> +    {
> +        static int flag;
> +        flag = !flag;
> +        if (flag) {
> +            return -TARGET_ERESTARTSYS;
> +        }
> +    }
> +#endif

I guess this is worth retaining, but it could use a comment
about what it's for.
Also, this is an odd place in the patch series to put it; I
would have expected it either before all the patches adding
ERESTARTSYS support to each arch, or after all of them.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 10/34] linux-user: Support for restarting system calls for Microblaze targets
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 10/34] linux-user: Support for restarting system calls for Microblaze targets Timothy E Baldwin
@ 2015-09-10 18:14   ` Peter Maydell
  2016-03-03 20:15     ` Peter Maydell
  0 siblings, 1 reply; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:14 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>
> Works without signals, but my signal test case
> crashes with or without my changes.
>
>  linux-user/main.c               | 14 +++++++++-----
>  linux-user/microblaze/syscall.h |  2 ++
>  linux-user/signal.c             |  2 +-
>  3 files changed, 12 insertions(+), 6 deletions(-)
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index d47e33f..3eacc9c 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -2911,14 +2911,14 @@ void cpu_loop(CPUMBState *env)
>                  queue_signal(env, info.si_signo, &info);
>              }
>              break;
> -       case EXCP_INTERRUPT:
> -         /* just indicate that signals should be handled asap */
> -         break;
> +        case EXCP_INTERRUPT:
> +            /* just indicate that signals should be handled asap */
> +            break;
>          case EXCP_BREAK:
>              /* Return address is 4 bytes after the call.  */
>              env->regs[14] += 4;
>              env->sregs[SR_PC] = env->regs[14];
> -            ret = do_syscall(env,
> +            ret = do_syscall(env,
>                               env->regs[12],
>                               env->regs[5],
>                               env->regs[6],
> @@ -2927,7 +2927,11 @@ void cpu_loop(CPUMBState *env)
>                               env->regs[9],
>                               env->regs[10],
>                               0, 0);
> -            env->regs[3] = ret;
> +            if (ret == -TARGET_ERESTARTSYS) {
> +                env->sregs[SR_PC] -= 4;

This isn't going to cleanly undo the changes to regs[14]
and sregs[SR_PC] that we do on entry, so I think the restart
isn't going to work right.

> +            } else if (ret != -TARGET_QEMU_ESIGRETURN) {
> +                env->regs[3] = ret;
> +            }
>              break;
>          case EXCP_HW_EXCP:
>              env->regs[17] = env->sregs[SR_PC] + 4;

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 11/34] linux-user: Support for restarting system calls for SH4 targets
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 11/34] linux-user: Support for restarting system calls for SH4 targets Timothy E Baldwin
@ 2015-09-10 18:15   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:15 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>
> Works without signals, but my signal test case
> crashes with or without my changes.

As long as we're not making things worse....

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 12/34] linux-user: Support for restarting system calls for APLHA targets
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 12/34] linux-user: Support for restarting system calls for APLHA targets Timothy E Baldwin
@ 2015-09-10 18:16   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:16 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>
> Signal handling NOT TESTED

Typo in subject line: should be "Alpha" (also, not all caps).

Otherwise
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 13/34] linux-user: Fix signal before blocking system calls race and SA_RESTART
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 13/34] linux-user: Fix signal before blocking system calls race and SA_RESTART Timothy E Baldwin
@ 2015-09-10 18:46   ` Peter Maydell
  2015-09-11 10:57   ` Peter Maydell
  1 sibling, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:46 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:

This is definitely the right design for fixing this race. Comments
below are mainly about structure, documentation and minor nits.

> If a signal is delivered immediately before a blocking system calls the

"call"

> handler will only be called after the system call returns, which may be a
> long time later or never.
>
> This is fixed by using a function (safe_syscall_base) that checks  if a guest

double space ("  ")

> signal is pending prior to making a system call, and if so does not call the
> system call and returns -TARGET_ERESTARTSYS. If a signal is received between

"but instead returns".

> the check and the system call host_signal_handler() rewinds execution to

"then host_signal_handler()"

> before the check. If the system call returns an error a guest error code
> is returned.
>
> safe_syscall_base is implemented in assembly language with initially
> only a x86-64 version, a fall back is provided keep the old behaviour.

"version. A fall back is provided until other host architectures are
converted to use this mechanism."

>
> Also setting the SA_RESTART flag would result in host system calls being
> restarted and the guest signal handler only being called when they have
> completed. This is also fixed.

Fixed only for host archs using safe_syscall, I assume?

> This commit contains general infrastructure and safe_syscall_base for x86-64.
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  configure                        |  13 +++++
>  linux-user/Makefile.objs         |   3 +-
>  linux-user/qemu.h                |  17 +++++++
>  linux-user/safe_syscall/x86_64.S |  34 +++++++++++++
>  linux-user/signal.c              |  12 +++++
>  linux-user/syscall.c             | 107 +++++++++++++++++++++++++++++++++++++++
>  6 files changed, 185 insertions(+), 1 deletion(-)
>  create mode 100644 linux-user/safe_syscall/x86_64.S
>
> diff --git a/configure b/configure
> index 21c4089..d7c115a 100755
> --- a/configure
> +++ b/configure
> @@ -5219,6 +5219,19 @@ if test "$gcov" = "yes" ; then
>    echo "GCOV=$gcov_tool" >> $config_host_mak
>  fi
>
> +# Which safe_syscall_base implmentation?

"implementation"

> +if test "$linux" = "yes" ; then
> +  case "$cpu" in
> +  x86_64)
> +    echo "SAFE_SYSCALL_BASE=safe_syscall/x86_64.o" >> $config_host_mak
> +    echo "CONFIG_SAFE_SYSCALL=y" >> $config_host_mak
> +    ;;
> +  *)
> +    echo "SAFE_SYSCALL_BASE=" >> $config_host_mak
> +    ;;
> +  esac
> +fi

I can't help feeling there ought to be a cleaner way than this,
but I can't think of one, so this will work. It would probably
be nice to factor out the "write safe_syscall/something.o to
config file" part, because that will get repetitive when we
get more architectures in this switch.

> +
>  # use included Linux headers
>  if test "$linux" = "yes" ; then
>    mkdir -p linux-headers
> diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs
> index fd50217..56f9937 100644
> --- a/linux-user/Makefile.objs
> +++ b/linux-user/Makefile.objs
> @@ -1,5 +1,6 @@
>  obj-y = main.o syscall.o strace.o mmap.o signal.o \
> -       elfload.o linuxload.o uaccess.o uname.o
> +       elfload.o linuxload.o uaccess.o uname.o \
> +       $(SAFE_SYSCALL_BASE)
>
>  obj-$(TARGET_HAS_BFLT) += flatload.o
>  obj-$(TARGET_I386) += vm86.o
> diff --git a/linux-user/qemu.h b/linux-user/qemu.h
> index 8012cc2..57c7e43 100644
> --- a/linux-user/qemu.h
> +++ b/linux-user/qemu.h
> @@ -216,8 +216,25 @@ unsigned long init_guest_space(unsigned long host_start,
>
>  #include "qemu/log.h"
>
> +/* safe_syscall.S */
> +
> +/* Call a system call if guest signal not pending.
> + * Returns -TARGET_ESIGRETURN if signal pending.

The code seems to return -TARGET_ERESTARTSYS...

> + * Returns guest error code on error.
> + */

Doc-comment style comments for functions are preferred over
ad-hoc ones (see eg bitops.h extract32 &c for example syntax).

Worth emphasising that this is going to directly call a host
system call (ie will not go via glibc).

We should also actually mention the most important thing
about the API -- that there is no race between signals arriving
and taking the syscall, so either we return -TARGET_ERESTARTSYS,
or we enter the syscall (which then will return EINTR/etc as
appropriate when the host signal arrives).

Saying which syscalls need to be implemented using this and
which don't would also be good. (I think the distinction is
that anything that can block has to go via this, whereas
syscalls which can't block can be implemented via glibc
functions if that's easier. Is that right?)

> +
> +extern long safe_syscall_base(volatile int *pending, long number, ...);
> +#define safe_syscall(...) \
> +    safe_syscall_base(&((TaskState *)thread_cpu->opaque)->signal_pending, \
> +    __VA_ARGS__)
> +
> +/* For host_signal_handler() */
> +extern char safe_syscall_start[];
> +extern char safe_syscall_end[];
> +
>  /* syscall.c */
>  int host_to_target_waitstatus(int status);
> +abi_long convert_syscall_return_value(abi_long ret);

Any new global function should have a doc comment.

>  /* strace.c */
>  void print_syscall(int num,
> diff --git a/linux-user/safe_syscall/x86_64.S b/linux-user/safe_syscall/x86_64.S
> new file mode 100644
> index 0000000..2e32563
> --- /dev/null
> +++ b/linux-user/safe_syscall/x86_64.S
> @@ -0,0 +1,34 @@
> +#include "errno_defs.h"

New source files need a comment at the top which gives the
copyright and license information and a brief description of
what the file is.

> +
> +        .global safe_syscall_base
> +        .global safe_syscall_start
> +        .global safe_syscall_end
> +        .type   safe_syscall_base, @function
> +
> +safe_syscall_base:

This definitely needs a comment describing the ABI on entry,
at a minimum.

> +        push    %rbp
> +        mov     %rsi, %rax // Move syscall number
> +        mov     %rdi, %rbp // Move signal_pending pointer
> +
> +        mov     %rdx, %rdi // Move syscall arguments
> +        mov     %rcx, %rsi
> +        mov     %r8,  %rdx
> +        mov     %r9,  %r10
> +        mov     16(%rsp), %r8
> +        mov     24(%rsp), %r9
> +
> +safe_syscall_start:
> +        testl   $1, (%rbp) // Check signal_pending
> +        jnz     return_ERESTARTSYS
> +        syscall
> +safe_syscall_end:

These labels are deep magic and need a suitable comment to
let the reader know that weird things can happen to the
flow control in this function that are not apparent at
first glance.

(Consider that most people trying to add support for
a new target architecture will probably do so by
cribbing from this existing implementation; we should
document what those readers need to know to get it right.)

> +        pop     %rbp
> +        mov     %rax, %rdi
> +        jmp     convert_syscall_return_value
> +
> +return_ERESTARTSYS:
> +        mov     $-TARGET_ERESTARTSYS, %rax
> +        pop     %rbp
> +        ret
> +
> +        .size   safe_syscall_base, .-safe_syscall_base
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index 5cf75a4..09551ba 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -569,6 +569,10 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
>      }
>  }
>
> +#if defined(__x86_64__)
> +#define PC_SIG (uc->uc_mcontext.gregs[REG_RIP])
> +#endif

This is going to turn into an ifdef ladder for every host
architecture we support. We have too many ifdef ladders
already -- can you find a way to structure this so per-arch
defines and functions live in their own files and are
pulled in correctly by the build system, please?

(One possibility that comes to mind is adding another
directory to the include path, which is how we handle
linux-headers and tcg/ backends. That would probably also
let you automatically #include a linux-user/host-arch/safe_syscall.S
somehow without having to put something special in configure
for that part. I haven't thought the details through too
carefully here yet.)

> +
>  static void host_signal_handler(int host_signum, siginfo_t *info,
>                                  void *puc)
>  {
> @@ -591,6 +595,14 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
>  #if defined(DEBUG_SIGNAL)
>      fprintf(stderr, "qemu: got signal %d\n", sig);
>  #endif
> +
> +    struct ucontext *uc = puc;
> +#ifdef CONFIG_SAFE_SYSCALL
> +    if (PC_SIG > (uintptr_t)safe_syscall_start
> +            && PC_SIG < (uintptr_t)safe_syscall_end)
> +        PC_SIG = (uintptr_t)safe_syscall_start;

Is this going to work for SPARC, with its pc/npc distinction?
Or do we need a more complex abstraction?

> +#endif
> +
>      host_to_target_siginfo_noswap(&tinfo, info);
>      if (queue_signal(env, sig, &tinfo) == 1) {
>          /* interrupt the virtual CPU as soon as possible */
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 80b8fa8..b9ad7b6 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -599,6 +599,113 @@ char *target_strerror(int err)
>      return strerror(target_to_host_errno(err));
>  }
>
> +abi_long convert_syscall_return_value(abi_long ret) {
> +    if (is_error(ret)) {
> +        ret = host_to_target_errno(ret);
> +    }
> +    return ret;
> +}
> +
> +#if defined(CONFIG_SAFE_SYSCALL) && defined(TARGET_USE_ERESTARTSYS)
> +
> +#define safe_syscall0(type, name) \
> +static type safe_##name (void) \
> +{ \
> +    return safe_syscall(__NR_##name); \
> +}
> +
> +#define safe_syscall1(type, name, type1, arg1) \
> +static type safe_##name (type1 arg1) \
> +{ \
> +    return safe_syscall(__NR_##name, arg1); \
> +}
> +
> +#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
> +static type safe_##name (type1 arg1, type2 arg2) \
> +{ \
> +    return safe_syscall(__NR_##name, arg1, arg2); \
> +}
> +
> +#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
> +static type safe_##name (type1 arg1, type2 arg2, type3 arg3) \
> +{ \
> +    return safe_syscall(__NR_##name, arg1, arg2, arg3); \
> +}
> +
> +#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
> +    type4, arg4) \
> +static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
> +{ \
> +    return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
> +}
> +
> +#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
> +    type4, arg4, type5, arg5) \
> +static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
> +    type5 arg5) \
> +{ \
> +    return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
> +}
> +
> +#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
> +    type4, arg4, type5, arg5, type6, arg6) \
> +static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
> +    type5 arg5, type6 arg6) \
> +{ \
> +    return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
> +}
> +
> +#else
> +
> +#define safe_syscall0(type, name) \
> +static type safe_##name (void) \
> +{ \
> +    return get_errno(name()); \
> +}

Should these fallbacks call the syscall, not the libc function?

> +#define safe_syscall1(type, name, type1, arg1) \
> +static type safe_##name (type1 arg1) \
> +{ \
> +    return get_errno(name(arg1)); \
> +}
> +
> +#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
> +static type safe_##name (type1 arg1, type2 arg2) \
> +{ \
> +    return get_errno(name(arg1, arg2)); \
> +}
> +
> +#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
> +static type safe_##name (type1 arg1, type2 arg2, type3 arg3) \
> +{ \
> +    return get_errno(name(arg1, arg2, arg3)); \
> +}
> +
> +#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
> +    type4, arg4) \
> +static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
> +{ \
> +    return get_errno(name(arg1, arg2, arg3, arg4)); \
> +}
> +
> +#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
> +    type4, arg4, type5, arg5) \
> +static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
> +    type5 arg5) \
> +{ \
> +    return get_errno(name(arg1, arg2, arg3, arg4, arg5)); \
> +}
> +
> +#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
> +    type4, arg4, type5, arg5, type6, arg6) \
> +static type safe_##name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
> +    type5 arg5, type6 arg6)  \
> +{ \
> +    return get_errno(name(arg1, arg2, arg3, arg4, arg5, arg6)); \
> +}
> +
> +#endif
> +
>  static inline int host_to_target_sock_type(int host_type)
>  {
>      int target_type;
> --
> 2.1.4

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 14/34] linux-user: Use safe_syscall for read and write system calls
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 14/34] linux-user: Use safe_syscall for read and write system calls Timothy E Baldwin
@ 2015-09-10 18:48   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:48 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Restart read() and write() if signals occur before, or during with SA_RESTART
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 15/34] linux-user: Remove redundant get_errno() calls
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 15/34] linux-user: Remove redundant get_errno() calls Timothy E Baldwin
@ 2015-09-10 18:50   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:50 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> The return value of openat was being translated by get_errno() twice.
> Fixed by removing calls of get_errno() in do_syscall() and keeping those
> in do_openat().
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/syscall.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index c213588..df9b2ca 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -5764,17 +5764,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>      case TARGET_NR_open:
>          if (!(p = lock_user_string(arg1)))
>              goto efault;
> -        ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
> -                                  target_to_host_bitmask(arg2, fcntl_flags_tbl),
> -                                  arg3));
> +        ret = do_openat(cpu_env, AT_FDCWD, p,
> +                        target_to_host_bitmask(arg2, fcntl_flags_tbl),
> +                        arg3);
>          unlock_user(p, arg1, 0);
>          break;
>      case TARGET_NR_openat:
>          if (!(p = lock_user_string(arg2)))
>              goto efault;
> -        ret = get_errno(do_openat(cpu_env, arg1, p,
> -                                  target_to_host_bitmask(arg3, fcntl_flags_tbl),
> -                                  arg4));
> +        ret = do_openat(cpu_env, arg1, p,
> +                        target_to_host_bitmask(arg3, fcntl_flags_tbl),
> +                        arg4);
>          unlock_user(p, arg2, 0);
>          break;
>      case TARGET_NR_close:

Nice catch, but I don't think this patch is sufficient. There are still
code paths in do_openat() which aren't returning a target errno, like
the "mkstemp failed" case. The fake_open->fill functions are also not
generally returning target errnos.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 16/34] linux-user: Use safe_syscall for open and openat system calls
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 16/34] linux-user: Use safe_syscall for open and openat system calls Timothy E Baldwin
@ 2015-09-10 18:54   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:54 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Restart open() and openat() if signals occur before,
> or during with SA_RESTART.
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

When we get to the cases where not all the host architectures provide
a particular syscall (ie where we're currently relying on glibc to
implement a function with whatever the host arch's syscall ABI demands)
this is going to get trickier, but for the functions so far I think
they're present with the same ABI on all archs.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 17/34] linux-user: Use safe_syscall for wait system calls
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 17/34] linux-user: Use safe_syscall for wait " Timothy E Baldwin
@ 2015-09-10 18:58   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 18:58 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/syscall.c | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 29/34] linux-user: Support for restarting system calls for UniCore32 targets
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 29/34] linux-user: Support for restarting system calls for UniCore32 targets Timothy E Baldwin
@ 2015-09-10 19:05   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 19:05 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>
> WARNING - NOT TESTED
>
>  linux-user/main.c              | 7 ++++++-
>  linux-user/unicore32/syscall.h | 2 ++
>  2 files changed, 8 insertions(+), 1 deletion(-)

Unicore32 is teetering on the brink of being a dead target,
so I don't care much.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 30/34] linux-user: Support for restarting system calls for OpenRISC targets
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 30/34] linux-user: Support for restarting system calls for OpenRISC targets Timothy E Baldwin
@ 2015-09-10 19:06   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 19:06 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>
> WARNING - NOT TESTED
>
>  linux-user/main.c             | 22 ++++++++++++++--------
>  linux-user/openrisc/syscall.h |  2 ++
>  2 files changed, 16 insertions(+), 8 deletions(-)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 31/34] linux-user: Support for restarting system calls for M68K targets
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 31/34] linux-user: Support for restarting system calls for M68K targets Timothy E Baldwin
@ 2015-09-10 19:06   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 19:06 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/m68k/syscall.h |  2 ++
>  linux-user/main.c         | 24 +++++++++++++++---------
>  linux-user/signal.c       | 20 ++++++++------------
>  3 files changed, 25 insertions(+), 21 deletions(-)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 32/34] linux-user: Support for restarting system calls for S390 targets
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 32/34] linux-user: Support for restarting system calls for S390 targets Timothy E Baldwin
@ 2015-09-10 19:07   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 19:07 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>
> WARNING - NOT TESTED
>
>  linux-user/main.c          | 12 +++++++++---
>  linux-user/s390x/syscall.h |  2 ++
>  linux-user/signal.c        |  4 ++--
>  3 files changed, 13 insertions(+), 5 deletions(-)
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 0863945..a59907e 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -3355,6 +3355,7 @@ void cpu_loop(CPUS390XState *env)
>      int trapnr, n, sig;
>      target_siginfo_t info;
>      target_ulong addr;
> +    abi_long ret;
>
>      while (1) {
>          cpu_exec_start(cs);
> @@ -3372,9 +3373,14 @@ void cpu_loop(CPUS390XState *env)
>                  n = env->regs[1];
>              }
>              env->psw.addr += env->int_svc_ilen;
> -            env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3],
> -                                      env->regs[4], env->regs[5],
> -                                      env->regs[6], env->regs[7], 0, 0);
> +            ret = do_syscall(env, n, env->regs[2], env->regs[3],
> +                             env->regs[4], env->regs[5],
> +                             env->regs[6], env->regs[7], 0, 0);
> +            if (ret == -TARGET_ERESTARTSYS) {
> +                env->psw.addr -= env->int_svc_ilen;;

Stray doubled semicolon.

Otherwise

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 33/34] linux-user: Support for restarting system calls for CRIS targets
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 33/34] linux-user: Support for restarting system calls for CRIS targets Timothy E Baldwin
@ 2015-09-10 19:12   ` Peter Maydell
  2015-09-11 14:18     ` Edgar E. Iglesias
  0 siblings, 1 reply; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 19:12 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Edgar E. Iglesias, Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>
> WARNING - NOT TESTED
>
>  linux-user/cris/syscall.h | 2 ++
>  linux-user/main.c         | 6 +++++-
>  linux-user/signal.c       | 2 +-
>  3 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/linux-user/cris/syscall.h b/linux-user/cris/syscall.h
> index 2957b0d..29218e2 100644
> --- a/linux-user/cris/syscall.h
> +++ b/linux-user/cris/syscall.h
> @@ -44,3 +44,5 @@ struct target_pt_regs {
>  #define TARGET_MLOCKALL_MCL_FUTURE  2
>
>  #endif
> +
> +#define TARGET_USE_ERESTARTSYS 1
> diff --git a/linux-user/main.c b/linux-user/main.c
> index a59907e..a9eb15c 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -2878,7 +2878,11 @@ void cpu_loop(CPUCRISState *env)
>                               env->pregs[7],
>                               env->pregs[11],
>                               0, 0);
> -            env->regs[10] = ret;
> +            if (ret == -TARGET_ERESTARTSYS) {
> +                env->pc -= 2;
> +            } else if (ret != -TARGET_QEMU_ESIGRETURN) {
> +                env->regs[10] = ret;
> +            }
>              break;
>          case EXCP_DEBUG:
>              {
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index e17514e..3741517 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -3761,7 +3761,7 @@ long do_sigreturn(CPUCRISState *env)
>
>      restore_sigcontext(&frame->sc, env);
>      unlock_user_struct(frame, frame_addr, 0);
> -    return env->regs[10];
> +    return -TARGET_QEMU_ESIGRETURN;
>  badframe:
>      force_sig(TARGET_SIGSEGV);
>  }

Looks OK, but this one I'm not sure enough about the CRIS instruction
set and the surrounding code doesn't clarify. Edgar -- is the CRIS
instruction for "take linux system call" always exactly 2 bytes long?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 34/34] linux-user: Remove TARGET_USE_ERESTARTSYS
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 34/34] linux-user: Remove TARGET_USE_ERESTARTSYS Timothy E Baldwin
@ 2015-09-10 19:13   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-10 19:13 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Now with system call restarting support by all targets remove
> uneeded conditionals.
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/aarch64/syscall.h    | 2 --
>  linux-user/alpha/syscall.h      | 2 --
>  linux-user/arm/syscall.h        | 2 --
>  linux-user/cris/syscall.h       | 2 --
>  linux-user/i386/syscall.h       | 2 --
>  linux-user/m68k/syscall.h       | 2 --
>  linux-user/microblaze/syscall.h | 2 --
>  linux-user/mips/syscall.h       | 2 --
>  linux-user/mips64/syscall.h     | 2 --
>  linux-user/openrisc/syscall.h   | 2 --
>  linux-user/ppc/syscall.h        | 2 --
>  linux-user/s390x/syscall.h      | 2 --
>  linux-user/sh4/syscall.h        | 2 --
>  linux-user/signal.c             | 3 ---
>  linux-user/sparc/syscall.h      | 2 --
>  linux-user/sparc64/syscall.h    | 2 --
>  linux-user/syscall.c            | 4 ++--
>  linux-user/unicore32/syscall.h  | 2 --
>  linux-user/x86_64/syscall.h     | 2 --
>  19 files changed, 2 insertions(+), 39 deletions(-)

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

(though note there is a new target arch, tilegx, currently circling
to land, which will mean you'll need to add some more stuff to
this patchset assuming it doesn't get in first.)

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 13/34] linux-user: Fix signal before blocking system calls race and SA_RESTART
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 13/34] linux-user: Fix signal before blocking system calls race and SA_RESTART Timothy E Baldwin
  2015-09-10 18:46   ` Peter Maydell
@ 2015-09-11 10:57   ` Peter Maydell
  1 sibling, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-11 10:57 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> If a signal is delivered immediately before a blocking system calls the
> handler will only be called after the system call returns, which may be a
> long time later or never.
>
> This is fixed by using a function (safe_syscall_base) that checks  if a guest
> signal is pending prior to making a system call, and if so does not call the
> system call and returns -TARGET_ERESTARTSYS. If a signal is received between
> the check and the system call host_signal_handler() rewinds execution to
> before the check. If the system call returns an error a guest error code
> is returned.
>
> safe_syscall_base is implemented in assembly language with initially
> only a x86-64 version, a fall back is provided keep the old behaviour.
>
> Also setting the SA_RESTART flag would result in host system calls being
> restarted and the guest signal handler only being called when they have
> completed. This is also fixed.
>
> This commit contains general infrastructure and safe_syscall_base for x86-64.
>
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -599,6 +599,113 @@ char *target_strerror(int err)
>      return strerror(target_to_host_errno(err));
>  }
>
> +abi_long convert_syscall_return_value(abi_long ret) {
> +    if (is_error(ret)) {
> +        ret = host_to_target_errno(ret);

This should be
    ret = -host_to_target_errno(-ret);

host_to_target_errno() expects positive host errno
values and returns positive guest errno values, but in
this case we are converting a -errno return.

This is why some of the LTP tests were failing: we were passing
a negative value to host_to_target_errno, which then indexed
backwards off the front of its table and into the target_to_host_errno
table. So you typically got back an errno, but not the right one...

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 01/34] linux-user: Fix array bounds in errno conversion
  2015-09-05 23:56 ` [Qemu-devel] [PATCH 01/34] linux-user: Fix array bounds in errno conversion Timothy E Baldwin
  2015-09-10 18:04   ` Peter Maydell
@ 2015-09-11 10:59   ` Peter Maydell
  2015-10-12 13:42     ` Riku Voipio
  1 sibling, 1 reply; 76+ messages in thread
From: Peter Maydell @ 2015-09-11 10:59 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:56, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Check array bounds in host_to_target_errno() and target_to_host_errno().
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/syscall.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 264debc..4e40dc6 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -566,14 +566,14 @@ static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
>
>  static inline int host_to_target_errno(int err)
>  {
> -    if(host_to_target_errno_table[err])
> +    if(err < ERRNO_TABLE_SIZE && host_to_target_errno_table[err])
>          return host_to_target_errno_table[err];
>      return err;
>  }
>
>  static inline int target_to_host_errno(int err)
>  {
> -    if (target_to_host_errno_table[err])
> +    if (err < ERRNO_TABLE_SIZE && target_to_host_errno_table[err])
>          return target_to_host_errno_table[err];
>      return err;
>  }

Maybe we should also check that the passed in error value is
not negative? (Given the errno-is-positive/syscall-return-negative
conventions, it's an easy mistake to make...)

-- PMM

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

* Re: [Qemu-devel] [PATCH 33/34] linux-user: Support for restarting system calls for CRIS targets
  2015-09-10 19:12   ` Peter Maydell
@ 2015-09-11 14:18     ` Edgar E. Iglesias
  2015-09-11 14:20       ` Peter Maydell
  0 siblings, 1 reply; 76+ messages in thread
From: Edgar E. Iglesias @ 2015-09-11 14:18 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Edgar E. Iglesias, Riku Voipio, Timothy E Baldwin, QEMU Developers

On Thu, Sep 10, 2015 at 08:12:21PM +0100, Peter Maydell wrote:
> On 6 September 2015 at 00:57, Timothy E Baldwin
> <T.E.Baldwin99@members.leeds.ac.uk> wrote:
> > Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> > ---
> >
> > WARNING - NOT TESTED
> >
> >  linux-user/cris/syscall.h | 2 ++
> >  linux-user/main.c         | 6 +++++-
> >  linux-user/signal.c       | 2 +-
> >  3 files changed, 8 insertions(+), 2 deletions(-)
> >
> > diff --git a/linux-user/cris/syscall.h b/linux-user/cris/syscall.h
> > index 2957b0d..29218e2 100644
> > --- a/linux-user/cris/syscall.h
> > +++ b/linux-user/cris/syscall.h
> > @@ -44,3 +44,5 @@ struct target_pt_regs {
> >  #define TARGET_MLOCKALL_MCL_FUTURE  2
> >
> >  #endif
> > +
> > +#define TARGET_USE_ERESTARTSYS 1
> > diff --git a/linux-user/main.c b/linux-user/main.c
> > index a59907e..a9eb15c 100644
> > --- a/linux-user/main.c
> > +++ b/linux-user/main.c
> > @@ -2878,7 +2878,11 @@ void cpu_loop(CPUCRISState *env)
> >                               env->pregs[7],
> >                               env->pregs[11],
> >                               0, 0);
> > -            env->regs[10] = ret;
> > +            if (ret == -TARGET_ERESTARTSYS) {
> > +                env->pc -= 2;
> > +            } else if (ret != -TARGET_QEMU_ESIGRETURN) {
> > +                env->regs[10] = ret;
> > +            }
> >              break;
> >          case EXCP_DEBUG:
> >              {
> > diff --git a/linux-user/signal.c b/linux-user/signal.c
> > index e17514e..3741517 100644
> > --- a/linux-user/signal.c
> > +++ b/linux-user/signal.c
> > @@ -3761,7 +3761,7 @@ long do_sigreturn(CPUCRISState *env)
> >
> >      restore_sigcontext(&frame->sc, env);
> >      unlock_user_struct(frame, frame_addr, 0);
> > -    return env->regs[10];
> > +    return -TARGET_QEMU_ESIGRETURN;
> >  badframe:
> >      force_sig(TARGET_SIGSEGV);
> >  }
> 
> Looks OK, but this one I'm not sure enough about the CRIS instruction
> set and the surrounding code doesn't clarify. Edgar -- is the CRIS
> instruction for "take linux system call" always exactly 2 bytes long?
>

Yes, those are always 2 bytes.

Cheers,
Edgar 

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

* Re: [Qemu-devel] [PATCH 33/34] linux-user: Support for restarting system calls for CRIS targets
  2015-09-11 14:18     ` Edgar E. Iglesias
@ 2015-09-11 14:20       ` Peter Maydell
  2015-09-11 14:26         ` Edgar E. Iglesias
  0 siblings, 1 reply; 76+ messages in thread
From: Peter Maydell @ 2015-09-11 14:20 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: Edgar E. Iglesias, Riku Voipio, Timothy E Baldwin, QEMU Developers

On 11 September 2015 at 15:18, Edgar E. Iglesias
<edgar.iglesias@xilinx.com> wrote:
> On Thu, Sep 10, 2015 at 08:12:21PM +0100, Peter Maydell wrote:
>> On 6 September 2015 at 00:57, Timothy E Baldwin
>> <T.E.Baldwin99@members.leeds.ac.uk> wrote:
>> > Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
>> > ---
>> >
>> > WARNING - NOT TESTED
>> >
>> >  linux-user/cris/syscall.h | 2 ++
>> >  linux-user/main.c         | 6 +++++-
>> >  linux-user/signal.c       | 2 +-
>> >  3 files changed, 8 insertions(+), 2 deletions(-)


>> Looks OK, but this one I'm not sure enough about the CRIS instruction
>> set and the surrounding code doesn't clarify. Edgar -- is the CRIS
>> instruction for "take linux system call" always exactly 2 bytes long?
>>
>
> Yes, those are always 2 bytes.

Cool. In that case
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 33/34] linux-user: Support for restarting system calls for CRIS targets
  2015-09-11 14:20       ` Peter Maydell
@ 2015-09-11 14:26         ` Edgar E. Iglesias
  0 siblings, 0 replies; 76+ messages in thread
From: Edgar E. Iglesias @ 2015-09-11 14:26 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Edgar E. Iglesias, Riku Voipio, Timothy E Baldwin, QEMU Developers

On Fri, Sep 11, 2015 at 03:20:31PM +0100, Peter Maydell wrote:
> On 11 September 2015 at 15:18, Edgar E. Iglesias
> <edgar.iglesias@xilinx.com> wrote:
> > On Thu, Sep 10, 2015 at 08:12:21PM +0100, Peter Maydell wrote:
> >> On 6 September 2015 at 00:57, Timothy E Baldwin
> >> <T.E.Baldwin99@members.leeds.ac.uk> wrote:
> >> > Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> >> > ---
> >> >
> >> > WARNING - NOT TESTED
> >> >
> >> >  linux-user/cris/syscall.h | 2 ++
> >> >  linux-user/main.c         | 6 +++++-
> >> >  linux-user/signal.c       | 2 +-
> >> >  3 files changed, 8 insertions(+), 2 deletions(-)
> 
> 
> >> Looks OK, but this one I'm not sure enough about the CRIS instruction
> >> set and the surrounding code doesn't clarify. Edgar -- is the CRIS
> >> instruction for "take linux system call" always exactly 2 bytes long?
> >>
> >
> > Yes, those are always 2 bytes.
> 
> Cool. In that case
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
>

Thanks, me too:

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> 

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

* Re: [Qemu-devel] [PATCH 18/34] linux-user: Fix race between multiple signals
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 18/34] linux-user: Fix race between multiple signals Timothy E Baldwin
@ 2015-09-11 14:30   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-11 14:30 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> If multiple host signals are recieved in quick succession they would
> be queued in TaskState then delivered to the guest in spite of
> signals being blocked. Fixed by keeping host signals blocked until
> process_pending_signals() runs, this needs the guest signal state
> to be maintained by Qemu.
>
> Blocking host signals also ensures the correct behaviour with respect
> to multiple threads and the overrun count of timer related signals.
> Alas blocking and queuing in qemu is still needed because of virtual
> processor exceptions, SIGSEGV and SIGBUS.
>
> Blocking signals inside process_pending_signals() protects against
> concurrency problems with respect to signal handlers.
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
>
> Conflicts:
>         linux-user/qemu.h

So, my primary problem with this patch is that it doesn't really
explain the underlying design.

We could really use a comment (say, at the top of signal.c) which describes
the overall design approach to signal handling, including when and how
a syscall implementation should block signals, when it needs to use
safe_syscall, when the host signal mask is the same as the target's
and when it is not, and so on. (Providing a comment like this would
make this patch much easier to review -- it is always harder work having
to reverse engineer the design from the code.)

> ---
>  linux-user/qemu.h    |   8 +++-
>  linux-user/signal.c  | 111 ++++++++++++++++++++++++++++++++++-----------------
>  linux-user/syscall.c |  49 +++++++++++++++--------
>  3 files changed, 113 insertions(+), 55 deletions(-)
>
> diff --git a/linux-user/qemu.h b/linux-user/qemu.h
> index 57c7e43..f2235eb3 100644
> --- a/linux-user/qemu.h
> +++ b/linux-user/qemu.h
> @@ -127,14 +127,17 @@ typedef struct TaskState {
>  #endif
>      uint32_t stack_base;
>      int used; /* non zero if used */
> -    bool sigsegv_blocked; /* SIGSEGV blocked by guest */
>      struct image_info *info;
>      struct linux_binprm *bprm;
>
>      struct emulated_sigtable sigtab[TARGET_NSIG];
>      struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
>      struct sigqueue *first_free; /* first free siginfo queue entry */
> -    int signal_pending; /* non zero if a signal may be pending */
> +    sigset_t signal_mask;
> +
> +    /* non zero if host signals blocked, bit 1 set if signal pending */
> +    volatile int signal_pending;

"volatile sig_atomic_t" would be preferable (if only because it clues
the reader into expect that there might be interactions between signal
handler and main code for this variable).

> +
>  } __attribute__((aligned(16))) TaskState;
>
>  extern char *exec_path;
> @@ -255,6 +258,7 @@ long do_sigreturn(CPUArchState *env);
>  long do_rt_sigreturn(CPUArchState *env);
>  abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
>  int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
> +int block_signals(void); /* Returns non zero if signal pending */

This function needs a proper doc comment.

>
>  #ifdef TARGET_I386
>  /* vm86.c */
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index 09551ba..3e272a5 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -197,53 +197,66 @@ void target_to_host_old_sigset(sigset_t *sigset,
>      target_to_host_sigset(sigset, &d);
>  }
>
> +int block_signals(void)
> +{
> +    TaskState *ts = (TaskState *)thread_cpu->opaque;
> +    sigset_t set;
> +    int pending;
> +
> +    sigfillset(&set);
> +    sigdelset(&set, SIGSEGV);
> +    sigdelset(&set, SIGBUS);

An explanation of why SIGSEGV and SIGBUS are special would be helpful.

> +    sigprocmask(SIG_SETMASK, &set, 0);

Should this be setting the signal mask for the thread only
(via pthread_sigmask) rather than the whole process?

> +
> +    pending = ts->signal_pending;
> +    pending |= 2;
> +    ts->signal_pending = pending;

Worth a comment that it's ok to do this non-atomically because we
have all signals blocked.

> +
> +#ifdef TARGET_USE_ERESTARTSYS
> +    return pending & 1;
> +#endif
> +    return 0;
> +}
> +
>  /* Wrapper for sigprocmask function
>   * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset
> - * are host signal set, not guest ones. This wraps the sigprocmask host calls
> - * that should be protected (calls originated from guest)
> + * are host signal set, not guest ones.
>   */

Why have you dropped the bit of the comment about wrapping the calls
originating from guests? AFAICT it's still true.

>  int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
>  {
> -    int ret;
> -    sigset_t val;
> -    sigset_t *temp = NULL;
> -    CPUState *cpu = thread_cpu;
> -    TaskState *ts = (TaskState *)cpu->opaque;
> -    bool segv_was_blocked = ts->sigsegv_blocked;
> +    TaskState *ts = (TaskState *)thread_cpu->opaque;
> +
> +    if (oldset) {
> +        *oldset = ts->signal_mask;
> +    }
>
>      if (set) {
> -        bool has_sigsegv = sigismember(set, SIGSEGV);
> -        val = *set;
> -        temp = &val;
> +        int i;
>
> -        sigdelset(temp, SIGSEGV);
> +        if (block_signals()) {
> +            return -TARGET_ERESTARTSYS;
> +        }
>
>          switch (how) {
>          case SIG_BLOCK:
> -            if (has_sigsegv) {
> -                ts->sigsegv_blocked = true;
> -            }
> +            sigorset(&ts->signal_mask, &ts->signal_mask, set);
>              break;
>          case SIG_UNBLOCK:
> -            if (has_sigsegv) {
> -                ts->sigsegv_blocked = false;
> +            for (i = 0; i != NSIG; ++i) {
> +                if (sigismember(set, i)) {
> +                    sigdelset(&ts->signal_mask, i);
> +                }
>              }
>              break;
>          case SIG_SETMASK:
> -            ts->sigsegv_blocked = has_sigsegv;
> +            ts->signal_mask = *set;
>              break;
>          default:
>              g_assert_not_reached();
>          }
> -    }
> -
> -    ret = sigprocmask(how, temp, oldset);
>
> -    if (oldset && segv_was_blocked) {
> -        sigaddset(oldset, SIGSEGV);
>      }
> -
> -    return ret;
> +    return 0;
>  }
>
>  /* siginfo conversion */
> @@ -374,6 +387,7 @@ static int core_dump_signal(int sig)
>
>  void signal_init(void)
>  {
> +    TaskState *ts = (TaskState *)thread_cpu->opaque;
>      struct sigaction act;
>      struct sigaction oact;
>      int i, j;
> @@ -389,6 +403,9 @@ void signal_init(void)
>          target_to_host_signal_table[j] = i;
>      }
>
> +    /* Set the signal mask from the host mask. */
> +    sigprocmask(0, 0, &ts->signal_mask);
> +
>      /* set all host signal handlers. ALL signals are blocked during
>         the handlers to serialize them. */
>      memset(sigact_table, 0, sizeof(sigact_table));
> @@ -508,7 +525,7 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
>      queue = gdb_queuesig ();
>      handler = sigact_table[sig - 1]._sa_handler;
>
> -    if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
> +    if (sig == TARGET_SIGSEGV && sigismember(&ts->signal_mask, SIGSEGV)) {
>          /* Guest has blocked SIGSEGV but we got one anyway. Assume this
>           * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
>           * because it got a real MMU fault). A blocked SIGSEGV in that
> @@ -605,6 +622,11 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
>
>      host_to_target_siginfo_noswap(&tinfo, info);
>      if (queue_signal(env, sig, &tinfo) == 1) {
> +        /* Block host signals until target signal handler entered */
> +        sigfillset(&uc->uc_sigmask);
> +        sigdelset(&uc->uc_sigmask, SIGSEGV);
> +        sigdelset(&uc->uc_sigmask, SIGBUS);
> +
>          /* interrupt the virtual CPU as soon as possible */
>          cpu_exit(thread_cpu);
>      }
> @@ -5628,26 +5650,40 @@ void process_pending_signals(CPUArchState *cpu_env)
>      CPUState *cpu = ENV_GET_CPU(cpu_env);
>      int sig;
>      abi_ulong handler;
> -    sigset_t set, old_set;
> +    sigset_t set;
>      target_sigset_t target_old_set;
>      struct emulated_sigtable *k;
>      struct target_sigaction *sa;
>      struct sigqueue *q;
>      TaskState *ts = cpu->opaque;
>
> -    if (!ts->signal_pending)
> +restart:
> +    if (!ts->signal_pending) {
>          return;
> +    }
>
>      /* FIXME: This is not threadsafe.  */
> +    sigfillset(&set);
> +    sigprocmask(SIG_SETMASK, &set, 0);
> +
> + next_signal:

I'm not a great fan of this use of goto for flow control.

>      k = ts->sigtab;
>      for(sig = 1; sig <= TARGET_NSIG; sig++) {
> -        if (k->pending)
> +        if (k->pending && (
> +                    !sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
> +                    || sig == TARGET_SIGSEGV)) {

It's not entirely clear why this is a special case for SIGSEGV only,
but we treat SIGSEGV and SIGBUS mostly the same elsewhere.

>              goto handle_signal;
> +        }
>          k++;
>      }
> -    /* if no signal is pending, just return */
> +
> +    /* if no signal is pending, unblock signals and restart */
>      ts->signal_pending = 0;
> -    return;
> +    set = ts->signal_mask;
> +    sigdelset(&set, SIGSEGV);
> +    sigdelset(&set, SIGBUS);
> +    sigprocmask(SIG_SETMASK, &set, 0);
> +    goto restart; /* Another signal? */
>
>   handle_signal:
>  #ifdef DEBUG_SIGNAL
> @@ -5668,7 +5704,7 @@ void process_pending_signals(CPUArchState *cpu_env)
>          handler = sa->_sa_handler;
>      }
>
> -    if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) {
> +    if (sig == TARGET_SIGSEGV && sigismember(&ts->signal_mask, SIGSEGV)) {
>          /* Guest has blocked SIGSEGV but we got one anyway. Assume this
>           * is a forced SIGSEGV (ie one the kernel handles via force_sig_info
>           * because it got a real MMU fault), and treat as if default handler.
> @@ -5698,11 +5734,12 @@ void process_pending_signals(CPUArchState *cpu_env)
>          if (!(sa->sa_flags & TARGET_SA_NODEFER))
>              sigaddset(&set, target_to_host_signal(sig));
>
> -        /* block signals in the handler using Linux */
> -        do_sigprocmask(SIG_BLOCK, &set, &old_set);
>          /* save the previous blocked signal state to restore it at the
>             end of the signal execution (see do_sigreturn) */
> -        host_to_target_sigset_internal(&target_old_set, &old_set);
> +        host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
> +
> +        /* block signals in the handler */
> +        sigorset(&ts->signal_mask, &ts->signal_mask, &set);
>
>          /* if the CPU is in VM86 mode, we restore the 32 bit values */
>  #if defined(TARGET_I386) && !defined(TARGET_X86_64)
> @@ -5722,9 +5759,11 @@ void process_pending_signals(CPUArchState *cpu_env)
>          else
>              setup_frame(sig, sa, &target_old_set, cpu_env);
>  #endif
> -       if (sa->sa_flags & TARGET_SA_RESETHAND)
> +        if (sa->sa_flags & TARGET_SA_RESETHAND)
>              sa->_sa_handler = TARGET_SIG_DFL;
>      }
>      if (q != &k->info)
>          free_sigqueue(cpu_env, q);
> +
> +    goto next_signal;
>  }
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 281fa2d..682090d 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -4676,6 +4676,7 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
>          new_cpu->opaque = ts;
>          ts->bprm = parent_ts->bprm;
>          ts->info = parent_ts->info;
> +        ts->signal_mask = parent_ts->signal_mask;
>          nptl_flags = flags;
>          flags &= ~CLONE_NPTL_FLAGS2;
>
> @@ -6492,9 +6493,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>          {
>              sigset_t cur_set;
>              abi_ulong target_set;
> -            do_sigprocmask(0, NULL, &cur_set);
> -            host_to_target_old_sigset(&target_set, &cur_set);
> -            ret = target_set;
> +            ret = do_sigprocmask(0, NULL, &cur_set);
> +            if (!ret) {
> +                host_to_target_old_sigset(&target_set, &cur_set);
> +                ret = target_set;
> +            }
>          }
>          break;
>  #endif
> @@ -6503,12 +6506,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>          {
>              sigset_t set, oset, cur_set;
>              abi_ulong target_set = arg1;
> -            do_sigprocmask(0, NULL, &cur_set);
> -            target_to_host_old_sigset(&set, &target_set);
> -            sigorset(&set, &set, &cur_set);
> -            do_sigprocmask(SIG_SETMASK, &set, &oset);
> -            host_to_target_old_sigset(&target_set, &oset);
> -            ret = target_set;
> +            ret = do_sigprocmask(0, NULL, &cur_set);
> +            if (!ret) {
> +                target_to_host_old_sigset(&set, &target_set);
> +                sigorset(&set, &set, &cur_set);
> +                do_sigprocmask(SIG_SETMASK, &set, &oset);
> +                host_to_target_old_sigset(&target_set, &oset);
> +                ret = target_set;
> +            }
>          }
>          break;
>  #endif
> @@ -6537,7 +6542,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>              mask = arg2;
>              target_to_host_old_sigset(&set, &mask);
>
> -            ret = get_errno(do_sigprocmask(how, &set, &oldset));
> +            ret = do_sigprocmask(how, &set, &oldset);
>              if (!is_error(ret)) {
>                  host_to_target_old_sigset(&mask, &oldset);
>                  ret = mask;
> @@ -6571,7 +6576,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>                  how = 0;
>                  set_ptr = NULL;
>              }
> -            ret = get_errno(do_sigprocmask(how, set_ptr, &oldset));
> +            ret = do_sigprocmask(how, set_ptr, &oldset);
>              if (!is_error(ret) && arg3) {
>                  if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
>                      goto efault;
> @@ -6611,7 +6616,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>                  how = 0;
>                  set_ptr = NULL;
>              }
> -            ret = get_errno(do_sigprocmask(how, set_ptr, &oldset));
> +            ret = do_sigprocmask(how, set_ptr, &oldset);
>              if (!is_error(ret) && arg3) {
>                  if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
>                      goto efault;
> @@ -6716,11 +6721,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>          break;
>  #ifdef TARGET_NR_sigreturn
>      case TARGET_NR_sigreturn:
> -        ret = do_sigreturn(cpu_env);
> +        if (block_signals()) {
> +            ret = -TARGET_ERESTARTSYS;
> +        } else {
> +            ret = do_sigreturn(cpu_env);
> +        }
>          break;
>  #endif
>      case TARGET_NR_rt_sigreturn:
> -        ret = do_rt_sigreturn(cpu_env);
> +        if (block_signals()) {
> +            ret = -TARGET_ERESTARTSYS;
> +        } else {
> +            ret = do_rt_sigreturn(cpu_env);
> +        }
>          break;
>      case TARGET_NR_sethostname:
>          if (!(p = lock_user_string(arg1)))
> @@ -8744,9 +8757,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>              }
>              mask = arg2;
>              target_to_host_old_sigset(&set, &mask);
> -            do_sigprocmask(how, &set, &oldset);
> -            host_to_target_old_sigset(&mask, &oldset);
> -            ret = mask;
> +            ret = do_sigprocmask(how, &set, &oldset);
> +            if (!ret) {
> +                host_to_target_old_sigset(&mask, &oldset);
> +                ret = mask;
> +            }
>          }
>          break;
>  #endif
> --
> 2.1.4

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 19/34] linux-user: Restart fork() if signals pending
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 19/34] linux-user: Restart fork() if signals pending Timothy E Baldwin
@ 2015-09-11 14:34   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-11 14:34 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> If there is a signal pending during fork() the signal handler will
> erroneously be called in both the parent and child, so handle any
> pending signals first.
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/syscall.c | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 682090d..1ce381e 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -4731,6 +4731,11 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
>          if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) {
>              return -TARGET_EINVAL;
>          }
> +
> +        if (block_signals()) {
> +            return -TARGET_ERESTARTSYS;
> +        }
> +
>          fork_start();
>          ret = fork();
>          if (ret == 0) {

This is in the fork part of do_fork(). In the clone part we
have some code which does "block all signals, then arrange to
restore them after the pthread_create in both threads". Can
we change that to work with the new block_signals approach?
(I have a feeling that in that case this call to block_signals
ends up being done earlier so it happens in both halves of
the function.)

If we block all signals here, what causes us to unblock them
again?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 24/34] linux-user: Restart execve() if signal pending
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 24/34] linux-user: Restart execve() if signal pending Timothy E Baldwin
@ 2015-09-11 14:36   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-11 14:36 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Without this SIGTERM could fail to terminate the process, as the
> signal lost in QEMU's queue.
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/syscall.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 1ce381e..4839154 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -702,6 +702,7 @@ safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
>      struct rusage *, rusage)
>  safe_syscall4(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
>      int, options)
> +safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
>
>
>  static inline int host_to_target_sock_type(int host_type)
> @@ -5929,7 +5930,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>              }
>              if (!(p = lock_user_string(arg1)))
>                  goto execve_efault;
> -            ret = get_errno(execve(p, argp, envp));
> +            ret = safe_execve(p, argp, envp);
>              unlock_user(p, arg1, 0);
>
>              goto execve_end;

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

but should this be earlier in the patch series?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 25/34] linux-user: Restart exit() if signal pending
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 25/34] linux-user: Restart exit() " Timothy E Baldwin
@ 2015-09-11 14:36   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-11 14:36 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Without this a signal could vanish on thread exit.
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/syscall.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 4839154..efe61e3 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -5719,8 +5719,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>             However in threaded applictions it is used for thread termination,
>             and _exit_group is used for application termination.
>             Do thread termination if we have more then one thread.  */
> -        /* FIXME: This probably breaks if a signal arrives.  We should probably
> -           be disabling signals.  */
> +
> +        if (block_signals()) {
> +            ret = -TARGET_ERESTARTSYS;
> +            break;
> +        }
> +
>          if (CPU_NEXT(first_cpu)) {
>              TaskState *ts;
>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 27/34] linux-user: pause() should not pause if signal pending
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 27/34] linux-user: pause() should not pause " Timothy E Baldwin
@ 2015-09-11 14:36   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-11 14:36 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/syscall.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index da6d140..f89b730 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -6106,7 +6106,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
>  #endif
>  #ifdef TARGET_NR_pause /* not on alpha */
>      case TARGET_NR_pause:
> -        ret = get_errno(pause());
> +        if (!block_signals()) {
> +            sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
> +        }
> +        ret = -TARGET_EINTR;
>          break;
>  #endif
>  #ifdef TARGET_NR_utime
> --
> 2.1.4

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 28/34] linux-user: Restart sigaction() if signal pending
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 28/34] linux-user: Restart sigaction() " Timothy E Baldwin
@ 2015-09-11 14:37   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-11 14:37 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
> ---
>  linux-user/signal.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index 15bd082..fc37f3b 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -629,7 +629,7 @@ out:
>      return ret;
>  }
>
> -/* do_sigaction() return host values and errnos */
> +/* do_sigaction() return target values and host errnos */
>  int do_sigaction(int sig, const struct target_sigaction *act,
>                   struct target_sigaction *oact)
>  {
> @@ -638,8 +638,14 @@ int do_sigaction(int sig, const struct target_sigaction *act,
>      int host_sig;
>      int ret = 0;
>
> -    if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP)
> -        return -EINVAL;
> +    if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
> +        return -TARGET_EINVAL;
> +    }
> +
> +    if (block_signals()) {
> +        return -TARGET_ERESTARTSYS;
> +    }
> +
>      k = &sigact_table[sig - 1];
>  #if defined(DEBUG_SIGNAL)
>      fprintf(stderr, "sigaction sig=%d act=0x%p, oact=0x%p\n",

This doesn't look right -- we change this function from returning
host errnos to returning guest errnos, but we haven't changed any
of its callers.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 20/34] linux-user: Remove redundant default action check in queue_signal()
  2015-09-05 23:57 ` [Qemu-devel] [PATCH 20/34] linux-user: Remove redundant default action check in queue_signal() Timothy E Baldwin
@ 2015-09-11 14:41   ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2015-09-11 14:41 UTC (permalink / raw)
  To: Timothy E Baldwin; +Cc: Riku Voipio, QEMU Developers

On 6 September 2015 at 00:57, Timothy E Baldwin
<T.E.Baldwin99@members.leeds.ac.uk> wrote:
> Both queue_signal() and process_pending_signals() did check for default
> actions of signals, this is redundant and also causes fatal and stopping
> signals to incorrectly cause guest system calls to be interrupted.
>
> The code in queue_signal() is removed.
>
> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>

Is it really OK to always queue signals? This doesn't seem obviously
true to me, so some explanation of why it is would be helpful.

Also it looks like you've lost the handling of "we got a SIGSEGV
but the guest has blocked SIGSEGV".

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART
  2015-09-10 18:00 ` [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Peter Maydell
@ 2015-10-02 11:52   ` Riku Voipio
  0 siblings, 0 replies; 76+ messages in thread
From: Riku Voipio @ 2015-10-02 11:52 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Timothy E Baldwin, QEMU Developers

Hi Timothy,

On Thu, Sep 10, 2015 at 07:00:18PM +0100, Peter Maydell wrote:
> On 6 September 2015 at 00:56, Timothy E Baldwin
> <T.E.Baldwin99@members.leeds.ac.uk> wrote:
> > There are many races with signals in linux user:
> >
> >  - Multiple host signals in quick succession, fixed by keeping host signals
> >    blocked, and checking if target signals are blocked before calling
> >    target signal handler.
> >  - Signal shortly before blocking system call, fixed by either:
> >    - Block hosts signals, check and use host system call with
> >      sigset_t parameter.
> >    - Or check if signals are pending immediately before host system call
> >      and if a signal arrives between the check and system call rewind
> >      host instruction pointer to before the check. Also fixes SA_RESTART.
> >  - Signal before or during sensitive system call, fixed in a similar manner.
> >  - Close host and synchronous signals, partly fixed by implementing a separate
> >    queue for synchronous signals which are dispatched first. The asynchronous
> >    signal may still be delayed or lost rather than dispatched to another thread
> >    or handled after exec().
> >
> > Also fixed:
> >  - Errno array bounds.
> >  - Default fatal actions occurring in the middle of target instructions.
> 
> Thanks for sending this patchset. This is really cool and we've needed
> it for a long time...

Indeed, this would be nice to have for Qemu 2.5. Do you have time to
work through Peters comments and send an updated round of patches?

Riku

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

* Re: [Qemu-devel] [PATCH 01/34] linux-user: Fix array bounds in errno conversion
  2015-09-11 10:59   ` Peter Maydell
@ 2015-10-12 13:42     ` Riku Voipio
  2015-10-31  2:51       ` Laurent Vivier
  0 siblings, 1 reply; 76+ messages in thread
From: Riku Voipio @ 2015-10-12 13:42 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Timothy E Baldwin, QEMU Developers

On perjantaina 11. syyskuuta 2015 13.59.29 EEST, Peter Maydell wrote:
> On 6 September 2015 at 00:56, Timothy E Baldwin
> <T.E.Baldwin99@members.leeds.ac.uk> wrote:
>> Check array bounds in host_to_target_errno() and target_to_host_errno().
>> 
>> Signed-off-by: Timothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
>> ---
>>  linux-user/syscall.c | 4 ++--
>>  1 file changed, 2 insertions(+), 2 deletions(-) ...
>
> Maybe we should also check that the passed in error value is
> not negative? (Given the errno-is-positive/syscall-return-negative
> conventions, it's an easy mistake to make...)

I've applied a version of this patch that implements this by setting the 
function argument to unsigned

Riku

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

* Re: [Qemu-devel] [PATCH 01/34] linux-user: Fix array bounds in errno conversion
  2015-10-12 13:42     ` Riku Voipio
@ 2015-10-31  2:51       ` Laurent Vivier
  0 siblings, 0 replies; 76+ messages in thread
From: Laurent Vivier @ 2015-10-31  2:51 UTC (permalink / raw)
  To: Riku Voipio, Peter Maydell; +Cc: Timothy E Baldwin, QEMU Developers



Le 12/10/2015 15:42, Riku Voipio a écrit :
> On perjantaina 11. syyskuuta 2015 13.59.29 EEST, Peter Maydell wrote:
>> On 6 September 2015 at 00:56, Timothy E Baldwin
>> <T.E.Baldwin99@members.leeds.ac.uk> wrote:
>>> Check array bounds in host_to_target_errno() and target_to_host_errno().
>>>
>>> Signed-off-by: Timothy Edward Baldwin
>>> <T.E.Baldwin99@members.leeds.ac.uk>
>>> ---
>>>  linux-user/syscall.c | 4 ++--
>>>  1 file changed, 2 insertions(+), 2 deletions(-) ...
>>
>> Maybe we should also check that the passed in error value is
>> not negative? (Given the errno-is-positive/syscall-return-negative
>> conventions, it's an easy mistake to make...)
> 
> I've applied a version of this patch that implements this by setting the
> function argument to unsigned
> 
> Riku
> 
> 
This patch breaks get_errno().

On a 64bit target, if errno is 22, host_to_target_errno(22) is (unsigned
int)-22 = 0xffffffea, and get_errno() is (abi_long)0xffffffea =
0x000000000xffffffea = 4294967274. It is not negative, and thus is not
an error.

host_to_target_errno() and target_to_host_errno() must stay signed.

Laurent

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

* Re: [Qemu-devel] [PATCH 10/34] linux-user: Support for restarting system calls for Microblaze targets
  2015-09-10 18:14   ` Peter Maydell
@ 2016-03-03 20:15     ` Peter Maydell
  2016-03-04  0:27       ` Edgar E. Iglesias
  0 siblings, 1 reply; 76+ messages in thread
From: Peter Maydell @ 2016-03-03 20:15 UTC (permalink / raw)
  To: Edgar E. Iglesias; +Cc: Riku Voipio, QEMU Developers, Timothy E Baldwin

Hi Edgar -- I'm just looking back at these signal handling
race condition fix patches, and with this one I have a confusion
about the Microblaze Linux syscall code that I hope you can
clear up for me.

Looking at the kernel entry.S code it looks to me like
the way syscalls work on microblaze is:
 * syscall insn is brki r14
 * the insn itself saves the PC of the brki into r14
 * on entry the kernel advances r14 by 4 to skip the brki
 * then SAVE_REGS saves r14 into the 'PC' slot in the pt_regs
   struct
 * for syscall restart handle_restart() may wind the PC
   value in the pt_regs back by 4
 * in any case, on syscall exit we pull the PC value out of
   pt_regs into r14, and do a return with rtbd r14, 0

I think what this implies is that:
 * r14 is a "used by the kernel, may be corrupted at any
   time, not to be touched by userspace" register
 * on exit from a syscall PC and r14 are always the same
 * this includes do_sigreturn, ie "taking a signal" is one
   of the things that can corrupt r14

Is that right?

(For context, the original patch is this one:
http://patchwork.ozlabs.org/patch/514879/
and I now suspect my review comments at the time to be wrong.)

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH 10/34] linux-user: Support for restarting system calls for Microblaze targets
  2016-03-03 20:15     ` Peter Maydell
@ 2016-03-04  0:27       ` Edgar E. Iglesias
  2016-03-04 10:11         ` Peter Maydell
  0 siblings, 1 reply; 76+ messages in thread
From: Edgar E. Iglesias @ 2016-03-04  0:27 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Riku Voipio, QEMU Developers, Timothy E Baldwin

On Thu, Mar 03, 2016 at 08:15:13PM +0000, Peter Maydell wrote:
> Hi Edgar -- I'm just looking back at these signal handling
> race condition fix patches, and with this one I have a confusion
> about the Microblaze Linux syscall code that I hope you can
> clear up for me.
> 
> Looking at the kernel entry.S code it looks to me like
> the way syscalls work on microblaze is:
>  * syscall insn is brki r14
>  * the insn itself saves the PC of the brki into r14
>  * on entry the kernel advances r14 by 4 to skip the brki
>  * then SAVE_REGS saves r14 into the 'PC' slot in the pt_regs
>    struct
>  * for syscall restart handle_restart() may wind the PC
>    value in the pt_regs back by 4
>  * in any case, on syscall exit we pull the PC value out of
>    pt_regs into r14, and do a return with rtbd r14, 0

Yes, that sounds right.

> 
> I think what this implies is that:
>  * r14 is a "used by the kernel, may be corrupted at any
>    time, not to be touched by userspace" register

Yes. r14 is not really usable by user-space, interrupts will for example clobber r14 at any time aswell.

>  * on exit from a syscall PC and r14 are always the same

Yes that's how it works but as far as user-space is concerned r14 may have any value at any time as it's not really observable in a safe way.

>  * this includes do_sigreturn, ie "taking a signal" is one
>    of the things that can corrupt r14

Yes.

> 
> Is that right?

Yes, I think so.

> (For context, the original patch is this one:
> http://patchwork.ozlabs.org/patch/514879/
> and I now suspect my review comments at the time to be wrong.)

I see. Functionally I think the patch is OK. It seems to have some whitespace fixes mixed with functional changes (nitpick). Either way:

Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>

Best regards,
Edgar

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

* Re: [Qemu-devel] [PATCH 10/34] linux-user: Support for restarting system calls for Microblaze targets
  2016-03-04  0:27       ` Edgar E. Iglesias
@ 2016-03-04 10:11         ` Peter Maydell
  0 siblings, 0 replies; 76+ messages in thread
From: Peter Maydell @ 2016-03-04 10:11 UTC (permalink / raw)
  To: Edgar E. Iglesias; +Cc: Riku Voipio, QEMU Developers, Timothy E Baldwin

On 4 March 2016 at 00:27, Edgar E. Iglesias <edgar.iglesias@gmail.com> wrote:
> On Thu, Mar 03, 2016 at 08:15:13PM +0000, Peter Maydell wrote:
>> Hi Edgar -- I'm just looking back at these signal handling
>> race condition fix patches, and with this one I have a confusion
>> about the Microblaze Linux syscall code that I hope you can
>> clear up for me.
>>
>> Looking at the kernel entry.S code it looks to me like
>> the way syscalls work on microblaze is:

> Yes, that sounds right.

Thanks for the confirmation.

>> (For context, the original patch is this one:
>> http://patchwork.ozlabs.org/patch/514879/
>> and I now suspect my review comments at the time to be wrong.)
>
> I see. Functionally I think the patch is OK. It seems to have
> some whitespace fixes mixed with functional changes (nitpick).

It also fixes a bug in do_sigreturn -- you'll notice that
previously we were returning env->regs[10] and so would
corrupt the guest r3 with the guest r10 value. Switching to
using -TARGET_QEMU_ESIGRETURN avoids that.

> Either way:
>
> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>

(I'm going to add a brief comment about why not updating r14 is ok.)

Thanks
-- PMM

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

end of thread, other threads:[~2016-03-04 10:11 UTC | newest]

Thread overview: 76+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-05 23:56 [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Timothy E Baldwin
2015-09-05 23:56 ` [Qemu-devel] [PATCH 01/34] linux-user: Fix array bounds in errno conversion Timothy E Baldwin
2015-09-10 18:04   ` Peter Maydell
2015-09-11 10:59   ` Peter Maydell
2015-10-12 13:42     ` Riku Voipio
2015-10-31  2:51       ` Laurent Vivier
2015-09-05 23:56 ` [Qemu-devel] [PATCH 02/34] linux-user: Reindent signal handling Timothy E Baldwin
2015-09-05 23:56 ` [Qemu-devel] [PATCH 03/34] linux-user: Support for restarting system calls Timothy E Baldwin
2015-09-10 18:08   ` Peter Maydell
2015-09-05 23:56 ` [Qemu-devel] [PATCH 04/34] linux-user: Support for restarting system calls for x86 targets Timothy E Baldwin
2015-09-10 18:08   ` Peter Maydell
2015-09-05 23:56 ` [Qemu-devel] [PATCH 05/34] linux-user: Support for restarting system calls for ARM targets Timothy E Baldwin
2015-09-10 18:09   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 06/34] linux-user: Support for restarting system calls for MIPS targets Timothy E Baldwin
2015-09-10 18:09   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 07/34] linux-user: Support for restarting system calls for PPC targets Timothy E Baldwin
2015-09-10 18:10   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 08/34] linux-user: Support for restarting system calls for SPARC targets Timothy E Baldwin
2015-09-10 18:10   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 09/34] linux-user: Test for restarting system calls Timothy E Baldwin
2015-09-10 18:12   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 10/34] linux-user: Support for restarting system calls for Microblaze targets Timothy E Baldwin
2015-09-10 18:14   ` Peter Maydell
2016-03-03 20:15     ` Peter Maydell
2016-03-04  0:27       ` Edgar E. Iglesias
2016-03-04 10:11         ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 11/34] linux-user: Support for restarting system calls for SH4 targets Timothy E Baldwin
2015-09-10 18:15   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 12/34] linux-user: Support for restarting system calls for APLHA targets Timothy E Baldwin
2015-09-10 18:16   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 13/34] linux-user: Fix signal before blocking system calls race and SA_RESTART Timothy E Baldwin
2015-09-10 18:46   ` Peter Maydell
2015-09-11 10:57   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 14/34] linux-user: Use safe_syscall for read and write system calls Timothy E Baldwin
2015-09-10 18:48   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 15/34] linux-user: Remove redundant get_errno() calls Timothy E Baldwin
2015-09-10 18:50   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 16/34] linux-user: Use safe_syscall for open and openat system calls Timothy E Baldwin
2015-09-10 18:54   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 17/34] linux-user: Use safe_syscall for wait " Timothy E Baldwin
2015-09-10 18:58   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 18/34] linux-user: Fix race between multiple signals Timothy E Baldwin
2015-09-11 14:30   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 19/34] linux-user: Restart fork() if signals pending Timothy E Baldwin
2015-09-11 14:34   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 20/34] linux-user: Remove redundant default action check in queue_signal() Timothy E Baldwin
2015-09-11 14:41   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 21/34] linux-user: Remove redundant gdb_queuesig() Timothy E Baldwin
2015-09-05 23:57 ` [Qemu-devel] [PATCH 22/34] linux-user: Remove real-time signal queuing Timothy E Baldwin
2015-09-05 23:57 ` [Qemu-devel] [PATCH 23/34] linux-user: Queue synchronous signals separately Timothy E Baldwin
2015-09-05 23:57 ` [Qemu-devel] [PATCH 24/34] linux-user: Restart execve() if signal pending Timothy E Baldwin
2015-09-11 14:36   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 25/34] linux-user: Restart exit() " Timothy E Baldwin
2015-09-11 14:36   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 26/34] linux-user: Restart kill() " Timothy E Baldwin
2015-09-05 23:57 ` [Qemu-devel] [PATCH 27/34] linux-user: pause() should not pause " Timothy E Baldwin
2015-09-11 14:36   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 28/34] linux-user: Restart sigaction() " Timothy E Baldwin
2015-09-11 14:37   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 29/34] linux-user: Support for restarting system calls for UniCore32 targets Timothy E Baldwin
2015-09-10 19:05   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 30/34] linux-user: Support for restarting system calls for OpenRISC targets Timothy E Baldwin
2015-09-10 19:06   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 31/34] linux-user: Support for restarting system calls for M68K targets Timothy E Baldwin
2015-09-10 19:06   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 32/34] linux-user: Support for restarting system calls for S390 targets Timothy E Baldwin
2015-09-10 19:07   ` Peter Maydell
2015-09-05 23:57 ` [Qemu-devel] [PATCH 33/34] linux-user: Support for restarting system calls for CRIS targets Timothy E Baldwin
2015-09-10 19:12   ` Peter Maydell
2015-09-11 14:18     ` Edgar E. Iglesias
2015-09-11 14:20       ` Peter Maydell
2015-09-11 14:26         ` Edgar E. Iglesias
2015-09-05 23:57 ` [Qemu-devel] [PATCH 34/34] linux-user: Remove TARGET_USE_ERESTARTSYS Timothy E Baldwin
2015-09-10 19:13   ` Peter Maydell
2015-09-10 18:00 ` [Qemu-devel] [PATCH 00/34] linux-user: Fix signal race conditions and SA_RESTART Peter Maydell
2015-10-02 11:52   ` Riku Voipio

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.