Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 17 Dec 2019 19:03:57 +0000 (11:03 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 17 Dec 2019 19:03:57 +0000 (11:03 -0800)
Pull perf tooling fixes from Ingo  Molnar:
 "These are all perf tooling changes: most of them are fixes.

  Note that the large CPU count related fixes go beyond regression
  fixes, but the IPI-flood symptoms are severe enough that I think
  justifies their inclusion"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (38 commits)
  perf vendor events s390: Remove name from L1D_RO_EXCL_WRITES description
  perf vendor events s390: Fix counter long description for DTLB1_GPAGE_WRITES
  libtraceevent: Allow custom libdir path
  perf header: Fix false warning when there are no duplicate cache entries
  perf metricgroup: Fix printing event names of metric group with multiple events
  perf/x86/pmu-events: Fix Kernel_Utilization metric
  perf top: Do not bail out when perf_env__read_cpuid() returns ENOSYS
  perf arch: Make the default get_cpuid() return compatible error
  tools headers kvm: Sync linux/kvm.h with the kernel sources
  tools headers UAPI: Update tools's copy of drm.h headers
  tools headers UAPI: Sync drm/i915_drm.h with the kernel sources
  perf inject: Fix processing of ID index for injected instruction tracing
  perf report: Bail out --mem-mode if mem info is not available
  perf report: Make -F more strict like -s
  perf report/top TUI: Replace pr_err() with ui__error()
  libtraceevent: Copy pkg-config file to output folder when using O=
  libtraceevent: Fix lib installation with O=
  perf kvm: Clarify the 'perf kvm' -i and -o command line options
  tools arch x86: Sync asm/cpufeatures.h with the kernel sources
  perf beauty: Add CLEAR_SIGHAND support for clone's flags arg
  ...

65 files changed:
tools/arch/arm/include/uapi/asm/kvm.h
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/powerpc/include/uapi/asm/kvm.h
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/msr-index.h
tools/arch/x86/lib/memcpy_64.S
tools/arch/x86/lib/memset_64.S
tools/include/uapi/drm/drm.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/fscrypt.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/sched.h
tools/include/uapi/linux/stat.h
tools/lib/traceevent/Makefile
tools/lib/traceevent/plugins/Makefile
tools/perf/Documentation/perf-kvm.txt
tools/perf/arch/arm/tests/regs_load.S
tools/perf/arch/arm64/tests/regs_load.S
tools/perf/arch/x86/tests/regs_load.S
tools/perf/builtin-inject.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-stat.c
tools/perf/builtin-top.c
tools/perf/check-headers.sh
tools/perf/lib/cpumap.c
tools/perf/lib/evlist.c
tools/perf/lib/evsel.c
tools/perf/lib/include/internal/evlist.h
tools/perf/lib/include/perf/cpumap.h
tools/perf/lib/include/perf/evsel.h
tools/perf/pmu-events/arch/s390/cf_z13/extended.json
tools/perf/pmu-events/arch/s390/cf_z14/extended.json
tools/perf/pmu-events/arch/x86/broadwell/bdw-metrics.json
tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json
tools/perf/pmu-events/arch/x86/broadwellx/bdx-metrics.json
tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json
tools/perf/pmu-events/arch/x86/haswell/hsw-metrics.json
tools/perf/pmu-events/arch/x86/haswellx/hsx-metrics.json
tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json
tools/perf/pmu-events/arch/x86/ivytown/ivt-metrics.json
tools/perf/pmu-events/arch/x86/jaketown/jkt-metrics.json
tools/perf/pmu-events/arch/x86/sandybridge/snb-metrics.json
tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json
tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
tools/perf/tests/Build
tools/perf/tests/builtin-test.c
tools/perf/tests/cpumap.c
tools/perf/tests/event-times.c
tools/perf/tests/genelf.c [new file with mode: 0644]
tools/perf/tests/tests.h
tools/perf/trace/beauty/clone.c
tools/perf/util/cpumap.h
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/genelf.c
tools/perf/util/header.c
tools/perf/util/include/linux/linkage.h
tools/perf/util/machine.c
tools/perf/util/metricgroup.c
tools/perf/util/sort.c
tools/perf/util/stat.c
tools/perf/util/stat.h

index 2769360..03cd7c1 100644 (file)
@@ -131,8 +131,9 @@ struct kvm_vcpu_events {
        struct {
                __u8 serror_pending;
                __u8 serror_has_esr;
+               __u8 ext_dabt_pending;
                /* Align it to 8 bytes */
-               __u8 pad[6];
+               __u8 pad[5];
                __u64 serror_esr;
        } exception;
        __u32 reserved[12];
index 67c21f9..820e575 100644 (file)
@@ -164,8 +164,9 @@ struct kvm_vcpu_events {
        struct {
                __u8 serror_pending;
                __u8 serror_has_esr;
+               __u8 ext_dabt_pending;
                /* Align it to 8 bytes */
-               __u8 pad[6];
+               __u8 pad[5];
                __u64 serror_esr;
        } exception;
        __u32 reserved[12];
@@ -323,6 +324,8 @@ struct kvm_vcpu_events {
 #define KVM_ARM_VCPU_TIMER_CTRL                1
 #define   KVM_ARM_VCPU_TIMER_IRQ_VTIMER                0
 #define   KVM_ARM_VCPU_TIMER_IRQ_PTIMER                1
+#define KVM_ARM_VCPU_PVTIME_CTRL       2
+#define   KVM_ARM_VCPU_PVTIME_IPA      0
 
 /* KVM_IRQ_LINE irq field index values */
 #define KVM_ARM_IRQ_VCPU2_SHIFT                28
index b0f72de..264e266 100644 (file)
@@ -667,6 +667,8 @@ struct kvm_ppc_cpu_char {
 
 /* PPC64 eXternal Interrupt Controller Specification */
 #define KVM_DEV_XICS_GRP_SOURCES       1       /* 64-bit source attributes */
+#define KVM_DEV_XICS_GRP_CTRL          2
+#define   KVM_DEV_XICS_NR_SERVERS      1
 
 /* Layout of 64-bit source attribute values */
 #define  KVM_XICS_DESTINATION_SHIFT    0
@@ -683,6 +685,7 @@ struct kvm_ppc_cpu_char {
 #define KVM_DEV_XIVE_GRP_CTRL          1
 #define   KVM_DEV_XIVE_RESET           1
 #define   KVM_DEV_XIVE_EQ_SYNC         2
+#define   KVM_DEV_XIVE_NR_SERVERS      3
 #define KVM_DEV_XIVE_GRP_SOURCE                2       /* 64-bit source identifier */
 #define KVM_DEV_XIVE_GRP_SOURCE_CONFIG 3       /* 64-bit source identifier */
 #define KVM_DEV_XIVE_GRP_EQ_CONFIG     4       /* 64-bit EQ identifier */
index 0652d3e..e9b6249 100644 (file)
 #define X86_FEATURE_CLZERO             (13*32+ 0) /* CLZERO instruction */
 #define X86_FEATURE_IRPERF             (13*32+ 1) /* Instructions Retired Count */
 #define X86_FEATURE_XSAVEERPTR         (13*32+ 2) /* Always save/restore FP error pointers */
+#define X86_FEATURE_RDPRU              (13*32+ 4) /* Read processor register at user level */
 #define X86_FEATURE_WBNOINVD           (13*32+ 9) /* WBNOINVD instruction */
 #define X86_FEATURE_AMD_IBPB           (13*32+12) /* "" Indirect Branch Prediction Barrier */
 #define X86_FEATURE_AMD_IBRS           (13*32+14) /* "" Indirect Branch Restricted Speculation */
 #define X86_BUG_MDS                    X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */
 #define X86_BUG_MSBDS_ONLY             X86_BUG(20) /* CPU is only affected by the  MSDBS variant of BUG_MDS */
 #define X86_BUG_SWAPGS                 X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
+#define X86_BUG_TAA                    X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
+#define X86_BUG_ITLB_MULTIHIT          X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index 20ce682..084e98d 100644 (file)
                                                  * Microarchitectural Data
                                                  * Sampling (MDS) vulnerabilities.
                                                  */
+#define ARCH_CAP_PSCHANGE_MC_NO                BIT(6)   /*
+                                                 * The processor is not susceptible to a
+                                                 * machine check error due to modifying the
+                                                 * code page size along with either the
+                                                 * physical address or cache type
+                                                 * without TLB invalidation.
+                                                 */
+#define ARCH_CAP_TSX_CTRL_MSR          BIT(7)  /* MSR for TSX control is available. */
+#define ARCH_CAP_TAA_NO                        BIT(8)  /*
+                                                * Not susceptible to
+                                                * TSX Async Abort (TAA) vulnerabilities.
+                                                */
 
 #define MSR_IA32_FLUSH_CMD             0x0000010b
 #define L1D_FLUSH                      BIT(0)  /*
 #define MSR_IA32_BBL_CR_CTL            0x00000119
 #define MSR_IA32_BBL_CR_CTL3           0x0000011e
 
+#define MSR_IA32_TSX_CTRL              0x00000122
+#define TSX_CTRL_RTM_DISABLE           BIT(0)  /* Disable RTM feature */
+#define TSX_CTRL_CPUID_CLEAR           BIT(1)  /* Disable TSX enumeration */
+
 #define MSR_IA32_SYSENTER_CS           0x00000174
 #define MSR_IA32_SYSENTER_ESP          0x00000175
 #define MSR_IA32_SYSENTER_EIP          0x00000176
 #define MSR_AMD_PSTATE_DEF_BASE                0xc0010064
 #define MSR_AMD64_OSVW_ID_LENGTH       0xc0010140
 #define MSR_AMD64_OSVW_STATUS          0xc0010141
+#define MSR_AMD_PPIN_CTL               0xc00102f0
+#define MSR_AMD_PPIN                   0xc00102f1
 #define MSR_AMD64_LS_CFG               0xc0011020
 #define MSR_AMD64_DC_CFG               0xc0011022
 #define MSR_AMD64_BU_CFG2              0xc001102a
index 9274866..df767af 100644 (file)
@@ -28,8 +28,8 @@
  * Output:
  * rax original destination
  */
-ENTRY(__memcpy)
-ENTRY(memcpy)
+SYM_FUNC_START_ALIAS(__memcpy)
+SYM_FUNC_START_LOCAL(memcpy)
        ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
                      "jmp memcpy_erms", X86_FEATURE_ERMS
 
@@ -41,8 +41,8 @@ ENTRY(memcpy)
        movl %edx, %ecx
        rep movsb
        ret
-ENDPROC(memcpy)
-ENDPROC(__memcpy)
+SYM_FUNC_END(memcpy)
+SYM_FUNC_END_ALIAS(__memcpy)
 EXPORT_SYMBOL(memcpy)
 EXPORT_SYMBOL(__memcpy)
 
@@ -50,14 +50,14 @@ EXPORT_SYMBOL(__memcpy)
  * memcpy_erms() - enhanced fast string memcpy. This is faster and
  * simpler than memcpy. Use memcpy_erms when possible.
  */
-ENTRY(memcpy_erms)
+SYM_FUNC_START(memcpy_erms)
        movq %rdi, %rax
        movq %rdx, %rcx
        rep movsb
        ret
-ENDPROC(memcpy_erms)
+SYM_FUNC_END(memcpy_erms)
 
-ENTRY(memcpy_orig)
+SYM_FUNC_START(memcpy_orig)
        movq %rdi, %rax
 
        cmpq $0x20, %rdx
@@ -182,7 +182,7 @@ ENTRY(memcpy_orig)
 
 .Lend:
        retq
-ENDPROC(memcpy_orig)
+SYM_FUNC_END(memcpy_orig)
 
 #ifndef CONFIG_UML
 
@@ -193,7 +193,7 @@ MCSAFE_TEST_CTL
  * Note that we only catch machine checks when reading the source addresses.
  * Writes to target are posted and don't generate machine checks.
  */
-ENTRY(__memcpy_mcsafe)
+SYM_FUNC_START(__memcpy_mcsafe)
        cmpl $8, %edx
        /* Less than 8 bytes? Go to byte copy loop */
        jb .L_no_whole_words
@@ -260,7 +260,7 @@ ENTRY(__memcpy_mcsafe)
        xorl %eax, %eax
 .L_done:
        ret
-ENDPROC(__memcpy_mcsafe)
+SYM_FUNC_END(__memcpy_mcsafe)
 EXPORT_SYMBOL_GPL(__memcpy_mcsafe)
 
        .section .fixup, "ax"
index f8f3dc0..fd5d25a 100644 (file)
@@ -18,8 +18,8 @@
  *
  * rax   original destination
  */
-ENTRY(memset)
-ENTRY(__memset)
+SYM_FUNC_START_ALIAS(memset)
+SYM_FUNC_START(__memset)
        /*
         * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
         * to use it when possible. If not available, use fast string instructions.
@@ -42,8 +42,8 @@ ENTRY(__memset)
        rep stosb
        movq %r9,%rax
        ret
-ENDPROC(memset)
-ENDPROC(__memset)
+SYM_FUNC_END(__memset)
+SYM_FUNC_END_ALIAS(memset)
 
 /*
  * ISO C memset - set a memory block to a byte value. This function uses
@@ -56,16 +56,16 @@ ENDPROC(__memset)
  *
  * rax   original destination
  */
-ENTRY(memset_erms)
+SYM_FUNC_START(memset_erms)
        movq %rdi,%r9
        movb %sil,%al
        movq %rdx,%rcx
        rep stosb
        movq %r9,%rax
        ret
-ENDPROC(memset_erms)
+SYM_FUNC_END(memset_erms)
 
-ENTRY(memset_orig)
+SYM_FUNC_START(memset_orig)
        movq %rdi,%r10
 
        /* expand byte value  */
@@ -136,4 +136,4 @@ ENTRY(memset_orig)
        subq %r8,%rdx
        jmp .Lafter_bad_alignment
 .Lfinal:
-ENDPROC(memset_orig)
+SYM_FUNC_END(memset_orig)
index 8a5b2f8..868bf79 100644 (file)
@@ -778,11 +778,12 @@ struct drm_syncobj_array {
        __u32 pad;
 };
 
+#define DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED (1 << 0) /* last available point on timeline syncobj */
 struct drm_syncobj_timeline_array {
        __u64 handles;
        __u64 points;
        __u32 count_handles;
-       __u32 pad;
+       __u32 flags;
 };
 
 
index 469dc51..5400d7e 100644 (file)
@@ -611,6 +611,13 @@ typedef struct drm_i915_irq_wait {
  * See I915_EXEC_FENCE_OUT and I915_EXEC_FENCE_SUBMIT.
  */
 #define I915_PARAM_HAS_EXEC_SUBMIT_FENCE 53
+
+/*
+ * Revision of the i915-perf uAPI. The value returned helps determine what
+ * i915-perf features are available. See drm_i915_perf_property_id.
+ */
+#define I915_PARAM_PERF_REVISION       54
+
 /* Must be kept compact -- no holes and well documented */
 
 typedef struct drm_i915_getparam {
@@ -1565,6 +1572,21 @@ struct drm_i915_gem_context_param {
  *   i915_context_engines_bond (I915_CONTEXT_ENGINES_EXT_BOND)
  */
 #define I915_CONTEXT_PARAM_ENGINES     0xa
+
+/*
+ * I915_CONTEXT_PARAM_PERSISTENCE:
+ *
+ * Allow the context and active rendering to survive the process until
+ * completion. Persistence allows fire-and-forget clients to queue up a
+ * bunch of work, hand the output over to a display server and then quit.
+ * If the context is marked as not persistent, upon closing (either via
+ * an explicit DRM_I915_GEM_CONTEXT_DESTROY or implicitly from file closure
+ * or process termination), the context and any outstanding requests will be
+ * cancelled (and exported fences for cancelled requests marked as -EIO).
+ *
+ * By default, new contexts allow persistence.
+ */
+#define I915_CONTEXT_PARAM_PERSISTENCE 0xb
 /* Must be kept compact -- no holes and well documented */
 
        __u64 value;
@@ -1844,23 +1866,31 @@ enum drm_i915_perf_property_id {
         * Open the stream for a specific context handle (as used with
         * execbuffer2). A stream opened for a specific context this way
         * won't typically require root privileges.
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_CTX_HANDLE = 1,
 
        /**
         * A value of 1 requests the inclusion of raw OA unit reports as
         * part of stream samples.
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_SAMPLE_OA,
 
        /**
         * The value specifies which set of OA unit metrics should be
         * be configured, defining the contents of any OA unit reports.
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_OA_METRICS_SET,
 
        /**
         * The value specifies the size and layout of OA unit reports.
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_OA_FORMAT,
 
@@ -1870,9 +1900,22 @@ enum drm_i915_perf_property_id {
         * from this exponent as follows:
         *
         *   80ns * 2^(period_exponent + 1)
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_OA_EXPONENT,
 
+       /**
+        * Specifying this property is only valid when specify a context to
+        * filter with DRM_I915_PERF_PROP_CTX_HANDLE. Specifying this property
+        * will hold preemption of the particular context we want to gather
+        * performance data about. The execbuf2 submissions must include a
+        * drm_i915_gem_execbuffer_ext_perf parameter for this to apply.
+        *
+        * This property is available in perf revision 3.
+        */
+       DRM_I915_PERF_PROP_HOLD_PREEMPTION,
+
        DRM_I915_PERF_PROP_MAX /* non-ABI */
 };
 
@@ -1901,6 +1944,8 @@ struct drm_i915_perf_open_param {
  * to close and re-open a stream with the same configuration.
  *
  * It's undefined whether any pending data for the stream will be lost.
+ *
+ * This ioctl is available in perf revision 1.
  */
 #define I915_PERF_IOCTL_ENABLE _IO('i', 0x0)
 
@@ -1908,10 +1953,25 @@ struct drm_i915_perf_open_param {
  * Disable data capture for a stream.
  *
  * It is an error to try and read a stream that is disabled.
+ *
+ * This ioctl is available in perf revision 1.
  */
 #define I915_PERF_IOCTL_DISABLE        _IO('i', 0x1)
 
 /**
+ * Change metrics_set captured by a stream.
+ *
+ * If the stream is bound to a specific context, the configuration change
+ * will performed inline with that context such that it takes effect before
+ * the next execbuf submission.
+ *
+ * Returns the previously bound metrics set id, or a negative error code.
+ *
+ * This ioctl is available in perf revision 2.
+ */
+#define I915_PERF_IOCTL_CONFIG _IO('i', 0x2)
+
+/**
  * Common to all i915 perf records
  */
 struct drm_i915_perf_record_header {
@@ -1984,6 +2044,7 @@ struct drm_i915_query_item {
        __u64 query_id;
 #define DRM_I915_QUERY_TOPOLOGY_INFO    1
 #define DRM_I915_QUERY_ENGINE_INFO     2
+#define DRM_I915_QUERY_PERF_CONFIG      3
 /* Must be kept compact -- no holes and well documented */
 
        /*
@@ -1995,9 +2056,18 @@ struct drm_i915_query_item {
        __s32 length;
 
        /*
-        * Unused for now. Must be cleared to zero.
+        * When query_id == DRM_I915_QUERY_TOPOLOGY_INFO, must be 0.
+        *
+        * When query_id == DRM_I915_QUERY_PERF_CONFIG, must be one of the
+        * following :
+        *         - DRM_I915_QUERY_PERF_CONFIG_LIST
+        *         - DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID
+        *         - DRM_I915_QUERY_PERF_CONFIG_FOR_UUID
         */
        __u32 flags;
+#define DRM_I915_QUERY_PERF_CONFIG_LIST          1
+#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID 2
+#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID   3
 
        /*
         * Data will be written at the location pointed by data_ptr when the
@@ -2033,8 +2103,10 @@ struct drm_i915_query {
  *           (data[X / 8] >> (X % 8)) & 1
  *
  * - the subslice mask for each slice with one bit per subslice telling
- *   whether a subslice is available. The availability of subslice Y in slice
- *   X can be queried with the following formula :
+ *   whether a subslice is available. Gen12 has dual-subslices, which are
+ *   similar to two gen11 subslices. For gen12, this array represents dual-
+ *   subslices. The availability of subslice Y in slice X can be queried
+ *   with the following formula :
  *
  *           (data[subslice_offset +
  *                 X * subslice_stride +
@@ -2123,6 +2195,56 @@ struct drm_i915_query_engine_info {
        struct drm_i915_engine_info engines[];
 };
 
+/*
+ * Data written by the kernel with query DRM_I915_QUERY_PERF_CONFIG.
+ */
+struct drm_i915_query_perf_config {
+       union {
+               /*
+                * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_LIST, i915 sets
+                * this fields to the number of configurations available.
+                */
+               __u64 n_configs;
+
+               /*
+                * When query_id == DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID,
+                * i915 will use the value in this field as configuration
+                * identifier to decide what data to write into config_ptr.
+                */
+               __u64 config;
+
+               /*
+                * When query_id == DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID,
+                * i915 will use the value in this field as configuration
+                * identifier to decide what data to write into config_ptr.
+                *
+                * String formatted like "%08x-%04x-%04x-%04x-%012x"
+                */
+               char uuid[36];
+       };
+
+       /*
+        * Unused for now. Must be cleared to zero.
+        */
+       __u32 flags;
+
+       /*
+        * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_LIST, i915 will
+        * write an array of __u64 of configuration identifiers.
+        *
+        * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_DATA, i915 will
+        * write a struct drm_i915_perf_oa_config. If the following fields of
+        * drm_i915_perf_oa_config are set not set to 0, i915 will write into
+        * the associated pointers the values of submitted when the
+        * configuration was created :
+        *
+        *         - n_mux_regs
+        *         - n_boolean_regs
+        *         - n_flex_regs
+        */
+       __u8 data[];
+};
+
 #if defined(__cplusplus)
 }
 #endif
index 39ccfe9..1beb174 100644 (file)
@@ -17,7 +17,8 @@
 #define FSCRYPT_POLICY_FLAGS_PAD_32            0x03
 #define FSCRYPT_POLICY_FLAGS_PAD_MASK          0x03
 #define FSCRYPT_POLICY_FLAG_DIRECT_KEY         0x04
-#define FSCRYPT_POLICY_FLAGS_VALID             0x07
+#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64     0x08
+#define FSCRYPT_POLICY_FLAGS_VALID             0x0F
 
 /* Encryption algorithms */
 #define FSCRYPT_MODE_AES_256_XTS               1
index 52641d8..f0a16b4 100644 (file)
@@ -235,6 +235,7 @@ struct kvm_hyperv_exit {
 #define KVM_EXIT_S390_STSI        25
 #define KVM_EXIT_IOAPIC_EOI       26
 #define KVM_EXIT_HYPERV           27
+#define KVM_EXIT_ARM_NISV         28
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -394,6 +395,11 @@ struct kvm_run {
                } eoi;
                /* KVM_EXIT_HYPERV */
                struct kvm_hyperv_exit hyperv;
+               /* KVM_EXIT_ARM_NISV */
+               struct {
+                       __u64 esr_iss;
+                       __u64 fault_ipa;
+               } arm_nisv;
                /* Fix the size of the union. */
                char padding[256];
        };
@@ -1000,6 +1006,9 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_PMU_EVENT_FILTER 173
 #define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174
 #define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175
+#define KVM_CAP_PPC_GUEST_DEBUG_SSTEP 176
+#define KVM_CAP_ARM_NISV_TO_USER 177
+#define KVM_CAP_ARM_INJECT_EXT_DABT 178
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1227,6 +1236,8 @@ enum kvm_device_type {
 #define KVM_DEV_TYPE_ARM_VGIC_ITS      KVM_DEV_TYPE_ARM_VGIC_ITS
        KVM_DEV_TYPE_XIVE,
 #define KVM_DEV_TYPE_XIVE              KVM_DEV_TYPE_XIVE
+       KVM_DEV_TYPE_ARM_PV_TIME,
+#define KVM_DEV_TYPE_ARM_PV_TIME       KVM_DEV_TYPE_ARM_PV_TIME
        KVM_DEV_TYPE_MAX,
 };
 
@@ -1337,6 +1348,7 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_GET_CPU_CHAR     _IOR(KVMIO,  0xb1, struct kvm_ppc_cpu_char)
 /* Available with KVM_CAP_PMU_EVENT_FILTER */
 #define KVM_SET_PMU_EVENT_FILTER  _IOW(KVMIO,  0xb2, struct kvm_pmu_event_filter)
+#define KVM_PPC_SVM_OFF                  _IO(KVMIO,  0xb3)
 
 /* ioctl for vm fd */
 #define KVM_CREATE_DEVICE        _IOWR(KVMIO,  0xe0, struct kvm_create_device)
index 99335e1..4a02178 100644 (file)
 #define CLONE_NEWNET           0x40000000      /* New network namespace */
 #define CLONE_IO               0x80000000      /* Clone io context */
 
+/* Flags for the clone3() syscall. */
+#define CLONE_CLEAR_SIGHAND 0x100000000ULL /* Clear any signal handler and reset to SIG_DFL. */
+
 #ifndef __ASSEMBLY__
 /**
  * struct clone_args - arguments for the clone3 syscall
- * @flags:       Flags for the new process as listed above.
- *               All flags are valid except for CSIGNAL and
- *               CLONE_DETACHED.
- * @pidfd:       If CLONE_PIDFD is set, a pidfd will be
- *               returned in this argument.
- * @child_tid:   If CLONE_CHILD_SETTID is set, the TID of the
- *               child process will be returned in the child's
- *               memory.
- * @parent_tid:  If CLONE_PARENT_SETTID is set, the TID of
- *               the child process will be returned in the
- *               parent's memory.
- * @exit_signal: The exit_signal the parent process will be
- *               sent when the child exits.
- * @stack:       Specify the location of the stack for the
- *               child process.
- * @stack_size:  The size of the stack for the child process.
- * @tls:         If CLONE_SETTLS is set, the tls descriptor
- *               is set to tls.
+ * @flags:        Flags for the new process as listed above.
+ *                All flags are valid except for CSIGNAL and
+ *                CLONE_DETACHED.
+ * @pidfd:        If CLONE_PIDFD is set, a pidfd will be
+ *                returned in this argument.
+ * @child_tid:    If CLONE_CHILD_SETTID is set, the TID of the
+ *                child process will be returned in the child's
+ *                memory.
+ * @parent_tid:   If CLONE_PARENT_SETTID is set, the TID of
+ *                the child process will be returned in the
+ *                parent's memory.
+ * @exit_signal:  The exit_signal the parent process will be
+ *                sent when the child exits.
+ * @stack:        Specify the location of the stack for the
+ *                child process.
+ *                Note, @stack is expected to point to the
+ *                lowest address. The stack direction will be
+ *                determined by the kernel and set up
+ *                appropriately based on @stack_size.
+ * @stack_size:   The size of the stack for the child process.
+ * @tls:          If CLONE_SETTLS is set, the tls descriptor
+ *                is set to tls.
+ * @set_tid:      Pointer to an array of type *pid_t. The size
+ *                of the array is defined using @set_tid_size.
+ *                This array is used to select PIDs/TIDs for
+ *                newly created processes. The first element in
+ *                this defines the PID in the most nested PID
+ *                namespace. Each additional element in the array
+ *                defines the PID in the parent PID namespace of
+ *                the original PID namespace. If the array has
+ *                less entries than the number of currently
+ *                nested PID namespaces only the PIDs in the
+ *                corresponding namespaces are set.
+ * @set_tid_size: This defines the size of the array referenced
+ *                in @set_tid. This cannot be larger than the
+ *                kernel's limit of nested PID namespaces.
  *
  * The structure is versioned by size and thus extensible.
  * New struct members must go at the end of the struct and
@@ -68,10 +89,13 @@ struct clone_args {
        __aligned_u64 stack;
        __aligned_u64 stack_size;
        __aligned_u64 tls;
+       __aligned_u64 set_tid;
+       __aligned_u64 set_tid_size;
 };
 #endif
 
 #define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */
+#define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */
 
 /*
  * Scheduling policies
index 7b35e98..ad80a5c 100644 (file)
@@ -167,8 +167,8 @@ struct statx {
 #define STATX_ATTR_APPEND              0x00000020 /* [I] File is append-only */
 #define STATX_ATTR_NODUMP              0x00000040 /* [I] File is not to be dumped */
 #define STATX_ATTR_ENCRYPTED           0x00000800 /* [I] File requires key to decrypt in fs */
-
 #define STATX_ATTR_AUTOMOUNT           0x00001000 /* Dir: Automount trigger */
+#define STATX_ATTR_VERITY              0x00100000 /* [I] Verity protected file */
 
 
 #endif /* _UAPI_LINUX_STAT_H */
index cbb429f..c874c01 100644 (file)
@@ -39,11 +39,12 @@ DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
 
 LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
 ifeq ($(LP64), 1)
-  libdir_relative = lib64
+  libdir_relative_temp = lib64
 else
-  libdir_relative = lib
+  libdir_relative_temp = lib
 endif
 
+libdir_relative ?= $(libdir_relative_temp)
 prefix ?= /usr/local
 libdir = $(prefix)/$(libdir_relative)
 man_dir = $(prefix)/share/man
@@ -97,6 +98,7 @@ EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
 
 LIB_TARGET  = libtraceevent.a libtraceevent.so.$(EVENT_PARSE_VERSION)
 LIB_INSTALL = libtraceevent.a libtraceevent.so*
+LIB_INSTALL := $(addprefix $(OUTPUT),$(LIB_INSTALL))
 
 INCLUDES = -I. -I $(srctree)/tools/include $(CONFIG_INCLUDES)
 
@@ -207,10 +209,11 @@ define do_install
        $(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR_SQ)$2'
 endef
 
-PKG_CONFIG_FILE = libtraceevent.pc
+PKG_CONFIG_SOURCE_FILE = libtraceevent.pc
+PKG_CONFIG_FILE := $(addprefix $(OUTPUT),$(PKG_CONFIG_SOURCE_FILE))
 define do_install_pkgconfig_file
        if [ -n "${pkgconfig_dir}" ]; then                                      \
-               cp -f ${PKG_CONFIG_FILE}.template ${PKG_CONFIG_FILE};           \
+               cp -f ${PKG_CONFIG_SOURCE_FILE}.template ${PKG_CONFIG_FILE};    \
                sed -i "s|INSTALL_PREFIX|${1}|g" ${PKG_CONFIG_FILE};            \
                sed -i "s|LIB_VERSION|${EVENT_PARSE_VERSION}|g" ${PKG_CONFIG_FILE}; \
                sed -i "s|LIB_DIR|${libdir}|g" ${PKG_CONFIG_FILE}; \
index f440989..349bb81 100644 (file)
@@ -32,11 +32,12 @@ DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
 
 LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
 ifeq ($(LP64), 1)
-  libdir_relative = lib64
+  libdir_relative_tmp = lib64
 else
-  libdir_relative = lib
+  libdir_relative_tmp = lib
 endif
 
+libdir_relative ?= $(libdir_relative_tmp)
 prefix ?= /usr/local
 libdir = $(prefix)/$(libdir_relative)
 
index 6a5bb2b..cf95bae 100644 (file)
@@ -68,10 +68,11 @@ OPTIONS
 -------
 -i::
 --input=<path>::
-        Input file name.
+        Input file name, for the 'report', 'diff' and 'buildid-list' subcommands.
 -o::
 --output=<path>::
-        Output file name.
+        Output file name, for the 'record' subcommand. Doesn't work with 'report',
+        just redirect the output to a file when using 'report'.
 --host::
         Collect host side performance profile.
 --guest::
index 6e2495c..4284307 100644 (file)
@@ -37,7 +37,7 @@
 
 .text
 .type perf_regs_load,%function
-ENTRY(perf_regs_load)
+SYM_FUNC_START(perf_regs_load)
        str r0, [r0, #R0]
        str r1, [r0, #R1]
        str r2, [r0, #R2]
@@ -56,4 +56,4 @@ ENTRY(perf_regs_load)
        str lr, [r0, #PC]       // store pc as lr in order to skip the call
                                //  to this function
        mov pc, lr
-ENDPROC(perf_regs_load)
+SYM_FUNC_END(perf_regs_load)
index 0704251..d49de40 100644 (file)
@@ -7,7 +7,7 @@
 #define LDR_REG(r)     ldr x##r, [x0, 8 * r]
 #define SP     (8 * 31)
 #define PC     (8 * 32)
-ENTRY(perf_regs_load)
+SYM_FUNC_START(perf_regs_load)
        STR_REG(0)
        STR_REG(1)
        STR_REG(2)
@@ -44,4 +44,4 @@ ENTRY(perf_regs_load)
        str x30, [x0, #PC]
        LDR_REG(1)
        ret
-ENDPROC(perf_regs_load)
+SYM_FUNC_END(perf_regs_load)
index bbe5a0d..80f14f5 100644 (file)
@@ -28,7 +28,7 @@
 
 .text
 #ifdef HAVE_ARCH_X86_64_SUPPORT
-ENTRY(perf_regs_load)
+SYM_FUNC_START(perf_regs_load)
        movq %rax, AX(%rdi)
        movq %rbx, BX(%rdi)
        movq %rcx, CX(%rdi)
@@ -60,9 +60,9 @@ ENTRY(perf_regs_load)
        movq %r14, R14(%rdi)
        movq %r15, R15(%rdi)
        ret
-ENDPROC(perf_regs_load)
+SYM_FUNC_END(perf_regs_load)
 #else
-ENTRY(perf_regs_load)
+SYM_FUNC_START(perf_regs_load)
        push %edi
        movl 8(%esp), %edi
        movl %eax, AX(%edi)
@@ -88,7 +88,7 @@ ENTRY(perf_regs_load)
        movl $0, FS(%edi)
        movl $0, GS(%edi)
        ret
-ENDPROC(perf_regs_load)
+SYM_FUNC_END(perf_regs_load)
 #endif
 
 /*
index 9664a72..7e124a7 100644 (file)
@@ -403,17 +403,6 @@ static int perf_event__repipe_tracing_data(struct perf_session *session,
        return err;
 }
 
-static int perf_event__repipe_id_index(struct perf_session *session,
-                                      union perf_event *event)
-{
-       int err;
-
-       perf_event__repipe_synth(session->tool, event);
-       err = perf_event__process_id_index(session, event);
-
-       return err;
-}
-
 static int dso__read_build_id(struct dso *dso)
 {
        if (dso->has_build_id)
@@ -651,7 +640,7 @@ static int __cmd_inject(struct perf_inject *inject)
                inject->tool.comm           = perf_event__repipe_comm;
                inject->tool.namespaces     = perf_event__repipe_namespaces;
                inject->tool.exit           = perf_event__repipe_exit;
-               inject->tool.id_index       = perf_event__repipe_id_index;
+               inject->tool.id_index       = perf_event__process_id_index;
                inject->tool.auxtrace_info  = perf_event__process_auxtrace_info;
                inject->tool.auxtrace       = perf_event__process_auxtrace;
                inject->tool.aux            = perf_event__drop_aux;
index b5063d3..fb19ef6 100644 (file)
@@ -832,7 +832,7 @@ try_again:
                        if ((errno == EINVAL || errno == EBADF) &&
                            pos->leader != pos &&
                            pos->weak_group) {
-                               pos = perf_evlist__reset_weak_group(evlist, pos);
+                               pos = perf_evlist__reset_weak_group(evlist, pos, true);
                                goto try_again;
                        }
                        rc = -errno;
index 830d563..387311c 100644 (file)
@@ -388,6 +388,14 @@ static int report__setup_sample_type(struct report *rep)
                }
        }
 
+       if (sort__mode == SORT_MODE__MEMORY) {
+               if (!is_pipe && !(sample_type & PERF_SAMPLE_DATA_SRC)) {
+                       ui__error("Selected --mem-mode but no mem data. "
+                                 "Did you call perf record without -d?\n");
+                       return -1;
+               }
+       }
+
        if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
                if ((sample_type & PERF_SAMPLE_REGS_USER) &&
                    (sample_type & PERF_SAMPLE_STACK_USER)) {
index 0a15253..a098c2e 100644 (file)
@@ -65,6 +65,7 @@
 #include "util/target.h"
 #include "util/time-utils.h"
 #include "util/top.h"
+#include "util/affinity.h"
 #include "asm/bug.h"
 
 #include <linux/time64.h>
@@ -265,15 +266,10 @@ static int read_single_counter(struct evsel *counter, int cpu,
  * Read out the results of a single counter:
  * do not aggregate counts across CPUs in system-wide mode
  */
-static int read_counter(struct evsel *counter, struct timespec *rs)
+static int read_counter_cpu(struct evsel *counter, struct timespec *rs, int cpu)
 {
        int nthreads = perf_thread_map__nr(evsel_list->core.threads);
-       int ncpus, cpu, thread;
-
-       if (target__has_cpu(&target) && !target__has_per_thread(&target))
-               ncpus = perf_evsel__nr_cpus(counter);
-       else
-               ncpus = 1;
+       int thread;
 
        if (!counter->supported)
                return -ENOENT;
@@ -282,40 +278,38 @@ static int read_counter(struct evsel *counter, struct timespec *rs)
                nthreads = 1;
 
        for (thread = 0; thread < nthreads; thread++) {
-               for (cpu = 0; cpu < ncpus; cpu++) {
-                       struct perf_counts_values *count;
-
-                       count = perf_counts(counter->counts, cpu, thread);
-
-                       /*
-                        * The leader's group read loads data into its group members
-                        * (via perf_evsel__read_counter) and sets threir count->loaded.
-                        */
-                       if (!perf_counts__is_loaded(counter->counts, cpu, thread) &&
-                           read_single_counter(counter, cpu, thread, rs)) {
-                               counter->counts->scaled = -1;
-                               perf_counts(counter->counts, cpu, thread)->ena = 0;
-                               perf_counts(counter->counts, cpu, thread)->run = 0;
-                               return -1;
-                       }
+               struct perf_counts_values *count;
 
-                       perf_counts__set_loaded(counter->counts, cpu, thread, false);
+               count = perf_counts(counter->counts, cpu, thread);
 
-                       if (STAT_RECORD) {
-                               if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
-                                       pr_err("failed to write stat event\n");
-                                       return -1;
-                               }
-                       }
+               /*
+                * The leader's group read loads data into its group members
+                * (via perf_evsel__read_counter()) and sets their count->loaded.
+                */
+               if (!perf_counts__is_loaded(counter->counts, cpu, thread) &&
+                   read_single_counter(counter, cpu, thread, rs)) {
+                       counter->counts->scaled = -1;
+                       perf_counts(counter->counts, cpu, thread)->ena = 0;
+                       perf_counts(counter->counts, cpu, thread)->run = 0;
+                       return -1;
+               }
+
+               perf_counts__set_loaded(counter->counts, cpu, thread, false);
 
-                       if (verbose > 1) {
-                               fprintf(stat_config.output,
-                                       "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
-                                               perf_evsel__name(counter),
-                                               cpu,
-                                               count->val, count->ena, count->run);
+               if (STAT_RECORD) {
+                       if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
+                               pr_err("failed to write stat event\n");
+                               return -1;
                        }
                }
+
+               if (verbose > 1) {
+                       fprintf(stat_config.output,
+                               "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
+                                       perf_evsel__name(counter),
+                                       cpu,
+                                       count->val, count->ena, count->run);
+               }
        }
 
        return 0;
@@ -324,15 +318,37 @@ static int read_counter(struct evsel *counter, struct timespec *rs)
 static void read_counters(struct timespec *rs)
 {
        struct evsel *counter;
-       int ret;
+       struct affinity affinity;
+       int i, ncpus, cpu;
+
+       if (affinity__setup(&affinity) < 0)
+               return;
+
+       ncpus = perf_cpu_map__nr(evsel_list->core.all_cpus);
+       if (!target__has_cpu(&target) || target__has_per_thread(&target))
+               ncpus = 1;
+       evlist__for_each_cpu(evsel_list, i, cpu) {
+               if (i >= ncpus)
+                       break;
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evsel_list, counter) {
+                       if (evsel__cpu_iter_skip(counter, cpu))
+                               continue;
+                       if (!counter->err) {
+                               counter->err = read_counter_cpu(counter, rs,
+                                                               counter->cpu_iter - 1);
+                       }
+               }
+       }
+       affinity__cleanup(&affinity);
 
        evlist__for_each_entry(evsel_list, counter) {
-               ret = read_counter(counter, rs);
-               if (ret)
+               if (counter->err)
                        pr_debug("failed to read counter %s\n", counter->name);
-
-               if (ret == 0 && perf_stat_process_counter(&stat_config, counter))
+               if (counter->err == 0 && perf_stat_process_counter(&stat_config, counter))
                        pr_warning("failed to process counter %s\n", counter->name);
+               counter->err = 0;
        }
 }
 
@@ -420,6 +436,62 @@ static bool is_target_alive(struct target *_target,
        return false;
 }
 
+enum counter_recovery {
+       COUNTER_SKIP,
+       COUNTER_RETRY,
+       COUNTER_FATAL,
+};
+
+static enum counter_recovery stat_handle_error(struct evsel *counter)
+{
+       char msg[BUFSIZ];
+       /*
+        * PPC returns ENXIO for HW counters until 2.6.37
+        * (behavior changed with commit b0a873e).
+        */
+       if (errno == EINVAL || errno == ENOSYS ||
+           errno == ENOENT || errno == EOPNOTSUPP ||
+           errno == ENXIO) {
+               if (verbose > 0)
+                       ui__warning("%s event is not supported by the kernel.\n",
+                                   perf_evsel__name(counter));
+               counter->supported = false;
+               /*
+                * errored is a sticky flag that means one of the counter's
+                * cpu event had a problem and needs to be reexamined.
+                */
+               counter->errored = true;
+
+               if ((counter->leader != counter) ||
+                   !(counter->leader->core.nr_members > 1))
+                       return COUNTER_SKIP;
+       } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
+               if (verbose > 0)
+                       ui__warning("%s\n", msg);
+               return COUNTER_RETRY;
+       } else if (target__has_per_thread(&target) &&
+                  evsel_list->core.threads &&
+                  evsel_list->core.threads->err_thread != -1) {
+               /*
+                * For global --per-thread case, skip current
+                * error thread.
+                */
+               if (!thread_map__remove(evsel_list->core.threads,
+                                       evsel_list->core.threads->err_thread)) {
+                       evsel_list->core.threads->err_thread = -1;
+                       return COUNTER_RETRY;
+               }
+       }
+
+       perf_evsel__open_strerror(counter, &target,
+                                 errno, msg, sizeof(msg));
+       ui__error("%s\n", msg);
+
+       if (child_pid != -1)
+               kill(child_pid, SIGTERM);
+       return COUNTER_FATAL;
+}
+
 static int __run_perf_stat(int argc, const char **argv, int run_idx)
 {
        int interval = stat_config.interval;
@@ -433,6 +505,9 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
        int status = 0;
        const bool forks = (argc > 0);
        bool is_pipe = STAT_RECORD ? perf_stat.data.is_pipe : false;
+       struct affinity affinity;
+       int i, cpu;
+       bool second_pass = false;
 
        if (interval) {
                ts.tv_sec  = interval / USEC_PER_MSEC;
@@ -457,61 +532,104 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
        if (group)
                perf_evlist__set_leader(evsel_list);
 
-       evlist__for_each_entry(evsel_list, counter) {
+       if (affinity__setup(&affinity) < 0)
+               return -1;
+
+       evlist__for_each_cpu (evsel_list, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evsel_list, counter) {
+                       if (evsel__cpu_iter_skip(counter, cpu))
+                               continue;
+                       if (counter->reset_group || counter->errored)
+                               continue;
 try_again:
-               if (create_perf_stat_counter(counter, &stat_config, &target) < 0) {
-
-                       /* Weak group failed. Reset the group. */
-                       if ((errno == EINVAL || errno == EBADF) &&
-                           counter->leader != counter &&
-                           counter->weak_group) {
-                               counter = perf_evlist__reset_weak_group(evsel_list, counter);
-                               goto try_again;
-                       }
+                       if (create_perf_stat_counter(counter, &stat_config, &target,
+                                                    counter->cpu_iter - 1) < 0) {
 
-                       /*
-                        * PPC returns ENXIO for HW counters until 2.6.37
-                        * (behavior changed with commit b0a873e).
-                        */
-                       if (errno == EINVAL || errno == ENOSYS ||
-                           errno == ENOENT || errno == EOPNOTSUPP ||
-                           errno == ENXIO) {
-                               if (verbose > 0)
-                                       ui__warning("%s event is not supported by the kernel.\n",
-                                                   perf_evsel__name(counter));
-                               counter->supported = false;
-
-                               if ((counter->leader != counter) ||
-                                   !(counter->leader->core.nr_members > 1))
-                                       continue;
-                       } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
-                                if (verbose > 0)
-                                        ui__warning("%s\n", msg);
-                                goto try_again;
-                       } else if (target__has_per_thread(&target) &&
-                                  evsel_list->core.threads &&
-                                  evsel_list->core.threads->err_thread != -1) {
                                /*
-                                * For global --per-thread case, skip current
-                                * error thread.
+                                * Weak group failed. We cannot just undo this here
+                                * because earlier CPUs might be in group mode, and the kernel
+                                * doesn't support mixing group and non group reads. Defer
+                                * it to later.
+                                * Don't close here because we're in the wrong affinity.
                                 */
-                               if (!thread_map__remove(evsel_list->core.threads,
-                                                       evsel_list->core.threads->err_thread)) {
-                                       evsel_list->core.threads->err_thread = -1;
+                               if ((errno == EINVAL || errno == EBADF) &&
+                                   counter->leader != counter &&
+                                   counter->weak_group) {
+                                       perf_evlist__reset_weak_group(evsel_list, counter, false);
+                                       assert(counter->reset_group);
+                                       second_pass = true;
+                                       continue;
+                               }
+
+                               switch (stat_handle_error(counter)) {
+                               case COUNTER_FATAL:
+                                       return -1;
+                               case COUNTER_RETRY:
                                        goto try_again;
+                               case COUNTER_SKIP:
+                                       continue;
+                               default:
+                                       break;
                                }
+
                        }
+                       counter->supported = true;
+               }
+       }
 
-                       perf_evsel__open_strerror(counter, &target,
-                                                 errno, msg, sizeof(msg));
-                       ui__error("%s\n", msg);
+       if (second_pass) {
+               /*
+                * Now redo all the weak group after closing them,
+                * and also close errored counters.
+                */
 
-                       if (child_pid != -1)
-                               kill(child_pid, SIGTERM);
+               evlist__for_each_cpu(evsel_list, i, cpu) {
+                       affinity__set(&affinity, cpu);
+                       /* First close errored or weak retry */
+                       evlist__for_each_entry(evsel_list, counter) {
+                               if (!counter->reset_group && !counter->errored)
+                                       continue;
+                               if (evsel__cpu_iter_skip_no_inc(counter, cpu))
+                                       continue;
+                               perf_evsel__close_cpu(&counter->core, counter->cpu_iter);
+                       }
+                       /* Now reopen weak */
+                       evlist__for_each_entry(evsel_list, counter) {
+                               if (!counter->reset_group && !counter->errored)
+                                       continue;
+                               if (evsel__cpu_iter_skip(counter, cpu))
+                                       continue;
+                               if (!counter->reset_group)
+                                       continue;
+try_again_reset:
+                               pr_debug2("reopening weak %s\n", perf_evsel__name(counter));
+                               if (create_perf_stat_counter(counter, &stat_config, &target,
+                                                            counter->cpu_iter - 1) < 0) {
+
+                                       switch (stat_handle_error(counter)) {
+                                       case COUNTER_FATAL:
+                                               return -1;
+                                       case COUNTER_RETRY:
+                                               goto try_again_reset;
+                                       case COUNTER_SKIP:
+                                               continue;
+                                       default:
+                                               break;
+                                       }
+                               }
+                               counter->supported = true;
+                       }
+               }
+       }
+       affinity__cleanup(&affinity);
 
-                       return -1;
+       evlist__for_each_entry(evsel_list, counter) {
+               if (!counter->supported) {
+                       perf_evsel__free_fd(&counter->core);
+                       continue;
                }
-               counter->supported = true;
 
                l = strlen(counter->unit);
                if (l > stat_config.unit_width)
index dc80044..795e353 100644 (file)
@@ -1568,9 +1568,13 @@ int cmd_top(int argc, const char **argv)
         */
        status = perf_env__read_cpuid(&perf_env);
        if (status) {
-               pr_err("Couldn't read the cpuid for this machine: %s\n",
-                      str_error_r(errno, errbuf, sizeof(errbuf)));
-               goto out_delete_evlist;
+               /*
+                * Some arches do not provide a get_cpuid(), so just use pr_debug, otherwise
+                * warn the user explicitely.
+                */
+               eprintf(status == ENOSYS ? 1 : 0, verbose,
+                       "Couldn't read the cpuid for this machine: %s\n",
+                       str_error_r(errno, errbuf, sizeof(errbuf)));
        }
        top.evlist->env = &perf_env;
 
index a1dc167..68039a9 100755 (executable)
@@ -110,8 +110,8 @@ for i in $FILES; do
 done
 
 # diff with extra ignore lines
-check arch/x86/lib/memcpy_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"'
-check arch/x86/lib/memset_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"'
+check arch/x86/lib/memcpy_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" -I"^SYM_FUNC_START\(_LOCAL\)*(memcpy_\(erms\|orig\))"'
+check arch/x86/lib/memset_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" -I"^SYM_FUNC_START\(_LOCAL\)*(memset_\(erms\|orig\))"'
 check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common\(-tools\)*.h>"'
 check include/uapi/linux/mman.h       '-I "^#include <\(uapi/\)*asm/mman.h>"'
 check include/linux/ctype.h          '-I "isdigit("'
index 2ca1faf..f93f4e7 100644 (file)
@@ -68,14 +68,28 @@ static struct perf_cpu_map *cpu_map__default_new(void)
        return cpus;
 }
 
+static int cmp_int(const void *a, const void *b)
+{
+       return *(const int *)a - *(const int*)b;
+}
+
 static struct perf_cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
 {
        size_t payload_size = nr_cpus * sizeof(int);
        struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
+       int i, j;
 
        if (cpus != NULL) {
-               cpus->nr = nr_cpus;
                memcpy(cpus->map, tmp_cpus, payload_size);
+               qsort(cpus->map, nr_cpus, sizeof(int), cmp_int);
+               /* Remove dups */
+               j = 0;
+               for (i = 0; i < nr_cpus; i++) {
+                       if (i == 0 || cpus->map[i] != cpus->map[i - 1])
+                               cpus->map[j++] = cpus->map[i];
+               }
+               cpus->nr = j;
+               assert(j <= nr_cpus);
                refcount_set(&cpus->refcnt, 1);
        }
 
@@ -272,3 +286,60 @@ int perf_cpu_map__max(struct perf_cpu_map *map)
 
        return max;
 }
+
+/*
+ * Merge two cpumaps
+ *
+ * orig either gets freed and replaced with a new map, or reused
+ * with no reference count change (similar to "realloc")
+ * other has its reference count increased.
+ */
+
+struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig,
+                                        struct perf_cpu_map *other)
+{
+       int *tmp_cpus;
+       int tmp_len;
+       int i, j, k;
+       struct perf_cpu_map *merged;
+
+       if (!orig && !other)
+               return NULL;
+       if (!orig) {
+               perf_cpu_map__get(other);
+               return other;
+       }
+       if (!other)
+               return orig;
+       if (orig->nr == other->nr &&
+           !memcmp(orig->map, other->map, orig->nr * sizeof(int)))
+               return orig;
+
+       tmp_len = orig->nr + other->nr;
+       tmp_cpus = malloc(tmp_len * sizeof(int));
+       if (!tmp_cpus)
+               return NULL;
+
+       /* Standard merge algorithm from wikipedia */
+       i = j = k = 0;
+       while (i < orig->nr && j < other->nr) {
+               if (orig->map[i] <= other->map[j]) {
+                       if (orig->map[i] == other->map[j])
+                               j++;
+                       tmp_cpus[k++] = orig->map[i++];
+               } else
+                       tmp_cpus[k++] = other->map[j++];
+       }
+
+       while (i < orig->nr)
+               tmp_cpus[k++] = orig->map[i++];
+
+       while (j < other->nr)
+               tmp_cpus[k++] = other->map[j++];
+       assert(k <= tmp_len);
+
+       merged = cpu_map__trim_new(k, tmp_cpus);
+       free(tmp_cpus);
+       perf_cpu_map__put(orig);
+       return merged;
+}
index 205ddbb..ae9e65a 100644 (file)
@@ -54,6 +54,7 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
 
        perf_thread_map__put(evsel->threads);
        evsel->threads = perf_thread_map__get(evlist->threads);
+       evlist->all_cpus = perf_cpu_map__merge(evlist->all_cpus, evsel->cpus);
 }
 
 static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
index 5a89857..4dc0628 100644 (file)
@@ -114,16 +114,23 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
        return err;
 }
 
+static void perf_evsel__close_fd_cpu(struct perf_evsel *evsel, int cpu)
+{
+       int thread;
+
+       for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
+               if (FD(evsel, cpu, thread) >= 0)
+                       close(FD(evsel, cpu, thread));
+               FD(evsel, cpu, thread) = -1;
+       }
+}
+
 void perf_evsel__close_fd(struct perf_evsel *evsel)
 {
-       int cpu, thread;
+       int cpu;
 
        for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++)
-               for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
-                       if (FD(evsel, cpu, thread) >= 0)
-                               close(FD(evsel, cpu, thread));
-                       FD(evsel, cpu, thread) = -1;
-               }
+               perf_evsel__close_fd_cpu(evsel, cpu);
 }
 
 void perf_evsel__free_fd(struct perf_evsel *evsel)
@@ -141,6 +148,14 @@ void perf_evsel__close(struct perf_evsel *evsel)
        perf_evsel__free_fd(evsel);
 }
 
+void perf_evsel__close_cpu(struct perf_evsel *evsel, int cpu)
+{
+       if (evsel->fd == NULL)
+               return;
+
+       perf_evsel__close_fd_cpu(evsel, cpu);
+}
+
 int perf_evsel__read_size(struct perf_evsel *evsel)
 {
        u64 read_format = evsel->attr.read_format;
@@ -183,38 +198,61 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
 }
 
 static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
-                                int ioc,  void *arg)
+                                int ioc,  void *arg,
+                                int cpu)
 {
-       int cpu, thread;
+       int thread;
 
-       for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
-               for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
-                       int fd = FD(evsel, cpu, thread),
-                           err = ioctl(fd, ioc, arg);
+       for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
+               int fd = FD(evsel, cpu, thread),
+                   err = ioctl(fd, ioc, arg);
 
-                       if (err)
-                               return err;
-               }
+               if (err)
+                       return err;
        }
 
        return 0;
 }
 
+int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu)
+{
+       return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, cpu);
+}
+
 int perf_evsel__enable(struct perf_evsel *evsel)
 {
-       return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0);
+       int i;
+       int err = 0;
+
+       for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
+               err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, i);
+       return err;
+}
+
+int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu)
+{
+       return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, cpu);
 }
 
 int perf_evsel__disable(struct perf_evsel *evsel)
 {
-       return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0);
+       int i;
+       int err = 0;
+
+       for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
+               err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, i);
+       return err;
 }
 
 int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter)
 {
-       return perf_evsel__run_ioctl(evsel,
+       int err = 0, i;
+
+       for (i = 0; i < evsel->cpus->nr && !err; i++)
+               err = perf_evsel__run_ioctl(evsel,
                                     PERF_EVENT_IOC_SET_FILTER,
-                                    (void *)filter);
+                                    (void *)filter, i);
+       return err;
 }
 
 struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
