Commit 21ee2fcb authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo-4.11-20170209' of...

Merge tag 'perf-core-for-mingo-4.11-20170209' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

User visible changes:

 - 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)

 - Support --symfs in 'perf probe' (Uwe Kleine-König)

 - Add support for generating bpf prologue on the aarch64 architecture (He Kuang)

 - Show proper hint when SDT event not yet in place via 'perf probe' (Ravi Bangoria)

 - Take into account symfs setting when reading file build ID (Victor Kamensky)

Infrastructure changes:

 - Map gcc7's '__attribute__ ((fallthrough))', that warns when code
   associated to case blocks in switches continue into the next case entry,
   to '__falltrough' and use it where warned by gcc, tested on Fedora Rawhide
   (Arnaldo Carvalho de Melo)

 - Fix buffer sizes used with snprintf that could lead to truncation,
   another warning introduced in gcc7 (Arnaldo Carvalho de Melo)

 - Robustify do_generate_dynamic_list_file in libtraceevent (David Carrillo-Cisneros)

 - Use zfree() in more places (Taeung Song)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents b6263178 7ea6856d
......@@ -126,4 +126,13 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
#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; })
#ifndef __fallthrough
# if defined(__GNUC__) && __GNUC__ >= 7
# define __fallthrough __attribute__ ((fallthrough))
# else
# define __fallthrough
# endif
#endif
#endif /* _TOOLS_LINUX_COMPILER_H */
......@@ -86,9 +86,13 @@ void put_tracing_file(char *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 filename[PATH_MAX];
snprintf(filename, PATH_MAX, "%s/%s", sys, name ?: "*");
switch (err) {
case ENOENT:
......@@ -99,10 +103,19 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
* - jirka
*/
if (debugfs__configured() || tracefs__configured()) {
/* sdt markers */
if (!strncmp(filename, "sdt_", 4)) {
snprintf(buf, size,
"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;
}
snprintf(buf, size, "%s",
......@@ -125,12 +138,3 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
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
#include <linux/bpf.h>
#include <stddef.h>
int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
int max_entries, __u32 map_flags);
......
......@@ -257,10 +257,16 @@ define do_install_plugins
endef
define do_generate_dynamic_list_file
symbol_type=`$(NM) -u -D $1 | awk 'NF>1 {print $$1}' | \
xargs echo "U W w" | tr ' ' '\n' | sort -u | xargs echo`;\
if [ "$$symbol_type" = "U W w" ];then \
(echo '{'; \
$(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u; \
$(NM) -u -D $1 | awk 'NF>1 {print "\t"$$2";"}' | sort -u;\
echo '};'; \
) > $2
) > $2; \
else \
(echo Either missing one of [$1] or bad version of $(NM)) 1>&2;\
fi
endef
install_lib: all_cmd install_plugins
......
......@@ -2,3 +2,4 @@ ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1
endif
PERF_HAVE_JITDUMP := 1
PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
......@@ -10,17 +10,20 @@
#include <stddef.h>
#include <dwarf-regs.h>
#include <linux/ptrace.h> /* for struct user_pt_regs */
#include "util.h"
struct pt_regs_dwarfnum {
const char *name;
unsigned int dwarfnum;
};
#define STR(s) #s
#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
#define GPR_DWARFNUM_NAME(num) \
{.name = STR(%x##num), .dwarfnum = num}
#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
#define DWARFNUM2OFFSET(index) \
(index * sizeof((struct user_pt_regs *)0)->regs[0])
/*
* Reference:
......@@ -78,3 +81,13 @@ const char *get_arch_regstr(unsigned int n)
return roff->name;
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;
}
......@@ -1573,13 +1573,13 @@ static int __bench_numa(const char *name)
"GB/sec,", "total-speed", "GB/sec total speed");
if (g->p.show_details >= 2) {
char tname[32];
char tname[14 + 2 * 10 + 1];
struct thread_data *td;
for (p = 0; p < g->p.nr_proc; p++) {
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;
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,
"GB/sec", "thread-speed", "GB/sec/thread speed");
print_res(tname, td->system_time_ns / NSEC_PER_SEC,
......
......@@ -14,6 +14,7 @@
#include "util/parse-events.h"
#include "util/cache.h"
#include "util/pmu.h"
#include "util/debug.h"
#include <subcmd/parse-options.h>
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."),
OPT_BOOLEAN('v', "long-desc", &long_desc_flag,
"Print longer event descriptions."),
OPT_INCR(0, "debug", &verbose,
"Enable debugging output"),
OPT_END()
};
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,
"Enable kernel symbol demangling"),
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()
};
int ret;
......
......@@ -643,7 +643,7 @@ static void *display_thread(void *arg)
case -1:
if (errno == EINTR)
continue;
/* Fall trhu */
__fallthrough;
default:
c = getc(stdin);
tcsetattr(0, TCSAFLUSH, &save);
......
This diff is collapsed.
[
{
"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"
}
]
[
{
"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"
}
]
This diff is collapsed.
[
{
"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"
}
]
[
{
"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"
}
]
[
{
"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"
}
]
This diff is collapsed.
[
{
"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"
}
]
[
{
"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"
}
]
[
{
"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"
}
]
This diff is collapsed.
[
{
"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"
}
]
[
{
"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"
}
]
This diff is collapsed.
[
{
"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"
}
]
[
{
"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"
}
]
[
{
"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"
}
]
This diff is collapsed.
[
{
"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 *kernel;
} fields[] = {
{ "EventCode", "event=" },
{ "UMask", "umask=" },
{ "CounterMask", "cmask=" },
{ "Invert", "inv=" },
......@@ -189,6 +188,27 @@ static struct msrmap *lookup_msr(char *map, jsmntok_t *val)
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)) { \
jsmntok_t *loc = (t); \
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,
char *desc, char *long_desc)
char *desc, char *long_desc,
char *pmu, char *unit, char *perpkg)
{
struct perf_entry_data *pd = data;
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);
if (long_desc && long_desc[0])
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");
return 0;
......@@ -335,7 +361,8 @@ static char *real_event(const char *name, char *event)
/* Call func with each event in the json file */
int json_events(const char *fn,
int (*func)(void *data, char *name, char *event, char *desc,
char *long_desc),
char *long_desc,
char *pmu, char *unit, char *perpkg),
void *data)
{
int err = -EIO;
......@@ -343,6 +370,7 @@ int json_events(const char *fn,
jsmntok_t *tokens, *tok;
int i, j, len;
char *map;
char buf[128];
if (!fn)
return -ENOENT;
......@@ -356,6 +384,11 @@ int json_events(const char *fn,
char *event = NULL, *desc = NULL, *name = NULL;
char *long_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;
jsmntok_t *msrval = NULL;
jsmntok_t *precise = NULL;
......@@ -376,6 +409,16 @@ int json_events(const char *fn,
nz = !json_streq(map, val, "0");
if (match_field(map, field, nz, &event, val)) {
/* 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")) {
addfield(map, &name, "", "", val);
} else if (json_streq(map, field, "BriefDescription")) {
......@@ -399,6 +442,28 @@ int json_events(const char *fn,
addfield(map, &extra_desc, ". ",
" Supports address when precise",
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 */
}
......@@ -410,20 +475,29 @@ int json_events(const char *fn,
addfield(map, &extra_desc, " ",
"(Precise event)", NULL);
}
snprintf(buf, sizeof buf, "event=%#llx", eventcode);
addfield(map, &event, ",", buf, NULL);
if (desc && extra_desc)
addfield(map, &desc, " ", extra_desc, NULL);
if (long_desc && extra_desc)
addfield(map, &long_desc, " ", extra_desc, NULL);
if (filter)
addfield(map, &event, ",", filter, NULL);
if (msr != NULL)
addfield(map, &event, ",", msr->pname, msrval);
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(desc);
free(name);
free(long_desc);
free(extra_desc);
free(pmu);
free(filter);
free(perpkg);
free(unit);
if (err)
break;
tok += j;
......
......@@ -3,7 +3,9 @@
int json_events(const char *fn,
int (*func)(void *data, char *name, char *event, char *desc,
char *long_desc),
char *long_desc,
char *pmu,
char *unit, char *perpkg),
void *data);
char *get_cpu_str(void);
......
......@@ -10,6 +10,9 @@ struct pmu_event {
const char *desc;
const char *topic;
const char *long_desc;
const char *pmu;
const char *unit;
const char *perpkg;
};
/*
......
......@@ -1779,15 +1779,14 @@ static int test_pmu_events(void)
}
while (!ret && (ent = readdir(dir))) {
#define MAX_NAME 100
struct evlist_test e;
char name[MAX_NAME];
char name[2 * NAME_MAX + 1 + 12 + 3];
/* Names containing . are special and cannot be used directly */
if (strchr(ent->d_name, '.'))
continue;
snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name);
snprintf(name, sizeof(name), "cpu/event=%s/u", ent->d_name);
e.name = name;
e.check = test__checkevent_pmu_events;
......@@ -1795,11 +1794,10 @@ static int test_pmu_events(void)
ret = test_event(&e);
if (ret)
break;
snprintf(name, MAX_NAME, "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name);
snprintf(name, sizeof(name), "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name);
e.name = name;
e.check = test__checkevent_pmu_events_mix;
ret = test_event(&e);
#undef MAX_NAME
}
closedir(dir);
......
......@@ -670,13 +670,13 @@ int bpf__probe(struct bpf_object *obj)
err = convert_perf_probe_events(pev, 1);
if (err < 0) {
pr_debug("bpf_probe: failed to convert perf probe events");
pr_debug("bpf_probe: failed to convert perf probe events\n");
goto out;
}
err = apply_perf_probe_events(pev, 1);
if (err < 0) {
pr_debug("bpf_probe: failed to apply perf probe events");
pr_debug("bpf_probe: failed to apply perf probe events\n");
goto out;
}
......
#include <linux/types.h>
#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
#include <linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
#include <api/fs/fs.h>
#include "event.h"
#include "debug.h"
......
......@@ -3205,6 +3205,7 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
case PERF_EVENT_UPDATE__SCALE:
ev_scale = (struct event_update_event_scale *) ev->data;
evsel->scale = ev_scale->scale;
break;
case PERF_EVENT_UPDATE__CPUS:
ev_cpus = (struct event_update_event_cpus *) ev->data;
......
......@@ -22,6 +22,7 @@
#include <errno.h>
#include <stdint.h>
#include <inttypes.h>
#include <linux/compiler.h>
#include "../cache.h"
#include "../util.h"
......@@ -1746,6 +1747,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
switch (decoder->packet.type) {
case INTEL_PT_TIP_PGD:
decoder->continuous_period = false;
__fallthrough;
case INTEL_PT_TIP_PGE:
case INTEL_PT_TIP:
intel_pt_log("ERROR: Unexpected packet\n");
......@@ -1799,6 +1801,8 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
decoder->pge = false;
decoder->continuous_period = false;
intel_pt_clear_tx_flags(decoder);
__fallthrough;
case INTEL_PT_TNT:
decoder->have_tma = false;
intel_pt_log("ERROR: Unexpected packet\n");
......@@ -1839,6 +1843,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
switch (decoder->packet.type) {
case INTEL_PT_TIP_PGD:
decoder->continuous_period = false;
__fallthrough;
case INTEL_PT_TIP_PGE:
case INTEL_PT_TIP:
decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
......
......@@ -17,6 +17,7 @@
#include <string.h>
#include <endian.h>
#include <byteswap.h>
#include <linux/compiler.h>
#include "intel-pt-pkt-decoder.h"
......@@ -498,6 +499,7 @@ int intel_pt_pkt_desc(const struct intel_pt_pkt *packet, char *buf,
case INTEL_PT_FUP:
if (!(packet->count))
return snprintf(buf, buf_len, "%s no ip", name);
__fallthrough;
case INTEL_PT_CYC:
case INTEL_PT_VMCS:
case INTEL_PT_MTC:
......
......@@ -211,6 +211,8 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
closedir(evt_dir);
closedir(sys_dir);
path = zalloc(sizeof(*path));
if (!path)
return NULL;
path->system = malloc(MAX_EVENT_LENGTH);
if (!path->system) {
free(path);
......@@ -252,8 +254,7 @@ struct tracepoint_path *tracepoint_name_to_path(const char *name)
if (path->system == NULL || path->name == NULL) {
zfree(&path->system);
zfree(&path->name);
free(path);
path = NULL;
zfree(&path);
}
return path;
......@@ -310,10 +311,11 @@ __add_event(struct list_head *list, int *idx,
event_attr_init(attr);
evsel = perf_evsel__new_idx(attr, (*idx)++);
evsel = perf_evsel__new_idx(attr, *idx);
if (!evsel)
return NULL;
(*idx)++;
evsel->cpus = cpu_map__get(cpus);
evsel->own_cpus = cpu_map__get(cpus);
......@@ -1477,10 +1479,9 @@ static void perf_pmu__parse_cleanup(void)
for (i = 0; i < perf_pmu_events_list_num; i++) {
p = perf_pmu_events_list + i;
free(p->symbol);
zfree(&p->symbol);
}
free(perf_pmu_events_list);
perf_pmu_events_list = NULL;
zfree(&perf_pmu_events_list);
perf_pmu_events_list_num = 0;
}
}
......@@ -1504,22 +1505,27 @@ static void perf_pmu__parse_init(void)
struct perf_pmu_alias *alias;
int len = 0;
pmu = perf_pmu__find("cpu");
if ((pmu == NULL) || list_empty(&pmu->aliases)) {
perf_pmu_events_list_num = -1;
return;
}
pmu = NULL;
while ((pmu = perf_pmu__scan(pmu)) != NULL) {
list_for_each_entry(alias, &pmu->aliases, list) {
if (strchr(alias->name, '-'))
len++;
len++;
}
}
if (len == 0) {
perf_pmu_events_list_num = -1;
return;
}
perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len);
if (!perf_pmu_events_list)
return;
perf_pmu_events_list_num = len;
len = 0;
pmu = NULL;
while ((pmu = perf_pmu__scan(pmu)) != NULL) {
list_for_each_entry(alias, &pmu->aliases, list) {
struct perf_pmu_event_symbol *p = perf_pmu_events_list + len;
char *tmp = strchr(alias->name, '-');
......@@ -1535,6 +1541,7 @@ static void perf_pmu__parse_init(void)
len++;
}
}
}
qsort(perf_pmu_events_list, len,
sizeof(struct perf_pmu_event_symbol), comp_pmu);
......@@ -1563,7 +1570,7 @@ perf_pmu__parse_check(const char *name)
r = bsearch(&p, perf_pmu_events_list,
(size_t) perf_pmu_events_list_num,
sizeof(struct perf_pmu_event_symbol), comp_pmu);
free(p.symbol);
zfree(&p.symbol);
return r ? r->type : PMU_EVENT_SYMBOL_ERR;
}
......@@ -1710,8 +1717,8 @@ static void parse_events_print_error(struct parse_events_error *err,
fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err->str);
if (err->help)
fprintf(stderr, "\n%s\n", err->help);
free(err->str);
free(err->help);
zfree(&err->str);
zfree(&err->help);
}
fprintf(stderr, "Run 'perf list' for a list of valid events\n");
......@@ -2406,7 +2413,7 @@ void parse_events_terms__purge(struct list_head *terms)
list_for_each_entry_safe(term, h, terms, list) {
if (term->array.nr_ranges)
free(term->array.ranges);
zfree(&term->array.ranges);
list_del_init(&term->list);
free(term);
}
......@@ -2422,7 +2429,7 @@ void parse_events_terms__delete(struct list_head *terms)
void parse_events__clear_array(struct parse_events_array *a)
{
free(a->ranges);
zfree(&a->ranges);
}
void parse_events_evlist_error(struct parse_events_evlist *data,
......
......@@ -12,6 +12,8 @@
#include <linux/list.h>
#include <linux/types.h>
#include "util.h"
#include "pmu.h"
#include "debug.h"
#include "parse-events.h"
#include "parse-events-bison.h"
......@@ -236,15 +238,34 @@ PE_KERNEL_PMU_EVENT sep_dc
struct list_head *head;
struct parse_events_term *term;
struct list_head *list;
struct perf_pmu *pmu = NULL;
int ok = 0;
/* Add it for all PMUs that support the alias */
ALLOC_LIST(list);
while ((pmu = perf_pmu__scan(pmu)) != NULL) {
struct perf_pmu_alias *alias;
list_for_each_entry(alias, &pmu->aliases, list) {
if (!strcasecmp(alias->name, $1)) {
ALLOC_LIST(head);
ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
$1, 1, &@1, NULL));
list_add_tail(&term->list, head);
ALLOC_LIST(list);
ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
if (!parse_events_add_pmu(data, list,
pmu->name, head)) {
pr_debug("%s -> %s/%s/\n", $1,
pmu->name, alias->str);
ok++;
}
parse_events_terms__delete(head);
}
}
}
if (!ok)
YYABORT;
$$ = list;
}
|
......
......@@ -229,11 +229,13 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
}
static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
char *desc, char *val, char *long_desc,
char *topic)
char *desc, char *val,
char *long_desc, char *topic,
char *unit, char *perpkg)
{
struct perf_pmu_alias *alias;
int ret;
int num;
alias = malloc(sizeof(*alias));
if (!alias)
......@@ -267,6 +269,13 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
alias->long_desc = long_desc ? strdup(long_desc) :
desc ? strdup(desc) : NULL;
alias->topic = topic ? strdup(topic) : NULL;
if (unit) {
if (convert_scale(unit, &unit, &alias->scale) < 0)
return -1;
snprintf(alias->unit, sizeof(alias->unit), "%s", unit);
}
alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1;
alias->str = strdup(val);
list_add_tail(&alias->list, list);
......@@ -284,7 +293,8 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
buf[ret] = 0;
return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL);
return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL,
NULL);
}
static inline bool pmu_alias_info_file(char *name)
......@@ -504,7 +514,7 @@ char * __weak get_cpuid_str(void)
* to the current running CPU. Then, add all PMU events from that table
* as aliases.
*/
static void pmu_add_cpu_aliases(struct list_head *head)
static void pmu_add_cpu_aliases(struct list_head *head, const char *name)
{
int i;
struct pmu_events_map *map;
......@@ -540,14 +550,21 @@ static void pmu_add_cpu_aliases(struct list_head *head)
*/
i = 0;
while (1) {
const char *pname;
pe = &map->table[i++];
if (!pe->name)
break;
pname = pe->pmu ? pe->pmu : "cpu";
if (strncmp(pname, name, strlen(pname)))
continue;
/* need type casts to override 'const' */
__perf_pmu__new_alias(head, NULL, (char *)pe->name,
(char *)pe->desc, (char *)pe->event,
(char *)pe->long_desc, (char *)pe->topic);
(char *)pe->long_desc, (char *)pe->topic,
(char *)pe->unit, (char *)pe->perpkg);
}
out:
......@@ -575,15 +592,16 @@ static struct perf_pmu *pmu_lookup(const char *name)
if (pmu_format(name, &format))
return NULL;
if (pmu_aliases(name, &aliases))
/*
* Check the type first to avoid unnecessary work.
*/
if (pmu_type(name, &type))
return NULL;
if (!strcmp(name, "cpu"))
pmu_add_cpu_aliases(&aliases);
if (pmu_type(name, &type))
if (pmu_aliases(name, &aliases))
return NULL;
pmu_add_cpu_aliases(&aliases, name);
pmu = zalloc(sizeof(*pmu));
if (!pmu)
return NULL;
......@@ -1071,6 +1089,8 @@ struct sevent {
char *name;
char *desc;
char *topic;
char *str;
char *pmu;
};
static int cmp_sevent(const void *a, const void *b)
......@@ -1167,6 +1187,8 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
aliases[j].desc = long_desc ? alias->long_desc :
alias->desc;
aliases[j].topic = alias->topic;
aliases[j].str = alias->str;
aliases[j].pmu = pmu->name;
j++;
}
if (pmu->selectable &&
......@@ -1181,6 +1203,9 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
len = j;
qsort(aliases, len, sizeof(struct sevent), cmp_sevent);
for (j = 0; j < len; j++) {
/* Skip duplicates */
if (j > 0 && !strcmp(aliases[j].name, aliases[j - 1].name))
continue;
if (name_only) {
printf("%s ", aliases[j].name);
continue;
......@@ -1198,6 +1223,8 @@ void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
printf("%*s", 8, "[");
wordwrap(aliases[j].desc, 8, columns, 0);
printf("]\n");
if (verbose)
printf("%*s%s/%s/\n", 8, "", aliases[j].pmu, aliases[j].str);
} else
printf(" %-50s [Kernel PMU event]\n", aliases[j].name);
printed++;
......
......@@ -43,6 +43,7 @@ struct perf_pmu_alias {
char *desc;
char *long_desc;
char *topic;
char *str;
struct list_head terms; /* HEAD struct parse_events_term -> list */
struct list_head list; /* ELEM */
char unit[UNIT_MAX_LEN+1];
......
......@@ -269,6 +269,7 @@ static int strfilter_node__sprint(struct strfilter_node *node, char *buf)
len = strfilter_node__sprint_pt(node->l, buf);
if (len < 0)
return len;
__fallthrough;
case '!':
if (buf) {
*(buf + len++) = *node->p;
......
......@@ -21,6 +21,8 @@ s64 perf_atoll(const char *str)
case 'b': case 'B':
if (*p)
goto out_err;
__fallthrough;
case '\0':
return length;
default:
......
......@@ -1460,9 +1460,11 @@ int dso__load(struct dso *dso, struct map *map)
* DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work
*/
if (!dso->has_build_id &&
is_regular_file(dso->long_name) &&
filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0)
is_regular_file(dso->long_name)) {
__symbol__join_symfs(name, PATH_MAX, dso->long_name);
if (filename__read_build_id(name, build_id, BUILD_ID_SIZE) > 0)
dso__set_build_id(dso, build_id);
}
/*
* Iterate over candidate debug images.
......
......@@ -93,7 +93,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
{
DIR *proc;
int max_threads = 32, items, i;
char path[256];
char path[NAME_MAX + 1 + 6];
struct dirent *dirent, **namelist = NULL;
struct thread_map *threads = thread_map__alloc(max_threads);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment