Page MenuHomeFreeBSD

D35342.diff
No OneTemporary

D35342.diff

diff --git a/lib/libpmc/pmc.3 b/lib/libpmc/pmc.3
--- a/lib/libpmc/pmc.3
+++ b/lib/libpmc/pmc.3
@@ -23,7 +23,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 10, 2021
+.Dd May 28, 2022
.Dt PMC 3
.Os
.Sh NAME
@@ -200,6 +200,8 @@
.Bl -tag -width "Li PMC_CAP_INTERRUPT" -compact
.It Li PMC_CAP_CASCADE
The ability to cascade counters.
+.It Li PMC_CAP_DOMWIDE
+Separate counters tied to each NUMA domain.
.It Li PMC_CAP_EDGE
The ability to count negated to asserted transitions of the hardware
conditions being probed for.
@@ -218,6 +220,8 @@
.It Li PMC_CAP_SYSTEM
The ability to restrict counting of hardware events to when the CPU is
running privileged code.
+.It Li PMC_CAP_SYSWIDE
+A single counter aggregating events for the whole system.
.It Li PMC_CAP_THRESHOLD
The ability to ignore simultaneous hardware events below a
programmable threshold.
diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h
--- a/sys/sys/pmc.h
+++ b/sys/sys/pmc.h
@@ -171,7 +171,10 @@
__PMC_CLASS(MIPS74K, 0x12, "MIPS 74K") \
__PMC_CLASS(E500, 0x13, "Freescale e500 class") \
__PMC_CLASS(BERI, 0x14, "MIPS BERI") \
- __PMC_CLASS(POWER8, 0x15, "IBM POWER8 class")
+ __PMC_CLASS(POWER8, 0x15, "IBM POWER8 class") \
+ __PMC_CLASS(DMC620_PMU_CD2, 0x16, "ARM DMC620 Memory Controller PMU CLKDIV2") \
+ __PMC_CLASS(DMC620_PMU_C, 0x17, "ARM DMC620 Memory Controller PMU CLK") \
+ __PMC_CLASS(CMN600_PMU, 0x18, "Arm CoreLink CMN600 Coherent Mesh Network PMU")
enum pmc_class {
#undef __PMC_CLASS
@@ -180,7 +183,7 @@
};
#define PMC_CLASS_FIRST PMC_CLASS_TSC
-#define PMC_CLASS_LAST PMC_CLASS_POWER8
+#define PMC_CLASS_LAST PMC_CLASS_CMN600_PMU
/*
* A PMC can be in the following states:
@@ -308,7 +311,9 @@
__PMC_CAP(QUALIFIER, 8, "further qualify monitored events") \
__PMC_CAP(PRECISE, 9, "perform precise sampling") \
__PMC_CAP(TAGGING, 10, "tag upstream events") \
- __PMC_CAP(CASCADE, 11, "cascade counters")
+ __PMC_CAP(CASCADE, 11, "cascade counters") \
+ __PMC_CAP(SYSWIDE, 12, "system wide counter") \
+ __PMC_CAP(DOMWIDE, 13, "NUMA domain wide counter")
enum pmc_caps
{
@@ -318,7 +323,7 @@
};
#define PMC_CAP_FIRST PMC_CAP_INTERRUPT
-#define PMC_CAP_LAST PMC_CAP_CASCADE
+#define PMC_CAP_LAST PMC_CAP_DOMWIDE
/*
* PMC Event Numbers
diff --git a/usr.sbin/pmcstat/pmcstat.c b/usr.sbin/pmcstat/pmcstat.c
--- a/usr.sbin/pmcstat/pmcstat.c
+++ b/usr.sbin/pmcstat/pmcstat.c
@@ -59,6 +59,7 @@
#include <regex.h>
#include <signal.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -116,6 +117,7 @@
static kvm_t *pmcstat_kvm;
static struct kinfo_proc *pmcstat_plist;
struct pmcstat_args args;
+static bool libpmc_initialized = false;
static void
pmcstat_get_cpumask(const char *cpuspec, cpuset_t *cpumask)
@@ -419,6 +421,22 @@
endwin();
}
+static inline void
+libpmc_initialize(int *npmc)
+{
+
+ if (libpmc_initialized)
+ return;
+ if (pmc_init() < 0)
+ err(EX_UNAVAILABLE, "ERROR: Initialization of the pmc(3)"
+ " library failed");
+
+ /* assume all CPUs are identical */
+ if ((*npmc = pmc_npmc(0)) < 0)
+ err(EX_OSERR, "ERROR: Cannot determine the number of PMCs on "
+ "CPU %d", 0);
+ libpmc_initialized = true;
+}
/*
* Main
*/
@@ -426,14 +444,14 @@
int
main(int argc, char **argv)
{
- cpuset_t cpumask, rootmask;
+ cpuset_t cpumask, dommask, rootmask;
double interval;
double duration;
int option, npmc;
int c, check_driver_stats;
int do_callchain, do_descendants, do_logproccsw, do_logprocexit;
- int do_print, do_read, do_listcounters, do_descr;
- int do_userspace;
+ int do_print, do_read, do_listcounters, do_descr, domains;
+ int do_userspace, i;
size_t len;
int graphdepth;
int pipefd[2], rfd;
@@ -450,6 +468,7 @@
struct winsize ws;
struct stat sb;
char buffer[PATH_MAX];
+ uint32_t caps;
check_driver_stats = 0;
current_sampling_count = 0;
@@ -460,6 +479,7 @@
do_logproccsw = 0;
do_logprocexit = 0;
do_listcounters = 0;
+ domains = 0;
use_cumulative_counts = 0;
graphfilename = "-";
args.pa_required = 0;
@@ -489,8 +509,10 @@
bzero(&ds_end, sizeof(ds_end));
ev = NULL;
event = NULL;
+ caps = 0;
CPU_ZERO(&cpumask);
+
/* Default to using the running system kernel. */
len = 0;
if (sysctlbyname("kern.bootfile", NULL, &len, NULL, 0) == -1)
@@ -500,6 +522,9 @@
errx(EX_SOFTWARE, "ERROR: Out of memory.");
if (sysctlbyname("kern.bootfile", args.pa_kernel, &len, NULL, 0) == -1)
err(EX_OSERR, "ERROR: Cannot determine path of running kernel");
+ len = sizeof(domains);
+ if (sysctlbyname("vm.ndomains", &domains, &len, NULL, 0) == -1)
+ err(EX_OSERR, "ERROR: Cannot get number of domains");
/*
* The initial CPU mask specifies the root mask of this process
@@ -640,6 +665,7 @@
case 's': /* system-wide counting PMC */
case 'P': /* process virtual sampling PMC */
case 'S': /* system-wide sampling PMC */
+ caps = 0;
if ((ev = malloc(sizeof(*ev))) == NULL)
errx(EX_SOFTWARE, "ERROR: Out of memory.");
@@ -707,12 +733,48 @@
errx(EX_SOFTWARE, "ERROR: Out of memory.");
(void) strncpy(ev->ev_name, optarg, c);
*(ev->ev_name + c) = '\0';
+ libpmc_initialize(&npmc);
+ if (args.pa_flags & FLAG_HAS_SYSTEM_PMCS) {
+ if (pmc_allocate(ev->ev_spec, ev->ev_mode,
+ ev->ev_flags, ev->ev_cpu, &ev->ev_pmcid,
+ ev->ev_count) < 0)
+ err(EX_OSERR, "ERROR: Cannot allocate "
+ "system-mode pmc with specification"
+ " \"%s\"", ev->ev_spec);
+ if (pmc_capabilities(ev->ev_pmcid, &caps)) {
+ pmc_release(ev->ev_pmcid);
+ err(EX_OSERR, "ERROR: Cannot get pmc "
+ "capabilities");
+ }
+ }
+
STAILQ_INSERT_TAIL(&args.pa_events, ev, ev_next);
+ if ((caps & PMC_CAP_SYSWIDE) == PMC_CAP_SYSWIDE)
+ break;
+ if ((caps & PMC_CAP_DOMWIDE) == PMC_CAP_DOMWIDE) {
+ CPU_ZERO(&cpumask);
+ /*
+ * Get number of domains and allocate one
+ * counter in each.
+ * First already allocated.
+ */
+ for (i = 1; i < domains; i++) {
+ CPU_ZERO(&dommask);
+ cpuset_getaffinity(CPU_LEVEL_WHICH,
+ CPU_WHICH_DOMAIN, i, sizeof(dommask),
+ &dommask);
+ CPU_SET(CPU_FFS(&dommask) - 1, &cpumask);
+ }
+ args.pa_flags |= FLAGS_HAS_CPUMASK;
+ }
if (option == 's' || option == 'S') {
CPU_CLR(ev->ev_cpu, &cpumask);
+ pmc_id_t saved_pmcid = ev->ev_pmcid;
+ ev->ev_pmcid = PMC_ID_INVALID;
pmcstat_clone_event_descriptor(ev, &cpumask, &args);
+ ev->ev_pmcid = saved_pmcid;
CPU_SET(ev->ev_cpu, &cpumask);
}
@@ -1050,17 +1112,8 @@
}
/* if we've been asked to process a log file, skip init */
- if ((args.pa_flags & FLAG_READ_LOGFILE) == 0) {
- if (pmc_init() < 0)
- err(EX_UNAVAILABLE,
- "ERROR: Initialization of the pmc(3) library failed"
- );
-
- if ((npmc = pmc_npmc(0)) < 0) /* assume all CPUs are identical */
- err(EX_OSERR,
-"ERROR: Cannot determine the number of PMCs on CPU %d",
- 0);
- }
+ if ((args.pa_flags & FLAG_READ_LOGFILE) == 0)
+ libpmc_initialize(&npmc);
/* Allocate a kqueue */
if ((pmcstat_kq = kqueue()) < 0)
@@ -1134,7 +1187,8 @@
*/
STAILQ_FOREACH(ev, &args.pa_events, ev_next) {
- if (pmc_allocate(ev->ev_spec, ev->ev_mode,
+ if (ev->ev_pmcid == PMC_ID_INVALID &&
+ pmc_allocate(ev->ev_spec, ev->ev_mode,
ev->ev_flags, ev->ev_cpu, &ev->ev_pmcid,
ev->ev_count) < 0)
err(EX_OSERR,

File Metadata

Mime Type
text/plain
Expires
Mon, Dec 2, 12:39 AM (21 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14973925
Default Alt Text
D35342.diff (7 KB)

Event Timeline