index a2fbccf..74dc8c3 100644 (file)
@@ -18,6 +18,7 @@ struct perf_evlist {
        int                      nr_entries;
        bool                     has_user_cpus;
        struct perf_cpu_map     *cpus;
+       struct perf_cpu_map     *all_cpus;
        struct perf_thread_map  *threads;
        int                      nr_mmaps;
        size_t                   mmap_len;
index ac9aa49..6a17ad7 100644 (file)
@@ -12,6 +12,8 @@ LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void);
 LIBPERF_API struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list);
 LIBPERF_API struct perf_cpu_map *perf_cpu_map__read(FILE *file);
 LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map);
+LIBPERF_API struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig,
+                                                    struct perf_cpu_map *other);
 LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map);
 LIBPERF_API int perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx);
 LIBPERF_API int perf_cpu_map__nr(const struct perf_cpu_map *cpus);
index 557f581..c82ec39 100644 (file)
@@ -26,10 +26,13 @@ LIBPERF_API void perf_evsel__delete(struct perf_evsel *evsel);
 LIBPERF_API int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
                                 struct perf_thread_map *threads);
 LIBPERF_API void perf_evsel__close(struct perf_evsel *evsel);
+LIBPERF_API void perf_evsel__close_cpu(struct perf_evsel *evsel, int cpu);
 LIBPERF_API int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
                                 struct perf_counts_values *count);
 LIBPERF_API int perf_evsel__enable(struct perf_evsel *evsel);
