git: fbbf71f5813b - main - libpmc: surface raw TSC in pmclog events
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 16 Apr 2026 06:06:31 UTC
The branch main has been updated by imp:
URL: https://cgit.FreeBSD.org/src/commit/?id=fbbf71f5813b041526c4d439d9961e8a8281d291
commit fbbf71f5813b041526c4d439d9961e8a8281d291
Author: Andre Silva <andasilv@amd.com>
AuthorDate: 2026-03-31 20:28:04 +0000
Commit: Warner Losh <imp@FreeBSD.org>
CommitDate: 2026-04-16 06:05:21 +0000
libpmc: surface raw TSC in pmclog events
The pmclog record header carries the raw TSC for each event. Export it
in struct pmclog_ev, fix JSON output to emit it unsigned, and preserve
the installed header ABI by overlaying pl_tsc with the legacy pl_ts
storage.
Update pmclog(3) to document the TSC semantics and the legacy alias.
Sponsored by: AMD
Signed-off-by: Andre Silva <andasilv@amd.com>
Reviewed by: imp, mhorne, Ali Mashtizadeh
Pull Request: https://github.com/freebsd/freebsd-src/pull/2085
---
lib/libpmc/libpmc_json.cc | 5 ++---
lib/libpmc/pmclog.3 | 29 +++++++++++++++++++++++++++--
lib/libpmc/pmclog.c | 4 ++--
lib/libpmc/pmclog.h | 6 ++++--
4 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/lib/libpmc/libpmc_json.cc b/lib/libpmc/libpmc_json.cc
index 90881f22971e..1ac0b3a50a6c 100644
--- a/lib/libpmc/libpmc_json.cc
+++ b/lib/libpmc/libpmc_json.cc
@@ -74,8 +74,8 @@ startentry(struct pmclog_ev *ev)
{
char eventbuf[128];
- snprintf(eventbuf, sizeof(eventbuf), "%s, \"tsc\": \"%jd\"",
- typenames[ev->pl_type], (uintmax_t)ev->pl_ts.tv_sec);
+ snprintf(eventbuf, sizeof(eventbuf), "%s, \"tsc\": \"%ju\"",
+ typenames[ev->pl_type], (uintmax_t)ev->pl_tsc);
return (string(eventbuf));
}
@@ -393,4 +393,3 @@ event_to_json(struct pmclog_ev *ev){
errx(EX_USAGE, "ERROR: unrecognized event type: %d\n", ev->pl_type);
}
}
-
diff --git a/lib/libpmc/pmclog.3 b/lib/libpmc/pmclog.3
index 4af4150d60a9..452a14f42f55 100644
--- a/lib/libpmc/pmclog.3
+++ b/lib/libpmc/pmclog.3
@@ -77,7 +77,10 @@ struct pmclog_ev {
enum pmclog_state pl_state; /* parser state after 'get_event()' */
off_t pl_offset; /* byte offset in stream */
size_t pl_count; /* count of records so far */
- struct timespec pl_ts; /* log entry timestamp */
+ union {
+ uint64_t pl_tsc; /* TSC timestamp */
+ struct timespec pl_ts; /* log entry timestamp (legacy) */
+ };
enum pmclog_type pl_type; /* log entry kind */
union { /* log entry data */
struct pmclog_ev_callchain pl_cc;
@@ -136,8 +139,30 @@ Field
.Va pl_count
contains the serial number of this event.
Field
+.Va pl_tsc
+carries the raw CPU Time Stamp Counter (TSC) value recorded at the time
+of the event.
+This is not a wall-clock time; to convert to nanoseconds divide the TSC
+delta between two events by the TSC frequency
+.Pq Va pl_u.pl_i.pl_tsc_freq
+reported in the
+.Dv PMCLOG_TYPE_INITIALIZE
+record.
+The legacy
.Va pl_ts
-contains a timestamp with the system time when the event occurred.
+member aliases the same storage for ABI compatibility, but its contents
+no longer represent a wall-clock timestamp.
+.Pp
+Note that TSC-based timestamps and
+.Va pl_u.pl_i.pl_tsc_freq
+are only meaningful on x86 architectures
+.Pq amd64 and i386 .
+On all other architectures
+.Pq including arm64 and powerpc ,
+.Va pl_tsc
+and
+.Va pl_u.pl_i.pl_tsc_freq
+are set to zero.
Field
.Va pl_type
denotes the kind of the event returned in argument
diff --git a/lib/libpmc/pmclog.c b/lib/libpmc/pmclog.c
index 22ff50b10ee0..c3587af46c7b 100644
--- a/lib/libpmc/pmclog.c
+++ b/lib/libpmc/pmclog.c
@@ -287,8 +287,8 @@ pmclog_get_event(void *cookie, char **data, ssize_t *len,
return -1;
}
- /* copy out the time stamp */
- ev->pl_ts.tv_sec = ph->pl_tsc;
+ /* copy out the TSC from the event header */
+ ev->pl_tsc = ph->pl_tsc;
le += sizeof(*ph)/4;
evlen = PMCLOG_HEADER_TO_LENGTH(h);
diff --git a/lib/libpmc/pmclog.h b/lib/libpmc/pmclog.h
index 72e73e3928d2..a79d33529890 100644
--- a/lib/libpmc/pmclog.h
+++ b/lib/libpmc/pmclog.h
@@ -169,7 +169,10 @@ struct pmclog_ev {
enum pmclog_state pl_state; /* state after 'get_event()' */
off_t pl_offset; /* byte offset in stream */
size_t pl_count; /* count of records so far */
- struct timespec pl_ts; /* log entry timestamp */
+ union {
+ uint64_t pl_tsc; /* TSC timestamp */
+ struct timespec pl_ts; /* log entry timestamp (legacy) */
+ };
enum pmclog_type pl_type; /* type of log entry */
void *pl_data;
int pl_len;
@@ -229,4 +232,3 @@ void pmclog_close(void *_cookie);
__END_DECLS
#endif
-