Esempio n. 1
0
static inline int
save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
{
	int err = 0;
#ifdef CONFIG_SMP
	if (test_tsk_thread_flag(current, TIF_USEDFPU)) {
		put_psr(get_psr() | PSR_EF);
		fpsave(&current->thread.float_regs[0], &current->thread.fsr,
		       &current->thread.fpqueue[0], &current->thread.fpqdepth);
		regs->psr &= ~(PSR_EF);
		clear_tsk_thread_flag(current, TIF_USEDFPU);
	}
#else
	if (current == last_task_used_math) {
		put_psr(get_psr() | PSR_EF);
		fpsave(&current->thread.float_regs[0], &current->thread.fsr,
		       &current->thread.fpqueue[0], &current->thread.fpqdepth);
		last_task_used_math = NULL;
		regs->psr &= ~(PSR_EF);
	}
#endif
	err |= __copy_to_user(&fpu->si_float_regs[0],
			      &current->thread.float_regs[0],
			      (sizeof(unsigned long) * 32));
	err |= __put_user(current->thread.fsr, &fpu->si_fsr);
	err |= __put_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
	if (current->thread.fpqdepth != 0)
		err |= __copy_to_user(&fpu->si_fpqueue[0],
				      &current->thread.fpqueue[0],
				      ((sizeof(unsigned long) +
				      (sizeof(unsigned long *)))*16));
	clear_used_math();
	return err;
}
Esempio n. 2
0
static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned long *prax)
{
	unsigned int err = 0;

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

#define COPY(x)		err |= __get_user(regs->x, &sc->x)

	COPY(rdi); COPY(rsi); COPY(rbp); COPY(rsp); COPY(rbx);
	COPY(rdx); COPY(rcx); COPY(rip);
	COPY(r8);
	COPY(r9);
	COPY(r10);
	COPY(r11);
	COPY(r12);
	COPY(r13);
	COPY(r14);
	COPY(r15);

	/* Kernel saves and restores only the CS segment register on signals,
	 * which is the bare minimum needed to allow mixed 32/64-bit code.
	 * App's signal handler can save/restore other segments if needed. */
	{
		unsigned cs;
		err |= __get_user(cs, &sc->cs);
		regs->cs = cs | 3;	/* Force into user mode */
	}

	{
		unsigned int tmpflags;
		err |= __get_user(tmpflags, &sc->eflags);
		regs->eflags = (regs->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
		regs->orig_rax = -1;		/* disable syscall checks */
	}

	{
		struct _fpstate __user * buf;
		err |= __get_user(buf, &sc->fpstate);

		if (buf) {
			if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
				goto badframe;
			err |= restore_i387(buf);
		} else {
			struct task_struct *me = current;
			if (used_math()) {
				clear_fpu(me);
				clear_used_math();
			}
		}
	}

	err |= __get_user(*prax, &sc->rax);
	return err;

badframe:
	return 1;
}
static inline int save_i387(struct _fpstate __user *buf)
{
	struct task_struct *tsk = current;
	int err = 0;

	BUILD_BUG_ON(sizeof(struct user_i387_struct) !=
			sizeof(tsk->thread.xstate->fxsave));

	if ((unsigned long)buf % 16)
		printk("save_i387: bad fpstate %p\n", buf);

	if (!used_math())
		return 0;
	clear_used_math(); /* trigger finit */
	if (task_thread_info(tsk)->status & TS_USEDFPU) {
		err = save_i387_checking((struct i387_fxsave_struct __user *)
					 buf);
		if (err)
			return err;
		task_thread_info(tsk)->status &= ~TS_USEDFPU;
		stts();
	} else {
		if (__copy_to_user(buf, &tsk->thread.xstate->fxsave,
				   sizeof(struct i387_fxsave_struct)))
			return -1;
	}
	return 1;
}
Esempio n. 4
0
/*
 * This restores directly out of user space. Exceptions are handled.
 */
int restore_i387_xstate(void __user *buf)
{
    struct task_struct *tsk = current;
    int err = 0;

    if (!buf) {
        if (used_math())
            goto clear;
        return 0;
    } else if (!access_ok(VERIFY_READ, buf, sig_xstate_size))
        return -EACCES;

    if (!used_math()) {
        err = init_fpu(tsk);
        if (err)
            return err;
    }

    user_fpu_begin();
    if (use_xsave())
        err = restore_user_xstate(buf);
    else
        err = fxrstor_checking((__force struct i387_fxsave_struct *)
                               buf);
    if (unlikely(err)) {
        /*
         * Encountered an error while doing the restore from the
         * user buffer, clear the fpu state.
         */
clear:
        clear_fpu(tsk);
        clear_used_math();
    }
    return err;
}
Esempio n. 5
0
static inline int restore_sigcontext_fpu(struct pt_regs *regs,
					 struct sigcontext __user *sc)
{
	struct task_struct *tsk = current;
	unsigned long used_math_flag;
	int ret = 0;

	clear_used_math();
	__get_user_error(used_math_flag, &sc->used_math_flag, ret);

	if (!used_math_flag)
		return 0;
	set_used_math();

#if IS_ENABLED(CONFIG_LAZY_FPU)
	preempt_disable();
	if (current == last_task_used_math) {
		last_task_used_math = NULL;
		disable_ptreg_fpu(regs);
	}
	preempt_enable();
#else
	clear_fpu(regs);
#endif

	return __copy_from_user(&tsk->thread.fpu, &sc->fpu,
				sizeof(struct fpu_struct));
}
Esempio n. 6
0
void __init cpu_init (void)
{
    int cpu_id = smp_processor_id();

    if (test_and_set_bit(cpu_id, &cpu_initialized)) {
        printk(KERN_WARNING "CPU#%d already initialized!\n", cpu_id);
        for ( ; ; )
            local_irq_enable();
    }
    printk(KERN_INFO "Initializing CPU#%d\n", cpu_id);

    /* Set up and load the per-CPU TSS and LDT */
    atomic_inc(&init_mm.mm_count);
    current->active_mm = &init_mm;
    if (current->mm)
        BUG();

    /* Force FPU initialization */
    current_thread_info()->status = 0;
    clear_used_math();

#ifdef CONFIG_MMU
    /* Set up MMU */
    init_mmu();
#endif

    /* Set up ICUIMASK */
    outl(0x00070000, M32R_ICU_IMASK_PORTL);		/* imask=111 */
}
/*
 * This restores directly out of user space. Exceptions are handled.
 */
static inline int restore_i387(struct _fpstate __user *buf)
{
	struct task_struct *tsk = current;
	int err;

	if (!used_math()) {
		err = init_fpu(tsk);
		if (err)
			return err;
	}

	if (!(task_thread_info(current)->status & TS_USEDFPU)) {
		clts();
		task_thread_info(current)->status |= TS_USEDFPU;
	}
	err = restore_fpu_checking((__force struct i387_fxsave_struct *)buf);
	if (unlikely(err)) {
		/*
		 * Encountered an error while doing the restore from the
		 * user buffer, clear the fpu state.
		 */
		clear_fpu(tsk);
		clear_used_math();
	}
	return err;
}
Esempio n. 8
0
static inline int
setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
{
    int err = 0;
    int fpvalid;

    fpvalid = !!used_math();
    err |= __put_user(fpvalid, &sc->sc_fpvalid);
    if (! fpvalid)
        return err;

    if (current == last_task_used_math) {
        enable_fpu();
        save_fpu(current);
        disable_fpu();
        last_task_used_math = NULL;
        regs->sr |= SR_FD;
    }

    err |= __copy_to_user(&sc->sc_fpregs[0], &current->thread.xstate->hardfpu,
                          (sizeof(long long) * 32) + (sizeof(int) * 1));
    clear_used_math();

    return err;
}
Esempio n. 9
0
void flush_thread(void)
{
	struct thread_info *thread = current_thread_info();
	struct task_struct *tsk = current;

	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
	memset(&thread->fpstate, 0, sizeof(union fp_state));

	clear_used_math();
}
Esempio n. 10
0
void flush_thread(void)
{
	struct task_struct *tsk = current;

	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..
	 */
	clear_fpu(tsk);
	clear_used_math();
}
Esempio n. 11
0
static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned long *prax)
{
	unsigned int err = 0;

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

#define COPY(x)		err |= __get_user(regs->x, &sc->x)

	COPY(rdi); COPY(rsi); COPY(rbp); COPY(rsp); COPY(rbx);
	COPY(rdx); COPY(rcx); COPY(rip);
	COPY(r8);
	COPY(r9);
	COPY(r10);
	COPY(r11);
	COPY(r12);
	COPY(r13);
	COPY(r14);
	COPY(r15);

	{
		unsigned int tmpflags;
		err |= __get_user(tmpflags, &sc->eflags);
		regs->eflags = (regs->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
		regs->orig_rax = -1;		/* disable syscall checks */
	}

	{
		struct _fpstate __user * buf;
		err |= __get_user(buf, &sc->fpstate);

		if (buf) {
			if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
				goto badframe;
			err |= restore_i387(buf);
		} else {
			struct task_struct *me = current;
			if (used_math()) {
				clear_fpu(me);
				clear_used_math();
			}
		}
	}

	err |= __get_user(*prax, &sc->rax);
	return err;

badframe:
	return 1;
}
Esempio n. 12
0
void flush_thread(void)
{
	struct task_struct *tsk = current;

#if defined(CONFIG_X86_32) && !defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_PAX_MEMORY_UDEREF)
	loadsegment(gs, 0);
#endif
	flush_ptrace_hw_breakpoint(tsk);
	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
	/*
	 * Forget coprocessor state..
	 */
	tsk->fpu_counter = 0;
	clear_fpu(tsk);
	clear_used_math();
}
Esempio n. 13
0
void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
{
	unsigned long status;

	/* New thread loses kernel privileges. */
	status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|ST0_FR|KU_MASK);
	status |= KU_USER;
	regs->cp0_status = status;
	clear_used_math();
	clear_fpu_owner();
	init_dsp();
	clear_thread_flag(TIF_USEDMSA);
	clear_thread_flag(TIF_MSA_CTX_LIVE);
	disable_msa();
	regs->cp0_epc = pc;
	regs->regs[29] = sp;
}
Esempio n. 14
0
File: setup.c Progetto: 710leo/LVS
/*
 * cpu_init() initializes state that is per-CPU.
 */
