Commit c5b3a094 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'perf-tools-fixes-for-v5.19-2022-06-19' of...

Merge tag 'perf-tools-fixes-for-v5.19-2022-06-19' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tool fixes from Arnaldo Carvalho de Melo:

 - Don't set data source if it's not a memory operation in ARM SPE
   (Statistical Profiling Extensions).

 - Fix handling of exponent floating point values in perf stat
   expressions.

 - Don't leak fd on failure on libperf open.

 - Fix 'perf test' CPU topology test for PPC guest systems.

 - Fix undefined behaviour on breakpoint account 'perf test' entry.

 - Record only user callchains on the "Check ARM64 callgraphs are
   complete in FP mode" 'perf test' entry.

 - Fix "perf stat CSV output linter" test on s390.

 - Sync batch of kernel headers with tools/perf/.

* tag 'perf-tools-fixes-for-v5.19-2022-06-19' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux:
  tools headers UAPI: Sync linux/prctl.h with the kernel sources
  perf metrics: Ensure at least 1 id per metric
  tools headers arm64: Sync arm64's cputype.h with the kernel sources
  tools headers UAPI: Sync x86's asm/kvm.h with the kernel sources
  perf arm-spe: Don't set data source if it's not a memory operation
  perf expr: Allow exponents on floating point values
  perf test topology: Use !strncmp(right platform) to fix guest PPC comparision check
  perf test: Record only user callchains on the "Check Arm64 callgraphs are complete in fp mode" test
  perf beauty: Update copy of linux/socket.h with the kernel sources
  perf test: Fix variable length array undefined behavior in bp_account
  libperf evsel: Open shouldn't leak fd on failure
  perf test: Fix "perf stat CSV output linter" test on s390
  perf unwind: Fix uninitialized variable
