[PATCH] [Karmic] SRU: arm: fix singal restart when Old EABI enabled

Eric Miao eric.miao at canonical.com
Sun Dec 13 12:12:53 UTC 2009


Stefan,

This patch is verified to fix bug #453682 for Karmic on dove, although not yet
hit -stable.

>From 09f30d75269669eca5706fe2105196ee2f2c744c Mon Sep 17 00:00:00 2001
From: Russle King <rmk+kernel at arm.linux.org.uk>
Date: Tue, 27 Oct 2009 11:02:16 +0200
Subject: [PATCH] arm: fix singal restart when Old EABI enabled

Signed-off-by: Saeed Bishara <saeed at marvell.com>
---
 arch/arm/kernel/signal.c |   41 +++++++++++++++++------------------------
 arch/arm/kernel/signal.h |    4 +++-
 arch/arm/kernel/traps.c  |    4 +++-
 3 files changed, 23 insertions(+), 26 deletions(-)
 mode change 100644 => 100755 arch/arm/kernel/signal.c

diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
old mode 100644
new mode 100755
index f6bc5d4..b09af17
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/kernel/signal.c
  *
- *  Copyright (C) 1995-2002 Russell King
+ *  Copyright (C) 1995-2009 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -28,6 +28,7 @@
  */
 #define SWI_SYS_SIGRETURN	(0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE))
 #define SWI_SYS_RT_SIGRETURN	(0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE))
+#define SWI_SYS_RESTART		(0xef000000|__NR_restart_syscall|__NR_OABI_SYSCALL_BASE)

 /*
  * With EABI, the syscall number has to be loaded into r7.
@@ -50,6 +51,18 @@ const unsigned long sigreturn_codes[7] = {
 static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);

 /*
+ * Either we support OABI only, or we have EABI with the OABI
+ * compat layer enabled.  In the later case we don't know if
+ * user space is EABI or not, and if not we must not clobber r7.
+ * Always using the OABI syscall solves that issue and works for
+ * all those cases.
+ */
+const unsigned long syscall_restart_code[2] = {
+	SWI_SYS_RESTART,	/* swi	__NR_restart_syscall */
+	0xe49df004,		/* ldr	pc, [sp], #4 */
+};
+
+/*
  * atomically swap in the new signal mask, and wait for a signal.
  */
 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask,
old_sigset_t mask, struct pt_regs *regs)
@@ -663,32 +676,12 @@ static int do_signal(sigset_t *oldset, struct
pt_regs *regs, int syscall)
 				regs->ARM_pc -= 4;
 #else
 				u32 __user *usp;
-				u32 swival = __NR_restart_syscall;

-				regs->ARM_sp -= 12;
+				regs->ARM_sp -= 4;
 				usp = (u32 __user *)regs->ARM_sp;

-				/*
-				 * Either we supports OABI only, or we have
-				 * EABI with the OABI compat layer enabled.
-				 * In the later case we don't know if user
-				 * space is EABI or not, and if not we must
-				 * not clobber r7.  Always using the OABI
-				 * syscall solves that issue and works for
-				 * all those cases.
-				 */
-				swival = swival - __NR_SYSCALL_BASE + __NR_OABI_SYSCALL_BASE;
-
-				put_user(regs->ARM_pc, &usp[0]);
-				/* swi __NR_restart_syscall */
-				put_user(0xef000000 | swival, &usp[1]);
-				/* ldr	pc, [sp], #12 */
-				put_user(0xe49df00c, &usp[2]);
-
-				flush_icache_range((unsigned long)usp,
-						   (unsigned long)(usp + 3));
-
-				regs->ARM_pc = regs->ARM_sp + 4;
+				put_user(regs->ARM_pc, usp);
+				regs->ARM_pc = KERN_RESTART_CODE;
 #endif
 			}
 		}
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
index 27beece..6fcfe83 100644
--- a/arch/arm/kernel/signal.h
+++ b/arch/arm/kernel/signal.h
@@ -1,12 +1,14 @@
 /*
  *  linux/arch/arm/kernel/signal.h
  *
- *  Copyright (C) 2005 Russell King.
+ *  Copyright (C) 2005-2009 Russell King.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
 #define KERN_SIGRETURN_CODE	(CONFIG_VECTORS_BASE + 0x00000500)
+#define KERN_RESTART_CODE	(KERN_SIGRETURN_CODE + sizeof(sigreturn_codes))

 extern const unsigned long sigreturn_codes[7];
+extern const unsigned long syscall_restart_code[2];
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 57eb0f6..9cc19c9 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/kernel/traps.c
  *
- *  Copyright (C) 1995-2002 Russell King
+ *  Copyright (C) 1995-2009 Russell King
  *  Fragments that appear the same as linux/arch/i386/kernel/traps.c
(C) Linus Torvalds
  *
  * This program is free software; you can redistribute it and/or modify
@@ -742,6 +742,8 @@ void __init early_trap_init(void)
 	 */
 	memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
 	       sizeof(sigreturn_codes));
+	memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
+	       sizeof(syscall_restart_code));

 	flush_icache_range(vectors, vectors + PAGE_SIZE);
 	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
-- 
1.6.3.3




More information about the kernel-team mailing list