diff options
Diffstat (limited to 'kernel/events')
-rw-r--r-- | kernel/events/hw_breakpoint.c | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c index 6e28d2866be5..314e2a9040c7 100644 --- a/kernel/events/hw_breakpoint.c +++ b/kernel/events/hw_breakpoint.c @@ -400,16 +400,35 @@ int dbg_release_bp_slot(struct perf_event *bp) return 0; } -static int validate_hw_breakpoint(struct perf_event *bp) +#ifndef hw_breakpoint_arch_parse +int hw_breakpoint_arch_parse(struct perf_event *bp, + const struct perf_event_attr *attr, + struct arch_hw_breakpoint *hw) { - int ret; + int err; - ret = arch_validate_hwbkpt_settings(bp); - if (ret) - return ret; + err = arch_validate_hwbkpt_settings(bp); + if (err) + return err; + + *hw = bp->hw.info; + + return 0; +} +#endif + +static int hw_breakpoint_parse(struct perf_event *bp, + const struct perf_event_attr *attr, + struct arch_hw_breakpoint *hw) +{ + int err; + + err = hw_breakpoint_arch_parse(bp, attr, hw); + if (err) + return err; if (arch_check_bp_in_kernelspace(bp)) { - if (bp->attr.exclude_kernel) + if (attr->exclude_kernel) return -EINVAL; /* * Don't let unprivileged users set a breakpoint in the trap @@ -424,19 +443,22 @@ static int validate_hw_breakpoint(struct perf_event *bp) int register_perf_hw_breakpoint(struct perf_event *bp) { - int ret; - - ret = reserve_bp_slot(bp); - if (ret) - return ret; + struct arch_hw_breakpoint hw; + int err; - ret = validate_hw_breakpoint(bp); + err = reserve_bp_slot(bp); + if (err) + return err; - /* if arch_validate_hwbkpt_settings() fails then release bp slot */ - if (ret) + err = hw_breakpoint_parse(bp, &bp->attr, &hw); + if (err) { release_bp_slot(bp); + return err; + } - return ret; + bp->hw.info = hw; + + return 0; } /** @@ -464,6 +486,7 @@ modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *a u64 old_len = bp->attr.bp_len; int old_type = bp->attr.bp_type; bool modify = attr->bp_type != old_type; + struct arch_hw_breakpoint hw; int err = 0; bp->attr.bp_addr = attr->bp_addr; @@ -473,7 +496,7 @@ modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *a if (check && memcmp(&bp->attr, attr, sizeof(*attr))) return -EINVAL; - err = validate_hw_breakpoint(bp); + err = hw_breakpoint_parse(bp, attr, &hw); if (!err && modify) err = modify_bp_slot(bp, old_type); @@ -484,7 +507,9 @@ modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *a return err; } + bp->hw.info = hw; bp->attr.disabled = attr->disabled; + return 0; } |