Esempio n. 1
0
File: signal.c Progetto: 7799/linux
/* Returns non-zero on fault. */
static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
{
	_sigregs user_sregs;

	save_access_regs(current->thread.acrs);

	/* Copy a 'clean' PSW mask to the user to avoid leaking
	   information about whether PER is currently on.  */
	user_sregs.regs.psw.mask = PSW_USER_BITS |
		(regs->psw.mask & (PSW_MASK_USER | PSW_MASK_RI));
	user_sregs.regs.psw.addr = regs->psw.addr;
	memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
	memcpy(&user_sregs.regs.acrs, current->thread.acrs,
	       sizeof(user_sregs.regs.acrs));
	/* 
	 * We have to store the fp registers to current->thread.fp_regs
	 * to merge them with the emulated registers.
	 */
	save_fp_ctl(&current->thread.fp_regs.fpc);
	save_fp_regs(current->thread.fp_regs.fprs);
	memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
	       sizeof(user_sregs.fpregs));
	if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs)))
		return -EFAULT;
	return 0;
}
Esempio n. 2
0
/* Returns non-zero on fault. */
static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
{
	unsigned long old_mask = regs->psw.mask;
	int err;
  
	save_access_regs(current->thread.acrs);

	/* Copy a 'clean' PSW mask to the user to avoid leaking
	   information about whether PER is currently on.  */
	regs->psw.mask = PSW_MASK_MERGE(PSW_USER_BITS, regs->psw.mask);
	err = __copy_to_user(&sregs->regs.psw, &regs->psw,
			     sizeof(sregs->regs.psw)+sizeof(sregs->regs.gprs));
	regs->psw.mask = old_mask;
	if (err != 0)
		return err;
	err = __copy_to_user(&sregs->regs.acrs, current->thread.acrs,
			     sizeof(sregs->regs.acrs));
	if (err != 0)
		return err;
	/* 
	 * We have to store the fp registers to current->thread.fp_regs
	 * to merge them with the emulated registers.
	 */
	save_fp_regs(&current->thread.fp_regs);
	return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
			      sizeof(s390_fp_regs));
}
Esempio n. 3
0
/*
 * Returns the address space associated with the fault.
 * Returns 0 for kernel space, 1 for user space and
 * 2 for code execution in user space with noexec=on.
 */
static inline int check_space(struct task_struct *tsk)
{
	/*
	 * The lowest two bits of S390_lowcore.trans_exc_code
	 * indicate which paging table was used.
	 */
	int desc = S390_lowcore.trans_exc_code & 3;

	if (desc == 3)	/* Home Segment Table Descriptor */
		return switch_amode == 0;
	if (desc == 2)	/* Secondary Segment Table Descriptor */
		return tsk->thread.mm_segment.ar4;
#ifdef CONFIG_S390_SWITCH_AMODE
	if (unlikely(desc == 1)) { /* STD determined via access register */
		/* %a0 always indicates primary space. */
		if (S390_lowcore.exc_access_id != 0) {
			save_access_regs(tsk->thread.acrs);
			/*
			 * An alet of 0 indicates primary space.
			 * An alet of 1 indicates secondary space.
			 * Any other alet values generate an
			 * alen-translation exception.
			 */
			if (tsk->thread.acrs[S390_lowcore.exc_access_id])
				return tsk->thread.mm_segment.ar4;
		}
	}
#endif
	/* Primary Segment Table Descriptor */
	return switch_amode << s390_noexec;
}
Esempio n. 4
0
static inline int dump_regs32(struct pt_regs *ptregs, elf_gregset_t *regs)
{
	int i;

	memcpy(&regs->psw.mask, &ptregs->psw.mask, 4);
	memcpy(&regs->psw.addr, (char *)&ptregs->psw.addr + 4, 4);
	for (i = 0; i < NUM_GPRS; i++)
		regs->gprs[i] = ptregs->gprs[i];
	save_access_regs(regs->acrs);
	regs->orig_gpr2 = ptregs->orig_gpr2;
	return 1;
}
/* Store registers needed to create the signal frame */
static void store_sigregs(void)
{
    int i;

    save_access_regs(current->thread.acrs);
    save_fp_ctl(&current->thread.fp_regs.fpc);
    if (current->thread.vxrs) {
        save_vx_regs(current->thread.vxrs);
        for (i = 0; i < __NUM_FPRS; i++)
            current->thread.fp_regs.fprs[i] =
                *(freg_t *)(current->thread.vxrs + i);
    } else
        save_fp_regs(current->thread.fp_regs.fprs);
}
Esempio n. 6
0
/*
 * Check which address space the address belongs to.
 * Returns 1 for user space and 0 for kernel space.
 */
static inline int check_user_space(struct pt_regs *regs, int error_code)
{
	/*
	 * The lowest two bits of S390_lowcore.trans_exc_code indicate
	 * which paging table was used:
	 *   0: Primary Segment Table Descriptor
	 *   1: STD determined via access register
	 *   2: Secondary Segment Table Descriptor
	 *   3: Home Segment Table Descriptor
	 */
	int descriptor = S390_lowcore.trans_exc_code & 3;
	if (descriptor == 1) {
		save_access_regs(current->thread.acrs);
		return __check_access_register(regs, error_code);
	}
	return descriptor >> 1;
}
Esempio n. 7
0
static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
{
	_s390_regs_common32 regs32;
	int err, i;

	regs32.psw.mask = PSW32_MASK_MERGE(psw32_user_bits,
					   (__u32)(regs->psw.mask >> 32));
	regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
	for (i = 0; i < NUM_GPRS; i++)
		regs32.gprs[i] = (__u32) regs->gprs[i];
	save_access_regs(current->thread.acrs);
	memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs));
	err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
	if (err)
		return err;
	save_fp_regs(&current->thread.fp_regs);
	/* s390_fp_regs and _s390_fp_regs32 are the same ! */
	return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
			      sizeof(_s390_fp_regs32));
}
Esempio n. 8
0
/*
 * Check which address space is addressed by the access
 * register in S390_lowcore.exc_access_id.
 * Returns 1 for user space and 0 for kernel space.
 */
