diff options
Diffstat (limited to 'arch/powerpc/lib/sstep.c')
| -rw-r--r-- | arch/powerpc/lib/sstep.c | 62 | 
1 files changed, 28 insertions, 34 deletions
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index ae5189ab0049..9a52349874ee 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c @@ -11,6 +11,7 @@  #include <linux/kernel.h>  #include <linux/kprobes.h>  #include <linux/ptrace.h> +#include <linux/prefetch.h>  #include <asm/sstep.h>  #include <asm/processor.h>  #include <asm/uaccess.h> @@ -45,6 +46,18 @@ extern int do_stxvd2x(int rn, unsigned long ea);  #endif  /* + * Emulate the truncation of 64 bit values in 32-bit mode. + */ +static unsigned long truncate_if_32bit(unsigned long msr, unsigned long val) +{ +#ifdef __powerpc64__ +	if ((msr & MSR_64BIT) == 0) +		val &= 0xffffffffUL; +#endif +	return val; +} + +/*   * Determine whether a conditional branch instruction would branch.   */  static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs) @@ -90,11 +103,8 @@ static unsigned long __kprobes dform_ea(unsigned int instr, struct pt_regs *regs  		if (instr & 0x04000000)		/* update forms */  			regs->gpr[ra] = ea;  	} -#ifdef __powerpc64__ -	if (!(regs->msr & MSR_SF)) -		ea &= 0xffffffffUL; -#endif -	return ea; + +	return truncate_if_32bit(regs->msr, ea);  }  #ifdef __powerpc64__ @@ -113,9 +123,8 @@ static unsigned long __kprobes dsform_ea(unsigned int instr, struct pt_regs *reg  		if ((instr & 3) == 1)		/* update forms */  			regs->gpr[ra] = ea;  	} -	if (!(regs->msr & MSR_SF)) -		ea &= 0xffffffffUL; -	return ea; + +	return truncate_if_32bit(regs->msr, ea);  }  #endif /* __powerpc64 */ @@ -136,11 +145,8 @@ static unsigned long __kprobes xform_ea(unsigned int instr, struct pt_regs *regs  		if (do_update)		/* update forms */  			regs->gpr[ra] = ea;  	} -#ifdef __powerpc64__ -	if (!(regs->msr & MSR_SF)) -		ea &= 0xffffffffUL; -#endif -	return ea; + +	return truncate_if_32bit(regs->msr, ea);  }  /* @@ -466,7 +472,7 @@ static void __kprobes set_cr0(struct pt_regs *regs, int rd)  	regs->ccr = (regs->ccr & 0x0fffffff) | ((regs->xer >> 3) & 0x10000000);  #ifdef __powerpc64__ -	if (!(regs->msr & MSR_SF)) +	if (!(regs->msr & MSR_64BIT))  		val = (int) val;  #endif  	if (val < 0) @@ -487,7 +493,7 @@ static void __kprobes add_with_carry(struct pt_regs *regs, int rd,  		++val;  	regs->gpr[rd] = val;  #ifdef __powerpc64__ -	if (!(regs->msr & MSR_SF)) { +	if (!(regs->msr & MSR_64BIT)) {  		val = (unsigned int) val;  		val1 = (unsigned int) val1;  	} @@ -570,8 +576,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)  		if ((instr & 2) == 0)  			imm += regs->nip;  		regs->nip += 4; -		if ((regs->msr & MSR_SF) == 0) -			regs->nip &= 0xffffffffUL; +		regs->nip = truncate_if_32bit(regs->msr, regs->nip);  		if (instr & 1)  			regs->link = regs->nip;  		if (branch_taken(instr, regs)) @@ -604,13 +609,9 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)  			imm -= 0x04000000;  		if ((instr & 2) == 0)  			imm += regs->nip; -		if (instr & 1) { -			regs->link = regs->nip + 4; -			if ((regs->msr & MSR_SF) == 0) -				regs->link &= 0xffffffffUL; -		} -		if ((regs->msr & MSR_SF) == 0) -			imm &= 0xffffffffUL; +		if (instr & 1) +			regs->link = truncate_if_32bit(regs->msr, regs->nip + 4); +		imm = truncate_if_32bit(regs->msr, imm);  		regs->nip = imm;  		return 1;  	case 19: @@ -618,11 +619,8 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)  		case 16:	/* bclr */  		case 528:	/* bcctr */  			imm = (instr & 0x400)? regs->ctr: regs->link; -			regs->nip += 4; -			if ((regs->msr & MSR_SF) == 0) { -				regs->nip &= 0xffffffffUL; -				imm &= 0xffffffffUL; -			} +			regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4); +			imm = truncate_if_32bit(regs->msr, imm);  			if (instr & 1)  				regs->link = regs->nip;  			if (branch_taken(instr, regs)) @@ -1616,11 +1614,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)  		return 0;	/* invoke DSI if -EFAULT? */  	}   instr_done: -	regs->nip += 4; -#ifdef __powerpc64__ -	if ((regs->msr & MSR_SF) == 0) -		regs->nip &= 0xffffffffUL; -#endif +	regs->nip = truncate_if_32bit(regs->msr, regs->nip + 4);  	return 1;   logical_done:  |