+LIBPERF_API int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu);
 LIBPERF_API int perf_evsel__disable(struct perf_evsel *evsel);
+LIBPERF_API int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu);
 LIBPERF_API struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel);
 LIBPERF_API struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel);
 LIBPERF_API struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel);
index 436ce33..5da8296 100644 (file)
@@ -32,7 +32,7 @@
                "EventCode": "132",
                "EventName": "DTLB1_GPAGE_WRITES",
                "BriefDescription": "DTLB1 Two-Gigabyte Page Writes",
-               "PublicDescription": "Counter:132       Name:DTLB1_GPAGE_WRITES A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a two-gigabyte page."
+               "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a two-gigabyte page."
        },
        {
                "Unit": "CPU-M-CF",
index 6861815..89e0707 100644 (file)
@@ -4,7 +4,7 @@
                "EventCode": "128",
                "EventName": "L1D_RO_EXCL_WRITES",
                "BriefDescription": "L1D Read-only Exclusive Writes",
-               "PublicDescription": "L1D_RO_EXCL_WRITES A directory write to the Level-1 Data cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
+               "PublicDescription": "A directory write to the Level-1 Data cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
        },
        {
                "Unit": "CPU-M-CF",
index bc7151d..45a34ce 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 49c5f12..961fe43 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 113d19e..746734c 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 2ba32af..f946532 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index c80f16f..5402cd3 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index e501729..832f3cb 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index e244696..d69b2a8 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 9294769..5f465fd 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 603ff9c..3e909b3 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index c6b485b..50c0532 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 0ca539b..e7feb60 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 047d7e1..21d7a0c 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index a3c595f..1692529 100644 (file)
@@ -54,6 +54,7 @@ perf-y += unit_number__scnprintf.o
 perf-y += mem2node.o
 perf-y += maps.o
 perf-y += time-utils-test.o
+perf-y += genelf.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
        $(call rule_mkdir)
index 7115aa3..5f05db7 100644 (file)
@@ -260,6 +260,11 @@ static struct test generic_tests[] = {
                .func = test__cpu_map_print,
        },
        {
+               .desc = "Merge cpu map",
+               .func = test__cpu_map_merge,
+       },
+
+       {
                .desc = "Probe SDT events",
                .func = test__sdt_event,
        },
@@ -297,6 +302,10 @@ static struct test generic_tests[] = {
                .func = test__time_utils,
        },
        {
+               .desc = "Test jit_write_elf",
+               .func = test__jit_write_elf,
+       },
+       {
                .desc = "maps__merge_in",
                .func = test__maps__merge_in,
        },
index 8a0d236..4ac5674 100644 (file)
@@ -120,3 +120,19 @@ int test__cpu_map_print(struct test *test __maybe_unused, int subtest __maybe_un
        TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1-10,12-20,22-30,32-40"));
        return 0;
 }
+
+int test__cpu_map_merge(struct test *test __maybe_unused, int subtest __maybe_unused)
+{
+       struct perf_cpu_map *a = perf_cpu_map__new("4,2,1");
+       struct perf_cpu_map *b = perf_cpu_map__new("4,5,7");
+       struct perf_cpu_map *c = perf_cpu_map__merge(a, b);
+       char buf[100];
+
+       TEST_ASSERT_VAL("failed to merge map: bad nr", c->nr == 5);
+       cpu_map__snprint(c, buf, sizeof(buf));
+       TEST_ASSERT_VAL("failed to merge map: bad result", !strcmp(buf, "1-2,4-5,7"));
+       perf_cpu_map__put(a);
+       perf_cpu_map__put(b);
+       perf_cpu_map__put(c);
+       return 0;
+}
index 1ee8704..1e8a9f5 100644 (file)
@@ -125,7 +125,7 @@ static int attach__cpu_disabled(struct evlist *evlist)
 
        evsel->core.attr.disabled = 1;
 
-       err = perf_evsel__open_per_cpu(evsel, cpus);
+       err = perf_evsel__open_per_cpu(evsel, cpus, -1);
        if (err) {
                if (err == -EACCES)
                        return TEST_SKIP;
@@ -152,7 +152,7 @@ static int attach__cpu_enabled(struct evlist *evlist)
                return -1;
        }
 
-       err = perf_evsel__open_per_cpu(evsel, cpus);
+       err = perf_evsel__open_per_cpu(evsel, cpus, -1);
        if (err == -EACCES)
                return TEST_SKIP;
 
diff --git a/tools/perf/tests/genelf.c b/tools/perf/tests/genelf.c
new file mode 100644 (file)
index 0000000..f797f98
--- /dev/null
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/compiler.h>
+
+#include "debug.h"
+#include "tests.h"
+
+#ifdef HAVE_JITDUMP
+#include <libelf.h>
+#include "../util/genelf.h"
+#endif
+
+#define TEMPL "/tmp/perf-test-XXXXXX"
+
+int test__jit_write_elf(struct test *test __maybe_unused,
+                       int subtest __maybe_unused)
+{
+#ifdef HAVE_JITDUMP
+       static unsigned char x86_code[] = {
+               0xBB, 0x2A, 0x00, 0x00, 0x00, /* movl $42, %ebx */
+               0xB8, 0x01, 0x00, 0x00, 0x00, /* movl $1, %eax */
+               0xCD, 0x80            /* int $0x80 */
+       };
+       char path[PATH_MAX];
+       int fd, ret;
+
+       strcpy(path, TEMPL);
+
+       fd = mkstemp(path);
+       if (fd < 0) {
+               perror("mkstemp failed");
+               return TEST_FAIL;
+       }
+
+       pr_info("Writing jit code to: %s\n", path);
+
+       ret = jit_write_elf(fd, 0, "main", x86_code, sizeof(x86_code),
+                       NULL, 0, NULL, 0, 0);
+       close(fd);
+
+       unlink(path);
+
+       return ret ? TEST_FAIL : 0;
+#else
+       return TEST_SKIP;
+#endif
+}
index 25aea38..9a160fe 100644 (file)
@@ -98,6 +98,7 @@ int test__event_update(struct test *test, int subtest);
 int test__event_times(struct test *test, int subtest);
 int test__backward_ring_buffer(struct test *test, int subtest);
 int test__cpu_map_print(struct test *test, int subtest);
+int test__cpu_map_merge(struct test *test, int subtest);
 int test__sdt_event(struct test *test, int subtest);
 int test__is_printable_array(struct test *test, int subtest);
 int test__bitmap_print(struct test *test, int subtest);
@@ -109,6 +110,7 @@ int test__unit_number__scnprint(struct test *test, int subtest);
 int test__mem2node(struct test *t, int subtest);
 int test__maps__merge_in(struct test *t, int subtest);
 int test__time_utils(struct test *t, int subtest);
+int test__jit_write_elf(struct test *test, int subtest);
 
 bool test__bp_signal_is_supported(void);
 bool test__bp_account_is_supported(void);
index 1a8d3be..062ca84 100644 (file)
@@ -45,6 +45,7 @@ static size_t clone__scnprintf_flags(unsigned long flags, char *bf, size_t size,
        P_FLAG(NEWPID);
        P_FLAG(NEWNET);
        P_FLAG(IO);
+       P_FLAG(CLEAR_SIGHAND);
 #undef P_FLAG
 
        if (flags)
index 57943f3..3a442f0 100644 (file)
@@ -63,4 +63,5 @@ int cpu_map__build_map(struct perf_cpu_map *cpus, struct perf_cpu_map **res,
 
 int cpu_map__cpu(struct perf_cpu_map *cpus, int idx);
 bool cpu_map__has(struct perf_cpu_map *cpus, int cpu);
+
 #endif /* __PERF_CPUMAP_H */
index fdce590..1548237 100644 (file)
@@ -18,6 +18,7 @@
 #include "debug.h"
 #include "units.h"
 #include <internal/lib.h> // page_size
+#include "affinity.h"
 #include "../perf.h"
 #include "asm/bug.h"
 #include "bpf-event.h"
@@ -342,14 +343,63 @@ static int perf_evlist__nr_threads(struct evlist *evlist,
                return perf_thread_map__nr(evlist->core.threads);
 }
 
+void evlist__cpu_iter_start(struct evlist *evlist)
+{
+       struct evsel *pos;
+
+       /*
+        * Reset the per evsel cpu_iter. This is needed because
+        * each evsel's cpumap may have a different index space,
+        * and some operations need the index to modify
+        * the FD xyarray (e.g. open, close)
+        */
+       evlist__for_each_entry(evlist, pos)
+               pos->cpu_iter = 0;
+}
+
+bool evsel__cpu_iter_skip_no_inc(struct evsel *ev, int cpu)
+{
+       if (ev->cpu_iter >= ev->core.cpus->nr)
+               return true;
+       if (cpu >= 0 && ev->core.cpus->map[ev->cpu_iter] != cpu)
+               return true;
+       return false;
+}
+
+bool evsel__cpu_iter_skip(struct evsel *ev, int cpu)
+{
+       if (!evsel__cpu_iter_skip_no_inc(ev, cpu)) {
+               ev->cpu_iter++;
+               return false;
+       }
+       return true;
+}
+
 void evlist__disable(struct evlist *evlist)
 {
        struct evsel *pos;
+       struct affinity affinity;
+       int cpu, i;
+
+       if (affinity__setup(&affinity) < 0)
+               return;
 
+       evlist__for_each_cpu(evlist, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evlist, pos) {
+                       if (evsel__cpu_iter_skip(pos, cpu))
+                               continue;
+                       if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->core.fd)
+                               continue;
+                       evsel__disable_cpu(pos, pos->cpu_iter - 1);
+               }
+       }
+       affinity__cleanup(&affinity);
        evlist__for_each_entry(evlist, pos) {
-               if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->core.fd)
+               if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
                        continue;
-               evsel__disable(pos);
+               pos->disabled = true;
        }
 
        evlist->enabled = false;
@@ -358,11 +408,28 @@ void evlist__disable(struct evlist *evlist)
 void evlist__enable(struct evlist *evlist)
 {
        struct evsel *pos;
+       struct affinity affinity;
+       int cpu, i;
+
+       if (affinity__setup(&affinity) < 0)
+               return;
 
+       evlist__for_each_cpu(evlist, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evlist, pos) {
+                       if (evsel__cpu_iter_skip(pos, cpu))
+                               continue;
+                       if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
+                               continue;
+                       evsel__enable_cpu(pos, pos->cpu_iter - 1);
+               }
+       }
+       affinity__cleanup(&affinity);
        evlist__for_each_entry(evlist, pos) {
                if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
                        continue;
-               evsel__enable(pos);
+               pos->disabled = false;
        }
 
        evlist->enabled = true;
@@ -1137,9 +1204,35 @@ void perf_evlist__set_selected(struct evlist *evlist,
 void evlist__close(struct evlist *evlist)
 {
        struct evsel *evsel;
+       struct affinity affinity;
+       int cpu, i;
 
-       evlist__for_each_entry_reverse(evlist, evsel)
-               evsel__close(evsel);
+       /*
+        * With perf record core.cpus is usually NULL.
+        * Use the old method to handle this for now.
+        */
+       if (!evlist->core.cpus) {
+               evlist__for_each_entry_reverse(evlist, evsel)
+                       evsel__close(evsel);
+               return;
+       }
+
+       if (affinity__setup(&affinity) < 0)
+               return;
+       evlist__for_each_cpu(evlist, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry_reverse(evlist, evsel) {
+                       if (evsel__cpu_iter_skip(evsel, cpu))
+                           continue;
+                       perf_evsel__close_cpu(&evsel->core, evsel->cpu_iter - 1);
+               }
+       }
+       affinity__cleanup(&affinity);
+       evlist__for_each_entry_reverse(evlist, evsel) {
+               perf_evsel__free_fd(&evsel->core);
+               perf_evsel__free_id(&evsel->core);
+       }
 }
 
 static int perf_evlist__create_syswide_maps(struct evlist *evlist)
@@ -1577,7 +1670,8 @@ void perf_evlist__force_leader(struct evlist *evlist)
 }
 
 struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
-                                                struct evsel *evsel)
+                                                struct evsel *evsel,
+                                               bool close)
 {
        struct evsel *c2, *leader;
        bool is_open = true;
@@ -1594,10 +1688,15 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
                if (c2 == evsel)
                        is_open = false;
                if (c2->leader == leader) {
-                       if (is_open)
+                       if (is_open && close)
                                perf_evsel__close(&c2->core);
                        c2->leader = c2;
                        c2->core.nr_members = 0;
+                       /*
+                        * Set this for all former members of the group
+                        * to indicate they get reopened.
+                        */
+                       c2->reset_group = true;
                }
        }
        return leader;
