Event attribute validation is one of the biggest sources of EINVALs around perf_event_open() syscall. This patch annotates error checks with extended error reporting macros to provide the user with more details on what they are doing wrong.
Signed-off-by: Alexander Shishkin <alexander.shish...@linux.intel.com> --- arch/x86/kernel/cpu/perf_event_intel_pt.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c index 4216928344..9a09c89928 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_pt.c +++ b/arch/x86/kernel/cpu/perf_event_intel_pt.c @@ -18,6 +18,8 @@ #undef DEBUG +#define PERF_MODNAME "perf/x86/intel/pt" + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/types.h> @@ -198,29 +200,29 @@ fail: RTIT_CTL_CYC_PSB | \ RTIT_CTL_MTC) -static bool pt_event_valid(struct perf_event *event) +static int pt_event_valid(struct perf_event *event) { u64 config = event->attr.config; u64 allowed, requested; if ((config & PT_CONFIG_MASK) != config) - return false; + return perf_err(-EINVAL, "PT config: disallowed bits"); if (config & RTIT_CTL_CYC_PSB) { if (!pt_cap_get(PT_CAP_psb_cyc)) - return false; + return perf_err(-EINVAL, "PT config: PSB/CYC not supported"); allowed = pt_cap_get(PT_CAP_psb_periods); requested = (config & RTIT_CTL_PSB_FREQ) >> RTIT_CTL_PSB_FREQ_OFFSET; if (requested && (!(allowed & BIT(requested)))) - return false; + return perf_err(-EINVAL, "PT config: unsupported PSB period"); allowed = pt_cap_get(PT_CAP_cycle_thresholds); requested = (config & RTIT_CTL_CYC_THRESH) >> RTIT_CTL_CYC_THRESH_OFFSET; if (requested && (!(allowed & BIT(requested)))) - return false; + return perf_err(-EINVAL, "PT config: unsupported CYC threshold"); } if (config & RTIT_CTL_MTC) { @@ -232,20 +234,20 @@ static bool pt_event_valid(struct perf_event *event) * CPUID is 0 will #GP, so better safe than sorry. */ if (!pt_cap_get(PT_CAP_mtc)) - return false; + return perf_err(-EINVAL, "PT config: MTC not supported"); allowed = pt_cap_get(PT_CAP_mtc_periods); if (!allowed) - return false; + return perf_err(-EINVAL, "PT config: MTC periods not supported"); requested = (config & RTIT_CTL_MTC_RANGE) >> RTIT_CTL_MTC_RANGE_OFFSET; if (!(allowed & BIT(requested))) - return false; + return perf_err(-EINVAL, "PT config: unsupported MTC period"); } - return true; + return 0; } /* @@ -1111,14 +1113,17 @@ static void pt_event_destroy(struct perf_event *event) static int pt_event_init(struct perf_event *event) { + int err; + if (event->attr.type != pt_pmu.pmu.type) return -ENOENT; - if (!pt_event_valid(event)) - return -EINVAL; + err = pt_event_valid(event); + if (err) + return err; if (x86_add_exclusive(x86_lbr_exclusive_pt)) - return -EBUSY; + return perf_err(-EBUSY, "PT conflicts with active events"); event->destroy = pt_event_destroy; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/