All of lore.kernel.org
 help / color / mirror / Atom feed
* PATCH: Make i386 signal delivery work with -mregparm
@ 2004-08-26 21:14 H. Peter Anvin
  0 siblings, 0 replies; only message in thread
From: H. Peter Anvin @ 2004-08-26 21:14 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-kernel

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

This patch allows i386 signal delivery to work correctly when userspace 
is compiled with -mregparm.  This is somewhat hacky: it passes the 
arguments *both* on the stack and in registers, but it works because 
there are only one or three (depending on SA_SIGINFO) official 
arguments.  If you're relying on the unofficial arguments then you're 
doing something nonportable anyway and can put in the 
__attribute__((cdecl,regparm(0))) in the correct place.

Patch against current top of tree (2.6.9-rc1).

	-hpa

[-- Attachment #2: signal-regparm.diff --]
[-- Type: text/x-patch, Size: 2619 bytes --]

Index: linux-2.5/arch/i386/kernel/signal.c
===================================================================
RCS file: /home/hpa/kernel/bkcvs/linux-2.5/arch/i386/kernel/signal.c,v
retrieving revision 1.42
diff -u -r1.42 signal.c
--- linux-2.5/arch/i386/kernel/signal.c	13 Jul 2004 18:02:33 -0000	1.42
+++ linux-2.5/arch/i386/kernel/signal.c	26 Aug 2004 06:50:40 -0000
@@ -345,18 +345,20 @@
 	void __user *restorer;
 	struct sigframe __user *frame;
 	int err = 0;
+	int usig;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	err |= __put_user((current_thread_info()->exec_domain
-		           && current_thread_info()->exec_domain->signal_invmap
-		           && sig < 32
-		           ? current_thread_info()->exec_domain->signal_invmap[sig]
-		           : sig),
-		          &frame->sig);
+	usig = current_thread_info()->exec_domain
+		&& current_thread_info()->exec_domain->signal_invmap
+		&& sig < 32
+		? current_thread_info()->exec_domain->signal_invmap[sig]
+		: sig;
+
+	err |= __put_user(usig, &frame->sig);
 	if (err)
 		goto give_sigsegv;
 
@@ -395,6 +397,9 @@
 	/* Set up registers for signal handler */
 	regs->esp = (unsigned long) frame;
 	regs->eip = (unsigned long) ka->sa.sa_handler;
+	regs->eax = (unsigned long) sig;
+	regs->edx = (unsigned long) 0;
+	regs->ecx = (unsigned long) 0;
 
 	set_fs(USER_DS);
 	regs->xds = __USER_DS;
@@ -422,18 +427,20 @@
 	void __user *restorer;
 	struct rt_sigframe __user *frame;
 	int err = 0;
+	int usig;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	err |= __put_user((current_thread_info()->exec_domain
-		    	   && current_thread_info()->exec_domain->signal_invmap
-		    	   && sig < 32
-		    	   ? current_thread_info()->exec_domain->signal_invmap[sig]
-			   : sig),
-			  &frame->sig);
+	usig = current_thread_info()->exec_domain
+		&& current_thread_info()->exec_domain->signal_invmap
+		&& sig < 32
+		? current_thread_info()->exec_domain->signal_invmap[sig]
+		: sig;
+
+	err |= __put_user(usig, &frame->sig);
 	err |= __put_user(&frame->info, &frame->pinfo);
 	err |= __put_user(&frame->uc, &frame->puc);
 	err |= copy_siginfo_to_user(&frame->info, info);
@@ -476,6 +483,9 @@
 	/* Set up registers for signal handler */
 	regs->esp = (unsigned long) frame;
 	regs->eip = (unsigned long) ka->sa.sa_handler;
+	regs->eax = (unsigned long) usig;
+	regs->edx = (unsigned long) &frame->info;
+	regs->ecx = (unsigned long) &frame->uc;
 
 	set_fs(USER_DS);
 	regs->xds = __USER_DS;

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2004-08-26 21:18 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-26 21:14 PATCH: Make i386 signal delivery work with -mregparm H. Peter Anvin

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.