index 3655b9e..f5bd5c3 100644 (file)
@@ -334,9 +334,17 @@ void perf_evlist__to_front(struct evlist *evlist,
 #define evlist__for_each_entry_safe(evlist, tmp, evsel) \
        __evlist__for_each_entry_safe(&(evlist)->core.entries, tmp, evsel)
 
+#define evlist__for_each_cpu(evlist, index, cpu)       \
+       evlist__cpu_iter_start(evlist);                 \
+       perf_cpu_map__for_each_cpu (cpu, index, (evlist)->core.all_cpus)
+
 void perf_evlist__set_tracking_event(struct evlist *evlist,
                                     struct evsel *tracking_evsel);
 
+void evlist__cpu_iter_start(struct evlist *evlist);
+bool evsel__cpu_iter_skip(struct evsel *ev, int cpu);
+bool evsel__cpu_iter_skip_no_inc(struct evsel *ev, int cpu);
+
 struct evsel *
 perf_evlist__find_evsel_by_str(struct evlist *evlist, const char *str);
 
@@ -348,5 +356,6 @@ bool perf_evlist__exclude_kernel(struct evlist *evlist);
 void perf_evlist__force_leader(struct evlist *evlist);
 
 struct evsel *perf_evlist__reset_weak_group(struct evlist *evlist,
-                                                struct evsel *evsel);
+                                                struct evsel *evsel,
+                                               bool close);
 #endif /* __PERF_EVLIST_H */