void __cpuinit cpu_init(void)
{
        /*
         * Store processor id in lowcore (used e.g. in timer_interrupt)
         */
	get_cpu_id(&S390_lowcore.cpu_id);

        /*
         * Force FPU initialization:
         */
        clear_thread_flag(TIF_USEDFPU);
        clear_used_math();

	atomic_inc(&init_mm.mm_count);
	current->active_mm = &init_mm;
	BUG_ON(current->mm);
        enter_lazy_tlb(&init_mm, current);
}
Esempio n. 15
0
static void flush_thread_from_task(struct task_struct *tsk)
{
	clear_tsk_thread_flag(tsk, TIF_DEBUG);

	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));
	/*
	 * Forget coprocessor state..
	 */
	tsk->fpu_counter = 0;
	clear_fpu(tsk);
	clear_used_math();
}
Esempio n. 16
0
void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
{
	unsigned long status;

	/* New thread loses kernel privileges. */
	status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|ST0_FR|KU_MASK);
#ifdef CONFIG_64BIT
	status |= test_thread_flag(TIF_32BIT_REGS) ? 0 : ST0_FR;
#endif
	status |= KU_USER;
	regs->cp0_status = status;
	clear_used_math();
	clear_fpu_owner();
	if (cpu_has_dsp)
		__init_dsp();
	regs->cp0_epc = pc;
	regs->regs[29] = sp;
}
Esempio n. 17
0
void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
{
	unsigned long status;

	/* New thread loses kernel privileges. */
	status = regs->cp0_status & ~(ST0_CU0|ST0_CU1|KU_MASK);
#ifdef CONFIG_64BIT
	status &= ~ST0_FR;
	status |= (current->thread.mflags & MF_32BIT_REGS) ? 0 : ST0_FR;
#endif
	status |= KU_USER;
	regs->cp0_status = status;
	clear_used_math();
	lose_fpu();
	if (cpu_has_dsp)
		__init_dsp();
	regs->cp0_epc = pc;
	regs->regs[29] = sp;
	current_thread_info()->addr_limit = USER_DS;
}
Esempio n. 18
0
/*
 * cpu_init() initializes state that is per-CPU.
 */
