From f1e88e5c9c24f04e49538e960ad3aba8a29abc16 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Sat, 3 Sep 2005 15:56:44 -0700 Subject: [PATCH] --- yaml --- r: 6985 b: refs/heads/master c: a5201129307f414890f9a4410e38da205f5d7359 h: refs/heads/master i: 6983: 0026af6e9e681d79ac9532eb28e38066ad1b7549 v: v3 --- [refs] | 2 +- trunk/arch/i386/kernel/ioport.c | 7 ++++--- trunk/arch/i386/kernel/process.c | 6 ++++++ trunk/include/asm-i386/processor.h | 16 ++++++++++++++++ trunk/include/asm-i386/system.h | 4 +--- 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/[refs] b/[refs] index fedd70e29021..1f904c8f77cc 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0998e4228aca046fbd747c3fed909791d52e88eb +refs/heads/master: a5201129307f414890f9a4410e38da205f5d7359 diff --git a/trunk/arch/i386/kernel/ioport.c b/trunk/arch/i386/kernel/ioport.c index 8b25160393c1..f2b37654777f 100644 --- a/trunk/arch/i386/kernel/ioport.c +++ b/trunk/arch/i386/kernel/ioport.c @@ -132,6 +132,7 @@ asmlinkage long sys_iopl(unsigned long unused) volatile struct pt_regs * regs = (struct pt_regs *) &unused; unsigned int level = regs->ebx; unsigned int old = (regs->eflags >> 12) & 3; + struct thread_struct *t = ¤t->thread; if (level > 3) return -EINVAL; @@ -140,8 +141,8 @@ asmlinkage long sys_iopl(unsigned long unused) if (!capable(CAP_SYS_RAWIO)) return -EPERM; } - regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12); - /* Make sure we return the long way (not sysenter) */ - set_thread_flag(TIF_IRET); + t->iopl = level << 12; + regs->eflags = (regs->eflags & ~X86_EFLAGS_IOPL) | t->iopl; + set_iopl_mask(t->iopl); return 0; } diff --git a/trunk/arch/i386/kernel/process.c b/trunk/arch/i386/kernel/process.c index 660997800393..b45cbf93d439 100644 --- a/trunk/arch/i386/kernel/process.c +++ b/trunk/arch/i386/kernel/process.c @@ -711,6 +711,12 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas if (prev->gs | next->gs) loadsegment(gs, next->gs); + /* + * Restore IOPL if needed. + */ + if (unlikely(prev->iopl != next->iopl)) + set_iopl_mask(next->iopl); + /* * Now maybe reload the debug registers */ diff --git a/trunk/include/asm-i386/processor.h b/trunk/include/asm-i386/processor.h index 992224bff549..37bef8ed7bed 100644 --- a/trunk/include/asm-i386/processor.h +++ b/trunk/include/asm-i386/processor.h @@ -455,6 +455,7 @@ 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; }; @@ -511,6 +512,21 @@ static inline void load_esp0(struct tss_struct *tss, struct thread_struct *threa : /* no output */ \ :"r" (value)) +/* + * Set IOPL bits in EFLAGS from given mask + */ +static inline void set_iopl_mask(unsigned mask) +{ + unsigned int reg; + __asm__ __volatile__ ("pushfl;" + "popl %0;" + "andl %1, %0;" + "orl %2, %0;" + "pushl %0;" + "popfl" + : "=&r" (reg) + : "i" (~X86_EFLAGS_IOPL), "r" (mask)); +} /* Forward declaration, a strange C thing */ struct task_struct; diff --git a/trunk/include/asm-i386/system.h b/trunk/include/asm-i386/system.h index 37fd2f8c7196..acd5c26b69ba 100644 --- a/trunk/include/asm-i386/system.h +++ b/trunk/include/asm-i386/system.h @@ -14,8 +14,7 @@ extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struc #define switch_to(prev,next,last) do { \ unsigned long esi,edi; \ - asm volatile("pushfl\n\t" \ - "pushl %%ebp\n\t" \ + asm volatile("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 */ \ @@ -23,7 +22,6 @@ extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struc "jmp __switch_to\n" \ "1:\t" \ "popl %%ebp\n\t" \ - "popfl" \ :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \ "=a" (last),"=S" (esi),"=D" (edi) \ :"m" (next->thread.esp),"m" (next->thread.eip), \