patch-2.1.109 linux/include/asm-i386/system.h

Next file: linux/include/asm-i386/vga.h
Previous file: linux/include/asm-i386/processor.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.108/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
@@ -1,6 +1,7 @@
 #ifndef __ASM_SYSTEM_H
 #define __ASM_SYSTEM_H
 
+#include <linux/kernel.h>
 #include <asm/segment.h>
 
 /*
@@ -35,83 +36,34 @@
 	:"=a" (n) \
 	:"0" (0),"i" (FIRST_TSS_ENTRY<<3))
 
-/* This special macro can be used to load a debugging register */
-
-#define loaddebug(tsk,register) \
-		__asm__("movl %0,%%db" #register  \
-			: /* no output */ \
-			:"r" (tsk->debugreg[register]))
-
+struct task_struct;	/* one of the stranger aspects of C forward declarations.. */
+extern void FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
 
 /*
- *	switch_to(n) should switch tasks to task nr n, first
- * checking that n isn't the current task, in which case it does nothing.
- * This also clears the TS-flag if the task we switched to has used
- * the math co-processor latest.
- *
- * It also reloads the debug regs if necessary..
+ * We do most of the task switching in C, but we need
+ * to do the EIP/ESP switch in assembly..
  */
-
- 
-#ifdef __SMP__
-	/*
-	 *	Keep the lock depth straight. If we switch on an interrupt from
-	 *	kernel->user task we need to lose a depth, and if we switch the
-	 *	other way we need to gain a depth. Same layer switches come out
-	 *	the same.
-	 *
-	 *	We spot a switch in user mode because the kernel counter is the
-	 *	same as the interrupt counter depth. (We never switch during the
-	 *	message/invalidate IPI).
-	 *
-	 *	We fsave/fwait so that an exception goes off at the right time
-	 *	(as a call from the fsave or fwait in effect) rather than to
-	 *	the wrong process.
-	 */
-
-#define switch_to(prev,next) do { \
-	if(prev->flags&PF_USEDFPU) \
-	{ \
-		__asm__ __volatile__("fnsave %0":"=m" (prev->tss.i387.hard)); \
-		__asm__ __volatile__("fwait"); \
-		prev->flags&=~PF_USEDFPU;	 \
-	} \
-__asm__("ljmp %0\n\t" \
-	: /* no output */ \
-	:"m" (*(((char *)&next->tss.tr)-4)), \
-	 "c" (next)); \
-	/* Now maybe reload the debug registers */ \
-	if(prev->debugreg[7]){ \
-		loaddebug(prev,0); \
-		loaddebug(prev,1); \
-		loaddebug(prev,2); \
-		loaddebug(prev,3); \
-		loaddebug(prev,6); \
-		loaddebug(prev,7); \
-	} \
-} while (0)
-
-#else
-#define switch_to(prev,next) do { \
-__asm__("ljmp %0\n\t" \
-	"cmpl %1,"SYMBOL_NAME_STR(last_task_used_math)"\n\t" \
-	"jne 1f\n\t" \
-	"clts\n" \
-	"1:" \
-	: /* no outputs */ \
-	:"m" (*(((char *)&next->tss.tr)-4)), \
-	 "r" (prev), "r" (next)); \
-	/* Now maybe reload the debug registers */ \
-	if(prev->debugreg[7]){ \
-		loaddebug(prev,0); \
-		loaddebug(prev,1); \
-		loaddebug(prev,2); \
-		loaddebug(prev,3); \
-		loaddebug(prev,6); \
-		loaddebug(prev,7); \
-	} \
+#define switch_to(prev,next) do {					\
+	unsigned long eax, edx, ecx;					\
+	asm volatile("pushl %%ebx\n\t"					\
+		     "pushl %%esi\n\t"					\
+		     "pushl %%edi\n\t"					\
+		     "pushl %%ebp\n\t"					\
+		     "movl %%esp,%0\n\t"	/* save ESP */		\
+		     "movl %5,%%esp\n\t"	/* restore ESP */	\
+		     "movl $1f,%1\n\t"		/* save EIP */		\
+		     "pushl %6\n\t"		/* restore EIP */	\
+		     "jmp __switch_to\n"				\
+		     "1:\t"						\
+		     "popl %%ebp\n\t"					\
+		     "popl %%edi\n\t"					\
+		     "popl %%esi\n\t"					\
+		     "popl %%ebx"					\
+		     :"=m" (prev->tss.esp),"=m" (prev->tss.eip),	\
+		      "=a" (eax), "=d" (edx), "=c" (ecx)		\
+		     :"m" (next->tss.esp),"m" (next->tss.eip),		\
+		      "a" (prev), "d" (next)); 				\
 } while (0)
-#endif
 
 #define _set_base(addr,base) \
 __asm__("movw %%dx,%0\n\t" \

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov