The perf_event test currently uses hard-coded 0 as the CPU index. Howver, if CPU#0 happens to be offline, the test then fails because perf_event_open(2) returns -ENODEV. To fix this, try to find the index of the first online CPU and use that instead of the hard-coded value. Verified to work well on a machine with the first 8 CPU cores offline. Signed-off-by: Ondrej Mosnacek <omosnace@xxxxxxxxxx> --- tests/perf_event/perf_event.c | 23 ++++++++++++++--------- tests/perf_event/test | 32 +++++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/tests/perf_event/perf_event.c b/tests/perf_event/perf_event.c index 453aa91..0e8bdce 100644 --- a/tests/perf_event/perf_event.c +++ b/tests/perf_event/perf_event.c @@ -20,13 +20,14 @@ enum { static void print_usage(char *progname) { fprintf(stderr, - "usage: %s [-f|-m] [-v] EVENT_ID\n" + "usage: %s [-f|-m] [-v] CPU EVENT_ID\n" "Where:\n\t" + "CPU target CPU (must be online)\n\n\t" "EVENT_ID target ftrace event ID\n\n\t" - "-f Read perf_event info using read(2)\n\t" - "-m Read perf_event info using mmap(2)\n\t" - " Default is to use read(2) and mmap(2)\n\t" - "-v Print information\n", progname); + "-f Read perf_event info using read(2)\n\t" + "-m Read perf_event info using mmap(2)\n\t" + " Default is to use read(2) and mmap(2)\n\t" + "-v Print information\n", progname); exit(-1); } @@ -39,7 +40,7 @@ static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int main(int argc, char **argv) { - int opt, result, page_size, mmap_size, fd; + int opt, result, page_size, mmap_size, fd, cpu; long long count, event_id; bool verbose = false; char *context; @@ -65,10 +66,14 @@ int main(int argc, char **argv) } } - if ((argc - optind) != 1) + if ((argc - optind) != 2) print_usage(argv[0]); - event_id = atoll(argv[optind]); + cpu = atoi(argv[optind]); + if (cpu < 0) + print_usage(argv[0]); + + event_id = atoll(argv[optind + 1]); if (event_id < 0) print_usage(argv[0]); @@ -90,7 +95,7 @@ int main(int argc, char **argv) pe_attr.disabled = 1; pe_attr.exclude_hv = 1; - fd = perf_event_open(&pe_attr, -1, 0, -1, 0); + fd = perf_event_open(&pe_attr, -1, cpu, -1, 0); if (fd < 0) { fprintf(stderr, "Failed perf_event_open(): %s\n", strerror(errno)); diff --git a/tests/perf_event/test b/tests/perf_event/test index 380d9cc..c336477 100755 --- a/tests/perf_event/test +++ b/tests/perf_event/test @@ -48,56 +48,70 @@ BEGIN { plan tests => $test_count; } +# find some CPU that is online +for ( $cpu = 0 ; -e "/sys/devices/system/cpu/cpu$cpu" ; $cpu++ ) { + + # if the "online" file doesn't exist, the CPU can't be offline + last unless -e "/sys/devices/system/cpu/cpu$cpu/online"; + + $online = `cat /sys/devices/system/cpu/cpu$cpu/online`; + chomp($online); + last if ( $online eq "1" ); +} + $event_id = `cat /sys/kernel/debug/tracing/events/ftrace/function/id`; chomp($event_id); # perf_event { open cpu kernel tracepoint read write }; print "Test perf_event\n"; -$result = system "runcon -t test_perf_t $basedir/perf_event $v $event_id"; +$result = system "runcon -t test_perf_t $basedir/perf_event $v $cpu $event_id"; ok( $result eq 0 ); if ($capability) { # Deny capability { perfmon } - EACCES perf_event_open(2) $result = system - "runcon -t test_perf_no_cap_t $basedir/perf_event $v $event_id 2>&1"; + "runcon -t test_perf_no_cap_t $basedir/perf_event $v $cpu $event_id 2>&1"; ok( $result >> 8 eq 1 ); } # Deny perf_event { open } - EACCES perf_event_open(2) $result = - system "runcon -t test_perf_no_open_t $basedir/perf_event $v $event_id 2>&1"; + system + "runcon -t test_perf_no_open_t $basedir/perf_event $v $cpu $event_id 2>&1"; ok( $result >> 8 eq 1 ); # Deny perf_event { cpu } - EACCES perf_event_open(2) $result = - system "runcon -t test_perf_no_cpu_t $basedir/perf_event $v $event_id 2>&1"; + system + "runcon -t test_perf_no_cpu_t $basedir/perf_event $v $cpu $event_id 2>&1"; ok( $result >> 8 eq 1 ); # Deny perf_event { kernel } - EACCES perf_event_open(2) $result = system - "runcon -t test_perf_no_kernel_t $basedir/perf_event $v $event_id 2>&1"; + "runcon -t test_perf_no_kernel_t $basedir/perf_event $v $cpu $event_id 2>&1"; ok( $result >> 8 eq 1 ); # Deny perf_event { tracepoint } - EACCES perf_event_open(2) $result = system - "runcon -t test_perf_no_tracepoint_t $basedir/perf_event $v $event_id 2>&1"; +"runcon -t test_perf_no_tracepoint_t $basedir/perf_event $v $cpu $event_id 2>&1"; ok( $result >> 8 eq 1 ); # Deny perf_event { read } - EACCES mmap(2) $result = system - "runcon -t test_perf_no_read_t $basedir/perf_event -m $v $event_id 2>&1"; + "runcon -t test_perf_no_read_t $basedir/perf_event -m $v $cpu $event_id 2>&1"; ok( $result >> 8 eq 6 ); # Deny perf_event { read } - EACCES read(2) $result = system - "runcon -t test_perf_no_read_t $basedir/perf_event -f $v $event_id 2>&1"; + "runcon -t test_perf_no_read_t $basedir/perf_event -f $v $cpu $event_id 2>&1"; ok( $result >> 8 eq 7 ); # Deny perf_event { write } - EACCES ioctl(2) write $result = - system "runcon -t test_perf_no_write_t $basedir/perf_event $v $event_id 2>&1"; + system + "runcon -t test_perf_no_write_t $basedir/perf_event $v $cpu $event_id 2>&1"; ok( $result >> 8 eq 2 ); exit; -- 2.31.1