parents 59b785fe 140cd9ec
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#define MIDR_VARIANT(midr) \ #define MIDR_VARIANT(midr) \
(((midr) & MIDR_VARIANT_MASK) >> MIDR_VARIANT_SHIFT) (((midr) & MIDR_VARIANT_MASK) >> MIDR_VARIANT_SHIFT)
#define MIDR_IMPLEMENTOR_SHIFT 24 #define MIDR_IMPLEMENTOR_SHIFT 24
#define MIDR_IMPLEMENTOR_MASK (0xff << MIDR_IMPLEMENTOR_SHIFT) #define MIDR_IMPLEMENTOR_MASK (0xffU << MIDR_IMPLEMENTOR_SHIFT)
#define MIDR_IMPLEMENTOR(midr) \ #define MIDR_IMPLEMENTOR(midr) \
(((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT) (((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
...@@ -118,6 +118,10 @@ ...@@ -118,6 +118,10 @@
#define APPLE_CPU_PART_M1_ICESTORM 0x022 #define APPLE_CPU_PART_M1_ICESTORM 0x022
#define APPLE_CPU_PART_M1_FIRESTORM 0x023 #define APPLE_CPU_PART_M1_FIRESTORM 0x023
#define APPLE_CPU_PART_M1_ICESTORM_PRO 0x024
#define APPLE_CPU_PART_M1_FIRESTORM_PRO 0x025
#define APPLE_CPU_PART_M1_ICESTORM_MAX 0x028
#define APPLE_CPU_PART_M1_FIRESTORM_MAX 0x029
#define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
#define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
...@@ -164,6 +168,10 @@ ...@@ -164,6 +168,10 @@
#define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110) #define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110)
#define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM) #define MIDR_APPLE_M1_ICESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM)
#define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM) #define MIDR_APPLE_M1_FIRESTORM MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM)
#define MIDR_APPLE_M1_ICESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_PRO)
#define MIDR_APPLE_M1_FIRESTORM_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_PRO)
#define MIDR_APPLE_M1_ICESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_ICESTORM_MAX)
#define MIDR_APPLE_M1_FIRESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX)
/* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */ /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
#define MIDR_FUJITSU_ERRATUM_010001 MIDR_FUJITSU_A64FX #define MIDR_FUJITSU_ERRATUM_010001 MIDR_FUJITSU_A64FX
...@@ -172,7 +180,7 @@ ...@@ -172,7 +180,7 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include "sysreg.h" #include <asm/sysreg.h>
#define read_cpuid(reg) read_sysreg_s(SYS_ ## reg) #define read_cpuid(reg) read_sysreg_s(SYS_ ## reg)
......
...@@ -433,6 +433,7 @@ struct kvm_sync_regs { ...@@ -433,6 +433,7 @@ struct kvm_sync_regs {
#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2) #define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2)
#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3) #define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3)
#define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4) #define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4)
#define KVM_X86_QUIRK_FIX_HYPERCALL_INSN (1 << 5)
#define KVM_STATE_NESTED_FORMAT_VMX 0 #define KVM_STATE_NESTED_FORMAT_VMX 0
#define KVM_STATE_NESTED_FORMAT_SVM 1 #define KVM_STATE_NESTED_FORMAT_SVM 1
......
...@@ -272,6 +272,15 @@ struct prctl_mm_map { ...@@ -272,6 +272,15 @@ struct prctl_mm_map {
# define PR_SCHED_CORE_SCOPE_THREAD_GROUP 1 # define PR_SCHED_CORE_SCOPE_THREAD_GROUP 1
# define PR_SCHED_CORE_SCOPE_PROCESS_GROUP 2 # define PR_SCHED_CORE_SCOPE_PROCESS_GROUP 2
/* arm64 Scalable Matrix Extension controls */
/* Flag values must be in sync with SVE versions */
#define PR_SME_SET_VL 63 /* set task vector length */
# define PR_SME_SET_VL_ONEXEC (1 << 18) /* defer effect until exec */
#define PR_SME_GET_VL 64 /* get task vector length */
/* Bits common to PR_SME_SET_VL and PR_SME_GET_VL */
# define PR_SME_VL_LEN_MASK 0xffff
# define PR_SME_VL_INHERIT (1 << 17) /* inherit across exec */
#define PR_SET_VMA 0x53564d41 #define PR_SET_VMA 0x53564d41
# define PR_SET_VMA_ANON_NAME 0 # define PR_SET_VMA_ANON_NAME 0
......
...@@ -149,23 +149,30 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus, ...@@ -149,23 +149,30 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
int fd, group_fd, *evsel_fd; int fd, group_fd, *evsel_fd;
evsel_fd = FD(evsel, idx, thread); evsel_fd = FD(evsel, idx, thread);
if (evsel_fd == NULL) if (evsel_fd == NULL) {
return -EINVAL; err = -EINVAL;
goto out;
}
err = get_group_fd(evsel, idx, thread, &group_fd); err = get_group_fd(evsel, idx, thread, &group_fd);
if (err < 0) if (err < 0)
return err; goto out;
fd = sys_perf_event_open(&evsel->attr, fd = sys_perf_event_open(&evsel->attr,
threads->map[thread].pid, threads->map[thread].pid,
cpu, group_fd, 0); cpu, group_fd, 0);
if (fd < 0) if (fd < 0) {
return -errno; err = -errno;
goto out;
}
*evsel_fd = fd; *evsel_fd = fd;
} }
} }
out:
if (err)
perf_evsel__close(evsel);
return err; return err;
} }
......
...@@ -151,11 +151,21 @@ static int detect_ioctl(void) ...@@ -151,11 +151,21 @@ static int detect_ioctl(void)
static int detect_share(int wp_cnt, int bp_cnt) static int detect_share(int wp_cnt, int bp_cnt)
{ {
struct perf_event_attr attr; struct perf_event_attr attr;
int i, fd[wp_cnt + bp_cnt], ret; int i, *fd = NULL, ret = -1;
if (wp_cnt + bp_cnt == 0)
return 0;
fd = malloc(sizeof(int) * (wp_cnt + bp_cnt));
if (!fd)
return -1;
for (i = 0; i < wp_cnt; i++) { for (i = 0; i < wp_cnt; i++) {
fd[i] = wp_event((void *)&the_var, &attr); fd[i] = wp_event((void *)&the_var, &attr);
TEST_ASSERT_VAL("failed to create wp\n", fd[i] != -1); if (fd[i] == -1) {
pr_err("failed to create wp\n");
goto out;
}
} }
for (; i < (bp_cnt + wp_cnt); i++) { for (; i < (bp_cnt + wp_cnt); i++) {
...@@ -166,9 +176,11 @@ static int detect_share(int wp_cnt, int bp_cnt) ...@@ -166,9 +176,11 @@ static int detect_share(int wp_cnt, int bp_cnt)
ret = i != (bp_cnt + wp_cnt); ret = i != (bp_cnt + wp_cnt);
out:
while (i--) while (i--)
close(fd[i]); close(fd[i]);
free(fd);
return ret; return ret;
} }
......
...@@ -97,6 +97,8 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u ...@@ -97,6 +97,8 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
ret |= test(ctx, "2.2 > 2.2", 0); ret |= test(ctx, "2.2 > 2.2", 0);
ret |= test(ctx, "2.2 < 1.1", 0); ret |= test(ctx, "2.2 < 1.1", 0);
ret |= test(ctx, "1.1 > 2.2", 0); ret |= test(ctx, "1.1 > 2.2", 0);
ret |= test(ctx, "1.1e10 < 1.1e100", 1);
ret |= test(ctx, "1.1e2 > 1.1e-2", 1);
if (ret) { if (ret) {
expr__ctx_free(ctx); expr__ctx_free(ctx);
......
#!/usr/bin/python
# SPDX-License-Identifier: GPL-2.0
import argparse
import sys
# Basic sanity check of perf CSV output as specified in the man page.
# Currently just checks the number of fields per line in output.
ap = argparse.ArgumentParser()
ap.add_argument('--no-args', action='store_true')
ap.add_argument('--interval', action='store_true')
ap.add_argument('--system-wide-no-aggr', action='store_true')
ap.add_argument('--system-wide', action='store_true')
ap.add_argument('--event', action='store_true')
ap.add_argument('--per-core', action='store_true')
ap.add_argument('--per-thread', action='store_true')
ap.add_argument('--per-die', action='store_true')
ap.add_argument('--per-node', action='store_true')
ap.add_argument('--per-socket', action='store_true')
ap.add_argument('--separator', default=',', nargs='?')
args = ap.parse_args()
Lines = sys.stdin.readlines()
def check_csv_output(exp):
for line in Lines:
if 'failed' not in line:
count = line.count(args.separator)
if count != exp:
sys.stdout.write(''.join(Lines))
raise RuntimeError(f'wrong number of fields. expected {exp} in {line}')
try:
if args.no_args or args.system_wide or args.event:
expected_items = 6
elif args.interval or args.per_thread or args.system_wide_no_aggr:
expected_items = 7
elif args.per_core or args.per_socket or args.per_node or args.per_die:
expected_items = 8
else:
ap.print_help()
raise RuntimeError('No checking option specified')
check_csv_output(expected_items)
except:
sys.stdout.write('Test failed for input: ' + ''.join(Lines))
raise
...@@ -6,20 +6,41 @@ ...@@ -6,20 +6,41 @@
set -e set -e
pythonchecker=$(dirname $0)/lib/perf_csv_output_lint.py function commachecker()
if [ "x$PYTHON" == "x" ] {
then local -i cnt=0 exp=0
if which python3 > /dev/null
then case "$1"
PYTHON=python3 in "--no-args") exp=6
elif which python > /dev/null ;; "--system-wide") exp=6
then ;; "--event") exp=6
PYTHON=python ;; "--interval") exp=7
else ;; "--per-thread") exp=7
echo Skipping test, python not detected please set environment variable PYTHON. ;; "--system-wide-no-aggr") exp=7
exit 2 [ $(uname -m) = "s390x" ] && exp=6
fi ;; "--per-core") exp=8
fi ;; "--per-socket") exp=8
;; "--per-node") exp=8
;; "--per-die") exp=8
esac
while read line
do
# Check for lines beginning with Failed
x=${line:0:6}
[ "$x" = "Failed" ] && continue
# Count the number of commas
x=$(echo $line | tr -d -c ',')
cnt="${#x}"
# echo $line $cnt
[ "$cnt" -ne "$exp" ] && {
echo "wrong number of fields. expected $exp in $line" 1>&2
exit 1;
}
done
return 0
}
# Return true if perf_event_paranoid is > $1 and not running as root. # Return true if perf_event_paranoid is > $1 and not running as root.
function ParanoidAndNotRoot() function ParanoidAndNotRoot()
...@@ -30,7 +51,7 @@ function ParanoidAndNotRoot() ...@@ -30,7 +51,7 @@ function ParanoidAndNotRoot()
check_no_args() check_no_args()
{ {
echo -n "Checking CSV output: no args " echo -n "Checking CSV output: no args "
perf stat -x, true 2>&1 | $PYTHON $pythonchecker --no-args perf stat -x, true 2>&1 | commachecker --no-args
echo "[Success]" echo "[Success]"
} }
...@@ -42,7 +63,7 @@ check_system_wide() ...@@ -42,7 +63,7 @@ check_system_wide()
echo "[Skip] paranoid and not root" echo "[Skip] paranoid and not root"
return return
fi fi
perf stat -x, -a true 2>&1 | $PYTHON $pythonchecker --system-wide perf stat -x, -a true 2>&1 | commachecker --system-wide
echo "[Success]" echo "[Success]"
} }
...@@ -55,14 +76,14 @@ check_system_wide_no_aggr() ...@@ -55,14 +76,14 @@ check_system_wide_no_aggr()
return return
fi fi
echo -n "Checking CSV output: system wide no aggregation " echo -n "Checking CSV output: system wide no aggregation "
perf stat -x, -A -a --no-merge true 2>&1 | $PYTHON $pythonchecker --system-wide-no-aggr perf stat -x, -A -a --no-merge true 2>&1 | commachecker --system-wide-no-aggr
echo "[Success]" echo "[Success]"
} }
check_interval() check_interval()
{ {
echo -n "Checking CSV output: interval " echo -n "Checking CSV output: interval "
perf stat -x, -I 1000 true 2>&1 | $PYTHON $pythonchecker --interval perf stat -x, -I 1000 true 2>&1 | commachecker --interval
echo "[Success]" echo "[Success]"
} }
...@@ -70,7 +91,7 @@ check_interval() ...@@ -70,7 +91,7 @@ check_interval()
check_event() check_event()
{ {
echo -n "Checking CSV output: event " echo -n "Checking CSV output: event "
perf stat -x, -e cpu-clock true 2>&1 | $PYTHON $pythonchecker --event perf stat -x, -e cpu-clock true 2>&1 | commachecker --event
echo "[Success]" echo "[Success]"
} }
...@@ -82,7 +103,7 @@ check_per_core() ...@@ -82,7 +103,7 @@ check_per_core()
echo "[Skip] paranoid and not root" echo "[Skip] paranoid and not root"
return return
fi fi
perf stat -x, --per-core -a true 2>&1 | $PYTHON $pythonchecker --per-core perf stat -x, --per-core -a true 2>&1 | commachecker --per-core
echo "[Success]" echo "[Success]"
} }
...@@ -94,7 +115,7 @@ check_per_thread() ...@@ -94,7 +115,7 @@ check_per_thread()
echo "[Skip] paranoid and not root" echo "[Skip] paranoid and not root"
return return
fi fi
perf stat -x, --per-thread -a true 2>&1 | $PYTHON $pythonchecker --per-thread perf stat -x, --per-thread -a true 2>&1 | commachecker --per-thread
echo "[Success]" echo "[Success]"
} }
...@@ -106,7 +127,7 @@ check_per_die() ...@@ -106,7 +127,7 @@ check_per_die()
echo "[Skip] paranoid and not root" echo "[Skip] paranoid and not root"
return return
fi fi
perf stat -x, --per-die -a true 2>&1 | $PYTHON $pythonchecker --per-die perf stat -x, --per-die -a true 2>&1 | commachecker --per-die
echo "[Success]" echo "[Success]"
} }
...@@ -118,7 +139,7 @@ check_per_node() ...@@ -118,7 +139,7 @@ check_per_node()
echo "[Skip] paranoid and not root" echo "[Skip] paranoid and not root"
return return
fi fi
perf stat -x, --per-node -a true 2>&1 | $PYTHON $pythonchecker --per-node perf stat -x, --per-node -a true 2>&1 | commachecker --per-node
echo "[Success]" echo "[Success]"
} }
...@@ -130,7 +151,7 @@ check_per_socket() ...@@ -130,7 +151,7 @@ check_per_socket()
echo "[Skip] paranoid and not root" echo "[Skip] paranoid and not root"
return return
fi fi
perf stat -x, --per-socket -a true 2>&1 | $PYTHON $pythonchecker --per-socket perf stat -x, --per-socket -a true 2>&1 | commachecker --per-socket
echo "[Success]" echo "[Success]"
} }
......
...@@ -43,7 +43,7 @@ CFLAGS="-g -O0 -fno-inline -fno-omit-frame-pointer" ...@@ -43,7 +43,7 @@ CFLAGS="-g -O0 -fno-inline -fno-omit-frame-pointer"
cc $CFLAGS $TEST_PROGRAM_SOURCE -o $TEST_PROGRAM || exit 1 cc $CFLAGS $TEST_PROGRAM_SOURCE -o $TEST_PROGRAM || exit 1
# Add a 1 second delay to skip samples that are not in the leaf() function # Add a 1 second delay to skip samples that are not in the leaf() function
perf record -o $PERF_DATA --call-graph fp -e cycles//u -D 1000 -- $TEST_PROGRAM 2> /dev/null & perf record -o $PERF_DATA --call-graph fp -e cycles//u -D 1000 --user-callchains -- $TEST_PROGRAM 2> /dev/null &
PID=$! PID=$!
echo " + Recording (PID=$PID)..." echo " + Recording (PID=$PID)..."
......
...@@ -115,7 +115,7 @@ static int check_cpu_topology(char *path, struct perf_cpu_map *map) ...@@ -115,7 +115,7 @@ static int check_cpu_topology(char *path, struct perf_cpu_map *map)
* physical_package_id will be set to -1. Hence skip this * physical_package_id will be set to -1. Hence skip this
* test if physical_package_id returns -1 for cpu from perf_cpu_map. * test if physical_package_id returns -1 for cpu from perf_cpu_map.
*/ */
if (strncmp(session->header.env.arch, "powerpc", 7)) { if (!strncmp(session->header.env.arch, "ppc64le", 7)) {
if (cpu__get_socket_id(perf_cpu_map__cpu(map, 0)) == -1) if (cpu__get_socket_id(perf_cpu_map__cpu(map, 0)) == -1)
return TEST_SKIP; return TEST_SKIP;
} }
......
...@@ -50,6 +50,9 @@ struct linger { ...@@ -50,6 +50,9 @@ struct linger {
struct msghdr { struct msghdr {
void *msg_name; /* ptr to socket address structure */ void *msg_name; /* ptr to socket address structure */
int msg_namelen; /* size of socket address structure */ int msg_namelen; /* size of socket address structure */
int msg_inq; /* output, data left in socket */
struct iov_iter msg_iter; /* data */ struct iov_iter msg_iter; /* data */
/* /*
...@@ -62,8 +65,9 @@ struct msghdr { ...@@ -62,8 +65,9 @@ struct msghdr {
void __user *msg_control_user; void __user *msg_control_user;
}; };
bool msg_control_is_user : 1; bool msg_control_is_user : 1;
__kernel_size_t msg_controllen; /* ancillary data buffer length */ bool msg_get_inq : 1;/* return INQ after receive */
unsigned int msg_flags; /* flags on received message */ unsigned int msg_flags; /* flags on received message */
__kernel_size_t msg_controllen; /* ancillary data buffer length */
struct kiocb *msg_iocb; /* ptr to iocb for async requests */ struct kiocb *msg_iocb; /* ptr to iocb for async requests */
}; };
...@@ -434,6 +438,7 @@ extern struct file *do_accept(struct file *file, unsigned file_flags, ...@@ -434,6 +438,7 @@ extern struct file *do_accept(struct file *file, unsigned file_flags,
extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr, extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen, int flags); int __user *upeer_addrlen, int flags);
extern int __sys_socket(int family, int type, int protocol); extern int __sys_socket(int family, int type, int protocol);
extern struct file *__sys_socket_file(int family, int type, int protocol);
extern int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen); extern int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen);
extern int __sys_connect_file(struct file *file, struct sockaddr_storage *addr, extern int __sys_connect_file(struct file *file, struct sockaddr_storage *addr,
int addrlen, int file_flags); int addrlen, int file_flags);
......
...@@ -387,26 +387,16 @@ static int arm_spe__synth_instruction_sample(struct arm_spe_queue *speq, ...@@ -387,26 +387,16 @@ static int arm_spe__synth_instruction_sample(struct arm_spe_queue *speq,
return arm_spe_deliver_synth_event(spe, speq, event, &sample); return arm_spe_deliver_synth_event(spe, speq, event, &sample);
} }
#define SPE_MEM_TYPE (ARM_SPE_L1D_ACCESS | ARM_SPE_L1D_MISS | \
ARM_SPE_LLC_ACCESS | ARM_SPE_LLC_MISS | \
ARM_SPE_REMOTE_ACCESS)
static bool arm_spe__is_memory_event(enum arm_spe_sample_type type)
{
if (type & SPE_MEM_TYPE)
return true;
return false;
}
static u64 arm_spe__synth_data_source(const struct arm_spe_record *record) static u64 arm_spe__synth_data_source(const struct arm_spe_record *record)
{ {
union perf_mem_data_src data_src = { 0 }; union perf_mem_data_src data_src = { 0 };
if (record->op == ARM_SPE_LD) if (record->op == ARM_SPE_LD)
data_src.mem_op = PERF_MEM_OP_LOAD; data_src.mem_op = PERF_MEM_OP_LOAD;
else else if (record->op == ARM_SPE_ST)
data_src.mem_op = PERF_MEM_OP_STORE; data_src.mem_op = PERF_MEM_OP_STORE;
else
return 0;
if (record->type & (ARM_SPE_LLC_ACCESS | ARM_SPE_LLC_MISS)) { if (record->type & (ARM_SPE_LLC_ACCESS | ARM_SPE_LLC_MISS)) {
data_src.mem_lvl = PERF_MEM_LVL_L3; data_src.mem_lvl = PERF_MEM_LVL_L3;
...@@ -510,7 +500,11 @@ static int arm_spe_sample(struct arm_spe_queue *speq) ...@@ -510,7 +500,11 @@ static int arm_spe_sample(struct arm_spe_queue *speq)
return err; return err;
} }
if (spe->sample_memory && arm_spe__is_memory_event(record->type)) { /*
* When data_src is zero it means the record is not a memory operation,
* skip to synthesize memory sample for this case.
*/
if (spe->sample_memory && data_src) {
err = arm_spe__synth_mem_sample(speq, spe->memory_id, data_src); err = arm_spe__synth_mem_sample(speq, spe->memory_id, data_src);
if (err) if (err)
return err; return err;
......
...@@ -91,7 +91,7 @@ static int literal(yyscan_t scanner) ...@@ -91,7 +91,7 @@ static int literal(yyscan_t scanner)
} }
%} %}
number ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+) number ([0-9]+\.?[0-9]*|[0-9]*\.?[0-9]+)(e-?[0-9]+)?
sch [-,=] sch [-,=]
spec \\{sch} spec \\{sch}
......
...@@ -1372,6 +1372,7 @@ static int parse_ids(bool metric_no_merge, struct perf_pmu *fake_pmu, ...@@ -1372,6 +1372,7 @@ static int parse_ids(bool metric_no_merge, struct perf_pmu *fake_pmu,
*out_evlist = NULL; *out_evlist = NULL;
if (!metric_no_merge || hashmap__size(ids->ids) == 0) { if (!metric_no_merge || hashmap__size(ids->ids) == 0) {
bool added_event = false;
int i; int i;
/* /*
* We may fail to share events between metrics because a tool * We may fail to share events between metrics because a tool
...@@ -1393,8 +1394,16 @@ static int parse_ids(bool metric_no_merge, struct perf_pmu *fake_pmu, ...@@ -1393,8 +1394,16 @@ static int parse_ids(bool metric_no_merge, struct perf_pmu *fake_pmu,
if (!tmp) if (!tmp)
return -ENOMEM; return -ENOMEM;
ids__insert(ids->ids, tmp); ids__insert(ids->ids, tmp);
added_event = true;
} }
} }
if (!added_event && hashmap__size(ids->ids) == 0) {
char *tmp = strdup("duration_time");
if (!tmp)
return -ENOMEM;
ids__insert(ids->ids, tmp);
}
} }
ret = metricgroup__build_event_string(&events, ids, modifier, ret = metricgroup__build_event_string(&events, ids, modifier,
has_constraint); has_constraint);
......
...@@ -174,7 +174,7 @@ static int elf_section_address_and_offset(int fd, const char *name, u64 *address ...@@ -174,7 +174,7 @@ static int elf_section_address_and_offset(int fd, const char *name, u64 *address
Elf *elf; Elf *elf;
GElf_Ehdr ehdr; GElf_Ehdr ehdr;
GElf_Shdr shdr; GElf_Shdr shdr;
int ret; int ret = -1;
elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
if (elf == NULL) if (elf == NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment