Exemplo n.º 1
0
asmlinkage long s390_futex(u32 *uaddr, int op, int val,
	struct timespec *utime, u32 *uaddr2)
{
	struct pt_regs *regs;

	regs = __KSTK_PTREGS(current);
	return sys_futex(uaddr, op, val, utime, uaddr2, regs->gprs[7]);
}
Exemplo n.º 2
0
/*
 * Write a word to the user area of a process at location addr. This
 * operation does have an additional problem compared to peek_user.
 * Stores to the program status word and on the floating point
 * control register needs to get checked for validity.
 */
static int
poke_user(struct task_struct *child, addr_t addr, addr_t data)
{
	struct user *dummy = NULL;
	addr_t offset, mask;

	/*
	 * Stupid gdb peeks/pokes the access registers in 64 bit with
	 * an alignment of 4. Programmers from hell indeed...
	 */
	mask = __ADDR_MASK;
#ifdef CONFIG_ARCH_S390X
	if (addr >= (addr_t) &dummy->regs.acrs &&
	    addr < (addr_t) &dummy->regs.orig_gpr2)
		mask = 3;
#endif
	if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
		return -EIO;

	if (addr < (addr_t) &dummy->regs.acrs) {
		/*
		 * psw and gprs are stored on the stack
		 */
		if (addr == (addr_t) &dummy->regs.psw.mask &&
#ifdef CONFIG_S390_SUPPORT
		    data != PSW_MASK_MERGE(PSW_USER32_BITS, data) &&
#endif
		    data != PSW_MASK_MERGE(PSW_USER_BITS, data))
			/* Invalid psw mask. */
			return -EINVAL;
#ifndef CONFIG_ARCH_S390X
		if (addr == (addr_t) &dummy->regs.psw.addr)
			/* I'd like to reject addresses without the
			   high order bit but older gdb's rely on it */
			data |= PSW_ADDR_AMODE;
#endif
		*(addr_t *)((addr_t) &__KSTK_PTREGS(child)->psw + addr) = data;

	} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
		/*
		 * access registers are stored in the thread structure
		 */
		offset = addr - (addr_t) &dummy->regs.acrs;
#ifdef CONFIG_ARCH_S390X
		/*
		 * Very special case: old & broken 64 bit gdb writing
		 * to acrs[15] with a 64 bit value. Ignore the lower
		 * half of the value and write the upper 32 bit to
		 * acrs[15]. Sick...
		 */
		if (addr == (addr_t) &dummy->regs.acrs[15])
			child->thread.acrs[15] = (unsigned int) (data >> 32);
		else
Exemplo n.º 3
0
static inline int dump_task_regs32(struct task_struct *tsk, elf_gregset_t *regs)
{
	struct pt_regs *ptregs = __KSTK_PTREGS(tsk);
	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];
	memcpy(regs->acrs, tsk->thread.acrs, sizeof(regs->acrs));
	regs->orig_gpr2 = ptregs->orig_gpr2;
	return 1;
}
Exemplo n.º 4
0
static void
FixPerRegisters(struct task_struct *task)
{
	struct pt_regs *regs;
	per_struct *per_info;

	regs = __KSTK_PTREGS(task);
	per_info = (per_struct *) &task->thread.per_info;
	per_info->control_regs.bits.em_instruction_fetch =
		per_info->single_step | per_info->instruction_fetch;
	
	if (per_info->single_step) {
		per_info->control_regs.bits.starting_addr = 0;
#ifdef CONFIG_S390_SUPPORT
		if (test_thread_flag(TIF_31BIT))
			per_info->control_regs.bits.ending_addr = 0x7fffffffUL;
		else
#endif
			per_info->control_regs.bits.ending_addr = PSW_ADDR_INSN;
	} else {
		per_info->control_regs.bits.starting_addr =
			per_info->starting_addr;
		per_info->control_regs.bits.ending_addr =
			per_info->ending_addr;
	}
	/*
	 * if any of the control reg tracing bits are on 
	 * we switch on per in the psw
	 */
	if (per_info->control_regs.words.cr[0] & PER_EM_MASK)
		regs->psw.mask |= PSW_MASK_PER;
	else
		regs->psw.mask &= ~PSW_MASK_PER;

	if (per_info->control_regs.bits.em_storage_alteration)
		per_info->control_regs.bits.storage_alt_space_ctl = 1;
	else
		per_info->control_regs.bits.storage_alt_space_ctl = 0;
}
Exemplo n.º 5
0
void FixPerRegisters(struct task_struct *task)
{
	struct pt_regs *regs = __KSTK_PTREGS(task);
	per_struct *per_info=
			(per_struct *)&task->thread.per_info;

	per_info->control_regs.bits.em_instruction_fetch=
	per_info->single_step|per_info->instruction_fetch;
	
	if(per_info->single_step)
	{
		per_info->control_regs.bits.starting_addr=0;
		per_info->control_regs.bits.ending_addr=0x7fffffffUL;
	}
	else
	{
		per_info->control_regs.bits.starting_addr=
		per_info->starting_addr;
		per_info->control_regs.bits.ending_addr=
		per_info->ending_addr;
	}
	/* if any of the control reg tracing bits are on 
	   we switch on per in the psw */
	if(per_info->control_regs.words.cr[0]&PER_EM_MASK)
		regs->psw.mask |=PSW_PER_MASK;
	else
		regs->psw.mask &= ~PSW_PER_MASK;
	if (per_info->control_regs.bits.em_storage_alteration)
	{
		per_info->control_regs.bits.storage_alt_space_ctl=1;
		//((pgd_t *)__pa(task->mm->pgd))->pgd |= USER_STD_MASK;
	}
	else
	{
		per_info->control_regs.bits.storage_alt_space_ctl=0;
		//((pgd_t *)__pa(task->mm->pgd))->pgd &= ~USER_STD_MASK;
	}
}
Exemplo n.º 6
0
void FixPerRegisters(struct task_struct *task)
{
	struct pt_regs *regs = __KSTK_PTREGS(task);
	per_struct *per_info=
			(per_struct *)&task->thread.per_info;

	per_info->control_regs.bits.em_instruction_fetch =
	        per_info->single_step | per_info->instruction_fetch;
	
	if (per_info->single_step) {
		per_info->control_regs.bits.starting_addr=0;
#ifdef CONFIG_S390_SUPPORT
		if (current->thread.flags & S390_FLAG_31BIT) {
			per_info->control_regs.bits.ending_addr=0x7fffffffUL;
	        }
		else 
#endif      
		{
		per_info->control_regs.bits.ending_addr=-1L;
		}
	} else {
		per_info->control_regs.bits.starting_addr=
		        per_info->starting_addr;
		per_info->control_regs.bits.ending_addr=
		        per_info->ending_addr;
	}
	/* if any of the control reg tracing bits are on 
	   we switch on per in the psw */
	if (per_info->control_regs.words.cr[0] & PER_EM_MASK)
		regs->psw.mask |= PSW_PER_MASK;
	else
		regs->psw.mask &= ~PSW_PER_MASK;
	if (per_info->control_regs.bits.storage_alt_space_ctl)
		task->thread.user_seg |= USER_STD_MASK;
	else
		task->thread.user_seg &= ~USER_STD_MASK;
}
Exemplo n.º 7
0
/*
 * Read the word at offset addr from the user area of a process. The
 * trouble here is that the information is littered over different
 * locations. The process registers are found on the kernel stack,
 * the floating point stuff and the trace settings are stored in
 * the task structure. In addition the different structures in
 * struct user contain pad bytes that should be read as zeroes.
 * Lovely...
 */
static int
peek_user(struct task_struct *child, addr_t addr, addr_t data)
{
	struct user *dummy = NULL;
	addr_t offset, tmp, mask;

	/*
	 * Stupid gdb peeks/pokes the access registers in 64 bit with
	 * an alignment of 4. Programmers from hell...
	 */
	mask = __ADDR_MASK;
#ifdef CONFIG_ARCH_S390X
	if (addr >= (addr_t) &dummy->regs.acrs &&
	    addr < (addr_t) &dummy->regs.orig_gpr2)
		mask = 3;
#endif
	if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
		return -EIO;

	if (addr < (addr_t) &dummy->regs.acrs) {
		/*
		 * psw and gprs are stored on the stack
		 */
		tmp = *(addr_t *)((addr_t) &__KSTK_PTREGS(child)->psw + addr);
		if (addr == (addr_t) &dummy->regs.psw.mask)
			/* Remove per bit from user psw. */
			tmp &= ~PSW_MASK_PER;

	} else if (addr < (addr_t) &dummy->regs.orig_gpr2) {
		/*
		 * access registers are stored in the thread structure
		 */
		offset = addr - (addr_t) &dummy->regs.acrs;
#ifdef CONFIG_ARCH_S390X
		/*
		 * Very special case: old & broken 64 bit gdb reading
		 * from acrs[15]. Result is a 64 bit value. Read the
		 * 32 bit acrs[15] value and shift it by 32. Sick...
		 */
		if (addr == (addr_t) &dummy->regs.acrs[15])
			tmp = ((unsigned long) child->thread.acrs[15]) << 32;
		else
#endif
		tmp = *(addr_t *)((addr_t) &child->thread.acrs + offset);

	} else if (addr == (addr_t) &dummy->regs.orig_gpr2) {
		/*
		 * orig_gpr2 is stored on the kernel stack
		 */
		tmp = (addr_t) __KSTK_PTREGS(child)->orig_gpr2;

	} else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
		/* 
		 * floating point regs. are stored in the thread structure
		 */
		offset = addr - (addr_t) &dummy->regs.fp_regs;
		tmp = *(addr_t *)((addr_t) &child->thread.fp_regs + offset);
		if (addr == (addr_t) &dummy->regs.fp_regs.fpc)
			tmp &= (unsigned long) FPC_VALID_MASK
				<< (BITS_PER_LONG - 32);

	} else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
		/*
		 * per_info is found in the thread structure
		 */
		offset = addr - (addr_t) &dummy->regs.per_info;
		tmp = *(addr_t *)((addr_t) &child->thread.per_info + offset);

	} else
		tmp = 0;

	return put_user(tmp, (addr_t __user *) data);
}
Exemplo n.º 8
0
int copy_user(struct task_struct *task,saddr_t useraddr, addr_t copyaddr,
              int len, int tofromuser, int writingtouser)
{
	int copylen=0,copymax;
	addr_t  realuseraddr;
	saddr_t enduseraddr;
	
	unsigned long mask;

#ifdef CONFIG_S390_SUPPORT
	if (current->thread.flags & S390_FLAG_31BIT) {
	/* adjust user offsets to 64 bit structure */
		if (useraddr < PT_PSWADDR / 2)
			useraddr = 2 * useraddr;
		else if(useraddr < PT_ACR0 / 2)
			useraddr = 2 * useraddr + sizeof(addr_t) / 2;
		else if(useraddr < PT_ACR0 / 2 + (PT_ORIGGPR2 - PT_ACR0))
			useraddr = useraddr + PT_ACR0 / 2;
		else if(useraddr < PT_ACR0 / 2 + (sizeof(struct user_regs_struct) - sizeof(addr_t) / 2 - PT_ACR0))
			useraddr = useraddr + PT_ACR0 / 2 + sizeof(addr_t) / 2; 
        }
#endif  
    
	enduseraddr=useraddr+len;

	if (useraddr < 0 || enduseraddr > sizeof(struct user)||
	   (useraddr < PT_ENDREGS && (useraddr&3))||
	   (enduseraddr < PT_ENDREGS && (enduseraddr&3)))
		return (-EIO);
	while(len>0)
	{
		mask=PSW_ADDR_MASK;
		if(useraddr<PT_FPC)
		{
			realuseraddr=((addr_t) __KSTK_PTREGS(task)) + useraddr;
			if(useraddr<PT_PSWMASK)
			{
				copymax=PT_PSWMASK;
			}
			else if(useraddr<(PT_PSWMASK+8))
			{
				copymax=(PT_PSWMASK+8);
				if(writingtouser)
					mask=PSW_MASK_DEBUGCHANGE;
			}
			else if(useraddr<(PT_PSWADDR+8))
			{
				copymax=PT_PSWADDR+8;
				mask=PSW_ADDR_DEBUGCHANGE;
			}
			else
				copymax=PT_FPC;
			
		}
		else if(useraddr<(PT_FPR15+sizeof(freg_t)))
		{
			copymax=(PT_FPR15+sizeof(freg_t));
			realuseraddr=(addr_t)&(((u8 *)&task->thread.fp_regs)[useraddr-PT_FPC]);
		}
		else if(useraddr<sizeof(struct user_regs_struct))
		{
			copymax=sizeof(struct user_regs_struct);
			realuseraddr=(addr_t)&(((u8 *)&task->thread.per_info)[useraddr-PT_CR_9]);
		}
		else 
		{
			copymax=sizeof(struct user);
			realuseraddr=(addr_t)NULL;
		}
		copylen=copymax-useraddr;
		copylen=(copylen>len ? len:copylen);
		if(ptrace_usercopy(realuseraddr,copyaddr,copylen,tofromuser,writingtouser,mask))
			return (-EIO);
		copyaddr+=copylen;
		len-=copylen;
		useraddr+=copylen;
	}
	FixPerRegisters(task);
	return(0);
}
Exemplo n.º 9
0
int copy_user(struct task_struct *task,saddr_t useraddr,addr_t copyaddr,int len,int tofromuser,int writingtouser)
{
	int copylen=0,copymax;
	addr_t  realuseraddr;
	saddr_t enduseraddr=useraddr+len;
	
	u32 mask;

	if (useraddr < 0 || enduseraddr > sizeof(struct user)||
	   (useraddr < PT_ENDREGS && (useraddr&3))||
	   (enduseraddr < PT_ENDREGS && (enduseraddr&3)))
		return (-EIO);
	while(len>0)
	{
		mask=0xffffffff;
		if(useraddr<PT_FPC)
		{
			realuseraddr=((addr_t) __KSTK_PTREGS(task)) + useraddr;
			if(useraddr<PT_PSWMASK)
			{
				copymax=PT_PSWMASK;
			}
			else if(useraddr<(PT_PSWMASK+4))
			{
				copymax=(PT_PSWMASK+4);
				if(writingtouser)
					mask=PSW_MASK_DEBUGCHANGE;
			}
			else if(useraddr<(PT_PSWADDR+4))
			{
				copymax=PT_PSWADDR+4;
				mask=PSW_ADDR_DEBUGCHANGE;
			}
			else
				copymax=PT_FPC;
			
		}
		else if(useraddr<(PT_FPR15_LO+4))
		{
			copymax=(PT_FPR15_LO+4);
			realuseraddr=(addr_t)&(((u8 *)&task->thread.fp_regs)[useraddr-PT_FPC]);
		}
		else if(useraddr<sizeof(struct user_regs_struct))
		{
			copymax=sizeof(struct user_regs_struct);
			realuseraddr=(addr_t)&(((u8 *)&task->thread.per_info)[useraddr-PT_CR_9]);
		}
		else 
		{
			copymax=sizeof(struct user);
			realuseraddr=(addr_t)NULL;
		}
		copylen=copymax-useraddr;
		copylen=(copylen>len ? len:copylen);
		if(ptrace_usercopy(realuseraddr,copyaddr,copylen,tofromuser,writingtouser,mask))
			return (-EIO);
		copyaddr+=copylen;
		len-=copylen;
		useraddr+=copylen;
	}
	FixPerRegisters(task);
	return(0);
}