index f4dea05..a69e642 100644 (file)
@@ -1223,16 +1223,27 @@ int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter)
        return perf_evsel__append_filter(evsel, "%s,%s", filter);
 }
 
+/* Caller has to clear disabled after going through all CPUs. */
+int evsel__enable_cpu(struct evsel *evsel, int cpu)
+{
+       return perf_evsel__enable_cpu(&evsel->core, cpu);
+}
+
 int evsel__enable(struct evsel *evsel)
 {
        int err = perf_evsel__enable(&evsel->core);
 
        if (!err)
                evsel->disabled = false;
-
        return err;
 }
 
+/* Caller has to set disabled after going through all CPUs. */
+int evsel__disable_cpu(struct evsel *evsel, int cpu)
+{
+       return perf_evsel__disable_cpu(&evsel->core, cpu);
+}
+
 int evsel__disable(struct evsel *evsel)
 {
        int err = perf_evsel__disable(&evsel->core);
@@ -1587,8 +1598,9 @@ static int perf_event_open(struct evsel *evsel,
        return fd;
 }
 
-int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
-               struct perf_thread_map *threads)
+static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus,
+               struct perf_thread_map *threads,
+               int start_cpu, int end_cpu)
 {
        int cpu, thread, nthreads;
        unsigned long flags = PERF_FLAG_FD_CLOEXEC;
@@ -1665,7 +1677,7 @@ retry_sample_id:
 
        display_attr(&evsel->core.attr);
 
-       for (cpu = 0; cpu < cpus->nr; cpu++) {
+       for (cpu = start_cpu; cpu < end_cpu; cpu++) {
 
                for (thread = 0; thread < nthreads; thread++) {
                        int fd, group_fd;
@@ -1843,6 +1855,12 @@ out_close:
        return err;
 }
 
+int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
+               struct perf_thread_map *threads)
+{
+       return evsel__open_cpu(evsel, cpus, threads, 0, cpus ? cpus->nr : 1);
+}
+
 void evsel__close(struct evsel *evsel)
 {
        perf_evsel__close(&evsel->core);
@@ -1850,9 +1868,14 @@ void evsel__close(struct evsel *evsel)
 }
 
 int perf_evsel__open_per_cpu(struct evsel *evsel,
-                            struct perf_cpu_map *cpus)
+                            struct perf_cpu_map *cpus,
+                            int cpu)
 {
-       return evsel__open(evsel, cpus, NULL);
+       if (cpu == -1)
+               return evsel__open_cpu(evsel, cpus, NULL, 0,
+                                       cpus ? cpus->nr : 1);
+
+       return evsel__open_cpu(evsel, cpus, NULL, cpu, cpu + 1);
 }
 
 int perf_evsel__open_per_thread(struct evsel *evsel,
index ddc5ee6..dc14f4a 100644 (file)
@@ -86,6 +86,7 @@ struct evsel {
        struct list_head        config_terms;
        struct bpf_object       *bpf_obj;
        int                     bpf_fd;
+       int                     err;
        bool                    auto_merge_stats;
        bool                    merged_stat;
        const char *            metric_expr;
@@ -94,7 +95,10 @@ struct evsel {
        struct evsel            *metric_leader;
        bool                    collect_stat;
        bool                    weak_group;
+       bool                    reset_group;
+       bool                    errored;
        bool                    percore;
+       int                     cpu_iter;
        const char              *pmu_name;
        struct {
                perf_evsel__sb_cb_t     *cb;
@@ -218,11 +222,14 @@ int perf_evsel__set_filter(struct evsel *evsel, const char *filter);
 int perf_evsel__append_tp_filter(struct evsel *evsel, const char *filter);
 int perf_evsel__append_addr_filter(struct evsel *evsel,
                                   const char *filter);
+int evsel__enable_cpu(struct evsel *evsel, int cpu);
 int evsel__enable(struct evsel *evsel);
 int evsel__disable(struct evsel *evsel);
+int evsel__disable_cpu(struct evsel *evsel, int cpu);
 
 int perf_evsel__open_per_cpu(struct evsel *evsel,
-                            struct perf_cpu_map *cpus);
+                            struct perf_cpu_map *cpus,
+                            int cpu);
 int perf_evsel__open_per_thread(struct evsel *evsel,
                                struct perf_thread_map *threads);
 int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
index f9f18b8..aed4980 100644 (file)
@@ -8,15 +8,12 @@
  */
 
 #include <sys/types.h>
-#include <stdio.h>
-#include <getopt.h>
 #include <stddef.h>
 #include <libelf.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <inttypes.h>
-#include <limits.h>
 #include <fcntl.h>
 #include <err.h>
 #ifdef HAVE_DWARF_SUPPORT
@@ -31,8 +28,6 @@
 #define NT_GNU_BUILD_ID 3
 #endif
 
-#define JVMTI
-
 #define BUILD_ID_URANDOM /* different uuid for each run */
 
 #ifdef HAVE_LIBCRYPTO
@@ -511,44 +506,3 @@ error:
 
        return retval;
 }
-
-#ifndef JVMTI
-
-static unsigned char x86_code[] = {
-    0xBB, 0x2A, 0x00, 0x00, 0x00, /* movl $42, %ebx */
-    0xB8, 0x01, 0x00, 0x00, 0x00, /* movl $1, %eax */
-    0xCD, 0x80            /* int $0x80 */
-};
-
-static struct options options;
-
-int main(int argc, char **argv)
-{
-       int c, fd, ret;
-
-       while ((c = getopt(argc, argv, "o:h")) != -1) {
-               switch (c) {
-               case 'o':
-                       options.output = optarg;
-                       break;
-               case 'h':
-                       printf("Usage: genelf -o output_file [-h]\n");
-                       return 0;
-               default:
-                       errx(1, "unknown option");
-               }
-       }
-
-       fd = open(options.output, O_CREAT|O_TRUNC|O_RDWR, 0666);
-       if (fd == -1)
-               err(1, "cannot create file %s", options.output);
-
-       ret = jit_write_elf(fd, "main", x86_code, sizeof(x86_code));
-       close(fd);
-
-       if (ret != 0)
-               unlink(options.output);
-
-       return ret;
-}
-#endif
index becc2d1..93ad278 100644 (file)
@@ -850,7 +850,7 @@ int __weak strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
  */
 int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
 {
-       return -1;
+       return ENOSYS; /* Not implemented */
 }
 
 static int write_cpuid(struct feat_fd *ff,
@@ -1089,21 +1089,18 @@ static void cpu_cache_level__fprintf(FILE *out, struct cpu_cache_level *c)
        fprintf(out, "L%d %-15s %8s [%s]\n", c->level, c->type, c->size, c->map);
 }
 
-static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
+#define MAX_CACHE_LVL 4
+
+static int build_caches(struct cpu_cache_level caches[], u32 *cntp)
 {
        u32 i, cnt = 0;
-       long ncpus;
        u32 nr, cpu;
        u16 level;
 
-       ncpus = sysconf(_SC_NPROCESSORS_CONF);
-       if (ncpus < 0)
-               return -1;
-
-       nr = (u32)(ncpus & UINT_MAX);
+       nr = cpu__max_cpu();
 
        for (cpu = 0; cpu < nr; cpu++) {
-               for (level = 0; level < 10; level++) {
+               for (level = 0; level < MAX_CACHE_LVL; level++) {
                        struct cpu_cache_level c;
                        int err;
 
@@ -1123,18 +1120,12 @@ static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
                                caches[cnt++] = c;
                        else
                                cpu_cache_level__free(&c);
-
-                       if (WARN_ONCE(cnt == size, "way too many cpu caches.."))
-                               goto out;
                }
        }
- out:
        *cntp = cnt;
        return 0;
 }
 
-#define MAX_CACHE_LVL 4
-
 static int write_cache(struct feat_fd *ff,
                       struct evlist *evlist __maybe_unused)
 {
@@ -1143,7 +1134,7 @@ static int write_cache(struct feat_fd *ff,
        u32 cnt = 0, i, version = 1;
        int ret;
 
-       ret = build_caches(caches, max_caches, &cnt);
+       ret = build_caches(caches, &cnt);
        if (ret)
                goto out;
 
index f01d48a..b8a5159 100644 (file)
@@ -5,10 +5,93 @@
 
 /* linkage.h ... for including arch/x86/lib/memcpy_64.S */
 
-#define ENTRY(name)                            \
-       .globl name;                            \
+/* Some toolchains use other characters (e.g. '`') to mark new line in macro */
+#ifndef ASM_NL
+#define ASM_NL          ;
+#endif
+
+#ifndef __ALIGN
+#define __ALIGN                .align 4,0x90
+#define __ALIGN_STR    ".align 4,0x90"
+#endif
+
+/* SYM_T_FUNC -- type used by assembler to mark functions */
+#ifndef SYM_T_FUNC
+#define SYM_T_FUNC                             STT_FUNC
+#endif
+
+/* SYM_A_* -- align the symbol? */
+#define SYM_A_ALIGN                            ALIGN
+
+/* SYM_L_* -- linkage of symbols */
+#define SYM_L_GLOBAL(name)                     .globl name
+#define SYM_L_LOCAL(name)                      /* nothing */
+
+#define ALIGN __ALIGN
+
+/* === generic annotations === */
+
+/* SYM_ENTRY -- use only if you have to for non-paired symbols */
+#ifndef SYM_ENTRY
+#define SYM_ENTRY(name, linkage, align...)             \
+       linkage(name) ASM_NL                            \
+       align ASM_NL                                    \
        name:
+#endif
+
+/* SYM_START -- use only if you have to */
+#ifndef SYM_START
+#define SYM_START(name, linkage, align...)             \
+       SYM_ENTRY(name, linkage, align)
+#endif
+
+/* SYM_END -- use only if you have to */
+#ifndef SYM_END
+#define SYM_END(name, sym_type)                                \
+       .type name sym_type ASM_NL                      \
+       .size name, .-name
+#endif
+
+/*
+ * SYM_FUNC_START_ALIAS -- use where there are two global names for one
+ * function
+ */
+#ifndef SYM_FUNC_START_ALIAS
+#define SYM_FUNC_START_ALIAS(name)                     \
+       SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
+#endif
+
+/* SYM_FUNC_START -- use for global functions */
+#ifndef SYM_FUNC_START
+/*
+ * The same as SYM_FUNC_START_ALIAS, but we will need to distinguish these two
+ * later.
+ */
+#define SYM_FUNC_START(name)                           \
+       SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
+#endif
+
+/* SYM_FUNC_START_LOCAL -- use for local functions */
+#ifndef SYM_FUNC_START_LOCAL
+/* the same as SYM_FUNC_START_LOCAL_ALIAS, see comment near SYM_FUNC_START */
+#define SYM_FUNC_START_LOCAL(name)                     \
+       SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN)
+#endif
+
+/* SYM_FUNC_END_ALIAS -- the end of LOCAL_ALIASed or ALIASed function */
+#ifndef SYM_FUNC_END_ALIAS
+#define SYM_FUNC_END_ALIAS(name)                       \
+       SYM_END(name, SYM_T_FUNC)
+#endif
 
-#define ENDPROC(name)
+/*
+ * SYM_FUNC_END -- the end of SYM_FUNC_START_LOCAL, SYM_FUNC_START,
+ * SYM_FUNC_START_WEAK, ...
+ */
+#ifndef SYM_FUNC_END
+/* the same as SYM_FUNC_END_ALIAS, see comment near SYM_FUNC_START */
+#define SYM_FUNC_END(name)                             \
+       SYM_END(name, SYM_T_FUNC)
+#endif
 
 #endif /* PERF_LINUX_LINKAGE_H_ */
index 416d174..c8c5410 100644 (file)
@@ -2446,6 +2446,7 @@ static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms
 
        list_for_each_entry(ilist, &inline_node->val, list) {
                struct map_symbol ilist_ms = {
+                       .maps = ms->maps,
                        .map = map,
                        .sym = ilist->symbol,
                };
index 6a4d350..02aee94 100644 (file)
@@ -103,8 +103,11 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist,
                if (!strcmp(ev->name, ids[i])) {
                        if (!metric_events[i])
                                metric_events[i] = ev;
+                       i++;
+                       if (i == idnum)
+                               break;
                } else {
-                       if (++i == idnum) {
+                       if (i + 1 == idnum) {
                                /* Discard the whole match and start again */
                                i = 0;
                                memset(metric_events, 0,
@@ -124,7 +127,7 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist,
                }
        }
 
-       if (i != idnum - 1) {
+       if (i != idnum) {
                /* Not whole match */
                return NULL;
        }
index 345b5cc..9fcba28 100644 (file)
@@ -2681,12 +2681,12 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str,
                        ret = sort_dimension__add(list, tok, evlist, level);
                        if (ret == -EINVAL) {
                                if (!cacheline_size() && !strncasecmp(tok, "dcacheline", strlen(tok)))
-                                       pr_err("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system");
+                                       ui__error("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system");
                                else
-                                       pr_err("Invalid --sort key: `%s'", tok);
+                                       ui__error("Invalid --sort key: `%s'", tok);
                                break;
                        } else if (ret == -ESRCH) {
-                               pr_err("Unknown --sort key: `%s'", tok);
+                               ui__error("Unknown --sort key: `%s'", tok);
                                break;
                        }
                }
@@ -2743,7 +2743,7 @@ static int setup_sort_order(struct evlist *evlist)
                return 0;
 
        if (sort_order[1] == '\0') {
-               pr_err("Invalid --sort key: `+'");
+               ui__error("Invalid --sort key: `+'");
                return -EINVAL;
        }
 
@@ -2959,6 +2959,9 @@ int output_field_add(struct perf_hpp_list *list, char *tok)
                if (strncasecmp(tok, sd->name, strlen(tok)))
                        continue;
 
+               if (sort__mode != SORT_MODE__MEMORY)
+                       return -EINVAL;
+
                return __sort_dimension__add_output(list, sd);
        }
 
@@ -2968,6 +2971,9 @@ int output_field_add(struct perf_hpp_list *list, char *tok)
                if (strncasecmp(tok, sd->name, strlen(tok)))
                        continue;
 
+               if (sort__mode != SORT_MODE__BRANCH)
+                       return -EINVAL;
+
                return __sort_dimension__add_output(list, sd);
        }
 
@@ -3034,7 +3040,7 @@ static int __setup_output_field(void)
                strp++;
 
        if (!strlen(strp)) {
-               pr_err("Invalid --fields key: `+'");
+               ui__error("Invalid --fields key: `+'");
                goto out;
        }
 
index 332cb73..5f26137 100644 (file)
@@ -464,7 +464,8 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
 
 int create_perf_stat_counter(struct evsel *evsel,
                             struct perf_stat_config *config,
-                            struct target *target)
+                            struct target *target,
+                            int cpu)
 {
        struct perf_event_attr *attr = &evsel->core.attr;
        struct evsel *leader = evsel->leader;
@@ -518,7 +519,7 @@ int create_perf_stat_counter(struct evsel *evsel,
        }
 
        if (target__has_cpu(target) && !target__has_per_thread(target))
-               return perf_evsel__open_per_cpu(evsel, evsel__cpus(evsel));
+               return perf_evsel__open_per_cpu(evsel, evsel__cpus(evsel), cpu);
 
        return perf_evsel__open_per_thread(evsel, evsel->core.threads);
 }
index bfa9aaf..fb990ef 100644 (file)
@@ -214,7 +214,8 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
 
 int create_perf_stat_counter(struct evsel *evsel,
                             struct perf_stat_config *config,
-                            struct target *target);
+                            struct target *target,
+                            int cpu);
 void
 perf_evlist__print_counters(struct evlist *evlist,
                            struct perf_stat_config *config,