| Upstream-Status: Backport |
| |
| From ca6d916a6f8f0f8abbb4c9b6a97dd1a1615bb124 Mon Sep 17 00:00:00 2001 |
| From: Maynard Johnson <maynardj@us.ibm.com> |
| Date: Wed, 5 Dec 2012 10:16:35 -0600 |
| Subject: [PATCH] Fix up configure to handle architectures that do not |
| implement perf_event_open |
| |
| This patch fixes the following problems: |
| |
| 1) The configure script allows the user to pass a location to kernel |
| headers (via --with-kernel option) such that, even if the running |
| kernel does not have perf_events support, it may be possible to |
| build operf (e.g., in cross-compile environments). But the message |
| 'This kernel does not have perf_events support; falling back to legacy |
| oprofile' was being displayed inappropriately in such cases. This |
| patch changes the configure script so that the "falling back to |
| legacy oprofile" message will only be displayed if we're running |
| on a kernel that does not have perf_events support AND the user |
| did not pass specify the "--with-kernel" option. |
| |
| 2) Some architectures don't even implement the perf_event_open syscall, so the |
| configure script must do more than checking kernel version and whether or not |
| perf_event.h is present in order to decide if perf_events is supported. |
| This patch provides that extra capability. |
| |
| These problems were reported by Tony Jones <tonyj@suse.com>. |
| |
| Signed-off-by: Maynard Johnson <maynardj@us.ibm.com> |
| --- |
| configure.ac | 74 +++++++++++++++++++++++++++++----------- |
| utils/op_perf_events_checker.c | 6 ++-- |
| 2 files changed, 58 insertions(+), 22 deletions(-) |
| |
| diff --git a/configure.ac b/configure.ac |
| --- a/configure.ac |
| +++ b/configure.ac |
| @@ -70,35 +70,70 @@ KERNELDIR=$withval) |
| |
| |
| dnl Check kernel version for perf_events supported |
| -AC_MSG_CHECKING([kernel version supports perf_events]) |
| if test "$KERNELDIR" != ""; then |
| KINC="$KERNELDIR/include" |
| + PERF_EVENT_FLAGS=" -I$KERNELDIR/include" |
| + AC_SUBST(PERF_EVENT_FLAGS) |
| + PERF_EVENT_H="$KERNELDIR/include/linux/perf_event.h" |
| +else |
| + PERF_EVENT_H="/usr/include/linux/perf_event.h" |
| fi |
| -AX_KERNEL_VERSION(2, 6, 31, <=, kernel_has_perf_events_support="yes", |
| + |
| +PERF_EVENT_H_EXISTS="no" |
| +kernel_may_have_perf_events_support="no" |
| +AX_KERNEL_VERSION(2, 6, 31, <=, kernel_may_have_perf_events_support="yes", |
| kernel_has_perf_events_support="no") |
| |
| -if test "$kernel_has_perf_events_support" = "no"; then |
| - AC_MSG_RESULT([This kernel does not have perf_events support; falling back to legacy oprofile]) |
| +dnl The AX_KERNEL_VERSION macro may return kernel_may_have_perf_events_support="yes", |
| +dnl indicating a partial answer. Some architectures do not implement the Performance |
| +dnl Events Kernel Subsystem even with kernel versions > 2.6.31 -- i.e., not even |
| +dnl implementing the perf_event_open syscall to return ENOSYS. So the check below |
| +dnl will identify and handle such situations. |
| + |
| +if test "$kernel_may_have_perf_events_support" = "yes"; then |
| + AC_CHECK_HEADER($PERF_EVENT_H,PERF_EVENT_H_EXISTS="yes") |
| + AC_MSG_CHECKING([kernel supports perf_events]) |
| + if test "$PERF_EVENT_H_EXISTS" = "yes"; then |
| + rm -f test-for-PERF_EVENT_OPEN |
| + AC_LANG_CONFTEST( |
| + [AC_LANG_PROGRAM([[#include <linux/perf_event.h> |
| + #include <asm/unistd.h> |
| + #include <sys/types.h> |
| + #include <string.h> |
| + ]], |
| + [[struct perf_event_attr attr; |
| + pid_t pid; |
| + memset(&attr, 0, sizeof(attr)); |
| + attr.size = sizeof(attr); |
| + attr.sample_type = PERF_SAMPLE_IP; |
| + pid = getpid(); |
| + syscall(__NR_perf_event_open, &attr, pid, 0, -1, 0); |
| + ]]) |
| + ]) |
| + $CC conftest.$ac_ext $CFLAGS $LDFLAGS $LIBS $PERF_EVENT_FLAGS -o test-for-PERF_EVENT_OPEN > /dev/null 2>&1 |
| + if test -f test-for-PERF_EVENT_OPEN; then |
| + kernel_has_perf_events_support="yes" |
| + AC_MSG_RESULT(yes) |
| + else |
| + AC_MSG_RESULT(no) |
| + kernel_has_perf_events_support="no" |
| + fi |
| + else |
| + AC_MSG_RESULT(unknown -- perf_event.h not found) |
| + fi |
| else |
| - AC_MSG_RESULT([This kernel has perf_events support]) |
| + AC_MSG_RESULT(kernel supports perf_events... no) |
| + kernel_has_perf_events_support="no" |
| +fi |
| +AM_CONDITIONAL(BUILD_FOR_PERF_EVENT, test "$kernel_has_perf_events_support" = "yes") |
| + |
| +if test "$kernel_has_perf_events_support" = "yes"; then |
| + HAVE_PERF_EVENTS='1' |
| +else |
| + HAVE_PERF_EVENTS='0' |
| + AC_MSG_RESULT([No perf_events support available; falling back to legacy oprofile]) |
| fi |
| |
| -if test "$KERNELDIR" == ""; then |
| - PERF_EVENT_H="/usr/include/linux/perf_event.h" |
| -else |
| - PERF_EVENT_H="$KERNELDIR/include/linux/perf_event.h" |
| -fi |
| -AC_CHECK_HEADER($PERF_EVENT_H,PERF_EVENT_H_EXISTS="yes") |
| -AM_CONDITIONAL(BUILD_FOR_PERF_EVENT, test -n "$PERF_EVENT_H_EXISTS") |
| -if test "$PERF_EVENT_H_EXISTS" = "yes"; then |
| - HAVE_PERF_EVENTS='1' |
| - if test "$KERNELDIR" != ""; then |
| - PERF_EVENT_FLAGS=" -I$KERNELDIR/include" |
| - AC_SUBST(PERF_EVENT_FLAGS) |
| - fi |
| -else |
| - HAVE_PERF_EVENTS='0' |
| -fi |
| AC_DEFINE_UNQUOTED(HAVE_PERF_EVENTS, $HAVE_PERF_EVENTS, [Kernel support for perf_events exists]) |
| AC_CANONICAL_HOST |
| if test "$HAVE_PERF_EVENTS" = "1"; then |
| @@ -414,7 +449,7 @@ elif test "`getent passwd oprofile 2>/de |
| fi |
| fi |
| |
| -if test "$PERF_EVENT_H_EXISTS" != "yes" && test "$kernel_has_perf_events_support" = "yes"; then |
| +if test "$PERF_EVENT_H_EXISTS" != "yes" && test "$kernel_may_have_perf_events_support" = "yes"; then |
| echo "Warning: perf_event.h not found. Please install the kernel headers package if you" |
| echo " want non-root support built into OProfile." |
| fi |
| diff --git a/utils/op_perf_events_checker.c b/utils/op_perf_events_checker.c |
| --- a/utils/op_perf_events_checker.c |
| +++ b/utils/op_perf_events_checker.c |
| @@ -49,8 +49,10 @@ int main(int argc, char **argv) |
| } |
| |
| #if HAVE_PERF_EVENTS |
| - /* If perf_events syscall is not implemented, the syscall below will fail |
| - * with ENOSYS (38). If implemented, but the processor type on which this |
| + /* Even if the perf_event_open syscall is implemented, the architecture may still |
| + * not provide a full implementation of the perf_events subsystem, in which case, |
| + * the syscall below will fail with ENOSYS (38). If the perf_events subsystem is |
| + * implemented for the architecture, but the processor type on which this |
| * program is running is not supported by perf_events, the syscall returns |
| * ENOENT (2). |
| */ |