mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar: "On the kernel side the main changes in this cycle were: - Add Intel Kaby Lake CPU support (Srinivas Pandruvada) - AMD uncore driver updates for fam17 (Janakarajan Natarajan) - Intel/PT updates and core events optimizations and cleanups (Alexander Shishkin) - cgroups events fixes (David Carrillo-Cisneros) - kprobes improvements (Masami Hiramatsu) - ... plus misc fixes and updates. On the tooling side the main changes were: - Support clang build in tools/{perf,lib/{bpf,traceevent,api}} with CC=clang, to, for instance, take advantage of better warnings (Arnaldo Carvalho de Melo): - Introduce the 'delta-abs' 'perf diff' compute method, that orders the histogram entries by the absolute value of the percentage delta for a function in two perf.data files, i.e. the functions that changed the most (increase or decrease in samples) comes first (Namhyung Kim) - Add support for parsing Intel uncore vendor event files and add uncore vendor events for the Intel server processors (Haswell, Broadwell, IvyBridge), Xeon Phi (Knights Landing) and Broadwell DE (Andi Kleen) - Introduce 'perf ftrace' a perf front end to the kernel's ftrace function and function_graph tracer, defaulting to the "function_graph" tracer, more work will be done in reviving this effort, forward porting it from its initial patch submission (Namhyung Kim) - Add 'e' and 'c' hotkeys to expand/collapse call chains for a single hist entry in the 'perf report' and 'perf top' TUI (Jiri Olsa) - Account thread wait time (off CPU time) separately: sleep, iowait and preempt, based on the prev_state of the last event, show the breakdown when using "perf sched timehist --state" (Namhyumg Kim) - Add more triggers to switch the output file (perf.data.TIMESTAMP). Now, in addition to switching to a different output file when receiving a SIGUSR2, one can also specify file size and time based triggers: perf record -a --switch-output=signal is equivalent to what we had before: perf record -a --switch-output While we can also ask for the file to be "sliced" by size, taking into account that that will happen only when we get woken up by the kernel, i.e. one has to take into account the --mmap-pages (the size of the perf mmap ring buffer): perf record -a --switch-output=2G will break the perf.data output into multiple files limited to 2GB of samples, right when generating the output. For time based samples, alert() will be used, so to have 1 minute limited perf.data output files: perf record -a --switch-output=1m (Jiri Olsa) - Improve 'perf trace' (Arnaldo Carvalho de Melo) - 'perf kallsyms' toy tool to look for extended symbol information on the running kernel and demonstrate the machine/thread/symbol APIs for use in other tools, such as 'perf probe' (Arnaldo Carvalho de Melo) - ... plus tons of other changes, see the shortlog and Git log for details" * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (131 commits) perf tools: Add missing parse_events_error() prototype perf pmu: Fix check for unset alias->unit array perf tools: Be consistent on the type of map->symbols[] interator perf intel pt decoder: clang has no -Wno-override-init perf evsel: Do not put a variable sized type not at the end of a struct perf probe: Avoid accessing uninitialized 'map' variable perf tools: Do not put a variable sized type not at the end of a struct perf record: Do not put a variable sized type not at the end of a struct perf tests: Synthesize struct instead of using field after variable sized type perf bench numa: Make sure dprintf() is not defined Revert "perf bench futex: Sanitize numeric parameters" tools lib subcmd: Make it an error to pass a signed value to OPTION_UINTEGER tools: Set the maximum optimization level according to the compiler being used tools: Suppress request for warning options not existent in clang samples/bpf: Reset global variables samples/bpf: Ignore already processed ELF sections samples/bpf: Add missing header perf symbols: dso->name is an array, no need to check it against NULL perf tests record: No need to test an array against NULL perf symbols: No need to check if sym->name is NULL ...
This commit is contained in:
commit
7f4eb0a6d5
6
Makefile
6
Makefile
@ -87,10 +87,12 @@ endif
|
|||||||
ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4
|
ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4
|
||||||
ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)
|
ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)
|
||||||
quiet=silent_
|
quiet=silent_
|
||||||
|
tools_silent=s
|
||||||
endif
|
endif
|
||||||
else # make-3.8x
|
else # make-3.8x
|
||||||
ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
|
ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
|
||||||
quiet=silent_
|
quiet=silent_
|
||||||
|
tools_silent=-s
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -1607,11 +1609,11 @@ image_name:
|
|||||||
# Clear a bunch of variables before executing the submake
|
# Clear a bunch of variables before executing the submake
|
||||||
tools/: FORCE
|
tools/: FORCE
|
||||||
$(Q)mkdir -p $(objtree)/tools
|
$(Q)mkdir -p $(objtree)/tools
|
||||||
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/
|
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(tools_silent) $(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/
|
||||||
|
|
||||||
tools/%: FORCE
|
tools/%: FORCE
|
||||||
$(Q)mkdir -p $(objtree)/tools
|
$(Q)mkdir -p $(objtree)/tools
|
||||||
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/ $*
|
$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(tools_silent) $(filter --j% -j,$(MAKEFLAGS))" O=$(shell cd $(objtree) && /bin/pwd) subdir=tools -C $(src)/tools/ $*
|
||||||
|
|
||||||
# Single targets
|
# Single targets
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
@ -96,7 +96,7 @@ config ARM64
|
|||||||
select HAVE_RCU_TABLE_FREE
|
select HAVE_RCU_TABLE_FREE
|
||||||
select HAVE_SYSCALL_TRACEPOINTS
|
select HAVE_SYSCALL_TRACEPOINTS
|
||||||
select HAVE_KPROBES
|
select HAVE_KPROBES
|
||||||
select HAVE_KRETPROBES if HAVE_KPROBES
|
select HAVE_KRETPROBES
|
||||||
select IOMMU_DMA if IOMMU_SUPPORT
|
select IOMMU_DMA if IOMMU_SUPPORT
|
||||||
select IRQ_DOMAIN
|
select IRQ_DOMAIN
|
||||||
select IRQ_FORCED_THREADING
|
select IRQ_FORCED_THREADING
|
||||||
|
@ -1,11 +1,4 @@
|
|||||||
obj-y += core.o
|
obj-y += core.o
|
||||||
|
obj-y += amd/
|
||||||
obj-$(CONFIG_CPU_SUP_AMD) += amd/core.o amd/uncore.o
|
obj-$(CONFIG_X86_LOCAL_APIC) += msr.o
|
||||||
obj-$(CONFIG_PERF_EVENTS_AMD_POWER) += amd/power.o
|
|
||||||
obj-$(CONFIG_X86_LOCAL_APIC) += amd/ibs.o msr.o
|
|
||||||
ifdef CONFIG_AMD_IOMMU
|
|
||||||
obj-$(CONFIG_CPU_SUP_AMD) += amd/iommu.o
|
|
||||||
endif
|
|
||||||
|
|
||||||
obj-$(CONFIG_CPU_SUP_INTEL) += msr.o
|
|
||||||
obj-$(CONFIG_CPU_SUP_INTEL) += intel/
|
obj-$(CONFIG_CPU_SUP_INTEL) += intel/
|
||||||
|
7
arch/x86/events/amd/Makefile
Normal file
7
arch/x86/events/amd/Makefile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
obj-$(CONFIG_CPU_SUP_AMD) += core.o uncore.o
|
||||||
|
obj-$(CONFIG_PERF_EVENTS_AMD_POWER) += power.o
|
||||||
|
obj-$(CONFIG_X86_LOCAL_APIC) += ibs.o
|
||||||
|
ifdef CONFIG_AMD_IOMMU
|
||||||
|
obj-$(CONFIG_CPU_SUP_AMD) += iommu.o
|
||||||
|
endif
|
||||||
|
|
@ -22,13 +22,17 @@
|
|||||||
|
|
||||||
#define NUM_COUNTERS_NB 4
|
#define NUM_COUNTERS_NB 4
|
||||||
#define NUM_COUNTERS_L2 4
|
#define NUM_COUNTERS_L2 4
|
||||||
#define MAX_COUNTERS NUM_COUNTERS_NB
|
#define NUM_COUNTERS_L3 6
|
||||||
|
#define MAX_COUNTERS 6
|
||||||
|
|
||||||
#define RDPMC_BASE_NB 6
|
#define RDPMC_BASE_NB 6
|
||||||
#define RDPMC_BASE_L2 10
|
#define RDPMC_BASE_LLC 10
|
||||||
|
|
||||||
#define COUNTER_SHIFT 16
|
#define COUNTER_SHIFT 16
|
||||||
|
|
||||||
|
static int num_counters_llc;
|
||||||
|
static int num_counters_nb;
|
||||||
|
|
||||||
static HLIST_HEAD(uncore_unused_list);
|
static HLIST_HEAD(uncore_unused_list);
|
||||||
|
|
||||||
struct amd_uncore {
|
struct amd_uncore {
|
||||||
@ -45,30 +49,30 @@ struct amd_uncore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct amd_uncore * __percpu *amd_uncore_nb;
|
static struct amd_uncore * __percpu *amd_uncore_nb;
|
||||||
static struct amd_uncore * __percpu *amd_uncore_l2;
|
static struct amd_uncore * __percpu *amd_uncore_llc;
|
||||||
|
|
||||||
static struct pmu amd_nb_pmu;
|
static struct pmu amd_nb_pmu;
|
||||||
static struct pmu amd_l2_pmu;
|
static struct pmu amd_llc_pmu;
|
||||||
|
|
||||||
static cpumask_t amd_nb_active_mask;
|
static cpumask_t amd_nb_active_mask;
|
||||||
static cpumask_t amd_l2_active_mask;
|
static cpumask_t amd_llc_active_mask;
|
||||||
|
|
||||||
static bool is_nb_event(struct perf_event *event)
|
static bool is_nb_event(struct perf_event *event)
|
||||||
{
|
{
|
||||||
return event->pmu->type == amd_nb_pmu.type;
|
return event->pmu->type == amd_nb_pmu.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_l2_event(struct perf_event *event)
|
static bool is_llc_event(struct perf_event *event)
|
||||||
{
|
{
|
||||||
return event->pmu->type == amd_l2_pmu.type;
|
return event->pmu->type == amd_llc_pmu.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct amd_uncore *event_to_amd_uncore(struct perf_event *event)
|
static struct amd_uncore *event_to_amd_uncore(struct perf_event *event)
|
||||||
{
|
{
|
||||||
if (is_nb_event(event) && amd_uncore_nb)
|
if (is_nb_event(event) && amd_uncore_nb)
|
||||||
return *per_cpu_ptr(amd_uncore_nb, event->cpu);
|
return *per_cpu_ptr(amd_uncore_nb, event->cpu);
|
||||||
else if (is_l2_event(event) && amd_uncore_l2)
|
else if (is_llc_event(event) && amd_uncore_llc)
|
||||||
return *per_cpu_ptr(amd_uncore_l2, event->cpu);
|
return *per_cpu_ptr(amd_uncore_llc, event->cpu);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -183,16 +187,16 @@ static int amd_uncore_event_init(struct perf_event *event)
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NB and L2 counters (MSRs) are shared across all cores that share the
|
* NB and Last level cache counters (MSRs) are shared across all cores
|
||||||
* same NB / L2 cache. Interrupts can be directed to a single target
|
* that share the same NB / Last level cache. Interrupts can be directed
|
||||||
* core, however, event counts generated by processes running on other
|
* to a single target core, however, event counts generated by processes
|
||||||
* cores cannot be masked out. So we do not support sampling and
|
* running on other cores cannot be masked out. So we do not support
|
||||||
* per-thread events.
|
* sampling and per-thread events.
|
||||||
*/
|
*/
|
||||||
if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
|
if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* NB and L2 counters do not have usr/os/guest/host bits */
|
/* NB and Last level cache counters do not have usr/os/guest/host bits */
|
||||||
if (event->attr.exclude_user || event->attr.exclude_kernel ||
|
if (event->attr.exclude_user || event->attr.exclude_kernel ||
|
||||||
event->attr.exclude_host || event->attr.exclude_guest)
|
event->attr.exclude_host || event->attr.exclude_guest)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -226,8 +230,8 @@ static ssize_t amd_uncore_attr_show_cpumask(struct device *dev,
|
|||||||
|
|
||||||
if (pmu->type == amd_nb_pmu.type)
|
if (pmu->type == amd_nb_pmu.type)
|
||||||
active_mask = &amd_nb_active_mask;
|
active_mask = &amd_nb_active_mask;
|
||||||
else if (pmu->type == amd_l2_pmu.type)
|
else if (pmu->type == amd_llc_pmu.type)
|
||||||
active_mask = &amd_l2_active_mask;
|
active_mask = &amd_llc_active_mask;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -244,30 +248,47 @@ static struct attribute_group amd_uncore_attr_group = {
|
|||||||
.attrs = amd_uncore_attrs,
|
.attrs = amd_uncore_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
PMU_FORMAT_ATTR(event, "config:0-7,32-35");
|
/*
|
||||||
PMU_FORMAT_ATTR(umask, "config:8-15");
|
* Similar to PMU_FORMAT_ATTR but allowing for format_attr to be assigned based
|
||||||
|
* on family
|
||||||
|
*/
|
||||||
|
#define AMD_FORMAT_ATTR(_dev, _name, _format) \
|
||||||
|
static ssize_t \
|
||||||
|
_dev##_show##_name(struct device *dev, \
|
||||||
|
struct device_attribute *attr, \
|
||||||
|
char *page) \
|
||||||
|
{ \
|
||||||
|
BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \
|
||||||
|
return sprintf(page, _format "\n"); \
|
||||||
|
} \
|
||||||
|
static struct device_attribute format_attr_##_dev##_name = __ATTR_RO(_dev);
|
||||||
|
|
||||||
static struct attribute *amd_uncore_format_attr[] = {
|
/* Used for each uncore counter type */
|
||||||
&format_attr_event.attr,
|
#define AMD_ATTRIBUTE(_name) \
|
||||||
&format_attr_umask.attr,
|
static struct attribute *amd_uncore_format_attr_##_name[] = { \
|
||||||
NULL,
|
&format_attr_event_##_name.attr, \
|
||||||
|
&format_attr_umask.attr, \
|
||||||
|
NULL, \
|
||||||
|
}; \
|
||||||
|
static struct attribute_group amd_uncore_format_group_##_name = { \
|
||||||
|
.name = "format", \
|
||||||
|
.attrs = amd_uncore_format_attr_##_name, \
|
||||||
|
}; \
|
||||||
|
static const struct attribute_group *amd_uncore_attr_groups_##_name[] = { \
|
||||||
|
&amd_uncore_attr_group, \
|
||||||
|
&amd_uncore_format_group_##_name, \
|
||||||
|
NULL, \
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attribute_group amd_uncore_format_group = {
|
AMD_FORMAT_ATTR(event, , "config:0-7,32-35");
|
||||||
.name = "format",
|
AMD_FORMAT_ATTR(umask, , "config:8-15");
|
||||||
.attrs = amd_uncore_format_attr,
|
AMD_FORMAT_ATTR(event, _df, "config:0-7,32-35,59-60");
|
||||||
};
|
AMD_FORMAT_ATTR(event, _l3, "config:0-7");
|
||||||
|
AMD_ATTRIBUTE(df);
|
||||||
static const struct attribute_group *amd_uncore_attr_groups[] = {
|
AMD_ATTRIBUTE(l3);
|
||||||
&amd_uncore_attr_group,
|
|
||||||
&amd_uncore_format_group,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct pmu amd_nb_pmu = {
|
static struct pmu amd_nb_pmu = {
|
||||||
.task_ctx_nr = perf_invalid_context,
|
.task_ctx_nr = perf_invalid_context,
|
||||||
.attr_groups = amd_uncore_attr_groups,
|
|
||||||
.name = "amd_nb",
|
|
||||||
.event_init = amd_uncore_event_init,
|
.event_init = amd_uncore_event_init,
|
||||||
.add = amd_uncore_add,
|
.add = amd_uncore_add,
|
||||||
.del = amd_uncore_del,
|
.del = amd_uncore_del,
|
||||||
@ -276,10 +297,8 @@ static struct pmu amd_nb_pmu = {
|
|||||||
.read = amd_uncore_read,
|
.read = amd_uncore_read,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pmu amd_l2_pmu = {
|
static struct pmu amd_llc_pmu = {
|
||||||
.task_ctx_nr = perf_invalid_context,
|
.task_ctx_nr = perf_invalid_context,
|
||||||
.attr_groups = amd_uncore_attr_groups,
|
|
||||||
.name = "amd_l2",
|
|
||||||
.event_init = amd_uncore_event_init,
|
.event_init = amd_uncore_event_init,
|
||||||
.add = amd_uncore_add,
|
.add = amd_uncore_add,
|
||||||
.del = amd_uncore_del,
|
.del = amd_uncore_del,
|
||||||
@ -296,14 +315,14 @@ static struct amd_uncore *amd_uncore_alloc(unsigned int cpu)
|
|||||||
|
|
||||||
static int amd_uncore_cpu_up_prepare(unsigned int cpu)
|
static int amd_uncore_cpu_up_prepare(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct amd_uncore *uncore_nb = NULL, *uncore_l2;
|
struct amd_uncore *uncore_nb = NULL, *uncore_llc;
|
||||||
|
|
||||||
if (amd_uncore_nb) {
|
if (amd_uncore_nb) {
|
||||||
uncore_nb = amd_uncore_alloc(cpu);
|
uncore_nb = amd_uncore_alloc(cpu);
|
||||||
if (!uncore_nb)
|
if (!uncore_nb)
|
||||||
goto fail;
|
goto fail;
|
||||||
uncore_nb->cpu = cpu;
|
uncore_nb->cpu = cpu;
|
||||||
uncore_nb->num_counters = NUM_COUNTERS_NB;
|
uncore_nb->num_counters = num_counters_nb;
|
||||||
uncore_nb->rdpmc_base = RDPMC_BASE_NB;
|
uncore_nb->rdpmc_base = RDPMC_BASE_NB;
|
||||||
uncore_nb->msr_base = MSR_F15H_NB_PERF_CTL;
|
uncore_nb->msr_base = MSR_F15H_NB_PERF_CTL;
|
||||||
uncore_nb->active_mask = &amd_nb_active_mask;
|
uncore_nb->active_mask = &amd_nb_active_mask;
|
||||||
@ -312,18 +331,18 @@ static int amd_uncore_cpu_up_prepare(unsigned int cpu)
|
|||||||
*per_cpu_ptr(amd_uncore_nb, cpu) = uncore_nb;
|
*per_cpu_ptr(amd_uncore_nb, cpu) = uncore_nb;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amd_uncore_l2) {
|
if (amd_uncore_llc) {
|
||||||
uncore_l2 = amd_uncore_alloc(cpu);
|
uncore_llc = amd_uncore_alloc(cpu);
|
||||||
if (!uncore_l2)
|
if (!uncore_llc)
|
||||||
goto fail;
|
goto fail;
|
||||||
uncore_l2->cpu = cpu;
|
uncore_llc->cpu = cpu;
|
||||||
uncore_l2->num_counters = NUM_COUNTERS_L2;
|
uncore_llc->num_counters = num_counters_llc;
|
||||||
uncore_l2->rdpmc_base = RDPMC_BASE_L2;
|
uncore_llc->rdpmc_base = RDPMC_BASE_LLC;
|
||||||
uncore_l2->msr_base = MSR_F16H_L2I_PERF_CTL;
|
uncore_llc->msr_base = MSR_F16H_L2I_PERF_CTL;
|
||||||
uncore_l2->active_mask = &amd_l2_active_mask;
|
uncore_llc->active_mask = &amd_llc_active_mask;
|
||||||
uncore_l2->pmu = &amd_l2_pmu;
|
uncore_llc->pmu = &amd_llc_pmu;
|
||||||
uncore_l2->id = -1;
|
uncore_llc->id = -1;
|
||||||
*per_cpu_ptr(amd_uncore_l2, cpu) = uncore_l2;
|
*per_cpu_ptr(amd_uncore_llc, cpu) = uncore_llc;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -376,17 +395,17 @@ static int amd_uncore_cpu_starting(unsigned int cpu)
|
|||||||
*per_cpu_ptr(amd_uncore_nb, cpu) = uncore;
|
*per_cpu_ptr(amd_uncore_nb, cpu) = uncore;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amd_uncore_l2) {
|
if (amd_uncore_llc) {
|
||||||
unsigned int apicid = cpu_data(cpu).apicid;
|
unsigned int apicid = cpu_data(cpu).apicid;
|
||||||
unsigned int nshared;
|
unsigned int nshared;
|
||||||
|
|
||||||
uncore = *per_cpu_ptr(amd_uncore_l2, cpu);
|
uncore = *per_cpu_ptr(amd_uncore_llc, cpu);
|
||||||
cpuid_count(0x8000001d, 2, &eax, &ebx, &ecx, &edx);
|
cpuid_count(0x8000001d, 2, &eax, &ebx, &ecx, &edx);
|
||||||
nshared = ((eax >> 14) & 0xfff) + 1;
|
nshared = ((eax >> 14) & 0xfff) + 1;
|
||||||
uncore->id = apicid - (apicid % nshared);
|
uncore->id = apicid - (apicid % nshared);
|
||||||
|
|
||||||
uncore = amd_uncore_find_online_sibling(uncore, amd_uncore_l2);
|
uncore = amd_uncore_find_online_sibling(uncore, amd_uncore_llc);
|
||||||
*per_cpu_ptr(amd_uncore_l2, cpu) = uncore;
|
*per_cpu_ptr(amd_uncore_llc, cpu) = uncore;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -419,8 +438,8 @@ static int amd_uncore_cpu_online(unsigned int cpu)
|
|||||||
if (amd_uncore_nb)
|
if (amd_uncore_nb)
|
||||||
uncore_online(cpu, amd_uncore_nb);
|
uncore_online(cpu, amd_uncore_nb);
|
||||||
|
|
||||||
if (amd_uncore_l2)
|
if (amd_uncore_llc)
|
||||||
uncore_online(cpu, amd_uncore_l2);
|
uncore_online(cpu, amd_uncore_llc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -456,8 +475,8 @@ static int amd_uncore_cpu_down_prepare(unsigned int cpu)
|
|||||||
if (amd_uncore_nb)
|
if (amd_uncore_nb)
|
||||||
uncore_down_prepare(cpu, amd_uncore_nb);
|
uncore_down_prepare(cpu, amd_uncore_nb);
|
||||||
|
|
||||||
if (amd_uncore_l2)
|
if (amd_uncore_llc)
|
||||||
uncore_down_prepare(cpu, amd_uncore_l2);
|
uncore_down_prepare(cpu, amd_uncore_llc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -479,8 +498,8 @@ static int amd_uncore_cpu_dead(unsigned int cpu)
|
|||||||
if (amd_uncore_nb)
|
if (amd_uncore_nb)
|
||||||
uncore_dead(cpu, amd_uncore_nb);
|
uncore_dead(cpu, amd_uncore_nb);
|
||||||
|
|
||||||
if (amd_uncore_l2)
|
if (amd_uncore_llc)
|
||||||
uncore_dead(cpu, amd_uncore_l2);
|
uncore_dead(cpu, amd_uncore_llc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -492,6 +511,47 @@ static int __init amd_uncore_init(void)
|
|||||||
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
|
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
|
||||||
goto fail_nodev;
|
goto fail_nodev;
|
||||||
|
|
||||||
|
switch(boot_cpu_data.x86) {
|
||||||
|
case 23:
|
||||||
|
/* Family 17h: */
|
||||||
|
num_counters_nb = NUM_COUNTERS_NB;
|
||||||
|
num_counters_llc = NUM_COUNTERS_L3;
|
||||||
|
/*
|
||||||
|
* For Family17h, the NorthBridge counters are
|
||||||
|
* re-purposed as Data Fabric counters. Also, support is
|
||||||
|
* added for L3 counters. The pmus are exported based on
|
||||||
|
* family as either L2 or L3 and NB or DF.
|
||||||
|
*/
|
||||||
|
amd_nb_pmu.name = "amd_df";
|
||||||
|
amd_llc_pmu.name = "amd_l3";
|
||||||
|
format_attr_event_df.show = &event_show_df;
|
||||||
|
format_attr_event_l3.show = &event_show_l3;
|
||||||
|
break;
|
||||||
|
case 22:
|
||||||
|
/* Family 16h - may change: */
|
||||||
|
num_counters_nb = NUM_COUNTERS_NB;
|
||||||
|
num_counters_llc = NUM_COUNTERS_L2;
|
||||||
|
amd_nb_pmu.name = "amd_nb";
|
||||||
|
amd_llc_pmu.name = "amd_l2";
|
||||||
|
format_attr_event_df = format_attr_event;
|
||||||
|
format_attr_event_l3 = format_attr_event;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* All prior families have the same number of
|
||||||
|
* NorthBridge and Last Level Cache counters
|
||||||
|
*/
|
||||||
|
num_counters_nb = NUM_COUNTERS_NB;
|
||||||
|
num_counters_llc = NUM_COUNTERS_L2;
|
||||||
|
amd_nb_pmu.name = "amd_nb";
|
||||||
|
amd_llc_pmu.name = "amd_l2";
|
||||||
|
format_attr_event_df = format_attr_event;
|
||||||
|
format_attr_event_l3 = format_attr_event;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
amd_nb_pmu.attr_groups = amd_uncore_attr_groups_df;
|
||||||
|
amd_llc_pmu.attr_groups = amd_uncore_attr_groups_l3;
|
||||||
|
|
||||||
if (!boot_cpu_has(X86_FEATURE_TOPOEXT))
|
if (!boot_cpu_has(X86_FEATURE_TOPOEXT))
|
||||||
goto fail_nodev;
|
goto fail_nodev;
|
||||||
|
|
||||||
@ -510,16 +570,16 @@ static int __init amd_uncore_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (boot_cpu_has(X86_FEATURE_PERFCTR_L2)) {
|
if (boot_cpu_has(X86_FEATURE_PERFCTR_L2)) {
|
||||||
amd_uncore_l2 = alloc_percpu(struct amd_uncore *);
|
amd_uncore_llc = alloc_percpu(struct amd_uncore *);
|
||||||
if (!amd_uncore_l2) {
|
if (!amd_uncore_llc) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto fail_l2;
|
goto fail_llc;
|
||||||
}
|
}
|
||||||
ret = perf_pmu_register(&amd_l2_pmu, amd_l2_pmu.name, -1);
|
ret = perf_pmu_register(&amd_llc_pmu, amd_llc_pmu.name, -1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail_l2;
|
goto fail_llc;
|
||||||
|
|
||||||
pr_info("perf: AMD L2I counters detected\n");
|
pr_info("perf: AMD LLC counters detected\n");
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,7 +589,7 @@ static int __init amd_uncore_init(void)
|
|||||||
if (cpuhp_setup_state(CPUHP_PERF_X86_AMD_UNCORE_PREP,
|
if (cpuhp_setup_state(CPUHP_PERF_X86_AMD_UNCORE_PREP,
|
||||||
"perf/x86/amd/uncore:prepare",
|
"perf/x86/amd/uncore:prepare",
|
||||||
amd_uncore_cpu_up_prepare, amd_uncore_cpu_dead))
|
amd_uncore_cpu_up_prepare, amd_uncore_cpu_dead))
|
||||||
goto fail_l2;
|
goto fail_llc;
|
||||||
|
|
||||||
if (cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING,
|
if (cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING,
|
||||||
"perf/x86/amd/uncore:starting",
|
"perf/x86/amd/uncore:starting",
|
||||||
@ -546,11 +606,11 @@ fail_start:
|
|||||||
cpuhp_remove_state(CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING);
|
cpuhp_remove_state(CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING);
|
||||||
fail_prep:
|
fail_prep:
|
||||||
cpuhp_remove_state(CPUHP_PERF_X86_AMD_UNCORE_PREP);
|
cpuhp_remove_state(CPUHP_PERF_X86_AMD_UNCORE_PREP);
|
||||||
fail_l2:
|
fail_llc:
|
||||||
if (boot_cpu_has(X86_FEATURE_PERFCTR_NB))
|
if (boot_cpu_has(X86_FEATURE_PERFCTR_NB))
|
||||||
perf_pmu_unregister(&amd_nb_pmu);
|
perf_pmu_unregister(&amd_nb_pmu);
|
||||||
if (amd_uncore_l2)
|
if (amd_uncore_llc)
|
||||||
free_percpu(amd_uncore_l2);
|
free_percpu(amd_uncore_llc);
|
||||||
fail_nb:
|
fail_nb:
|
||||||
if (amd_uncore_nb)
|
if (amd_uncore_nb)
|
||||||
free_percpu(amd_uncore_nb);
|
free_percpu(amd_uncore_nb);
|
||||||
|
@ -541,6 +541,9 @@ static const struct x86_cpu_id intel_cstates_match[] __initconst = {
|
|||||||
X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_MOBILE, snb_cstates),
|
X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_MOBILE, snb_cstates),
|
||||||
X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_DESKTOP, snb_cstates),
|
X86_CSTATES_MODEL(INTEL_FAM6_SKYLAKE_DESKTOP, snb_cstates),
|
||||||
|
|
||||||
|
X86_CSTATES_MODEL(INTEL_FAM6_KABYLAKE_MOBILE, snb_cstates),
|
||||||
|
X86_CSTATES_MODEL(INTEL_FAM6_KABYLAKE_DESKTOP, snb_cstates),
|
||||||
|
|
||||||
X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNL, knl_cstates),
|
X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNL, knl_cstates),
|
||||||
X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNM, knl_cstates),
|
X86_CSTATES_MODEL(INTEL_FAM6_XEON_PHI_KNM, knl_cstates),
|
||||||
{ },
|
{ },
|
||||||
|
@ -99,18 +99,24 @@ static struct attribute_group pt_cap_group = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
PMU_FORMAT_ATTR(cyc, "config:1" );
|
PMU_FORMAT_ATTR(cyc, "config:1" );
|
||||||
|
PMU_FORMAT_ATTR(pwr_evt, "config:4" );
|
||||||
|
PMU_FORMAT_ATTR(fup_on_ptw, "config:5" );
|
||||||
PMU_FORMAT_ATTR(mtc, "config:9" );
|
PMU_FORMAT_ATTR(mtc, "config:9" );
|
||||||
PMU_FORMAT_ATTR(tsc, "config:10" );
|
PMU_FORMAT_ATTR(tsc, "config:10" );
|
||||||
PMU_FORMAT_ATTR(noretcomp, "config:11" );
|
PMU_FORMAT_ATTR(noretcomp, "config:11" );
|
||||||
|
PMU_FORMAT_ATTR(ptw, "config:12" );
|
||||||
PMU_FORMAT_ATTR(mtc_period, "config:14-17" );
|
PMU_FORMAT_ATTR(mtc_period, "config:14-17" );
|
||||||
PMU_FORMAT_ATTR(cyc_thresh, "config:19-22" );
|
PMU_FORMAT_ATTR(cyc_thresh, "config:19-22" );
|
||||||
PMU_FORMAT_ATTR(psb_period, "config:24-27" );
|
PMU_FORMAT_ATTR(psb_period, "config:24-27" );
|
||||||
|
|
||||||
static struct attribute *pt_formats_attr[] = {
|
static struct attribute *pt_formats_attr[] = {
|
||||||
&format_attr_cyc.attr,
|
&format_attr_cyc.attr,
|
||||||
|
&format_attr_pwr_evt.attr,
|
||||||
|
&format_attr_fup_on_ptw.attr,
|
||||||
&format_attr_mtc.attr,
|
&format_attr_mtc.attr,
|
||||||
&format_attr_tsc.attr,
|
&format_attr_tsc.attr,
|
||||||
&format_attr_noretcomp.attr,
|
&format_attr_noretcomp.attr,
|
||||||
|
&format_attr_ptw.attr,
|
||||||
&format_attr_mtc_period.attr,
|
&format_attr_mtc_period.attr,
|
||||||
&format_attr_cyc_thresh.attr,
|
&format_attr_cyc_thresh.attr,
|
||||||
&format_attr_psb_period.attr,
|
&format_attr_psb_period.attr,
|
||||||
|
@ -771,6 +771,9 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = {
|
|||||||
X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP, skl_rapl_init),
|
X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP, skl_rapl_init),
|
||||||
X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_X, hsx_rapl_init),
|
X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_X, hsx_rapl_init),
|
||||||
|
|
||||||
|
X86_RAPL_MODEL_MATCH(INTEL_FAM6_KABYLAKE_MOBILE, skl_rapl_init),
|
||||||
|
X86_RAPL_MODEL_MATCH(INTEL_FAM6_KABYLAKE_DESKTOP, skl_rapl_init),
|
||||||
|
|
||||||
X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT, hsw_rapl_init),
|
X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT, hsw_rapl_init),
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
@ -1328,6 +1328,8 @@ static const struct x86_cpu_id intel_uncore_match[] __initconst = {
|
|||||||
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP,skl_uncore_init),
|
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_DESKTOP,skl_uncore_init),
|
||||||
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_MOBILE, skl_uncore_init),
|
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_MOBILE, skl_uncore_init),
|
||||||
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_X, skx_uncore_init),
|
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_SKYLAKE_X, skx_uncore_init),
|
||||||
|
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_KABYLAKE_MOBILE, skl_uncore_init),
|
||||||
|
X86_UNCORE_MODEL_MATCH(INTEL_FAM6_KABYLAKE_DESKTOP, skl_uncore_init),
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -745,7 +745,7 @@ __visible __used void *trampoline_handler(struct pt_regs *regs)
|
|||||||
* will be the real return address, and all the rest will
|
* will be the real return address, and all the rest will
|
||||||
* point to kretprobe_trampoline.
|
* point to kretprobe_trampoline.
|
||||||
*/
|
*/
|
||||||
hlist_for_each_entry_safe(ri, tmp, head, hlist) {
|
hlist_for_each_entry(ri, head, hlist) {
|
||||||
if (ri->task != current)
|
if (ri->task != current)
|
||||||
/* another task is sharing our hash bucket */
|
/* another task is sharing our hash bucket */
|
||||||
continue;
|
continue;
|
||||||
|
@ -278,9 +278,13 @@ struct kprobe_insn_cache {
|
|||||||
int nr_garbage;
|
int nr_garbage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef __ARCH_WANT_KPROBES_INSN_SLOT
|
||||||
extern kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c);
|
extern kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c);
|
||||||
extern void __free_insn_slot(struct kprobe_insn_cache *c,
|
extern void __free_insn_slot(struct kprobe_insn_cache *c,
|
||||||
kprobe_opcode_t *slot, int dirty);
|
kprobe_opcode_t *slot, int dirty);
|
||||||
|
/* sleep-less address checking routine */
|
||||||
|
extern bool __is_insn_slot_addr(struct kprobe_insn_cache *c,
|
||||||
|
unsigned long addr);
|
||||||
|
|
||||||
#define DEFINE_INSN_CACHE_OPS(__name) \
|
#define DEFINE_INSN_CACHE_OPS(__name) \
|
||||||
extern struct kprobe_insn_cache kprobe_##__name##_slots; \
|
extern struct kprobe_insn_cache kprobe_##__name##_slots; \
|
||||||
@ -294,6 +298,18 @@ static inline void free_##__name##_slot(kprobe_opcode_t *slot, int dirty)\
|
|||||||
{ \
|
{ \
|
||||||
__free_insn_slot(&kprobe_##__name##_slots, slot, dirty); \
|
__free_insn_slot(&kprobe_##__name##_slots, slot, dirty); \
|
||||||
} \
|
} \
|
||||||
|
\
|
||||||
|
static inline bool is_kprobe_##__name##_slot(unsigned long addr) \
|
||||||
|
{ \
|
||||||
|
return __is_insn_slot_addr(&kprobe_##__name##_slots, addr); \
|
||||||
|
}
|
||||||
|
#else /* __ARCH_WANT_KPROBES_INSN_SLOT */
|
||||||
|
#define DEFINE_INSN_CACHE_OPS(__name) \
|
||||||
|
static inline bool is_kprobe_##__name##_slot(unsigned long addr) \
|
||||||
|
{ \
|
||||||
|
return 0; \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
DEFINE_INSN_CACHE_OPS(insn);
|
DEFINE_INSN_CACHE_OPS(insn);
|
||||||
|
|
||||||
@ -330,7 +346,6 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table,
|
|||||||
int write, void __user *buffer,
|
int write, void __user *buffer,
|
||||||
size_t *length, loff_t *ppos);
|
size_t *length, loff_t *ppos);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* CONFIG_OPTPROBES */
|
#endif /* CONFIG_OPTPROBES */
|
||||||
#ifdef CONFIG_KPROBES_ON_FTRACE
|
#ifdef CONFIG_KPROBES_ON_FTRACE
|
||||||
extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||||
@ -481,6 +496,19 @@ static inline int enable_jprobe(struct jprobe *jp)
|
|||||||
return enable_kprobe(&jp->kp);
|
return enable_kprobe(&jp->kp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_KPROBES
|
||||||
|
static inline bool is_kprobe_insn_slot(unsigned long addr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifndef CONFIG_OPTPROBES
|
||||||
|
static inline bool is_kprobe_optinsn_slot(unsigned long addr)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_KPROBES
|
#ifdef CONFIG_KPROBES
|
||||||
/*
|
/*
|
||||||
* Blacklist ganerating macro. Specify functions which is not probed
|
* Blacklist ganerating macro. Specify functions which is not probed
|
||||||
|
@ -482,6 +482,7 @@ struct perf_addr_filter {
|
|||||||
* @list: list of filters for this event
|
* @list: list of filters for this event
|
||||||
* @lock: spinlock that serializes accesses to the @list and event's
|
* @lock: spinlock that serializes accesses to the @list and event's
|
||||||
* (and its children's) filter generations.
|
* (and its children's) filter generations.
|
||||||
|
* @nr_file_filters: number of file-based filters
|
||||||
*
|
*
|
||||||
* A child event will use parent's @list (and therefore @lock), so they are
|
* A child event will use parent's @list (and therefore @lock), so they are
|
||||||
* bundled together; see perf_event_addr_filters().
|
* bundled together; see perf_event_addr_filters().
|
||||||
@ -489,6 +490,7 @@ struct perf_addr_filter {
|
|||||||
struct perf_addr_filters_head {
|
struct perf_addr_filters_head {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
raw_spinlock_t lock;
|
raw_spinlock_t lock;
|
||||||
|
unsigned int nr_file_filters;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -785,9 +787,9 @@ struct perf_cpu_context {
|
|||||||
ktime_t hrtimer_interval;
|
ktime_t hrtimer_interval;
|
||||||
unsigned int hrtimer_active;
|
unsigned int hrtimer_active;
|
||||||
|
|
||||||
struct pmu *unique_pmu;
|
|
||||||
#ifdef CONFIG_CGROUP_PERF
|
#ifdef CONFIG_CGROUP_PERF
|
||||||
struct perf_cgroup *cgrp;
|
struct perf_cgroup *cgrp;
|
||||||
|
struct list_head cgrp_cpuctx_entry;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct list_head sched_cb_entry;
|
struct list_head sched_cb_entry;
|
||||||
|
@ -355,6 +355,8 @@ enum event_type_t {
|
|||||||
EVENT_FLEXIBLE = 0x1,
|
EVENT_FLEXIBLE = 0x1,
|
||||||
EVENT_PINNED = 0x2,
|
EVENT_PINNED = 0x2,
|
||||||
EVENT_TIME = 0x4,
|
EVENT_TIME = 0x4,
|
||||||
|
/* see ctx_resched() for details */
|
||||||
|
EVENT_CPU = 0x8,
|
||||||
EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED,
|
EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -678,6 +680,8 @@ perf_cgroup_set_timestamp(struct task_struct *task,
|
|||||||
info->timestamp = ctx->timestamp;
|
info->timestamp = ctx->timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DEFINE_PER_CPU(struct list_head, cgrp_cpuctx_list);
|
||||||
|
|
||||||
#define PERF_CGROUP_SWOUT 0x1 /* cgroup switch out every event */
|
#define PERF_CGROUP_SWOUT 0x1 /* cgroup switch out every event */
|
||||||
#define PERF_CGROUP_SWIN 0x2 /* cgroup switch in events based on task */
|
#define PERF_CGROUP_SWIN 0x2 /* cgroup switch in events based on task */
|
||||||
|
|
||||||
@ -690,61 +694,46 @@ perf_cgroup_set_timestamp(struct task_struct *task,
|
|||||||
static void perf_cgroup_switch(struct task_struct *task, int mode)
|
static void perf_cgroup_switch(struct task_struct *task, int mode)
|
||||||
{
|
{
|
||||||
struct perf_cpu_context *cpuctx;
|
struct perf_cpu_context *cpuctx;
|
||||||
struct pmu *pmu;
|
struct list_head *list;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* disable interrupts to avoid geting nr_cgroup
|
* Disable interrupts and preemption to avoid this CPU's
|
||||||
* changes via __perf_event_disable(). Also
|
* cgrp_cpuctx_entry to change under us.
|
||||||
* avoids preemption.
|
|
||||||
*/
|
*/
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
|
||||||
/*
|
list = this_cpu_ptr(&cgrp_cpuctx_list);
|
||||||
* we reschedule only in the presence of cgroup
|
list_for_each_entry(cpuctx, list, cgrp_cpuctx_entry) {
|
||||||
* constrained events.
|
WARN_ON_ONCE(cpuctx->ctx.nr_cgroups == 0);
|
||||||
*/
|
|
||||||
|
|
||||||
list_for_each_entry_rcu(pmu, &pmus, entry) {
|
perf_ctx_lock(cpuctx, cpuctx->task_ctx);
|
||||||
cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
|
perf_pmu_disable(cpuctx->ctx.pmu);
|
||||||
if (cpuctx->unique_pmu != pmu)
|
|
||||||
continue; /* ensure we process each cpuctx once */
|
|
||||||
|
|
||||||
/*
|
if (mode & PERF_CGROUP_SWOUT) {
|
||||||
* perf_cgroup_events says at least one
|
cpu_ctx_sched_out(cpuctx, EVENT_ALL);
|
||||||
* context on this CPU has cgroup events.
|
/*
|
||||||
*
|
* must not be done before ctxswout due
|
||||||
* ctx->nr_cgroups reports the number of cgroup
|
* to event_filter_match() in event_sched_out()
|
||||||
* events for a context.
|
*/
|
||||||
*/
|
cpuctx->cgrp = NULL;
|
||||||
if (cpuctx->ctx.nr_cgroups > 0) {
|
|
||||||
perf_ctx_lock(cpuctx, cpuctx->task_ctx);
|
|
||||||
perf_pmu_disable(cpuctx->ctx.pmu);
|
|
||||||
|
|
||||||
if (mode & PERF_CGROUP_SWOUT) {
|
|
||||||
cpu_ctx_sched_out(cpuctx, EVENT_ALL);
|
|
||||||
/*
|
|
||||||
* must not be done before ctxswout due
|
|
||||||
* to event_filter_match() in event_sched_out()
|
|
||||||
*/
|
|
||||||
cpuctx->cgrp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode & PERF_CGROUP_SWIN) {
|
|
||||||
WARN_ON_ONCE(cpuctx->cgrp);
|
|
||||||
/*
|
|
||||||
* set cgrp before ctxsw in to allow
|
|
||||||
* event_filter_match() to not have to pass
|
|
||||||
* task around
|
|
||||||
* we pass the cpuctx->ctx to perf_cgroup_from_task()
|
|
||||||
* because cgorup events are only per-cpu
|
|
||||||
*/
|
|
||||||
cpuctx->cgrp = perf_cgroup_from_task(task, &cpuctx->ctx);
|
|
||||||
cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
|
|
||||||
}
|
|
||||||
perf_pmu_enable(cpuctx->ctx.pmu);
|
|
||||||
perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mode & PERF_CGROUP_SWIN) {
|
||||||
|
WARN_ON_ONCE(cpuctx->cgrp);
|
||||||
|
/*
|
||||||
|
* set cgrp before ctxsw in to allow
|
||||||
|
* event_filter_match() to not have to pass
|
||||||
|
* task around
|
||||||
|
* we pass the cpuctx->ctx to perf_cgroup_from_task()
|
||||||
|
* because cgorup events are only per-cpu
|
||||||
|
*/
|
||||||
|
cpuctx->cgrp = perf_cgroup_from_task(task,
|
||||||
|
&cpuctx->ctx);
|
||||||
|
cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
|
||||||
|
}
|
||||||
|
perf_pmu_enable(cpuctx->ctx.pmu);
|
||||||
|
perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
@ -889,6 +878,7 @@ list_update_cgroup_event(struct perf_event *event,
|
|||||||
struct perf_event_context *ctx, bool add)
|
struct perf_event_context *ctx, bool add)
|
||||||
{
|
{
|
||||||
struct perf_cpu_context *cpuctx;
|
struct perf_cpu_context *cpuctx;
|
||||||
|
struct list_head *cpuctx_entry;
|
||||||
|
|
||||||
if (!is_cgroup_event(event))
|
if (!is_cgroup_event(event))
|
||||||
return;
|
return;
|
||||||
@ -902,15 +892,16 @@ list_update_cgroup_event(struct perf_event *event,
|
|||||||
* this will always be called from the right CPU.
|
* this will always be called from the right CPU.
|
||||||
*/
|
*/
|
||||||
cpuctx = __get_cpu_context(ctx);
|
cpuctx = __get_cpu_context(ctx);
|
||||||
|
cpuctx_entry = &cpuctx->cgrp_cpuctx_entry;
|
||||||
/*
|
/* cpuctx->cgrp is NULL unless a cgroup event is active in this CPU .*/
|
||||||
* cpuctx->cgrp is NULL until a cgroup event is sched in or
|
if (add) {
|
||||||
* ctx->nr_cgroup == 0 .
|
list_add(cpuctx_entry, this_cpu_ptr(&cgrp_cpuctx_list));
|
||||||
*/
|
if (perf_cgroup_from_task(current, ctx) == event->cgrp)
|
||||||
if (add && perf_cgroup_from_task(current, ctx) == event->cgrp)
|
cpuctx->cgrp = event->cgrp;
|
||||||
cpuctx->cgrp = event->cgrp;
|
} else {
|
||||||
else if (!add)
|
list_del(cpuctx_entry);
|
||||||
cpuctx->cgrp = NULL;
|
cpuctx->cgrp = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !CONFIG_CGROUP_PERF */
|
#else /* !CONFIG_CGROUP_PERF */
|
||||||
@ -1453,6 +1444,20 @@ static void update_group_times(struct perf_event *leader)
|
|||||||
update_event_times(event);
|
update_event_times(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum event_type_t get_event_type(struct perf_event *event)
|
||||||
|
{
|
||||||
|
struct perf_event_context *ctx = event->ctx;
|
||||||
|
enum event_type_t event_type;
|
||||||
|
|
||||||
|
lockdep_assert_held(&ctx->lock);
|
||||||
|
|
||||||
|
event_type = event->attr.pinned ? EVENT_PINNED : EVENT_FLEXIBLE;
|
||||||
|
if (!ctx->task)
|
||||||
|
event_type |= EVENT_CPU;
|
||||||
|
|
||||||
|
return event_type;
|
||||||
|
}
|
||||||
|
|
||||||
static struct list_head *
|
static struct list_head *
|
||||||
ctx_group_list(struct perf_event *event, struct perf_event_context *ctx)
|
ctx_group_list(struct perf_event *event, struct perf_event_context *ctx)
|
||||||
{
|
{
|
||||||
@ -2226,7 +2231,8 @@ ctx_sched_in(struct perf_event_context *ctx,
|
|||||||
struct task_struct *task);
|
struct task_struct *task);
|
||||||
|
|
||||||
static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
|
static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
|
||||||
struct perf_event_context *ctx)
|
struct perf_event_context *ctx,
|
||||||
|
enum event_type_t event_type)
|
||||||
{
|
{
|
||||||
if (!cpuctx->task_ctx)
|
if (!cpuctx->task_ctx)
|
||||||
return;
|
return;
|
||||||
@ -2234,7 +2240,7 @@ static void task_ctx_sched_out(struct perf_cpu_context *cpuctx,
|
|||||||
if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
|
if (WARN_ON_ONCE(ctx != cpuctx->task_ctx))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ctx_sched_out(ctx, cpuctx, EVENT_ALL);
|
ctx_sched_out(ctx, cpuctx, event_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void perf_event_sched_in(struct perf_cpu_context *cpuctx,
|
static void perf_event_sched_in(struct perf_cpu_context *cpuctx,
|
||||||
@ -2249,13 +2255,51 @@ static void perf_event_sched_in(struct perf_cpu_context *cpuctx,
|
|||||||
ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE, task);
|
ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We want to maintain the following priority of scheduling:
|
||||||
|
* - CPU pinned (EVENT_CPU | EVENT_PINNED)
|
||||||
|
* - task pinned (EVENT_PINNED)
|
||||||
|
* - CPU flexible (EVENT_CPU | EVENT_FLEXIBLE)
|
||||||
|
* - task flexible (EVENT_FLEXIBLE).
|
||||||
|
*
|
||||||
|
* In order to avoid unscheduling and scheduling back in everything every
|
||||||
|
* time an event is added, only do it for the groups of equal priority and
|
||||||
|
* below.
|
||||||
|
*
|
||||||
|
* This can be called after a batch operation on task events, in which case
|
||||||
|
* event_type is a bit mask of the types of events involved. For CPU events,
|
||||||
|
* event_type is only either EVENT_PINNED or EVENT_FLEXIBLE.
|
||||||
|
*/
|
||||||
static void ctx_resched(struct perf_cpu_context *cpuctx,
|
static void ctx_resched(struct perf_cpu_context *cpuctx,
|
||||||
struct perf_event_context *task_ctx)
|
struct perf_event_context *task_ctx,
|
||||||
|
enum event_type_t event_type)
|
||||||
{
|
{
|
||||||
|
enum event_type_t ctx_event_type = event_type & EVENT_ALL;
|
||||||
|
bool cpu_event = !!(event_type & EVENT_CPU);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If pinned groups are involved, flexible groups also need to be
|
||||||
|
* scheduled out.
|
||||||
|
*/
|
||||||
|
if (event_type & EVENT_PINNED)
|
||||||
|
event_type |= EVENT_FLEXIBLE;
|
||||||
|
|
||||||
perf_pmu_disable(cpuctx->ctx.pmu);
|
perf_pmu_disable(cpuctx->ctx.pmu);
|
||||||
if (task_ctx)
|
if (task_ctx)
|
||||||
task_ctx_sched_out(cpuctx, task_ctx);
|
task_ctx_sched_out(cpuctx, task_ctx, event_type);
|
||||||
cpu_ctx_sched_out(cpuctx, EVENT_ALL);
|
|
||||||
|
/*
|
||||||
|
* Decide which cpu ctx groups to schedule out based on the types
|
||||||
|
* of events that caused rescheduling:
|
||||||
|
* - EVENT_CPU: schedule out corresponding groups;
|
||||||
|
* - EVENT_PINNED task events: schedule out EVENT_FLEXIBLE groups;
|
||||||
|
* - otherwise, do nothing more.
|
||||||
|
*/
|
||||||
|
if (cpu_event)
|
||||||
|
cpu_ctx_sched_out(cpuctx, ctx_event_type);
|
||||||
|
else if (ctx_event_type & EVENT_PINNED)
|
||||||
|
cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
|
||||||
|
|
||||||
perf_event_sched_in(cpuctx, task_ctx, current);
|
perf_event_sched_in(cpuctx, task_ctx, current);
|
||||||
perf_pmu_enable(cpuctx->ctx.pmu);
|
perf_pmu_enable(cpuctx->ctx.pmu);
|
||||||
}
|
}
|
||||||
@ -2302,7 +2346,7 @@ static int __perf_install_in_context(void *info)
|
|||||||
if (reprogram) {
|
if (reprogram) {
|
||||||
ctx_sched_out(ctx, cpuctx, EVENT_TIME);
|
ctx_sched_out(ctx, cpuctx, EVENT_TIME);
|
||||||
add_event_to_ctx(event, ctx);
|
add_event_to_ctx(event, ctx);
|
||||||
ctx_resched(cpuctx, task_ctx);
|
ctx_resched(cpuctx, task_ctx, get_event_type(event));
|
||||||
} else {
|
} else {
|
||||||
add_event_to_ctx(event, ctx);
|
add_event_to_ctx(event, ctx);
|
||||||
}
|
}
|
||||||
@ -2469,7 +2513,7 @@ static void __perf_event_enable(struct perf_event *event,
|
|||||||
if (ctx->task)
|
if (ctx->task)
|
||||||
WARN_ON_ONCE(task_ctx != ctx);
|
WARN_ON_ONCE(task_ctx != ctx);
|
||||||
|
|
||||||
ctx_resched(cpuctx, task_ctx);
|
ctx_resched(cpuctx, task_ctx, get_event_type(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2896,7 +2940,7 @@ unlock:
|
|||||||
|
|
||||||
if (do_switch) {
|
if (do_switch) {
|
||||||
raw_spin_lock(&ctx->lock);
|
raw_spin_lock(&ctx->lock);
|
||||||
task_ctx_sched_out(cpuctx, ctx);
|
task_ctx_sched_out(cpuctx, ctx, EVENT_ALL);
|
||||||
raw_spin_unlock(&ctx->lock);
|
raw_spin_unlock(&ctx->lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2943,7 +2987,7 @@ static void perf_pmu_sched_task(struct task_struct *prev,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
list_for_each_entry(cpuctx, this_cpu_ptr(&sched_cb_list), sched_cb_entry) {
|
list_for_each_entry(cpuctx, this_cpu_ptr(&sched_cb_list), sched_cb_entry) {
|
||||||
pmu = cpuctx->unique_pmu; /* software PMUs will not have sched_task */
|
pmu = cpuctx->ctx.pmu; /* software PMUs will not have sched_task */
|
||||||
|
|
||||||
if (WARN_ON_ONCE(!pmu->sched_task))
|
if (WARN_ON_ONCE(!pmu->sched_task))
|
||||||
continue;
|
continue;
|
||||||
@ -3133,8 +3177,12 @@ static void perf_event_context_sched_in(struct perf_event_context *ctx,
|
|||||||
* We want to keep the following priority order:
|
* We want to keep the following priority order:
|
||||||
* cpu pinned (that don't need to move), task pinned,
|
* cpu pinned (that don't need to move), task pinned,
|
||||||
* cpu flexible, task flexible.
|
* cpu flexible, task flexible.
|
||||||
|
*
|
||||||
|
* However, if task's ctx is not carrying any pinned
|
||||||
|
* events, no need to flip the cpuctx's events around.
|
||||||
*/
|
*/
|
||||||
cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
|
if (!list_empty(&ctx->pinned_groups))
|
||||||
|
cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
|
||||||
perf_event_sched_in(cpuctx, ctx, task);
|
perf_event_sched_in(cpuctx, ctx, task);
|
||||||
perf_pmu_enable(ctx->pmu);
|
perf_pmu_enable(ctx->pmu);
|
||||||
perf_ctx_unlock(cpuctx, ctx);
|
perf_ctx_unlock(cpuctx, ctx);
|
||||||
@ -3449,6 +3497,7 @@ static int event_enable_on_exec(struct perf_event *event,
|
|||||||
static void perf_event_enable_on_exec(int ctxn)
|
static void perf_event_enable_on_exec(int ctxn)
|
||||||
{
|
{
|
||||||
struct perf_event_context *ctx, *clone_ctx = NULL;
|
struct perf_event_context *ctx, *clone_ctx = NULL;
|
||||||
|
enum event_type_t event_type = 0;
|
||||||
struct perf_cpu_context *cpuctx;
|
struct perf_cpu_context *cpuctx;
|
||||||
struct perf_event *event;
|
struct perf_event *event;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -3462,15 +3511,17 @@ static void perf_event_enable_on_exec(int ctxn)
|
|||||||
cpuctx = __get_cpu_context(ctx);
|
cpuctx = __get_cpu_context(ctx);
|
||||||
perf_ctx_lock(cpuctx, ctx);
|
perf_ctx_lock(cpuctx, ctx);
|
||||||
ctx_sched_out(ctx, cpuctx, EVENT_TIME);
|
ctx_sched_out(ctx, cpuctx, EVENT_TIME);
|
||||||
list_for_each_entry(event, &ctx->event_list, event_entry)
|
list_for_each_entry(event, &ctx->event_list, event_entry) {
|
||||||
enabled |= event_enable_on_exec(event, ctx);
|
enabled |= event_enable_on_exec(event, ctx);
|
||||||
|
event_type |= get_event_type(event);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unclone and reschedule this context if we enabled any event.
|
* Unclone and reschedule this context if we enabled any event.
|
||||||
*/
|
*/
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
clone_ctx = unclone_ctx(ctx);
|
clone_ctx = unclone_ctx(ctx);
|
||||||
ctx_resched(cpuctx, ctx);
|
ctx_resched(cpuctx, ctx, event_type);
|
||||||
}
|
}
|
||||||
perf_ctx_unlock(cpuctx, ctx);
|
perf_ctx_unlock(cpuctx, ctx);
|
||||||
|
|
||||||
@ -8044,6 +8095,9 @@ static void perf_event_addr_filters_apply(struct perf_event *event)
|
|||||||
if (task == TASK_TOMBSTONE)
|
if (task == TASK_TOMBSTONE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!ifh->nr_file_filters)
|
||||||
|
return;
|
||||||
|
|
||||||
mm = get_task_mm(event->ctx->task);
|
mm = get_task_mm(event->ctx->task);
|
||||||
if (!mm)
|
if (!mm)
|
||||||
goto restart;
|
goto restart;
|
||||||
@ -8214,6 +8268,7 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
|
|||||||
* attribute.
|
* attribute.
|
||||||
*/
|
*/
|
||||||
if (state == IF_STATE_END) {
|
if (state == IF_STATE_END) {
|
||||||
|
ret = -EINVAL;
|
||||||
if (kernel && event->attr.exclude_kernel)
|
if (kernel && event->attr.exclude_kernel)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -8221,6 +8276,18 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
|
|||||||
if (!filename)
|
if (!filename)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For now, we only support file-based filters
|
||||||
|
* in per-task events; doing so for CPU-wide
|
||||||
|
* events requires additional context switching
|
||||||
|
* trickery, since same object code will be
|
||||||
|
* mapped at different virtual addresses in
|
||||||
|
* different processes.
|
||||||
|
*/
|
||||||
|
ret = -EOPNOTSUPP;
|
||||||
|
if (!event->ctx->task)
|
||||||
|
goto fail_free_name;
|
||||||
|
|
||||||
/* look up the path and grab its inode */
|
/* look up the path and grab its inode */
|
||||||
ret = kern_path(filename, LOOKUP_FOLLOW, &path);
|
ret = kern_path(filename, LOOKUP_FOLLOW, &path);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -8236,6 +8303,8 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
|
|||||||
!S_ISREG(filter->inode->i_mode))
|
!S_ISREG(filter->inode->i_mode))
|
||||||
/* free_filters_list() will iput() */
|
/* free_filters_list() will iput() */
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
event->addr_filters.nr_file_filters++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ready to consume more filters */
|
/* ready to consume more filters */
|
||||||
@ -8275,24 +8344,13 @@ perf_event_set_addr_filter(struct perf_event *event, char *filter_str)
|
|||||||
if (WARN_ON_ONCE(event->parent))
|
if (WARN_ON_ONCE(event->parent))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
|
||||||
* For now, we only support filtering in per-task events; doing so
|
|
||||||
* for CPU-wide events requires additional context switching trickery,
|
|
||||||
* since same object code will be mapped at different virtual
|
|
||||||
* addresses in different processes.
|
|
||||||
*/
|
|
||||||
if (!event->ctx->task)
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
ret = perf_event_parse_addr_filter(event, filter_str, &filters);
|
ret = perf_event_parse_addr_filter(event, filter_str, &filters);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto fail_clear_files;
|
||||||
|
|
||||||
ret = event->pmu->addr_filters_validate(&filters);
|
ret = event->pmu->addr_filters_validate(&filters);
|
||||||
if (ret) {
|
if (ret)
|
||||||
free_filters_list(&filters);
|
goto fail_free_filters;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove existing filters, if any */
|
/* remove existing filters, if any */
|
||||||
perf_addr_filters_splice(event, &filters);
|
perf_addr_filters_splice(event, &filters);
|
||||||
@ -8300,6 +8358,14 @@ perf_event_set_addr_filter(struct perf_event *event, char *filter_str)
|
|||||||
/* install new filters */
|
/* install new filters */
|
||||||
perf_event_for_each_child(event, perf_event_addr_filters_apply);
|
perf_event_for_each_child(event, perf_event_addr_filters_apply);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
fail_free_filters:
|
||||||
|
free_filters_list(&filters);
|
||||||
|
|
||||||
|
fail_clear_files:
|
||||||
|
event->addr_filters.nr_file_filters = 0;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8652,37 +8718,10 @@ static struct perf_cpu_context __percpu *find_pmu_context(int ctxn)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu)
|
|
||||||
{
|
|
||||||
int cpu;
|
|
||||||
|
|
||||||
for_each_possible_cpu(cpu) {
|
|
||||||
struct perf_cpu_context *cpuctx;
|
|
||||||
|
|
||||||
cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
|
|
||||||
|
|
||||||
if (cpuctx->unique_pmu == old_pmu)
|
|
||||||
cpuctx->unique_pmu = pmu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_pmu_context(struct pmu *pmu)
|
static void free_pmu_context(struct pmu *pmu)
|
||||||
{
|
{
|
||||||
struct pmu *i;
|
|
||||||
|
|
||||||
mutex_lock(&pmus_lock);
|
mutex_lock(&pmus_lock);
|
||||||
/*
|
|
||||||
* Like a real lame refcount.
|
|
||||||
*/
|
|
||||||
list_for_each_entry(i, &pmus, entry) {
|
|
||||||
if (i->pmu_cpu_context == pmu->pmu_cpu_context) {
|
|
||||||
update_pmu_context(i, pmu);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free_percpu(pmu->pmu_cpu_context);
|
free_percpu(pmu->pmu_cpu_context);
|
||||||
out:
|
|
||||||
mutex_unlock(&pmus_lock);
|
mutex_unlock(&pmus_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8886,8 +8925,6 @@ skip_type:
|
|||||||
cpuctx->ctx.pmu = pmu;
|
cpuctx->ctx.pmu = pmu;
|
||||||
|
|
||||||
__perf_mux_hrtimer_init(cpuctx, cpu);
|
__perf_mux_hrtimer_init(cpuctx, cpu);
|
||||||
|
|
||||||
cpuctx->unique_pmu = pmu;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
got_cpu_context:
|
got_cpu_context:
|
||||||
@ -9005,6 +9042,14 @@ static struct pmu *perf_init_event(struct perf_event *event)
|
|||||||
|
|
||||||
idx = srcu_read_lock(&pmus_srcu);
|
idx = srcu_read_lock(&pmus_srcu);
|
||||||
|
|
||||||
|
/* Try parent's PMU first: */
|
||||||
|
if (event->parent && event->parent->pmu) {
|
||||||
|
pmu = event->parent->pmu;
|
||||||
|
ret = perf_try_init_event(pmu, event);
|
||||||
|
if (!ret)
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
pmu = idr_find(&pmu_idr, event->attr.type);
|
pmu = idr_find(&pmu_idr, event->attr.type);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
@ -10265,7 +10310,7 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
|
|||||||
* in.
|
* in.
|
||||||
*/
|
*/
|
||||||
raw_spin_lock_irq(&child_ctx->lock);
|
raw_spin_lock_irq(&child_ctx->lock);
|
||||||
task_ctx_sched_out(__get_cpu_context(child_ctx), child_ctx);
|
task_ctx_sched_out(__get_cpu_context(child_ctx), child_ctx, EVENT_ALL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that the context is inactive, destroy the task <-> ctx relation
|
* Now that the context is inactive, destroy the task <-> ctx relation
|
||||||
@ -10714,6 +10759,9 @@ static void __init perf_event_init_all_cpus(void)
|
|||||||
INIT_LIST_HEAD(&per_cpu(pmu_sb_events.list, cpu));
|
INIT_LIST_HEAD(&per_cpu(pmu_sb_events.list, cpu));
|
||||||
raw_spin_lock_init(&per_cpu(pmu_sb_events.lock, cpu));
|
raw_spin_lock_init(&per_cpu(pmu_sb_events.lock, cpu));
|
||||||
|
|
||||||
|
#ifdef CONFIG_CGROUP_PERF
|
||||||
|
INIT_LIST_HEAD(&per_cpu(cgrp_cpuctx_list, cpu));
|
||||||
|
#endif
|
||||||
INIT_LIST_HEAD(&per_cpu(sched_cb_list, cpu));
|
INIT_LIST_HEAD(&per_cpu(sched_cb_list, cpu));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/kprobes.h>
|
||||||
|
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
@ -104,6 +105,8 @@ int __kernel_text_address(unsigned long addr)
|
|||||||
return 1;
|
return 1;
|
||||||
if (is_ftrace_trampoline(addr))
|
if (is_ftrace_trampoline(addr))
|
||||||
return 1;
|
return 1;
|
||||||
|
if (is_kprobe_optinsn_slot(addr) || is_kprobe_insn_slot(addr))
|
||||||
|
return 1;
|
||||||
/*
|
/*
|
||||||
* There might be init symbols in saved stacktraces.
|
* There might be init symbols in saved stacktraces.
|
||||||
* Give those symbols a chance to be printed in
|
* Give those symbols a chance to be printed in
|
||||||
@ -123,7 +126,11 @@ int kernel_text_address(unsigned long addr)
|
|||||||
return 1;
|
return 1;
|
||||||
if (is_module_text_address(addr))
|
if (is_module_text_address(addr))
|
||||||
return 1;
|
return 1;
|
||||||
return is_ftrace_trampoline(addr);
|
if (is_ftrace_trampoline(addr))
|
||||||
|
return 1;
|
||||||
|
if (is_kprobe_optinsn_slot(addr) || is_kprobe_insn_slot(addr))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -149,9 +149,11 @@ kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c)
|
|||||||
struct kprobe_insn_page *kip;
|
struct kprobe_insn_page *kip;
|
||||||
kprobe_opcode_t *slot = NULL;
|
kprobe_opcode_t *slot = NULL;
|
||||||
|
|
||||||
|
/* Since the slot array is not protected by rcu, we need a mutex */
|
||||||
mutex_lock(&c->mutex);
|
mutex_lock(&c->mutex);
|
||||||
retry:
|
retry:
|
||||||
list_for_each_entry(kip, &c->pages, list) {
|
rcu_read_lock();
|
||||||
|
list_for_each_entry_rcu(kip, &c->pages, list) {
|
||||||
if (kip->nused < slots_per_page(c)) {
|
if (kip->nused < slots_per_page(c)) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < slots_per_page(c); i++) {
|
for (i = 0; i < slots_per_page(c); i++) {
|
||||||
@ -159,6 +161,7 @@ kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c)
|
|||||||
kip->slot_used[i] = SLOT_USED;
|
kip->slot_used[i] = SLOT_USED;
|
||||||
kip->nused++;
|
kip->nused++;
|
||||||
slot = kip->insns + (i * c->insn_size);
|
slot = kip->insns + (i * c->insn_size);
|
||||||
|
rcu_read_unlock();
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,6 +170,7 @@ kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c)
|
|||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
/* If there are any garbage slots, collect it and try again. */
|
/* If there are any garbage slots, collect it and try again. */
|
||||||
if (c->nr_garbage && collect_garbage_slots(c) == 0)
|
if (c->nr_garbage && collect_garbage_slots(c) == 0)
|
||||||
@ -193,7 +197,7 @@ kprobe_opcode_t *__get_insn_slot(struct kprobe_insn_cache *c)
|
|||||||
kip->nused = 1;
|
kip->nused = 1;
|
||||||
kip->ngarbage = 0;
|
kip->ngarbage = 0;
|
||||||
kip->cache = c;
|
kip->cache = c;
|
||||||
list_add(&kip->list, &c->pages);
|
list_add_rcu(&kip->list, &c->pages);
|
||||||
slot = kip->insns;
|
slot = kip->insns;
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&c->mutex);
|
mutex_unlock(&c->mutex);
|
||||||
@ -213,7 +217,8 @@ static int collect_one_slot(struct kprobe_insn_page *kip, int idx)
|
|||||||
* next time somebody inserts a probe.
|
* next time somebody inserts a probe.
|
||||||
*/
|
*/
|
||||||
if (!list_is_singular(&kip->list)) {
|
if (!list_is_singular(&kip->list)) {
|
||||||
list_del(&kip->list);
|
list_del_rcu(&kip->list);
|
||||||
|
synchronize_rcu();
|
||||||
kip->cache->free(kip->insns);
|
kip->cache->free(kip->insns);
|
||||||
kfree(kip);
|
kfree(kip);
|
||||||
}
|
}
|
||||||
@ -235,8 +240,7 @@ static int collect_garbage_slots(struct kprobe_insn_cache *c)
|
|||||||
continue;
|
continue;
|
||||||
kip->ngarbage = 0; /* we will collect all garbages */
|
kip->ngarbage = 0; /* we will collect all garbages */
|
||||||
for (i = 0; i < slots_per_page(c); i++) {
|
for (i = 0; i < slots_per_page(c); i++) {
|
||||||
if (kip->slot_used[i] == SLOT_DIRTY &&
|
if (kip->slot_used[i] == SLOT_DIRTY && collect_one_slot(kip, i))
|
||||||
collect_one_slot(kip, i))
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,29 +252,60 @@ void __free_insn_slot(struct kprobe_insn_cache *c,
|
|||||||
kprobe_opcode_t *slot, int dirty)
|
kprobe_opcode_t *slot, int dirty)
|
||||||
{
|
{
|
||||||
struct kprobe_insn_page *kip;
|
struct kprobe_insn_page *kip;
|
||||||
|
long idx;
|
||||||
|
|
||||||
mutex_lock(&c->mutex);
|
mutex_lock(&c->mutex);
|
||||||
list_for_each_entry(kip, &c->pages, list) {
|
rcu_read_lock();
|
||||||
long idx = ((long)slot - (long)kip->insns) /
|
list_for_each_entry_rcu(kip, &c->pages, list) {
|
||||||
(c->insn_size * sizeof(kprobe_opcode_t));
|
idx = ((long)slot - (long)kip->insns) /
|
||||||
if (idx >= 0 && idx < slots_per_page(c)) {
|
(c->insn_size * sizeof(kprobe_opcode_t));
|
||||||
WARN_ON(kip->slot_used[idx] != SLOT_USED);
|
if (idx >= 0 && idx < slots_per_page(c))
|
||||||
if (dirty) {
|
|
||||||
kip->slot_used[idx] = SLOT_DIRTY;
|
|
||||||
kip->ngarbage++;
|
|
||||||
if (++c->nr_garbage > slots_per_page(c))
|
|
||||||
collect_garbage_slots(c);
|
|
||||||
} else
|
|
||||||
collect_one_slot(kip, idx);
|
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
/* Could not find this slot. */
|
||||||
|
WARN_ON(1);
|
||||||
|
kip = NULL;
|
||||||
|
out:
|
||||||
|
rcu_read_unlock();
|
||||||
|
/* Mark and sweep: this may sleep */
|
||||||
|
if (kip) {
|
||||||
|
/* Check double free */
|
||||||
|
WARN_ON(kip->slot_used[idx] != SLOT_USED);
|
||||||
|
if (dirty) {
|
||||||
|
kip->slot_used[idx] = SLOT_DIRTY;
|
||||||
|
kip->ngarbage++;
|
||||||
|
if (++c->nr_garbage > slots_per_page(c))
|
||||||
|
collect_garbage_slots(c);
|
||||||
|
} else {
|
||||||
|
collect_one_slot(kip, idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Could not free this slot. */
|
|
||||||
WARN_ON(1);
|
|
||||||
out:
|
|
||||||
mutex_unlock(&c->mutex);
|
mutex_unlock(&c->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check given address is on the page of kprobe instruction slots.
|
||||||
|
* This will be used for checking whether the address on a stack
|
||||||
|
* is on a text area or not.
|
||||||
|
*/
|
||||||
|
bool __is_insn_slot_addr(struct kprobe_insn_cache *c, unsigned long addr)
|
||||||
|
{
|
||||||
|
struct kprobe_insn_page *kip;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
list_for_each_entry_rcu(kip, &c->pages, list) {
|
||||||
|
if (addr >= (unsigned long)kip->insns &&
|
||||||
|
addr < (unsigned long)kip->insns + PAGE_SIZE) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OPTPROBES
|
#ifdef CONFIG_OPTPROBES
|
||||||
/* For optimized_kprobe buffer */
|
/* For optimized_kprobe buffer */
|
||||||
struct kprobe_insn_cache kprobe_optinsn_slots = {
|
struct kprobe_insn_cache kprobe_optinsn_slots = {
|
||||||
|
@ -277,6 +277,11 @@ int load_bpf_file(char *path)
|
|||||||
Elf_Data *data, *data_prog, *symbols = NULL;
|
Elf_Data *data, *data_prog, *symbols = NULL;
|
||||||
char *shname, *shname_prog;
|
char *shname, *shname_prog;
|
||||||
|
|
||||||
|
/* reset global variables */
|
||||||
|
kern_version = 0;
|
||||||
|
memset(license, 0, sizeof(license));
|
||||||
|
memset(processed_sec, 0, sizeof(processed_sec));
|
||||||
|
|
||||||
if (elf_version(EV_CURRENT) == EV_NONE)
|
if (elf_version(EV_CURRENT) == EV_NONE)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -328,6 +333,8 @@ int load_bpf_file(char *path)
|
|||||||
|
|
||||||
/* load programs that need map fixup (relocations) */
|
/* load programs that need map fixup (relocations) */
|
||||||
for (i = 1; i < ehdr.e_shnum; i++) {
|
for (i = 1; i < ehdr.e_shnum; i++) {
|
||||||
|
if (processed_sec[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
if (get_sec(elf, i, &ehdr, &shname, &shdr, &data))
|
if (get_sec(elf, i, &ehdr, &shname, &shdr, &data))
|
||||||
continue;
|
continue;
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
#include <uapi/linux/bpf.h>
|
#include <uapi/linux/bpf.h>
|
||||||
#include <uapi/linux/seccomp.h>
|
#include <uapi/linux/seccomp.h>
|
||||||
|
#include <uapi/linux/unistd.h>
|
||||||
#include "bpf_helpers.h"
|
#include "bpf_helpers.h"
|
||||||
|
|
||||||
#define PROG(F) SEC("kprobe/"__stringify(F)) int bpf_func_##F
|
#define PROG(F) SEC("kprobe/"__stringify(F)) int bpf_func_##F
|
||||||
|
@ -84,6 +84,15 @@ struct kvm_regs {
|
|||||||
#define KVM_VGIC_V2_DIST_SIZE 0x1000
|
#define KVM_VGIC_V2_DIST_SIZE 0x1000
|
||||||
#define KVM_VGIC_V2_CPU_SIZE 0x2000
|
#define KVM_VGIC_V2_CPU_SIZE 0x2000
|
||||||
|
|
||||||
|
/* Supported VGICv3 address types */
|
||||||
|
#define KVM_VGIC_V3_ADDR_TYPE_DIST 2
|
||||||
|
#define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
|
||||||
|
#define KVM_VGIC_ITS_ADDR_TYPE 4
|
||||||
|
|
||||||
|
#define KVM_VGIC_V3_DIST_SIZE SZ_64K
|
||||||
|
#define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
|
||||||
|
#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
|
||||||
|
|
||||||
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
|
#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
|
||||||
#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
|
#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
|
||||||
|
|
||||||
|
@ -573,6 +573,10 @@ struct kvm_get_htab_header {
|
|||||||
#define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
|
#define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
|
||||||
#define KVM_REG_PPC_DBSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbb)
|
#define KVM_REG_PPC_DBSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbb)
|
||||||
|
|
||||||
|
/* POWER9 registers */
|
||||||
|
#define KVM_REG_PPC_TIDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc)
|
||||||
|
#define KVM_REG_PPC_PSSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd)
|
||||||
|
|
||||||
/* Transactional Memory checkpointed state:
|
/* Transactional Memory checkpointed state:
|
||||||
* This is all GPRs, all VSX regs and a subset of SPRs
|
* This is all GPRs, all VSX regs and a subset of SPRs
|
||||||
*/
|
*/
|
||||||
@ -596,6 +600,7 @@ struct kvm_get_htab_header {
|
|||||||
#define KVM_REG_PPC_TM_VSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U32 | 0x67)
|
#define KVM_REG_PPC_TM_VSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U32 | 0x67)
|
||||||
#define KVM_REG_PPC_TM_DSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x68)
|
#define KVM_REG_PPC_TM_DSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x68)
|
||||||
#define KVM_REG_PPC_TM_TAR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x69)
|
#define KVM_REG_PPC_TM_TAR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x69)
|
||||||
|
#define KVM_REG_PPC_TM_XER (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x6a)
|
||||||
|
|
||||||
/* PPC64 eXternal Interrupt Controller Specification */
|
/* PPC64 eXternal Interrupt Controller Specification */
|
||||||
#define KVM_DEV_XICS_GRP_SOURCES 1 /* 64-bit source attributes */
|
#define KVM_DEV_XICS_GRP_SOURCES 1 /* 64-bit source attributes */
|
||||||
|
@ -105,6 +105,7 @@
|
|||||||
#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */
|
#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */
|
||||||
#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
|
#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
|
||||||
#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */
|
#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */
|
||||||
|
#define X86_FEATURE_TSC_KNOWN_FREQ ( 3*32+31) /* TSC has known frequency */
|
||||||
|
|
||||||
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
|
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
|
||||||
#define X86_FEATURE_XMM3 ( 4*32+ 0) /* "pni" SSE-3 */
|
#define X86_FEATURE_XMM3 ( 4*32+ 0) /* "pni" SSE-3 */
|
||||||
@ -188,10 +189,14 @@
|
|||||||
|
|
||||||
#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */
|
#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */
|
||||||
#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
|
#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
|
||||||
|
#define X86_FEATURE_CAT_L3 ( 7*32+ 4) /* Cache Allocation Technology L3 */
|
||||||
|
#define X86_FEATURE_CAT_L2 ( 7*32+ 5) /* Cache Allocation Technology L2 */
|
||||||
|
#define X86_FEATURE_CDP_L3 ( 7*32+ 6) /* Code and Data Prioritization L3 */
|
||||||
|
|
||||||
#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
|
#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
|
||||||
#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
|
#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
|
||||||
|
|
||||||
|
#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */
|
||||||
#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */
|
#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */
|
||||||
#define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */
|
#define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */
|
||||||
#define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */
|
#define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */
|
||||||
@ -220,11 +225,13 @@
|
|||||||
#define X86_FEATURE_RTM ( 9*32+11) /* Restricted Transactional Memory */
|
#define X86_FEATURE_RTM ( 9*32+11) /* Restricted Transactional Memory */
|
||||||
#define X86_FEATURE_CQM ( 9*32+12) /* Cache QoS Monitoring */
|
#define X86_FEATURE_CQM ( 9*32+12) /* Cache QoS Monitoring */
|
||||||
#define X86_FEATURE_MPX ( 9*32+14) /* Memory Protection Extension */
|
#define X86_FEATURE_MPX ( 9*32+14) /* Memory Protection Extension */
|
||||||
|
#define X86_FEATURE_RDT_A ( 9*32+15) /* Resource Director Technology Allocation */
|
||||||
#define X86_FEATURE_AVX512F ( 9*32+16) /* AVX-512 Foundation */
|
#define X86_FEATURE_AVX512F ( 9*32+16) /* AVX-512 Foundation */
|
||||||
#define X86_FEATURE_AVX512DQ ( 9*32+17) /* AVX-512 DQ (Double/Quad granular) Instructions */
|
#define X86_FEATURE_AVX512DQ ( 9*32+17) /* AVX-512 DQ (Double/Quad granular) Instructions */
|
||||||
#define X86_FEATURE_RDSEED ( 9*32+18) /* The RDSEED instruction */
|
#define X86_FEATURE_RDSEED ( 9*32+18) /* The RDSEED instruction */
|
||||||
#define X86_FEATURE_ADX ( 9*32+19) /* The ADCX and ADOX instructions */
|
#define X86_FEATURE_ADX ( 9*32+19) /* The ADCX and ADOX instructions */
|
||||||
#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */
|
#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */
|
||||||
|
#define X86_FEATURE_AVX512IFMA ( 9*32+21) /* AVX-512 Integer Fused Multiply-Add instructions */
|
||||||
#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
|
#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
|
||||||
#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */
|
#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */
|
||||||
#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */
|
#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */
|
||||||
@ -278,8 +285,10 @@
|
|||||||
#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */
|
#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */
|
||||||
|
|
||||||
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
|
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
|
||||||
|
#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
|
||||||
#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */
|
#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */
|
||||||
#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */
|
#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */
|
||||||
|
#define X86_FEATURE_RDPID (16*32+ 22) /* RDPID instruction */
|
||||||
|
|
||||||
/* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */
|
/* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */
|
||||||
#define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */
|
#define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */
|
||||||
@ -310,4 +319,6 @@
|
|||||||
#define X86_BUG_NULL_SEG X86_BUG(10) /* Nulling a selector preserves the base */
|
#define X86_BUG_NULL_SEG X86_BUG(10) /* Nulling a selector preserves the base */
|
||||||
#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */
|
#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */
|
||||||
#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */
|
#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */
|
||||||
|
#define X86_BUG_AMD_E400 X86_BUG(13) /* CPU is among the affected by Erratum 400 */
|
||||||
|
|
||||||
#endif /* _ASM_X86_CPUFEATURES_H */
|
#endif /* _ASM_X86_CPUFEATURES_H */
|
||||||
|
@ -65,6 +65,8 @@
|
|||||||
#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
|
#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
|
||||||
#define EXIT_REASON_APIC_ACCESS 44
|
#define EXIT_REASON_APIC_ACCESS 44
|
||||||
#define EXIT_REASON_EOI_INDUCED 45
|
#define EXIT_REASON_EOI_INDUCED 45
|
||||||
|
#define EXIT_REASON_GDTR_IDTR 46
|
||||||
|
#define EXIT_REASON_LDTR_TR 47
|
||||||
#define EXIT_REASON_EPT_VIOLATION 48
|
#define EXIT_REASON_EPT_VIOLATION 48
|
||||||
#define EXIT_REASON_EPT_MISCONFIG 49
|
#define EXIT_REASON_EPT_MISCONFIG 49
|
||||||
#define EXIT_REASON_INVEPT 50
|
#define EXIT_REASON_INVEPT 50
|
||||||
@ -113,6 +115,8 @@
|
|||||||
{ EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
|
{ EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
|
||||||
{ EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
|
{ EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
|
||||||
{ EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
|
{ EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
|
||||||
|
{ EXIT_REASON_GDTR_IDTR, "GDTR_IDTR" }, \
|
||||||
|
{ EXIT_REASON_LDTR_TR, "LDTR_TR" }, \
|
||||||
{ EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
|
{ EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
|
||||||
{ EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
|
{ EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
|
||||||
{ EXIT_REASON_INVEPT, "INVEPT" }, \
|
{ EXIT_REASON_INVEPT, "INVEPT" }, \
|
||||||
@ -129,6 +133,7 @@
|
|||||||
{ EXIT_REASON_XRSTORS, "XRSTORS" }
|
{ EXIT_REASON_XRSTORS, "XRSTORS" }
|
||||||
|
|
||||||
#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1
|
#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1
|
||||||
|
#define VMX_ABORT_LOAD_HOST_PDPTE_FAIL 2
|
||||||
#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4
|
#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4
|
||||||
|
|
||||||
#endif /* _UAPIVMX_H */
|
#endif /* _UAPIVMX_H */
|
||||||
|
@ -19,6 +19,16 @@ else
|
|||||||
Q=@
|
Q=@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4
|
||||||
|
ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)
|
||||||
|
quiet=silent_
|
||||||
|
endif
|
||||||
|
else # make-3.8x
|
||||||
|
ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
|
||||||
|
quiet=silent_
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
build-dir := $(srctree)/tools/build
|
build-dir := $(srctree)/tools/build
|
||||||
|
|
||||||
# Define $(fixdep) for dep-cmd function
|
# Define $(fixdep) for dep-cmd function
|
||||||
|
14
tools/include/linux/compiler-gcc.h
Normal file
14
tools/include/linux/compiler-gcc.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _TOOLS_LINUX_COMPILER_H_
|
||||||
|
#error "Please don't include <linux/compiler-gcc.h> directly, include <linux/compiler.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Common definitions for all gcc versions go here.
|
||||||
|
*/
|
||||||
|
#define GCC_VERSION (__GNUC__ * 10000 \
|
||||||
|
+ __GNUC_MINOR__ * 100 \
|
||||||
|
+ __GNUC_PATCHLEVEL__)
|
||||||
|
|
||||||
|
#if GCC_VERSION >= 70000 && !defined(__CHECKER__)
|
||||||
|
# define __fallthrough __attribute__ ((fallthrough))
|
||||||
|
#endif
|
@ -1,6 +1,10 @@
|
|||||||
#ifndef _TOOLS_LINUX_COMPILER_H_
|
#ifndef _TOOLS_LINUX_COMPILER_H_
|
||||||
#define _TOOLS_LINUX_COMPILER_H_
|
#define _TOOLS_LINUX_COMPILER_H_
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#include <linux/compiler-gcc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Optimization barrier */
|
/* Optimization barrier */
|
||||||
/* The "volatile" is due to gcc bugs */
|
/* The "volatile" is due to gcc bugs */
|
||||||
#define barrier() __asm__ __volatile__("": : :"memory")
|
#define barrier() __asm__ __volatile__("": : :"memory")
|
||||||
@ -126,4 +130,9 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
|
|||||||
#define WRITE_ONCE(x, val) \
|
#define WRITE_ONCE(x, val) \
|
||||||
({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
|
({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __fallthrough
|
||||||
|
# define __fallthrough
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _TOOLS_LINUX_COMPILER_H */
|
#endif /* _TOOLS_LINUX_COMPILER_H */
|
||||||
|
@ -17,7 +17,13 @@ MAKEFLAGS += --no-print-directory
|
|||||||
LIBFILE = $(OUTPUT)libapi.a
|
LIBFILE = $(OUTPUT)libapi.a
|
||||||
|
|
||||||
CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
|
CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
|
||||||
CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
|
CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
|
||||||
|
|
||||||
|
ifeq ($(CC), clang)
|
||||||
|
CFLAGS += -O3
|
||||||
|
else
|
||||||
|
CFLAGS += -O6
|
||||||
|
endif
|
||||||
|
|
||||||
# Treat warnings as errors unless directed not to
|
# Treat warnings as errors unless directed not to
|
||||||
ifneq ($(WERROR),0)
|
ifneq ($(WERROR),0)
|
||||||
|
@ -38,6 +38,10 @@
|
|||||||
#define HUGETLBFS_MAGIC 0x958458f6
|
#define HUGETLBFS_MAGIC 0x958458f6
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BPF_FS_MAGIC
|
||||||
|
#define BPF_FS_MAGIC 0xcafe4a11
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char * const sysfs__fs_known_mountpoints[] = {
|
static const char * const sysfs__fs_known_mountpoints[] = {
|
||||||
"/sys",
|
"/sys",
|
||||||
0,
|
0,
|
||||||
@ -75,6 +79,11 @@ static const char * const hugetlbfs__known_mountpoints[] = {
|
|||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char * const bpf_fs__known_mountpoints[] = {
|
||||||
|
"/sys/fs/bpf",
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
struct fs {
|
struct fs {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char * const *mounts;
|
const char * const *mounts;
|
||||||
@ -89,6 +98,7 @@ enum {
|
|||||||
FS__DEBUGFS = 2,
|
FS__DEBUGFS = 2,
|
||||||
FS__TRACEFS = 3,
|
FS__TRACEFS = 3,
|
||||||
FS__HUGETLBFS = 4,
|
FS__HUGETLBFS = 4,
|
||||||
|
FS__BPF_FS = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef TRACEFS_MAGIC
|
#ifndef TRACEFS_MAGIC
|
||||||
@ -121,6 +131,11 @@ static struct fs fs__entries[] = {
|
|||||||
.mounts = hugetlbfs__known_mountpoints,
|
.mounts = hugetlbfs__known_mountpoints,
|
||||||
.magic = HUGETLBFS_MAGIC,
|
.magic = HUGETLBFS_MAGIC,
|
||||||
},
|
},
|
||||||
|
[FS__BPF_FS] = {
|
||||||
|
.name = "bpf",
|
||||||
|
.mounts = bpf_fs__known_mountpoints,
|
||||||
|
.magic = BPF_FS_MAGIC,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool fs__read_mounts(struct fs *fs)
|
static bool fs__read_mounts(struct fs *fs)
|
||||||
@ -280,6 +295,7 @@ FS(procfs, FS__PROCFS);
|
|||||||
FS(debugfs, FS__DEBUGFS);
|
FS(debugfs, FS__DEBUGFS);
|
||||||
FS(tracefs, FS__TRACEFS);
|
FS(tracefs, FS__TRACEFS);
|
||||||
FS(hugetlbfs, FS__HUGETLBFS);
|
FS(hugetlbfs, FS__HUGETLBFS);
|
||||||
|
FS(bpf_fs, FS__BPF_FS);
|
||||||
|
|
||||||
int filename__read_int(const char *filename, int *value)
|
int filename__read_int(const char *filename, int *value)
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,7 @@ FS(procfs)
|
|||||||
FS(debugfs)
|
FS(debugfs)
|
||||||
FS(tracefs)
|
FS(tracefs)
|
||||||
FS(hugetlbfs)
|
FS(hugetlbfs)
|
||||||
|
FS(bpf_fs)
|
||||||
|
|
||||||
#undef FS
|
#undef FS
|
||||||
|
|
||||||
|
@ -86,9 +86,13 @@ void put_tracing_file(char *file)
|
|||||||
free(file);
|
free(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int strerror_open(int err, char *buf, size_t size, const char *filename)
|
int tracing_path__strerror_open_tp(int err, char *buf, size_t size,
|
||||||
|
const char *sys, const char *name)
|
||||||
{
|
{
|
||||||
char sbuf[128];
|
char sbuf[128];
|
||||||
|
char filename[PATH_MAX];
|
||||||
|
|
||||||
|
snprintf(filename, PATH_MAX, "%s/%s", sys, name ?: "*");
|
||||||
|
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
@ -99,10 +103,19 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
|
|||||||
* - jirka
|
* - jirka
|
||||||
*/
|
*/
|
||||||
if (debugfs__configured() || tracefs__configured()) {
|
if (debugfs__configured() || tracefs__configured()) {
|
||||||
snprintf(buf, size,
|
/* sdt markers */
|
||||||
"Error:\tFile %s/%s not found.\n"
|
if (!strncmp(filename, "sdt_", 4)) {
|
||||||
"Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
|
snprintf(buf, size,
|
||||||
tracing_events_path, filename);
|
"Error:\tFile %s/%s not found.\n"
|
||||||
|
"Hint:\tSDT event cannot be directly recorded on.\n"
|
||||||
|
"\tPlease first use 'perf probe %s:%s' before recording it.\n",
|
||||||
|
tracing_events_path, filename, sys, name);
|
||||||
|
} else {
|
||||||
|
snprintf(buf, size,
|
||||||
|
"Error:\tFile %s/%s not found.\n"
|
||||||
|
"Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
|
||||||
|
tracing_events_path, filename);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
snprintf(buf, size, "%s",
|
snprintf(buf, size, "%s",
|
||||||
@ -125,12 +138,3 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tracing_path__strerror_open_tp(int err, char *buf, size_t size, const char *sys, const char *name)
|
|
||||||
{
|
|
||||||
char path[PATH_MAX];
|
|
||||||
|
|
||||||
snprintf(path, PATH_MAX, "%s/%s", sys, name ?: "*");
|
|
||||||
|
|
||||||
return strerror_open(err, buf, size, path);
|
|
||||||
}
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#define __BPF_BPF_H
|
#define __BPF_BPF_H
|
||||||
|
|
||||||
#include <linux/bpf.h>
|
#include <linux/bpf.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
|
int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
|
||||||
int max_entries, __u32 map_flags);
|
int max_entries, __u32 map_flags);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
* Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
|
* Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
|
||||||
* Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
|
* Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
|
||||||
* Copyright (C) 2015 Huawei Inc.
|
* Copyright (C) 2015 Huawei Inc.
|
||||||
|
* Copyright (C) 2017 Nicira, Inc.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -22,15 +23,21 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
|
#include <linux/err.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/bpf.h>
|
#include <linux/bpf.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
#include <linux/limits.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/vfs.h>
|
||||||
#include <libelf.h>
|
#include <libelf.h>
|
||||||
#include <gelf.h>
|
#include <gelf.h>
|
||||||
|
|
||||||
@ -41,6 +48,10 @@
|
|||||||
#define EM_BPF 247
|
#define EM_BPF 247
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BPF_FS_MAGIC
|
||||||
|
#define BPF_FS_MAGIC 0xcafe4a11
|
||||||
|
#endif
|
||||||
|
|
||||||
#define __printf(a, b) __attribute__((format(printf, a, b)))
|
#define __printf(a, b) __attribute__((format(printf, a, b)))
|
||||||
|
|
||||||
__printf(1, 2)
|
__printf(1, 2)
|
||||||
@ -779,7 +790,7 @@ static int
|
|||||||
bpf_program__collect_reloc(struct bpf_program *prog,
|
bpf_program__collect_reloc(struct bpf_program *prog,
|
||||||
size_t nr_maps, GElf_Shdr *shdr,
|
size_t nr_maps, GElf_Shdr *shdr,
|
||||||
Elf_Data *data, Elf_Data *symbols,
|
Elf_Data *data, Elf_Data *symbols,
|
||||||
int maps_shndx)
|
int maps_shndx, struct bpf_map *maps)
|
||||||
{
|
{
|
||||||
int i, nrels;
|
int i, nrels;
|
||||||
|
|
||||||
@ -829,7 +840,15 @@ bpf_program__collect_reloc(struct bpf_program *prog,
|
|||||||
return -LIBBPF_ERRNO__RELOC;
|
return -LIBBPF_ERRNO__RELOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
map_idx = sym.st_value / sizeof(struct bpf_map_def);
|
/* TODO: 'maps' is sorted. We can use bsearch to make it faster. */
|
||||||
|
for (map_idx = 0; map_idx < nr_maps; map_idx++) {
|
||||||
|
if (maps[map_idx].offset == sym.st_value) {
|
||||||
|
pr_debug("relocation: find map %zd (%s) for insn %u\n",
|
||||||
|
map_idx, maps[map_idx].name, insn_idx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (map_idx >= nr_maps) {
|
if (map_idx >= nr_maps) {
|
||||||
pr_warning("bpf relocation: map_idx %d large than %d\n",
|
pr_warning("bpf relocation: map_idx %d large than %d\n",
|
||||||
(int)map_idx, (int)nr_maps - 1);
|
(int)map_idx, (int)nr_maps - 1);
|
||||||
@ -953,7 +972,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
|
|||||||
err = bpf_program__collect_reloc(prog, nr_maps,
|
err = bpf_program__collect_reloc(prog, nr_maps,
|
||||||
shdr, data,
|
shdr, data,
|
||||||
obj->efile.symbols,
|
obj->efile.symbols,
|
||||||
obj->efile.maps_shndx);
|
obj->efile.maps_shndx,
|
||||||
|
obj->maps);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1227,6 +1247,191 @@ out:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_path(const char *path)
|
||||||
|
{
|
||||||
|
struct statfs st_fs;
|
||||||
|
char *dname, *dir;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (path == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
dname = strdup(path);
|
||||||
|
if (dname == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dir = dirname(dname);
|
||||||
|
if (statfs(dir, &st_fs)) {
|
||||||
|
pr_warning("failed to statfs %s: %s\n", dir, strerror(errno));
|
||||||
|
err = -errno;
|
||||||
|
}
|
||||||
|
free(dname);
|
||||||
|
|
||||||
|
if (!err && st_fs.f_type != BPF_FS_MAGIC) {
|
||||||
|
pr_warning("specified path %s is not on BPF FS\n", path);
|
||||||
|
err = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_program__pin_instance(struct bpf_program *prog, const char *path,
|
||||||
|
int instance)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = check_path(path);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (prog == NULL) {
|
||||||
|
pr_warning("invalid program pointer\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance < 0 || instance >= prog->instances.nr) {
|
||||||
|
pr_warning("invalid prog instance %d of prog %s (max %d)\n",
|
||||||
|
instance, prog->section_name, prog->instances.nr);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bpf_obj_pin(prog->instances.fds[instance], path)) {
|
||||||
|
pr_warning("failed to pin program: %s\n", strerror(errno));
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
pr_debug("pinned program '%s'\n", path);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int make_dir(const char *path)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (mkdir(path, 0700) && errno != EEXIST)
|
||||||
|
err = -errno;
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
pr_warning("failed to mkdir %s: %s\n", path, strerror(-err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_program__pin(struct bpf_program *prog, const char *path)
|
||||||
|
{
|
||||||
|
int i, err;
|
||||||
|
|
||||||
|
err = check_path(path);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (prog == NULL) {
|
||||||
|
pr_warning("invalid program pointer\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prog->instances.nr <= 0) {
|
||||||
|
pr_warning("no instances of prog %s to pin\n",
|
||||||
|
prog->section_name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = make_dir(path);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
for (i = 0; i < prog->instances.nr; i++) {
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = snprintf(buf, PATH_MAX, "%s/%d", path, i);
|
||||||
|
if (len < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
else if (len >= PATH_MAX)
|
||||||
|
return -ENAMETOOLONG;
|
||||||
|
|
||||||
|
err = bpf_program__pin_instance(prog, buf, i);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_map__pin(struct bpf_map *map, const char *path)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = check_path(path);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (map == NULL) {
|
||||||
|
pr_warning("invalid map pointer\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bpf_obj_pin(map->fd, path)) {
|
||||||
|
pr_warning("failed to pin map: %s\n", strerror(errno));
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("pinned map '%s'\n", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_object__pin(struct bpf_object *obj, const char *path)
|
||||||
|
{
|
||||||
|
struct bpf_program *prog;
|
||||||
|
struct bpf_map *map;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!obj)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
if (!obj->loaded) {
|
||||||
|
pr_warning("object not yet loaded; load it first\n");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = make_dir(path);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
bpf_map__for_each(map, obj) {
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = snprintf(buf, PATH_MAX, "%s/%s", path,
|
||||||
|
bpf_map__name(map));
|
||||||
|
if (len < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
else if (len >= PATH_MAX)
|
||||||
|
return -ENAMETOOLONG;
|
||||||
|
|
||||||
|
err = bpf_map__pin(map, buf);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
bpf_object__for_each_program(prog, obj) {
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = snprintf(buf, PATH_MAX, "%s/%s", path,
|
||||||
|
prog->section_name);
|
||||||
|
if (len < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
else if (len >= PATH_MAX)
|
||||||
|
return -ENAMETOOLONG;
|
||||||
|
|
||||||
|
err = bpf_program__pin(prog, buf);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void bpf_object__close(struct bpf_object *obj)
|
void bpf_object__close(struct bpf_object *obj)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
@ -1419,37 +1624,33 @@ static void bpf_program__set_type(struct bpf_program *prog,
|
|||||||
prog->type = type;
|
prog->type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpf_program__set_tracepoint(struct bpf_program *prog)
|
|
||||||
{
|
|
||||||
if (!prog)
|
|
||||||
return -EINVAL;
|
|
||||||
bpf_program__set_type(prog, BPF_PROG_TYPE_TRACEPOINT);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int bpf_program__set_kprobe(struct bpf_program *prog)
|
|
||||||
{
|
|
||||||
if (!prog)
|
|
||||||
return -EINVAL;
|
|
||||||
bpf_program__set_type(prog, BPF_PROG_TYPE_KPROBE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool bpf_program__is_type(struct bpf_program *prog,
|
static bool bpf_program__is_type(struct bpf_program *prog,
|
||||||
enum bpf_prog_type type)
|
enum bpf_prog_type type)
|
||||||
{
|
{
|
||||||
return prog ? (prog->type == type) : false;
|
return prog ? (prog->type == type) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bpf_program__is_tracepoint(struct bpf_program *prog)
|
#define BPF_PROG_TYPE_FNS(NAME, TYPE) \
|
||||||
{
|
int bpf_program__set_##NAME(struct bpf_program *prog) \
|
||||||
return bpf_program__is_type(prog, BPF_PROG_TYPE_TRACEPOINT);
|
{ \
|
||||||
}
|
if (!prog) \
|
||||||
|
return -EINVAL; \
|
||||||
|
bpf_program__set_type(prog, TYPE); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
bool bpf_program__is_##NAME(struct bpf_program *prog) \
|
||||||
|
{ \
|
||||||
|
return bpf_program__is_type(prog, TYPE); \
|
||||||
|
} \
|
||||||
|
|
||||||
bool bpf_program__is_kprobe(struct bpf_program *prog)
|
BPF_PROG_TYPE_FNS(socket_filter, BPF_PROG_TYPE_SOCKET_FILTER);
|
||||||
{
|
BPF_PROG_TYPE_FNS(kprobe, BPF_PROG_TYPE_KPROBE);
|
||||||
return bpf_program__is_type(prog, BPF_PROG_TYPE_KPROBE);
|
BPF_PROG_TYPE_FNS(sched_cls, BPF_PROG_TYPE_SCHED_CLS);
|
||||||
}
|
BPF_PROG_TYPE_FNS(sched_act, BPF_PROG_TYPE_SCHED_ACT);
|
||||||
|
BPF_PROG_TYPE_FNS(tracepoint, BPF_PROG_TYPE_TRACEPOINT);
|
||||||
|
BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP);
|
||||||
|
BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT);
|
||||||
|
|
||||||
int bpf_map__fd(struct bpf_map *map)
|
int bpf_map__fd(struct bpf_map *map)
|
||||||
{
|
{
|
||||||
@ -1537,3 +1738,10 @@ bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset)
|
|||||||
}
|
}
|
||||||
return ERR_PTR(-ENOENT);
|
return ERR_PTR(-ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long libbpf_get_error(const void *ptr)
|
||||||
|
{
|
||||||
|
if (IS_ERR(ptr))
|
||||||
|
return PTR_ERR(ptr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#define __BPF_LIBBPF_H
|
#define __BPF_LIBBPF_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <linux/err.h>
|
|
||||||
#include <sys/types.h> // for size_t
|
#include <sys/types.h> // for size_t
|
||||||
|
|
||||||
enum libbpf_errno {
|
enum libbpf_errno {
|
||||||
@ -65,6 +65,7 @@ struct bpf_object *bpf_object__open(const char *path);
|
|||||||
struct bpf_object *bpf_object__open_buffer(void *obj_buf,
|
struct bpf_object *bpf_object__open_buffer(void *obj_buf,
|
||||||
size_t obj_buf_sz,
|
size_t obj_buf_sz,
|
||||||
const char *name);
|
const char *name);
|
||||||
|
int bpf_object__pin(struct bpf_object *object, const char *path);
|
||||||
void bpf_object__close(struct bpf_object *object);
|
void bpf_object__close(struct bpf_object *object);
|
||||||
|
|
||||||
/* Load/unload object into/from kernel */
|
/* Load/unload object into/from kernel */
|
||||||
@ -106,6 +107,9 @@ void *bpf_program__priv(struct bpf_program *prog);
|
|||||||
const char *bpf_program__title(struct bpf_program *prog, bool needs_copy);
|
const char *bpf_program__title(struct bpf_program *prog, bool needs_copy);
|
||||||
|
|
||||||
int bpf_program__fd(struct bpf_program *prog);
|
int bpf_program__fd(struct bpf_program *prog);
|
||||||
|
int bpf_program__pin_instance(struct bpf_program *prog, const char *path,
|
||||||
|
int instance);
|
||||||
|
int bpf_program__pin(struct bpf_program *prog, const char *path);
|
||||||
|
|
||||||
struct bpf_insn;
|
struct bpf_insn;
|
||||||
|
|
||||||
@ -174,11 +178,21 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n);
|
|||||||
/*
|
/*
|
||||||
* Adjust type of bpf program. Default is kprobe.
|
* Adjust type of bpf program. Default is kprobe.
|
||||||
*/
|
*/
|
||||||
|
int bpf_program__set_socket_filter(struct bpf_program *prog);
|
||||||
int bpf_program__set_tracepoint(struct bpf_program *prog);
|
int bpf_program__set_tracepoint(struct bpf_program *prog);
|
||||||
int bpf_program__set_kprobe(struct bpf_program *prog);
|
int bpf_program__set_kprobe(struct bpf_program *prog);
|
||||||
|
int bpf_program__set_sched_cls(struct bpf_program *prog);
|
||||||
|
int bpf_program__set_sched_act(struct bpf_program *prog);
|
||||||
|
int bpf_program__set_xdp(struct bpf_program *prog);
|
||||||
|
int bpf_program__set_perf_event(struct bpf_program *prog);
|
||||||
|
|
||||||
|
bool bpf_program__is_socket_filter(struct bpf_program *prog);
|
||||||
bool bpf_program__is_tracepoint(struct bpf_program *prog);
|
bool bpf_program__is_tracepoint(struct bpf_program *prog);
|
||||||
bool bpf_program__is_kprobe(struct bpf_program *prog);
|
bool bpf_program__is_kprobe(struct bpf_program *prog);
|
||||||
|
bool bpf_program__is_sched_cls(struct bpf_program *prog);
|
||||||
|
bool bpf_program__is_sched_act(struct bpf_program *prog);
|
||||||
|
bool bpf_program__is_xdp(struct bpf_program *prog);
|
||||||
|
bool bpf_program__is_perf_event(struct bpf_program *prog);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't need __attribute__((packed)) now since it is
|
* We don't need __attribute__((packed)) now since it is
|
||||||
@ -223,5 +237,8 @@ typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
|
|||||||
int bpf_map__set_priv(struct bpf_map *map, void *priv,
|
int bpf_map__set_priv(struct bpf_map *map, void *priv,
|
||||||
bpf_map_clear_priv_t clear_priv);
|
bpf_map_clear_priv_t clear_priv);
|
||||||
void *bpf_map__priv(struct bpf_map *map);
|
void *bpf_map__priv(struct bpf_map *map);
|
||||||
|
int bpf_map__pin(struct bpf_map *map, const char *path);
|
||||||
|
|
||||||
|
long libbpf_get_error(const void *ptr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,7 +19,13 @@ MAKEFLAGS += --no-print-directory
|
|||||||
LIBFILE = $(OUTPUT)libsubcmd.a
|
LIBFILE = $(OUTPUT)libsubcmd.a
|
||||||
|
|
||||||
CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
|
CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
|
||||||
CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
|
CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
|
||||||
|
|
||||||
|
ifeq ($(CC), clang)
|
||||||
|
CFLAGS += -O3
|
||||||
|
else
|
||||||
|
CFLAGS += -O6
|
||||||
|
endif
|
||||||
|
|
||||||
# Treat warnings as errors unless directed not to
|
# Treat warnings as errors unless directed not to
|
||||||
ifneq ($(WERROR),0)
|
ifneq ($(WERROR),0)
|
||||||
|
@ -270,6 +270,8 @@ static int get_value(struct parse_opt_ctx_t *p,
|
|||||||
}
|
}
|
||||||
if (get_arg(p, opt, flags, &arg))
|
if (get_arg(p, opt, flags, &arg))
|
||||||
return -1;
|
return -1;
|
||||||
|
if (arg[0] == '-')
|
||||||
|
return opterror(opt, "expects an unsigned numerical value", flags);
|
||||||
*(unsigned int *)opt->value = strtol(arg, (char **)&s, 10);
|
*(unsigned int *)opt->value = strtol(arg, (char **)&s, 10);
|
||||||
if (*s)
|
if (*s)
|
||||||
return opterror(opt, "expects a numerical value", flags);
|
return opterror(opt, "expects a numerical value", flags);
|
||||||
@ -302,6 +304,8 @@ static int get_value(struct parse_opt_ctx_t *p,
|
|||||||
}
|
}
|
||||||
if (get_arg(p, opt, flags, &arg))
|
if (get_arg(p, opt, flags, &arg))
|
||||||
return -1;
|
return -1;
|
||||||
|
if (arg[0] == '-')
|
||||||
|
return opterror(opt, "expects an unsigned numerical value", flags);
|
||||||
*(u64 *)opt->value = strtoull(arg, (char **)&s, 10);
|
*(u64 *)opt->value = strtoull(arg, (char **)&s, 10);
|
||||||
if (*s)
|
if (*s)
|
||||||
return opterror(opt, "expects a numerical value", flags);
|
return opterror(opt, "expects a numerical value", flags);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef __SUBCMD_PARSE_OPTIONS_H
|
#ifndef __SUBCMD_PARSE_OPTIONS_H
|
||||||
#define __SUBCMD_PARSE_OPTIONS_H
|
#define __SUBCMD_PARSE_OPTIONS_H
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -132,32 +133,32 @@ struct option {
|
|||||||
#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) }
|
#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) }
|
||||||
#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
|
#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) }
|
||||||
#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
|
#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) }
|
||||||
#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) }
|
#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), .argh = (a), .help = (h) }
|
||||||
#define OPT_STRING_OPTARG(s, l, v, a, h, d) \
|
#define OPT_STRING_OPTARG(s, l, v, a, h, d) \
|
||||||
{ .type = OPTION_STRING, .short_name = (s), .long_name = (l), \
|
{ .type = OPTION_STRING, .short_name = (s), .long_name = (l), \
|
||||||
.value = check_vtype(v, const char **), (a), .help = (h), \
|
.value = check_vtype(v, const char **), .argh =(a), .help = (h), \
|
||||||
.flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) }
|
.flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) }
|
||||||
#define OPT_STRING_OPTARG_SET(s, l, v, os, a, h, d) \
|
#define OPT_STRING_OPTARG_SET(s, l, v, os, a, h, d) \
|
||||||
{ .type = OPTION_STRING, .short_name = (s), .long_name = (l), \
|
{ .type = OPTION_STRING, .short_name = (s), .long_name = (l), \
|
||||||
.value = check_vtype(v, const char **), (a), .help = (h), \
|
.value = check_vtype(v, const char **), .argh = (a), .help = (h), \
|
||||||
.flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d), \
|
.flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d), \
|
||||||
.set = check_vtype(os, bool *)}
|
.set = check_vtype(os, bool *)}
|
||||||
#define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
|
#define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), .argh = (a), .help = (h), .flags = PARSE_OPT_NOEMPTY}
|
||||||
#define OPT_DATE(s, l, v, h) \
|
#define OPT_DATE(s, l, v, h) \
|
||||||
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
|
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb }
|
||||||
#define OPT_CALLBACK(s, l, v, a, h, f) \
|
#define OPT_CALLBACK(s, l, v, a, h, f) \
|
||||||
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f) }
|
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f) }
|
||||||
#define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \
|
#define OPT_CALLBACK_NOOPT(s, l, v, a, h, f) \
|
||||||
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG }
|
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f), .flags = PARSE_OPT_NOARG }
|
||||||
#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
|
#define OPT_CALLBACK_DEFAULT(s, l, v, a, h, f, d) \
|
||||||
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
|
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = (a), .help = (h), .callback = (f), .defval = (intptr_t)d, .flags = PARSE_OPT_LASTARG_DEFAULT }
|
||||||
#define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \
|
#define OPT_CALLBACK_DEFAULT_NOOPT(s, l, v, a, h, f, d) \
|
||||||
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\
|
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l),\
|
||||||
.value = (v), (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\
|
.value = (v), .arg = (a), .help = (h), .callback = (f), .defval = (intptr_t)d,\
|
||||||
.flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG}
|
.flags = PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NOARG}
|
||||||
#define OPT_CALLBACK_OPTARG(s, l, v, d, a, h, f) \
|
#define OPT_CALLBACK_OPTARG(s, l, v, d, a, h, f) \
|
||||||
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \
|
{ .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), \
|
||||||
.value = (v), (a), .help = (h), .callback = (f), \
|
.value = (v), .argh = (a), .help = (h), .callback = (f), \
|
||||||
.flags = PARSE_OPT_OPTARG, .data = (d) }
|
.flags = PARSE_OPT_OPTARG, .data = (d) }
|
||||||
|
|
||||||
/* parse_options() will filter out the processed options and leave the
|
/* parse_options() will filter out the processed options and leave the
|
||||||
|
@ -257,10 +257,16 @@ define do_install_plugins
|
|||||||
endef
|
endef
|
||||||
|
|
||||||
define do_generate_dynamic_list_file
|
define do_generate_dynamic_list_file
|
||||||
(echo '{'; \
|
symbol_type=`$(NM) -u -D $1 | awk 'NF>1 {print $$1}' | \
|
||||||
$(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u; \
|
xargs echo "U W w" | tr ' ' '\n' | sort -u | xargs echo`;\
|
||||||
echo '};'; \
|
if [ "$$symbol_type" = "U W w" ];then \
|
||||||
) > $2
|
(echo '{'; \
|
||||||
|
$(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u;\
|
||||||
|
echo '};'; \
|
||||||
|
) > $2; \
|
||||||
|
else \
|
||||||
|
(echo Either missing one of [$1] or bad version of $(NM)) 1>&2;\
|
||||||
|
fi
|
||||||
endef
|
endef
|
||||||
|
|
||||||
install_lib: all_cmd install_plugins
|
install_lib: all_cmd install_plugins
|
||||||
|
@ -315,6 +315,7 @@ static unsigned int old_update_pointers(struct kbuffer *kbuf)
|
|||||||
extend += delta;
|
extend += delta;
|
||||||
delta = extend;
|
delta = extend;
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
|
length = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OLD_RINGBUF_TYPE_TIME_STAMP:
|
case OLD_RINGBUF_TYPE_TIME_STAMP:
|
||||||
|
@ -130,7 +130,7 @@ static int function_handler(struct trace_seq *s, struct pevent_record *record,
|
|||||||
unsigned long long pfunction;
|
unsigned long long pfunction;
|
||||||
const char *func;
|
const char *func;
|
||||||
const char *parent;
|
const char *parent;
|
||||||
int index;
|
int index = 0;
|
||||||
|
|
||||||
if (pevent_get_field_val(s, event, "ip", record, &function, 1))
|
if (pevent_get_field_val(s, event, "ip", record, &function, 1))
|
||||||
return trace_seq_putc(s, '!');
|
return trace_seq_putc(s, '!');
|
||||||
|
@ -3,10 +3,12 @@ perf-y += builtin-annotate.o
|
|||||||
perf-y += builtin-config.o
|
perf-y += builtin-config.o
|
||||||
perf-y += builtin-diff.o
|
perf-y += builtin-diff.o
|
||||||
perf-y += builtin-evlist.o
|
perf-y += builtin-evlist.o
|
||||||
|
perf-y += builtin-ftrace.o
|
||||||
perf-y += builtin-help.o
|
perf-y += builtin-help.o
|
||||||
perf-y += builtin-sched.o
|
perf-y += builtin-sched.o
|
||||||
perf-y += builtin-buildid-list.o
|
perf-y += builtin-buildid-list.o
|
||||||
perf-y += builtin-buildid-cache.o
|
perf-y += builtin-buildid-cache.o
|
||||||
|
perf-y += builtin-kallsyms.o
|
||||||
perf-y += builtin-list.o
|
perf-y += builtin-list.o
|
||||||
perf-y += builtin-record.o
|
perf-y += builtin-record.o
|
||||||
perf-y += builtin-report.o
|
perf-y += builtin-report.o
|
||||||
@ -39,8 +41,7 @@ CFLAGS_builtin-help.o += $(paths)
|
|||||||
CFLAGS_builtin-timechart.o += $(paths)
|
CFLAGS_builtin-timechart.o += $(paths)
|
||||||
CFLAGS_perf.o += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" \
|
CFLAGS_perf.o += -DPERF_HTML_PATH="BUILD_STR($(htmldir_SQ))" \
|
||||||
-DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" \
|
-DPERF_EXEC_PATH="BUILD_STR($(perfexecdir_SQ))" \
|
||||||
-DPREFIX="BUILD_STR($(prefix_SQ))" \
|
-DPREFIX="BUILD_STR($(prefix_SQ))"
|
||||||
-include $(OUTPUT)PERF-VERSION-FILE
|
|
||||||
CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))"
|
CFLAGS_builtin-trace.o += -DSTRACE_GROUPS_DIR="BUILD_STR($(STRACE_GROUPS_DIR_SQ))"
|
||||||
CFLAGS_builtin-report.o += -DTIPDIR="BUILD_STR($(tipdir_SQ))"
|
CFLAGS_builtin-report.o += -DTIPDIR="BUILD_STR($(tipdir_SQ))"
|
||||||
CFLAGS_builtin-report.o += -DDOCDIR="BUILD_STR($(srcdir_SQ)/Documentation)"
|
CFLAGS_builtin-report.o += -DDOCDIR="BUILD_STR($(srcdir_SQ)/Documentation)"
|
||||||
|
@ -248,7 +248,7 @@ output fields set for caheline offsets output:
|
|||||||
Code address, Code symbol, Shared Object, Source line
|
Code address, Code symbol, Shared Object, Source line
|
||||||
dso - coalesced by shared object
|
dso - coalesced by shared object
|
||||||
|
|
||||||
By default the coalescing is setup with 'pid,tid,iaddr'.
|
By default the coalescing is setup with 'pid,iaddr'.
|
||||||
|
|
||||||
STDIO OUTPUT
|
STDIO OUTPUT
|
||||||
------------
|
------------
|
||||||
|
@ -498,6 +498,18 @@ record.*::
|
|||||||
But if this option is 'no-cache', it will not update the build-id cache.
|
But if this option is 'no-cache', it will not update the build-id cache.
|
||||||
'skip' skips post-processing and does not update the cache.
|
'skip' skips post-processing and does not update the cache.
|
||||||
|
|
||||||
|
diff.*::
|
||||||
|
diff.order::
|
||||||
|
This option sets the number of columns to sort the result.
|
||||||
|
The default is 0, which means sorting by baseline.
|
||||||
|
Setting it to 1 will sort the result by delta (or other
|
||||||
|
compute method selected).
|
||||||
|
|
||||||
|
diff.compute::
|
||||||
|
This options sets the method for computing the diff result.
|
||||||
|
Possible values are 'delta', 'delta-abs', 'ratio' and
|
||||||
|
'wdiff'. Default is 'delta'.
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
linkperf:perf[1]
|
linkperf:perf[1]
|
||||||
|
@ -86,8 +86,9 @@ OPTIONS
|
|||||||
|
|
||||||
-c::
|
-c::
|
||||||
--compute::
|
--compute::
|
||||||
Differential computation selection - delta,ratio,wdiff (default is delta).
|
Differential computation selection - delta, ratio, wdiff, delta-abs
|
||||||
See COMPARISON METHODS section for more info.
|
(default is delta-abs). Default can be changed using diff.compute
|
||||||
|
config option. See COMPARISON METHODS section for more info.
|
||||||
|
|
||||||
-p::
|
-p::
|
||||||
--period::
|
--period::
|
||||||
@ -99,7 +100,11 @@ OPTIONS
|
|||||||
|
|
||||||
-o::
|
-o::
|
||||||
--order::
|
--order::
|
||||||
Specify compute sorting column number.
|
Specify compute sorting column number. 0 means sorting by baseline
|
||||||
|
overhead and 1 (default) means sorting by computed value of column 1
|
||||||
|
(data from the first file other base baseline). Values more than 1
|
||||||
|
can be used only if enough data files are provided.
|
||||||
|
The default value can be set using the diff.order config option.
|
||||||
|
|
||||||
--percentage::
|
--percentage::
|
||||||
Determine how to display the overhead percentage of filtered entries.
|
Determine how to display the overhead percentage of filtered entries.
|
||||||
@ -181,6 +186,10 @@ with:
|
|||||||
relative to how entries are filtered. Use --percentage=absolute to
|
relative to how entries are filtered. Use --percentage=absolute to
|
||||||
prevent such fluctuation.
|
prevent such fluctuation.
|
||||||
|
|
||||||
|
delta-abs
|
||||||
|
~~~~~~~~~
|
||||||
|
Same as 'delta` method, but sort the result with the absolute values.
|
||||||
|
|
||||||
ratio
|
ratio
|
||||||
~~~~~
|
~~~~~
|
||||||
If specified the 'Ratio' column is displayed with value 'r' computed as:
|
If specified the 'Ratio' column is displayed with value 'r' computed as:
|
||||||
|
36
tools/perf/Documentation/perf-ftrace.txt
Normal file
36
tools/perf/Documentation/perf-ftrace.txt
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
perf-ftrace(1)
|
||||||
|
=============
|
||||||
|
|
||||||
|
NAME
|
||||||
|
----
|
||||||
|
perf-ftrace - simple wrapper for kernel's ftrace functionality
|
||||||
|
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
--------
|
||||||
|
[verse]
|
||||||
|
'perf ftrace' <command>
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
The 'perf ftrace' command is a simple wrapper of kernel's ftrace
|
||||||
|
functionality. It only supports single thread tracing currently and
|
||||||
|
just reads trace_pipe in text and then write it to stdout.
|
||||||
|
|
||||||
|
The following options apply to perf ftrace.
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-------
|
||||||
|
|
||||||
|
-t::
|
||||||
|
--tracer=::
|
||||||
|
Tracer to use: function_graph or function.
|
||||||
|
|
||||||
|
-v::
|
||||||
|
--verbose=::
|
||||||
|
Verbosity level.
|
||||||
|
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
--------
|
||||||
|
linkperf:perf-record[1], linkperf:perf-trace[1]
|
24
tools/perf/Documentation/perf-kallsyms.txt
Normal file
24
tools/perf/Documentation/perf-kallsyms.txt
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
perf-kallsyms(1)
|
||||||
|
==============
|
||||||
|
|
||||||
|
NAME
|
||||||
|
----
|
||||||
|
perf-kallsyms - Searches running kernel for symbols
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
--------
|
||||||
|
[verse]
|
||||||
|
'perf kallsyms <options> symbol_name[,symbol_name...]'
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
-----------
|
||||||
|
This command searches the running kernel kallsyms file for the given symbol(s)
|
||||||
|
and prints information about it, including the DSO, the kallsyms begin/end
|
||||||
|
addresses and the addresses in the ELF kallsyms symbol table (for symbols in
|
||||||
|
modules).
|
||||||
|
|
||||||
|
OPTIONS
|
||||||
|
-------
|
||||||
|
-v::
|
||||||
|
--verbose=::
|
||||||
|
Increase verbosity level, showing details about symbol table loading, etc.
|
@ -421,9 +421,19 @@ Configure all used events to run in user space.
|
|||||||
--timestamp-filename
|
--timestamp-filename
|
||||||
Append timestamp to output file name.
|
Append timestamp to output file name.
|
||||||
|
|
||||||
--switch-output::
|
--switch-output[=mode]::
|
||||||
Generate multiple perf.data files, timestamp prefixed, switching to a new one
|
Generate multiple perf.data files, timestamp prefixed, switching to a new one
|
||||||
when receiving a SIGUSR2.
|
based on 'mode' value:
|
||||||
|
"signal" - when receiving a SIGUSR2 (default value) or
|
||||||
|
<size> - when reaching the size threshold, size is expected to
|
||||||
|
be a number with appended unit character - B/K/M/G
|
||||||
|
<time> - when reaching the time threshold, size is expected to
|
||||||
|
be a number with appended unit character - s/m/h/d
|
||||||
|
|
||||||
|
Note: the precision of the size threshold hugely depends
|
||||||
|
on your configuration - the number and size of your ring
|
||||||
|
buffers (-m). It is generally more precise for higher sizes
|
||||||
|
(like >5M), for lower values expect different sizes.
|
||||||
|
|
||||||
A possible use case is to, given an external event, slice the perf.data file
|
A possible use case is to, given an external event, slice the perf.data file
|
||||||
that gets then processed, possibly via a perf script, to decide if that
|
that gets then processed, possibly via a perf script, to decide if that
|
||||||
|
@ -143,6 +143,8 @@ OPTIONS for 'perf sched timehist'
|
|||||||
stop time is not given (i.e, time string is 'x.y,') then analysis goes
|
stop time is not given (i.e, time string is 'x.y,') then analysis goes
|
||||||
to end of file.
|
to end of file.
|
||||||
|
|
||||||
|
--state::
|
||||||
|
Show task state when it switched out.
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
|
@ -36,7 +36,7 @@ There are several variants of perf script:
|
|||||||
|
|
||||||
'perf script report <script> [args]' to run and display the results
|
'perf script report <script> [args]' to run and display the results
|
||||||
of <script>. <script> is the name displayed in the output of 'perf
|
of <script>. <script> is the name displayed in the output of 'perf
|
||||||
trace --list' i.e. the actual script name minus any language
|
script --list' i.e. the actual script name minus any language
|
||||||
extension. The perf.data output from a previous run of 'perf script
|
extension. The perf.data output from a previous run of 'perf script
|
||||||
record <script>' is used and should be present for this command to
|
record <script>' is used and should be present for this command to
|
||||||
succeed. [args] refers to the (mainly optional) args expected by
|
succeed. [args] refers to the (mainly optional) args expected by
|
||||||
@ -76,7 +76,7 @@ OPTIONS
|
|||||||
Any command you can specify in a shell.
|
Any command you can specify in a shell.
|
||||||
|
|
||||||
-D::
|
-D::
|
||||||
--dump-raw-script=::
|
--dump-raw-trace=::
|
||||||
Display verbose dump of the trace data.
|
Display verbose dump of the trace data.
|
||||||
|
|
||||||
-L::
|
-L::
|
||||||
|
@ -35,7 +35,10 @@ OPTIONS
|
|||||||
|
|
||||||
-e::
|
-e::
|
||||||
--expr::
|
--expr::
|
||||||
List of syscalls to show, currently only syscall names.
|
--event::
|
||||||
|
List of syscalls and other perf events (tracepoints, HW cache events,
|
||||||
|
etc) to show.
|
||||||
|
See 'perf list' for a complete list of events.
|
||||||
Prefixing with ! shows all syscalls but the ones specified. You may
|
Prefixing with ! shows all syscalls but the ones specified. You may
|
||||||
need to escape it.
|
need to escape it.
|
||||||
|
|
||||||
@ -135,9 +138,6 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
|
|||||||
--kernel-syscall-graph::
|
--kernel-syscall-graph::
|
||||||
Show the kernel callchains on the syscall exit path.
|
Show the kernel callchains on the syscall exit path.
|
||||||
|
|
||||||
--event::
|
|
||||||
Trace other events, see 'perf list' for a complete list.
|
|
||||||
|
|
||||||
--max-stack::
|
--max-stack::
|
||||||
Set the stack depth limit when parsing the callchain, anything
|
Set the stack depth limit when parsing the callchain, anything
|
||||||
beyond the specified depth will be ignored. Note that at this point
|
beyond the specified depth will be ignored. Note that at this point
|
||||||
|
@ -61,6 +61,7 @@ tools/include/asm-generic/bitops.h
|
|||||||
tools/include/linux/atomic.h
|
tools/include/linux/atomic.h
|
||||||
tools/include/linux/bitops.h
|
tools/include/linux/bitops.h
|
||||||
tools/include/linux/compiler.h
|
tools/include/linux/compiler.h
|
||||||
|
tools/include/linux/compiler-gcc.h
|
||||||
tools/include/linux/coresight-pmu.h
|
tools/include/linux/coresight-pmu.h
|
||||||
tools/include/linux/filter.h
|
tools/include/linux/filter.h
|
||||||
tools/include/linux/hash.h
|
tools/include/linux/hash.h
|
||||||
|
@ -144,8 +144,12 @@ ifndef DEBUG
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(DEBUG),0)
|
ifeq ($(DEBUG),0)
|
||||||
|
ifeq ($(CC), clang)
|
||||||
|
CFLAGS += -O3
|
||||||
|
else
|
||||||
CFLAGS += -O6
|
CFLAGS += -O6
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef PARSER_DEBUG
|
ifdef PARSER_DEBUG
|
||||||
PARSER_DEBUG_BISON := -t
|
PARSER_DEBUG_BISON := -t
|
||||||
@ -291,8 +295,10 @@ else
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
ifneq ($(feature-dwarf), 1)
|
ifneq ($(feature-dwarf), 1)
|
||||||
msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
|
ifndef NO_DWARF
|
||||||
NO_DWARF := 1
|
msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev);
|
||||||
|
NO_DWARF := 1
|
||||||
|
endif
|
||||||
else
|
else
|
||||||
ifneq ($(feature-dwarf_getlocations), 1)
|
ifneq ($(feature-dwarf_getlocations), 1)
|
||||||
msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157);
|
msg := $(warning Old libdw.h, finding variables at given 'perf probe' point will not work, install elfutils-devel/libdw-dev >= 0.157);
|
||||||
|
@ -661,6 +661,7 @@ ifndef NO_PERF_READ_VDSOX32
|
|||||||
endif
|
endif
|
||||||
ifndef NO_JVMTI
|
ifndef NO_JVMTI
|
||||||
$(call QUIET_INSTALL, $(LIBJVMTI)) \
|
$(call QUIET_INSTALL, $(LIBJVMTI)) \
|
||||||
|
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(libdir_SQ)'; \
|
||||||
$(INSTALL) $(OUTPUT)$(LIBJVMTI) '$(DESTDIR_SQ)$(libdir_SQ)';
|
$(INSTALL) $(OUTPUT)$(LIBJVMTI) '$(DESTDIR_SQ)$(libdir_SQ)';
|
||||||
endif
|
endif
|
||||||
$(call QUIET_INSTALL, libexec) \
|
$(call QUIET_INSTALL, libexec) \
|
||||||
|
@ -2,3 +2,4 @@ ifndef NO_DWARF
|
|||||||
PERF_HAVE_DWARF_REGS := 1
|
PERF_HAVE_DWARF_REGS := 1
|
||||||
endif
|
endif
|
||||||
PERF_HAVE_JITDUMP := 1
|
PERF_HAVE_JITDUMP := 1
|
||||||
|
PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
/* This is included in perf/util/dwarf-regs.c */
|
/* This is included in perf/util/dwarf-regs.c */
|
||||||
|
|
||||||
static const char * const aarch64_regstr_tbl[] = {
|
static const char * const aarch64_regstr_tbl[] = {
|
||||||
"%r0", "%r1", "%r2", "%r3", "%r4",
|
"%x0", "%x1", "%x2", "%x3", "%x4",
|
||||||
"%r5", "%r6", "%r7", "%r8", "%r9",
|
"%x5", "%x6", "%x7", "%x8", "%x9",
|
||||||
"%r10", "%r11", "%r12", "%r13", "%r14",
|
"%x10", "%x11", "%x12", "%x13", "%x14",
|
||||||
"%r15", "%r16", "%r17", "%r18", "%r19",
|
"%x15", "%x16", "%x17", "%x18", "%x19",
|
||||||
"%r20", "%r21", "%r22", "%r23", "%r24",
|
"%x20", "%x21", "%x22", "%x23", "%x24",
|
||||||
"%r25", "%r26", "%r27", "%r28", "%r29",
|
"%x25", "%x26", "%x27", "%x28", "%x29",
|
||||||
"%lr", "%sp",
|
"%lr", "%sp",
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
@ -10,17 +10,20 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <dwarf-regs.h>
|
#include <dwarf-regs.h>
|
||||||
|
#include <linux/ptrace.h> /* for struct user_pt_regs */
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
struct pt_regs_dwarfnum {
|
struct pt_regs_dwarfnum {
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned int dwarfnum;
|
unsigned int dwarfnum;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define STR(s) #s
|
|
||||||
#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
|
#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
|
||||||
#define GPR_DWARFNUM_NAME(num) \
|
#define GPR_DWARFNUM_NAME(num) \
|
||||||
{.name = STR(%x##num), .dwarfnum = num}
|
{.name = STR(%x##num), .dwarfnum = num}
|
||||||
#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
|
#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
|
||||||
|
#define DWARFNUM2OFFSET(index) \
|
||||||
|
(index * sizeof((struct user_pt_regs *)0)->regs[0])
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reference:
|
* Reference:
|
||||||
@ -78,3 +81,13 @@ const char *get_arch_regstr(unsigned int n)
|
|||||||
return roff->name;
|
return roff->name;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int regs_query_register_offset(const char *name)
|
||||||
|
{
|
||||||
|
const struct pt_regs_dwarfnum *roff;
|
||||||
|
|
||||||
|
for (roff = regdwarfnum_table; roff->name != NULL; roff++)
|
||||||
|
if (!strcmp(roff->name, name))
|
||||||
|
return DWARFNUM2OFFSET(roff->dwarfnum);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
@ -130,8 +130,6 @@ int bench_futex_hash(int argc, const char **argv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
|
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
nsecs = futexbench_sanitize_numeric(nsecs);
|
|
||||||
nfutexes = futexbench_sanitize_numeric(nfutexes);
|
|
||||||
|
|
||||||
sigfillset(&act.sa_mask);
|
sigfillset(&act.sa_mask);
|
||||||
act.sa_sigaction = toggle_done;
|
act.sa_sigaction = toggle_done;
|
||||||
@ -139,8 +137,6 @@ int bench_futex_hash(int argc, const char **argv,
|
|||||||
|
|
||||||
if (!nthreads) /* default to the number of CPUs */
|
if (!nthreads) /* default to the number of CPUs */
|
||||||
nthreads = ncpus;
|
nthreads = ncpus;
|
||||||
else
|
|
||||||
nthreads = futexbench_sanitize_numeric(nthreads);
|
|
||||||
|
|
||||||
worker = calloc(nthreads, sizeof(*worker));
|
worker = calloc(nthreads, sizeof(*worker));
|
||||||
if (!worker)
|
if (!worker)
|
||||||
|
@ -152,7 +152,6 @@ int bench_futex_lock_pi(int argc, const char **argv,
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
|
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
nsecs = futexbench_sanitize_numeric(nsecs);
|
|
||||||
|
|
||||||
sigfillset(&act.sa_mask);
|
sigfillset(&act.sa_mask);
|
||||||
act.sa_sigaction = toggle_done;
|
act.sa_sigaction = toggle_done;
|
||||||
@ -160,8 +159,6 @@ int bench_futex_lock_pi(int argc, const char **argv,
|
|||||||
|
|
||||||
if (!nthreads)
|
if (!nthreads)
|
||||||
nthreads = ncpus;
|
nthreads = ncpus;
|
||||||
else
|
|
||||||
nthreads = futexbench_sanitize_numeric(nthreads);
|
|
||||||
|
|
||||||
worker = calloc(nthreads, sizeof(*worker));
|
worker = calloc(nthreads, sizeof(*worker));
|
||||||
if (!worker)
|
if (!worker)
|
||||||
|
@ -128,8 +128,6 @@ int bench_futex_requeue(int argc, const char **argv,
|
|||||||
|
|
||||||
if (!nthreads)
|
if (!nthreads)
|
||||||
nthreads = ncpus;
|
nthreads = ncpus;
|
||||||
else
|
|
||||||
nthreads = futexbench_sanitize_numeric(nthreads);
|
|
||||||
|
|
||||||
worker = calloc(nthreads, sizeof(*worker));
|
worker = calloc(nthreads, sizeof(*worker));
|
||||||
if (!worker)
|
if (!worker)
|
||||||
|
@ -217,12 +217,8 @@ int bench_futex_wake_parallel(int argc, const char **argv,
|
|||||||
sigaction(SIGINT, &act, NULL);
|
sigaction(SIGINT, &act, NULL);
|
||||||
|
|
||||||
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
|
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
nwaking_threads = futexbench_sanitize_numeric(nwaking_threads);
|
|
||||||
|
|
||||||
if (!nblocked_threads)
|
if (!nblocked_threads)
|
||||||
nblocked_threads = ncpus;
|
nblocked_threads = ncpus;
|
||||||
else
|
|
||||||
nblocked_threads = futexbench_sanitize_numeric(nblocked_threads);
|
|
||||||
|
|
||||||
/* some sanity checks */
|
/* some sanity checks */
|
||||||
if (nwaking_threads > nblocked_threads || !nwaking_threads)
|
if (nwaking_threads > nblocked_threads || !nwaking_threads)
|
||||||
|
@ -129,7 +129,6 @@ int bench_futex_wake(int argc, const char **argv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
|
ncpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
nwakes = futexbench_sanitize_numeric(nwakes);
|
|
||||||
|
|
||||||
sigfillset(&act.sa_mask);
|
sigfillset(&act.sa_mask);
|
||||||
act.sa_sigaction = toggle_done;
|
act.sa_sigaction = toggle_done;
|
||||||
@ -137,8 +136,6 @@ int bench_futex_wake(int argc, const char **argv,
|
|||||||
|
|
||||||
if (!nthreads)
|
if (!nthreads)
|
||||||
nthreads = ncpus;
|
nthreads = ncpus;
|
||||||
else
|
|
||||||
nthreads = futexbench_sanitize_numeric(nthreads);
|
|
||||||
|
|
||||||
worker = calloc(nthreads, sizeof(*worker));
|
worker = calloc(nthreads, sizeof(*worker));
|
||||||
if (!worker)
|
if (!worker)
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#ifndef _FUTEX_H
|
#ifndef _FUTEX_H
|
||||||
#define _FUTEX_H
|
#define _FUTEX_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -100,7 +99,4 @@ static inline int pthread_attr_setaffinity_np(pthread_attr_t *attr,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* User input sanitation */
|
|
||||||
#define futexbench_sanitize_numeric(__n) abs((__n))
|
|
||||||
|
|
||||||
#endif /* _FUTEX_H */
|
#endif /* _FUTEX_H */
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
/*
|
/*
|
||||||
* Debug printf:
|
* Debug printf:
|
||||||
*/
|
*/
|
||||||
|
#undef dprintf
|
||||||
#define dprintf(x...) do { if (g && g->p.show_details >= 1) printf(x); } while (0)
|
#define dprintf(x...) do { if (g && g->p.show_details >= 1) printf(x); } while (0)
|
||||||
|
|
||||||
struct thread_data {
|
struct thread_data {
|
||||||
@ -1573,13 +1574,13 @@ static int __bench_numa(const char *name)
|
|||||||
"GB/sec,", "total-speed", "GB/sec total speed");
|
"GB/sec,", "total-speed", "GB/sec total speed");
|
||||||
|
|
||||||
if (g->p.show_details >= 2) {
|
if (g->p.show_details >= 2) {
|
||||||
char tname[32];
|
char tname[14 + 2 * 10 + 1];
|
||||||
struct thread_data *td;
|
struct thread_data *td;
|
||||||
for (p = 0; p < g->p.nr_proc; p++) {
|
for (p = 0; p < g->p.nr_proc; p++) {
|
||||||
for (t = 0; t < g->p.nr_threads; t++) {
|
for (t = 0; t < g->p.nr_threads; t++) {
|
||||||
memset(tname, 0, 32);
|
memset(tname, 0, sizeof(tname));
|
||||||
td = g->threads + p*g->p.nr_threads + t;
|
td = g->threads + p*g->p.nr_threads + t;
|
||||||
snprintf(tname, 32, "process%d:thread%d", p, t);
|
snprintf(tname, sizeof(tname), "process%d:thread%d", p, t);
|
||||||
print_res(tname, td->speed_gbs,
|
print_res(tname, td->speed_gbs,
|
||||||
"GB/sec", "thread-speed", "GB/sec/thread speed");
|
"GB/sec", "thread-speed", "GB/sec/thread speed");
|
||||||
print_res(tname, td->system_time_ns / NSEC_PER_SEC,
|
print_res(tname, td->system_time_ns / NSEC_PER_SEC,
|
||||||
|
@ -58,7 +58,7 @@ struct c2c_hist_entry {
|
|||||||
struct hist_entry he;
|
struct hist_entry he;
|
||||||
};
|
};
|
||||||
|
|
||||||
static char const *coalesce_default = "pid,tid,iaddr";
|
static char const *coalesce_default = "pid,iaddr";
|
||||||
|
|
||||||
struct perf_c2c {
|
struct perf_c2c {
|
||||||
struct perf_tool tool;
|
struct perf_tool tool;
|
||||||
@ -2476,6 +2476,7 @@ static int build_cl_output(char *cl_sort, bool no_source)
|
|||||||
"mean_rmt,"
|
"mean_rmt,"
|
||||||
"mean_lcl,"
|
"mean_lcl,"
|
||||||
"mean_load,"
|
"mean_load,"
|
||||||
|
"tot_recs,"
|
||||||
"cpucnt,",
|
"cpucnt,",
|
||||||
add_sym ? "symbol," : "",
|
add_sym ? "symbol," : "",
|
||||||
add_dso ? "dso," : "",
|
add_dso ? "dso," : "",
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "util/symbol.h"
|
#include "util/symbol.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "util/data.h"
|
#include "util/data.h"
|
||||||
|
#include "util/config.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@ -30,6 +31,7 @@ enum {
|
|||||||
PERF_HPP_DIFF__RATIO,
|
PERF_HPP_DIFF__RATIO,
|
||||||
PERF_HPP_DIFF__WEIGHTED_DIFF,
|
PERF_HPP_DIFF__WEIGHTED_DIFF,
|
||||||
PERF_HPP_DIFF__FORMULA,
|
PERF_HPP_DIFF__FORMULA,
|
||||||
|
PERF_HPP_DIFF__DELTA_ABS,
|
||||||
|
|
||||||
PERF_HPP_DIFF__MAX_INDEX
|
PERF_HPP_DIFF__MAX_INDEX
|
||||||
};
|
};
|
||||||
@ -64,7 +66,7 @@ static bool force;
|
|||||||
static bool show_period;
|
static bool show_period;
|
||||||
static bool show_formula;
|
static bool show_formula;
|
||||||
static bool show_baseline_only;
|
static bool show_baseline_only;
|
||||||
static unsigned int sort_compute;
|
static unsigned int sort_compute = 1;
|
||||||
|
|
||||||
static s64 compute_wdiff_w1;
|
static s64 compute_wdiff_w1;
|
||||||
static s64 compute_wdiff_w2;
|
static s64 compute_wdiff_w2;
|
||||||
@ -73,19 +75,22 @@ enum {
|
|||||||
COMPUTE_DELTA,
|
COMPUTE_DELTA,
|
||||||
COMPUTE_RATIO,
|
COMPUTE_RATIO,
|
||||||
COMPUTE_WEIGHTED_DIFF,
|
COMPUTE_WEIGHTED_DIFF,
|
||||||
|
COMPUTE_DELTA_ABS,
|
||||||
COMPUTE_MAX,
|
COMPUTE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *compute_names[COMPUTE_MAX] = {
|
const char *compute_names[COMPUTE_MAX] = {
|
||||||
[COMPUTE_DELTA] = "delta",
|
[COMPUTE_DELTA] = "delta",
|
||||||
|
[COMPUTE_DELTA_ABS] = "delta-abs",
|
||||||
[COMPUTE_RATIO] = "ratio",
|
[COMPUTE_RATIO] = "ratio",
|
||||||
[COMPUTE_WEIGHTED_DIFF] = "wdiff",
|
[COMPUTE_WEIGHTED_DIFF] = "wdiff",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int compute;
|
static int compute = COMPUTE_DELTA_ABS;
|
||||||
|
|
||||||
static int compute_2_hpp[COMPUTE_MAX] = {
|
static int compute_2_hpp[COMPUTE_MAX] = {
|
||||||
[COMPUTE_DELTA] = PERF_HPP_DIFF__DELTA,
|
[COMPUTE_DELTA] = PERF_HPP_DIFF__DELTA,
|
||||||
|
[COMPUTE_DELTA_ABS] = PERF_HPP_DIFF__DELTA_ABS,
|
||||||
[COMPUTE_RATIO] = PERF_HPP_DIFF__RATIO,
|
[COMPUTE_RATIO] = PERF_HPP_DIFF__RATIO,
|
||||||
[COMPUTE_WEIGHTED_DIFF] = PERF_HPP_DIFF__WEIGHTED_DIFF,
|
[COMPUTE_WEIGHTED_DIFF] = PERF_HPP_DIFF__WEIGHTED_DIFF,
|
||||||
};
|
};
|
||||||
@ -111,6 +116,10 @@ static struct header_column {
|
|||||||
.name = "Delta",
|
.name = "Delta",
|
||||||
.width = 7,
|
.width = 7,
|
||||||
},
|
},
|
||||||
|
[PERF_HPP_DIFF__DELTA_ABS] = {
|
||||||
|
.name = "Delta Abs",
|
||||||
|
.width = 7,
|
||||||
|
},
|
||||||
[PERF_HPP_DIFF__RATIO] = {
|
[PERF_HPP_DIFF__RATIO] = {
|
||||||
.name = "Ratio",
|
.name = "Ratio",
|
||||||
.width = 14,
|
.width = 14,
|
||||||
@ -298,6 +307,7 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
|
|||||||
{
|
{
|
||||||
switch (compute) {
|
switch (compute) {
|
||||||
case COMPUTE_DELTA:
|
case COMPUTE_DELTA:
|
||||||
|
case COMPUTE_DELTA_ABS:
|
||||||
return formula_delta(he, pair, buf, size);
|
return formula_delta(he, pair, buf, size);
|
||||||
case COMPUTE_RATIO:
|
case COMPUTE_RATIO:
|
||||||
return formula_ratio(he, pair, buf, size);
|
return formula_ratio(he, pair, buf, size);
|
||||||
@ -461,6 +471,7 @@ static void hists__precompute(struct hists *hists)
|
|||||||
|
|
||||||
switch (compute) {
|
switch (compute) {
|
||||||
case COMPUTE_DELTA:
|
case COMPUTE_DELTA:
|
||||||
|
case COMPUTE_DELTA_ABS:
|
||||||
compute_delta(he, pair);
|
compute_delta(he, pair);
|
||||||
break;
|
break;
|
||||||
case COMPUTE_RATIO:
|
case COMPUTE_RATIO:
|
||||||
@ -498,6 +509,13 @@ __hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
|
|||||||
|
|
||||||
return cmp_doubles(l, r);
|
return cmp_doubles(l, r);
|
||||||
}
|
}
|
||||||
|
case COMPUTE_DELTA_ABS:
|
||||||
|
{
|
||||||
|
double l = fabs(left->diff.period_ratio_delta);
|
||||||
|
double r = fabs(right->diff.period_ratio_delta);
|
||||||
|
|
||||||
|
return cmp_doubles(l, r);
|
||||||
|
}
|
||||||
case COMPUTE_RATIO:
|
case COMPUTE_RATIO:
|
||||||
{
|
{
|
||||||
double l = left->diff.period_ratio;
|
double l = left->diff.period_ratio;
|
||||||
@ -564,7 +582,7 @@ hist_entry__cmp_compute_idx(struct hist_entry *left, struct hist_entry *right,
|
|||||||
if (!p_left || !p_right)
|
if (!p_left || !p_right)
|
||||||
return p_left ? -1 : 1;
|
return p_left ? -1 : 1;
|
||||||
|
|
||||||
if (c != COMPUTE_DELTA) {
|
if (c != COMPUTE_DELTA && c != COMPUTE_DELTA_ABS) {
|
||||||
/*
|
/*
|
||||||
* The delta can be computed without the baseline, but
|
* The delta can be computed without the baseline, but
|
||||||
* others are not. Put those entries which have no
|
* others are not. Put those entries which have no
|
||||||
@ -606,6 +624,15 @@ hist_entry__cmp_delta(struct perf_hpp_fmt *fmt,
|
|||||||
return hist_entry__cmp_compute(right, left, COMPUTE_DELTA, d->idx);
|
return hist_entry__cmp_compute(right, left, COMPUTE_DELTA, d->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int64_t
|
||||||
|
hist_entry__cmp_delta_abs(struct perf_hpp_fmt *fmt,
|
||||||
|
struct hist_entry *left, struct hist_entry *right)
|
||||||
|
{
|
||||||
|
struct data__file *d = fmt_to_data_file(fmt);
|
||||||
|
|
||||||
|
return hist_entry__cmp_compute(right, left, COMPUTE_DELTA_ABS, d->idx);
|
||||||
|
}
|
||||||
|
|
||||||
static int64_t
|
static int64_t
|
||||||
hist_entry__cmp_ratio(struct perf_hpp_fmt *fmt,
|
hist_entry__cmp_ratio(struct perf_hpp_fmt *fmt,
|
||||||
struct hist_entry *left, struct hist_entry *right)
|
struct hist_entry *left, struct hist_entry *right)
|
||||||
@ -632,6 +659,14 @@ hist_entry__cmp_delta_idx(struct perf_hpp_fmt *fmt __maybe_unused,
|
|||||||
sort_compute);
|
sort_compute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int64_t
|
||||||
|
hist_entry__cmp_delta_abs_idx(struct perf_hpp_fmt *fmt __maybe_unused,
|
||||||
|
struct hist_entry *left, struct hist_entry *right)
|
||||||
|
{
|
||||||
|
return hist_entry__cmp_compute_idx(right, left, COMPUTE_DELTA_ABS,
|
||||||
|
sort_compute);
|
||||||
|
}
|
||||||
|
|
||||||
static int64_t
|
static int64_t
|
||||||
hist_entry__cmp_ratio_idx(struct perf_hpp_fmt *fmt __maybe_unused,
|
hist_entry__cmp_ratio_idx(struct perf_hpp_fmt *fmt __maybe_unused,
|
||||||
struct hist_entry *left, struct hist_entry *right)
|
struct hist_entry *left, struct hist_entry *right)
|
||||||
@ -775,7 +810,7 @@ static const struct option options[] = {
|
|||||||
OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
|
OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
|
||||||
"Show only items with match in baseline"),
|
"Show only items with match in baseline"),
|
||||||
OPT_CALLBACK('c', "compute", &compute,
|
OPT_CALLBACK('c', "compute", &compute,
|
||||||
"delta,ratio,wdiff:w1,w2 (default delta)",
|
"delta,delta-abs,ratio,wdiff:w1,w2 (default delta-abs)",
|
||||||
"Entries differential computation selection",
|
"Entries differential computation selection",
|
||||||
setup_compute),
|
setup_compute),
|
||||||
OPT_BOOLEAN('p', "period", &show_period,
|
OPT_BOOLEAN('p', "period", &show_period,
|
||||||
@ -945,6 +980,7 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,
|
|||||||
|
|
||||||
switch (idx) {
|
switch (idx) {
|
||||||
case PERF_HPP_DIFF__DELTA:
|
case PERF_HPP_DIFF__DELTA:
|
||||||
|
case PERF_HPP_DIFF__DELTA_ABS:
|
||||||
if (pair->diff.computed)
|
if (pair->diff.computed)
|
||||||
diff = pair->diff.period_ratio_delta;
|
diff = pair->diff.period_ratio_delta;
|
||||||
else
|
else
|
||||||
@ -1118,6 +1154,10 @@ static void data__hpp_register(struct data__file *d, int idx)
|
|||||||
fmt->color = hpp__color_wdiff;
|
fmt->color = hpp__color_wdiff;
|
||||||
fmt->sort = hist_entry__cmp_wdiff;
|
fmt->sort = hist_entry__cmp_wdiff;
|
||||||
break;
|
break;
|
||||||
|
case PERF_HPP_DIFF__DELTA_ABS:
|
||||||
|
fmt->color = hpp__color_delta;
|
||||||
|
fmt->sort = hist_entry__cmp_delta_abs;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fmt->sort = hist_entry__cmp_nop;
|
fmt->sort = hist_entry__cmp_nop;
|
||||||
break;
|
break;
|
||||||
@ -1195,6 +1235,9 @@ static int ui_init(void)
|
|||||||
case COMPUTE_WEIGHTED_DIFF:
|
case COMPUTE_WEIGHTED_DIFF:
|
||||||
fmt->sort = hist_entry__cmp_wdiff_idx;
|
fmt->sort = hist_entry__cmp_wdiff_idx;
|
||||||
break;
|
break;
|
||||||
|
case COMPUTE_DELTA_ABS:
|
||||||
|
fmt->sort = hist_entry__cmp_delta_abs_idx;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
BUG_ON(1);
|
BUG_ON(1);
|
||||||
}
|
}
|
||||||
@ -1249,6 +1292,31 @@ static int data_init(int argc, const char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int diff__config(const char *var, const char *value,
|
||||||
|
void *cb __maybe_unused)
|
||||||
|
{
|
||||||
|
if (!strcmp(var, "diff.order")) {
|
||||||
|
sort_compute = perf_config_int(var, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!strcmp(var, "diff.compute")) {
|
||||||
|
if (!strcmp(value, "delta")) {
|
||||||
|
compute = COMPUTE_DELTA;
|
||||||
|
} else if (!strcmp(value, "delta-abs")) {
|
||||||
|
compute = COMPUTE_DELTA_ABS;
|
||||||
|
} else if (!strcmp(value, "ratio")) {
|
||||||
|
compute = COMPUTE_RATIO;
|
||||||
|
} else if (!strcmp(value, "wdiff")) {
|
||||||
|
compute = COMPUTE_WEIGHTED_DIFF;
|
||||||
|
} else {
|
||||||
|
pr_err("Invalid compute method: %s\n", value);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
|
int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||||
{
|
{
|
||||||
int ret = hists__init();
|
int ret = hists__init();
|
||||||
@ -1256,6 +1324,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
perf_config(diff__config, NULL);
|
||||||
|
|
||||||
argc = parse_options(argc, argv, options, diff_usage, 0);
|
argc = parse_options(argc, argv, options, diff_usage, 0);
|
||||||
|
|
||||||
if (symbol__init(NULL) < 0)
|
if (symbol__init(NULL) < 0)
|
||||||
|
265
tools/perf/builtin-ftrace.c
Normal file
265
tools/perf/builtin-ftrace.c
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
/*
|
||||||
|
* builtin-ftrace.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 LG Electronics, Namhyung Kim <namhyung@kernel.org>
|
||||||
|
*
|
||||||
|
* Released under the GPL v2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "builtin.h"
|
||||||
|
#include "perf.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
#include <subcmd/parse-options.h>
|
||||||
|
#include "evlist.h"
|
||||||
|
#include "target.h"
|
||||||
|
#include "thread_map.h"
|
||||||
|
#include "util/config.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFAULT_TRACER "function_graph"
|
||||||
|
|
||||||
|
struct perf_ftrace {
|
||||||
|
struct perf_evlist *evlist;
|
||||||
|
struct target target;
|
||||||
|
const char *tracer;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool done;
|
||||||
|
|
||||||
|
static void sig_handler(int sig __maybe_unused)
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* perf_evlist__prepare_workload will send a SIGUSR1 if the fork fails, since
|
||||||
|
* we asked by setting its exec_error to the function below,
|
||||||
|
* ftrace__workload_exec_failed_signal.
|
||||||
|
*
|
||||||
|
* XXX We need to handle this more appropriately, emitting an error, etc.
|
||||||
|
*/
|
||||||
|
static void ftrace__workload_exec_failed_signal(int signo __maybe_unused,
|
||||||
|
siginfo_t *info __maybe_unused,
|
||||||
|
void *ucontext __maybe_unused)
|
||||||
|
{
|
||||||
|
/* workload_exec_errno = info->si_value.sival_int; */
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_tracing_file(const char *name, const char *val)
|
||||||
|
{
|
||||||
|
char *file;
|
||||||
|
int fd, ret = -1;
|
||||||
|
ssize_t size = strlen(val);
|
||||||
|
|
||||||
|
file = get_tracing_file(name);
|
||||||
|
if (!file) {
|
||||||
|
pr_debug("cannot get tracing file: %s\n", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(file, O_WRONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
pr_debug("cannot open tracing file: %s\n", name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write(fd, val, size) == size)
|
||||||
|
ret = 0;
|
||||||
|
else
|
||||||
|
pr_debug("write '%s' to tracing/%s failed\n", val, name);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
out:
|
||||||
|
put_tracing_file(file);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reset_tracing_files(struct perf_ftrace *ftrace __maybe_unused)
|
||||||
|
{
|
||||||
|
if (write_tracing_file("tracing_on", "0") < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (write_tracing_file("current_tracer", "nop") < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (write_tracing_file("set_ftrace_pid", " ") < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __cmd_ftrace(struct perf_ftrace *ftrace, int argc, const char **argv)
|
||||||
|
{
|
||||||
|
char *trace_file;
|
||||||
|
int trace_fd;
|
||||||
|
char *trace_pid;
|
||||||
|
char buf[4096];
|
||||||
|
struct pollfd pollfd = {
|
||||||
|
.events = POLLIN,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (geteuid() != 0) {
|
||||||
|
pr_err("ftrace only works for root!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc < 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
signal(SIGINT, sig_handler);
|
||||||
|
signal(SIGUSR1, sig_handler);
|
||||||
|
signal(SIGCHLD, sig_handler);
|
||||||
|
|
||||||
|
reset_tracing_files(ftrace);
|
||||||
|
|
||||||
|
/* reset ftrace buffer */
|
||||||
|
if (write_tracing_file("trace", "0") < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (perf_evlist__prepare_workload(ftrace->evlist, &ftrace->target,
|
||||||
|
argv, false, ftrace__workload_exec_failed_signal) < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (write_tracing_file("current_tracer", ftrace->tracer) < 0) {
|
||||||
|
pr_err("failed to set current_tracer to %s\n", ftrace->tracer);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (asprintf(&trace_pid, "%d", thread_map__pid(ftrace->evlist->threads, 0)) < 0) {
|
||||||
|
pr_err("failed to allocate pid string\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_tracing_file("set_ftrace_pid", trace_pid) < 0) {
|
||||||
|
pr_err("failed to set pid: %s\n", trace_pid);
|
||||||
|
goto out_free_pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_file = get_tracing_file("trace_pipe");
|
||||||
|
if (!trace_file) {
|
||||||
|
pr_err("failed to open trace_pipe\n");
|
||||||
|
goto out_free_pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_fd = open(trace_file, O_RDONLY);
|
||||||
|
|
||||||
|
put_tracing_file(trace_file);
|
||||||
|
|
||||||
|
if (trace_fd < 0) {
|
||||||
|
pr_err("failed to open trace_pipe\n");
|
||||||
|
goto out_free_pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
fcntl(trace_fd, F_SETFL, O_NONBLOCK);
|
||||||
|
pollfd.fd = trace_fd;
|
||||||
|
|
||||||
|
if (write_tracing_file("tracing_on", "1") < 0) {
|
||||||
|
pr_err("can't enable tracing\n");
|
||||||
|
goto out_close_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
perf_evlist__start_workload(ftrace->evlist);
|
||||||
|
|
||||||
|
while (!done) {
|
||||||
|
if (poll(&pollfd, 1, -1) < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (pollfd.revents & POLLIN) {
|
||||||
|
int n = read(trace_fd, buf, sizeof(buf));
|
||||||
|
if (n < 0)
|
||||||
|
break;
|
||||||
|
if (fwrite(buf, n, 1, stdout) != 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write_tracing_file("tracing_on", "0");
|
||||||
|
|
||||||
|
/* read remaining buffer contents */
|
||||||
|
while (true) {
|
||||||
|
int n = read(trace_fd, buf, sizeof(buf));
|
||||||
|
if (n <= 0)
|
||||||
|
break;
|
||||||
|
if (fwrite(buf, n, 1, stdout) != 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_close_fd:
|
||||||
|
close(trace_fd);
|
||||||
|
out_free_pid:
|
||||||
|
free(trace_pid);
|
||||||
|
out:
|
||||||
|
reset_tracing_files(ftrace);
|
||||||
|
|
||||||
|
return done ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int perf_ftrace_config(const char *var, const char *value, void *cb)
|
||||||
|
{
|
||||||
|
struct perf_ftrace *ftrace = cb;
|
||||||
|
|
||||||
|
if (prefixcmp(var, "ftrace."))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (strcmp(var, "ftrace.tracer"))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!strcmp(value, "function_graph") ||
|
||||||
|
!strcmp(value, "function")) {
|
||||||
|
ftrace->tracer = value;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_err("Please select \"function_graph\" (default) or \"function\"\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_ftrace(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct perf_ftrace ftrace = {
|
||||||
|
.tracer = DEFAULT_TRACER,
|
||||||
|
.target = { .uid = UINT_MAX, },
|
||||||
|
};
|
||||||
|
const char * const ftrace_usage[] = {
|
||||||
|
"perf ftrace [<options>] <command>",
|
||||||
|
"perf ftrace [<options>] -- <command> [<options>]",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
const struct option ftrace_options[] = {
|
||||||
|
OPT_STRING('t', "tracer", &ftrace.tracer, "tracer",
|
||||||
|
"tracer to use: function_graph(default) or function"),
|
||||||
|
OPT_INCR('v', "verbose", &verbose,
|
||||||
|
"be more verbose"),
|
||||||
|
OPT_END()
|
||||||
|
};
|
||||||
|
|
||||||
|
ret = perf_config(perf_ftrace_config, &ftrace);
|
||||||
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
argc = parse_options(argc, argv, ftrace_options, ftrace_usage,
|
||||||
|
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||||
|
if (!argc)
|
||||||
|
usage_with_options(ftrace_usage, ftrace_options);
|
||||||
|
|
||||||
|
ftrace.evlist = perf_evlist__new();
|
||||||
|
if (ftrace.evlist == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = perf_evlist__create_maps(ftrace.evlist, &ftrace.target);
|
||||||
|
if (ret < 0)
|
||||||
|
goto out_delete_evlist;
|
||||||
|
|
||||||
|
ret = __cmd_ftrace(&ftrace, argc, argv);
|
||||||
|
|
||||||
|
out_delete_evlist:
|
||||||
|
perf_evlist__delete(ftrace.evlist);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
@ -434,7 +434,7 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
const char * const builtin_help_subcommands[] = {
|
const char * const builtin_help_subcommands[] = {
|
||||||
"buildid-cache", "buildid-list", "diff", "evlist", "help", "list",
|
"buildid-cache", "buildid-list", "diff", "evlist", "help", "list",
|
||||||
"record", "report", "bench", "stat", "timechart", "top", "annotate",
|
"record", "report", "bench", "stat", "timechart", "top", "annotate",
|
||||||
"script", "sched", "kmem", "lock", "kvm", "test", "inject", "mem", "data",
|
"script", "sched", "kallsyms", "kmem", "lock", "kvm", "test", "inject", "mem", "data",
|
||||||
#ifdef HAVE_LIBELF_SUPPORT
|
#ifdef HAVE_LIBELF_SUPPORT
|
||||||
"probe",
|
"probe",
|
||||||
#endif
|
#endif
|
||||||
@ -447,11 +447,13 @@ int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
const char *alias;
|
const char *alias;
|
||||||
int rc = 0;
|
int rc;
|
||||||
|
|
||||||
load_command_list("perf-", &main_cmds, &other_cmds);
|
load_command_list("perf-", &main_cmds, &other_cmds);
|
||||||
|
|
||||||
perf_config(perf_help_config, &help_format);
|
rc = perf_config(perf_help_config, &help_format);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
argc = parse_options_subcommand(argc, argv, builtin_help_options,
|
argc = parse_options_subcommand(argc, argv, builtin_help_options,
|
||||||
builtin_help_subcommands, builtin_help_usage, 0);
|
builtin_help_subcommands, builtin_help_usage, 0);
|
||||||
|
67
tools/perf/builtin-kallsyms.c
Normal file
67
tools/perf/builtin-kallsyms.c
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* builtin-kallsyms.c
|
||||||
|
*
|
||||||
|
* Builtin command: Look for a symbol in the running kernel and its modules
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||||
|
*
|
||||||
|
* Released under the GPL v2. (and only v2, not any later version)
|
||||||
|
*/
|
||||||
|
#include "builtin.h"
|
||||||
|
#include <linux/compiler.h>
|
||||||
|
#include <subcmd/parse-options.h>
|
||||||
|
#include "debug.h"
|
||||||
|
#include "machine.h"
|
||||||
|
#include "symbol.h"
|
||||||
|
|
||||||
|
static int __cmd_kallsyms(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct machine *machine = machine__new_kallsyms();
|
||||||
|
|
||||||
|
if (machine == NULL) {
|
||||||
|
pr_err("Couldn't read /proc/kallsyms\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < argc; ++i) {
|
||||||
|
struct map *map;
|
||||||
|
struct symbol *symbol = machine__find_kernel_function_by_name(machine, argv[i], &map);
|
||||||
|
|
||||||
|
if (symbol == NULL) {
|
||||||
|
printf("%s: not found\n", argv[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s: %s %s %#" PRIx64 "-%#" PRIx64 " (%#" PRIx64 "-%#" PRIx64")\n",
|
||||||
|
symbol->name, map->dso->short_name, map->dso->long_name,
|
||||||
|
map->unmap_ip(map, symbol->start), map->unmap_ip(map, symbol->end),
|
||||||
|
symbol->start, symbol->end);
|
||||||
|
}
|
||||||
|
|
||||||
|
machine__delete(machine);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_kallsyms(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||||
|
{
|
||||||
|
const struct option options[] = {
|
||||||
|
OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"),
|
||||||
|
OPT_END()
|
||||||
|
};
|
||||||
|
const char * const kallsyms_usage[] = {
|
||||||
|
"perf kallsyms [<options>] symbol_name",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
argc = parse_options(argc, argv, options, kallsyms_usage, 0);
|
||||||
|
if (argc < 1)
|
||||||
|
usage_with_options(kallsyms_usage, options);
|
||||||
|
|
||||||
|
symbol_conf.sort_by_name = true;
|
||||||
|
symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
|
||||||
|
if (symbol__init(NULL) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return __cmd_kallsyms(argc, argv);
|
||||||
|
}
|
@ -1065,7 +1065,7 @@ static void __print_page_alloc_result(struct perf_session *session, int n_lines)
|
|||||||
|
|
||||||
data = rb_entry(next, struct page_stat, node);
|
data = rb_entry(next, struct page_stat, node);
|
||||||
sym = machine__find_kernel_function(machine, data->callsite, &map);
|
sym = machine__find_kernel_function(machine, data->callsite, &map);
|
||||||
if (sym && sym->name)
|
if (sym)
|
||||||
caller = sym->name;
|
caller = sym->name;
|
||||||
else
|
else
|
||||||
scnprintf(buf, sizeof(buf), "%"PRIx64, data->callsite);
|
scnprintf(buf, sizeof(buf), "%"PRIx64, data->callsite);
|
||||||
@ -1107,7 +1107,7 @@ static void __print_page_caller_result(struct perf_session *session, int n_lines
|
|||||||
|
|
||||||
data = rb_entry(next, struct page_stat, node);
|
data = rb_entry(next, struct page_stat, node);
|
||||||
sym = machine__find_kernel_function(machine, data->callsite, &map);
|
sym = machine__find_kernel_function(machine, data->callsite, &map);
|
||||||
if (sym && sym->name)
|
if (sym)
|
||||||
caller = sym->name;
|
caller = sym->name;
|
||||||
else
|
else
|
||||||
scnprintf(buf, sizeof(buf), "%"PRIx64, data->callsite);
|
scnprintf(buf, sizeof(buf), "%"PRIx64, data->callsite);
|
||||||
@ -1920,10 +1920,12 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
struct perf_session *session;
|
struct perf_session *session;
|
||||||
int ret = -1;
|
|
||||||
const char errmsg[] = "No %s allocation events found. Have you run 'perf kmem record --%s'?\n";
|
const char errmsg[] = "No %s allocation events found. Have you run 'perf kmem record --%s'?\n";
|
||||||
|
int ret = perf_config(kmem_config, NULL);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
perf_config(kmem_config, NULL);
|
|
||||||
argc = parse_options_subcommand(argc, argv, kmem_options,
|
argc = parse_options_subcommand(argc, argv, kmem_options,
|
||||||
kmem_subcommands, kmem_usage, 0);
|
kmem_subcommands, kmem_usage, 0);
|
||||||
|
|
||||||
@ -1948,6 +1950,8 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
if (session == NULL)
|
if (session == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
if (kmem_slab) {
|
if (kmem_slab) {
|
||||||
if (!perf_evlist__find_tracepoint_by_name(session->evlist,
|
if (!perf_evlist__find_tracepoint_by_name(session->evlist,
|
||||||
"kmem:kmalloc")) {
|
"kmem:kmalloc")) {
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "util/parse-events.h"
|
#include "util/parse-events.h"
|
||||||
#include "util/cache.h"
|
#include "util/cache.h"
|
||||||
#include "util/pmu.h"
|
#include "util/pmu.h"
|
||||||
|
#include "util/debug.h"
|
||||||
#include <subcmd/parse-options.h>
|
#include <subcmd/parse-options.h>
|
||||||
|
|
||||||
static bool desc_flag = true;
|
static bool desc_flag = true;
|
||||||
@ -29,6 +30,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
"Print extra event descriptions. --no-desc to not print."),
|
"Print extra event descriptions. --no-desc to not print."),
|
||||||
OPT_BOOLEAN('v', "long-desc", &long_desc_flag,
|
OPT_BOOLEAN('v', "long-desc", &long_desc_flag,
|
||||||
"Print longer event descriptions."),
|
"Print longer event descriptions."),
|
||||||
|
OPT_INCR(0, "debug", &verbose,
|
||||||
|
"Enable debugging output"),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
const char * const list_usage[] = {
|
const char * const list_usage[] = {
|
||||||
|
@ -552,6 +552,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
|
OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
|
||||||
"Enable kernel symbol demangling"),
|
"Enable kernel symbol demangling"),
|
||||||
OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
|
OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
|
||||||
|
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
|
||||||
|
"Look for files with symbols relative to this directory"),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -46,6 +46,15 @@
|
|||||||
#include <asm/bug.h>
|
#include <asm/bug.h>
|
||||||
#include <linux/time64.h>
|
#include <linux/time64.h>
|
||||||
|
|
||||||
|
struct switch_output {
|
||||||
|
bool enabled;
|
||||||
|
bool signal;
|
||||||
|
unsigned long size;
|
||||||
|
unsigned long time;
|
||||||
|
const char *str;
|
||||||
|
bool set;
|
||||||
|
};
|
||||||
|
|
||||||
struct record {
|
struct record {
|
||||||
struct perf_tool tool;
|
struct perf_tool tool;
|
||||||
struct record_opts opts;
|
struct record_opts opts;
|
||||||
@ -62,10 +71,33 @@ struct record {
|
|||||||
bool no_buildid_cache_set;
|
bool no_buildid_cache_set;
|
||||||
bool buildid_all;
|
bool buildid_all;
|
||||||
bool timestamp_filename;
|
bool timestamp_filename;
|
||||||
bool switch_output;
|
struct switch_output switch_output;
|
||||||
unsigned long long samples;
|
unsigned long long samples;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static volatile int auxtrace_record__snapshot_started;
|
||||||
|
static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
|
||||||
|
static DEFINE_TRIGGER(switch_output_trigger);
|
||||||
|
|
||||||
|
static bool switch_output_signal(struct record *rec)
|
||||||
|
{
|
||||||
|
return rec->switch_output.signal &&
|
||||||
|
trigger_is_ready(&switch_output_trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool switch_output_size(struct record *rec)
|
||||||
|
{
|
||||||
|
return rec->switch_output.size &&
|
||||||
|
trigger_is_ready(&switch_output_trigger) &&
|
||||||
|
(rec->bytes_written >= rec->switch_output.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool switch_output_time(struct record *rec)
|
||||||
|
{
|
||||||
|
return rec->switch_output.time &&
|
||||||
|
trigger_is_ready(&switch_output_trigger);
|
||||||
|
}
|
||||||
|
|
||||||
static int record__write(struct record *rec, void *bf, size_t size)
|
static int record__write(struct record *rec, void *bf, size_t size)
|
||||||
{
|
{
|
||||||
if (perf_data_file__write(rec->session->file, bf, size) < 0) {
|
if (perf_data_file__write(rec->session->file, bf, size) < 0) {
|
||||||
@ -74,6 +106,10 @@ static int record__write(struct record *rec, void *bf, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rec->bytes_written += size;
|
rec->bytes_written += size;
|
||||||
|
|
||||||
|
if (switch_output_size(rec))
|
||||||
|
trigger_hit(&switch_output_trigger);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,10 +229,6 @@ static volatile int done;
|
|||||||
static volatile int signr = -1;
|
static volatile int signr = -1;
|
||||||
static volatile int child_finished;
|
static volatile int child_finished;
|
||||||
|
|
||||||
static volatile int auxtrace_record__snapshot_started;
|
|
||||||
static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
|
|
||||||
static DEFINE_TRIGGER(switch_output_trigger);
|
|
||||||
|
|
||||||
static void sig_handler(int sig)
|
static void sig_handler(int sig)
|
||||||
{
|
{
|
||||||
if (sig == SIGCHLD)
|
if (sig == SIGCHLD)
|
||||||
@ -386,7 +418,7 @@ static int record__mmap(struct record *rec)
|
|||||||
|
|
||||||
static int record__open(struct record *rec)
|
static int record__open(struct record *rec)
|
||||||
{
|
{
|
||||||
char msg[512];
|
char msg[BUFSIZ];
|
||||||
struct perf_evsel *pos;
|
struct perf_evsel *pos;
|
||||||
struct perf_evlist *evlist = rec->evlist;
|
struct perf_evlist *evlist = rec->evlist;
|
||||||
struct perf_session *session = rec->session;
|
struct perf_session *session = rec->session;
|
||||||
@ -623,22 +655,23 @@ record__finish_output(struct record *rec)
|
|||||||
|
|
||||||
static int record__synthesize_workload(struct record *rec, bool tail)
|
static int record__synthesize_workload(struct record *rec, bool tail)
|
||||||
{
|
{
|
||||||
struct {
|
int err;
|
||||||
struct thread_map map;
|
struct thread_map *thread_map;
|
||||||
struct thread_map_data map_data;
|
|
||||||
} thread_map;
|
|
||||||
|
|
||||||
if (rec->opts.tail_synthesize != tail)
|
if (rec->opts.tail_synthesize != tail)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
thread_map.map.nr = 1;
|
thread_map = thread_map__new_by_tid(rec->evlist->workload.pid);
|
||||||
thread_map.map.map[0].pid = rec->evlist->workload.pid;
|
if (thread_map == NULL)
|
||||||
thread_map.map.map[0].comm = NULL;
|
return -1;
|
||||||
return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map,
|
|
||||||
|
err = perf_event__synthesize_thread_map(&rec->tool, thread_map,
|
||||||
process_synthesized_event,
|
process_synthesized_event,
|
||||||
&rec->session->machines.host,
|
&rec->session->machines.host,
|
||||||
rec->opts.sample_address,
|
rec->opts.sample_address,
|
||||||
rec->opts.proc_map_timeout);
|
rec->opts.proc_map_timeout);
|
||||||
|
thread_map__put(thread_map);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int record__synthesize(struct record *rec, bool tail);
|
static int record__synthesize(struct record *rec, bool tail);
|
||||||
@ -712,6 +745,7 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void snapshot_sig_handler(int sig);
|
static void snapshot_sig_handler(int sig);
|
||||||
|
static void alarm_sig_handler(int sig);
|
||||||
|
|
||||||
int __weak
|
int __weak
|
||||||
perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
|
perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
|
||||||
@ -842,11 +876,11 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
|
|||||||
signal(SIGTERM, sig_handler);
|
signal(SIGTERM, sig_handler);
|
||||||
signal(SIGSEGV, sigsegv_handler);
|
signal(SIGSEGV, sigsegv_handler);
|
||||||
|
|
||||||
if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
|
if (rec->opts.auxtrace_snapshot_mode || rec->switch_output.enabled) {
|
||||||
signal(SIGUSR2, snapshot_sig_handler);
|
signal(SIGUSR2, snapshot_sig_handler);
|
||||||
if (rec->opts.auxtrace_snapshot_mode)
|
if (rec->opts.auxtrace_snapshot_mode)
|
||||||
trigger_on(&auxtrace_snapshot_trigger);
|
trigger_on(&auxtrace_snapshot_trigger);
|
||||||
if (rec->switch_output)
|
if (rec->switch_output.enabled)
|
||||||
trigger_on(&switch_output_trigger);
|
trigger_on(&switch_output_trigger);
|
||||||
} else {
|
} else {
|
||||||
signal(SIGUSR2, SIG_IGN);
|
signal(SIGUSR2, SIG_IGN);
|
||||||
@ -1043,6 +1077,10 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
|
|||||||
err = fd;
|
err = fd;
|
||||||
goto out_child;
|
goto out_child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* re-arm the alarm */
|
||||||
|
if (rec->switch_output.time)
|
||||||
|
alarm(rec->switch_output.time);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hits == rec->samples) {
|
if (hits == rec->samples) {
|
||||||
@ -1352,6 +1390,78 @@ out_free:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void switch_output_size_warn(struct record *rec)
|
||||||
|
{
|
||||||
|
u64 wakeup_size = perf_evlist__mmap_size(rec->opts.mmap_pages);
|
||||||
|
struct switch_output *s = &rec->switch_output;
|
||||||
|
|
||||||
|
wakeup_size /= 2;
|
||||||
|
|
||||||
|
if (s->size < wakeup_size) {
|
||||||
|
char buf[100];
|
||||||
|
|
||||||
|
unit_number__scnprintf(buf, sizeof(buf), wakeup_size);
|
||||||
|
pr_warning("WARNING: switch-output data size lower than "
|
||||||
|
"wakeup kernel buffer size (%s) "
|
||||||
|
"expect bigger perf.data sizes\n", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int switch_output_setup(struct record *rec)
|
||||||
|
{
|
||||||
|
struct switch_output *s = &rec->switch_output;
|
||||||
|
static struct parse_tag tags_size[] = {
|
||||||
|
{ .tag = 'B', .mult = 1 },
|
||||||
|
{ .tag = 'K', .mult = 1 << 10 },
|
||||||
|
{ .tag = 'M', .mult = 1 << 20 },
|
||||||
|
{ .tag = 'G', .mult = 1 << 30 },
|
||||||
|
{ .tag = 0 },
|
||||||
|
};
|
||||||
|
static struct parse_tag tags_time[] = {
|
||||||
|
{ .tag = 's', .mult = 1 },
|
||||||
|
{ .tag = 'm', .mult = 60 },
|
||||||
|
{ .tag = 'h', .mult = 60*60 },
|
||||||
|
{ .tag = 'd', .mult = 60*60*24 },
|
||||||
|
{ .tag = 0 },
|
||||||
|
};
|
||||||
|
unsigned long val;
|
||||||
|
|
||||||
|
if (!s->set)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!strcmp(s->str, "signal")) {
|
||||||
|
s->signal = true;
|
||||||
|
pr_debug("switch-output with SIGUSR2 signal\n");
|
||||||
|
goto enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = parse_tag_value(s->str, tags_size);
|
||||||
|
if (val != (unsigned long) -1) {
|
||||||
|
s->size = val;
|
||||||
|
pr_debug("switch-output with %s size threshold\n", s->str);
|
||||||
|
goto enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = parse_tag_value(s->str, tags_time);
|
||||||
|
if (val != (unsigned long) -1) {
|
||||||
|
s->time = val;
|
||||||
|
pr_debug("switch-output with %s time threshold (%lu seconds)\n",
|
||||||
|
s->str, s->time);
|
||||||
|
goto enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
enabled:
|
||||||
|
rec->timestamp_filename = true;
|
||||||
|
s->enabled = true;
|
||||||
|
|
||||||
|
if (s->size && !rec->opts.no_buffering)
|
||||||
|
switch_output_size_warn(rec);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const char * const __record_usage[] = {
|
static const char * const __record_usage[] = {
|
||||||
"perf record [<options>] [<command>]",
|
"perf record [<options>] [<command>]",
|
||||||
"perf record [<options>] -- <command> [<options>]",
|
"perf record [<options>] -- <command> [<options>]",
|
||||||
@ -1519,8 +1629,10 @@ static struct option __record_options[] = {
|
|||||||
"Record build-id of all DSOs regardless of hits"),
|
"Record build-id of all DSOs regardless of hits"),
|
||||||
OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
|
OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
|
||||||
"append timestamp to output filename"),
|
"append timestamp to output filename"),
|
||||||
OPT_BOOLEAN(0, "switch-output", &record.switch_output,
|
OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
|
||||||
"Switch output when receive SIGUSR2"),
|
&record.switch_output.set, "signal,size,time",
|
||||||
|
"Switch output when receive SIGUSR2 or cross size,time threshold",
|
||||||
|
"signal"),
|
||||||
OPT_BOOLEAN(0, "dry-run", &dry_run,
|
OPT_BOOLEAN(0, "dry-run", &dry_run,
|
||||||
"Parse options then exit"),
|
"Parse options then exit"),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
@ -1559,7 +1671,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
if (rec->evlist == NULL)
|
if (rec->evlist == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
perf_config(perf_record_config, rec);
|
err = perf_config(perf_record_config, rec);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
argc = parse_options(argc, argv, record_options, record_usage,
|
argc = parse_options(argc, argv, record_options, record_usage,
|
||||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||||
@ -1578,8 +1692,15 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rec->switch_output)
|
if (switch_output_setup(rec)) {
|
||||||
rec->timestamp_filename = true;
|
parse_options_usage(record_usage, record_options, "switch-output", 0);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec->switch_output.time) {
|
||||||
|
signal(SIGALRM, alarm_sig_handler);
|
||||||
|
alarm(rec->switch_output.time);
|
||||||
|
}
|
||||||
|
|
||||||
if (!rec->itr) {
|
if (!rec->itr) {
|
||||||
rec->itr = auxtrace_record__init(rec->evlist, &err);
|
rec->itr = auxtrace_record__init(rec->evlist, &err);
|
||||||
@ -1629,7 +1750,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
|
|
||||||
if (rec->no_buildid_cache || rec->no_buildid) {
|
if (rec->no_buildid_cache || rec->no_buildid) {
|
||||||
disable_buildid_cache();
|
disable_buildid_cache();
|
||||||
} else if (rec->switch_output) {
|
} else if (rec->switch_output.enabled) {
|
||||||
/*
|
/*
|
||||||
* In 'perf record --switch-output', disable buildid
|
* In 'perf record --switch-output', disable buildid
|
||||||
* generation by default to reduce data file switching
|
* generation by default to reduce data file switching
|
||||||
@ -1721,6 +1842,8 @@ out:
|
|||||||
|
|
||||||
static void snapshot_sig_handler(int sig __maybe_unused)
|
static void snapshot_sig_handler(int sig __maybe_unused)
|
||||||
{
|
{
|
||||||
|
struct record *rec = &record;
|
||||||
|
|
||||||
if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
|
if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
|
||||||
trigger_hit(&auxtrace_snapshot_trigger);
|
trigger_hit(&auxtrace_snapshot_trigger);
|
||||||
auxtrace_record__snapshot_started = 1;
|
auxtrace_record__snapshot_started = 1;
|
||||||
@ -1728,6 +1851,14 @@ static void snapshot_sig_handler(int sig __maybe_unused)
|
|||||||
trigger_error(&auxtrace_snapshot_trigger);
|
trigger_error(&auxtrace_snapshot_trigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trigger_is_ready(&switch_output_trigger))
|
if (switch_output_signal(rec))
|
||||||
|
trigger_hit(&switch_output_trigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void alarm_sig_handler(int sig __maybe_unused)
|
||||||
|
{
|
||||||
|
struct record *rec = &record;
|
||||||
|
|
||||||
|
if (switch_output_time(rec))
|
||||||
trigger_hit(&switch_output_trigger);
|
trigger_hit(&switch_output_trigger);
|
||||||
}
|
}
|
||||||
|
@ -847,7 +847,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
perf_config(report__config, &report);
|
ret = perf_config(report__config, &report);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
argc = parse_options(argc, argv, options, report_usage, 0);
|
argc = parse_options(argc, argv, options, report_usage, 0);
|
||||||
if (argc) {
|
if (argc) {
|
||||||
|
@ -77,6 +77,22 @@ struct sched_atom {
|
|||||||
|
|
||||||
#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP"
|
#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP"
|
||||||
|
|
||||||
|
/* task state bitmask, copied from include/linux/sched.h */
|
||||||
|
#define TASK_RUNNING 0
|
||||||
|
#define TASK_INTERRUPTIBLE 1
|
||||||
|
#define TASK_UNINTERRUPTIBLE 2
|
||||||
|
#define __TASK_STOPPED 4
|
||||||
|
#define __TASK_TRACED 8
|
||||||
|
/* in tsk->exit_state */
|
||||||
|
#define EXIT_DEAD 16
|
||||||
|
#define EXIT_ZOMBIE 32
|
||||||
|
#define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD)
|
||||||
|
/* in tsk->state again */
|
||||||
|
#define TASK_DEAD 64
|
||||||
|
#define TASK_WAKEKILL 128
|
||||||
|
#define TASK_WAKING 256
|
||||||
|
#define TASK_PARKED 512
|
||||||
|
|
||||||
enum thread_state {
|
enum thread_state {
|
||||||
THREAD_SLEEPING = 0,
|
THREAD_SLEEPING = 0,
|
||||||
THREAD_WAIT_CPU,
|
THREAD_WAIT_CPU,
|
||||||
@ -206,6 +222,7 @@ struct perf_sched {
|
|||||||
bool show_cpu_visual;
|
bool show_cpu_visual;
|
||||||
bool show_wakeups;
|
bool show_wakeups;
|
||||||
bool show_migrations;
|
bool show_migrations;
|
||||||
|
bool show_state;
|
||||||
u64 skipped_samples;
|
u64 skipped_samples;
|
||||||
const char *time_str;
|
const char *time_str;
|
||||||
struct perf_time_interval ptime;
|
struct perf_time_interval ptime;
|
||||||
@ -216,13 +233,20 @@ struct perf_sched {
|
|||||||
struct thread_runtime {
|
struct thread_runtime {
|
||||||
u64 last_time; /* time of previous sched in/out event */
|
u64 last_time; /* time of previous sched in/out event */
|
||||||
u64 dt_run; /* run time */
|
u64 dt_run; /* run time */
|
||||||
u64 dt_wait; /* time between CPU access (off cpu) */
|
u64 dt_sleep; /* time between CPU access by sleep (off cpu) */
|
||||||
|
u64 dt_iowait; /* time between CPU access by iowait (off cpu) */
|
||||||
|
u64 dt_preempt; /* time between CPU access by preempt (off cpu) */
|
||||||
u64 dt_delay; /* time between wakeup and sched-in */
|
u64 dt_delay; /* time between wakeup and sched-in */
|
||||||
u64 ready_to_run; /* time of wakeup */
|
u64 ready_to_run; /* time of wakeup */
|
||||||
|
|
||||||
struct stats run_stats;
|
struct stats run_stats;
|
||||||
u64 total_run_time;
|
u64 total_run_time;
|
||||||
|
u64 total_sleep_time;
|
||||||
|
u64 total_iowait_time;
|
||||||
|
u64 total_preempt_time;
|
||||||
|
u64 total_delay_time;
|
||||||
|
|
||||||
|
int last_state;
|
||||||
u64 migrations;
|
u64 migrations;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1821,6 +1845,9 @@ static void timehist_header(struct perf_sched *sched)
|
|||||||
printf(" %-*s %9s %9s %9s", comm_width,
|
printf(" %-*s %9s %9s %9s", comm_width,
|
||||||
"task name", "wait time", "sch delay", "run time");
|
"task name", "wait time", "sch delay", "run time");
|
||||||
|
|
||||||
|
if (sched->show_state)
|
||||||
|
printf(" %s", "state");
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1831,9 +1858,14 @@ static void timehist_header(struct perf_sched *sched)
|
|||||||
if (sched->show_cpu_visual)
|
if (sched->show_cpu_visual)
|
||||||
printf(" %*s ", ncpus, "");
|
printf(" %*s ", ncpus, "");
|
||||||
|
|
||||||
printf(" %-*s %9s %9s %9s\n", comm_width,
|
printf(" %-*s %9s %9s %9s", comm_width,
|
||||||
"[tid/pid]", "(msec)", "(msec)", "(msec)");
|
"[tid/pid]", "(msec)", "(msec)", "(msec)");
|
||||||
|
|
||||||
|
if (sched->show_state)
|
||||||
|
printf(" %5s", "");
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* separator
|
* separator
|
||||||
*/
|
*/
|
||||||
@ -1846,18 +1878,34 @@ static void timehist_header(struct perf_sched *sched)
|
|||||||
graph_dotted_line, graph_dotted_line, graph_dotted_line,
|
graph_dotted_line, graph_dotted_line, graph_dotted_line,
|
||||||
graph_dotted_line);
|
graph_dotted_line);
|
||||||
|
|
||||||
|
if (sched->show_state)
|
||||||
|
printf(" %.5s", graph_dotted_line);
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char task_state_char(struct thread *thread, int state)
|
||||||
|
{
|
||||||
|
static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
|
||||||
|
unsigned bit = state ? ffs(state) : 0;
|
||||||
|
|
||||||
|
/* 'I' for idle */
|
||||||
|
if (thread->tid == 0)
|
||||||
|
return 'I';
|
||||||
|
|
||||||
|
return bit < sizeof(state_to_char) - 1 ? state_to_char[bit] : '?';
|
||||||
|
}
|
||||||
|
|
||||||
static void timehist_print_sample(struct perf_sched *sched,
|
static void timehist_print_sample(struct perf_sched *sched,
|
||||||
struct perf_sample *sample,
|
struct perf_sample *sample,
|
||||||
struct addr_location *al,
|
struct addr_location *al,
|
||||||
struct thread *thread,
|
struct thread *thread,
|
||||||
u64 t)
|
u64 t, int state)
|
||||||
{
|
{
|
||||||
struct thread_runtime *tr = thread__priv(thread);
|
struct thread_runtime *tr = thread__priv(thread);
|
||||||
u32 max_cpus = sched->max_cpu + 1;
|
u32 max_cpus = sched->max_cpu + 1;
|
||||||
char tstr[64];
|
char tstr[64];
|
||||||
|
u64 wait_time;
|
||||||
|
|
||||||
timestamp__scnprintf_usec(t, tstr, sizeof(tstr));
|
timestamp__scnprintf_usec(t, tstr, sizeof(tstr));
|
||||||
printf("%15s [%04d] ", tstr, sample->cpu);
|
printf("%15s [%04d] ", tstr, sample->cpu);
|
||||||
@ -1880,10 +1928,15 @@ static void timehist_print_sample(struct perf_sched *sched,
|
|||||||
|
|
||||||
printf(" %-*s ", comm_width, timehist_get_commstr(thread));
|
printf(" %-*s ", comm_width, timehist_get_commstr(thread));
|
||||||
|
|
||||||
print_sched_time(tr->dt_wait, 6);
|
wait_time = tr->dt_sleep + tr->dt_iowait + tr->dt_preempt;
|
||||||
|
print_sched_time(wait_time, 6);
|
||||||
|
|
||||||
print_sched_time(tr->dt_delay, 6);
|
print_sched_time(tr->dt_delay, 6);
|
||||||
print_sched_time(tr->dt_run, 6);
|
print_sched_time(tr->dt_run, 6);
|
||||||
|
|
||||||
|
if (sched->show_state)
|
||||||
|
printf(" %5c ", task_state_char(thread, state));
|
||||||
|
|
||||||
if (sched->show_wakeups)
|
if (sched->show_wakeups)
|
||||||
printf(" %-*s", comm_width, "");
|
printf(" %-*s", comm_width, "");
|
||||||
|
|
||||||
@ -1930,8 +1983,11 @@ static void timehist_update_runtime_stats(struct thread_runtime *r,
|
|||||||
u64 t, u64 tprev)
|
u64 t, u64 tprev)
|
||||||
{
|
{
|
||||||
r->dt_delay = 0;
|
r->dt_delay = 0;
|
||||||
r->dt_wait = 0;
|
r->dt_sleep = 0;
|
||||||
|
r->dt_iowait = 0;
|
||||||
|
r->dt_preempt = 0;
|
||||||
r->dt_run = 0;
|
r->dt_run = 0;
|
||||||
|
|
||||||
if (tprev) {
|
if (tprev) {
|
||||||
r->dt_run = t - tprev;
|
r->dt_run = t - tprev;
|
||||||
if (r->ready_to_run) {
|
if (r->ready_to_run) {
|
||||||
@ -1943,12 +1999,25 @@ static void timehist_update_runtime_stats(struct thread_runtime *r,
|
|||||||
|
|
||||||
if (r->last_time > tprev)
|
if (r->last_time > tprev)
|
||||||
pr_debug("time travel: last sched out time for task > previous sched_switch event\n");
|
pr_debug("time travel: last sched out time for task > previous sched_switch event\n");
|
||||||
else if (r->last_time)
|
else if (r->last_time) {
|
||||||
r->dt_wait = tprev - r->last_time;
|
u64 dt_wait = tprev - r->last_time;
|
||||||
|
|
||||||
|
if (r->last_state == TASK_RUNNING)
|
||||||
|
r->dt_preempt = dt_wait;
|
||||||
|
else if (r->last_state == TASK_UNINTERRUPTIBLE)
|
||||||
|
r->dt_iowait = dt_wait;
|
||||||
|
else
|
||||||
|
r->dt_sleep = dt_wait;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_stats(&r->run_stats, r->dt_run);
|
update_stats(&r->run_stats, r->dt_run);
|
||||||
r->total_run_time += r->dt_run;
|
|
||||||
|
r->total_run_time += r->dt_run;
|
||||||
|
r->total_delay_time += r->dt_delay;
|
||||||
|
r->total_sleep_time += r->dt_sleep;
|
||||||
|
r->total_iowait_time += r->dt_iowait;
|
||||||
|
r->total_preempt_time += r->dt_preempt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_idle_sample(struct perf_sample *sample,
|
static bool is_idle_sample(struct perf_sample *sample,
|
||||||
@ -1998,7 +2067,7 @@ static void save_task_callchain(struct perf_sched *sched,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
sym = node->sym;
|
sym = node->sym;
|
||||||
if (sym && sym->name) {
|
if (sym) {
|
||||||
if (!strcmp(sym->name, "schedule") ||
|
if (!strcmp(sym->name, "schedule") ||
|
||||||
!strcmp(sym->name, "__schedule") ||
|
!strcmp(sym->name, "__schedule") ||
|
||||||
!strcmp(sym->name, "preempt_schedule"))
|
!strcmp(sym->name, "preempt_schedule"))
|
||||||
@ -2373,6 +2442,8 @@ static int timehist_sched_change_event(struct perf_tool *tool,
|
|||||||
struct thread_runtime *tr = NULL;
|
struct thread_runtime *tr = NULL;
|
||||||
u64 tprev, t = sample->time;
|
u64 tprev, t = sample->time;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
int state = perf_evsel__intval(evsel, sample, "prev_state");
|
||||||
|
|
||||||
|
|
||||||
if (machine__resolve(machine, &al, sample) < 0) {
|
if (machine__resolve(machine, &al, sample) < 0) {
|
||||||
pr_err("problem processing %d event. skipping it\n",
|
pr_err("problem processing %d event. skipping it\n",
|
||||||
@ -2447,8 +2518,10 @@ static int timehist_sched_change_event(struct perf_tool *tool,
|
|||||||
* time. we only care total run time and run stat.
|
* time. we only care total run time and run stat.
|
||||||
*/
|
*/
|
||||||
last_tr->dt_run = 0;
|
last_tr->dt_run = 0;
|
||||||
last_tr->dt_wait = 0;
|
|
||||||
last_tr->dt_delay = 0;
|
last_tr->dt_delay = 0;
|
||||||
|
last_tr->dt_sleep = 0;
|
||||||
|
last_tr->dt_iowait = 0;
|
||||||
|
last_tr->dt_preempt = 0;
|
||||||
|
|
||||||
if (itr->cursor.nr)
|
if (itr->cursor.nr)
|
||||||
callchain_append(&itr->callchain, &itr->cursor, t - tprev);
|
callchain_append(&itr->callchain, &itr->cursor, t - tprev);
|
||||||
@ -2458,7 +2531,7 @@ static int timehist_sched_change_event(struct perf_tool *tool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!sched->summary_only)
|
if (!sched->summary_only)
|
||||||
timehist_print_sample(sched, sample, &al, thread, t);
|
timehist_print_sample(sched, sample, &al, thread, t, state);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (sched->hist_time.start == 0 && t >= ptime->start)
|
if (sched->hist_time.start == 0 && t >= ptime->start)
|
||||||
@ -2470,6 +2543,9 @@ out:
|
|||||||
/* time of this sched_switch event becomes last time task seen */
|
/* time of this sched_switch event becomes last time task seen */
|
||||||
tr->last_time = sample->time;
|
tr->last_time = sample->time;
|
||||||
|
|
||||||
|
/* last state is used to determine where to account wait time */
|
||||||
|
tr->last_state = state;
|
||||||
|
|
||||||
/* sched out event for task so reset ready to run time */
|
/* sched out event for task so reset ready to run time */
|
||||||
tr->ready_to_run = 0;
|
tr->ready_to_run = 0;
|
||||||
}
|
}
|
||||||
@ -2526,7 +2602,26 @@ static void print_thread_runtime(struct thread *t,
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print_thread_waittime(struct thread *t,
|
||||||
|
struct thread_runtime *r)
|
||||||
|
{
|
||||||
|
printf("%*s %5d %9" PRIu64 " ",
|
||||||
|
comm_width, timehist_get_commstr(t), t->ppid,
|
||||||
|
(u64) r->run_stats.n);
|
||||||
|
|
||||||
|
print_sched_time(r->total_run_time, 8);
|
||||||
|
print_sched_time(r->total_sleep_time, 6);
|
||||||
|
printf(" ");
|
||||||
|
print_sched_time(r->total_iowait_time, 6);
|
||||||
|
printf(" ");
|
||||||
|
print_sched_time(r->total_preempt_time, 6);
|
||||||
|
printf(" ");
|
||||||
|
print_sched_time(r->total_delay_time, 6);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
struct total_run_stats {
|
struct total_run_stats {
|
||||||
|
struct perf_sched *sched;
|
||||||
u64 sched_count;
|
u64 sched_count;
|
||||||
u64 task_count;
|
u64 task_count;
|
||||||
u64 total_run_time;
|
u64 total_run_time;
|
||||||
@ -2545,7 +2640,11 @@ static int __show_thread_runtime(struct thread *t, void *priv)
|
|||||||
stats->task_count++;
|
stats->task_count++;
|
||||||
stats->sched_count += r->run_stats.n;
|
stats->sched_count += r->run_stats.n;
|
||||||
stats->total_run_time += r->total_run_time;
|
stats->total_run_time += r->total_run_time;
|
||||||
print_thread_runtime(t, r);
|
|
||||||
|
if (stats->sched->show_state)
|
||||||
|
print_thread_waittime(t, r);
|
||||||
|
else
|
||||||
|
print_thread_runtime(t, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -2633,18 +2732,24 @@ static void timehist_print_summary(struct perf_sched *sched,
|
|||||||
u64 hist_time = sched->hist_time.end - sched->hist_time.start;
|
u64 hist_time = sched->hist_time.end - sched->hist_time.start;
|
||||||
|
|
||||||
memset(&totals, 0, sizeof(totals));
|
memset(&totals, 0, sizeof(totals));
|
||||||
|
totals.sched = sched;
|
||||||
|
|
||||||
if (sched->idle_hist) {
|
if (sched->idle_hist) {
|
||||||
printf("\nIdle-time summary\n");
|
printf("\nIdle-time summary\n");
|
||||||
printf("%*s parent sched-out ", comm_width, "comm");
|
printf("%*s parent sched-out ", comm_width, "comm");
|
||||||
printf(" idle-time min-idle avg-idle max-idle stddev migrations\n");
|
printf(" idle-time min-idle avg-idle max-idle stddev migrations\n");
|
||||||
|
} else if (sched->show_state) {
|
||||||
|
printf("\nWait-time summary\n");
|
||||||
|
printf("%*s parent sched-in ", comm_width, "comm");
|
||||||
|
printf(" run-time sleep iowait preempt delay\n");
|
||||||
} else {
|
} else {
|
||||||
printf("\nRuntime summary\n");
|
printf("\nRuntime summary\n");
|
||||||
printf("%*s parent sched-in ", comm_width, "comm");
|
printf("%*s parent sched-in ", comm_width, "comm");
|
||||||
printf(" run-time min-run avg-run max-run stddev migrations\n");
|
printf(" run-time min-run avg-run max-run stddev migrations\n");
|
||||||
}
|
}
|
||||||
printf("%*s (count) ", comm_width, "");
|
printf("%*s (count) ", comm_width, "");
|
||||||
printf(" (msec) (msec) (msec) (msec) %%\n");
|
printf(" (msec) (msec) (msec) (msec) %s\n",
|
||||||
|
sched->show_state ? "(msec)" : "%");
|
||||||
printf("%.117s\n", graph_dotted_line);
|
printf("%.117s\n", graph_dotted_line);
|
||||||
|
|
||||||
machine__for_each_thread(m, show_thread_runtime, &totals);
|
machine__for_each_thread(m, show_thread_runtime, &totals);
|
||||||
@ -3240,6 +3345,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
OPT_BOOLEAN('I', "idle-hist", &sched.idle_hist, "Show idle events only"),
|
OPT_BOOLEAN('I', "idle-hist", &sched.idle_hist, "Show idle events only"),
|
||||||
OPT_STRING(0, "time", &sched.time_str, "str",
|
OPT_STRING(0, "time", &sched.time_str, "str",
|
||||||
"Time span for analysis (start,stop)"),
|
"Time span for analysis (start,stop)"),
|
||||||
|
OPT_BOOLEAN(0, "state", &sched.show_state, "Show task state when sched-out"),
|
||||||
OPT_PARENT(sched_options)
|
OPT_PARENT(sched_options)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2180,7 +2180,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
"Show the mmap events"),
|
"Show the mmap events"),
|
||||||
OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,
|
OPT_BOOLEAN('\0', "show-switch-events", &script.show_switch_events,
|
||||||
"Show context switch events (if recorded)"),
|
"Show context switch events (if recorded)"),
|
||||||
OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
|
OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
|
||||||
OPT_BOOLEAN(0, "ns", &nanosecs,
|
OPT_BOOLEAN(0, "ns", &nanosecs,
|
||||||
"Use 9 decimal places when displaying time"),
|
"Use 9 decimal places when displaying time"),
|
||||||
OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
|
OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
|
||||||
@ -2212,6 +2212,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||||
|
|
||||||
file.path = input_name;
|
file.path = input_name;
|
||||||
|
file.force = symbol_conf.force;
|
||||||
|
|
||||||
if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
|
if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) {
|
||||||
rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
|
rec_script_path = get_script_path(argv[1], RECORD_SUFFIX);
|
||||||
|
@ -533,7 +533,7 @@ static int store_counter_ids(struct perf_evsel *counter)
|
|||||||
static int __run_perf_stat(int argc, const char **argv)
|
static int __run_perf_stat(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
int interval = stat_config.interval;
|
int interval = stat_config.interval;
|
||||||
char msg[512];
|
char msg[BUFSIZ];
|
||||||
unsigned long long t0, t1;
|
unsigned long long t0, t1;
|
||||||
struct perf_evsel *counter;
|
struct perf_evsel *counter;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
@ -643,7 +643,7 @@ repeat:
|
|||||||
case -1:
|
case -1:
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
/* Fall trhu */
|
__fallthrough;
|
||||||
default:
|
default:
|
||||||
c = getc(stdin);
|
c = getc(stdin);
|
||||||
tcsetattr(0, TCSAFLUSH, &save);
|
tcsetattr(0, TCSAFLUSH, &save);
|
||||||
@ -859,7 +859,7 @@ static void perf_top__mmap_read(struct perf_top *top)
|
|||||||
|
|
||||||
static int perf_top__start_counters(struct perf_top *top)
|
static int perf_top__start_counters(struct perf_top *top)
|
||||||
{
|
{
|
||||||
char msg[512];
|
char msg[BUFSIZ];
|
||||||
struct perf_evsel *counter;
|
struct perf_evsel *counter;
|
||||||
struct perf_evlist *evlist = top->evlist;
|
struct perf_evlist *evlist = top->evlist;
|
||||||
struct record_opts *opts = &top->record_opts;
|
struct record_opts *opts = &top->record_opts;
|
||||||
@ -1216,7 +1216,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
if (top.evlist == NULL)
|
if (top.evlist == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
perf_config(perf_top_config, &top);
|
status = perf_config(perf_top_config, &top);
|
||||||
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
argc = parse_options(argc, argv, options, top_usage, 0);
|
argc = parse_options(argc, argv, options, top_usage, 0);
|
||||||
if (argc)
|
if (argc)
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
|
#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
#include <linux/audit.h>
|
#include <linux/audit.h>
|
||||||
@ -2699,6 +2700,91 @@ static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
|
|||||||
evsel->handler = handler;
|
evsel->handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: Hackish, just splitting the combined -e+--event (syscalls
|
||||||
|
* (raw_syscalls:{sys_{enter,exit}} + events (tracepoints, HW, SW, etc) to use
|
||||||
|
* existing facilities unchanged (trace->ev_qualifier + parse_options()).
|
||||||
|
*
|
||||||
|
* It'd be better to introduce a parse_options() variant that would return a
|
||||||
|
* list with the terms it didn't match to an event...
|
||||||
|
*/
|
||||||
|
static int trace__parse_events_option(const struct option *opt, const char *str,
|
||||||
|
int unset __maybe_unused)
|
||||||
|
{
|
||||||
|
struct trace *trace = (struct trace *)opt->value;
|
||||||
|
const char *s = str;
|
||||||
|
char *sep = NULL, *lists[2] = { NULL, NULL, };
|
||||||
|
int len = strlen(str), err = -1, list;
|
||||||
|
char *strace_groups_dir = system_path(STRACE_GROUPS_DIR);
|
||||||
|
char group_name[PATH_MAX];
|
||||||
|
|
||||||
|
if (strace_groups_dir == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (*s == '!') {
|
||||||
|
++s;
|
||||||
|
trace->not_ev_qualifier = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if ((sep = strchr(s, ',')) != NULL)
|
||||||
|
*sep = '\0';
|
||||||
|
|
||||||
|
list = 0;
|
||||||
|
if (syscalltbl__id(trace->sctbl, s) >= 0) {
|
||||||
|
list = 1;
|
||||||
|
} else {
|
||||||
|
path__join(group_name, sizeof(group_name), strace_groups_dir, s);
|
||||||
|
if (access(group_name, R_OK) == 0)
|
||||||
|
list = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lists[list]) {
|
||||||
|
sprintf(lists[list] + strlen(lists[list]), ",%s", s);
|
||||||
|
} else {
|
||||||
|
lists[list] = malloc(len);
|
||||||
|
if (lists[list] == NULL)
|
||||||
|
goto out;
|
||||||
|
strcpy(lists[list], s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sep)
|
||||||
|
break;
|
||||||
|
|
||||||
|
*sep = ',';
|
||||||
|
s = sep + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lists[1] != NULL) {
|
||||||
|
struct strlist_config slist_config = {
|
||||||
|
.dirname = strace_groups_dir,
|
||||||
|
};
|
||||||
|
|
||||||
|
trace->ev_qualifier = strlist__new(lists[1], &slist_config);
|
||||||
|
if (trace->ev_qualifier == NULL) {
|
||||||
|
fputs("Not enough memory to parse event qualifier", trace->output);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trace__validate_ev_qualifier(trace))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
if (lists[0]) {
|
||||||
|
struct option o = OPT_CALLBACK('e', "event", &trace->evlist, "event",
|
||||||
|
"event selector. use 'perf list' to list available events",
|
||||||
|
parse_events_option);
|
||||||
|
err = parse_events_option(&o, lists[0], 0);
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
if (sep)
|
||||||
|
*sep = ',';
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
|
int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||||
{
|
{
|
||||||
const char *trace_usage[] = {
|
const char *trace_usage[] = {
|
||||||
@ -2730,15 +2816,15 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
.max_stack = UINT_MAX,
|
.max_stack = UINT_MAX,
|
||||||
};
|
};
|
||||||
const char *output_name = NULL;
|
const char *output_name = NULL;
|
||||||
const char *ev_qualifier_str = NULL;
|
|
||||||
const struct option trace_options[] = {
|
const struct option trace_options[] = {
|
||||||
OPT_CALLBACK(0, "event", &trace.evlist, "event",
|
OPT_CALLBACK('e', "event", &trace, "event",
|
||||||
"event selector. use 'perf list' to list available events",
|
"event/syscall selector. use 'perf list' to list available events",
|
||||||
parse_events_option),
|
trace__parse_events_option),
|
||||||
OPT_BOOLEAN(0, "comm", &trace.show_comm,
|
OPT_BOOLEAN(0, "comm", &trace.show_comm,
|
||||||
"show the thread COMM next to its id"),
|
"show the thread COMM next to its id"),
|
||||||
OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
|
OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),
|
||||||
OPT_STRING('e', "expr", &ev_qualifier_str, "expr", "list of syscalls to trace"),
|
OPT_CALLBACK(0, "expr", &trace, "expr", "list of syscalls/events to trace",
|
||||||
|
trace__parse_events_option),
|
||||||
OPT_STRING('o', "output", &output_name, "file", "output file name"),
|
OPT_STRING('o', "output", &output_name, "file", "output file name"),
|
||||||
OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
|
OPT_STRING('i', "input", &input_name, "file", "Analyze events in file"),
|
||||||
OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
|
OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
|
||||||
@ -2863,7 +2949,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!trace.trace_syscalls && ev_qualifier_str) {
|
if (!trace.trace_syscalls && trace.ev_qualifier) {
|
||||||
pr_err("The -e option can't be used with --no-syscalls.\n");
|
pr_err("The -e option can't be used with --no-syscalls.\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -2878,28 +2964,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||||||
|
|
||||||
trace.open_id = syscalltbl__id(trace.sctbl, "open");
|
trace.open_id = syscalltbl__id(trace.sctbl, "open");
|
||||||
|
|
||||||
if (ev_qualifier_str != NULL) {
|
|
||||||
const char *s = ev_qualifier_str;
|
|
||||||
struct strlist_config slist_config = {
|
|
||||||
.dirname = system_path(STRACE_GROUPS_DIR),
|
|
||||||
};
|
|
||||||
|
|
||||||
trace.not_ev_qualifier = *s == '!';
|
|
||||||
if (trace.not_ev_qualifier)
|
|
||||||
++s;
|
|
||||||
trace.ev_qualifier = strlist__new(s, &slist_config);
|
|
||||||
if (trace.ev_qualifier == NULL) {
|
|
||||||
fputs("Not enough memory to parse event qualifier",
|
|
||||||
trace.output);
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto out_close;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = trace__validate_ev_qualifier(&trace);
|
|
||||||
if (err)
|
|
||||||
goto out_close;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = target__validate(&trace.opts.target);
|
err = target__validate(&trace.opts.target);
|
||||||
if (err) {
|
if (err) {
|
||||||
target__strerror(&trace.opts.target, err, bf, sizeof(bf));
|
target__strerror(&trace.opts.target, err, bf, sizeof(bf));
|
||||||
|
@ -23,6 +23,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix);
|
|||||||
int cmd_evlist(int argc, const char **argv, const char *prefix);
|
int cmd_evlist(int argc, const char **argv, const char *prefix);
|
||||||
int cmd_help(int argc, const char **argv, const char *prefix);
|
int cmd_help(int argc, const char **argv, const char *prefix);
|
||||||
int cmd_sched(int argc, const char **argv, const char *prefix);
|
int cmd_sched(int argc, const char **argv, const char *prefix);
|
||||||
|
int cmd_kallsyms(int argc, const char **argv, const char *prefix);
|
||||||
int cmd_list(int argc, const char **argv, const char *prefix);
|
int cmd_list(int argc, const char **argv, const char *prefix);
|
||||||
int cmd_record(int argc, const char **argv, const char *prefix);
|
int cmd_record(int argc, const char **argv, const char *prefix);
|
||||||
int cmd_report(int argc, const char **argv, const char *prefix);
|
int cmd_report(int argc, const char **argv, const char *prefix);
|
||||||
@ -40,6 +41,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix);
|
|||||||
int cmd_inject(int argc, const char **argv, const char *prefix);
|
int cmd_inject(int argc, const char **argv, const char *prefix);
|
||||||
int cmd_mem(int argc, const char **argv, const char *prefix);
|
int cmd_mem(int argc, const char **argv, const char *prefix);
|
||||||
int cmd_data(int argc, const char **argv, const char *prefix);
|
int cmd_data(int argc, const char **argv, const char *prefix);
|
||||||
|
int cmd_ftrace(int argc, const char **argv, const char *prefix);
|
||||||
|
|
||||||
int find_scripts(char **scripts_array, char **scripts_path_array);
|
int find_scripts(char **scripts_array, char **scripts_path_array);
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,7 +11,9 @@ perf-data mainporcelain common
|
|||||||
perf-diff mainporcelain common
|
perf-diff mainporcelain common
|
||||||
perf-config mainporcelain common
|
perf-config mainporcelain common
|
||||||
perf-evlist mainporcelain common
|
perf-evlist mainporcelain common
|
||||||
|
perf-ftrace mainporcelain common
|
||||||
perf-inject mainporcelain common
|
perf-inject mainporcelain common
|
||||||
|
perf-kallsyms mainporcelain common
|
||||||
perf-kmem mainporcelain common
|
perf-kmem mainporcelain common
|
||||||
perf-kvm mainporcelain common
|
perf-kvm mainporcelain common
|
||||||
perf-list mainporcelain common
|
perf-list mainporcelain common
|
||||||
|
@ -29,7 +29,6 @@ const char perf_usage_string[] =
|
|||||||
const char perf_more_info_string[] =
|
const char perf_more_info_string[] =
|
||||||
"See 'perf help COMMAND' for more information on a specific command.";
|
"See 'perf help COMMAND' for more information on a specific command.";
|
||||||
|
|
||||||
int use_browser = -1;
|
|
||||||
static int use_pager = -1;
|
static int use_pager = -1;
|
||||||
const char *input_name;
|
const char *input_name;
|
||||||
|
|
||||||
@ -47,6 +46,7 @@ static struct cmd_struct commands[] = {
|
|||||||
{ "diff", cmd_diff, 0 },
|
{ "diff", cmd_diff, 0 },
|
||||||
{ "evlist", cmd_evlist, 0 },
|
{ "evlist", cmd_evlist, 0 },
|
||||||
{ "help", cmd_help, 0 },
|
{ "help", cmd_help, 0 },
|
||||||
|
{ "kallsyms", cmd_kallsyms, 0 },
|
||||||
{ "list", cmd_list, 0 },
|
{ "list", cmd_list, 0 },
|
||||||
{ "record", cmd_record, 0 },
|
{ "record", cmd_record, 0 },
|
||||||
{ "report", cmd_report, 0 },
|
{ "report", cmd_report, 0 },
|
||||||
@ -71,6 +71,7 @@ static struct cmd_struct commands[] = {
|
|||||||
{ "inject", cmd_inject, 0 },
|
{ "inject", cmd_inject, 0 },
|
||||||
{ "mem", cmd_mem, 0 },
|
{ "mem", cmd_mem, 0 },
|
||||||
{ "data", cmd_data, 0 },
|
{ "data", cmd_data, 0 },
|
||||||
|
{ "ftrace", cmd_ftrace, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pager_config {
|
struct pager_config {
|
||||||
@ -89,11 +90,12 @@ static int pager_command_config(const char *var, const char *value, void *data)
|
|||||||
/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
|
/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
|
||||||
int check_pager_config(const char *cmd)
|
int check_pager_config(const char *cmd)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
struct pager_config c;
|
struct pager_config c;
|
||||||
c.cmd = cmd;
|
c.cmd = cmd;
|
||||||
c.val = -1;
|
c.val = -1;
|
||||||
perf_config(pager_command_config, &c);
|
err = perf_config(pager_command_config, &c);
|
||||||
return c.val;
|
return err ?: c.val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int browser_command_config(const char *var, const char *value, void *data)
|
static int browser_command_config(const char *var, const char *value, void *data)
|
||||||
@ -112,11 +114,12 @@ static int browser_command_config(const char *var, const char *value, void *data
|
|||||||
*/
|
*/
|
||||||
static int check_browser_config(const char *cmd)
|
static int check_browser_config(const char *cmd)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
struct pager_config c;
|
struct pager_config c;
|
||||||
c.cmd = cmd;
|
c.cmd = cmd;
|
||||||
c.val = -1;
|
c.val = -1;
|
||||||
perf_config(browser_command_config, &c);
|
err = perf_config(browser_command_config, &c);
|
||||||
return c.val;
|
return err ?: c.val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void commit_pager_choice(void)
|
static void commit_pager_choice(void)
|
||||||
@ -329,8 +332,6 @@ static int handle_alias(int *argcp, const char ***argv)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char perf_version_string[] = PERF_VERSION;
|
|
||||||
|
|
||||||
#define RUN_SETUP (1<<0)
|
#define RUN_SETUP (1<<0)
|
||||||
#define USE_PAGER (1<<1)
|
#define USE_PAGER (1<<1)
|
||||||
|
|
||||||
@ -510,6 +511,7 @@ static void cache_line_size(int *cacheline_sizep)
|
|||||||
|
|
||||||
int main(int argc, const char **argv)
|
int main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
const char *cmd;
|
const char *cmd;
|
||||||
char sbuf[STRERR_BUFSIZE];
|
char sbuf[STRERR_BUFSIZE];
|
||||||
int value;
|
int value;
|
||||||
@ -535,7 +537,9 @@ int main(int argc, const char **argv)
|
|||||||
srandom(time(NULL));
|
srandom(time(NULL));
|
||||||
|
|
||||||
perf_config__init();
|
perf_config__init();
|
||||||
perf_config(perf_default_config, NULL);
|
err = perf_config(perf_default_config, NULL);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
set_buildid_dir(NULL);
|
set_buildid_dir(NULL);
|
||||||
|
|
||||||
/* get debugfs/tracefs mount point from /proc/mounts */
|
/* get debugfs/tracefs mount point from /proc/mounts */
|
||||||
|
317
tools/perf/pmu-events/arch/x86/broadwellde/uncore-cache.json
Normal file
317
tools/perf/pmu-events/arch/x86/broadwellde/uncore-cache.json
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_C_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x34",
|
||||||
|
"EventName": "UNC_C_LLC_LOOKUP.ANY",
|
||||||
|
"Filter": "filter_state=0x1",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x11",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x37",
|
||||||
|
"EventName": "UNC_C_LLC_VICTIMS.M_STATE",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses - demand and prefetch data reads - excludes LLC prefetches. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.DATA_READ",
|
||||||
|
"Filter": "filter_opc=0x182",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses - Uncacheable reads (from cpu) . Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.UNCACHEABLE",
|
||||||
|
"Filter": "filter_opc=0x187",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "MMIO reads. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.MMIO_READ",
|
||||||
|
"Filter": "filter_opc=0x187,filter_nc=1",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "MMIO writes. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.MMIO_WRITE",
|
||||||
|
"Filter": "filter_opc=0x18f,filter_nc=1",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC prefetch misses for RFO. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.RFO_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x190",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC prefetch misses for code reads. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.CODE_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x191",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC prefetch misses for data reads. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.DATA_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x192",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses for PCIe read current. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_READ",
|
||||||
|
"Filter": "filter_opc=0x19e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "ItoM write misses (as part of fast string memcpy stores) + PCIe full line writes. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe write misses (full cache line). Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_NON_SNOOP_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8,filter_tid=0x3e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe writes (partial cache line). Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_NS_PARTIAL_WRITE",
|
||||||
|
"Filter": "filter_opc=0x180,filter_tid=0x3e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "L2 demand and L2 prefetch code references to LLC. Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.CODE_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x181",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Streaming stores (full cache line). Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.STREAMING_FULL",
|
||||||
|
"Filter": "filter_opc=0x18c",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Streaming stores (partial cache line). Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.STREAMING_PARTIAL",
|
||||||
|
"Filter": "filter_opc=0x18d",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe read current. Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_READ",
|
||||||
|
"Filter": "filter_opc=0x19e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe write references (full cache line). Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8,filter_tid=0x3e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Occupancy counter for LLC data reads (demand and L2 prefetch). Derived from unc_c_tor_occupancy.miss_opcode",
|
||||||
|
"EventCode": "0x36",
|
||||||
|
"EventName": "UNC_C_TOR_OCCUPANCY.LLC_DATA_READ",
|
||||||
|
"Filter": "filter_opc=0x182",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.READS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to local home agent. Derived from unc_h_requests.reads_local",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.READS_LOCAL",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to remote home agent. Derived from unc_h_requests.reads_remote",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.READS_REMOTE",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x2",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.WRITES",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0xC",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to local home agent. Derived from unc_h_requests.writes_local",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.WRITES_LOCAL",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to remote home agent. Derived from unc_h_requests.writes_remote",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.WRITES_REMOTE",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x8",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously). Derived from unc_h_snoop_resp.rspcnflct",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x40",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x20",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x2",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x8",
|
||||||
|
"Unit": "HA"
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,83 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_M_CAS_COUNT.RD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_M_CAS_COUNT.WR",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0xC",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Memory controller clock ticks. Derived from unc_m_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_M_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x85",
|
||||||
|
"EventName": "UNC_M_POWER_CHANNEL_PPD",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x86",
|
||||||
|
"EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x43",
|
||||||
|
"EventName": "UNC_M_POWER_SELF_REFRESH",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Pre-charges due to page misses. Derived from unc_m_pre_count.page_miss",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x2",
|
||||||
|
"EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Pre-charge for reads. Derived from unc_m_pre_count.rd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x2",
|
||||||
|
"EventName": "UNC_M_PRE_COUNT.RD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Pre-charge for writes. Derived from unc_m_pre_count.wr",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x2",
|
||||||
|
"EventName": "UNC_M_PRE_COUNT.WR",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x8",
|
||||||
|
"Unit": "iMC"
|
||||||
|
}
|
||||||
|
]
|
84
tools/perf/pmu-events/arch/x86/broadwellde/uncore-power.json
Normal file
84
tools/perf/pmu-events/arch/x86/broadwellde/uncore-power.json
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_P_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "C0 and C1. Derived from unc_p_power_state_occupancy.cores_c0",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
|
||||||
|
"Filter": "occ_sel=1",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "C3. Derived from unc_p_power_state_occupancy.cores_c3",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
|
||||||
|
"Filter": "occ_sel=2",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "C6 and C7. Derived from unc_p_power_state_occupancy.cores_c6",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
|
||||||
|
"Filter": "occ_sel=3",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "External Prochot. Derived from unc_p_prochot_external_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xA",
|
||||||
|
"EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Thermal Strongest Upper Limit Cycles. Derived from unc_p_freq_max_limit_thermal_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "OS Strongest Upper Limit Cycles. Derived from unc_p_freq_max_os_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x6",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Power Strongest Upper Limit Cycles. Derived from unc_p_freq_max_power_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x5",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x74",
|
||||||
|
"EventName": "UNC_P_FREQ_TRANS_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
}
|
||||||
|
]
|
317
tools/perf/pmu-events/arch/x86/broadwellx/uncore-cache.json
Normal file
317
tools/perf/pmu-events/arch/x86/broadwellx/uncore-cache.json
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_C_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x34",
|
||||||
|
"EventName": "UNC_C_LLC_LOOKUP.ANY",
|
||||||
|
"Filter": "filter_state=0x1",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x11",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x37",
|
||||||
|
"EventName": "UNC_C_LLC_VICTIMS.M_STATE",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses - demand and prefetch data reads - excludes LLC prefetches. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.DATA_READ",
|
||||||
|
"Filter": "filter_opc=0x182",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses - Uncacheable reads (from cpu) . Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.UNCACHEABLE",
|
||||||
|
"Filter": "filter_opc=0x187",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "MMIO reads. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.MMIO_READ",
|
||||||
|
"Filter": "filter_opc=0x187,filter_nc=1",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "MMIO writes. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.MMIO_WRITE",
|
||||||
|
"Filter": "filter_opc=0x18f,filter_nc=1",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC prefetch misses for RFO. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.RFO_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x190",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC prefetch misses for code reads. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.CODE_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x191",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC prefetch misses for data reads. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.DATA_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x192",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses for PCIe read current. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_READ",
|
||||||
|
"Filter": "filter_opc=0x19e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "ItoM write misses (as part of fast string memcpy stores) + PCIe full line writes. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe write misses (full cache line). Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_NON_SNOOP_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8,filter_tid=0x3e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe writes (partial cache line). Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_NS_PARTIAL_WRITE",
|
||||||
|
"Filter": "filter_opc=0x180,filter_tid=0x3e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "L2 demand and L2 prefetch code references to LLC. Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.CODE_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x181",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Streaming stores (full cache line). Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.STREAMING_FULL",
|
||||||
|
"Filter": "filter_opc=0x18c",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Streaming stores (partial cache line). Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.STREAMING_PARTIAL",
|
||||||
|
"Filter": "filter_opc=0x18d",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe read current. Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_READ",
|
||||||
|
"Filter": "filter_opc=0x19e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe write references (full cache line). Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8,filter_tid=0x3e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Occupancy counter for LLC data reads (demand and L2 prefetch). Derived from unc_c_tor_occupancy.miss_opcode",
|
||||||
|
"EventCode": "0x36",
|
||||||
|
"EventName": "UNC_C_TOR_OCCUPANCY.LLC_DATA_READ",
|
||||||
|
"Filter": "filter_opc=0x182",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.READS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to local home agent. Derived from unc_h_requests.reads_local",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.READS_LOCAL",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to remote home agent. Derived from unc_h_requests.reads_remote",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.READS_REMOTE",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x2",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.WRITES",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0xC",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to local home agent. Derived from unc_h_requests.writes_local",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.WRITES_LOCAL",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to remote home agent. Derived from unc_h_requests.writes_remote",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.WRITES_REMOTE",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x8",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously). Derived from unc_h_snoop_resp.rspcnflct",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x40",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x20",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x2",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x8",
|
||||||
|
"Unit": "HA"
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,28 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "QPI clock ticks. Derived from unc_q_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x14",
|
||||||
|
"EventName": "UNC_Q_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_Q_TxL_FLITS_G0.DATA",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "8Bytes",
|
||||||
|
"UMask": "0x2",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "8Bytes",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
}
|
||||||
|
]
|
83
tools/perf/pmu-events/arch/x86/broadwellx/uncore-memory.json
Normal file
83
tools/perf/pmu-events/arch/x86/broadwellx/uncore-memory.json
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_M_CAS_COUNT.RD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_M_CAS_COUNT.WR",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0xC",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Memory controller clock ticks. Derived from unc_m_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_M_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x85",
|
||||||
|
"EventName": "UNC_M_POWER_CHANNEL_PPD",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x86",
|
||||||
|
"EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x43",
|
||||||
|
"EventName": "UNC_M_POWER_SELF_REFRESH",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Pre-charges due to page misses. Derived from unc_m_pre_count.page_miss",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x2",
|
||||||
|
"EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Pre-charge for reads. Derived from unc_m_pre_count.rd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x2",
|
||||||
|
"EventName": "UNC_M_PRE_COUNT.RD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Pre-charge for writes. Derived from unc_m_pre_count.wr",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x2",
|
||||||
|
"EventName": "UNC_M_PRE_COUNT.WR",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x8",
|
||||||
|
"Unit": "iMC"
|
||||||
|
}
|
||||||
|
]
|
84
tools/perf/pmu-events/arch/x86/broadwellx/uncore-power.json
Normal file
84
tools/perf/pmu-events/arch/x86/broadwellx/uncore-power.json
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_P_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "C0 and C1. Derived from unc_p_power_state_occupancy.cores_c0",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
|
||||||
|
"Filter": "occ_sel=1",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "C3. Derived from unc_p_power_state_occupancy.cores_c3",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
|
||||||
|
"Filter": "occ_sel=2",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "C6 and C7. Derived from unc_p_power_state_occupancy.cores_c6",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
|
||||||
|
"Filter": "occ_sel=3",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "External Prochot. Derived from unc_p_prochot_external_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xA",
|
||||||
|
"EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Thermal Strongest Upper Limit Cycles. Derived from unc_p_freq_max_limit_thermal_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "OS Strongest Upper Limit Cycles. Derived from unc_p_freq_max_os_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x6",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Power Strongest Upper Limit Cycles. Derived from unc_p_freq_max_power_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x5",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x74",
|
||||||
|
"EventName": "UNC_P_FREQ_TRANS_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
}
|
||||||
|
]
|
317
tools/perf/pmu-events/arch/x86/haswellx/uncore-cache.json
Normal file
317
tools/perf/pmu-events/arch/x86/haswellx/uncore-cache.json
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_C_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x34",
|
||||||
|
"EventName": "UNC_C_LLC_LOOKUP.ANY",
|
||||||
|
"Filter": "filter_state=0x1",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x11",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x37",
|
||||||
|
"EventName": "UNC_C_LLC_VICTIMS.M_STATE",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses - demand and prefetch data reads - excludes LLC prefetches. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.DATA_READ",
|
||||||
|
"Filter": "filter_opc=0x182",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses - Uncacheable reads (from cpu) . Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.UNCACHEABLE",
|
||||||
|
"Filter": "filter_opc=0x187",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "MMIO reads. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.MMIO_READ",
|
||||||
|
"Filter": "filter_opc=0x187,filter_nc=1",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "MMIO writes. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.MMIO_WRITE",
|
||||||
|
"Filter": "filter_opc=0x18f,filter_nc=1",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC prefetch misses for RFO. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.RFO_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x190",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC prefetch misses for code reads. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.CODE_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x191",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC prefetch misses for data reads. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.DATA_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x192",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses for PCIe read current. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_READ",
|
||||||
|
"Filter": "filter_opc=0x19e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "ItoM write misses (as part of fast string memcpy stores) + PCIe full line writes. Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe write misses (full cache line). Derived from unc_c_tor_inserts.miss_opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_NON_SNOOP_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8,filter_tid=0x3e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe writes (partial cache line). Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_NS_PARTIAL_WRITE",
|
||||||
|
"Filter": "filter_opc=0x180,filter_tid=0x3e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "L2 demand and L2 prefetch code references to LLC. Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.CODE_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x181",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Streaming stores (full cache line). Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.STREAMING_FULL",
|
||||||
|
"Filter": "filter_opc=0x18c",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Streaming stores (partial cache line). Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.STREAMING_PARTIAL",
|
||||||
|
"Filter": "filter_opc=0x18d",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe read current. Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_READ",
|
||||||
|
"Filter": "filter_opc=0x19e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe write references (full cache line). Derived from unc_c_tor_inserts.opcode",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8,filter_tid=0x3e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Occupancy counter for LLC data reads (demand and L2 prefetch). Derived from unc_c_tor_occupancy.miss_opcode",
|
||||||
|
"EventCode": "0x36",
|
||||||
|
"EventName": "UNC_C_TOR_OCCUPANCY.LLC_DATA_READ",
|
||||||
|
"Filter": "filter_opc=0x182",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.READS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to local home agent. Derived from unc_h_requests.reads_local",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.READS_LOCAL",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to remote home agent. Derived from unc_h_requests.reads_remote",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.READS_REMOTE",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x2",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.WRITES",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0xC",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to local home agent. Derived from unc_h_requests.writes_local",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.WRITES_LOCAL",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to remote home agent. Derived from unc_h_requests.writes_remote",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.WRITES_REMOTE",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x8",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Conflict requests (requests for same address from multiple agents simultaneously). Derived from unc_h_snoop_resp.rspcnflct",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPCNFLCT",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x40",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x20",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x2",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x8",
|
||||||
|
"Unit": "HA"
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,28 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "QPI clock ticks. Derived from unc_q_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x14",
|
||||||
|
"EventName": "UNC_Q_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_Q_TxL_FLITS_G0.DATA",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "8Bytes",
|
||||||
|
"UMask": "0x2",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "8Bytes",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
}
|
||||||
|
]
|
83
tools/perf/pmu-events/arch/x86/haswellx/uncore-memory.json
Normal file
83
tools/perf/pmu-events/arch/x86/haswellx/uncore-memory.json
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_M_CAS_COUNT.RD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_M_CAS_COUNT.WR",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0xC",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Memory controller clock ticks. Derived from unc_m_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_M_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x85",
|
||||||
|
"EventName": "UNC_M_POWER_CHANNEL_PPD",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x86",
|
||||||
|
"EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x43",
|
||||||
|
"EventName": "UNC_M_POWER_SELF_REFRESH",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Pre-charges due to page misses. Derived from unc_m_pre_count.page_miss",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x2",
|
||||||
|
"EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Pre-charge for reads. Derived from unc_m_pre_count.rd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x2",
|
||||||
|
"EventName": "UNC_M_PRE_COUNT.RD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Pre-charge for writes. Derived from unc_m_pre_count.wr",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x2",
|
||||||
|
"EventName": "UNC_M_PRE_COUNT.WR",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x8",
|
||||||
|
"Unit": "iMC"
|
||||||
|
}
|
||||||
|
]
|
84
tools/perf/pmu-events/arch/x86/haswellx/uncore-power.json
Normal file
84
tools/perf/pmu-events/arch/x86/haswellx/uncore-power.json
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_P_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "C0 and C1. Derived from unc_p_power_state_occupancy.cores_c0",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
|
||||||
|
"Filter": "occ_sel=1",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "C3. Derived from unc_p_power_state_occupancy.cores_c3",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
|
||||||
|
"Filter": "occ_sel=2",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "C6 and C7. Derived from unc_p_power_state_occupancy.cores_c6",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
|
||||||
|
"Filter": "occ_sel=3",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "External Prochot. Derived from unc_p_prochot_external_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xA",
|
||||||
|
"EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Thermal Strongest Upper Limit Cycles. Derived from unc_p_freq_max_limit_thermal_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "OS Strongest Upper Limit Cycles. Derived from unc_p_freq_max_os_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x6",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Power Strongest Upper Limit Cycles. Derived from unc_p_freq_max_power_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x5",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x74",
|
||||||
|
"EventName": "UNC_P_FREQ_TRANS_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
}
|
||||||
|
]
|
322
tools/perf/pmu-events/arch/x86/ivytown/uncore-cache.json
Normal file
322
tools/perf/pmu-events/arch/x86/ivytown/uncore-cache.json
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_C_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x34",
|
||||||
|
"EventName": "UNC_C_LLC_LOOKUP.ANY",
|
||||||
|
"Filter": "filter_state=0x1",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x11",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x37",
|
||||||
|
"EventName": "UNC_C_LLC_VICTIMS.M_STATE",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses - demand and prefetch data reads - excludes LLC prefetches. Derived from unc_c_tor_inserts.miss_opcode.demand",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.DATA_READ",
|
||||||
|
"Filter": "filter_opc=0x182",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses - Uncacheable reads. Derived from unc_c_tor_inserts.miss_opcode.uncacheable",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.UNCACHEABLE",
|
||||||
|
"Filter": "filter_opc=0x187",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC prefetch misses for RFO. Derived from unc_c_tor_inserts.miss_opcode.rfo_prefetch",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.RFO_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x190",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC prefetch misses for code reads. Derived from unc_c_tor_inserts.miss_opcode.code",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.CODE_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x191",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC prefetch misses for data reads. Derived from unc_c_tor_inserts.miss_opcode.data_read",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.DATA_LLC_PREFETCH",
|
||||||
|
"Filter": "filter_opc=0x192",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe allocating writes that miss LLC - DDIO misses. Derived from unc_c_tor_inserts.miss_opcode.ddio_miss",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_WRITE",
|
||||||
|
"Filter": "filter_opc=0x19c",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses for PCIe read current. Derived from unc_c_tor_inserts.miss_opcode.pcie_read",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_READ",
|
||||||
|
"Filter": "filter_opc=0x19e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses for ItoM writes (as part of fast string memcpy stores). Derived from unc_c_tor_inserts.miss_opcode.itom_write",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.ITOM_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses for PCIe non-snoop reads. Derived from unc_c_tor_inserts.miss_opcode.pcie_read",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_NON_SNOOP_READ",
|
||||||
|
"Filter": "filter_opc=0x1e4",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses for PCIe non-snoop writes (full line). Derived from unc_c_tor_inserts.miss_opcode.pcie_write",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_NON_SNOOP_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1e6",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Streaming stores (full cache line). Derived from unc_c_tor_inserts.opcode.streaming_full",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.STREAMING_FULL",
|
||||||
|
"Filter": "filter_opc=0x18c",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Streaming stores (partial cache line). Derived from unc_c_tor_inserts.opcode.streaming_partial",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.STREAMING_PARTIAL",
|
||||||
|
"Filter": "filter_opc=0x18d",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Partial PCIe reads. Derived from unc_c_tor_inserts.opcode.pcie_partial",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_PARTIAL_READ",
|
||||||
|
"Filter": "filter_opc=0x195",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe allocating writes that hit in LLC (DDIO hits). Derived from unc_c_tor_inserts.opcode.ddio_hit",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_WRITE",
|
||||||
|
"Filter": "filter_opc=0x19c",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe read current. Derived from unc_c_tor_inserts.opcode.pcie_read_current",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_READ",
|
||||||
|
"Filter": "filter_opc=0x19e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "ItoM write hits (as part of fast string memcpy stores). Derived from unc_c_tor_inserts.opcode.itom_write_hit",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.ITOM_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe non-snoop reads. Derived from unc_c_tor_inserts.opcode.pcie_read",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_NS_READ",
|
||||||
|
"Filter": "filter_opc=0x1e4",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe non-snoop writes (partial). Derived from unc_c_tor_inserts.opcode.pcie_partial_write",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_NS_PARTIAL_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1e5",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe non-snoop writes (full line). Derived from unc_c_tor_inserts.opcode.pcie_full_write",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_NS_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1e6",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Occupancy for all LLC misses that are addressed to local memory. Derived from unc_c_tor_occupancy.miss_local",
|
||||||
|
"EventCode": "0x36",
|
||||||
|
"EventName": "UNC_C_TOR_OCCUPANCY.MISS_LOCAL",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x2A",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Occupancy counter for LLC data reads (demand and L2 prefetch). Derived from unc_c_tor_occupancy.miss_opcode.llc_data_read",
|
||||||
|
"EventCode": "0x36",
|
||||||
|
"EventName": "UNC_C_TOR_OCCUPANCY.LLC_DATA_READ",
|
||||||
|
"Filter": "filter_opc=0x182",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Occupancy for all LLC misses that are addressed to remote memory. Derived from unc_c_tor_occupancy.miss_remote",
|
||||||
|
"EventCode": "0x36",
|
||||||
|
"EventName": "UNC_C_TOR_OCCUPANCY.MISS_REMOTE",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x8A",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Read requests to home agent. Derived from unc_h_requests.reads",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.READS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Write requests to home agent. Derived from unc_h_requests.writes",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.WRITES",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0xC",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line forwarded from remote cache along with writeback to memory. Derived from unc_h_snoop_resp.rsp_fwd_wb",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSP_FWD_WB",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x20",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line forwarded from remote cache with no writeback to memory. Derived from unc_h_snoop_resp.rspifwd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPIFWD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Shared line response from remote cache. Derived from unc_h_snoop_resp.rsps",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x2",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Shared line forwarded from remote cache. Derived from unc_h_snoop_resp.rspsfwd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x21",
|
||||||
|
"EventName": "UNC_H_SNOOP_RESP.RSPSFWD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x8",
|
||||||
|
"Unit": "HA"
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,46 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "QPI clock ticks. Use to get percentages for QPI cycles events. Derived from unc_q_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x14",
|
||||||
|
"EventName": "UNC_Q_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles where receiving QPI link is in half-width mode. Derived from unc_q_rxl0p_power_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x10",
|
||||||
|
"EventName": "UNC_Q_RxL0P_POWER_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_Q_RxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles where transmitting QPI link is in half-width mode. Derived from unc_q_txl0p_power_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xd",
|
||||||
|
"EventName": "UNC_Q_TxL0P_POWER_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_Q_TxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_Q_TxL_FLITS_G0.DATA",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "8Bytes",
|
||||||
|
"UMask": "0x2",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "8Bytes",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
}
|
||||||
|
]
|
75
tools/perf/pmu-events/arch/x86/ivytown/uncore-memory.json
Normal file
75
tools/perf/pmu-events/arch/x86/ivytown/uncore-memory.json
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "Memory page activates for reads and writes. Derived from unc_m_act_count.rd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_M_ACT_COUNT.RD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Umask": "0x3",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Read requests to memory controller. Derived from unc_m_cas_count.rd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_M_CAS_COUNT.RD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Write requests to memory controller. Derived from unc_m_cas_count.wr",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_M_CAS_COUNT.WR",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0xC",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Memory controller clock ticks. Use to generate percentages for memory controller CYCLES events. Derived from unc_m_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_M_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x85",
|
||||||
|
"EventName": "UNC_M_POWER_CHANNEL_PPD",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x86",
|
||||||
|
"EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x43",
|
||||||
|
"EventName": "UNC_M_POWER_SELF_REFRESH",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Memory page conflicts. Derived from unc_m_pre_count.page_miss",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x2",
|
||||||
|
"EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
}
|
||||||
|
]
|
249
tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
Normal file
249
tools/perf/pmu-events/arch/x86/ivytown/uncore-power.json
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_P_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band0=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band0_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xb",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND0_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band1=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band1_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xc",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND1_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band2=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band2_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xd",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND2_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band3_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xe",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND3_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of times that the uncore transitioned a frequency greater than or equal to the frequency that is configured in the filter. (filter_band0=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band0_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xb",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND0_TRANSITIONS",
|
||||||
|
"Filter": "edge=1",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of times that the uncore transitioned to a frequency greater than or equal to the frequency that is configured in the filter. (filter_band1=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band1_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xc",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND1_TRANSITIONS",
|
||||||
|
"Filter": "edge=1",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to the frequency that is configured in the filter. (filter_band2=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band2_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xd",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND2_TRANSITIONS",
|
||||||
|
"Filter": "edge=1",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to the frequency that is configured in the filter. (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band3_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xe",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND3_TRANSITIONS",
|
||||||
|
"Filter": "edge=1",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c0",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
|
||||||
|
"Filter": "occ_sel=1",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c3",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
|
||||||
|
"Filter": "occ_sel=2",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "This is an occupancy event that tracks the number of cores that are in the chosen C-State. It can be used by itself to get the average number of cores in that C-state with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c6",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
|
||||||
|
"Filter": "occ_sel=3",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip. Derived from unc_p_prochot_external_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xa",
|
||||||
|
"EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles when thermal conditions are the upper limit on frequency. This is related to the THERMAL_THROTTLE CYCLES_ABOVE_TEMP event, which always counts cycles when we are above the thermal temperature. This event (STRONGEST_UPPER_LIMIT) is sampled at the output of the algorithm that determines the actual frequency, while THERMAL_THROTTLE looks at the input. Derived from unc_p_freq_max_limit_thermal_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency. Derived from unc_p_freq_max_os_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x6",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles when power is the upper limit on frequency. Derived from unc_p_freq_max_power_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x5",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles when current is the upper limit on frequency. Derived from unc_p_freq_max_current_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x7",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_CURRENT_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_CURRENT_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles when the system is changing frequency. This can not be filtered by thread ID. One can also use it with the occupancy counter that monitors number of threads in C0 to estimate the performance impact that frequency transitions had on the system. Derived from unc_p_freq_trans_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x60",
|
||||||
|
"EventName": "UNC_P_FREQ_TRANS_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 1.2Ghz. Derived from unc_p_freq_band0_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xb",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES",
|
||||||
|
"Filter": "filter_band0=1200",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 2Ghz. Derived from unc_p_freq_band1_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xc",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES",
|
||||||
|
"Filter": "filter_band1=2000",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 3Ghz. Derived from unc_p_freq_band2_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xd",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES",
|
||||||
|
"Filter": "filter_band2=3000",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 4Ghz. Derived from unc_p_freq_band3_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xe",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES",
|
||||||
|
"Filter": "filter_band3=4000",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of times that the uncore transitioned to a frequency greater than or equal to 1.2Ghz. Derived from unc_p_freq_band0_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xb",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS",
|
||||||
|
"Filter": "edge=1,filter_band0=1200",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of times that the uncore transitioned to a frequency greater than or equal to 2Ghz. Derived from unc_p_freq_band1_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xc",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS",
|
||||||
|
"Filter": "edge=1,filter_band1=2000",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to 3Ghz. Derived from unc_p_freq_band2_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xd",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS",
|
||||||
|
"Filter": "edge=1,filter_band2=4000",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to 4Ghz. Derived from unc_p_freq_band3_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xe",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS",
|
||||||
|
"Filter": "edge=1,filter_band3=4000",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
}
|
||||||
|
]
|
209
tools/perf/pmu-events/arch/x86/jaketown/uncore-cache.json
Normal file
209
tools/perf/pmu-events/arch/x86/jaketown/uncore-cache.json
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "Uncore cache clock ticks. Derived from unc_c_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_C_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "All LLC Misses (code+ data rd + data wr - including demand and prefetch). Derived from unc_c_llc_lookup.any",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x34",
|
||||||
|
"EventName": "UNC_C_LLC_LOOKUP.ANY",
|
||||||
|
"Filter": "filter_state=0x1",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x11",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "M line evictions from LLC (writebacks to memory). Derived from unc_c_llc_victims.m_state",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x37",
|
||||||
|
"EventName": "UNC_C_LLC_VICTIMS.M_STATE",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses - demand and prefetch data reads - excludes LLC prefetches. Derived from unc_c_tor_inserts.miss_opcode.demand",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.DATA_READ",
|
||||||
|
"Filter": "filter_opc=0x182",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses - Uncacheable reads. Derived from unc_c_tor_inserts.miss_opcode.uncacheable",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.UNCACHEABLE",
|
||||||
|
"Filter": "filter_opc=0x187",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe allocating writes that miss LLC - DDIO misses. Derived from unc_c_tor_inserts.miss_opcode.ddio_miss",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.PCIE_WRITE",
|
||||||
|
"Filter": "filter_opc=0x19c",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "LLC misses for ItoM writes (as part of fast string memcpy stores). Derived from unc_c_tor_inserts.miss_opcode.itom_write",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_MISSES.ITOM_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Streaming stores (full cache line). Derived from unc_c_tor_inserts.opcode.streaming_full",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.STREAMING_FULL",
|
||||||
|
"Filter": "filter_opc=0x18c",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Streaming stores (partial cache line). Derived from unc_c_tor_inserts.opcode.streaming_partial",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.STREAMING_PARTIAL",
|
||||||
|
"Filter": "filter_opc=0x18d",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Partial PCIe reads. Derived from unc_c_tor_inserts.opcode.pcie_partial",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_PARTIAL_READ",
|
||||||
|
"Filter": "filter_opc=0x195",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe allocating writes that hit in LLC (DDIO hits). Derived from unc_c_tor_inserts.opcode.ddio_hit",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_WRITE",
|
||||||
|
"Filter": "filter_opc=0x19c",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe read current. Derived from unc_c_tor_inserts.opcode.pcie_read_current",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_READ",
|
||||||
|
"Filter": "filter_opc=0x19e",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "ItoM write hits (as part of fast string memcpy stores). Derived from unc_c_tor_inserts.opcode.itom_write_hit",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.ITOM_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1c8",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe non-snoop reads. Derived from unc_c_tor_inserts.opcode.pcie_read",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_NS_READ",
|
||||||
|
"Filter": "filter_opc=0x1e4",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe non-snoop writes (partial). Derived from unc_c_tor_inserts.opcode.pcie_partial_write",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_NS_PARTIAL_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1e5",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCIe non-snoop writes (full line). Derived from unc_c_tor_inserts.opcode.pcie_full_write",
|
||||||
|
"Counter": "0,1",
|
||||||
|
"EventCode": "0x35",
|
||||||
|
"EventName": "LLC_REFERENCES.PCIE_NS_WRITE",
|
||||||
|
"Filter": "filter_opc=0x1e6",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "64Bytes",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Occupancy counter for all LLC misses; we divide this by UNC_C_CLOCKTICKS to get average Q depth. Derived from unc_c_tor_occupancy.miss_all",
|
||||||
|
"EventCode": "0x36",
|
||||||
|
"EventName": "UNC_C_TOR_OCCUPANCY.MISS_ALL",
|
||||||
|
"Filter": "filter_opc=0x182",
|
||||||
|
"MetricExpr": "(UNC_C_TOR_OCCUPANCY.MISS_ALL / UNC_C_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0xa",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Occupancy counter for LLC data reads (demand and L2 prefetch). Derived from unc_c_tor_occupancy.miss_opcode.llc_data_read",
|
||||||
|
"EventCode": "0x36",
|
||||||
|
"EventName": "UNC_C_TOR_OCCUPANCY.LLC_DATA_READ",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "CBO"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to home agent. Derived from unc_h_requests.reads",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.READS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "HA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to home agent. Derived from unc_h_requests.writes",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_H_REQUESTS.WRITES",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0xc",
|
||||||
|
"Unit": "HA"
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,46 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "QPI clock ticks. Used to get percentages of QPI cycles events. Derived from unc_q_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x14",
|
||||||
|
"EventName": "UNC_Q_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles where receiving QPI link is in half-width mode. Derived from unc_q_rxl0p_power_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x10",
|
||||||
|
"EventName": "UNC_Q_RxL0P_POWER_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_Q_RxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles where transmitting QPI link is in half-width mode. Derived from unc_q_txl0p_power_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xd",
|
||||||
|
"EventName": "UNC_Q_TxL0P_POWER_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_Q_TxL0P_POWER_CYCLES / UNC_Q_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Number of data flits transmitted . Derived from unc_q_txl_flits_g0.data",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_Q_TxL_FLITS_G0.DATA",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "8Bytes",
|
||||||
|
"UMask": "0x2",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Number of non data (control) flits transmitted . Derived from unc_q_txl_flits_g0.non_data",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_Q_TxL_FLITS_G0.NON_DATA",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "8Bytes",
|
||||||
|
"UMask": "0x4",
|
||||||
|
"Unit": "QPI LL"
|
||||||
|
}
|
||||||
|
]
|
79
tools/perf/pmu-events/arch/x86/jaketown/uncore-memory.json
Normal file
79
tools/perf/pmu-events/arch/x86/jaketown/uncore-memory.json
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "Memory page activates. Derived from unc_m_act_count",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x1",
|
||||||
|
"EventName": "UNC_M_ACT_COUNT",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "read requests to memory controller. Derived from unc_m_cas_count.rd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_M_CAS_COUNT.RD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x3",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "write requests to memory controller. Derived from unc_m_cas_count.wr",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_M_CAS_COUNT.WR",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0xc",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Memory controller clock ticks. Used to get percentages of memory controller cycles events. Derived from unc_m_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_M_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles where DRAM ranks are in power down (CKE) mode. Derived from unc_m_power_channel_ppd",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x85",
|
||||||
|
"EventName": "UNC_M_POWER_CHANNEL_PPD",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_CHANNEL_PPD / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles all ranks are in critical thermal throttle. Derived from unc_m_power_critical_throttle_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x86",
|
||||||
|
"EventName": "UNC_M_POWER_CRITICAL_THROTTLE_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_CRITICAL_THROTTLE_CYCLES / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles Memory is in self refresh power mode. Derived from unc_m_power_self_refresh",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x43",
|
||||||
|
"EventName": "UNC_M_POWER_SELF_REFRESH",
|
||||||
|
"MetricExpr": "(UNC_M_POWER_SELF_REFRESH / UNC_M_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Memory page conflicts. Derived from unc_m_pre_count.page_miss",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x2",
|
||||||
|
"EventName": "UNC_M_PRE_COUNT.PAGE_MISS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"UMask": "0x1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Occupancy counter for memory read queue. Derived from unc_m_rpq_occupancy",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_M_RPQ_OCCUPANCY",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "iMC"
|
||||||
|
}
|
||||||
|
]
|
248
tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
Normal file
248
tools/perf/pmu-events/arch/x86/jaketown/uncore-power.json
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "PCU clock ticks. Use to get percentages of PCU cycles events. Derived from unc_p_clockticks",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_P_CLOCKTICKS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band0=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band0_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xb",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND0_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band1=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band1_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xc",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND1_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band2=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band2_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xd",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND2_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to the frequency that is configured in the filter. (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band3_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xe",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND3_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of times that the uncore transitioned a frequency greater than or equal to the frequency that is configured in the filter. (filter_band0=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band0_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xb",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND0_TRANSITIONS",
|
||||||
|
"Filter": "edge=1",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND0_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of times that the uncore transistioned to a frequency greater than or equal to the frequency that is configured in the filter. (filter_band1=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band1_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xc",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND1_TRANSITIONS",
|
||||||
|
"Filter": "edge=1",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND1_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to the frequency that is configured in the filter. (filter_band2=XXX with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band2_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xd",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND2_TRANSITIONS",
|
||||||
|
"Filter": "edge=1",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND2_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to the frequency that is configured in the filter. (filter_band3=XXX, with XXX in 100Mhz units). One can also use inversion (filter_inv=1) to track cycles when we were less than the configured frequency. Derived from unc_p_freq_band3_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xe",
|
||||||
|
"EventName": "UNC_P_FREQ_BAND3_TRANSITIONS",
|
||||||
|
"Filter": "edge=1",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_BAND3_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "This is an occupancy event that tracks the number of cores that are in C0. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c0",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C0",
|
||||||
|
"Filter": "occ_sel=1",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C0 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "This is an occupancy event that tracks the number of cores that are in C3. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events and occupancy triggering to capture other details. Derived from unc_p_power_state_occupancy.cores_c3",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C3",
|
||||||
|
"Filter": "occ_sel=2",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C3 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "This is an occupancy event that tracks the number of cores that are in C6. It can be used by itself to get the average number of cores in C0, with threshholding to generate histograms, or with other PCU events . Derived from unc_p_power_state_occupancy.cores_c6",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x80",
|
||||||
|
"EventName": "UNC_P_POWER_STATE_OCCUPANCY.CORES_C6",
|
||||||
|
"Filter": "occ_sel=3",
|
||||||
|
"MetricExpr": "(UNC_P_POWER_STATE_OCCUPANCY.CORES_C6 / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that we are in external PROCHOT mode. This mode is triggered when a sensor off the die determines that something off-die (like DRAM) is too hot and must throttle to avoid damaging the chip. Derived from unc_p_prochot_external_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xa",
|
||||||
|
"EventName": "UNC_P_PROCHOT_EXTERNAL_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_PROCHOT_EXTERNAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles when temperature is the upper limit on frequency. Derived from unc_p_freq_max_limit_thermal_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x4",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_LIMIT_THERMAL_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles when the OS is the upper limit on frequency. Derived from unc_p_freq_max_os_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x6",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_OS_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_OS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles when power is the upper limit on frequency. Derived from unc_p_freq_max_power_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x5",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_POWER_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_POWER_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles when current is the upper limit on frequency. Derived from unc_p_freq_max_current_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x7",
|
||||||
|
"EventName": "UNC_P_FREQ_MAX_CURRENT_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_MAX_CURRENT_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Cycles spent changing Frequency. Derived from unc_p_freq_trans_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventName": "UNC_P_FREQ_TRANS_CYCLES",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_TRANS_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 1.2Ghz. Derived from unc_p_freq_band0_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xb",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_1200MHZ_CYCLES",
|
||||||
|
"Filter": "filter_band0=1200",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 2Ghz. Derived from unc_p_freq_band1_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xc",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_2000MHZ_CYCLES",
|
||||||
|
"Filter": "filter_band1=2000",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 3Ghz. Derived from unc_p_freq_band2_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xd",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_3000MHZ_CYCLES",
|
||||||
|
"Filter": "filter_band2=3000",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore was running at a frequency greater than or equal to 4Ghz. Derived from unc_p_freq_band3_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xe",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_4000MHZ_CYCLES",
|
||||||
|
"Filter": "filter_band3=4000",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of times that the uncore transitioned to a frequency greater than or equal to 1.2Ghz. Derived from unc_p_freq_band0_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xb",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_1200MHZ_TRANSITIONS",
|
||||||
|
"Filter": "edge=1,filter_band0=1200",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_1200MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of times that the uncore transitioned to a frequency greater than or equal to 2Ghz. Derived from unc_p_freq_band1_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xc",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_2000MHZ_TRANSITIONS",
|
||||||
|
"Filter": "edge=1,filter_band1=2000",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_2000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to 3Ghz. Derived from unc_p_freq_band2_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xd",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_3000MHZ_TRANSITIONS",
|
||||||
|
"Filter": "edge=1,filter_band2=4000",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_3000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "Counts the number of cycles that the uncore transitioned to a frequency greater than or equal to 4Ghz. Derived from unc_p_freq_band3_cycles",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0xe",
|
||||||
|
"EventName": "UNC_P_FREQ_GE_4000MHZ_TRANSITIONS",
|
||||||
|
"Filter": "edge=1,filter_band3=4000",
|
||||||
|
"MetricExpr": "(UNC_P_FREQ_GE_4000MHZ_CYCLES / UNC_P_CLOCKTICKS) * 100.",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"Unit": "PCU"
|
||||||
|
}
|
||||||
|
]
|
@ -0,0 +1,42 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"BriefDescription": "ddr bandwidth read (CPU traffic only) (MB/sec). ",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x03",
|
||||||
|
"EventName": "UNC_M_CAS_COUNT.RD",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "6.4e-05MiB",
|
||||||
|
"UMask": "0x01",
|
||||||
|
"Unit": "imc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "ddr bandwidth write (CPU traffic only) (MB/sec). ",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x03",
|
||||||
|
"EventName": "UNC_M_CAS_COUNT.WR",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "6.4e-05MiB",
|
||||||
|
"UMask": "0x02",
|
||||||
|
"Unit": "imc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "mcdram bandwidth read (CPU traffic only) (MB/sec). ",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x01",
|
||||||
|
"EventName": "UNC_E_RPQ_INSERTS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "6.4e-05MiB",
|
||||||
|
"UMask": "0x01",
|
||||||
|
"Unit": "edc_eclk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"BriefDescription": "mcdram bandwidth write (CPU traffic only) (MB/sec). ",
|
||||||
|
"Counter": "0,1,2,3",
|
||||||
|
"EventCode": "0x02",
|
||||||
|
"EventName": "UNC_E_WPQ_INSERTS",
|
||||||
|
"PerPkg": "1",
|
||||||
|
"ScaleUnit": "6.4e-05MiB",
|
||||||
|
"UMask": "0x01",
|
||||||
|
"Unit": "edc_eclk"
|
||||||
|
}
|
||||||
|
]
|
@ -135,7 +135,6 @@ static struct field {
|
|||||||
const char *field;
|
const char *field;
|
||||||
const char *kernel;
|
const char *kernel;
|
||||||
} fields[] = {
|
} fields[] = {
|
||||||
{ "EventCode", "event=" },
|
|
||||||
{ "UMask", "umask=" },
|
{ "UMask", "umask=" },
|
||||||
{ "CounterMask", "cmask=" },
|
{ "CounterMask", "cmask=" },
|
||||||
{ "Invert", "inv=" },
|
{ "Invert", "inv=" },
|
||||||
@ -189,6 +188,27 @@ static struct msrmap *lookup_msr(char *map, jsmntok_t *val)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct map {
|
||||||
|
const char *json;
|
||||||
|
const char *perf;
|
||||||
|
} unit_to_pmu[] = {
|
||||||
|
{ "CBO", "uncore_cbox" },
|
||||||
|
{ "QPI LL", "uncore_qpi" },
|
||||||
|
{ "SBO", "uncore_sbox" },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *field_to_perf(struct map *table, char *map, jsmntok_t *val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; table[i].json; i++) {
|
||||||
|
if (json_streq(map, val, table[i].json))
|
||||||
|
return table[i].perf;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#define EXPECT(e, t, m) do { if (!(e)) { \
|
#define EXPECT(e, t, m) do { if (!(e)) { \
|
||||||
jsmntok_t *loc = (t); \
|
jsmntok_t *loc = (t); \
|
||||||
if (!(t)->start && (t) > tokens) \
|
if (!(t)->start && (t) > tokens) \
|
||||||
@ -270,7 +290,8 @@ static void print_events_table_prefix(FILE *fp, const char *tblname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int print_events_table_entry(void *data, char *name, char *event,
|
static int print_events_table_entry(void *data, char *name, char *event,
|
||||||
char *desc, char *long_desc)
|
char *desc, char *long_desc,
|
||||||
|
char *pmu, char *unit, char *perpkg)
|
||||||
{
|
{
|
||||||
struct perf_entry_data *pd = data;
|
struct perf_entry_data *pd = data;
|
||||||
FILE *outfp = pd->outfp;
|
FILE *outfp = pd->outfp;
|
||||||
@ -288,7 +309,12 @@ static int print_events_table_entry(void *data, char *name, char *event,
|
|||||||
fprintf(outfp, "\t.topic = \"%s\",\n", topic);
|
fprintf(outfp, "\t.topic = \"%s\",\n", topic);
|
||||||
if (long_desc && long_desc[0])
|
if (long_desc && long_desc[0])
|
||||||
fprintf(outfp, "\t.long_desc = \"%s\",\n", long_desc);
|
fprintf(outfp, "\t.long_desc = \"%s\",\n", long_desc);
|
||||||
|
if (pmu)
|
||||||
|
fprintf(outfp, "\t.pmu = \"%s\",\n", pmu);
|
||||||
|
if (unit)
|
||||||
|
fprintf(outfp, "\t.unit = \"%s\",\n", unit);
|
||||||
|
if (perpkg)
|
||||||
|
fprintf(outfp, "\t.perpkg = \"%s\",\n", perpkg);
|
||||||
fprintf(outfp, "},\n");
|
fprintf(outfp, "},\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -335,7 +361,8 @@ static char *real_event(const char *name, char *event)
|
|||||||
/* Call func with each event in the json file */
|
/* Call func with each event in the json file */
|
||||||
int json_events(const char *fn,
|
int json_events(const char *fn,
|
||||||
int (*func)(void *data, char *name, char *event, char *desc,
|
int (*func)(void *data, char *name, char *event, char *desc,
|
||||||
char *long_desc),
|
char *long_desc,
|
||||||
|
char *pmu, char *unit, char *perpkg),
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
int err = -EIO;
|
int err = -EIO;
|
||||||
@ -343,6 +370,7 @@ int json_events(const char *fn,
|
|||||||
jsmntok_t *tokens, *tok;
|
jsmntok_t *tokens, *tok;
|
||||||
int i, j, len;
|
int i, j, len;
|
||||||
char *map;
|
char *map;
|
||||||
|
char buf[128];
|
||||||
|
|
||||||
if (!fn)
|
if (!fn)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
@ -356,6 +384,11 @@ int json_events(const char *fn,
|
|||||||
char *event = NULL, *desc = NULL, *name = NULL;
|
char *event = NULL, *desc = NULL, *name = NULL;
|
||||||
char *long_desc = NULL;
|
char *long_desc = NULL;
|
||||||
char *extra_desc = NULL;
|
char *extra_desc = NULL;
|
||||||
|
char *pmu = NULL;
|
||||||
|
char *filter = NULL;
|
||||||
|
char *perpkg = NULL;
|
||||||
|
char *unit = NULL;
|
||||||
|
unsigned long long eventcode = 0;
|
||||||
struct msrmap *msr = NULL;
|
struct msrmap *msr = NULL;
|
||||||
jsmntok_t *msrval = NULL;
|
jsmntok_t *msrval = NULL;
|
||||||
jsmntok_t *precise = NULL;
|
jsmntok_t *precise = NULL;
|
||||||
@ -376,6 +409,16 @@ int json_events(const char *fn,
|
|||||||
nz = !json_streq(map, val, "0");
|
nz = !json_streq(map, val, "0");
|
||||||
if (match_field(map, field, nz, &event, val)) {
|
if (match_field(map, field, nz, &event, val)) {
|
||||||
/* ok */
|
/* ok */
|
||||||
|
} else if (json_streq(map, field, "EventCode")) {
|
||||||
|
char *code = NULL;
|
||||||
|
addfield(map, &code, "", "", val);
|
||||||
|
eventcode |= strtoul(code, NULL, 0);
|
||||||
|
free(code);
|
||||||
|
} else if (json_streq(map, field, "ExtSel")) {
|
||||||
|
char *code = NULL;
|
||||||
|
addfield(map, &code, "", "", val);
|
||||||
|
eventcode |= strtoul(code, NULL, 0) << 21;
|
||||||
|
free(code);
|
||||||
} else if (json_streq(map, field, "EventName")) {
|
} else if (json_streq(map, field, "EventName")) {
|
||||||
addfield(map, &name, "", "", val);
|
addfield(map, &name, "", "", val);
|
||||||
} else if (json_streq(map, field, "BriefDescription")) {
|
} else if (json_streq(map, field, "BriefDescription")) {
|
||||||
@ -399,6 +442,28 @@ int json_events(const char *fn,
|
|||||||
addfield(map, &extra_desc, ". ",
|
addfield(map, &extra_desc, ". ",
|
||||||
" Supports address when precise",
|
" Supports address when precise",
|
||||||
NULL);
|
NULL);
|
||||||
|
} else if (json_streq(map, field, "Unit")) {
|
||||||
|
const char *ppmu;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
ppmu = field_to_perf(unit_to_pmu, map, val);
|
||||||
|
if (ppmu) {
|
||||||
|
pmu = strdup(ppmu);
|
||||||
|
} else {
|
||||||
|
if (!pmu)
|
||||||
|
pmu = strdup("uncore_");
|
||||||
|
addfield(map, &pmu, "", "", val);
|
||||||
|
for (s = pmu; *s; s++)
|
||||||
|
*s = tolower(*s);
|
||||||
|
}
|
||||||
|
addfield(map, &desc, ". ", "Unit: ", NULL);
|
||||||
|
addfield(map, &desc, "", pmu, NULL);
|
||||||
|
} else if (json_streq(map, field, "Filter")) {
|
||||||
|
addfield(map, &filter, "", "", val);
|
||||||
|
} else if (json_streq(map, field, "ScaleUnit")) {
|
||||||
|
addfield(map, &unit, "", "", val);
|
||||||
|
} else if (json_streq(map, field, "PerPkg")) {
|
||||||
|
addfield(map, &perpkg, "", "", val);
|
||||||
}
|
}
|
||||||
/* ignore unknown fields */
|
/* ignore unknown fields */
|
||||||
}
|
}
|
||||||
@ -410,20 +475,29 @@ int json_events(const char *fn,
|
|||||||
addfield(map, &extra_desc, " ",
|
addfield(map, &extra_desc, " ",
|
||||||
"(Precise event)", NULL);
|
"(Precise event)", NULL);
|
||||||
}
|
}
|
||||||
|
snprintf(buf, sizeof buf, "event=%#llx", eventcode);
|
||||||
|
addfield(map, &event, ",", buf, NULL);
|
||||||
if (desc && extra_desc)
|
if (desc && extra_desc)
|
||||||
addfield(map, &desc, " ", extra_desc, NULL);
|
addfield(map, &desc, " ", extra_desc, NULL);
|
||||||
if (long_desc && extra_desc)
|
if (long_desc && extra_desc)
|
||||||
addfield(map, &long_desc, " ", extra_desc, NULL);
|
addfield(map, &long_desc, " ", extra_desc, NULL);
|
||||||
|
if (filter)
|
||||||
|
addfield(map, &event, ",", filter, NULL);
|
||||||
if (msr != NULL)
|
if (msr != NULL)
|
||||||
addfield(map, &event, ",", msr->pname, msrval);
|
addfield(map, &event, ",", msr->pname, msrval);
|
||||||
fixname(name);
|
fixname(name);
|
||||||
|
|
||||||
err = func(data, name, real_event(name, event), desc, long_desc);
|
err = func(data, name, real_event(name, event), desc, long_desc,
|
||||||
|
pmu, unit, perpkg);
|
||||||
free(event);
|
free(event);
|
||||||
free(desc);
|
free(desc);
|
||||||
free(name);
|
free(name);
|
||||||
free(long_desc);
|
free(long_desc);
|
||||||
free(extra_desc);
|
free(extra_desc);
|
||||||
|
free(pmu);
|
||||||
|
free(filter);
|
||||||
|
free(perpkg);
|
||||||
|
free(unit);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
tok += j;
|
tok += j;
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
int json_events(const char *fn,
|
int json_events(const char *fn,
|
||||||
int (*func)(void *data, char *name, char *event, char *desc,
|
int (*func)(void *data, char *name, char *event, char *desc,
|
||||||
char *long_desc),
|
char *long_desc,
|
||||||
|
char *pmu,
|
||||||
|
char *unit, char *perpkg),
|
||||||
void *data);
|
void *data);
|
||||||
char *get_cpu_str(void);
|
char *get_cpu_str(void);
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user