All of lore.kernel.org
 help / color / mirror / Atom feed
From: Robert Richter <robert.richter@amd.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>,
	Stephane Eranian <eranian@google.com>,
	LKML <linux-kernel@vger.kernel.org>,
	Robert Richter <robert.richter@amd.com>
Subject: [PATCH] perf: Introduce function to report unsupported syscall attribute flags
Date: Wed, 12 Sep 2012 13:01:25 +0200	[thread overview]
Message-ID: <1347447685-28513-1-git-send-email-robert.richter@amd.com> (raw)

Often a syscall fails with

   Error: sys_perf_event_open() syscall returned with 95 (Operation not supported).  /bin/dmesg may provide additional information.

but no additional information.

This patch adds some macro magic and a helper function to check and
report unsupported syscall attribute flags:

 has_unsupported_flags(attr1, attr2);
 has_unsupported_flag(attr, flag);
 __has_unsupported_flags(const struct perf_event_attr *attr,
                         u64 notsup);

E.g. dmesg reports the following (checking for the exclude_guest
flag):

 perf: unsupported attribute flags: 0000000000100000

or (checking precise modifier :ppp):

 perf: unsupported attribute flags: 0000000000018000

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 arch/x86/kernel/cpu/perf_event.c         |   19 ++++++++++---------
 arch/x86/kernel/cpu/perf_event_amd_ibs.c |    3 ++-
 include/linux/perf_event.h               |   23 +++++++++++++++++++++++
 kernel/events/core.c                     |    2 +-
 4 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 915b876..9ae8676 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -336,7 +336,7 @@ int x86_setup_perfctr(struct perf_event *event)
 			return -EOPNOTSUPP;
 
 		/* BTS is currently only allowed for user-mode. */
-		if (!attr->exclude_kernel)
+		if (has_unsupported_flag(attr, exclude_kernel))
 			return -EOPNOTSUPP;
 	}
 
@@ -389,8 +389,11 @@ int x86_pmu_hw_config(struct perf_event *event)
 				precise++;
 		}
 
-		if (event->attr.precise_ip > precise)
+		if (event->attr.precise_ip > precise) {
+			has_unsupported_flag(&event->attr, precise_ip);
 			return -EOPNOTSUPP;
+		}
+
 		/*
 		 * check that PEBS LBR correction does not conflict with
 		 * whatever the user is asking with attr->branch_sample_type
@@ -398,13 +401,7 @@ int x86_pmu_hw_config(struct perf_event *event)
 		if (event->attr.precise_ip > 1) {
 			u64 *br_type = &event->attr.branch_sample_type;
 
-			if (has_branch_stack(event)) {
-				if (!precise_br_compat(event))
-					return -EOPNOTSUPP;
-
-				/* branch_sample_type is compatible */
-
-			} else {
+			if (!has_branch_stack(event)) {
 				/*
 				 * user did not specify  branch_sample_type
 				 *
@@ -419,7 +416,11 @@ int x86_pmu_hw_config(struct perf_event *event)
 
 				if (!event->attr.exclude_kernel)
 					*br_type |= PERF_SAMPLE_BRANCH_KERNEL;
+			} else if (!precise_br_compat(event)) {
+				has_unsupported_flag(&event->attr, precise_ip);
+				return -EOPNOTSUPP;
 			}
+			/* else: branch_sample_type is compatible */
 		}
 	}
 
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
index 4af8275..fc145b0 100644
--- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c
+++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c
@@ -186,6 +186,7 @@ static int perf_ibs_precise_event(struct perf_event *event, u64 *config)
 	case 2:
 		break;
 	default:
+		has_unsupported_flag(&event->attr, precise_ip);
 		return -EOPNOTSUPP;
 	}
 
@@ -243,7 +244,7 @@ static int perf_ibs_init(struct perf_event *event)
 	if (event->pmu != &perf_ibs->pmu)
 		return -ENOENT;
 
-	if (perf_flags(&event->attr) & perf_flags(&ibs_notsupp))
+	if (has_unsupported_flags(&event->attr, &ibs_notsupp))
 		return -EINVAL;
 
 	if (config & ~perf_ibs->config_mask)
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index c36a04f..eb247a5 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -305,6 +305,14 @@ struct perf_event_attr {
 };
 
 #define perf_flags(attr)	(*(&(attr)->read_format + 1))
+#define perf_flags_init(flag) ({					\
+	volatile __u64	flags = 0;					\
+	struct perf_event_attr *attr;					\
+	attr = (void *)((char *)&flags -				\
+			(char *)&perf_flags((struct perf_event_attr *)(0))); \
+	if (!WARN_ON(&perf_flags(attr) != &flags)) 			\
+		attr->flag = ~0;					\
+	flags;})
 
 /*
  * Ioctls that can be done on a perf event fd:
@@ -1208,6 +1216,21 @@ extern int perf_event_overflow(struct perf_event *event,
 				 struct perf_sample_data *data,
 				 struct pt_regs *regs);
 
+static inline bool __has_unsupported_flags(const struct perf_event_attr *attr,
+					   u64 notsup)
+{
+	notsup &= perf_flags(attr);
+	if (notsup)
+		pr_warn("perf: unsupported attribute flags: %016llx\n", notsup);
+	return notsup != 0;
+}
+
+#define has_unsupported_flags(attr1, attr2) \
+	__has_unsupported_flags((attr1), perf_flags(attr2))
+/* flag is the name of the member in struct perf_event_attr: */
+#define has_unsupported_flag(attr, flag) \
+	__has_unsupported_flags((attr), perf_flags_init(flag))
+
 static inline bool is_sampling_event(struct perf_event *event)
 {
 	return event->attr.sample_period != 0;
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 2ba8904..2667ef6 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6291,7 +6291,7 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr,
 	if (ret)
 		return -EFAULT;
 
-	if (attr->__reserved_1)
+	if (has_unsupported_flag(attr, __reserved_1))
 		return -EINVAL;
 
 	if (attr->sample_type & ~(PERF_SAMPLE_MAX-1))
-- 
1.7.8.6



             reply	other threads:[~2012-09-12 11:02 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-12 11:01 Robert Richter [this message]
2012-09-12 11:20 ` [PATCH] perf: Introduce function to report unsupported syscall attribute flags Peter Zijlstra
2012-09-12 13:02   ` Robert Richter
2012-09-12 14:26   ` Andi Kleen
2012-09-12 14:29     ` Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1347447685-28513-1-git-send-email-robert.richter@amd.com \
    --to=robert.richter@amd.com \
    --cc=eranian@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.