From: zippel@fh-brandenburg.de (Roman Zippel)
Subject: L68K: 2.1.77 fix
To: linux-m68k@lists.linux-m68k.org
Date: Mon, 12 Jan 1998 13:43:41 +0100 (MET)
Sender: owner-linux-m68k@phil.uni-sb.de

Hi,

The following patch fixes a stack problem during heavy interrupt
load. The interupt mask must not be lowered immediatly, only if
no other interrupt is waiting on the stack. I could easily reproduce
the problem by generating some high disk activity.
The patch also contains some improvements and first changes for the
fpu emulator (there are some more improvements possible, patches
will follow soon).

Roman

--- linux-2.1.77/arch/m68k/kernel/entry.S.old	Fri Jan  9 03:08:08 1998
+++ linux-2.1.77/arch/m68k/kernel/entry.S	Mon Jan 12 11:13:16 1998
@@ -37,6 +37,8 @@
 #include <asm/setup.h>
 #include <asm/segment.h>
 
+#include "m68k_defs.h"
+
 .globl SYMBOL_NAME(system_call), SYMBOL_NAME(buserr), SYMBOL_NAME(trap)
 .globl SYMBOL_NAME(resume), SYMBOL_NAME(ret_from_exception)
 .globl SYMBOL_NAME(ret_from_signal)
@@ -63,9 +65,7 @@
 
 ENTRY(reschedule)
 	| save top of frame
-	pea	%sp@
-	jbsr	SYMBOL_NAME(set_esp0)
-	addql	#4,%sp
+	movel	%sp,%curptr@(TS_ESP0)
 
 	pea	SYMBOL_NAME(ret_from_exception)
 	jmp	SYMBOL_NAME(schedule)
@@ -98,9 +98,7 @@
 
 	GET_CURRENT(%d0)
 	| save top of frame
-	pea	%sp@
-	jbsr	SYMBOL_NAME(set_esp0)
-	addql	#4,%sp
+	movel	%sp,%curptr@(TS_ESP0)
 
 	cmpl	#NR_syscalls,%d2
 	jcc	badsys
@@ -112,6 +110,10 @@
 SYMBOL_NAME_LABEL(ret_from_exception)
 	btst	#5,%sp@(LPT_OFF_SR)	| check if returning to kernel
 	bnes	2f			| if so, skip resched, signals
+	| only allow interrupts when we are really the last one on the
+	| kernel stack, otherwise stack overflow can occur during
+	| heavy interupt load
+	andw	#ALLOWINT,%sr
 	tstl	SYMBOL_NAME(need_resched)
 	jne	SYMBOL_NAME(reschedule)
 	cmpl	#SYMBOL_NAME(task),%curptr	| task[0] cannot have signals
@@ -178,11 +180,6 @@
 #endif
 	jhi	2b
 #endif
-	/* Let the rest run with interrupts allowed.  This is safe since
-	   the kernel never uses a non-standard ipl and this is the outer
-	   level interrupt. */
-	andw	#ALLOWINT,%sr
-
 	/* check if we need to do software interrupts */
 
 	movel	SYMBOL_NAME(bh_active),%d0
--- linux-2.1.77/arch/m68k/kernel/m68k_defs.c.old	Mon Jan 12 10:47:30 1998
+++ linux-2.1.77/arch/m68k/kernel/m68k_defs.c	Mon Jan 12 11:09:51 1998
@@ -0,0 +1,22 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#include <linux/stddef.h>
+#include <linux/sched.h>
+
+#define DEFINE(sym, val) \
+	asm volatile("\n#define " #sym " %0" : : "i" (val))
+
+void main(void)
+{
+	DEFINE(TS_TSS, offsetof(struct task_struct, tss));
+	DEFINE(TS_ESP0, offsetof(struct task_struct, tss.esp0));
+	DEFINE(TS_FPU, offsetof(struct task_struct, tss.fp));
+}
--- linux-2.1.77/arch/m68k/kernel/m68k_defs.head.old	Mon Jan 12 10:47:38 1998
+++ linux-2.1.77/arch/m68k/kernel/m68k_defs.head	Sat Jan  3 01:54:38 1998
@@ -0,0 +1,5 @@
+/*
+ * WARNING! This file is automatically generated - DO NOT EDIT!
+ */
+
+#define TS_MAGICKEY	0x5a5a5a5a
--- linux-2.1.77/arch/m68k/kernel/Makefile.old	Fri Jan  9 03:08:08 1998
+++ linux-2.1.77/arch/m68k/kernel/Makefile	Mon Jan 12 10:59:27 1998
@@ -10,7 +10,7 @@
 .S.o:
 	$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
 
-all: kernel.o head.o
+all: head.o kernel.o
 O_TARGET := kernel.o
 O_OBJS := entry.o process.o traps.o ints.o signal.o ptrace.o \
 	  setup.o sys_m68k.o time.o
@@ -27,6 +27,12 @@
 O_OBJS += bios32.o
 endif
 
-head.o: head.S
+head.o: head.S m68k_defs.h
+
+m68k_defs.h: m68k_defs.c m68k_defs.head $(TOPDIR)/include/linux/sched.h
+	$(CC) ${CFLAGS} -S m68k_defs.c
+	cp m68k_defs.head m68k_defs.h
+	sed -n < m68k_defs.s >> m68k_defs.h '/^#define/s/ #/ /p'
+	rm m68k_defs.s
 
 include $(TOPDIR)/Rules.make
--- linux-2.1.77/arch/m68k/kernel/traps.c.old	Fri Jan  9 03:08:08 1998
+++ linux-2.1.77/arch/m68k/kernel/traps.c	Mon Jan 12 11:11:38 1998
@@ -955,11 +955,6 @@
 	force_sig_info (sig, &info, current);
 }
 
-asmlinkage void set_esp0 (unsigned long ssp)
-{
-  current->tss.esp0 = ssp;
-}
-
 void die_if_kernel (char *str, struct pt_regs *fp, int nr)
 {
 	if (!(fp->sr & PS_S))