static int __check_access_register(struct pt_regs *regs, int error_code)
{
	int areg = S390_lowcore.exc_access_id;

	if (areg == 0)
		/* Access via access register 0 -> kernel address */
		return 0;
	save_access_regs(current->thread.acrs);
	if (regs && areg < NUM_ACRS && current->thread.acrs[areg] <= 1)
		/*
		 * access register contains 0 -> kernel address,
		 * access register contains 1 -> user space address
		 */
		return current->thread.acrs[areg];

	/* Something unhealthy was done with the access registers... */
	die("page fault via unknown access register", regs, error_code);
	do_exit(SIGKILL);
	return 0;
}
Esempio n. 9
0
/* Returns non-zero on fault. */
static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
{
	_sigregs user_sregs;

	save_access_regs(current->thread.acrs);

	/* Copy a 'clean' PSW mask to the user to avoid leaking
	   information about whether PER is currently on.  */
	user_sregs.regs.psw.mask = PSW_MASK_MERGE(psw_user_bits, regs->psw.mask);
	user_sregs.regs.psw.addr = regs->psw.addr;
	memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
	memcpy(&user_sregs.regs.acrs, current->thread.acrs,
	       sizeof(sregs->regs.acrs));
	/* 
	 * We have to store the fp registers to current->thread.fp_regs
	 * to merge them with the emulated registers.
	 */
	save_fp_regs(&current->thread.fp_regs);
	memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
	       sizeof(s390_fp_regs));
	return __copy_to_user(sregs, &user_sregs, sizeof(_sigregs));
}
Esempio n. 10
0
static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
{
	_sigregs32 user_sregs;
	int i;

	user_sregs.regs.psw.mask = (__u32)(regs->psw.mask >> 32);
	user_sregs.regs.psw.mask &= PSW32_MASK_USER | PSW32_MASK_RI;
	user_sregs.regs.psw.mask |= psw32_user_bits;
	user_sregs.regs.psw.addr = (__u32) regs->psw.addr |
		(__u32)(regs->psw.mask & PSW_MASK_BA);
	for (i = 0; i < NUM_GPRS; i++)
		user_sregs.regs.gprs[i] = (__u32) regs->gprs[i];
	save_access_regs(current->thread.acrs);
	memcpy(&user_sregs.regs.acrs, current->thread.acrs,
	       sizeof(user_sregs.regs.acrs));
	save_fp_ctl(&current->thread.fp_regs.fpc);
	save_fp_regs(current->thread.fp_regs.fprs);
	memcpy(&user_sregs.fpregs, &current->thread.fp_regs,
	       sizeof(user_sregs.fpregs));
	if (__copy_to_user(sregs, &user_sregs, sizeof(_sigregs32)))
		return -EFAULT;
	return 0;
}
Esempio n. 11
0
int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
		unsigned long arg, struct task_struct *p)
{
	struct thread_info *ti;
	struct fake_frame
	{
		struct stack_frame sf;
		struct pt_regs childregs;
	} *frame;

	frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
	p->thread.ksp = (unsigned long) frame;
	/* Save access registers to new thread structure. */
	save_access_regs(&p->thread.acrs[0]);
	/* start new process with ar4 pointing to the correct address space */
	p->thread.mm_segment = get_fs();
	/* Don't copy debug registers */
	memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
	memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
	clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
	/* Initialize per thread user and system timer values */
	ti = task_thread_info(p);
	ti->user_timer = 0;
	ti->system_timer = 0;

	frame->sf.back_chain = 0;
	/* new return point is ret_from_fork */
	frame->sf.gprs[8] = (unsigned long) ret_from_fork;
	/* fake return stack for resume(), don't go back to schedule */
	frame->sf.gprs[9] = (unsigned long) frame;

	/* Store access registers to kernel stack of new process. */
	if (unlikely(p->flags & PF_KTHREAD)) {
		/* kernel thread */
		memset(&frame->childregs, 0, sizeof(struct pt_regs));
		frame->childregs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT |
				PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
		frame->childregs.psw.addr = PSW_ADDR_AMODE |
				(unsigned long) kernel_thread_starter;
		frame->childregs.gprs[9] = new_stackp; /* function */
		frame->childregs.gprs[10] = arg;
		frame->childregs.gprs[11] = (unsigned long) do_exit;
		frame->childregs.orig_gpr2 = -1;

		return 0;
	}
	frame->childregs = *current_pt_regs();
	frame->childregs.gprs[2] = 0;	/* child returns 0 on fork. */
	frame->childregs.flags = 0;
	if (new_stackp)
		frame->childregs.gprs[15] = new_stackp;

	/* Don't copy runtime instrumentation info */
	p->thread.ri_cb = NULL;
	p->thread.ri_signum = 0;
	frame->childregs.psw.mask &= ~PSW_MASK_RI;

#ifndef CONFIG_64BIT
	/*
	 * save fprs to current->thread.fp_regs to merge them with
	 * the emulated registers and then copy the result to the child.
	 */
	save_fp_ctl(&current->thread.fp_regs.fpc);
	save_fp_regs(current->thread.fp_regs.fprs);
	memcpy(&p->thread.fp_regs, &current->thread.fp_regs,
	       sizeof(s390_fp_regs));
	/* Set a new TLS ?  */
	if (clone_flags & CLONE_SETTLS)
		p->thread.acrs[0] = frame->childregs.gprs[6];
#else /* CONFIG_64BIT */
	/* Save the fpu registers to new thread structure. */
	save_fp_ctl(&p->thread.fp_regs.fpc);
	save_fp_regs(p->thread.fp_regs.fprs);
	p->thread.fp_regs.pad = 0;
	/* Set a new TLS ?  */
	if (clone_flags & CLONE_SETTLS) {
		unsigned long tls = frame->childregs.gprs[6];
		if (is_compat_task()) {
			p->thread.acrs[0] = (unsigned int)tls;
		} else {
			p->thread.acrs[0] = (unsigned int)(tls >> 32);
			p->thread.acrs[1] = (unsigned int)tls;
		}
	}
Esempio n. 12
0
/* Store registers needed to create the signal frame */
static void store_sigregs(void)
{
	save_access_regs(current->thread.acrs);
	save_fpu_regs();
}