# From: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
# 
# s390 syscalls might be done by a "svc X" instruction (2 bytes
# in size) or a "exec X,Y" instruction (4 bytes in size).
# There is no way to read the size of the instruction via ptrace,
# so UML/s390 can't do syscall-restarting by resetting instruction
# pointer to the value before the syscall.
# Also, in most cases syscall number is hardcoded in the "SVC X"
# instruction, so there is no way to handle ERESTART_RESTARTBLOCK
# correctly by *really* restarting the syscall.
# s390 host has implemented TIF_RESTART_SVC-flag to handle the
# latter case.
# In UML we have to use TIF_RESTART_SVC for both cases.
# This patch implements TIF_RESTART_SVC in UML.
# 
# Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
Index: linux-2.6.17/arch/um/include/kern_util.h
===================================================================
--- linux-2.6.17.orig/arch/um/include/kern_util.h	2007-10-24 10:04:50.000000000 -0400
+++ linux-2.6.17/arch/um/include/kern_util.h	2007-11-19 11:13:31.000000000 -0500
@@ -65,7 +65,7 @@ extern void init_flush_vm(void);
 extern void *syscall_sp(void *t);
 extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
 extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs);
-extern void interrupt_end(void);
+extern int interrupt_end(void);
 extern void initial_thread_cb(void (*proc)(void *), void *arg);
 extern int debugger_signal(int status, int pid);
 extern void debugger_parent_signal(int status, int pid);
Index: linux-2.6.17/arch/um/os-Linux/skas/process.c
===================================================================
--- linux-2.6.17.orig/arch/um/os-Linux/skas/process.c	2007-10-24 10:04:50.000000000 -0400
+++ linux-2.6.17/arch/um/os-Linux/skas/process.c	2007-11-19 11:12:54.000000000 -0500
@@ -367,8 +367,12 @@ void userspace(struct uml_pt_regs *regs)
 			        printk(UM_KERN_ERR "userspace - child stopped "
 				       "with signal %d\n", sig);
 			}
+again:
 			pid = userspace_pid[0];
-			interrupt_end();
+			if(interrupt_end()){
+				handle_syscall(regs);
+				goto again;
+			}
 
 			/* Avoid -ERESTARTSYS handling in host */
 			if (PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET)
Index: linux-2.6.17/arch/um/kernel/process.c
===================================================================
--- linux-2.6.17.orig/arch/um/kernel/process.c	2007-10-24 10:04:50.000000000 -0400
+++ linux-2.6.17/arch/um/kernel/process.c	2007-11-19 11:14:10.000000000 -0500
@@ -111,12 +111,17 @@ void *_switch_to(void *prev, void *next,
 
 }
 
-void interrupt_end(void)
+int interrupt_end(void)
 {
 	if (need_resched())
 		schedule();
 	if (test_tsk_thread_flag(current, TIF_SIGPENDING))
 		do_signal();
+#ifdef TIF_RESTART_SVC
+	return test_and_clear_tsk_thread_flag(current, TIF_RESTART_SVC);
+#else
+	return 0;
+#endif
 }
 
 void exit_thread(void)