diff options
Diffstat (limited to 'arch/mips/kernel/ptrace32.c')
| -rw-r--r-- | arch/mips/kernel/ptrace32.c | 88 | 
1 files changed, 26 insertions, 62 deletions
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 9486055ba66..b40c3ca60ee 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -80,6 +80,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,  	/* Read the word at location addr in the USER area. */  	case PTRACE_PEEKUSR: {  		struct pt_regs *regs; +		union fpureg *fregs;  		unsigned int tmp;  		regs = task_pt_regs(child); @@ -90,21 +91,23 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,  			tmp = regs->regs[addr];  			break;  		case FPR_BASE ... FPR_BASE + 31: -			if (tsk_used_math(child)) { -				fpureg_t *fregs = get_fpu_regs(child); - +			if (!tsk_used_math(child)) { +				/* FP not yet used */ +				tmp = -1; +				break; +			} +			fregs = get_fpu_regs(child); +			if (test_thread_flag(TIF_32BIT_FPREGS)) {  				/*  				 * The odd registers are actually the high  				 * order bits of the values stored in the even  				 * registers - unless we're using r2k_switch.S.  				 */ -				if (addr & 1) -					tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32); -				else -					tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff); -			} else { -				tmp = -1;	/* FP not yet used  */ +				tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE], +						addr & 1); +				break;  			} +			tmp = get_fpr32(&fregs[addr - FPR_BASE], 0);  			break;  		case PC:  			tmp = regs->cp0_epc; @@ -124,46 +127,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,  		case FPC_CSR:  			tmp = child->thread.fpu.fcr31;  			break; -		case FPC_EIR: { /* implementation / version register */ -			unsigned int flags; -#ifdef CONFIG_MIPS_MT_SMTC -			unsigned int irqflags; -			unsigned int mtflags; -#endif /* CONFIG_MIPS_MT_SMTC */ - -			preempt_disable(); -			if (!cpu_has_fpu) { -				preempt_enable(); -				tmp = 0; -				break; -			} - -#ifdef CONFIG_MIPS_MT_SMTC -			/* Read-modify-write of Status must be atomic */ -			local_irq_save(irqflags); -			mtflags = dmt(); -#endif /* CONFIG_MIPS_MT_SMTC */ - -			if (cpu_has_mipsmt) { -				unsigned int vpflags = dvpe(); -				flags = read_c0_status(); -				__enable_fpu(); -				__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); -				write_c0_status(flags); -				evpe(vpflags); -			} else { -				flags = read_c0_status(); -				__enable_fpu(); -				__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); -				write_c0_status(flags); -			} -#ifdef CONFIG_MIPS_MT_SMTC -			emt(mtflags); -			local_irq_restore(irqflags); -#endif /* CONFIG_MIPS_MT_SMTC */ -			preempt_enable(); +		case FPC_EIR: +			/* implementation / version register */ +			tmp = current_cpu_data.fpu_id;  			break; -		}  		case DSP_BASE ... DSP_BASE + 5: {  			dspreg_t *dregs; @@ -228,7 +195,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,  			regs->regs[addr] = data;  			break;  		case FPR_BASE ... FPR_BASE + 31: { -			fpureg_t *fregs = get_fpu_regs(child); +			union fpureg *fregs = get_fpu_regs(child);  			if (!tsk_used_math(child)) {  				/* FP not yet used  */ @@ -236,20 +203,17 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,  				       sizeof(child->thread.fpu));  				child->thread.fpu.fcr31 = 0;  			} -			/* -			 * The odd registers are actually the high order bits -			 * of the values stored in the even registers - unless -			 * we're using r2k_switch.S. -			 */ -			if (addr & 1) { -				fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff; -				fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32; -			} else { -				fregs[addr - FPR_BASE] &= ~0xffffffffLL; -				/* Must cast, lest sign extension fill upper -				   bits!  */ -				fregs[addr - FPR_BASE] |= (unsigned int)data; +			if (test_thread_flag(TIF_32BIT_FPREGS)) { +				/* +				 * The odd registers are actually the high +				 * order bits of the values stored in the even +				 * registers - unless we're using r2k_switch.S. +				 */ +				set_fpr32(&fregs[(addr & ~1) - FPR_BASE], +					  addr & 1, data); +				break;  			} +			set_fpr64(&fregs[addr - FPR_BASE], 0, data);  			break;  		}  		case PC:  | 
