*
*/
+#include <errno.h>
#include <stdio.h>
-#include <perfmon/pfmlib.h>
#include <string.h>
+#include <linux/perf_event.h>
+#include <perfmon/perf_event.h>
+#include <perfmon/pfmlib_perf_event.h>
+
int main(int argc, char **argv)
{
- int ret, i;
- unsigned int j;
- pfm_pmu_info_t pinfo;
+ int ret, fd;
+
+ /* pfm query objects */
+ pfm_perf_encode_arg_t pencoder;
+ pfm_event_info_t info;
+
+ /* Perf event object to be populated by libpfm */
+ struct perf_event_attr attr;
if (argc != 2) {
fprintf(stderr, "Usage: %s <pmu counter to find>\n"
"ex: %s UNHALTED_REFERENCE_CYCLES\n"
- "Returns the first occurence it finds with "
+ "Returns the event raw number if found and actionable with"
"return code 0.\n"
- "If not found returns 1, on error returns -1\n",
+ "If not found returns 1,"
+ "If not actionable return 2,"
+ "on error returns 255\n",
argv[0], argv[0]);
ret = -1;
goto end;
}
- memset(&pinfo, 0, sizeof(pinfo));
- pinfo.size = sizeof(pinfo);
+ /* Initialize perf_event_attr. */
+ memset(&attr, 0, sizeof(struct perf_event_attr));
+
+ /* Initialize libpfm encoder structure. */
+ memset(&pencoder, 0, sizeof(pencoder));
+ pencoder.size = sizeof(pfm_perf_encode_arg_t);
+
+ /* Initialize libpfm event info structure. */
+ memset(&info, 0, sizeof(info));
+ info.size = sizeof(info);
+
+ /* Prepare the encoder for query. */
+ pencoder.attr = &attr; /* Set the perf_event_attr pointer. */
+ pencoder.fstr = NULL; /* Not interested by the fully qualified event string. */
ret = pfm_initialize();
if (ret != PFM_SUCCESS) {
fprintf(stderr, "Failed to initialise libpfm: %s",
pfm_strerror(ret));
- ret = -1;
+ ret = 255;
+ goto end;
+ }
+
+ ret = pfm_get_os_event_encoding(argv[1],
+ PFM_PLM0 | PFM_PLM1 | PFM_PLM2 | PFM_PLM3,
+ PFM_OS_PERF_EVENT, &pencoder);
+ if (ret != PFM_SUCCESS) {
+ fprintf(stderr, "libpfm: error pfm_get_os_event_encoding: %s\n",
+ pfm_strerror(ret));
+ ret = 1;
+ goto end;
+ }
+
+ /*
+ * Query the raw code for later use. Do it now to simplify error
+ * management.
+ */
+ ret = pfm_get_event_info(pencoder.idx, PFM_OS_NONE, &info);
+ if (ret != PFM_SUCCESS) {
+ fprintf(stderr, "libpfm: error pfm_get_event_info: %s\n", pfm_strerror(ret));
+ ret = 1;
goto end;
}
- pfm_for_all_pmus(j) {
- ret = pfm_get_pmu_info(j, &pinfo);
- if (ret != PFM_SUCCESS) {
- continue;
- }
-
- for (i = pinfo.first_event; i != -1; i = pfm_get_event_next(i)) {
- pfm_event_info_t info =
- { .size = sizeof(pfm_event_info_t) };
-
- ret = pfm_get_event_info(i, PFM_OS_NONE, &info);
- if (ret != PFM_SUCCESS) {
- fprintf(stderr, "Cannot get event info: %s\n",
- pfm_strerror(ret));
- ret = -1;
- goto end;
- }
-
- if (info.pmu != j) {
- continue;
- }
-
- if (strcmp(info.name, argv[1]) == 0) {
- fprintf(stdout, "r%" PRIx64 "\n", info.code);
- ret = 0;
- goto end;
- }
- }
+ /*
+ * Now that the event is found, try to use it to validate that
+ * the current user has access to it and that it can be used on that
+ * host.
+ */
+
+ /* Set the event to disabled to prevent unnecessary side effects. */
+ pencoder.attr->disabled = 1;
+
+ /* perf_event_open is provided by perfmon/perf_event.h. */
+ fd = perf_event_open(pencoder.attr, 0, -1, -1, 0);
+ if (fd == -1) {
+ fprintf(stderr, "perf: error perf_event_open: %d: %s\n", errno,
+ strerror(errno));
+ ret = 2;
+ goto end;
}
- ret = 1;
+ /* We close the fd immediately since the event is actionable. */
+ close(fd);
+
+ /* Output the raw code for the event */
+ fprintf(stdout, "r%" PRIx64 "\n", info.code);
+ ret = 0;
end:
return ret;
function test_ust_raw()
{
- TRACE_PATH=$(mktemp -d)
- SESSION_NAME="ust_perf"
- CHAN_NAME="mychan"
- EVENT_NAME="tp:tptest"
- PMU="UNHALTED_REFERENCE_CYCLES"
- PERFID=$($CURDIR/find_event $PMU)
- test $? -eq "0"
- ok $? "Find PMU $PMU"
+ local TRACE_PATH=$(mktemp -d)
+ local SESSION_NAME="ust_perf"
+ local CHAN_NAME="mychan"
+ local EVENT_NAME="tp:tptest"
+ local PMU="UNHALTED_REFERENCE_CYCLES"
+ local tests_to_skip=9
+ local ret
+
+ # Find the raw perf id of the event.
+ PERFID=$("$CURDIR/find_event" "$PMU")
+ ret=$?
+ if [ "$ret" -eq "0" ]; then
+ pass "Find PMU $PMU"
+ elif [ "$ret" -eq "1" ]; then
+ skip 0 "PMU event not found." $tests_to_skip
+ return
+ elif [ "$ret" -eq "2" ]; then
+ skip 0 "PMU event not actionable." $tests_to_skip
+ return
+ else
+ fail "find_event returned $ret."
+ return
+ fi
create_lttng_session_ok $SESSION_NAME $TRACE_PATH
function test_kernel_raw()
{
- TRACE_PATH=$(mktemp -d)
- SESSION_NAME="kernel_perf"
- CHAN_NAME="mychan"
- EVENT_NAME="lttng_test_filter_event"
- PMU="UNHALTED_REFERENCE_CYCLES"
- PERFID=$($CURDIR/find_event $PMU)
- test $? -eq "0"
- ok $? "Find PMU $PMU"
+ local TRACE_PATH=$(mktemp -d)
+ local SESSION_NAME="kernel_perf"
+ local CHAN_NAME="mychan"
+ local EVENT_NAME="lttng_test_filter_event"
+ local PMU="UNHALTED_REFERENCE_CYCLES"
+ local PERFID=""
+ local tests_to_skip=9
+ local ret
+
+ # Find the raw perf id of the event.
+ PERFID=$("$CURDIR/find_event" "$PMU")
+ ret=$?
+ if [ "$ret" -eq "0" ]; then
+ pass "Find PMU $PMU"
+ elif [ "$ret" -eq "1" ]; then
+ skip 0 "PMU event not found." $tests_to_skip
+ return
+ elif [ "$ret" -eq "2" ]; then
+ skip 0 "PMU event not actionable." $tests_to_skip
+ return
+ else
+ fail "find_event returned $ret."
+ return
+ fi
create_lttng_session_ok $SESSION_NAME $TRACE_PATH