[Iohack-users 36] signal.c の変更

Back to archive index

Kaz Kojima kkoji****@rr*****
2004年 11月 6日 (土) 21:47:20 JST


小島です。

LANDISK kernel の arch/sh/kernel/signal.c のパッチです。

--
--- ../HDLSRC42/kernel/latest/linux-2.4.21-iodata/arch/sh/kernel/signal.c	2003-10-24 22:24:13.000000000 +0900
+++ arch/sh/kernel/signal.c	2004-11-05 23:19:50.000000000 +0900
@@ -167,20 +167,22 @@ sys_sigaltstack(const stack_t *uss, stac
  * Do a signal return; undo the signal stack.
  */
 
+#define MOVW(n)  (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
+#define TRAP16   0xc310		  /* Syscall w/no args (NR in R3) */
+#define OR_R0_R0 0x200b		  /* or r0,r0 (insert to avoid hardware bug) */
+
 struct sigframe
 {
 	struct sigcontext sc;
 	unsigned long extramask[_NSIG_WORDS-1];
-	char retcode[4];
+	u16 retcode[8];
 };
 
 struct rt_sigframe
 {
-	struct siginfo *pinfo;
-	void *puc;
 	struct siginfo info;
 	struct ucontext uc;
-	char retcode[4];
+	u16 retcode[8];
 };
 
 #if defined(__SH4__)
@@ -406,15 +408,16 @@ static void setup_frame(int sig, struct 
 	if (ka->sa.sa_flags & SA_RESTORER) {
 		regs->pr = (unsigned long) ka->sa.sa_restorer;
 	} else {
-		/* This is : mov  #__NR_sigreturn,r3 ; trapa #0x10 */
-#ifdef __LITTLE_ENDIAN__
-		unsigned long code = 0xc310e300 | (__NR_sigreturn);
-#else
-		unsigned long code = 0xe300c310 | (__NR_sigreturn << 16);
-#endif
-
+               /* Generate return code (system call to sigreturn) */
+		err |= __put_user(MOVW(7), &frame->retcode[0]);
+		err |= __put_user(TRAP16, &frame->retcode[1]);
+		err |= __put_user(OR_R0_R0, &frame->retcode[2]);
+		err |= __put_user(OR_R0_R0, &frame->retcode[3]);
+		err |= __put_user(OR_R0_R0, &frame->retcode[4]);
+		err |= __put_user(OR_R0_R0, &frame->retcode[5]);
+		err |= __put_user(OR_R0_R0, &frame->retcode[6]);
+		err |= __put_user((__NR_sigreturn), &frame->retcode[7]);
 		regs->pr = (unsigned long) frame->retcode;
-		err |= __put_user(code, (long *)(frame->retcode+0));
 	}
 
 	if (err)
@@ -423,7 +426,9 @@ static void setup_frame(int sig, struct 
 	/* Set up registers for signal handler */
 	regs->regs[15] = (unsigned long) frame;
 	regs->regs[4] = signal; /* Arg for signal handler */
-	regs->pc = (unsigned long) ka->sa.sa_handler;
+	regs->regs[5] = 0;
+	regs->regs[6] = (unsigned long) &frame->sc;
+ 	regs->pc = (unsigned long) ka->sa.sa_handler;
 
 	set_fs(USER_DS);
 
@@ -433,7 +438,9 @@ static void setup_frame(int sig, struct 
 #endif
 
 	flush_cache_sigtramp(regs->pr);
-	return;
+	if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
+		flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
+ 	return;
 
 give_sigsegv:
 	if (sig == SIGSEGV)
@@ -459,8 +466,6 @@ static void setup_rt_frame(int sig, stru
 		? current->exec_domain->signal_invmap[sig]
 		: sig;
 
-	err |= __put_user(&frame->info, &frame->pinfo);
-	err |= __put_user(&frame->uc, &frame->puc);
 	err |= copy_siginfo_to_user(&frame->info, info);
 
 	/* Create the ucontext.  */
@@ -480,15 +485,16 @@ static void setup_rt_frame(int sig, stru
 	if (ka->sa.sa_flags & SA_RESTORER) {
 		regs->pr = (unsigned long) ka->sa.sa_restorer;
 	} else {
-		/* This is : mov  #__NR_rt_sigreturn,r3 ; trapa #0x10 */
-#ifdef __LITTLE_ENDIAN__
-		unsigned long code = 0xc310e300 | (__NR_rt_sigreturn);
-#else
-		unsigned long code = 0xe300c310 | (__NR_rt_sigreturn << 16);
-#endif
-
+		/* Generate return code (system call to rt_sigreturn) */
+		err |= __put_user(MOVW(7), &frame->retcode[0]);
+		err |= __put_user(TRAP16, &frame->retcode[1]);
+		err |= __put_user(OR_R0_R0, &frame->retcode[2]);
+		err |= __put_user(OR_R0_R0, &frame->retcode[3]);
+		err |= __put_user(OR_R0_R0, &frame->retcode[4]);
+		err |= __put_user(OR_R0_R0, &frame->retcode[5]);
+		err |= __put_user(OR_R0_R0, &frame->retcode[6]);
+		err |= __put_user((__NR_rt_sigreturn), &frame->retcode[7]);
 		regs->pr = (unsigned long) frame->retcode;
-		err |= __put_user(code, (long *)(frame->retcode+0));
 	}
 
 	if (err)
@@ -497,6 +503,8 @@ static void setup_rt_frame(int sig, stru
 	/* Set up registers for signal handler */
 	regs->regs[15] = (unsigned long) frame;
 	regs->regs[4] = signal; /* Arg for signal handler */
+	regs->regs[5] = (unsigned long)&frame->info;    /* Arg2 (siginfo) */
+	regs->regs[6] = (unsigned long)&frame->uc;      /* Arg3 (context) */
 	regs->pc = (unsigned long) ka->sa.sa_handler;
 
 	set_fs(USER_DS);
@@ -507,7 +515,9 @@ static void setup_rt_frame(int sig, stru
 #endif
 
 	flush_cache_sigtramp(regs->pr);
-	return;
+	if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
+        	flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
+ 	return;
 
 give_sigsegv:
 	if (sig == SIGSEGV)



Iohack-users メーリングリストの案内
Back to archive index