Merge f7018be292 ("Merge tag 'perf_urgent_for_v5.16_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip") into android-mainline

Steps on the way to 5.16-rc1

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Ib09a014ec17915bf0b5559198639bdfbc321f696
This commit is contained in:
Greg Kroah-Hartman
2021-11-16 19:18:32 +01:00
142 changed files with 2735 additions and 1173 deletions

View File

@@ -63,3 +63,12 @@ kernel sends SIGILL to the application. If the process has permission then
the handler allocates a larger xstate buffer for the task so the large
state can be context switched. In the unlikely cases that the allocation
fails, the kernel sends SIGSEGV.
Dynamic features in signal frames
---------------------------------
Dynamcally enabled features are not written to the signal frame upon signal
entry if the feature is in its initial configuration. This differs from
non-dynamic features which are always written regardless of their
configuration. Signal handlers can examine the XSAVE buffer's XSTATE_BV
field to determine if a features was written.

View File

@@ -14419,7 +14419,9 @@ M: Juergen Gross <jgross@suse.com>
M: Deep Shah <sdeep@vmware.com>
M: "VMware, Inc." <pv-drivers@vmware.com>
L: virtualization@lists.linux-foundation.org
L: x86@kernel.org
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
F: Documentation/virt/paravirt_ops.rst
F: arch/*/include/asm/paravirt*.h
F: arch/*/kernel/paravirt*

View File

@@ -3048,8 +3048,10 @@ intel_vlbr_constraints(struct perf_event *event)
{
struct event_constraint *c = &vlbr_constraint;
if (unlikely(constraint_match(c, event->hw.config)))
if (unlikely(constraint_match(c, event->hw.config))) {
event->hw.flags |= c->flags;
return c;
}
return NULL;
}

View File

@@ -265,6 +265,8 @@ void intel_pmu_lbr_reset(void)
cpuc->last_task_ctx = NULL;
cpuc->last_log_id = 0;
if (!static_cpu_has(X86_FEATURE_ARCH_LBR) && cpuc->lbr_select)
wrmsrl(MSR_LBR_SELECT, 0);
}
/*

View File

@@ -3,6 +3,7 @@
#define _ASM_X86_FPU_XCR_H
#define XCR_XFEATURE_ENABLED_MASK 0x00000000
#define XCR_XFEATURE_IN_USE_MASK 0x00000001
static inline u64 xgetbv(u32 index)
{
@@ -20,4 +21,15 @@ static inline void xsetbv(u32 index, u64 value)
asm volatile("xsetbv" :: "a" (eax), "d" (edx), "c" (index));
}
/*
* Return a mask of xfeatures which are currently being tracked
* by the processor as being in the initial configuration.
*
* Callers should check X86_FEATURE_XGETBV1.
*/
static inline u64 xfeatures_in_use(void)
{
return xgetbv(XCR_XFEATURE_IN_USE_MASK);
}
#endif /* _ASM_X86_FPU_XCR_H */

View File

@@ -92,6 +92,13 @@
#define XFEATURE_MASK_FPSTATE (XFEATURE_MASK_USER_RESTORE | \
XFEATURE_MASK_SUPERVISOR_SUPPORTED)
/*
* Features in this mask have space allocated in the signal frame, but may not
* have that space initialized when the feature is in its init state.
*/
#define XFEATURE_MASK_SIGFRAME_INITOPT (XFEATURE_MASK_XTILE | \
XFEATURE_MASK_USER_DYNAMIC)
extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS];
extern void __init update_regset_xstate_info(unsigned int size,

View File

@@ -108,6 +108,8 @@
#define INTEL_FAM6_ALDERLAKE 0x97 /* Golden Cove / Gracemont */
#define INTEL_FAM6_ALDERLAKE_L 0x9A /* Golden Cove / Gracemont */
#define INTEL_FAM6_RAPTOR_LAKE 0xB7
/* "Small Core" Processors (Atom) */
#define INTEL_FAM6_ATOM_BONNELL 0x1C /* Diamondville, Pineview */

View File

@@ -76,6 +76,7 @@ static const struct cpuid_dep cpuid_deps[] = {
{ X86_FEATURE_SGX1, X86_FEATURE_SGX },
{ X86_FEATURE_SGX2, X86_FEATURE_SGX1 },
{ X86_FEATURE_XFD, X86_FEATURE_XSAVES },
{ X86_FEATURE_XFD, X86_FEATURE_XGETBV1 },
{ X86_FEATURE_AMX_TILE, X86_FEATURE_XFD },
{}
};

View File

@@ -547,12 +547,13 @@ bool intel_filter_mce(struct mce *m)
{
struct cpuinfo_x86 *c = &boot_cpu_data;
/* MCE errata HSD131, HSM142, HSW131, BDM48, and HSM142 */
/* MCE errata HSD131, HSM142, HSW131, BDM48, HSM142 and SKX37 */
if ((c->x86 == 6) &&
((c->x86_model == INTEL_FAM6_HASWELL) ||
(c->x86_model == INTEL_FAM6_HASWELL_L) ||
(c->x86_model == INTEL_FAM6_BROADWELL) ||
(c->x86_model == INTEL_FAM6_HASWELL_G)) &&
(c->x86_model == INTEL_FAM6_HASWELL_G) ||
(c->x86_model == INTEL_FAM6_SKYLAKE_X)) &&
(m->bank == 0) &&
((m->status & 0xa0000000ffffffff) == 0x80000000000f0005))
return true;

View File

@@ -4,6 +4,7 @@
#include <asm/cpufeature.h>
#include <asm/fpu/xstate.h>
#include <asm/fpu/xcr.h>
#ifdef CONFIG_X86_64
DECLARE_PER_CPU(u64, xfd_state);
@@ -198,6 +199,32 @@ static inline void os_xrstor_supervisor(struct fpstate *fpstate)
XSTATE_XRESTORE(&fpstate->regs.xsave, lmask, hmask);
}
/*
* XSAVE itself always writes all requested xfeatures. Removing features
* from the request bitmap reduces the features which are written.
* Generate a mask of features which must be written to a sigframe. The
* unset features can be optimized away and not written.
*
* This optimization is user-visible. Only use for states where
* uninitialized sigframe contents are tolerable, like dynamic features.
*
* Users of buffers produced with this optimization must check XSTATE_BV
* to determine which features have been optimized out.
*/
static inline u64 xfeatures_need_sigframe_write(void)
{
u64 xfeaures_to_write;
/* In-use features must be written: */
xfeaures_to_write = xfeatures_in_use();
/* Also write all non-optimizable sigframe features: */
xfeaures_to_write |= XFEATURE_MASK_USER_SUPPORTED &
~XFEATURE_MASK_SIGFRAME_INITOPT;
return xfeaures_to_write;
}
/*
* Save xstate to user space xsave area.
*
@@ -220,10 +247,16 @@ static inline int xsave_to_user_sigframe(struct xregs_state __user *buf)
*/
struct fpstate *fpstate = current->thread.fpu.fpstate;
u64 mask = fpstate->user_xfeatures;
u32 lmask = mask;
u32 hmask = mask >> 32;
u32 lmask;
u32 hmask;
int err;
/* Optimize away writing unnecessary xfeatures: */
if (fpu_state_size_dynamic())
mask &= xfeatures_need_sigframe_write();
lmask = mask;
hmask = mask >> 32;
xfd_validate_state(fpstate, mask, false);
stac();

View File

@@ -7155,7 +7155,6 @@ void perf_output_sample(struct perf_output_handle *handle,
static u64 perf_virt_to_phys(u64 virt)
{
u64 phys_addr = 0;
struct page *p = NULL;
if (!virt)
return 0;
@@ -7174,14 +7173,15 @@ static u64 perf_virt_to_phys(u64 virt)
* If failed, leave phys_addr as 0.
*/
if (current->mm != NULL) {
struct page *p;
pagefault_disable();
if (get_user_page_fast_only(virt, 0, &p))
if (get_user_page_fast_only(virt, 0, &p)) {
phys_addr = page_to_phys(p) + virt % PAGE_SIZE;
put_page(p);
}
pagefault_enable();
}
if (p)
put_page(p);
}
return phys_addr;

View File

@@ -625,6 +625,8 @@
#define MSR_IA32_BNDCFGS_RSVD 0x00000ffc
#define MSR_IA32_XFD 0x000001c4
#define MSR_IA32_XFD_ERR 0x000001c5
#define MSR_IA32_XSS 0x00000da0
#define MSR_IA32_APICBASE 0x0000001b

View File

@@ -10,6 +10,10 @@
#define ARCH_GET_CPUID 0x1011
#define ARCH_SET_CPUID 0x1012
#define ARCH_GET_XCOMP_SUPP 0x1021
#define ARCH_GET_XCOMP_PERM 0x1022
#define ARCH_REQ_XCOMP_PERM 0x1023
#define ARCH_MAP_VDSO_X32 0x2001
#define ARCH_MAP_VDSO_32 0x2002
#define ARCH_MAP_VDSO_64 0x2003

View File

@@ -880,8 +880,11 @@ __SYSCALL(__NR_memfd_secret, sys_memfd_secret)
#define __NR_process_mrelease 448
__SYSCALL(__NR_process_mrelease, sys_process_mrelease)
#define __NR_futex_waitv 449
__SYSCALL(__NR_futex_waitv, sys_futex_waitv)
#undef __NR_syscalls
#define __NR_syscalls 449
#define __NR_syscalls 450
/*
* 32 bit systems traditionally used different

View File

@@ -1522,6 +1522,12 @@ struct drm_i915_gem_caching {
#define I915_TILING_NONE 0
#define I915_TILING_X 1
#define I915_TILING_Y 2
/*
* Do not add new tiling types here. The I915_TILING_* values are for
* de-tiling fence registers that no longer exist on modern platforms. Although
* the hardware may support new types of tiling in general (e.g., Tile4), we
* do not need to add them to the uapi that is specific to now-defunct ioctls.
*/
#define I915_TILING_LAST I915_TILING_Y
#define I915_BIT_6_SWIZZLE_NONE 0
@@ -1824,6 +1830,7 @@ struct drm_i915_gem_context_param {
* Extensions:
* i915_context_engines_load_balance (I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE)
* i915_context_engines_bond (I915_CONTEXT_ENGINES_EXT_BOND)
* i915_context_engines_parallel_submit (I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT)
*/
#define I915_CONTEXT_PARAM_ENGINES 0xa
@@ -1846,6 +1853,55 @@ struct drm_i915_gem_context_param {
* attempted to use it, never re-use this context param number.
*/
#define I915_CONTEXT_PARAM_RINGSIZE 0xc
/*
* I915_CONTEXT_PARAM_PROTECTED_CONTENT:
*
* Mark that the context makes use of protected content, which will result
* in the context being invalidated when the protected content session is.
* Given that the protected content session is killed on suspend, the device
* is kept awake for the lifetime of a protected context, so the user should
* make sure to dispose of them once done.
* This flag can only be set at context creation time and, when set to true,
* must be preceded by an explicit setting of I915_CONTEXT_PARAM_RECOVERABLE
* to false. This flag can't be set to true in conjunction with setting the
* I915_CONTEXT_PARAM_BANNABLE flag to false. Creation example:
*
* .. code-block:: C
*
* struct drm_i915_gem_context_create_ext_setparam p_protected = {
* .base = {
* .name = I915_CONTEXT_CREATE_EXT_SETPARAM,
* },
* .param = {
* .param = I915_CONTEXT_PARAM_PROTECTED_CONTENT,
* .value = 1,
* }
* };
* struct drm_i915_gem_context_create_ext_setparam p_norecover = {
* .base = {
* .name = I915_CONTEXT_CREATE_EXT_SETPARAM,
* .next_extension = to_user_pointer(&p_protected),
* },
* .param = {
* .param = I915_CONTEXT_PARAM_RECOVERABLE,
* .value = 0,
* }
* };
* struct drm_i915_gem_context_create_ext create = {
* .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
* .extensions = to_user_pointer(&p_norecover);
* };
*
* ctx_id = gem_context_create_ext(drm_fd, &create);
*
* In addition to the normal failure cases, setting this flag during context
* creation can result in the following errors:
*
* -ENODEV: feature not available
* -EPERM: trying to mark a recoverable or not bannable context as protected
*/
#define I915_CONTEXT_PARAM_PROTECTED_CONTENT 0xd
/* Must be kept compact -- no holes and well documented */
__u64 value;
@@ -2049,6 +2105,135 @@ struct i915_context_engines_bond {
struct i915_engine_class_instance engines[N__]; \
} __attribute__((packed)) name__
/**
* struct i915_context_engines_parallel_submit - Configure engine for
* parallel submission.
*
* Setup a slot in the context engine map to allow multiple BBs to be submitted
* in a single execbuf IOCTL. Those BBs will then be scheduled to run on the GPU
* in parallel. Multiple hardware contexts are created internally in the i915 to
* run these BBs. Once a slot is configured for N BBs only N BBs can be
* submitted in each execbuf IOCTL and this is implicit behavior e.g. The user
* doesn't tell the execbuf IOCTL there are N BBs, the execbuf IOCTL knows how
* many BBs there are based on the slot's configuration. The N BBs are the last
* N buffer objects or first N if I915_EXEC_BATCH_FIRST is set.
*
* The default placement behavior is to create implicit bonds between each
* context if each context maps to more than 1 physical engine (e.g. context is
* a virtual engine). Also we only allow contexts of same engine class and these
* contexts must be in logically contiguous order. Examples of the placement
* behavior are described below. Lastly, the default is to not allow BBs to be
* preempted mid-batch. Rather insert coordinated preemption points on all
* hardware contexts between each set of BBs. Flags could be added in the future
* to change both of these default behaviors.
*
* Returns -EINVAL if hardware context placement configuration is invalid or if
* the placement configuration isn't supported on the platform / submission
* interface.
* Returns -ENODEV if extension isn't supported on the platform / submission
* interface.
*
* .. code-block:: none
*
* Examples syntax:
* CS[X] = generic engine of same class, logical instance X
* INVALID = I915_ENGINE_CLASS_INVALID, I915_ENGINE_CLASS_INVALID_NONE
*
* Example 1 pseudo code:
* set_engines(INVALID)
* set_parallel(engine_index=0, width=2, num_siblings=1,
* engines=CS[0],CS[1])
*
* Results in the following valid placement:
* CS[0], CS[1]
*
* Example 2 pseudo code:
* set_engines(INVALID)
* set_parallel(engine_index=0, width=2, num_siblings=2,
* engines=CS[0],CS[2],CS[1],CS[3])
*
* Results in the following valid placements:
* CS[0], CS[1]
* CS[2], CS[3]
*
* This can be thought of as two virtual engines, each containing two
* engines thereby making a 2D array. However, there are bonds tying the
* entries together and placing restrictions on how they can be scheduled.
* Specifically, the scheduler can choose only vertical columns from the 2D
* array. That is, CS[0] is bonded to CS[1] and CS[2] to CS[3]. So if the
* scheduler wants to submit to CS[0], it must also choose CS[1] and vice
* versa. Same for CS[2] requires also using CS[3].
* VE[0] = CS[0], CS[2]
* VE[1] = CS[1], CS[3]
*
* Example 3 pseudo code:
* set_engines(INVALID)
* set_parallel(engine_index=0, width=2, num_siblings=2,
* engines=CS[0],CS[1],CS[1],CS[3])
*
* Results in the following valid and invalid placements:
* CS[0], CS[1]
* CS[1], CS[3] - Not logically contiguous, return -EINVAL
*/
struct i915_context_engines_parallel_submit {
/**
* @base: base user extension.
*/
struct i915_user_extension base;
/**
* @engine_index: slot for parallel engine
*/
__u16 engine_index;
/**
* @width: number of contexts per parallel engine or in other words the
* number of batches in each submission
*/
__u16 width;
/**
* @num_siblings: number of siblings per context or in other words the
* number of possible placements for each submission
*/
__u16 num_siblings;
/**
* @mbz16: reserved for future use; must be zero
*/
__u16 mbz16;
/**
* @flags: all undefined flags must be zero, currently not defined flags
*/
__u64 flags;
/**
* @mbz64: reserved for future use; must be zero
*/
__u64 mbz64[3];
/**
* @engines: 2-d array of engine instances to configure parallel engine
*
* length = width (i) * num_siblings (j)
* index = j + i * num_siblings
*/
struct i915_engine_class_instance engines[0];
} __packed;
#define I915_DEFINE_CONTEXT_ENGINES_PARALLEL_SUBMIT(name__, N__) struct { \
struct i915_user_extension base; \
__u16 engine_index; \
__u16 width; \
__u16 num_siblings; \
__u16 mbz16; \
__u64 flags; \
__u64 mbz64[3]; \
struct i915_engine_class_instance engines[N__]; \
} __attribute__((packed)) name__
/**
* DOC: Context Engine Map uAPI
*
@@ -2108,6 +2293,7 @@ struct i915_context_param_engines {
__u64 extensions; /* linked chain of extension blocks, 0 terminates */
#define I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE 0 /* see i915_context_engines_load_balance */
#define I915_CONTEXT_ENGINES_EXT_BOND 1 /* see i915_context_engines_bond */
#define I915_CONTEXT_ENGINES_EXT_PARALLEL_SUBMIT 2 /* see i915_context_engines_parallel_submit */
struct i915_engine_class_instance engines[0];
} __attribute__((packed));
@@ -2726,14 +2912,20 @@ struct drm_i915_engine_info {
/** @flags: Engine flags. */
__u64 flags;
#define I915_ENGINE_INFO_HAS_LOGICAL_INSTANCE (1 << 0)
/** @capabilities: Capabilities of this engine. */
__u64 capabilities;
#define I915_VIDEO_CLASS_CAPABILITY_HEVC (1 << 0)
#define I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC (1 << 1)
/** @logical_instance: Logical instance of engine */
__u16 logical_instance;
/** @rsvd1: Reserved fields. */
__u64 rsvd1[4];
__u16 rsvd1[3];
/** @rsvd2: Reserved fields. */
__u64 rsvd2[3];
};
/**
@@ -2979,8 +3171,12 @@ struct drm_i915_gem_create_ext {
*
* For I915_GEM_CREATE_EXT_MEMORY_REGIONS usage see
* struct drm_i915_gem_create_ext_memory_regions.
*
* For I915_GEM_CREATE_EXT_PROTECTED_CONTENT usage see
* struct drm_i915_gem_create_ext_protected_content.
*/
#define I915_GEM_CREATE_EXT_MEMORY_REGIONS 0
#define I915_GEM_CREATE_EXT_PROTECTED_CONTENT 1
__u64 extensions;
};
@@ -3038,6 +3234,50 @@ struct drm_i915_gem_create_ext_memory_regions {
__u64 regions;
};
/**
* struct drm_i915_gem_create_ext_protected_content - The
* I915_OBJECT_PARAM_PROTECTED_CONTENT extension.
*
* If this extension is provided, buffer contents are expected to be protected
* by PXP encryption and require decryption for scan out and processing. This
* is only possible on platforms that have PXP enabled, on all other scenarios
* using this extension will cause the ioctl to fail and return -ENODEV. The
* flags parameter is reserved for future expansion and must currently be set
* to zero.
*
* The buffer contents are considered invalid after a PXP session teardown.
*
* The encryption is guaranteed to be processed correctly only if the object
* is submitted with a context created using the
* I915_CONTEXT_PARAM_PROTECTED_CONTENT flag. This will also enable extra checks
* at submission time on the validity of the objects involved.
*
* Below is an example on how to create a protected object:
*
* .. code-block:: C
*
* struct drm_i915_gem_create_ext_protected_content protected_ext = {
* .base = { .name = I915_GEM_CREATE_EXT_PROTECTED_CONTENT },
* .flags = 0,
* };
* struct drm_i915_gem_create_ext create_ext = {
* .size = PAGE_SIZE,
* .extensions = (uintptr_t)&protected_ext,
* };
*
* int err = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext);
* if (err) ...
*/
struct drm_i915_gem_create_ext_protected_content {
/** @base: Extension link. See struct i915_user_extension. */
struct i915_user_extension base;
/** @flags: reserved for future usage, currently MBZ */
__u32 flags;
};
/* ID of the protected content session managed by i915 when PXP is active */
#define I915_PROTECTED_CONTENT_DEFAULT_SESSION 0xf
#if defined(__cplusplus)
}
#endif

