[PATCH]: Fix syscall restart handling on sparc*-linux

David Miller davem@davemloft.net
Sun May 11 22:44:00 GMT 2008


From: Mark Kettenis <mark.kettenis@xs4all.nl>
Date: Sun, 11 May 2008 22:33:34 +0200 (CEST)

> > Date: Sun, 11 May 2008 13:18:50 -0700 (PDT)
> > From: David Miller <davem@davemloft.net>
> > 
> > The write_pc target method simply clears the bit, which does nothing
> > on previous kernels, but cancels syscall restart on newer kernels.
> > 
> > This fixes 40 or so testsuite failures.
> > 
> > Ok to commit?
> 
> I wouldn't mind a #define for these bits.  Otherwise, it looks fine to me.

Done, and installed as follows:

2008-05-11  David S. Miller  <davem@davemloft.net>

	* sparc-linux-tdep.c (PSR_SYSCALL): Define.
	(sparc_linux_write_pc): New function.
	(sparc32_linux_init_abi): Register it.
	* sparc64-linux-tdep.c (TSTATE_SYSCALL): Define.
	(sparc64_linux_write_pc): New function.
	(sparc64_linux_init_abi): Register it.

Index: gdb/sparc-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc-linux-tdep.c,v
retrieving revision 1.26
diff -u -r1.26 sparc-linux-tdep.c
--- gdb/sparc-linux-tdep.c	11 May 2008 20:03:25 -0000	1.26
+++ gdb/sparc-linux-tdep.c	11 May 2008 22:09:09 -0000
@@ -211,6 +211,32 @@
   sparc32_collect_fpregset (regcache, regnum, fpregs);
 }
 
+/* Set the program counter for process PTID to PC.  */
+
+#define PSR_SYSCALL	0x00004000
+
+static void
+sparc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+  ULONGEST psr;
+
+  regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
+  regcache_cooked_write_unsigned (regcache, tdep->npc_regnum, pc + 4);
+
+  /* Clear the "in syscall" bit to prevent the kernel from
+     messing with the PCs we just installed, if we happen to be
+     within an interrupted system call that the kernel wants to
+     restart.
+
+     Note that after we return from the dummy call, the PSR et al.
+     registers will be automatically restored, and the kernel
+     continues to restart the system call at this point.  */
+  regcache_cooked_read_unsigned (regcache, SPARC32_PSR_REGNUM, &psr);
+  psr &= ~PSR_SYSCALL;
+  regcache_cooked_write_unsigned (regcache, SPARC32_PSR_REGNUM, psr);
+}
+
 
 
 static void
@@ -251,6 +277,8 @@
 
   /* Hook in the DWARF CFI frame unwinder.  */
   dwarf2_append_unwinders (gdbarch);
+
+  set_gdbarch_write_pc (gdbarch, sparc_linux_write_pc);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
Index: gdb/sparc64-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc64-linux-tdep.c,v
retrieving revision 1.20
diff -u -r1.20 sparc64-linux-tdep.c
--- gdb/sparc64-linux-tdep.c	11 May 2008 20:03:26 -0000	1.20
+++ gdb/sparc64-linux-tdep.c	11 May 2008 22:09:09 -0000
@@ -174,6 +174,32 @@
   sparc64_collect_fpregset (regcache, regnum, fpregs);
 }
 
+/* Set the program counter for process PTID to PC.  */
+
+#define TSTATE_SYSCALL	0x0000000000000020ULL
+
+static void
+sparc64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+  ULONGEST state;
+
+  regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
+  regcache_cooked_write_unsigned (regcache, tdep->npc_regnum, pc + 4);
+
+  /* Clear the "in syscall" bit to prevent the kernel from
+     messing with the PCs we just installed, if we happen to be
+     within an interrupted system call that the kernel wants to
+     restart.
+
+     Note that after we return from the dummy call, the TSTATE et al.
+     registers will be automatically restored, and the kernel
+     continues to restart the system call at this point.  */
+  regcache_cooked_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state);
+  state &= ~TSTATE_SYSCALL;
+  regcache_cooked_write_unsigned (regcache, SPARC64_STATE_REGNUM, state);
+}
+
 
 
 static void
@@ -211,6 +237,8 @@
 
   /* Make sure we can single-step over signal return system calls.  */
   tdep->step_trap = sparc64_linux_step_trap;
+
+  set_gdbarch_write_pc (gdbarch, sparc64_linux_write_pc);
 }
 
 



More information about the Gdb-patches mailing list