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 #include +#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 +#include + +#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))