View File

@@ -268,5 +268,8 @@ struct prctl_mm_map {
# define PR_SCHED_CORE_SHARE_TO 2 /* push core_sched cookie to pid */
# define PR_SCHED_CORE_SHARE_FROM 3 /* pull core_sched cookie to pid */
# define PR_SCHED_CORE_MAX 4
# define PR_SCHED_CORE_SCOPE_THREAD 0
# define PR_SCHED_CORE_SCOPE_THREAD_GROUP 1
# define PR_SCHED_CORE_SCOPE_PROCESS_GROUP 2
#endif /* _LINUX_PRCTL_H */

View File

@@ -1002,7 +1002,7 @@ typedef int __bitwise snd_ctl_elem_iface_t;
#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */
// (1 << 3) is unused.
/* (1 << 3) is unused. */
#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */
#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */
#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)

View File

@@ -469,7 +469,7 @@ This option sets the time out limit. The default value is 500 ms.
--switch-events::
Record context switch events i.e. events of type PERF_RECORD_SWITCH or
PERF_RECORD_SWITCH_CPU_WIDE. In some cases (e.g. Intel PT or CoreSight)
PERF_RECORD_SWITCH_CPU_WIDE. In some cases (e.g. Intel PT, CoreSight or Arm SPE)
switch events will be enabled automatically, which can be suppressed by
by the option --no-switch-events.

View File

@@ -516,17 +516,17 @@ kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh
$(kvm_ioctl_array): $(kvm_hdr_dir)/kvm.h $(kvm_ioctl_tbl)
$(Q)$(SHELL) '$(kvm_ioctl_tbl)' $(kvm_hdr_dir) > $@
socket_ipproto_array := $(beauty_outdir)/socket_ipproto_array.c
socket_ipproto_tbl := $(srctree)/tools/perf/trace/beauty/socket_ipproto.sh
$(socket_ipproto_array): $(linux_uapi_dir)/in.h $(socket_ipproto_tbl)
$(Q)$(SHELL) '$(socket_ipproto_tbl)' $(linux_uapi_dir) > $@
socket_arrays := $(beauty_outdir)/socket_arrays.c
socket_arrays := $(beauty_outdir)/socket.c
socket_tbl := $(srctree)/tools/perf/trace/beauty/socket.sh
$(socket_arrays): $(beauty_linux_dir)/socket.h $(socket_tbl)
$(Q)$(SHELL) '$(socket_tbl)' $(beauty_linux_dir) > $@
$(socket_arrays): $(linux_uapi_dir)/in.h $(beauty_linux_dir)/socket.h $(socket_tbl)
$(Q)$(SHELL) '$(socket_tbl)' $(linux_uapi_dir) $(beauty_linux_dir) > $@
sockaddr_arrays := $(beauty_outdir)/sockaddr.c
sockaddr_tbl := $(srctree)/tools/perf/trace/beauty/sockaddr.sh
$(sockaddr_arrays): $(beauty_linux_dir)/socket.h $(sockaddr_tbl)
$(Q)$(SHELL) '$(sockaddr_tbl)' $(beauty_linux_dir) > $@
vhost_virtio_ioctl_array := $(beauty_ioctl_outdir)/vhost_virtio_ioctl_array.c
vhost_virtio_hdr_dir := $(srctree)/tools/include/uapi/linux
@@ -736,8 +736,8 @@ prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioc
$(sndrv_ctl_ioctl_array) \
$(kcmp_type_array) \
$(kvm_ioctl_array) \
$(socket_ipproto_array) \
$(socket_arrays) \
$(sockaddr_arrays) \
$(vhost_virtio_ioctl_array) \
$(madvise_behavior_array) \
$(mmap_flags_array) \
@@ -1113,8 +1113,8 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
$(OUTPUT)$(sndrv_pcm_ioctl_array) \
$(OUTPUT)$(kvm_ioctl_array) \
$(OUTPUT)$(kcmp_type_array) \
$(OUTPUT)$(socket_ipproto_array) \
$(OUTPUT)$(socket_arrays) \
$(OUTPUT)$(sockaddr_arrays) \
$(OUTPUT)$(vhost_virtio_ioctl_array) \
$(OUTPUT)$(perf_ioctl_array) \
$(OUTPUT)$(prctl_option_array) \

View File

@@ -2,6 +2,6 @@
#ifndef ARCH_TESTS_H
#define ARCH_TESTS_H
extern struct test arch_tests[];
extern struct test_suite *arch_tests[];
#endif

View File

@@ -3,18 +3,10 @@
#include "tests/tests.h"
#include "arch-tests.h"
struct test arch_tests[] = {
struct test_suite *arch_tests[] = {
#ifdef HAVE_DWARF_UNWIND_SUPPORT
{
.desc = "DWARF unwind",
.func = test__dwarf_unwind,
},
&suite__dwarf_unwind,
#endif
{
.desc = "Vectors page",
.func = test__vectors_page,
},
{
.func = NULL,
},
&suite__vectors_page,
NULL,
};

View File

@@ -9,8 +9,7 @@
#define VECTORS__MAP_NAME "[vectors]"
int test__vectors_page(struct test *test __maybe_unused,
int subtest __maybe_unused)
static int test__vectors_page(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
void *start, *end;
@@ -22,3 +21,5 @@ int test__vectors_page(struct test *test __maybe_unused,
return TEST_OK;
}
DEFINE_SUITE("Vectors page", vectors_page);

View File

@@ -2,6 +2,6 @@
#ifndef ARCH_TESTS_H
#define ARCH_TESTS_H
extern struct test arch_tests[];
extern struct test_suite *arch_tests[];
#endif

View File

@@ -3,14 +3,9 @@
#include "tests/tests.h"
#include "arch-tests.h"
struct test arch_tests[] = {
struct test_suite *arch_tests[] = {
#ifdef HAVE_DWARF_UNWIND_SUPPORT
{
.desc = "DWARF unwind",
.func = test__dwarf_unwind,
},
&suite__dwarf_unwind,
#endif
{
.func = NULL,
},
NULL,
};

View File

@@ -23,6 +23,7 @@
#include "../../../util/auxtrace.h"
#include "../../../util/record.h"
#include "../../../util/arm-spe.h"
#include <tools/libc_compat.h> // reallocarray
#define KiB(x) ((x) * 1024)
#define MiB(x) ((x) * 1024 * 1024)
@@ -31,6 +32,8 @@ struct arm_spe_recording {
struct auxtrace_record itr;
struct perf_pmu *arm_spe_pmu;
struct evlist *evlist;
int wrapped_cnt;
bool *wrapped;
};
static void arm_spe_set_timestamp(struct auxtrace_record *itr,
@@ -84,6 +87,55 @@ static int arm_spe_info_fill(struct auxtrace_record *itr,
return 0;
}
static void
arm_spe_snapshot_resolve_auxtrace_defaults(struct record_opts *opts,
bool privileged)
{
/*
* The default snapshot size is the auxtrace mmap size. If neither auxtrace mmap size nor
* snapshot size is specified, then the default is 4MiB for privileged users, 128KiB for
* unprivileged users.
*
* The default auxtrace mmap size is 4MiB/page_size for privileged users, 128KiB for
* unprivileged users. If an unprivileged user does not specify mmap pages, the mmap pages
* will be reduced from the default 512KiB/page_size to 256KiB/page_size, otherwise the
* user is likely to get an error as they exceed their mlock limmit.
*/
/*
* No size were given to '-S' or '-m,', so go with the default
*/
if (!opts->auxtrace_snapshot_size && !opts->auxtrace_mmap_pages) {
if (privileged) {
opts->auxtrace_mmap_pages = MiB(4) / page_size;
} else {
opts->auxtrace_mmap_pages = KiB(128) / page_size;
if (opts->mmap_pages == UINT_MAX)
opts->mmap_pages = KiB(256) / page_size;
}
} else if (!opts->auxtrace_mmap_pages && !privileged && opts->mmap_pages == UINT_MAX) {
opts->mmap_pages = KiB(256) / page_size;
}
/*
* '-m,xyz' was specified but no snapshot size, so make the snapshot size as big as the
* auxtrace mmap area.
*/
if (!opts->auxtrace_snapshot_size)
opts->auxtrace_snapshot_size = opts->auxtrace_mmap_pages * (size_t)page_size;
/*
* '-Sxyz' was specified but no auxtrace mmap area, so make the auxtrace mmap area big
* enough to fit the requested snapshot size.
*/
if (!opts->auxtrace_mmap_pages) {
size_t sz = opts->auxtrace_snapshot_size;
sz = round_up(sz, page_size) / page_size;
opts->auxtrace_mmap_pages = roundup_pow_of_two(sz);
}
}
static int arm_spe_recording_options(struct auxtrace_record *itr,
struct evlist *evlist,
struct record_opts *opts)
@@ -115,6 +167,36 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
if (!opts->full_auxtrace)
return 0;
/*
* we are in snapshot mode.
*/
if (opts->auxtrace_snapshot_mode) {
/*
* Command arguments '-Sxyz' and/or '-m,xyz' are missing, so fill those in with
* default values.
*/
if (!opts->auxtrace_snapshot_size || !opts->auxtrace_mmap_pages)
arm_spe_snapshot_resolve_auxtrace_defaults(opts, privileged);
/*
* Snapshot size can't be bigger than the auxtrace area.
*/
if (opts->auxtrace_snapshot_size > opts->auxtrace_mmap_pages * (size_t)page_size) {
pr_err("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n",
opts->auxtrace_snapshot_size,
opts->auxtrace_mmap_pages * (size_t)page_size);
return -EINVAL;
}
/*
* Something went wrong somewhere - this shouldn't happen.
*/
if (!opts->auxtrace_snapshot_size || !opts->auxtrace_mmap_pages) {
pr_err("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n");
return -EINVAL;
}
}
/* We are in full trace mode but '-m,xyz' wasn't specified */
if (!opts->auxtrace_mmap_pages) {
if (privileged) {
@@ -138,6 +220,9 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
}
}
if (opts->auxtrace_snapshot_mode)
pr_debug2("%sx snapshot size: %zu\n", ARM_SPE_PMU_NAME,
opts->auxtrace_snapshot_size);
/*
* To obtain the auxtrace buffer file descriptor, the auxtrace event
@@ -166,8 +251,199 @@ static int arm_spe_recording_options(struct auxtrace_record *itr,
tracking_evsel->core.attr.sample_period = 1;
/* In per-cpu case, always need the time of mmap events etc */
if (!perf_cpu_map__empty(cpus))
if (!perf_cpu_map__empty(cpus)) {
evsel__set_sample_bit(tracking_evsel, TIME);
evsel__set_sample_bit(tracking_evsel, CPU);
/* also track task context switch */
if (!record_opts__no_switch_events(opts))
tracking_evsel->core.attr.context_switch = 1;
}
return 0;
}
static int arm_spe_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused,
struct record_opts *opts,
const char *str)
{
unsigned long long snapshot_size = 0;
char *endptr;
if (str) {
snapshot_size = strtoull(str, &endptr, 0);
if (*endptr || snapshot_size > SIZE_MAX)
return -1;
}
opts->auxtrace_snapshot_mode = true;
opts->auxtrace_snapshot_size = snapshot_size;
return 0;
}
static int arm_spe_snapshot_start(struct auxtrace_record *itr)
{
struct arm_spe_recording *ptr =
container_of(itr, struct arm_spe_recording, itr);
struct evsel *evsel;
evlist__for_each_entry(ptr->evlist, evsel) {
if (evsel->core.attr.type == ptr->arm_spe_pmu->type)
return evsel__disable(evsel);
}
return -EINVAL;
}
static int arm_spe_snapshot_finish(struct auxtrace_record *itr)
{
struct arm_spe_recording *ptr =
container_of(itr, struct arm_spe_recording, itr);
struct evsel *evsel;
evlist__for_each_entry(ptr->evlist, evsel) {
if (evsel->core.attr.type == ptr->arm_spe_pmu->type)
return evsel__enable(evsel);
}
return -EINVAL;
}
static int arm_spe_alloc_wrapped_array(struct arm_spe_recording *ptr, int idx)
{
bool *wrapped;
int cnt = ptr->wrapped_cnt, new_cnt, i;
/*
* No need to allocate, so return early.
*/
if (idx < cnt)
return 0;
/*
* Make ptr->wrapped as big as idx.
*/
new_cnt = idx + 1;
/*
* Free'ed in arm_spe_recording_free().
*/
wrapped = reallocarray(ptr->wrapped, new_cnt, sizeof(bool));
if (!wrapped)
return -ENOMEM;
/*
* init new allocated values.
*/
for (i = cnt; i < new_cnt; i++)
wrapped[i] = false;
ptr->wrapped_cnt = new_cnt;
ptr->wrapped = wrapped;
return 0;
}
static bool arm_spe_buffer_has_wrapped(unsigned char *buffer,
size_t buffer_size, u64 head)
{
u64 i, watermark;
u64 *buf = (u64 *)buffer;
size_t buf_size = buffer_size;
/*
* Defensively handle the case where head might be continually increasing - if its value is
* equal or greater than the size of the ring buffer, then we can safely determine it has
* wrapped around. Otherwise, continue to detect if head might have wrapped.
*/
if (head >= buffer_size)
return true;
/*
* We want to look the very last 512 byte (chosen arbitrarily) in the ring buffer.
*/
watermark = buf_size - 512;
/*
* The value of head is somewhere within the size of the ring buffer. This can be that there
* hasn't been enough data to fill the ring buffer yet or the trace time was so long that
* head has numerically wrapped around. To find we need to check if we have data at the
* very end of the ring buffer. We can reliably do this because mmap'ed pages are zeroed
* out and there is a fresh mapping with every new session.
*/
/*
* head is less than 512 byte from the end of the ring buffer.
*/
if (head > watermark)
watermark = head;
/*
* Speed things up by using 64 bit transactions (see "u64 *buf" above)
*/
watermark /= sizeof(u64);
buf_size /= sizeof(u64);
/*
* If we find trace data at the end of the ring buffer, head has been there and has
* numerically wrapped around at least once.
*/
for (i = watermark; i < buf_size; i++)
if (buf[i])
return true;
return false;
}
static int arm_spe_find_snapshot(struct auxtrace_record *itr, int idx,
struct auxtrace_mmap *mm, unsigned char *data,
u64 *head, u64 *old)
{
int err;
bool wrapped;
struct arm_spe_recording *ptr =
container_of(itr, struct arm_spe_recording, itr);
/*
* Allocate memory to keep track of wrapping if this is the first
* time we deal with this *mm.
*/
if (idx >= ptr->wrapped_cnt) {
err = arm_spe_alloc_wrapped_array(ptr, idx);
if (err)
return err;
}
/*
* Check to see if *head has wrapped around. If it hasn't only the
* amount of data between *head and *old is snapshot'ed to avoid
* bloating the perf.data file with zeros. But as soon as *head has
* wrapped around the entire size of the AUX ring buffer it taken.
*/
wrapped = ptr->wrapped[idx];
if (!wrapped && arm_spe_buffer_has_wrapped(data, mm->len, *head)) {
wrapped = true;
ptr->wrapped[idx] = true;
}
pr_debug3("%s: mmap index %d old head %zu new head %zu size %zu\n",
__func__, idx, (size_t)*old, (size_t)*head, mm->len);
/*
* No wrap has occurred, we can just use *head and *old.
*/
if (!wrapped)
return 0;
/*
* *head has wrapped around - adjust *head and *old to pickup the
* entire content of the AUX buffer.
*/
if (*head >= mm->len) {
*old = *head - mm->len;
} else {
*head += mm->len;
*old = *head - mm->len;
}
return 0;
}
@@ -186,6 +462,7 @@ static void arm_spe_recording_free(struct auxtrace_record *itr)
struct arm_spe_recording *sper =
container_of(itr, struct arm_spe_recording, itr);
free(sper->wrapped);
free(sper);
}
@@ -207,6 +484,10 @@ struct auxtrace_record *arm_spe_recording_init(int *err,
sper->arm_spe_pmu = arm_spe_pmu;
sper->itr.pmu = arm_spe_pmu;
sper->itr.snapshot_start = arm_spe_snapshot_start;
sper->itr.snapshot_finish = arm_spe_snapshot_finish;
sper->itr.find_snapshot = arm_spe_find_snapshot;
sper->itr.parse_snapshot_options = arm_spe_parse_snapshot_options;
sper->itr.recording_options = arm_spe_recording_options;
sper->itr.info_priv_size = arm_spe_info_priv_size;
sper->itr.info_fill = arm_spe_info_fill;

View File

@@ -2,6 +2,6 @@
#ifndef ARCH_TESTS_H
#define ARCH_TESTS_H
extern struct test arch_tests[];
extern struct test_suite *arch_tests[];
#endif

View File

@@ -3,14 +3,10 @@
#include "tests/tests.h"
#include "arch-tests.h"
struct test arch_tests[] = {
struct test_suite *arch_tests[] = {
#ifdef HAVE_DWARF_UNWIND_SUPPORT
{
.desc = "Test dwarf unwind",
.func = test__dwarf_unwind,
},
&suite__dwarf_unwind,
#endif
{
.func = NULL,
},
NULL,
};

View File

@@ -370,6 +370,7 @@
446 common landlock_restrict_self sys_landlock_restrict_self
447 common memfd_secret sys_memfd_secret
448 common process_mrelease sys_process_mrelease
449 common futex_waitv sys_futex_waitv
#
# Due to a historical design error, certain syscalls are numbered differently

View File

@@ -2,15 +2,15 @@
#ifndef ARCH_TESTS_H
#define ARCH_TESTS_H
struct test;
struct test_suite;
/* Tests */
int test__rdpmc(struct test *test, int subtest);
int test__insn_x86(struct test *test, int subtest);
int test__intel_pt_pkt_decoder(struct test *test, int subtest);
int test__bp_modify(struct test *test, int subtest);
int test__x86_sample_parsing(struct test *test, int subtest);
int test__rdpmc(struct test_suite *test, int subtest);
int test__insn_x86(struct test_suite *test, int subtest);
int test__intel_pt_pkt_decoder(struct test_suite *test, int subtest);
int test__bp_modify(struct test_suite *test, int subtest);
int test__x86_sample_parsing(struct test_suite *test, int subtest);
extern struct test arch_tests[];
extern struct test_suite *arch_tests[];
#endif

View File

@@ -3,39 +3,28 @@
#include "tests/tests.h"
#include "arch-tests.h"
struct test arch_tests[] = {
{
.desc = "x86 rdpmc",
.func = test__rdpmc,
},
#ifdef HAVE_DWARF_UNWIND_SUPPORT
{
.desc = "DWARF unwind",
.func = test__dwarf_unwind,
},
#endif
DEFINE_SUITE("x86 rdpmc", rdpmc);
#ifdef HAVE_AUXTRACE_SUPPORT
{
.desc = "x86 instruction decoder - new instructions",
.func = test__insn_x86,
},
{
.desc = "Intel PT packet decoder",
.func = test__intel_pt_pkt_decoder,
},
DEFINE_SUITE("x86 instruction decoder - new instructions", insn_x86);
DEFINE_SUITE("Intel PT packet decoder", intel_pt_pkt_decoder);
#endif
#if defined(__x86_64__)
{
.desc = "x86 bp modify",
.func = test__bp_modify,
},
DEFINE_SUITE("x86 bp modify", bp_modify);
#endif
{
.desc = "x86 Sample parsing",
.func = test__x86_sample_parsing,
},
{
.func = NULL,
},
DEFINE_SUITE("x86 Sample parsing", x86_sample_parsing);
struct test_suite *arch_tests[] = {
&suite__rdpmc,
#ifdef HAVE_DWARF_UNWIND_SUPPORT
&suite__dwarf_unwind,
#endif
#ifdef HAVE_AUXTRACE_SUPPORT
&suite__insn_x86,
&suite__intel_pt_pkt_decoder,
#endif
#if defined(__x86_64__)
&suite__bp_modify,
#endif
&suite__x86_sample_parsing,
NULL,
};

View File

@@ -204,7 +204,7 @@ out:
return rip == (unsigned long) bp_1 ? TEST_OK : TEST_FAIL;
}
int test__bp_modify(struct test *test __maybe_unused,
int test__bp_modify(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
TEST_ASSERT_VAL("modify test 1 failed\n", !bp_modify1());

View File

@@ -173,7 +173,7 @@ static int test_data_set(struct test_data *dat_set, int x86_64)
* verbose (-v) option to see all the instructions and whether or not they
* decoded successfully.
*/
int test__insn_x86(struct test *test __maybe_unused, int subtest __maybe_unused)
int test__insn_x86(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int ret = 0;

View File

@@ -37,7 +37,7 @@ static pid_t spawn(void)
* the last read counter value to avoid triggering a WARN_ON_ONCE() in
* smp_call_function_many() caused by sending IPIs from NMI context.
*/
int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subtest __maybe_unused)
int test__intel_cqm_count_nmi_context(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct evlist *evlist = NULL;
struct evsel *evsel = NULL;

View File

@@ -289,7 +289,7 @@ static int test_one(struct test_data *d)
* This test feeds byte sequences to the Intel PT packet decoder and checks the
* results. Changes to the packet context are also checked.
*/
int test__intel_pt_pkt_decoder(struct test *test __maybe_unused, int subtest __maybe_unused)
int test__intel_pt_pkt_decoder(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct test_data *d = data;
int ret;

View File

@@ -157,7 +157,7 @@ out_close:
return 0;
}
int test__rdpmc(struct test *test __maybe_unused, int subtest __maybe_unused)
int test__rdpmc(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int status = 0;
int wret = 0;

View File

@@ -115,7 +115,7 @@ out_free:
* For now, the PERF_SAMPLE_WEIGHT_STRUCT is the only X86 specific sample type.
* The test only checks the PERF_SAMPLE_WEIGHT_STRUCT type.
*/
int test__x86_sample_parsing(struct test *test __maybe_unused, int subtest __maybe_unused)
int test__x86_sample_parsing(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
return do_test(PERF_SAMPLE_WEIGHT_STRUCT);
}

View File

@@ -233,6 +233,7 @@ int bench_futex_lock_pi(int argc, const char **argv)
print_summary();
free(worker);
perf_cpu_map__put(cpu);
return ret;
err:
usage_with_options(bench_futex_lock_pi_usage, options);

View File

@@ -294,6 +294,7 @@ int bench_futex_requeue(int argc, const char **argv)
print_summary();
free(worker);
perf_cpu_map__put(cpu);
return ret;
err:
usage_with_options(bench_futex_requeue_usage, options);

View File

@@ -329,6 +329,7 @@ int bench_futex_wake_parallel(int argc, const char **argv)
print_summary();
free(blocked_worker);
perf_cpu_map__put(cpu);
return ret;
}
#endif /* HAVE_PTHREAD_BARRIER */

View File

@@ -222,5 +222,6 @@ int bench_futex_wake(int argc, const char **argv)
print_summary();
free(worker);
perf_cpu_map__put(cpu);
return ret;
}

View File

@@ -979,6 +979,8 @@ static struct syscall_fmt syscall_fmts[] = {
.arg = { [2] = { .scnprintf = SCA_GETRANDOM_FLAGS, /* flags */ }, }, },
{ .name = "getrlimit",
.arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
{ .name = "getsockopt",
.arg = { [1] = STRARRAY(level, socket_level), }, },
{ .name = "gettid", .errpid = true, },
{ .name = "ioctl",
.arg = {
@@ -1121,6 +1123,8 @@ static struct syscall_fmt syscall_fmts[] = {
.arg = { [0] = STRARRAY(which, itimers), }, },
{ .name = "setrlimit",
.arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
{ .name = "setsockopt",
.arg = { [1] = STRARRAY(level, socket_level), }, },
{ .name = "socket",
.arg = { [0] = STRARRAY(family, socket_families),
[1] = { .scnprintf = SCA_SK_TYPE, /* type */ },

View File

@@ -106,6 +106,9 @@ enum perf_hw_id {
PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4,
PERF_COUNT_HW_BRANCH_MISSES = 5,
PERF_COUNT_HW_BUS_CYCLES = 6,
PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 7,
PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 8,
PERF_COUNT_HW_REF_CPU_CYCLES = 9,
};
These are standardized types of events that work relatively uniformly

View File

@@ -0,0 +1,676 @@
[
{
"BriefDescription": "Percentage of cycles that are run cycles",
"MetricExpr": "PM_RUN_CYC / PM_CYC * 100",
"MetricGroup": "General",
"MetricName": "RUN_CYCLES_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Average cycles per completed instruction",
"MetricExpr": "PM_CYC / PM_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "CYCLES_PER_INSTRUCTION"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled for any reason",
"MetricExpr": "PM_DISP_STALL_CYC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled because there was a flush",
"MetricExpr": "PM_DISP_STALL_FLUSH / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_FLUSH_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled because the MMU was handling a translation miss",
"MetricExpr": "PM_DISP_STALL_TRANSLATION / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_TRANSLATION_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled waiting to resolve an instruction ERAT miss",
"MetricExpr": "PM_DISP_STALL_IERAT_ONLY_MISS / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_IERAT_ONLY_MISS_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled waiting to resolve an instruction TLB miss",
"MetricExpr": "PM_DISP_STALL_ITLB_MISS / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_ITLB_MISS_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled due to an icache miss",
"MetricExpr": "PM_DISP_STALL_IC_MISS / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_IC_MISS_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled while the instruction was fetched from the local L2",
"MetricExpr": "PM_DISP_STALL_IC_L2 / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_IC_L2_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled while the instruction was fetched from the local L3",
"MetricExpr": "PM_DISP_STALL_IC_L3 / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_IC_L3_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled while the instruction was fetched from any source beyond the local L3",
"MetricExpr": "PM_DISP_STALL_IC_L3MISS / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_IC_L3MISS_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled due to an icache miss after a branch mispredict",
"MetricExpr": "PM_DISP_STALL_BR_MPRED_ICMISS / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_BR_MPRED_ICMISS_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled while instruction was fetched from the local L2 after suffering a branch mispredict",
"MetricExpr": "PM_DISP_STALL_BR_MPRED_IC_L2 / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_BR_MPRED_IC_L2_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled while instruction was fetched from the local L3 after suffering a branch mispredict",
"MetricExpr": "PM_DISP_STALL_BR_MPRED_IC_L3 / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_BR_MPRED_IC_L3_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled while instruction was fetched from any source beyond the local L3 after suffering a branch mispredict",
"MetricExpr": "PM_DISP_STALL_BR_MPRED_IC_L3MISS / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_BR_MPRED_IC_L3MISS_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled due to a branch mispredict",
"MetricExpr": "PM_DISP_STALL_BR_MPRED / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_BR_MPRED_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction was held at dispatch for any reason",
"MetricExpr": "PM_DISP_STALL_HELD_CYC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_HELD_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction was held at dispatch because of a synchronizing instruction that requires the ICT to be empty before dispatch",
"MetricExpr": "PM_DISP_STALL_HELD_SYNC_CYC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISP_HELD_STALL_SYNC_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction was held at dispatch while waiting on the scoreboard",
"MetricExpr": "PM_DISP_STALL_HELD_SCOREBOARD_CYC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISP_HELD_STALL_SCOREBOARD_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction was held at dispatch due to issue queue full",
"MetricExpr": "PM_DISP_STALL_HELD_ISSQ_FULL_CYC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISP_HELD_STALL_ISSQ_FULL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction was held at dispatch because the mapper/SRB was full",
"MetricExpr": "PM_DISP_STALL_HELD_RENAME_CYC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_HELD_RENAME_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction was held at dispatch because the STF mapper/SRB was full",
"MetricExpr": "PM_DISP_STALL_HELD_STF_MAPPER_CYC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_HELD_STF_MAPPER_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction was held at dispatch because the XVFC mapper/SRB was full",
"MetricExpr": "PM_DISP_STALL_HELD_XVFC_MAPPER_CYC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_HELD_XVFC_MAPPER_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction was held at dispatch for any other reason",
"MetricExpr": "PM_DISP_STALL_HELD_OTHER_CYC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_HELD_OTHER_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction has been dispatched but not issued for any reason",
"MetricExpr": "PM_ISSUE_STALL / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "ISSUE_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is waiting to be finished in one of the execution units",
"MetricExpr": "PM_EXEC_STALL / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "EXECUTION_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction spent executing an NTC instruction that gets flushed some time after dispatch",
"MetricExpr": "PM_EXEC_STALL_NTC_FLUSH / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "NTC_FLUSH_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTF instruction finishes at dispatch",
"MetricExpr": "PM_EXEC_STALL_FIN_AT_DISP / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "FIN_AT_DISP_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is executing in the branch unit",
"MetricExpr": "PM_EXEC_STALL_BRU / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "BRU_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is a simple fixed point instruction that is executing in the LSU",
"MetricExpr": "PM_EXEC_STALL_SIMPLE_FX / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "SIMPLE_FX_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is executing in the VSU",
"MetricExpr": "PM_EXEC_STALL_VSU / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "VSU_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is waiting to be finished in one of the execution units",
"MetricExpr": "PM_EXEC_STALL_TRANSLATION / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "TRANSLATION_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is a load or store that suffered a translation miss",
"MetricExpr": "PM_EXEC_STALL_DERAT_ONLY_MISS / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DERAT_ONLY_MISS_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is recovering from a TLB miss",
"MetricExpr": "PM_EXEC_STALL_DERAT_DTLB_MISS / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DERAT_DTLB_MISS_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is executing in the LSU",
"MetricExpr": "PM_EXEC_STALL_LSU / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "LSU_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is a load that is executing in the LSU",
"MetricExpr": "PM_EXEC_STALL_LOAD / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "LOAD_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is waiting for a load miss to resolve from either the local L2 or local L3",
"MetricExpr": "PM_EXEC_STALL_DMISS_L2L3 / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DMISS_L2L3_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is waiting for a load miss to resolve from either the local L2 or local L3, with an RC dispatch conflict",
"MetricExpr": "PM_EXEC_STALL_DMISS_L2L3_CONFLICT / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DMISS_L2L3_CONFLICT_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is waiting for a load miss to resolve from either the local L2 or local L3, without an RC dispatch conflict",
"MetricExpr": "PM_EXEC_STALL_DMISS_L2L3_NOCONFLICT / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DMISS_L2L3_NOCONFLICT_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is waiting for a load miss to resolve from a source beyond the local L2 and local L3",
"MetricExpr": "PM_EXEC_STALL_DMISS_L3MISS / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DMISS_L3MISS_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is waiting for a load miss to resolve from a neighbor chiplet's L2 or L3 in the same chip",
"MetricExpr": "PM_EXEC_STALL_DMISS_L21_L31 / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DMISS_L21_L31_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is waiting for a load miss to resolve from L4, local memory or OpenCAPI chip",
"MetricExpr": "PM_EXEC_STALL_DMISS_LMEM / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DMISS_LMEM_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is waiting for a load miss to resolve from a remote chip (cache, L4, memory or OpenCAPI) in the same group",
"MetricExpr": "PM_EXEC_STALL_DMISS_OFF_CHIP / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DMISS_OFF_CHIP_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is waiting for a load miss to resolve from a distant chip (cache, L4, memory or OpenCAPI chip)",
"MetricExpr": "PM_EXEC_STALL_DMISS_OFF_NODE / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DMISS_OFF_NODE_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is executing a TLBIEL instruction",
"MetricExpr": "PM_EXEC_STALL_TLBIEL / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "TLBIEL_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is finishing a load after its data has been reloaded from a data source beyond the local L1, OR when the LSU is processing an L1-hit, OR when the NTF instruction merged with another load in the LMQ",
"MetricExpr": "PM_EXEC_STALL_LOAD_FINISH / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "LOAD_FINISH_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is a store that is executing in the LSU",
"MetricExpr": "PM_EXEC_STALL_STORE / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "STORE_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is in the store unit outside of handling store misses or other special store operations",
"MetricExpr": "PM_EXEC_STALL_STORE_PIPE / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "STORE_PIPE_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is a store whose cache line was not resident in the L1 and had to wait for allocation of the missing line into the L1",
"MetricExpr": "PM_EXEC_STALL_STORE_MISS / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "STORE_MISS_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is a TLBIE instruction waiting for a response from the L2",
"MetricExpr": "PM_EXEC_STALL_TLBIE / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "TLBIE_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is executing a PTESYNC instruction",
"MetricExpr": "PM_EXEC_STALL_PTESYNC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "PTESYNC_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction cannot complete because the thread was blocked",
"MetricExpr": "PM_CMPL_STALL / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "COMPLETION_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction cannot complete because it was interrupted by ANY exception",
"MetricExpr": "PM_CMPL_STALL_EXCEPTION / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "EXCEPTION_COMPLETION_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is stuck at finish waiting for the non-speculative finish of either a STCX instruction waiting for its result or a load waiting for non-critical sectors of data and ECC",
"MetricExpr": "PM_CMPL_STALL_MEM_ECC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "MEM_ECC_COMPLETION_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is a STCX instruction waiting for resolution from the nest",
"MetricExpr": "PM_CMPL_STALL_STCX / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "STCX_COMPLETION_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is a LWSYNC instruction waiting to complete",
"MetricExpr": "PM_CMPL_STALL_LWSYNC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "LWSYNC_COMPLETION_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction is a HWSYNC instruction stuck at finish waiting for a response from the L2",
"MetricExpr": "PM_CMPL_STALL_HWSYNC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "HWSYNC_COMPLETION_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction required special handling before completion",
"MetricExpr": "PM_CMPL_STALL_SPECIAL / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "SPECIAL_COMPLETION_STALL_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when dispatch was stalled because fetch was being held, so there was nothing in the pipeline for this thread",
"MetricExpr": "PM_DISP_STALL_FETCH / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_FETCH_CPI"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTC instruction was held at dispatch because of power management",
"MetricExpr": "PM_DISP_STALL_HELD_HALT_CYC / PM_RUN_INST_CMPL",
"MetricGroup": "CPI",
"MetricName": "DISPATCHED_HELD_HALT_CPI"
},
{
"BriefDescription": "Percentage of flushes per completed instruction",
"MetricExpr": "PM_FLUSH / PM_RUN_INST_CMPL * 100",
"MetricGroup": "Others",
"MetricName": "FLUSH_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of flushes due to a branch mispredict per completed instruction",
"MetricExpr": "PM_FLUSH_MPRED / PM_RUN_INST_CMPL * 100",
"MetricGroup": "Others",
"MetricName": "BR_MPRED_FLUSH_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of branch mispredictions per completed instruction",
"MetricExpr": "PM_BR_MPRED_CMPL / PM_RUN_INST_CMPL",
"MetricGroup": "Others",
"MetricName": "BRANCH_MISPREDICTION_RATE"
},
{
"BriefDescription": "Percentage of finished loads that missed in the L1",
"MetricExpr": "PM_LD_MISS_L1 / PM_LD_REF_L1 * 100",
"MetricGroup": "Others",
"MetricName": "L1_LD_MISS_RATIO",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of completed instructions that were loads that missed the L1",
"MetricExpr": "PM_LD_MISS_L1 / PM_RUN_INST_CMPL * 100",
"MetricGroup": "Others",
"MetricName": "L1_LD_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of completed instructions when the DPTEG required for the load/store instruction in execution was missing from the TLB",
"MetricExpr": "PM_DTLB_MISS / PM_RUN_INST_CMPL * 100",
"MetricGroup": "Others",
"MetricName": "DTLB_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Average number of completed instructions dispatched per instruction completed",
"MetricExpr": "PM_INST_DISP / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "DISPATCH_PER_INST_CMPL"
},
{
"BriefDescription": "Percentage of completed instructions that were a demand load that did not hit in the L1 or L2",
"MetricExpr": "PM_DATA_FROM_L2MISS / PM_RUN_INST_CMPL * 100",
"MetricGroup": "General",
"MetricName": "L2_LD_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of completed instructions that were demand fetches that missed the L1 icache",
"MetricExpr": "PM_L1_ICACHE_MISS / PM_RUN_INST_CMPL * 100",
"MetricGroup": "Instruction_Misses",
"MetricName": "L1_INST_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of completed instructions that were demand fetches that reloaded from beyond the L3 icache",
"MetricExpr": "PM_INST_FROM_L3MISS / PM_RUN_INST_CMPL * 100",
"MetricGroup": "General",
"MetricName": "L3_INST_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Average number of completed instructions per cycle",
"MetricExpr": "PM_INST_CMPL / PM_CYC",
"MetricGroup": "General",
"MetricName": "IPC"
},
{
"BriefDescription": "Average number of cycles per completed instruction group",
"MetricExpr": "PM_CYC / PM_1PLUS_PPC_CMPL",
"MetricGroup": "General",
"MetricName": "CYCLES_PER_COMPLETED_INSTRUCTIONS_SET"
},
{
"BriefDescription": "Percentage of cycles when at least 1 instruction dispatched",
"MetricExpr": "PM_1PLUS_PPC_DISP / PM_RUN_CYC * 100",
"MetricGroup": "General",
"MetricName": "CYCLES_ATLEAST_ONE_INST_DISPATCHED",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Average number of finished loads per completed instruction",
"MetricExpr": "PM_LD_REF_L1 / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "LOADS_PER_INST"
},
{
"BriefDescription": "Average number of finished stores per completed instruction",
"MetricExpr": "PM_ST_FIN / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "STORES_PER_INST"
},
{
"BriefDescription": "Percentage of demand loads that reloaded from beyond the L2 per completed instruction",
"MetricExpr": "PM_DATA_FROM_L2MISS / PM_RUN_INST_CMPL * 100",
"MetricGroup": "dL1_Reloads",
"MetricName": "DL1_RELOAD_FROM_L2_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of demand loads that reloaded from beyond the L3 per completed instruction",
"MetricExpr": "PM_DATA_FROM_L3MISS / PM_RUN_INST_CMPL * 100",
"MetricGroup": "dL1_Reloads",
"MetricName": "DL1_RELOAD_FROM_L3_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of DERAT misses with 4k page size per completed instruction",
"MetricExpr": "PM_DERAT_MISS_4K / PM_RUN_INST_CMPL * 100",
"MetricGroup": "Translation",
"MetricName": "DERAT_4K_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of DERAT misses with 64k page size per completed instruction",
"MetricExpr": "PM_DERAT_MISS_64K / PM_RUN_INST_CMPL * 100",
"MetricGroup": "Translation",
"MetricName": "DERAT_64K_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Average number of run cycles per completed instruction",
"MetricExpr": "PM_RUN_CYC / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "RUN_CPI"
},
{
"BriefDescription": "Percentage of DERAT misses per completed instruction",
"MetricExpr": "PM_DERAT_MISS / PM_RUN_INST_CMPL * 100",
"MetricGroup": "Translation",
"MetricName": "DERAT_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Average number of completed instructions per run cycle",
"MetricExpr": "PM_RUN_INST_CMPL / PM_RUN_CYC",
"MetricGroup": "General",
"MetricName": "RUN_IPC"
},
{
"BriefDescription": "Average number of completed instructions per instruction group",
"MetricExpr": "PM_RUN_INST_CMPL / PM_1PLUS_PPC_CMPL",
"MetricGroup": "General",
"MetricName": "AVERAGE_COMPLETED_INSTRUCTION_SET_SIZE"
},
{
"BriefDescription": "Average number of finished instructions per completed instructions",
"MetricExpr": "PM_INST_FIN / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "INST_FIN_PER_CMPL"
},
{
"BriefDescription": "Average cycles per completed instruction when the NTF instruction is completing and the finish was overlooked",
"MetricExpr": "PM_EXEC_STALL_UNKNOWN / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "EXEC_STALL_UNKOWN_CPI"
},
{
"BriefDescription": "Percentage of finished branches that were taken",
"MetricExpr": "PM_BR_TAKEN_CMPL / PM_BR_FIN * 100",
"MetricGroup": "General",
"MetricName": "TAKEN_BRANCHES",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of completed instructions that were a demand load that did not hit in the L1, L2, or the L3",
"MetricExpr": "PM_DATA_FROM_L3MISS / PM_RUN_INST_CMPL * 100",
"MetricGroup": "General",
"MetricName": "L3_LD_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Average number of finished branches per completed instruction",
"MetricExpr": "PM_BR_FIN / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "BRANCHES_PER_INST"
},
{
"BriefDescription": "Average number of instructions finished in the LSU per completed instruction",
"MetricExpr": "PM_LSU_FIN / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "LSU_PER_INST"
},
{
"BriefDescription": "Average number of instructions finished in the VSU per completed instruction",
"MetricExpr": "PM_VSU_FIN / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "VSU_PER_INST"
},
{
"BriefDescription": "Average number of TLBIE instructions finished in the LSU per completed instruction",
"MetricExpr": "PM_TLBIE_FIN / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "TLBIE_PER_INST"
},
{
"BriefDescription": "Average number of STCX instructions finshed per completed instruction",
"MetricExpr": "PM_STCX_FIN / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "STXC_PER_INST"
},
{
"BriefDescription": "Average number of LARX instructions finshed per completed instruction",
"MetricExpr": "PM_LARX_FIN / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "LARX_PER_INST"
},
{
"BriefDescription": "Average number of PTESYNC instructions finshed per completed instruction",
"MetricExpr": "PM_PTESYNC_FIN / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "PTESYNC_PER_INST"
},
{
"BriefDescription": "Average number of simple fixed-point instructions finshed in the store unit per completed instruction",
"MetricExpr": "PM_FX_LSU_FIN / PM_RUN_INST_CMPL",
"MetricGroup": "General",
"MetricName": "FX_PER_INST"
},
{
"BriefDescription": "Percentage of demand load misses that reloaded the L1 cache",
"MetricExpr": "PM_LD_DEMAND_MISS_L1 / PM_LD_MISS_L1 * 100",
"MetricGroup": "General",
"MetricName": "DL1_MISS_RELOADS",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of demand load misses that reloaded from beyond the local L2",
"MetricExpr": "PM_DATA_FROM_L2MISS / PM_LD_DEMAND_MISS_L1 * 100",
"MetricGroup": "dL1_Reloads",
"MetricName": "DL1_RELOAD_FROM_L2_MISS",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of demand load misses that reloaded from beyond the local L3",
"MetricExpr": "PM_DATA_FROM_L3MISS / PM_LD_DEMAND_MISS_L1 * 100",
"MetricGroup": "dL1_Reloads",
"MetricName": "DL1_RELOAD_FROM_L3_MISS",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of cycles stalled due to the NTC instruction waiting for a load miss to resolve from a source beyond the local L2 and local L3",
"MetricExpr": "DMISS_L3MISS_STALL_CPI / RUN_CPI * 100",
"MetricGroup": "General",
"MetricName": "DCACHE_MISS_CPI",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of DERAT misses with 2M page size per completed instruction",
"MetricExpr": "PM_DERAT_MISS_2M / PM_RUN_INST_CMPL * 100",
"MetricGroup": "Translation",
"MetricName": "DERAT_2M_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of DERAT misses with 16M page size per completed instruction",
"MetricExpr": "PM_DERAT_MISS_16M / PM_RUN_INST_CMPL * 100",
"MetricGroup": "Translation",
"MetricName": "DERAT_16M_MISS_RATE",
"ScaleUnit": "1%"
},
{
"BriefDescription": "DERAT miss ratio for 4K page size",
"MetricExpr": "PM_DERAT_MISS_4K / PM_DERAT_MISS",
"MetricGroup": "Translation",
"MetricName": "DERAT_4K_MISS_RATIO"
},
{
"BriefDescription": "DERAT miss ratio for 2M page size",
"MetricExpr": "PM_DERAT_MISS_2M / PM_DERAT_MISS",
"MetricGroup": "Translation",
"MetricName": "DERAT_2M_MISS_RATIO"
},
{
"BriefDescription": "DERAT miss ratio for 16M page size",
"MetricExpr": "PM_DERAT_MISS_16M / PM_DERAT_MISS",
"MetricGroup": "Translation",
"MetricName": "DERAT_16M_MISS_RATIO"
},
{
"BriefDescription": "DERAT miss ratio for 64K page size",
"MetricExpr": "PM_DERAT_MISS_64K / PM_DERAT_MISS",
"MetricGroup": "Translation",
"MetricName": "DERAT_64K_MISS_RATIO"
},
{
"BriefDescription": "Percentage of DERAT misses that resulted in TLB reloads",
"MetricExpr": "PM_DTLB_MISS / PM_DERAT_MISS * 100",
"MetricGroup": "Translation",
"MetricName": "DERAT_MISS_RELOAD",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of icache misses that were reloaded from beyond the local L3",
"MetricExpr": "PM_INST_FROM_L3MISS / PM_L1_ICACHE_MISS * 100",
"MetricGroup": "Instruction_Misses",
"MetricName": "INST_FROM_L3_MISS",
"ScaleUnit": "1%"
},
{
"BriefDescription": "Percentage of icache reloads from the beyond the L3 per completed instruction",
"MetricExpr": "PM_INST_FROM_L3MISS / PM_RUN_INST_CMPL * 100",
"MetricGroup": "Instruction_Misses",
"MetricName": "INST_FROM_L3_MISS_RATE",
"ScaleUnit": "1%"
}
]

View File

@@ -289,8 +289,8 @@ static int test_get_dec(void)
return ret;
}
int test__api_io(struct test *test __maybe_unused,
int subtest __maybe_unused)
static int test__api_io(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
int ret = 0;
@@ -302,3 +302,5 @@ int test__api_io(struct test *test __maybe_unused,
ret = TEST_FAIL;
return ret;
}
DEFINE_SUITE("Test api io", api_io);

View File

@@ -178,7 +178,7 @@ static int run_dir(const char *d, const char *perf)
return system(cmd) ? TEST_FAIL : TEST_OK;
}
int test__attr(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__attr(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct stat st;
char path_perf[PATH_MAX];
@@ -207,3 +207,5 @@ int test__attr(struct test *test __maybe_unused, int subtest __maybe_unused)
return TEST_SKIP;
}
DEFINE_SUITE("Setup struct perf_event_attr", attr);

View File

@@ -82,7 +82,7 @@ static int do_test(struct evlist *evlist, int mmap_pages,
}
int test__backward_ring_buffer(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__backward_ring_buffer(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0;
char pid[16], sbuf[STRERR_BUFSIZE];
@@ -167,3 +167,5 @@ out_delete_evlist:
evlist__delete(evlist);
return ret;
}
DEFINE_SUITE("Read backward ring buffer", backward_ring_buffer);

View File

@@ -40,7 +40,7 @@ static int test_bitmap(const char *str)
return ret;
}
int test__bitmap_print(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__bitmap_print(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
TEST_ASSERT_VAL("failed to convert map", test_bitmap("1"));
TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,5"));
@@ -51,3 +51,5 @@ int test__bitmap_print(struct test *test __maybe_unused, int subtest __maybe_unu
TEST_ASSERT_VAL("failed to convert map", test_bitmap("1-10,12-20,22-30,32-40"));
return 0;
}
DEFINE_SUITE("Print bitmap", bitmap_print);

View File

@@ -19,6 +19,19 @@
#include "../perf-sys.h"
#include "cloexec.h"
/*
* PowerPC and S390 do not support creation of instruction breakpoints using the
* perf_event interface.
*
* Just disable the test for these architectures until these issues are
* resolved.
*/
#if defined(__powerpc__) || defined(__s390x__)
#define BP_ACCOUNT_IS_SUPPORTED 0
#else
#define BP_ACCOUNT_IS_SUPPORTED 1
#endif
static volatile long the_var;
static noinline int test_function(void)
@@ -173,13 +186,18 @@ static int detect_share(int wp_cnt, int bp_cnt)
* we create another watchpoint to ensure
* the slot accounting is correct
*/
int test__bp_accounting(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__bp_accounting(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int has_ioctl = detect_ioctl();
int wp_cnt = detect_cnt(false);
int bp_cnt = detect_cnt(true);
int share = detect_share(wp_cnt, bp_cnt);
if (!BP_ACCOUNT_IS_SUPPORTED) {
pr_debug("Test not supported on this architecture");
return TEST_SKIP;
}
pr_debug("watchpoints count %d, breakpoints count %d, has_ioctl %d, share %d\n",
wp_cnt, bp_cnt, has_ioctl, share);
@@ -189,18 +207,4 @@ int test__bp_accounting(struct test *test __maybe_unused, int subtest __maybe_un
return bp_accounting(wp_cnt, share);
}
bool test__bp_account_is_supported(void)
{
/*
* PowerPC and S390 do not support creation of instruction
* breakpoints using the perf_event interface.
*
* Just disable the test for these architectures until these
* issues are resolved.
*/
#if defined(__powerpc__) || defined(__s390x__)
return false;
#else
return true;
#endif
}
DEFINE_SUITE("Breakpoint accounting", bp_accounting);

View File

@@ -161,11 +161,16 @@ static long long bp_count(int fd)
return count;
}
int test__bp_signal(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__bp_signal(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct sigaction sa;
long long count1, count2, count3;
if (!BP_SIGNAL_IS_SUPPORTED) {
pr_debug("Test not supported on this architecture");
return TEST_SKIP;
}
/* setup SIGIO signal handler */
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_sigaction = (void *) sig_handler;
@@ -285,29 +290,4 @@ int test__bp_signal(struct test *test __maybe_unused, int subtest __maybe_unused
TEST_OK : TEST_FAIL;
}
bool test__bp_signal_is_supported(void)
{
/*
* PowerPC and S390 do not support creation of instruction
* breakpoints using the perf_event interface.
*
* ARM requires explicit rounding down of the instruction
* pointer in Thumb mode, and then requires the single-step
* to be handled explicitly in the overflow handler to avoid
* stepping into the SIGIO handler and getting stuck on the
* breakpointed instruction.
*
* Since arm64 has the same issue with arm for the single-step
* handling, this case also gets stuck on the breakpointed
* instruction.
*
* Just disable the test for these architectures until these
* issues are resolved.
*/
#if defined(__powerpc__) || defined(__s390x__) || defined(__arm__) || \
defined(__aarch64__)
return false;
#else
return true;
#endif
}
DEFINE_SUITE("Breakpoint overflow signal handler", bp_signal);

View File

@@ -59,13 +59,18 @@ static long long bp_count(int fd)
#define EXECUTIONS 10000
#define THRESHOLD 100
int test__bp_signal_overflow(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__bp_signal_overflow(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct perf_event_attr pe;
struct sigaction sa;
long long count;
int fd, i, fails = 0;
if (!BP_SIGNAL_IS_SUPPORTED) {
pr_debug("Test not supported on this architecture");
return TEST_SKIP;
}
/* setup SIGIO signal handler */
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_sigaction = (void *) sig_handler;
@@ -133,3 +138,5 @@ int test__bp_signal_overflow(struct test *test __maybe_unused, int subtest __may
return fails ? TEST_FAIL : TEST_OK;
}
DEFINE_SUITE("Breakpoint overflow sampling", bp_signal_overflow);

View File

@@ -62,7 +62,6 @@ static int llseek_loop(void)
static struct {
enum test_llvm__testcase prog_id;
const char *desc;
const char *name;
const char *msg_compile_fail;
const char *msg_load_fail;
@@ -72,7 +71,6 @@ static struct {
} bpf_testcase_table[] = {
{
.prog_id = LLVM_TESTCASE_BASE,
.desc = "Basic BPF filtering",
.name = "[basic_bpf_test]",
.msg_compile_fail = "fix 'perf test LLVM' first",
.msg_load_fail = "load bpf object failed",
@@ -81,7 +79,6 @@ static struct {
},
{
.prog_id = LLVM_TESTCASE_BASE,
.desc = "BPF pinning",
.name = "[bpf_pinning]",
.msg_compile_fail = "fix kbuild first",
.msg_load_fail = "check your vmlinux setting?",
@@ -92,7 +89,6 @@ static struct {
#ifdef HAVE_BPF_PROLOGUE
{
.prog_id = LLVM_TESTCASE_BPF_PROLOGUE,
.desc = "BPF prologue generation",
.name = "[bpf_prologue_test]",
.msg_compile_fail = "fix kbuild first",
.msg_load_fail = "check your vmlinux setting?",
@@ -283,18 +279,6 @@ out:
return ret;
}
int test__bpf_subtest_get_nr(void)
{
return (int)ARRAY_SIZE(bpf_testcase_table);
}
const char *test__bpf_subtest_get_desc(int i)
{
if (i < 0 || i >= (int)ARRAY_SIZE(bpf_testcase_table))
return NULL;
return bpf_testcase_table[i].desc;
}
static int check_env(void)
{
int err;
@@ -313,7 +297,7 @@ static int check_env(void)
}
err = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns,
sizeof(insns) / sizeof(insns[0]),
ARRAY_SIZE(insns),
license, kver_int, NULL, 0);
if (err < 0) {
pr_err("Missing basic BPF support, skip this test: %s\n",
@@ -325,7 +309,7 @@ static int check_env(void)
return 0;
}
int test__bpf(struct test *test __maybe_unused, int i)
static int test__bpf(int i)
{
int err;
@@ -343,21 +327,60 @@ int test__bpf(struct test *test __maybe_unused, int i)
err = __test__bpf(i);
return err;
}
#endif
static int test__basic_bpf_test(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
#ifdef HAVE_LIBBPF_SUPPORT
return test__bpf(0);
#else
int test__bpf_subtest_get_nr(void)
{
return 0;
}
const char *test__bpf_subtest_get_desc(int i __maybe_unused)
{
return NULL;
}
int test__bpf(struct test *test __maybe_unused, int i __maybe_unused)
{
pr_debug("Skip BPF test because BPF support is not compiled\n");
return TEST_SKIP;
}
#endif
}
static int test__bpf_pinning(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
#ifdef HAVE_LIBBPF_SUPPORT
return test__bpf(1);
#else
pr_debug("Skip BPF test because BPF support is not compiled\n");
return TEST_SKIP;
#endif
}
static int test__bpf_prologue_test(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
#if defined(HAVE_LIBBPF_SUPPORT) && defined(HAVE_BPF_PROLOGUE)
return test__bpf(2);
#else
pr_debug("Skip BPF test because BPF support is not compiled\n");
return TEST_SKIP;
#endif
}
static struct test_case bpf_tests[] = {
#ifdef HAVE_LIBBPF_SUPPORT
TEST_CASE("Basic BPF filtering", basic_bpf_test),
TEST_CASE("BPF pinning", bpf_pinning),
#ifdef HAVE_BPF_PROLOGUE
TEST_CASE("BPF prologue generation", bpf_prologue_test),
#else
TEST_CASE_REASON("BPF prologue generation", bpf_prologue_test, "not compiled in"),
#endif
#else
TEST_CASE_REASON("Basic BPF filtering", basic_bpf_test, "not compiled in"),
TEST_CASE_REASON("BPF pinning", bpf_pinning, "not compiled in"),
TEST_CASE_REASON("BPF prologue generation", bpf_prologue_test, "not compiled in"),
#endif
{ .name = NULL, }
};
struct test_suite suite__bpf = {
.desc = "BPF filter",
.test_cases = bpf_tests,
};

View File

@@ -30,350 +30,134 @@
static bool dont_fork;
struct test __weak arch_tests[] = {
{
.func = NULL,
},
struct test_suite *__weak arch_tests[] = {
NULL,
};
static struct test generic_tests[] = {
{
.desc = "vmlinux symtab matches kallsyms",
.func = test__vmlinux_matches_kallsyms,
},
{
.desc = "Detect openat syscall event",
.func = test__openat_syscall_event,
},
{
.desc = "Detect openat syscall event on all cpus",
.func = test__openat_syscall_event_on_all_cpus,
},
{
.desc = "Read samples using the mmap interface",
.func = test__basic_mmap,
},
{
.desc = "Test data source output",
.func = test__mem,
},
{
.desc = "Parse event definition strings",
.func = test__parse_events,
},
{
.desc = "Simple expression parser",
.func = test__expr,
},
{
.desc = "PERF_RECORD_* events & perf_sample fields",
.func = test__PERF_RECORD,
},
{
.desc = "Parse perf pmu format",
.func = test__pmu,
},
{
.desc = "PMU events",
.func = test__pmu_events,
.subtest = {
.skip_if_fail = false,
.get_nr = test__pmu_events_subtest_get_nr,
.get_desc = test__pmu_events_subtest_get_desc,
.skip_reason = test__pmu_events_subtest_skip_reason,
},
},
{
.desc = "DSO data read",
.func = test__dso_data,
},
{
.desc = "DSO data cache",
.func = test__dso_data_cache,
},
{
.desc = "DSO data reopen",
.func = test__dso_data_reopen,
},
{
.desc = "Roundtrip evsel->name",
.func = test__perf_evsel__roundtrip_name_test,
},
{
.desc = "Parse sched tracepoints fields",
.func = test__perf_evsel__tp_sched_test,
},
{
.desc = "syscalls:sys_enter_openat event fields",
.func = test__syscall_openat_tp_fields,
},
{
.desc = "Setup struct perf_event_attr",
.func = test__attr,
},
{
.desc = "Match and link multiple hists",
.func = test__hists_link,
},
{
.desc = "'import perf' in python",
.func = test__python_use,
},
{
.desc = "Breakpoint overflow signal handler",
.func = test__bp_signal,
.is_supported = test__bp_signal_is_supported,
},
{
.desc = "Breakpoint overflow sampling",
.func = test__bp_signal_overflow,
.is_supported = test__bp_signal_is_supported,
},
{
.desc = "Breakpoint accounting",
.func = test__bp_accounting,
.is_supported = test__bp_account_is_supported,
},
{
.desc = "Watchpoint",
.func = test__wp,
.is_supported = test__wp_is_supported,
.subtest = {
.skip_if_fail = false,
.get_nr = test__wp_subtest_get_nr,
.get_desc = test__wp_subtest_get_desc,
.skip_reason = test__wp_subtest_skip_reason,
},
},
{
.desc = "Number of exit events of a simple workload",
.func = test__task_exit,
},
{
.desc = "Software clock events period values",
.func = test__sw_clock_freq,
},
{
.desc = "Object code reading",
.func = test__code_reading,
},
{
.desc = "Sample parsing",
.func = test__sample_parsing,
},
{
.desc = "Use a dummy software event to keep tracking",
.func = test__keep_tracking,
},
{
.desc = "Parse with no sample_id_all bit set",
.func = test__parse_no_sample_id_all,
},
{
.desc = "Filter hist entries",
.func = test__hists_filter,
},
{
.desc = "Lookup mmap thread",
.func = test__mmap_thread_lookup,
},
{
.desc = "Share thread maps",
.func = test__thread_maps_share,
},
{
.desc = "Sort output of hist entries",
.func = test__hists_output,
},
{
.desc = "Cumulate child hist entries",
.func = test__hists_cumulate,
},
{
.desc = "Track with sched_switch",
.func = test__switch_tracking,
},
{
.desc = "Filter fds with revents mask in a fdarray",
.func = test__fdarray__filter,
},
{
.desc = "Add fd to a fdarray, making it autogrow",
.func = test__fdarray__add,
},
{
.desc = "kmod_path__parse",
.func = test__kmod_path__parse,
},
{
.desc = "Thread map",
.func = test__thread_map,
},
{
.desc = "LLVM search and compile",
.func = test__llvm,
.subtest = {
.skip_if_fail = true,
.get_nr = test__llvm_subtest_get_nr,
.get_desc = test__llvm_subtest_get_desc,
},
},
{
.desc = "Session topology",
.func = test__session_topology,
},
{
.desc = "BPF filter",
.func = test__bpf,
.subtest = {
.skip_if_fail = true,
.get_nr = test__bpf_subtest_get_nr,
.get_desc = test__bpf_subtest_get_desc,
},
},
{
.desc = "Synthesize thread map",
.func = test__thread_map_synthesize,
},
{
.desc = "Remove thread map",
.func = test__thread_map_remove,
},
{
.desc = "Synthesize cpu map",
.func = test__cpu_map_synthesize,
},
{
.desc = "Synthesize stat config",
.func = test__synthesize_stat_config,
},
{
.desc = "Synthesize stat",
.func = test__synthesize_stat,
},
{
.desc = "Synthesize stat round",
.func = test__synthesize_stat_round,
},
{
.desc = "Synthesize attr update",
.func = test__event_update,
},
{
.desc = "Event times",
.func = test__event_times,
},
{
.desc = "Read backward ring buffer",
.func = test__backward_ring_buffer,
},
{
.desc = "Print cpu map",
.func = test__cpu_map_print,
},
{
.desc = "Merge cpu map",
.func = test__cpu_map_merge,
},
{
.desc = "Probe SDT events",
.func = test__sdt_event,
},
{
.desc = "is_printable_array",
.func = test__is_printable_array,
},
{
.desc = "Print bitmap",
.func = test__bitmap_print,
},
{
.desc = "perf hooks",
.func = test__perf_hooks,
},
{
.desc = "builtin clang support",
.func = test__clang,
.subtest = {
.skip_if_fail = true,
.get_nr = test__clang_subtest_get_nr,
.get_desc = test__clang_subtest_get_desc,
}
},
{
.desc = "unit_number__scnprintf",
.func = test__unit_number__scnprint,
},
{
.desc = "mem2node",
.func = test__mem2node,
},
{
.desc = "time utils",
.func = test__time_utils,
},
{
.desc = "Test jit_write_elf",
.func = test__jit_write_elf,
},
{
.desc = "Test libpfm4 support",
.func = test__pfm,
.subtest = {
.skip_if_fail = true,
.get_nr = test__pfm_subtest_get_nr,
.get_desc = test__pfm_subtest_get_desc,
}
},
{
.desc = "Test api io",
.func = test__api_io,
},
{
.desc = "maps__merge_in",
.func = test__maps__merge_in,
},
{
.desc = "Demangle Java",
.func = test__demangle_java,
},
{
.desc = "Demangle OCaml",
.func = test__demangle_ocaml,
},
{
.desc = "Parse and process metrics",
.func = test__parse_metric,
},
{
.desc = "PE file support",
.func = test__pe_file_parsing,
},
{
.desc = "Event expansion for cgroups",
.func = test__expand_cgroup_events,
},
{
.desc = "Convert perf time to TSC",
.func = test__perf_time_to_tsc,
.is_supported = test__tsc_is_supported,
},
{
.desc = "dlfilter C API",
.func = test__dlfilter,
},
{
.func = NULL,
},
static struct test_suite *generic_tests[] = {
&suite__vmlinux_matches_kallsyms,
&suite__openat_syscall_event,
&suite__openat_syscall_event_on_all_cpus,
&suite__basic_mmap,
&suite__mem,
&suite__parse_events,
&suite__expr,
&suite__PERF_RECORD,
&suite__pmu,
&suite__pmu_events,
&suite__dso_data,
&suite__dso_data_cache,
&suite__dso_data_reopen,
&suite__perf_evsel__roundtrip_name_test,
&suite__perf_evsel__tp_sched_test,
&suite__syscall_openat_tp_fields,
&suite__attr,
&suite__hists_link,
&suite__python_use,
&suite__bp_signal,
&suite__bp_signal_overflow,
&suite__bp_accounting,
&suite__wp,
&suite__task_exit,
&suite__sw_clock_freq,
&suite__code_reading,
&suite__sample_parsing,
&suite__keep_tracking,
&suite__parse_no_sample_id_all,
&suite__hists_filter,
&suite__mmap_thread_lookup,
&suite__thread_maps_share,
&suite__hists_output,
&suite__hists_cumulate,
&suite__switch_tracking,
&suite__fdarray__filter,
&suite__fdarray__add,
&suite__kmod_path__parse,
&suite__thread_map,
&suite__llvm,
&suite__session_topology,
&suite__bpf,
&suite__thread_map_synthesize,
&suite__thread_map_remove,
&suite__cpu_map_synthesize,
&suite__synthesize_stat_config,
&suite__synthesize_stat,
&suite__synthesize_stat_round,
&suite__event_update,
&suite__event_times,
&suite__backward_ring_buffer,
&suite__cpu_map_print,
&suite__cpu_map_merge,
&suite__sdt_event,
&suite__is_printable_array,
&suite__bitmap_print,
&suite__perf_hooks,
&suite__clang,
&suite__unit_number__scnprint,
&suite__mem2node,
&suite__time_utils,
&suite__jit_write_elf,
&suite__pfm,
&suite__api_io,
&suite__maps__merge_in,
&suite__demangle_java,
&suite__demangle_ocaml,
&suite__parse_metric,
&suite__pe_file_parsing,
&suite__expand_cgroup_events,
&suite__perf_time_to_tsc,
&suite__dlfilter,
NULL,
};
static struct test *tests[] = {
static struct test_suite **tests[] = {
generic_tests,
arch_tests,
};
static int num_subtests(const struct test_suite *t)
{
int num;
if (!t->test_cases)
return 0;
num = 0;
while (t->test_cases[num].name)
num++;
return num;
}
static bool has_subtests(const struct test_suite *t)
{
return num_subtests(t) > 1;
}
static const char *skip_reason(const struct test_suite *t, int subtest)
{
if (t->test_cases && subtest >= 0)
return t->test_cases[subtest].skip_reason;
return NULL;
}
static const char *test_description(const struct test_suite *t, int subtest)
{
if (t->test_cases && subtest >= 0)
return t->test_cases[subtest].desc;
return t->desc;
}
static test_fnptr test_function(const struct test_suite *t, int subtest)
{
if (subtest <= 0)
return t->test_cases[0].run_case;
return t->test_cases[subtest].run_case;
}
static bool perf_test__matches(const char *desc, int curr, int argc, const char *argv[])
{
int i;
@@ -398,7 +182,7 @@ static bool perf_test__matches(const char *desc, int curr, int argc, const char
return false;
}
static int run_test(struct test *test, int subtest)
static int run_test(struct test_suite *test, int subtest)
{
int status, err = -1, child = dont_fork ? 0 : fork();
char sbuf[STRERR_BUFSIZE];
@@ -430,7 +214,7 @@ static int run_test(struct test *test, int subtest)
}
}
err = test->func(test, subtest);
err = test_function(test, subtest)(test, subtest);
if (!dont_fork)
exit(err);
}
@@ -450,24 +234,19 @@ static int run_test(struct test *test, int subtest)
return err;
}
#define for_each_test(j, t) \
#define for_each_test(j, k, t) \
for (j = 0; j < ARRAY_SIZE(tests); j++) \
for (t = &tests[j][0]; t->func; t++)
for (k = 0, t = tests[j][k]; tests[j][k]; k++, t = tests[j][k])
static int test_and_print(struct test *t, bool force_skip, int subtest)
static int test_and_print(struct test_suite *t, int subtest)
{
int err;
if (!force_skip) {
pr_debug("\n--- start ---\n");
err = run_test(t, subtest);
pr_debug("---- end ----\n");
} else {
pr_debug("\n--- force skipped ---\n");
err = TEST_SKIP;
}
pr_debug("\n--- start ---\n");
err = run_test(t, subtest);
pr_debug("---- end ----\n");
if (!t->subtest.get_nr)
if (!has_subtests(t))
pr_debug("%s:", t->desc);
else
pr_debug("%s subtest %d:", t->desc, subtest + 1);
@@ -477,11 +256,10 @@ static int test_and_print(struct test *t, bool force_skip, int subtest)
pr_info(" Ok\n");
break;
case TEST_SKIP: {
const char *skip_reason = NULL;
if (t->subtest.skip_reason)
skip_reason = t->subtest.skip_reason(subtest);
if (skip_reason)
color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (%s)\n", skip_reason);
const char *reason = skip_reason(t, subtest);
if (reason)
color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (%s)\n", reason);
else
color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip\n");
}
@@ -580,7 +358,7 @@ struct shell_test {
const char *file;
};
static int shell_test__run(struct test *test, int subdir __maybe_unused)
static int shell_test__run(struct test_suite *test, int subdir __maybe_unused)
{
int err;
char script[PATH_MAX];
@@ -622,24 +400,34 @@ static int run_shell_tests(int argc, const char *argv[], int i, int width,
for_each_shell_test(entlist, n_dirs, st.dir, ent) {
int curr = i++;
char desc[256];
struct test test = {
.desc = shell_test__description(desc, sizeof(desc), st.dir, ent->d_name),
.func = shell_test__run,
struct test_case test_cases[] = {
{
.desc = shell_test__description(desc,
sizeof(desc),
st.dir,
ent->d_name),
.run_case = shell_test__run,
},
{ .name = NULL, }
};
struct test_suite test_suite = {
.desc = test_cases[0].desc,
.test_cases = test_cases,
.priv = &st,
};
if (!perf_test__matches(test.desc, curr, argc, argv))
if (!perf_test__matches(test_suite.desc, curr, argc, argv))
continue;
st.file = ent->d_name;
pr_info("%2d: %-*s:", i, width, test.desc);
pr_info("%2d: %-*s:", i, width, test_suite.desc);
if (intlist__find(skiplist, i)) {
color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
continue;
}
test_and_print(&test, false, -1);
test_and_print(&test_suite, 0);
}
for (e = 0; e < n_dirs; e++)
@@ -650,33 +438,31 @@ static int run_shell_tests(int argc, const char *argv[], int i, int width,
static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
{
struct test *t;
unsigned int j;
struct test_suite *t;
unsigned int j, k;
int i = 0;
int width = shell_tests__max_desc_width();
for_each_test(j, t) {
int len = strlen(t->desc);
for_each_test(j, k, t) {
int len = strlen(test_description(t, -1));
if (width < len)
width = len;
}
for_each_test(j, t) {
int curr = i++, err;
for_each_test(j, k, t) {
int curr = i++;
int subi;
if (!perf_test__matches(t->desc, curr, argc, argv)) {
if (!perf_test__matches(test_description(t, -1), curr, argc, argv)) {
bool skip = true;
int subn;
if (!t->subtest.get_nr)
continue;
subn = t->subtest.get_nr();
subn = num_subtests(t);
for (subi = 0; subi < subn; subi++) {
if (perf_test__matches(t->subtest.get_desc(subi), curr, argc, argv))
if (perf_test__matches(test_description(t, subi),
curr, argc, argv))
skip = false;
}
@@ -684,22 +470,17 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
continue;
}
if (t->is_supported && !t->is_supported()) {
pr_debug("%2d: %-*s: Disabled\n", i, width, t->desc);
continue;
}
pr_info("%2d: %-*s:", i, width, t->desc);
pr_info("%2d: %-*s:", i, width, test_description(t, -1));
if (intlist__find(skiplist, i)) {
color_fprintf(stderr, PERF_COLOR_YELLOW, " Skip (user override)\n");
continue;
}
if (!t->subtest.get_nr) {
test_and_print(t, false, -1);
if (!has_subtests(t)) {
test_and_print(t, -1);
} else {
int subn = t->subtest.get_nr();
int subn = num_subtests(t);
/*
* minus 2 to align with normal testcases.
* For subtest we print additional '.x' in number.
@@ -709,7 +490,6 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
* 35.1: Basic BPF llvm compiling test : Ok
*/
int subw = width > 2 ? width - 2 : width;
bool skip = false;
if (subn <= 0) {
color_fprintf(stderr, PERF_COLOR_YELLOW,
@@ -719,21 +499,20 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
pr_info("\n");
for (subi = 0; subi < subn; subi++) {
int len = strlen(t->subtest.get_desc(subi));
int len = strlen(test_description(t, subi));
if (subw < len)
subw = len;
}
for (subi = 0; subi < subn; subi++) {
if (!perf_test__matches(t->subtest.get_desc(subi), curr, argc, argv))
if (!perf_test__matches(test_description(t, subi),
curr, argc, argv))
continue;
pr_info("%2d.%1d: %-*s:", i, subi + 1, subw,
t->subtest.get_desc(subi));
err = test_and_print(t, skip, subi);
if (err != TEST_OK && t->subtest.skip_if_fail)
skip = true;
test_description(t, subi));
test_and_print(t, subi);
}
}
}
@@ -759,7 +538,7 @@ static int perf_test__list_shell(int argc, const char **argv, int i)
for_each_shell_test(entlist, n_dirs, path, ent) {
int curr = i++;
char bf[256];
struct test t = {
struct test_suite t = {
.desc = shell_test__description(bf, sizeof(bf), path, ent->d_name),
};
@@ -778,26 +557,25 @@ static int perf_test__list_shell(int argc, const char **argv, int i)
static int perf_test__list(int argc, const char **argv)
{
unsigned int j;
struct test *t;
unsigned int j, k;
struct test_suite *t;
int i = 0;
for_each_test(j, t) {
for_each_test(j, k, t) {
int curr = i++;
if (!perf_test__matches(t->desc, curr, argc, argv) ||
(t->is_supported && !t->is_supported()))
if (!perf_test__matches(test_description(t, -1), curr, argc, argv))
continue;
pr_info("%2d: %s\n", i, t->desc);
pr_info("%2d: %s\n", i, test_description(t, -1));
if (t->subtest.get_nr) {
int subn = t->subtest.get_nr();
if (has_subtests(t)) {
int subn = num_subtests(t);
int subi;
for (subi = 0; subi < subn; subi++)
pr_info("%2d:%1d: %s\n", i, subi + 1,
t->subtest.get_desc(subi));
test_description(t, subi));
}
}

View File

@@ -3,44 +3,30 @@
#include "c++/clang-c.h"
#include <linux/kernel.h>
static struct {
int (*func)(void);
const char *desc;
} clang_testcase_table[] = {
#ifdef HAVE_LIBCLANGLLVM_SUPPORT
{
.func = test__clang_to_IR,
.desc = "builtin clang compile C source to IR",
},
{
.func = test__clang_to_obj,
.desc = "builtin clang compile C source to ELF object",
},
#endif
};
int test__clang_subtest_get_nr(void)
{
return (int)ARRAY_SIZE(clang_testcase_table);
}
const char *test__clang_subtest_get_desc(int i)
{
if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
return NULL;
return clang_testcase_table[i].desc;
}
#ifndef HAVE_LIBCLANGLLVM_SUPPORT
int test__clang(struct test *test __maybe_unused, int i __maybe_unused)
static int test__clang_to_IR(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
return TEST_SKIP;
}
#else
int test__clang(struct test *test __maybe_unused, int i)
static int test__clang_to_obj(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
if (i < 0 || i >= (int)ARRAY_SIZE(clang_testcase_table))
return TEST_FAIL;
return clang_testcase_table[i].func();
return TEST_SKIP;
}
#endif
static struct test_case clang_tests[] = {
TEST_CASE_REASON("builtin clang compile C source to IR", clang_to_IR,
"not compiled in"),
TEST_CASE_REASON("builtin clang compile C source to ELF object",
clang_to_obj,
"not compiled in"),
{ .name = NULL, }
};
struct test_suite suite__clang = {
.desc = "builtin clang support",
.test_cases = clang_tests,
};

View File

@@ -716,7 +716,7 @@ out_err:
return err;
}
int test__code_reading(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__code_reading(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int ret;
@@ -743,3 +743,5 @@ int test__code_reading(struct test *test __maybe_unused, int subtest __maybe_unu
return -1;
};
}
DEFINE_SUITE("Object code reading", code_reading);

View File

@@ -75,7 +75,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
}
int test__cpu_map_synthesize(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__cpu_map_synthesize(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct perf_cpu_map *cpus;
@@ -111,7 +111,7 @@ static int cpu_map_print(const char *str)
return !strcmp(buf, str);
}
int test__cpu_map_print(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__cpu_map_print(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1"));
TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1,5"));
@@ -123,7 +123,7 @@ int test__cpu_map_print(struct test *test __maybe_unused, int subtest __maybe_un
return 0;
}
int test__cpu_map_merge(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__cpu_map_merge(struct test_suite *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");
@@ -137,3 +137,7 @@ int test__cpu_map_merge(struct test *test __maybe_unused, int subtest __maybe_un
perf_cpu_map__put(c);
return 0;
}
DEFINE_SUITE("Synthesize cpu map", cpu_map_synthesize);
DEFINE_SUITE("Print cpu map", cpu_map_print);
DEFINE_SUITE("Merge cpu map", cpu_map_merge);

View File

@@ -7,7 +7,7 @@
#include "debug.h"
#include "demangle-java.h"
int test__demangle_java(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__demangle_java(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int ret = TEST_OK;
char *buf = NULL;
@@ -40,3 +40,5 @@ int test__demangle_java(struct test *test __maybe_unused, int subtest __maybe_un
return ret;
}
DEFINE_SUITE("Demangle Java", demangle_java);

View File

@@ -7,7 +7,7 @@
#include "debug.h"
#include "demangle-ocaml.h"
int test__demangle_ocaml(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__demangle_ocaml(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int ret = TEST_OK;
char *buf = NULL;
@@ -41,3 +41,5 @@ int test__demangle_ocaml(struct test *test __maybe_unused, int subtest __maybe_u
return ret;
}
DEFINE_SUITE("Demangle OCaml", demangle_ocaml);

View File

@@ -398,7 +398,7 @@ static void test_data__free(struct test_data *td)
}
}
int test__dlfilter(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__dlfilter(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct test_data td = {.fd = -1};
int pid = getpid();
@@ -414,3 +414,5 @@ int test__dlfilter(struct test *test __maybe_unused, int subtest __maybe_unused)
test_data__free(&td);
return err;
}
DEFINE_SUITE("dlfilter C API", dlfilter);

View File

@@ -113,7 +113,7 @@ static int dso__data_fd(struct dso *dso, struct machine *machine)
return fd;
}
int test__dso_data(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__dso_data(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct machine machine;
struct dso *dso;
@@ -248,7 +248,7 @@ static int set_fd_limit(int n)
return setrlimit(RLIMIT_NOFILE, &rlim);
}
int test__dso_data_cache(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__dso_data_cache(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct machine machine;
long nr_end, nr = open_files_cnt();
@@ -318,7 +318,7 @@ static long new_limit(int count)
return ret;
}
int test__dso_data_reopen(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__dso_data_reopen(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct machine machine;
long nr_end, nr = open_files_cnt(), lim = new_limit(3);
@@ -393,3 +393,7 @@ int test__dso_data_reopen(struct test *test __maybe_unused, int subtest __maybe_
TEST_ASSERT_VAL("failed leaking files", nr == nr_end);
return 0;
}
DEFINE_SUITE("DSO data read", dso_data);
DEFINE_SUITE("DSO data cache", dso_data_cache);
DEFINE_SUITE("DSO data reopen", dso_data_reopen);

View File

@@ -195,7 +195,8 @@ NO_TAIL_CALL_ATTRIBUTE noinline int test_dwarf_unwind__krava_1(struct thread *th
return ret;
}
int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__dwarf_unwind(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
struct machine *machine;
struct thread *thread;
@@ -237,3 +238,5 @@ int test__dwarf_unwind(struct test *test __maybe_unused, int subtest __maybe_unu
machine__delete(machine);
return err;
}
DEFINE_SUITE("Test dwarf unwind", dwarf_unwind);

View File

@@ -216,7 +216,7 @@ out_err:
* and checks that enabled and running times
* match.
*/
int test__event_times(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__event_times(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int err, ret = 0;
@@ -239,3 +239,5 @@ int test__event_times(struct test *test __maybe_unused, int subtest __maybe_unus
#undef _T
return ret;
}
DEFINE_SUITE("Event times", event_times);

View File

@@ -83,7 +83,7 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
return 0;
}
int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__event_update(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct evsel *evsel;
struct event_name tmp;
@@ -123,3 +123,5 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu
evlist__delete(evlist);
return 0;
}
DEFINE_SUITE("Synthesize attr update", event_update);

View File

@@ -99,7 +99,8 @@ out_delete_evlist:
#define perf_evsel__name_array_test(names, distance) \
__perf_evsel__name_array_test(names, ARRAY_SIZE(names), distance)
int test__perf_evsel__roundtrip_name_test(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__perf_evsel__roundtrip_name_test(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
int err = 0, ret = 0;
@@ -120,3 +121,5 @@ int test__perf_evsel__roundtrip_name_test(struct test *test __maybe_unused, int
return ret;
}
DEFINE_SUITE("Roundtrip evsel->name", perf_evsel__roundtrip_name_test);

View File

@@ -32,7 +32,8 @@ static int evsel__test_field(struct evsel *evsel, const char *name, int size, bo
return ret;
}
int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__perf_evsel__tp_sched_test(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
struct evsel *evsel = evsel__newtp("sched", "sched_switch");
int ret = 0;
@@ -87,3 +88,5 @@ int test__perf_evsel__tp_sched_test(struct test *test __maybe_unused, int subtes
evsel__delete(evsel);
return ret;
}
DEFINE_SUITE("Parse sched tracepoints fields", perf_evsel__tp_sched_test);

View File

@@ -221,8 +221,8 @@ out:
return ret;
}
int test__expand_cgroup_events(struct test *test __maybe_unused,
int subtest __maybe_unused)
static int test__expand_cgroup_events(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
int ret;
@@ -240,3 +240,5 @@ int test__expand_cgroup_events(struct test *test __maybe_unused,
return ret;
}
DEFINE_SUITE("Event expansion for cgroups", expand_cgroup_events);

View File

@@ -62,11 +62,11 @@ static int test(struct expr_parse_ctx *ctx, const char *e, double val2)
return 0;
}
int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused)
static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_unused)
{
struct expr_id_data *val_ptr;
const char *p;
double val;
double val, num_cpus, num_cores, num_dies, num_packages;
int ret;
struct expr_parse_ctx *ctx;
@@ -134,6 +134,16 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused)
TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, "EVENT2,param=3@",
(void **)&val_ptr));
expr__ctx_clear(ctx);
TEST_ASSERT_VAL("find ids",
expr__find_ids("dash\\-event1 - dash\\-event2",
NULL, ctx) == 0);
TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 2);
TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, "dash-event1",
(void **)&val_ptr));
TEST_ASSERT_VAL("find ids", hashmap__find(ctx->ids, "dash-event2",
(void **)&val_ptr));
/* Only EVENT1 or EVENT2 need be measured depending on the value of smt_on. */
expr__ctx_clear(ctx);
TEST_ASSERT_VAL("find ids",
@@ -151,7 +161,31 @@ int test__expr(struct test *t __maybe_unused, int subtest __maybe_unused)
NULL, ctx) == 0);
TEST_ASSERT_VAL("find ids", hashmap__size(ctx->ids) == 0);
/* Test toplogy constants appear well ordered. */
expr__ctx_clear(ctx);
TEST_ASSERT_VAL("#num_cpus", expr__parse(&num_cpus, ctx, "#num_cpus") == 0);
TEST_ASSERT_VAL("#num_cores", expr__parse(&num_cores, ctx, "#num_cores") == 0);
TEST_ASSERT_VAL("#num_cpus >= #num_cores", num_cpus >= num_cores);
TEST_ASSERT_VAL("#num_dies", expr__parse(&num_dies, ctx, "#num_dies") == 0);
TEST_ASSERT_VAL("#num_cores >= #num_dies", num_cores >= num_dies);
TEST_ASSERT_VAL("#num_packages", expr__parse(&num_packages, ctx, "#num_packages") == 0);
TEST_ASSERT_VAL("#num_dies >= #num_packages", num_dies >= num_packages);
/*
* Source count returns the number of events aggregating in a leader
* event including the leader. Check parsing yields an id.
*/
expr__ctx_clear(ctx);
TEST_ASSERT_VAL("source count",
expr__find_ids("source_count(EVENT1)",
NULL, ctx) == 0);
TEST_ASSERT_VAL("source count", hashmap__size(ctx->ids) == 1);
TEST_ASSERT_VAL("source count", hashmap__find(ctx->ids, "EVENT1",
(void **)&val_ptr));
expr__ctx_free(ctx);
return 0;
}
DEFINE_SUITE("Simple expression parser", expr);

View File

@@ -28,7 +28,7 @@ static int fdarray__fprintf_prefix(struct fdarray *fda, const char *prefix, FILE
return printed + fdarray__fprintf(fda, fp);
}
int test__fdarray__filter(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__fdarray__filter(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int nr_fds, err = TEST_FAIL;
struct fdarray *fda = fdarray__new(5, 5);
@@ -89,7 +89,7 @@ out:
return err;
}
int test__fdarray__add(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__fdarray__add(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int err = TEST_FAIL;
struct fdarray *fda = fdarray__new(2, 2);
@@ -158,3 +158,6 @@ out_delete:
out:
return err;
}
DEFINE_SUITE("Filter fds with revents mask in a fdarray", fdarray__filter);
DEFINE_SUITE("Add fd to a fdarray, making it autogrow", fdarray__add);

View File

@@ -16,8 +16,8 @@
#define TEMPL "/tmp/perf-test-XXXXXX"
int test__jit_write_elf(struct test *test __maybe_unused,
int subtest __maybe_unused)
static int test__jit_write_elf(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
#ifdef HAVE_JITDUMP
static unsigned char x86_code[] = {
@@ -49,3 +49,5 @@ int test__jit_write_elf(struct test *test __maybe_unused,
return TEST_SKIP;
#endif
}
DEFINE_SUITE("Test jit_write_elf", jit_write_elf);

View File

@@ -689,7 +689,7 @@ out:
return err;
}
int test__hists_cumulate(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__hists_cumulate(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int err = TEST_FAIL;
struct machines machines;
@@ -736,3 +736,5 @@ out:
return err;
}
DEFINE_SUITE("Cumulate child hist entries", hists_cumulate);

View File

@@ -101,7 +101,7 @@ out:
return TEST_FAIL;
}
int test__hists_filter(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__hists_filter(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int err = TEST_FAIL;
struct machines machines;
@@ -325,3 +325,5 @@ out:
return err;
}
DEFINE_SUITE("Filter hist entries", hists_filter);

View File

@@ -264,7 +264,7 @@ static int validate_link(struct hists *leader, struct hists *other)
return __validate_link(leader, 0) || __validate_link(other, 1);
}
int test__hists_link(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__hists_link(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int err = -1;
struct hists *hists, *first_hists;
@@ -339,3 +339,5 @@ out:
return err;
}
DEFINE_SUITE("Match and link multiple hists", hists_link);

View File

@@ -575,7 +575,7 @@ out:
return err;
}
int test__hists_output(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__hists_output(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int err = TEST_FAIL;
struct machines machines;
@@ -623,3 +623,5 @@ out:
return err;
}
DEFINE_SUITE("Sort output of hist entries", hists_output);

View File

@@ -5,7 +5,7 @@
#include "debug.h"
#include "print_binary.h"
int test__is_printable_array(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__is_printable_array(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
char buf1[] = { 'k', 'r', 4, 'v', 'a', 0 };
char buf2[] = { 'k', 'r', 'a', 'v', 4, 0 };
@@ -36,3 +36,5 @@ int test__is_printable_array(struct test *test __maybe_unused, int subtest __may
return TEST_OK;
}
DEFINE_SUITE("is_printable_array", is_printable_array);

View File

@@ -61,7 +61,7 @@ static int find_comm(struct evlist *evlist, const char *comm)
* when an event is disabled but a dummy software event is not disabled. If the
* test passes %0 is returned, otherwise %-1 is returned.
*/
int test__keep_tracking(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__keep_tracking(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct record_opts opts = {
.mmap_pages = UINT_MAX,
@@ -160,3 +160,5 @@ out_err:
return err;
}
DEFINE_SUITE("Use a dummy software event to keep tracking", keep_tracking);

View File

@@ -47,7 +47,7 @@ static int test_is_kernel_module(const char *path, int cpumode, bool expect)
#define M(path, c, e) \
TEST_ASSERT_VAL("failed", !test_is_kernel_module(path, c, e))
int test__kmod_path__parse(struct test *t __maybe_unused, int subtest __maybe_unused)
static int test__kmod_path__parse(struct test_suite *t __maybe_unused, int subtest __maybe_unused)
{
/* path alloc_name kmod comp name */
T("/xxxx/xxxx/x-x.ko", true , true, 0 , "[x_x]");
@@ -159,3 +159,5 @@ int test__kmod_path__parse(struct test *t __maybe_unused, int subtest __maybe_un
return 0;
}
DEFINE_SUITE("kmod_path__parse", kmod_path__parse);

View File

@@ -124,7 +124,7 @@ out:
return ret;
}
int test__llvm(struct test *test __maybe_unused, int subtest)
static int test__llvm(int subtest)
{
int ret;
void *obj_buf = NULL;
@@ -148,32 +148,72 @@ int test__llvm(struct test *test __maybe_unused, int subtest)
return ret;
}
#endif //HAVE_LIBBPF_SUPPORT
int test__llvm_subtest_get_nr(void)
{
return __LLVM_TESTCASE_MAX;
}
const char *test__llvm_subtest_get_desc(int subtest)
{
if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
return NULL;
return bpf_source_table[subtest].desc;
}
#else //HAVE_LIBBPF_SUPPORT
int test__llvm(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__llvm__bpf_base_prog(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
#ifdef HAVE_LIBBPF_SUPPORT
return test__llvm(LLVM_TESTCASE_BASE);
#else
pr_debug("Skip LLVM test because BPF support is not compiled\n");
return TEST_SKIP;
#endif
}
int test__llvm_subtest_get_nr(void)
static int test__llvm__bpf_test_kbuild_prog(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
return 0;
#ifdef HAVE_LIBBPF_SUPPORT
return test__llvm(LLVM_TESTCASE_KBUILD);
#else
pr_debug("Skip LLVM test because BPF support is not compiled\n");
return TEST_SKIP;
#endif
}
const char *test__llvm_subtest_get_desc(int subtest __maybe_unused)
static int test__llvm__bpf_test_prologue_prog(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
return NULL;
#ifdef HAVE_LIBBPF_SUPPORT
return test__llvm(LLVM_TESTCASE_BPF_PROLOGUE);
#else
pr_debug("Skip LLVM test because BPF support is not compiled\n");
return TEST_SKIP;
#endif
}
#endif // HAVE_LIBBPF_SUPPORT
static int test__llvm__bpf_test_relocation(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
#ifdef HAVE_LIBBPF_SUPPORT
return test__llvm(LLVM_TESTCASE_BPF_RELOCATION);
#else
pr_debug("Skip LLVM test because BPF support is not compiled\n");
return TEST_SKIP;
#endif
}
static struct test_case llvm_tests[] = {
#ifdef HAVE_LIBBPF_SUPPORT
TEST_CASE("Basic BPF llvm compile", llvm__bpf_base_prog),
TEST_CASE("kbuild searching", llvm__bpf_test_kbuild_prog),
TEST_CASE("Compile source for BPF prologue generation",
llvm__bpf_test_prologue_prog),
TEST_CASE("Compile source for BPF relocation", llvm__bpf_test_relocation),
#else
TEST_CASE_REASON("Basic BPF llvm compile", llvm__bpf_base_prog, "not compiled in"),
TEST_CASE_REASON("kbuild searching", llvm__bpf_test_kbuild_prog, "not compiled in"),
TEST_CASE_REASON("Compile source for BPF prologue generation",
llvm__bpf_test_prologue_prog, "not compiled in"),
TEST_CASE_REASON("Compile source for BPF relocation",
llvm__bpf_test_relocation, "not compiled in"),
#endif
{ .name = NULL, }
};
struct test_suite suite__llvm = {
.desc = "LLVM search and compile",
.test_cases = llvm_tests,
};

View File

@@ -33,7 +33,7 @@ static int check_maps(struct map_def *merged, unsigned int size, struct maps *ma
return TEST_OK;
}
int test__maps__merge_in(struct test *t __maybe_unused, int subtest __maybe_unused)
static int test__maps__merge_in(struct test_suite *t __maybe_unused, int subtest __maybe_unused)
{
struct maps maps;
unsigned int i;
@@ -120,3 +120,5 @@ int test__maps__merge_in(struct test *t __maybe_unused, int subtest __maybe_unus
maps__exit(&maps);
return TEST_OK;
}
DEFINE_SUITE("maps__merge_in", maps__merge_in);

View File

@@ -23,7 +23,7 @@ static int check(union perf_mem_data_src data_src,
return 0;
}
int test__mem(struct test *text __maybe_unused, int subtest __maybe_unused)
static int test__mem(struct test_suite *text __maybe_unused, int subtest __maybe_unused)
{
int ret = 0;
union perf_mem_data_src src;
@@ -56,3 +56,5 @@ int test__mem(struct test *text __maybe_unused, int subtest __maybe_unused)
return ret;
}
DEFINE_SUITE("Test data source output", mem);

View File

@@ -43,7 +43,7 @@ static unsigned long *get_bitmap(const char *str, int nbits)
return bm && map ? bm : NULL;
}
int test__mem2node(struct test *t __maybe_unused, int subtest __maybe_unused)
static int test__mem2node(struct test_suite *t __maybe_unused, int subtest __maybe_unused)
{
struct mem2node map;
struct memory_node nodes[3];
@@ -77,3 +77,5 @@ int test__mem2node(struct test *t __maybe_unused, int subtest __maybe_unused)
mem2node__exit(&map);
return 0;
}
DEFINE_SUITE("mem2node", mem2node);

View File

@@ -29,7 +29,7 @@
* Then it checks if the number of syscalls reported as perf events by
* the kernel corresponds to the number of syscalls made.
*/
int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__basic_mmap(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int err = -1;
union perf_event *event;
@@ -164,3 +164,5 @@ out_free_threads:
perf_thread_map__put(threads);
return err;
}
DEFINE_SUITE("Read samples using the mmap interface", basic_mmap);

View File

@@ -224,7 +224,7 @@ static int mmap_events(synth_cb synth)
*
* by using all thread objects.
*/
int test__mmap_thread_lookup(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__mmap_thread_lookup(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
/* perf_event__synthesize_threads synthesize */
TEST_ASSERT_VAL("failed with sythesizing all",
@@ -236,3 +236,5 @@ int test__mmap_thread_lookup(struct test *test __maybe_unused, int subtest __may
return 0;
}
DEFINE_SUITE("Lookup mmap thread", mmap_thread_lookup);

View File

@@ -19,7 +19,8 @@
#include "stat.h"
#include "util/counts.h"
int test__openat_syscall_event_on_all_cpus(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__openat_syscall_event_on_all_cpus(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
int err = -1, fd, cpu;
struct perf_cpu_map *cpus;
@@ -127,3 +128,5 @@ out_thread_map_delete:
perf_thread_map__put(threads);
return err;
}
DEFINE_SUITE("Detect openat syscall event on all cpus", openat_syscall_event_on_all_cpus);

View File

@@ -22,7 +22,8 @@
#define AT_FDCWD -100
#endif
int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__syscall_openat_tp_fields(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
struct record_opts opts = {
.target = {
@@ -142,3 +143,5 @@ out_delete_evlist:
out:
return err;
}
DEFINE_SUITE("syscalls:sys_enter_openat event fields", syscall_openat_tp_fields);

View File

@@ -13,7 +13,8 @@
#include "tests.h"
#include "util/counts.h"
int test__openat_syscall_event(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__openat_syscall_event(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
int err = -1, fd;
struct evsel *evsel;
@@ -66,3 +67,5 @@ out_thread_map_delete:
perf_thread_map__put(threads);
return err;
}
DEFINE_SUITE("Detect openat syscall event", openat_syscall_event);

View File

@@ -2276,7 +2276,7 @@ static int test_pmu_events_alias(char *event, char *alias)
return test_event(&e);
}
int test__parse_events(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__parse_events(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int ret1, ret2 = 0;
char *event, *alias;
@@ -2319,3 +2319,5 @@ do { \
return ret2;
}
DEFINE_SUITE("Parse event definition strings", parse_events);

View File

@@ -369,7 +369,7 @@ static int test_metric_group(void)
return 0;
}
int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__parse_metric(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
TEST_ASSERT_VAL("IPC failed", test_ipc() == 0);
TEST_ASSERT_VAL("frontend failed", test_frontend() == 0);
@@ -383,3 +383,5 @@ int test__parse_metric(struct test *test __maybe_unused, int subtest __maybe_unu
}
return 0;
}
DEFINE_SUITE("Parse and process metrics", parse_metric);

View File

@@ -67,7 +67,8 @@ struct test_attr_event {
*
* Return: %0 on success, %-1 if the test fails.
*/
int test__parse_no_sample_id_all(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__parse_no_sample_id_all(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
int err;
@@ -103,3 +104,5 @@ int test__parse_no_sample_id_all(struct test *test __maybe_unused, int subtest _
return 0;
}
DEFINE_SUITE("Parse with no sample_id_all bit set", parse_no_sample_id_all);

View File

@@ -68,7 +68,7 @@ static int run_dir(const char *d)
return TEST_OK;
}
int test__pe_file_parsing(struct test *test __maybe_unused,
static int test__pe_file_parsing(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
struct stat st;
@@ -89,10 +89,12 @@ int test__pe_file_parsing(struct test *test __maybe_unused,
#else
int test__pe_file_parsing(struct test *test __maybe_unused,
static int test__pe_file_parsing(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
return TEST_SKIP;
}
#endif
DEFINE_SUITE("PE file support", pe_file_parsing);

View File

@@ -26,7 +26,7 @@ static void the_hook(void *_hook_flags)
raise(SIGSEGV);
}
int test__perf_hooks(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__perf_hooks(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
int hook_flags = 0;
@@ -45,3 +45,5 @@ int test__perf_hooks(struct test *test __maybe_unused, int subtest __maybe_unuse
return TEST_FAIL;
return TEST_OK;
}
DEFINE_SUITE("perf hooks", perf_hooks);

View File

@@ -41,7 +41,7 @@ realloc:
return cpu;
}
int test__PERF_RECORD(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__PERF_RECORD(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct record_opts opts = {
.target = {
@@ -332,3 +332,5 @@ out_delete_evlist:
out:
return (err < 0 || errs > 0) ? -1 : 0;
}
DEFINE_SUITE("PERF_RECORD_* events & perf_sample fields", PERF_RECORD);

View File

@@ -23,6 +23,16 @@
#include "pmu.h"
#include "pmu-hybrid.h"
/*
* Except x86_64/i386 and Arm64, other archs don't support TSC in perf. Just
* enable the test for x86_64/i386 and Arm64 archs.
*/
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__)
#define TSC_IS_SUPPORTED 1
#else
#define TSC_IS_SUPPORTED 0
#endif
#define CHECK__(x) { \
while ((x) < 0) { \
pr_debug(#x " failed!\n"); \
@@ -45,7 +55,7 @@
* %0 is returned, otherwise %-1 is returned. If TSC conversion is not
* supported then then the test passes but " (not supported)" is printed.
*/
int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__perf_time_to_tsc(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
struct record_opts opts = {
.mmap_pages = UINT_MAX,
@@ -69,6 +79,11 @@ int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe
u64 test_time, comm1_time = 0, comm2_time = 0;
struct mmap *md;
if (!TSC_IS_SUPPORTED) {
pr_debug("Test not supported on this architecture");
return TEST_SKIP;
}
threads = thread_map__new(-1, getpid(), UINT_MAX);
CHECK_NOT_NULL__(threads);
@@ -185,15 +200,4 @@ out_err:
return err;
}
bool test__tsc_is_supported(void)
{
/*
* Except x86_64/i386 and Arm64, other archs don't support TSC in perf.
* Just enable the test for x86_64/i386 and Arm64 archs.
*/
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__)
return true;
#else
return false;
#endif
}
DEFINE_SUITE("Convert perf time to TSC", perf_time_to_tsc);

View File

@@ -11,27 +11,6 @@
#include <linux/kernel.h>
#ifdef HAVE_LIBPFM
static int test__pfm_events(void);
static int test__pfm_group(void);
#endif
static const struct {
int (*func)(void);
const char *desc;
} pfm_testcase_table[] = {
#ifdef HAVE_LIBPFM
{
.func = test__pfm_events,
.desc = "test of individual --pfm-events",
},
{
.func = test__pfm_group,
.desc = "test groups of --pfm-events",
},
#endif
};
#ifdef HAVE_LIBPFM
static int count_pfm_events(struct perf_evlist *evlist)
{
@@ -44,7 +23,8 @@ static int count_pfm_events(struct perf_evlist *evlist)
return count;
}
static int test__pfm_events(void)
static int test__pfm_events(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
struct evlist *evlist;
struct option opt;
@@ -104,7 +84,8 @@ static int test__pfm_events(void)
return 0;
}
static int test__pfm_group(void)
static int test__pfm_group(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
struct evlist *evlist;
struct option opt;
@@ -187,27 +168,27 @@ static int test__pfm_group(void)
}
return 0;
}
#endif
const char *test__pfm_subtest_get_desc(int i)
{
if (i < 0 || i >= (int)ARRAY_SIZE(pfm_testcase_table))
return NULL;
return pfm_testcase_table[i].desc;
}
int test__pfm_subtest_get_nr(void)
{
return (int)ARRAY_SIZE(pfm_testcase_table);
}
int test__pfm(struct test *test __maybe_unused, int i __maybe_unused)
{
#ifdef HAVE_LIBPFM
if (i < 0 || i >= (int)ARRAY_SIZE(pfm_testcase_table))
return TEST_FAIL;
return pfm_testcase_table[i].func();
#else
static int test__pfm_events(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
return TEST_SKIP;
#endif
}
static int test__pfm_group(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
return TEST_SKIP;
}
#endif
static struct test_case pfm_tests[] = {
TEST_CASE_REASON("test of individual --pfm-events", pfm_events, "not compiled in"),
TEST_CASE_REASON("test groups of --pfm-events", pfm_group, "not compiled in"),
{ .name = NULL, }
};
struct test_suite suite__pfm = {
.desc = "Test libpfm4 support",
.test_cases = pfm_tests,
};

View File

@@ -418,7 +418,8 @@ static int compare_alias_to_test_event(struct perf_pmu_alias *alias,
}
/* Verify generated events from pmu-events.c are as expected */
static int test_pmu_event_table(void)
static int test__pmu_event_table(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
const struct pmu_event *sys_event_tables = __test_pmu_get_sys_events_table();
const struct pmu_events_map *map = __test_pmu_get_events_map();
@@ -705,7 +706,8 @@ static struct perf_pmu_test_pmu test_pmus[] = {
};
/* Test that aliases generated are as expected */
static int test_aliases(void)
static int test__aliases(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
struct perf_pmu *pmu = NULL;
unsigned long i;
@@ -892,7 +894,8 @@ out_err:
}
static int test_parsing(void)
static int test__parsing(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
const struct pmu_events_map *cpus_map = pmu_events_map__find();
const struct pmu_events_map *map;
@@ -1034,7 +1037,8 @@ out:
* or all defined cpus via the 'fake_pmu'
* in parse_events.
*/
static int test_parsing_fake(void)
static int test__parsing_fake(struct test_suite *test __maybe_unused,
int subtest __maybe_unused)
{
const struct pmu_events_map *map;
const struct pmu_event *pe;
@@ -1068,55 +1072,16 @@ static int test_parsing_fake(void)
return 0;
}
static const struct {
int (*func)(void);
const char *desc;
} pmu_events_testcase_table[] = {
{
.func = test_pmu_event_table,
.desc = "PMU event table sanity",
},
{
.func = test_aliases,
.desc = "PMU event map aliases",
},
{
.func = test_parsing,
.desc = "Parsing of PMU event table metrics",
},
{
.func = test_parsing_fake,
.desc = "Parsing of PMU event table metrics with fake PMUs",
},
static struct test_case pmu_events_tests[] = {
TEST_CASE("PMU event table sanity", pmu_event_table),
TEST_CASE("PMU event map aliases", aliases),
TEST_CASE_REASON("Parsing of PMU event table metrics", parsing,
"some metrics failed"),
TEST_CASE("Parsing of PMU event table metrics with fake PMUs", parsing_fake),
{ .name = NULL, }
};
const char *test__pmu_events_subtest_get_desc(int subtest)
{
if (subtest < 0 ||
subtest >= (int)ARRAY_SIZE(pmu_events_testcase_table))
return NULL;
return pmu_events_testcase_table[subtest].desc;
}
const char *test__pmu_events_subtest_skip_reason(int subtest)
{
if (subtest < 0 ||
subtest >= (int)ARRAY_SIZE(pmu_events_testcase_table))
return NULL;
if (pmu_events_testcase_table[subtest].func != test_parsing)
return NULL;
return "some metrics failed";
}
int test__pmu_events_subtest_get_nr(void)
{
return (int)ARRAY_SIZE(pmu_events_testcase_table);
}
int test__pmu_events(struct test *test __maybe_unused, int subtest)
{
if (subtest < 0 ||
subtest >= (int)ARRAY_SIZE(pmu_events_testcase_table))
return TEST_FAIL;
return pmu_events_testcase_table[subtest].func();
}
struct test_suite suite__pmu_events = {
.desc = "PMU events",
.test_cases = pmu_events_tests,
};

View File

@@ -137,7 +137,7 @@ static struct list_head *test_terms_list(void)
return &terms;
}
int test__pmu(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__pmu(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
char *format = test_format_dir_get();
LIST_HEAD(formats);
@@ -177,3 +177,5 @@ int test__pmu(struct test *test __maybe_unused, int subtest __maybe_unused)
test_format_dir_put(format);
return ret;
}
DEFINE_SUITE("Parse perf pmu format", pmu);

View File

@@ -9,7 +9,7 @@
#include "tests.h"
#include "util/debug.h"
int test__python_use(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__python_use(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
char *cmd;
int ret;
@@ -23,3 +23,5 @@ int test__python_use(struct test *test __maybe_unused, int subtest __maybe_unuse
free(cmd);
return ret;
}
DEFINE_SUITE("'import perf' in python", python_use);

View File

@@ -368,7 +368,7 @@ out_free:
* checks sample format bits separately and together. If the test passes %0 is
* returned, otherwise %-1 is returned.
*/
int test__sample_parsing(struct test *test __maybe_unused, int subtest __maybe_unused)
static int test__sample_parsing(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{
const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15};
u64 sample_type;
@@ -426,3 +426,5 @@ int test__sample_parsing(struct test *test __maybe_unused, int subtest __maybe_u
return 0;
}
DEFINE_SUITE("Sample parsing", sample_parsing);

View File

@@ -76,7 +76,7 @@ static int search_cached_probe(const char *target,
return ret;
}
int test__sdt_event(struct test *test __maybe_unused, int subtests __maybe_unused)
static int test__sdt_event(struct test_suite *test __maybe_unused, int subtests __maybe_unused)
{
int ret = TEST_FAIL;
char __tempdir[] = "./test-buildid-XXXXXX";
@@ -114,9 +114,11 @@ error:
return ret;
}
#else
int test__sdt_event(struct test *test __maybe_unused, int subtests __maybe_unused)
static int test__sdt_event(struct test_suite *test __maybe_unused, int subtests __maybe_unused)
{
pr_debug("Skip SDT event test because SDT support is not compiled\n");
return TEST_SKIP;
}
#endif
DEFINE_SUITE("Probe SDT events", sdt_event);

View File

@@ -12,7 +12,7 @@ skip_if_no_z_record() {
collect_z_record() {
echo "Collecting compressed record file:"
[[ "$(uname -m)" != s390x ]] && gflag='-g'
[ "$(uname -m)" != s390x ] && gflag='-g'
$perf_tool record -o $trace_file $gflag -z -F 5000 -- \
dd count=500 if=/dev/urandom of=/dev/null
}

View File

@@ -7,11 +7,11 @@ set -e
for p in $(perf list --raw-dump pmu); do
echo "Testing $p"
result=$(perf stat -e "$p" true 2>&1)
if [[ ! "$result" =~ "$p" ]] && [[ ! "$result" =~ "<not supported>" ]]; then
if ! echo "$result" | grep -q "$p" && ! echo "$result" | grep -q "<not supported>" ; then
# We failed to see the event and it is supported. Possibly the workload was
# too small so retry with something longer.
result=$(perf stat -e "$p" perf bench internals synthesize 2>&1)
if [[ ! "$result" =~ "$p" ]]; then
if ! echo "$result" | grep -q "$p" ; then
echo "Event '$p' not printed in:"
echo "$result"
exit 1

View File

@@ -23,7 +23,7 @@ compare_number()
# skip if --bpf-counters is not supported
if ! perf stat --bpf-counters true > /dev/null 2>&1; then
if [ "$1" == "-v" ]; then
if [ "$1" = "-v" ]; then
echo "Skipping: --bpf-counters not supported"
perf --no-pager stat --bpf-counters true || true
fi

Some files were not shown because too many files have changed in this diff Show More