diff options
Diffstat (limited to 'arch/arm64/kernel/hw_breakpoint.c')
| -rw-r--r-- | arch/arm64/kernel/hw_breakpoint.c | 86 | 
1 files changed, 43 insertions, 43 deletions
| diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index 413dbe530da8..8c9644376326 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -343,14 +343,13 @@ static int get_hbp_len(u8 hbp_len)  /*   * Check whether bp virtual address is in kernel space.   */ -int arch_check_bp_in_kernelspace(struct perf_event *bp) +int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw)  {  	unsigned int len;  	unsigned long va; -	struct arch_hw_breakpoint *info = counter_arch_bp(bp); -	va = info->address; -	len = get_hbp_len(info->ctrl.len); +	va = hw->address; +	len = get_hbp_len(hw->ctrl.len);  	return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);  } @@ -421,53 +420,53 @@ int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,  /*   * Construct an arch_hw_breakpoint from a perf_event.   */ -static int arch_build_bp_info(struct perf_event *bp) +static int arch_build_bp_info(struct perf_event *bp, +			      const struct perf_event_attr *attr, +			      struct arch_hw_breakpoint *hw)  { -	struct arch_hw_breakpoint *info = counter_arch_bp(bp); -  	/* Type */ -	switch (bp->attr.bp_type) { +	switch (attr->bp_type) {  	case HW_BREAKPOINT_X: -		info->ctrl.type = ARM_BREAKPOINT_EXECUTE; +		hw->ctrl.type = ARM_BREAKPOINT_EXECUTE;  		break;  	case HW_BREAKPOINT_R: -		info->ctrl.type = ARM_BREAKPOINT_LOAD; +		hw->ctrl.type = ARM_BREAKPOINT_LOAD;  		break;  	case HW_BREAKPOINT_W: -		info->ctrl.type = ARM_BREAKPOINT_STORE; +		hw->ctrl.type = ARM_BREAKPOINT_STORE;  		break;  	case HW_BREAKPOINT_RW: -		info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE; +		hw->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE;  		break;  	default:  		return -EINVAL;  	}  	/* Len */ -	switch (bp->attr.bp_len) { +	switch (attr->bp_len) {  	case HW_BREAKPOINT_LEN_1: -		info->ctrl.len = ARM_BREAKPOINT_LEN_1; +		hw->ctrl.len = ARM_BREAKPOINT_LEN_1;  		break;  	case HW_BREAKPOINT_LEN_2: -		info->ctrl.len = ARM_BREAKPOINT_LEN_2; +		hw->ctrl.len = ARM_BREAKPOINT_LEN_2;  		break;  	case HW_BREAKPOINT_LEN_3: -		info->ctrl.len = ARM_BREAKPOINT_LEN_3; +		hw->ctrl.len = ARM_BREAKPOINT_LEN_3;  		break;  	case HW_BREAKPOINT_LEN_4: -		info->ctrl.len = ARM_BREAKPOINT_LEN_4; +		hw->ctrl.len = ARM_BREAKPOINT_LEN_4;  		break;  	case HW_BREAKPOINT_LEN_5: -		info->ctrl.len = ARM_BREAKPOINT_LEN_5; +		hw->ctrl.len = ARM_BREAKPOINT_LEN_5;  		break;  	case HW_BREAKPOINT_LEN_6: -		info->ctrl.len = ARM_BREAKPOINT_LEN_6; +		hw->ctrl.len = ARM_BREAKPOINT_LEN_6;  		break;  	case HW_BREAKPOINT_LEN_7: -		info->ctrl.len = ARM_BREAKPOINT_LEN_7; +		hw->ctrl.len = ARM_BREAKPOINT_LEN_7;  		break;  	case HW_BREAKPOINT_LEN_8: -		info->ctrl.len = ARM_BREAKPOINT_LEN_8; +		hw->ctrl.len = ARM_BREAKPOINT_LEN_8;  		break;  	default:  		return -EINVAL; @@ -478,37 +477,37 @@ static int arch_build_bp_info(struct perf_event *bp)  	 * AArch32 also requires breakpoints of length 2 for Thumb.  	 * Watchpoints can be of length 1, 2, 4 or 8 bytes.  	 */ -	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { +	if (hw->ctrl.type == ARM_BREAKPOINT_EXECUTE) {  		if (is_compat_bp(bp)) { -			if (info->ctrl.len != ARM_BREAKPOINT_LEN_2 && -			    info->ctrl.len != ARM_BREAKPOINT_LEN_4) +			if (hw->ctrl.len != ARM_BREAKPOINT_LEN_2 && +			    hw->ctrl.len != ARM_BREAKPOINT_LEN_4)  				return -EINVAL; -		} else if (info->ctrl.len != ARM_BREAKPOINT_LEN_4) { +		} else if (hw->ctrl.len != ARM_BREAKPOINT_LEN_4) {  			/*  			 * FIXME: Some tools (I'm looking at you perf) assume  			 *	  that breakpoints should be sizeof(long). This  			 *	  is nonsense. For now, we fix up the parameter  			 *	  but we should probably return -EINVAL instead.  			 */ -			info->ctrl.len = ARM_BREAKPOINT_LEN_4; +			hw->ctrl.len = ARM_BREAKPOINT_LEN_4;  		}  	}  	/* Address */ -	info->address = bp->attr.bp_addr; +	hw->address = attr->bp_addr;  	/*  	 * Privilege  	 * Note that we disallow combined EL0/EL1 breakpoints because  	 * that would complicate the stepping code.  	 */ -	if (arch_check_bp_in_kernelspace(bp)) -		info->ctrl.privilege = AARCH64_BREAKPOINT_EL1; +	if (arch_check_bp_in_kernelspace(hw)) +		hw->ctrl.privilege = AARCH64_BREAKPOINT_EL1;  	else -		info->ctrl.privilege = AARCH64_BREAKPOINT_EL0; +		hw->ctrl.privilege = AARCH64_BREAKPOINT_EL0;  	/* Enabled? */ -	info->ctrl.enabled = !bp->attr.disabled; +	hw->ctrl.enabled = !attr->disabled;  	return 0;  } @@ -516,14 +515,15 @@ static int arch_build_bp_info(struct perf_event *bp)  /*   * Validate the arch-specific HW Breakpoint register settings.   */ -int arch_validate_hwbkpt_settings(struct perf_event *bp) +int hw_breakpoint_arch_parse(struct perf_event *bp, +			     const struct perf_event_attr *attr, +			     struct arch_hw_breakpoint *hw)  { -	struct arch_hw_breakpoint *info = counter_arch_bp(bp);  	int ret;  	u64 alignment_mask, offset;  	/* Build the arch_hw_breakpoint. */ -	ret = arch_build_bp_info(bp); +	ret = arch_build_bp_info(bp, attr, hw);  	if (ret)  		return ret; @@ -537,42 +537,42 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)  	 * that here.  	 */  	if (is_compat_bp(bp)) { -		if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) +		if (hw->ctrl.len == ARM_BREAKPOINT_LEN_8)  			alignment_mask = 0x7;  		else  			alignment_mask = 0x3; -		offset = info->address & alignment_mask; +		offset = hw->address & alignment_mask;  		switch (offset) {  		case 0:  			/* Aligned */  			break;  		case 1:  			/* Allow single byte watchpoint. */ -			if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) +			if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1)  				break;  		case 2:  			/* Allow halfword watchpoints and breakpoints. */ -			if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) +			if (hw->ctrl.len == ARM_BREAKPOINT_LEN_2)  				break;  		default:  			return -EINVAL;  		}  	} else { -		if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) +		if (hw->ctrl.type == ARM_BREAKPOINT_EXECUTE)  			alignment_mask = 0x3;  		else  			alignment_mask = 0x7; -		offset = info->address & alignment_mask; +		offset = hw->address & alignment_mask;  	} -	info->address &= ~alignment_mask; -	info->ctrl.len <<= offset; +	hw->address &= ~alignment_mask; +	hw->ctrl.len <<= offset;  	/*  	 * Disallow per-task kernel breakpoints since these would  	 * complicate the stepping code.  	 */ -	if (info->ctrl.privilege == AARCH64_BREAKPOINT_EL1 && bp->hw.target) +	if (hw->ctrl.privilege == AARCH64_BREAKPOINT_EL1 && bp->hw.target)  		return -EINVAL;  	return 0; |