void exit_thread(void)
{
        /* The process may have allocated an io port bitmap... nuke it. */
        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:
                 */
                memset(tss->io_bitmap, 0xff, tss->io_bitmap_max);
                t->io_bitmap_max = 0;
                tss->io_bitmap_owner = NULL;
                tss->io_bitmap_max = 0;
                tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
                put_cpu();
        }
}

void flush_thread(void)
{
        struct task_struct *tsk = current;

        tsk->thread.debugreg0 = 0;
        tsk->thread.debugreg1 = 0;
        tsk->thread.debugreg2 = 0;
        tsk->thread.debugreg3 = 0;
        tsk->thread.debugreg6 = 0;
        tsk->thread.debugreg7 = 0;
        memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
        clear_tsk_thread_flag(tsk, TIF_DEBUG);
        /*
         * Forget coprocessor state..
         */
        tsk->fpu_counter = 0;
        clear_fpu(tsk);
        clear_used_math();
}

void
start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long
new_sp)
{
        __asm__("movl %0, %%gs" :: "r"(0));
        regs->fs                = 0;
        set_fs(USER_DS);
        regs->ds                = __USER_DS;
        regs->es                = __USER_DS;
        regs->ss                = __USER_DS;
        regs->cs                = __USER_CS;
        regs->ip                = new_ip;
        regs->sp                = new_sp;
        /*
         * Free the old FP and other extended state
         */
        free_thread_xstate(current);
}
EXPORT_SYMBOL_GPL(start_thread);

static void hard_disable_TSC(void)
{
        write_cr4(read_cr4() | X86_CR4_TSD);
}

void disable_TSC(void)
{
        preempt_disable();
        if (!test_and_set_thread_flag(TIF_NOTSC))
                /*
                 * Must flip the CPU state synchronously with
                 * TIF_NOTSC in the current running context.
                 */
                hard_disable_TSC();
        preempt_enable();
}

static void hard_enable_TSC(void)
{
        write_cr4(read_cr4() & ~X86_CR4_TSD);
}

static void enable_TSC(void)
{
        preempt_disable();
        if (test_and_clear_thread_flag(TIF_NOTSC))
                /*
                 * Must flip the CPU state synchronously with
                 * TIF_NOTSC in the current running context.
                 */
                hard_enable_TSC();
        preempt_enable();
}



int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
        unsigned long unused,
        struct task_struct * p, struct pt_regs * regs)
{
        struct pt_regs * childregs;
        struct task_struct *tsk;
        int err;

        childregs = task_pt_regs(p);
        *childregs = *regs;
        childregs->ax = 0;
        childregs->sp = sp;

        p->thread.sp = (unsigned long) childregs;
        p->thread.sp0 = (unsigned long) (childregs+1);

        p->thread.ip = (unsigned long) ret_from_fork;

        savesegment(gs, p->thread.gs);

        tsk = current;
        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;
                }
                set_tsk_thread_flag(p, TIF_IO_BITMAP);
        }

        err = 0;

        /*
         * Set a new TLS for the child thread?
         */
        if (clone_flags & CLONE_SETTLS)
                err = do_set_thread_area(p, -1,
                        (struct user_desc __user *)childregs->si, 0);

        if (err && p->thread.io_bitmap_ptr) {
                kfree(p->thread.io_bitmap_ptr);
                p->thread.io_bitmap_max = 0;
        }
        return err;
}

Reply via email to