diff options
Diffstat (limited to 'arch/sh/kernel/hw_breakpoint.c')
| -rw-r--r-- | arch/sh/kernel/hw_breakpoint.c | 53 | 
1 files changed, 23 insertions, 30 deletions
diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c index 8648ed05ccf0..d9ff3b42da7c 100644 --- a/arch/sh/kernel/hw_breakpoint.c +++ b/arch/sh/kernel/hw_breakpoint.c @@ -124,14 +124,13 @@ static int get_hbp_len(u16 hbp_len)  /*   * Check for virtual address 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->len); +	va = hw->address; +	len = get_hbp_len(hw->len);  	return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);  } @@ -174,40 +173,40 @@ int arch_bp_generic_fields(int sh_len, int sh_type,  	return 0;  } -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); - -	info->address = bp->attr.bp_addr; +	hw->address = attr->bp_addr;  	/* Len */ -	switch (bp->attr.bp_len) { +	switch (attr->bp_len) {  	case HW_BREAKPOINT_LEN_1: -		info->len = SH_BREAKPOINT_LEN_1; +		hw->len = SH_BREAKPOINT_LEN_1;  		break;  	case HW_BREAKPOINT_LEN_2: -		info->len = SH_BREAKPOINT_LEN_2; +		hw->len = SH_BREAKPOINT_LEN_2;  		break;  	case HW_BREAKPOINT_LEN_4: -		info->len = SH_BREAKPOINT_LEN_4; +		hw->len = SH_BREAKPOINT_LEN_4;  		break;  	case HW_BREAKPOINT_LEN_8: -		info->len = SH_BREAKPOINT_LEN_8; +		hw->len = SH_BREAKPOINT_LEN_8;  		break;  	default:  		return -EINVAL;  	}  	/* Type */ -	switch (bp->attr.bp_type) { +	switch (attr->bp_type) {  	case HW_BREAKPOINT_R: -		info->type = SH_BREAKPOINT_READ; +		hw->type = SH_BREAKPOINT_READ;  		break;  	case HW_BREAKPOINT_W: -		info->type = SH_BREAKPOINT_WRITE; +		hw->type = SH_BREAKPOINT_WRITE;  		break;  	case HW_BREAKPOINT_W | HW_BREAKPOINT_R: -		info->type = SH_BREAKPOINT_RW; +		hw->type = SH_BREAKPOINT_RW;  		break;  	default:  		return -EINVAL; @@ -219,19 +218,20 @@ 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);  	unsigned int align;  	int ret; -	ret = arch_build_bp_info(bp); +	ret = arch_build_bp_info(bp, attr, hw);  	if (ret)  		return ret;  	ret = -EINVAL; -	switch (info->len) { +	switch (hw->len) {  	case SH_BREAKPOINT_LEN_1:  		align = 0;  		break; @@ -249,17 +249,10 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)  	}  	/* -	 * For kernel-addresses, either the address or symbol name can be -	 * specified. -	 */ -	if (info->name) -		info->address = (unsigned long)kallsyms_lookup_name(info->name); - -	/*  	 * Check that the low-order bits of the address are appropriate  	 * for the alignment implied by len.  	 */ -	if (info->address & align) +	if (hw->address & align)  		return -EINVAL;  	return 0; @@ -346,7 +339,7 @@ static int __kprobes hw_breakpoint_handler(struct die_args *args)  		perf_bp_event(bp, args->regs);  		/* Deliver the signal to userspace */ -		if (!arch_check_bp_in_kernelspace(bp)) { +		if (!arch_check_bp_in_kernelspace(&bp->hw.info)) {  			force_sig_fault(SIGTRAP, TRAP_HWBKPT,  					(void __user *)NULL, current);  		}  |