Date: Wed, 3 Sep 1997 08:59:49 +0200 (CEST)
From: Geert Uytterhoeven <Geert.Uytterhoeven@cs.kuleuven.ac.be>
To: Jes Sorensen <Jes.Sorensen@cern.ch>
Cc: Linux/m68k <linux-m68k@phil.uni-sb.de>
Subject: Re: L68K: signal try 2
In-Reply-To: <199709021619.SAA28221@valhall.cern.ch>
Sender: owner-linux-m68k@phil.uni-sb.de
Reply-To: linux-m68k@phil.uni-sb.de

On Tue, 2 Sep 1997, Jes Sorensen wrote:
> If the patch I just sent you works, well ..... don't bother ;-)

At first it didn't work. Then I dug in my '040 manual and added the line

    _tmp1 &= ~(PAGE_SIZE - 1);

Now it works. CC to the list for our friends.

--- linux/arch/m68k/kernel/signal.c.orig	Thu Aug 28 23:05:16 1997
+++ linux/arch/m68k/kernel/signal.c	Tue Sep  2 21:25:09 1997
@@ -294,7 +294,7 @@
 
 	/* return address points to code on stack */
 
-	if(put_user((ulong)(frame+4), tframe))
+	if(put_user((unsigned long)(frame+4), tframe))
 		do_exit(SIGSEGV);
 	tframe++;
 	if (current->exec_domain && current->exec_domain->signal_invmap)
@@ -305,14 +305,81 @@
 
 	__put_user(regs->vector, tframe); tframe++;
 	/* "scp" parameter.  points to sigcontext */
-	__put_user((ulong)(frame+6), tframe); tframe++;
+	__put_user((unsigned long)(frame+6), tframe); tframe++;
 
 /* set up the return code... */
 	__put_user(0xdefc0014,tframe); tframe++; /* addaw #20,sp */
 	__put_user(0x70774e40,tframe); tframe++; /* moveq #119,d0; trap #0 */
+#if 0
 
 /* Flush caches so the instructions will be correctly executed. (MA) */
 	cache_push_v ((unsigned long)frame, (int)tframe - (int)frame);
+#else
+	/*
+	 * Using the old cache_push_v() was really a big waste.
+	 *
+	 * What we are trying to do is to flush 20 bytes to ram.
+	 * Flushing 3 cache lines of 16 bytes is much cheaper than
+	 * flushing 1 or 2 pages, as previously done in
+	 * cache_push_v(). I made it always flush 3 cache
+	 * lines since this is probably cheaper than the check for
+	 * whether we should flush the third line or not.
+	 *                                                     Jes
+	 */
+	if (CPU_IS_040){
+		int i;
+		unsigned long _tmp1, _tmp2;
+		unsigned long vaddr = (unsigned long) frame;
+
+		for (i = 0; i < 3; i++, vaddr += 16){
+
+			_tmp2 = vaddr & (PAGE_SIZE - 1);
+
+			__asm__ __volatile__ (".chip 68040\n\t"
+					      "nop\n\t"
+					      "ptestr (%1)\n\t"
+					      "movec %%mmusr,%0\n\t"
+					      ".chip 68k"
+					      : "=d" (_tmp1)
+					      : "a" (vaddr));
+
+			_tmp1 &= ~(PAGE_SIZE - 1);
+			_tmp1 |= _tmp2;
+
+			__asm__ __volatile__ (".chip 68040\n\t"
+					      "nop\n\t"
+					      "cpushl %%bc,(%0)\n\t"
+					      ".chip 68k"
+					      :
+					      : "a" (_tmp1));
+		}
+	}
+	else if (CPU_IS_060){
+		int i;
+		unsigned long _tmp;
+		unsigned long vaddr = (unsigned long) frame;
+
+		for (i = 0; i < 3; i++, vaddr += 16){
+			_tmp = vaddr;
+			__asm__ __volatile__ (".chip 68060\n\t"
+					      "plpar (%0)\n\t"
+					      "cpushl %%bc,(%0)\n\t"
+					      ".chip 68k"
+					      : "=a" (_tmp)
+					      : "0" (_tmp));
+		}
+	}
+	else
+		/*
+		 * 68030/68020 have no writeback cache;
+		 * still need to clear icache.
+		 */
+		asm volatile ("movec %/cacr,%/d0\n\t"
+			      "oriw %0,%/d0\n\t"
+			      "movec %/d0,%/cacr"
+			      : : "i" (FLUSH_I)
+			      : "d0");
+#endif
 
 /* setup and copy the sigcontext structure */
 	context.sc_mask       = oldmask;
@@ -324,14 +391,20 @@
 	context.sc_sr	      = regs->sr;
 	context.sc_pc	      = regs->pc;
 	context.sc_formatvec  = (regs->format << 12 | regs->vector);
-	__asm__ volatile ("fsave %0" : : "m" (*context.sc_fpstate) : "memory");
+	__asm__ volatile (".chip 68k/68881\n\t"
+			  "fsave %0\n\t"
+			  ".chip 68k"
+			  : : "m" (*context.sc_fpstate) : "memory");
+	
 	if ((!CPU_IS_060 && context.sc_fpstate[0]) || (CPU_IS_060 && context.sc_fpstate[2])){
 		fpu_version = context.sc_fpstate[0];
-		__asm__ volatile ("fmovemx %/fp0-%/fp1,%0\n\t"
-				  "fmoveml %/fpcr/%/fpsr/%/fpiar,%1"
+		__asm__ volatile (".chip 68k/68881\n\t"
+				  "fmovemx %/fp0-%/fp1,%0\n\t"
+				  "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t"
+				  ".chip 68k"
 				  : /* no outputs */
 				  : "m" (*context.sc_fpregs),
-				  "m" (*context.sc_fpcntl)
+				    "m" (*context.sc_fpcntl)
 				  : "memory");
 	}
 	if (copy_to_user (tframe, &context, sizeof(context)))

Greetings,

						Geert

--
Geert Uytterhoeven                     Geert.Uytterhoeven@cs.kuleuven.ac.be
Wavelets, Linux/{m68k~Amiga,PPC~CHRP}  http://www.cs.kuleuven.ac.be/~geert/
Department of Computer Science -- Katholieke Universiteit Leuven -- Belgium