void __devinit cpu_init (void)
{
        int addr = hard_smp_processor_id();

        /*
         * Store processor id in lowcore (used e.g. in timer_interrupt)
         */
	get_cpu_id(&S390_lowcore.cpu_data.cpu_id);
        S390_lowcore.cpu_data.cpu_addr = addr;

        /*
         * Force FPU initialization:
         */
        clear_thread_flag(TIF_USEDFPU);
        clear_used_math();

	atomic_inc(&init_mm.mm_count);
	current->active_mm = &init_mm;
        if (current->mm)
                BUG();
        enter_lazy_tlb(&init_mm, current);
}
Esempio n. 19
0
static inline int save_sigcontext_fpu(struct sigcontext __user *sc,
				      struct pt_regs *regs)
{
	struct task_struct *tsk = current;

	if (!(boot_cpu_data.flags & CPU_HAS_FPU))
		return 0;

	if (!used_math())
		return __put_user(0, &sc->sc_ownedfp);

	if (__put_user(1, &sc->sc_ownedfp))
		return -EFAULT;

	/* This will cause a "finit" to be triggered by the next
	   attempted FPU operation by the 'current' process.
	   */
	clear_used_math();

	unlazy_fpu(tsk, regs);
	return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.xstate->hardfpu,
			      sizeof(long)*(16*2+2));
}
Esempio n. 20
0
int ckpt_restore_fpu(ckpt_desc_t desc)
{
    int ret;
    int flag;

    log_restore_fpu("restoring fpu ...");
    if (ckpt_read(desc, &flag, sizeof(int)) != sizeof(int)) {
        log_err("failed to get file");
        return -EIO;
    }

    kernel_fpu_begin();
    clear_used_math();
    if (flag) {
        if (!ckpt_get_i387(current)) {
            init_fpu(current);
            if (!ckpt_get_i387(current)) {
                log_err("failed to get i387");
                return -EFAULT;
            }
        }
        if (ckpt_read(desc, ckpt_get_i387(current), xstate_size) != xstate_size) {
            log_err("failed to get i387");
            return -EFAULT;
        }

        ret = ckpt_check_fpu_state();
        if (ret) {
            log_err("failed to restore i387");
            return ret;
        }
        set_used_math();
    }
    kernel_fpu_end();
    log_restore_pos(desc);
    return 0;
}
static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p)
{
	unsigned int err = 0;

#define COPY(x)		err |= __get_user(regs->x, &sc->sc_##x)
			COPY(regs[1]);
	COPY(regs[2]);	COPY(regs[3]);
	COPY(regs[4]);	COPY(regs[5]);
	COPY(regs[6]);	COPY(regs[7]);
	COPY(regs[8]);	COPY(regs[9]);
	COPY(regs[10]);	COPY(regs[11]);
	COPY(regs[12]);	COPY(regs[13]);
	COPY(regs[14]);	COPY(regs[15]);
	COPY(gbr);	COPY(mach);
	COPY(macl);	COPY(pr);
	COPY(sr);	COPY(pc);
#undef COPY

#ifdef CONFIG_SH_FPU
	if (boot_cpu_data.flags & CPU_HAS_FPU) {
		int owned_fp;
		struct task_struct *tsk = current;

		regs->sr |= SR_FD; /* Release FPU */
		clear_fpu(tsk, regs);
		clear_used_math();
		__get_user (owned_fp, &sc->sc_ownedfp);
		if (owned_fp)
			err |= restore_sigcontext_fpu(sc);
	}
#endif

	regs->tra = -1;		/* disable syscall checks */
	err |= __get_user(*r0_p, &sc->sc_regs[0]);
	return err;
}
Esempio n. 22
0
int save_i387_xstate(void __user *buf)
{
	struct task_struct *tsk = current;
	int err = 0;

	if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size))
		return -EACCES;

	BUG_ON(sig_xstate_size < xstate_size);

	if ((unsigned long)buf % 64)
		printk("save_i387_xstate: bad fpstate %p\n", buf);

	if (!used_math())
		return 0;

	if (user_has_fpu()) {
		if (use_xsave())
			err = xsave_user(buf);
		else
			err = fxsave_user(buf);

		if (err)
			return err;
		user_fpu_end();
	} else {
		sanitize_i387_state(tsk);
		if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave,
				   xstate_size))
			return -1;
	}

	clear_used_math(); /* trigger finit */

	if (use_xsave()) {
		struct _fpstate __user *fx = buf;
		struct _xstate __user *x = buf;
		u64 xstate_bv;

		err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved,
				     sizeof(struct _fpx_sw_bytes));

		err |= __put_user(FP_XSTATE_MAGIC2,
				  (__u32 __user *) (buf + sig_xstate_size
						    - FP_XSTATE_MAGIC2_SIZE));

		/*
		 * Read the xstate_bv which we copied (directly from the cpu or
		 * from the state in task struct) to the user buffers and
		 * set the FP/SSE bits.
		 */
		err |= __get_user(xstate_bv, &x->xstate_hdr.xstate_bv);

		/*
		 * For legacy compatible, we always set FP/SSE bits in the bit
		 * vector while saving the state to the user context. This will
		 * enable us capturing any changes(during sigreturn) to
		 * the FP/SSE bits by the legacy applications which don't touch
		 * xstate_bv in the xsave header.
		 *
		 * xsave aware apps can change the xstate_bv in the xsave
		 * header as well as change any contents in the memory layout.
		 * xrestore as part of sigreturn will capture all the changes.
		 */
		xstate_bv |= XSTATE_FPSSE;

		err |= __put_user(xstate_bv, &x->xstate_hdr.xstate_bv);

		if (err)
			return err;
	}

	return 1;
}
Esempio n. 23
0
static int
restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax)
{
	unsigned int err = 0;

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

#define COPY(x)		err |= __get_user(regs->x, &sc->x)

#define COPY_SEG(seg)							\
	{ unsigned short tmp;						\
	  err |= __get_user(tmp, &sc->seg);				\
	  regs->x##seg = tmp; }

#define COPY_SEG_STRICT(seg)						\
	{ unsigned short tmp;						\
	  err |= __get_user(tmp, &sc->seg);				\
	  regs->x##seg = tmp|3; }

#define GET_SEG(seg)							\
	{ unsigned short tmp;						\
	  err |= __get_user(tmp, &sc->seg);				\
	  loadsegment(seg,tmp); }

#define	FIX_EFLAGS	(X86_EFLAGS_AC | X86_EFLAGS_RF |		 \
			 X86_EFLAGS_OF | X86_EFLAGS_DF |		 \
			 X86_EFLAGS_TF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \
			 X86_EFLAGS_AF | X86_EFLAGS_PF | X86_EFLAGS_CF)

	GET_SEG(gs);
	COPY_SEG(fs);
	COPY_SEG(es);
	COPY_SEG(ds);
	COPY(edi);
	COPY(esi);
	COPY(ebp);
	COPY(esp);
	COPY(ebx);
	COPY(edx);
	COPY(ecx);
	COPY(eip);
	COPY_SEG_STRICT(cs);
	COPY_SEG_STRICT(ss);
	
	{
		unsigned int tmpflags;
		err |= __get_user(tmpflags, &sc->eflags);
		regs->eflags = (regs->eflags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
		regs->orig_eax = -1;		/* disable syscall checks */
	}

	{
		struct _fpstate __user * buf;
		err |= __get_user(buf, &sc->fpstate);
		if (buf) {
			if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
				goto badframe;
			err |= restore_i387(buf);
		} else {
			struct task_struct *me = current;
			if (used_math()) {
				clear_fpu(me);
				clear_used_math();
			}
		}
	}

	err |= __get_user(*peax, &sc->eax);
	return err;

badframe:
	return 1;
}
Esempio n. 24
0
int save_i387_xstate(void __user *buf)
{
	struct task_struct *tsk = current;
	int err = 0;

	if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size))
		return -EACCES;

	BUG_ON(sig_xstate_size < xstate_size);

	if ((unsigned long)buf % 64)
		printk("save_i387_xstate: bad fpstate %p\n", buf);

	if (!used_math())
		return 0;

	if (user_has_fpu()) {
		if (use_xsave())
			err = xsave_user(buf);
		else
			err = fxsave_user(buf);

		if (err)
			return err;
		user_fpu_end();
	} else {
		sanitize_i387_state(tsk);
		if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave,
				   xstate_size))
			return -1;
	}

	clear_used_math(); /*               */

	if (use_xsave()) {
		struct _fpstate __user *fx = buf;
		struct _xstate __user *x = buf;
		u64 xstate_bv;

		err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved,
				     sizeof(struct _fpx_sw_bytes));

		err |= __put_user(FP_XSTATE_MAGIC2,
				  (__u32 __user *) (buf + sig_xstate_size
						    - FP_XSTATE_MAGIC2_SIZE));

		/*
                                                                 
                                                           
                         
   */
		err |= __get_user(xstate_bv, &x->xstate_hdr.xstate_bv);

		/*
                                                                
                                                                 
                                                         
                                                                 
                                   
    
                                                           
                                                                
                                                                
   */
		xstate_bv |= XSTATE_FPSSE;

		err |= __put_user(xstate_bv, &x->xstate_hdr.xstate_bv);

		if (err)
			return err;
	}

	return 1;
}