[rfc patch] i386: don't save eflags on task switch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



There is no real need to save eflags in switch_to().  Instead,
we can keep a constant value in the thread_struct and always
restore that.

This will cause a behavior change, though.  If a user sets
NT in eflags and then enters the kernel via sysenter, and
another task runs before the syscall returns:

        (1) If we return via the iret path then no fault
        will occur (currently the user gets a fault.)

        (2) If we return via sysexit, NT will be cleared
        (currently it remains set.)

Users shouldn't be setting NT anyway, so this shouldn't be a
problem.

On a K8 CPU, this patch didn't lower the minimum task-switch
time, but it did lower the average and removed most of the
variability.  It really needs testing on a P4, where it should
have much more effect.

Signed-off-by: Chuck Ebbert <[email protected]>
---

 arch/i386/kernel/ioport.c    |    7 ++++---
 include/asm-i386/processor.h |    5 +++--
 include/asm-i386/system.h    |    4 ++--
 3 files changed, 9 insertions(+), 7 deletions(-)

--- 2.6.19-rc4-32smp.orig/arch/i386/kernel/ioport.c	2006-08-27 11:30:50.000000000 -0400
+++ 2.6.19-rc4-32smp/arch/i386/kernel/ioport.c	2006-11-02 00:46:03.925570520 -0500
@@ -146,8 +146,9 @@ asmlinkage long sys_iopl(unsigned long u
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 	}
-	t->iopl = level << 12;
-	regs->eflags = (regs->eflags & ~X86_EFLAGS_IOPL) | t->iopl;
-	set_iopl_mask(t->iopl);
+	t->eflags = level << 12 | X86_EFLAGS_IF | 2;
+	regs->eflags = (regs->eflags & ~X86_EFLAGS_IOPL) |
+		       (t->eflags & X86_EFLAGS_IOPL);
+	set_iopl_mask(t->eflags);
 	return 0;
 }
--- 2.6.19-rc4-32smp.orig/include/asm-i386/processor.h	2006-11-01 22:05:55.760728595 -0500
+++ 2.6.19-rc4-32smp/include/asm-i386/processor.h	2006-11-02 00:50:06.899235722 -0500
@@ -449,6 +449,7 @@ struct thread_struct {
 	unsigned long	sysenter_cs;
 	unsigned long	eip;
 	unsigned long	esp;
+ 	unsigned long	eflags;
 	unsigned long	fs;
 	unsigned long	gs;
 /* Hardware debugging registers */
@@ -464,7 +465,6 @@ struct thread_struct {
 	unsigned int		saved_fs, saved_gs;
 /* IO permissions */
 	unsigned long	*io_bitmap_ptr;
- 	unsigned long	iopl;
 /* max allowed port in the bitmap, in bytes: */
 	unsigned long	io_bitmap_max;
 };
@@ -534,7 +534,8 @@ static inline void set_iopl_mask(unsigne
 			      "pushl %0;"
 			      "popfl"
 				: "=&r" (reg)
-				: "i" (~X86_EFLAGS_IOPL), "r" (mask));
+				: "i" (~X86_EFLAGS_IOPL),
+				  "r" (mask & X86_EFLAGS_IOPL));
 }
 
 /* Forward declaration, a strange C thing */
--- 2.6.19-rc4-32smp.orig/include/asm-i386/system.h	2006-11-01 22:05:55.870730255 -0500
+++ 2.6.19-rc4-32smp/include/asm-i386/system.h	2006-11-02 00:54:54.863579599 -0500
@@ -17,7 +17,7 @@ extern struct task_struct * FASTCALL(__s
  */
 #define switch_to(prev,next,last) do {					\
 	unsigned long esi,edi;						\
-	asm volatile("pushfl\n\t"		/* Save flags */	\
+	asm volatile("pushl %9\n\t"		/* Save flags */	\
 		     "pushl %%ebp\n\t"					\
 		     "movl %%esp,%0\n\t"	/* save ESP */		\
 		     "movl %5,%%esp\n\t"	/* restore ESP */	\
@@ -30,7 +30,7 @@ extern struct task_struct * FASTCALL(__s
 		     :"=m" (prev->thread.esp),"=m" (prev->thread.eip),	\
 		      "=a" (last),"=S" (esi),"=D" (edi)			\
 		     :"m" (next->thread.esp),"m" (next->thread.eip),	\
-		      "2" (prev), "d" (next));				\
+		      "2" (prev), "d" (next), "m" (prev->thread.eflags));				\
 } while (0)
 
 #define _set_base(addr,base) do { unsigned long __pr; \
-- 
Chuck
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux