Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / arch / i386 / kernel / process.c
index a995ce8..9abe5ab 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
-#include <linux/config.h>
 #include <linux/utsname.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
@@ -102,7 +101,7 @@ void default_idle(void)
        local_irq_enable();
 
        if (!hlt_counter && boot_cpu_data.hlt_works_ok) {
-               clear_thread_flag(TIF_POLLING_NRFLAG);
+               current_thread_info()->status &= ~TS_POLLING;
                smp_mb__after_clear_bit();
                while (!need_resched()) {
                        local_irq_disable();
@@ -111,7 +110,7 @@ void default_idle(void)
                        else
                                local_irq_enable();
                }
-               set_thread_flag(TIF_POLLING_NRFLAG);
+               current_thread_info()->status |= TS_POLLING;
        } else {
                while (!need_resched())
                        cpu_relax();
@@ -174,7 +173,7 @@ void cpu_idle(void)
 {
        int cpu = smp_processor_id();
 
-       set_thread_flag(TIF_POLLING_NRFLAG);
+       current_thread_info()->status |= TS_POLLING;
 
        /* endless idle loop with no priority at all */
        while (1) {
@@ -312,7 +311,7 @@ void show_regs(struct pt_regs * regs)
        cr3 = read_cr3();
        cr4 = read_cr4_safe();
        printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
-       show_trace(NULL, &regs->esp);
+       show_trace(NULL, regs, &regs->esp);
 }
 
 /*
@@ -321,15 +320,6 @@ void show_regs(struct pt_regs * regs)
  * the "args".
  */
 extern void kernel_thread_helper(void);
-__asm__(".section .text\n"
-       ".align 4\n"
-       "kernel_thread_helper:\n\t"
-       "movl %edx,%eax\n\t"
-       "pushl %edx\n\t"
-       "call *%ebx\n\t"
-       "pushl %eax\n\t"
-       "call do_exit\n"
-       ".previous");
 
 /*
  * Create a kernel thread
@@ -337,6 +327,7 @@ __asm__(".section .text\n"
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
        struct pt_regs regs;
+       int err;
 
        memset(&regs, 0, sizeof(regs));
 
@@ -351,7 +342,10 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
        regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
 
        /* Ok, create the new process.. */
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+       err = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+       if (err == 0) /* terminate kernel stack */
+               task_pt_regs(current)->eip = 0;
+       return err;
 }
 EXPORT_SYMBOL(kernel_thread);
 
@@ -360,16 +354,16 @@ EXPORT_SYMBOL(kernel_thread);
  */
 void exit_thread(void)
 {
-       struct task_struct *tsk = current;
-       struct thread_struct *t = &tsk->thread;
-
        /* The process may have allocated an io port bitmap... nuke it. */
-       if (unlikely(NULL != t->io_bitmap_ptr)) {
+       if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
+               struct task_struct *tsk = current;
+               struct thread_struct *t = &tsk->thread;
                int cpu = get_cpu();
                struct tss_struct *tss = &per_cpu(init_tss, cpu);
 
                kfree(t->io_bitmap_ptr);
                t->io_bitmap_ptr = NULL;
+               clear_thread_flag(TIF_IO_BITMAP);
                /*
                 * Careful, clear this in the TSS too:
                 */
@@ -388,6 +382,7 @@ void flush_thread(void)
 
        memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
        memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));        
+       clear_tsk_thread_flag(tsk, TIF_DEBUG);
        /*
         * Forget coprocessor state..
         */
@@ -432,7 +427,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
        savesegment(gs,p->thread.gs);
 
        tsk = current;
-       if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) {
+       if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
                p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
                if (!p->thread.io_bitmap_ptr) {
                        p->thread.io_bitmap_max = 0;
@@ -440,6 +435,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
                }
                memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr,
                        IO_BITMAP_BYTES);
+               set_tsk_thread_flag(p, TIF_IO_BITMAP);
        }
 
        /*
@@ -534,10 +530,24 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
        return 1;
 }
 
-static inline void
-handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss)
+static noinline void __switch_to_xtra(struct task_struct *next_p,
+                                   struct tss_struct *tss)
 {
-       if (!next->io_bitmap_ptr) {
+       struct thread_struct *next;
+
+       next = &next_p->thread;
+
+       if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+               set_debugreg(next->debugreg[0], 0);
+               set_debugreg(next->debugreg[1], 1);
+               set_debugreg(next->debugreg[2], 2);
+               set_debugreg(next->debugreg[3], 3);
+               /* no 4 and 5 */
+               set_debugreg(next->debugreg[6], 6);
+               set_debugreg(next->debugreg[7], 7);
+       }
+
+       if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
                /*
                 * Disable the bitmap via an invalid offset. We still cache
                 * the previous bitmap owner and the IO bitmap contents:
@@ -545,6 +555,7 @@ handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss)
                tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
                return;
        }
+
        if (likely(next == tss->io_bitmap_owner)) {
                /*
                 * Previous owner of the bitmap (hence the bitmap content)
@@ -674,20 +685,11 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
                set_iopl_mask(next->iopl);
 
        /*
-        * Now maybe reload the debug registers
+        * Now maybe handle debug registers and/or IO bitmaps
         */
-       if (unlikely(next->debugreg[7])) {
-               set_debugreg(next->debugreg[0], 0);
-               set_debugreg(next->debugreg[1], 1);
-               set_debugreg(next->debugreg[2], 2);
-               set_debugreg(next->debugreg[3], 3);
-               /* no 4 and 5 */
-               set_debugreg(next->debugreg[6], 6);
-               set_debugreg(next->debugreg[7], 7);
-       }
-
-       if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
-               handle_io_bitmap(next, tss);
+       if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)
+           || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)))
+               __switch_to_xtra(next_p, tss);
 
        disable_tsc(prev_p, next_p);
 
@@ -746,9 +748,6 @@ asmlinkage int sys_execve(struct pt_regs regs)
                        (char __user * __user *) regs.edx,
                        &regs);
        if (error == 0) {
-               task_lock(current);
-               current->ptrace &= ~PT_DTRACE;
-               task_unlock(current);
                /* Make sure we don't return using sysenter.. */
                set_thread_flag(TIF_IRET);
        }