Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / arch / i386 / kernel / process.c
index 94e2c87..b0a0780 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/kallsyms.h>
 #include <linux/ptrace.h>
 #include <linux/random.h>
+#include <linux/personality.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -296,9 +297,9 @@ void show_regs(struct pt_regs * regs)
        if (user_mode_vm(regs))
                printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
        printk(" EFLAGS: %08lx    %s  (%s %.*s)\n",
-              regs->eflags, print_tainted(), system_utsname.release,
-              (int)strcspn(system_utsname.version, " "),
-              system_utsname.version);
+              regs->eflags, print_tainted(), init_utsname()->release,
+              (int)strcspn(init_utsname()->version, " "),
+              init_utsname()->version);
        printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
                regs->eax,regs->ebx,regs->ecx,regs->edx);
        printk("ESI: %08lx EDI: %08lx EBP: %08lx",
@@ -320,15 +321,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
@@ -336,6 +328,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));
 
@@ -346,11 +339,14 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
        regs.xes = __USER_DS;
        regs.orig_eax = -1;
        regs.eip = (unsigned long) kernel_thread_helper;
-       regs.xcs = __KERNEL_CS;
+       regs.xcs = __KERNEL_CS | get_kernel_rpl();
        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);
 
@@ -359,16 +355,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:
                 */
@@ -387,6 +383,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..
         */
@@ -431,14 +428,14 @@ 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)) {
-               p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
+       if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
+               p->thread.io_bitmap_ptr = kmemdup(tsk->thread.io_bitmap_ptr,
+                                               IO_BITMAP_BYTES, GFP_KERNEL);
                if (!p->thread.io_bitmap_ptr) {
                        p->thread.io_bitmap_max = 0;
                        return -ENOMEM;
                }
-               memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr,
-                       IO_BITMAP_BYTES);
+               set_tsk_thread_flag(p, TIF_IO_BITMAP);
        }
 
        /*
@@ -533,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:
@@ -544,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)
@@ -671,20 +683,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);
 
@@ -897,7 +900,7 @@ asmlinkage int sys_get_thread_area(struct user_desc __user *u_info)
 
 unsigned long arch_align_stack(unsigned long sp)
 {
-       if (randomize_va_space)
+       if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
                sp -= get_random_int() % 8192;
        return sp & ~0xf;
 }