svn commit: r334749 - in head: lib lib/libpmc sys/dev/hwpmc sys/sys usr.sbin usr.sbin/pmc usr.sbin/pmccontrol usr.sbin/pmcstat

Matt Macy mmacy at FreeBSD.org
Thu Jun 7 02:05:02 UTC 2018


Author: mmacy
Date: Thu Jun  7 02:03:22 2018
New Revision: 334749
URL: https://svnweb.freebsd.org/changeset/base/334749

Log:
  pmc: convert native to jsonl and track TSC value of samples
  
  - add '-j' options to filter to enable converting native pmc
    log format to json lines format to enable the use of scripts
    and external tooling
  
  % pmc filter -j pmc.log pmc.jsonl
  
  - Record the tsc value in sampling interrupts as opposed to
    recording nanotime when the sample is copied to a global log
    in hardclock - potentially many milliseconds later.
  
  - At initialize record the tsc_freq and the time of day to give
    us an offset for translating the tsc values in callchain records

Added:
  head/lib/libpmc/libpmc_json.cc   (contents, props changed)
  head/lib/libpmc/pmcformat.h   (contents, props changed)
Modified:
  head/lib/Makefile
  head/lib/libpmc/Makefile
  head/lib/libpmc/pmclog.c
  head/lib/libpmc/pmclog.h
  head/sys/dev/hwpmc/hwpmc_logging.c
  head/sys/dev/hwpmc/hwpmc_mod.c
  head/sys/sys/pmc.h
  head/sys/sys/pmclog.h
  head/usr.sbin/Makefile
  head/usr.sbin/pmc/Makefile   (contents, props changed)
  head/usr.sbin/pmc/cmd_pmc_filter.cc
  head/usr.sbin/pmccontrol/Makefile
  head/usr.sbin/pmcstat/Makefile

Modified: head/lib/Makefile
==============================================================================
--- head/lib/Makefile	Thu Jun  7 00:55:17 2018	(r334748)
+++ head/lib/Makefile	Thu Jun  7 02:03:22 2018	(r334749)
@@ -202,7 +202,9 @@ _libdl=		libdl
 .endif
 
 SUBDIR.${MK_OPENSSL}+=	libmp
+.if (${COMPILER_TYPE} == "clang" || (${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} >= 60100))
 SUBDIR.${MK_PMC}+=	libpmc libpmcstat
+.endif
 SUBDIR.${MK_RADIUS_SUPPORT}+=	libradius
 SUBDIR.${MK_SENDMAIL}+=	libmilter libsm libsmdb libsmutil
 SUBDIR.${MK_TELNET}+=	libtelnet

Modified: head/lib/libpmc/Makefile
==============================================================================
--- head/lib/libpmc/Makefile	Thu Jun  7 00:55:17 2018	(r334748)
+++ head/lib/libpmc/Makefile	Thu Jun  7 02:03:22 2018	(r334749)
@@ -3,8 +3,8 @@
 PACKAGE=lib${LIB}
 LIB=	pmc
 
-SRCS=	libpmc.c pmclog.c libpmc_pmu_util.c
-INCS=	pmc.h pmclog.h
+SRCS=	libpmc.c pmclog.c libpmc_pmu_util.c libpmc_json.cc
+INCS=	pmc.h pmclog.h pmcformat.h
 
 CFLAGS+= -I${.CURDIR}
 

Added: head/lib/libpmc/libpmc_json.cc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libpmc/libpmc_json.cc	Thu Jun  7 02:03:22 2018	(r334749)
@@ -0,0 +1,393 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018, Matthew Macy
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/sysctl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <err.h>
+#include <limits.h>
+#include <string.h>
+#include <pmc.h>
+#include <pmclog.h>
+#include <assert.h>
+#include <string>
+#include <sysexits.h>
+#include <pmcformat.h>
+
+using std::string;
+
+static const char *typenames[] = {
+	"",
+	"{\"type\": \"closelog\"}\n",
+	"{\"type\": \"dropnotify\"}\n",
+	"{\"type\": \"initialize\"",
+	"",
+	"{\"type\": \"pmcallocate\"",
+	"{\"type\": \"pmcattach\"",
+	"{\"type\": \"pmcdetach\"",
+	"{\"type\": \"proccsw\"",
+	"{\"type\": \"procexec\"",
+	"{\"type\": \"procexit\"",
+	"{\"type\": \"procfork\"",
+	"{\"type\": \"sysexit\"",
+	"{\"type\": \"userdata\"",
+	"{\"type\": \"map_in\"",
+	"{\"type\": \"map_out\"",
+	"{\"type\": \"callchain\"",
+	"{\"type\": \"pmcallocatedyn\"",
+	"{\"type\": \"thr_create\"",
+	"{\"type\": \"thr_exit\"",
+	"{\"type\": \"proc_create\"",
+};
+
+static string
+startentry(struct pmclog_ev *ev)
+{
+	char eventbuf[128];
+
+	snprintf(eventbuf, sizeof(eventbuf), "%s, \"tsc\": \"%jd\"",
+	    typenames[ev->pl_type], (intmax_t)ev->pl_ts.tv_sec);
+	return (string(eventbuf));
+}
+
+static string
+initialize_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[256];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf),
+	    "%s, \"version\": \"0x%08x\", \"arch\": \"0x%08x\", \"cpuid\": \"%s\", "
+		"\"tsc_freq\": \"%jd\", \"sec\": \"%jd\", \"nsec\": \"%jd\"}\n",
+		startent.c_str(), ev->pl_u.pl_i.pl_version, ev->pl_u.pl_i.pl_arch,
+		ev->pl_u.pl_i.pl_cpuid, (uintmax_t)ev->pl_u.pl_i.pl_tsc_freq,
+		(uintmax_t)ev->pl_u.pl_i.pl_ts.tv_sec, (uintmax_t)ev->pl_u.pl_i.pl_ts.tv_nsec);
+	return string(eventbuf);
+}
+
+static string
+pmcallocate_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[256];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf),
+	    "%s, \"pmcid\": \"0x%08x\", \"event\": \"0x%08x\", \"flags\": \"0x%08x\", "
+	    "\"rate\": \"%jd\"}\n",
+		startent.c_str(), ev->pl_u.pl_a.pl_pmcid, ev->pl_u.pl_a.pl_event,
+	    ev->pl_u.pl_a.pl_flags, (intmax_t)ev->pl_u.pl_a.pl_rate);
+	return string(eventbuf);
+}
+
+static string
+pmcattach_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[2048];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf),
+	    "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\", \"pathname\": \"%s\"}\n",
+		startent.c_str(), ev->pl_u.pl_t.pl_pmcid, ev->pl_u.pl_t.pl_pid,
+	    ev->pl_u.pl_t.pl_pathname);
+	return string(eventbuf);
+}
+
+static string
+pmcdetach_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[128];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf),
+		"%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\"}\n",
+			 startent.c_str(), ev->pl_u.pl_d.pl_pmcid, ev->pl_u.pl_d.pl_pid);
+	return string(eventbuf);
+}
+
+
+static string
+proccsw_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[128];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf), "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\" "
+	    "\"tid\": \"%d\", \"value\": \"0x%016jx\"}\n",
+		startent.c_str(), ev->pl_u.pl_c.pl_pmcid, ev->pl_u.pl_c.pl_pid,
+	    ev->pl_u.pl_c.pl_tid, (uintmax_t)ev->pl_u.pl_c.pl_value);
+	return string(eventbuf);
+}
+
+static string
+procexec_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[2048];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf),
+		"%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\", "
+	    "\"start\": \"0x%016jx\", \"pathname\": \"%s\"}\n",
+		startent.c_str(), ev->pl_u.pl_x.pl_pmcid, ev->pl_u.pl_x.pl_pid,
+	    ev->pl_u.pl_x.pl_entryaddr, ev->pl_u.pl_x.pl_pathname);
+	return string(eventbuf);
+}
+
+static string
+procexit_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[128];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf),
+		"%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\", "
+	    "\"value\": \"0x%016jx\"}\n",
+		startent.c_str(), ev->pl_u.pl_e.pl_pmcid, ev->pl_u.pl_e.pl_pid,
+	    (uintmax_t)ev->pl_u.pl_e.pl_value);
+	return string(eventbuf);
+}
+
+static string
+procfork_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[128];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf),
+		"%s, \"oldpid\": \"%d\", \"newpid\": \"%d\"}\n",
+		startent.c_str(), ev->pl_u.pl_f.pl_oldpid, ev->pl_u.pl_f.pl_newpid);
+	return string(eventbuf);
+}
+
+static string
+sysexit_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[128];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf), "%s, \"pid\": \"%d\"}\n",
+		startent.c_str(), ev->pl_u.pl_se.pl_pid);
+	return string(eventbuf);
+}
+
+static string
+userdata_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[128];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf), "%s, \"userdata\": \"0x%08x\"}\n",
+	    startent.c_str(), ev->pl_u.pl_u.pl_userdata);
+	return string(eventbuf);
+}
+
+static string
+map_in_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[2048];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf), "%s, \"pid\": \"%d\", "
+	    "\"start\": \"0x%016jx\", \"pathname\": \"%s\"}\n",
+	    startent.c_str(), ev->pl_u.pl_mi.pl_pid,
+	    (uintmax_t)ev->pl_u.pl_mi.pl_start, ev->pl_u.pl_mi.pl_pathname);
+	return string(eventbuf);
+}
+
+static string
+map_out_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[256];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf), "%s, \"pid\": \"%d\", "
+	    "\"start\": \"0x%016jx\", \"end\": \"0x%016jx\"}\n",
+	    startent.c_str(), ev->pl_u.pl_mi.pl_pid,
+	    (uintmax_t)ev->pl_u.pl_mi.pl_start,
+	    (uintmax_t)ev->pl_u.pl_mo.pl_end);
+	return string(eventbuf);
+}
+
+static string
+callchain_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[1024];
+	string result;
+	uint32_t i;
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf),
+	    "%s, \"pmcid\": \"0x%08x\", \"pid\": \"%d\", \"tid\": \"%d\", "
+	    "\"cpuflags\": \"0x%08x\", \"cpuflags2\": \"0x%08x\", \"pc\": [ ",
+		startent.c_str(), ev->pl_u.pl_cc.pl_pmcid, ev->pl_u.pl_cc.pl_pid,
+	    ev->pl_u.pl_cc.pl_tid, ev->pl_u.pl_cc.pl_cpuflags, ev->pl_u.pl_cc.pl_cpuflags2);
+	result = string(eventbuf);
+	for (i = 0; i < ev->pl_u.pl_cc.pl_npc - 1; i++) {
+		snprintf(eventbuf, sizeof(eventbuf), "\"0x%016jx\", ", ev->pl_u.pl_cc.pl_pc[i]);
+		result += string(eventbuf);
+	}
+	snprintf(eventbuf, sizeof(eventbuf), "\"0x%016jx\"]}\n", ev->pl_u.pl_cc.pl_pc[i]);
+	result += string(eventbuf);
+	return (result);
+}
+
+static string
+pmcallocatedyn_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[2048];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf),
+	    "%s, \"pmcid\": \"0x%08x\", \"event\": \"%d\", \"flags\": \"0x%08x\", \"evname\": \"%s\"}\n",
+	    startent.c_str(), ev->pl_u.pl_ad.pl_pmcid, ev->pl_u.pl_ad.pl_event,
+	    ev->pl_u.pl_ad.pl_flags, ev->pl_u.pl_ad.pl_evname);
+	return string(eventbuf);
+}
+
+static string
+proccreate_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[2048];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf),
+	    "%s, \"pid\": \"%d\", \"flags\": \"0x%08x\", \"pcomm\": \"%s\"}\n",
+	    startent.c_str(), ev->pl_u.pl_pc.pl_pid,
+	    ev->pl_u.pl_pc.pl_flags, ev->pl_u.pl_pc.pl_pcomm);
+	return string(eventbuf);
+}
+
+static string
+threadcreate_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[2048];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf),
+	    "%s, \"tid\": \"%d\", \"pid\": \"%d\", \"flags\": \"0x%08x\", \"tdname\": \"%s\"}\n",
+	    startent.c_str(), ev->pl_u.pl_tc.pl_tid, ev->pl_u.pl_tc.pl_pid,
+	    ev->pl_u.pl_tc.pl_flags, ev->pl_u.pl_tc.pl_tdname);
+	return string(eventbuf);
+}
+
+static string
+threadexit_to_json(struct pmclog_ev *ev)
+{
+	char eventbuf[256];
+	string startent;
+
+	startent = startentry(ev);
+	snprintf(eventbuf, sizeof(eventbuf), "%s, \"tid\": \"%d\"}\n",
+	    startent.c_str(), ev->pl_u.pl_te.pl_tid);
+	return string(eventbuf);
+}
+
+static string
+stub_to_json(struct pmclog_ev *ev)
+{
+	string startent;
+
+	startent = startentry(ev);
+	startent += string("}\n");
+	return startent;
+}
+
+typedef string (*jconv) (struct pmclog_ev*);
+
+static jconv jsonconvert[] = {
+	NULL,
+	stub_to_json,
+	stub_to_json,
+	initialize_to_json,
+	NULL,
+	pmcallocate_to_json,
+	pmcattach_to_json,
+	pmcdetach_to_json,
+	proccsw_to_json,
+	procexec_to_json,
+	procexit_to_json,
+	procfork_to_json,
+	sysexit_to_json,
+	userdata_to_json,
+	map_in_to_json,
+	map_out_to_json,
+	callchain_to_json,
+	pmcallocatedyn_to_json,
+	threadcreate_to_json,
+	threadexit_to_json,
+	proccreate_to_json,
+};
+
+string
+event_to_json(struct pmclog_ev *ev){
+
+	switch (ev->pl_type) {
+	case PMCLOG_TYPE_DROPNOTIFY:
+	case PMCLOG_TYPE_CLOSELOG:
+	case PMCLOG_TYPE_INITIALIZE:
+	case PMCLOG_TYPE_PMCALLOCATE:
+	case PMCLOG_TYPE_PMCATTACH:
+	case PMCLOG_TYPE_PMCDETACH:
+	case PMCLOG_TYPE_PROCCSW:
+	case PMCLOG_TYPE_PROCEXEC:
+	case PMCLOG_TYPE_PROCEXIT:
+	case PMCLOG_TYPE_PROCFORK:
+	case PMCLOG_TYPE_SYSEXIT:
+	case PMCLOG_TYPE_USERDATA:
+	case PMCLOG_TYPE_MAP_IN:
+	case PMCLOG_TYPE_MAP_OUT:
+	case PMCLOG_TYPE_CALLCHAIN:
+	case PMCLOG_TYPE_PMCALLOCATEDYN:
+	case PMCLOG_TYPE_THR_CREATE:
+	case PMCLOG_TYPE_THR_EXIT:
+	case PMCLOG_TYPE_PROC_CREATE:
+		return jsonconvert[ev->pl_type](ev);
+	default:
+		errx(EX_USAGE, "ERROR: unrecognized event type: %d\n", ev->pl_type);
+	}
+}
+

Added: head/lib/libpmc/pmcformat.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lib/libpmc/pmcformat.h	Thu Jun  7 02:03:22 2018	(r334749)
@@ -0,0 +1,33 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018, Matthew Macy
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ *
+ */
+#ifndef __PMCFORMAT_H_
+#define __PMCFORMAT_H_
+std::string event_to_json(struct pmclog_ev *ev);
+#endif

Modified: head/lib/libpmc/pmclog.c
==============================================================================
--- head/lib/libpmc/pmclog.c	Thu Jun  7 00:55:17 2018	(r334748)
+++ head/lib/libpmc/pmclog.c	Thu Jun  7 02:03:22 2018	(r334749)
@@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$");
 
 #include "libpmcinternal.h"
 
-#define	PMCLOG_BUFFER_SIZE			4096
+#define	PMCLOG_BUFFER_SIZE			512*1024
 
 /*
  * API NOTES
@@ -260,6 +260,7 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
 	uint32_t h, *le, npc, noop;
 	enum pmclog_parser_state e;
 	struct pmclog_parse_state *ps;
+	struct pmclog_header *ph;
 
 	ps = (struct pmclog_parse_state *) cookie;
 
@@ -278,8 +279,9 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
 
 	PMCLOG_INITIALIZE_READER(le, ps->ps_saved);
 	ev->pl_data = le;
-	PMCLOG_READ32(le,h);
+	ph = (struct pmclog_header *)(uintptr_t)le;
 
+	h = ph->pl_header;
 	if (!PMCLOG_HEADER_CHECK_MAGIC(h)) {
 		printf("bad magic\n");
 		ps->ps_state = PL_STATE_ERROR;
@@ -288,8 +290,8 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
 	}
 
 	/* copy out the time stamp */
-	PMCLOG_READ32(le,ev->pl_ts.tv_sec);
-	PMCLOG_READ32(le,ev->pl_ts.tv_nsec);
+	ev->pl_ts.tv_sec = ph->pl_tsc;
+	le += sizeof(*ph)/4;
 
 	evlen = PMCLOG_HEADER_TO_LENGTH(h);
 
@@ -310,7 +312,6 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
 		PMCLOG_READ32(le,ev->pl_u.pl_cc.pl_tid);
 		PMCLOG_READ32(le,ev->pl_u.pl_cc.pl_pmcid);
 		PMCLOG_READ32(le,ev->pl_u.pl_cc.pl_cpuflags);
-		PMCLOG_READ32(le,ev->pl_u.pl_cc.pl_cpuflags2);
 		PMCLOG_GET_CALLCHAIN_SIZE(ev->pl_u.pl_cc.pl_npc,evlen);
 		for (npc = 0; npc < ev->pl_u.pl_cc.pl_npc; npc++)
 			PMCLOG_READADDR(le,ev->pl_u.pl_cc.pl_pc[npc]);
@@ -326,6 +327,9 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
 	case PMCLOG_TYPE_INITIALIZE:
 		PMCLOG_READ32(le,ev->pl_u.pl_i.pl_version);
 		PMCLOG_READ32(le,ev->pl_u.pl_i.pl_arch);
+		PMCLOG_READ64(le,ev->pl_u.pl_i.pl_tsc_freq);
+		memcpy(&ev->pl_u.pl_i.pl_ts, le, sizeof(struct timespec));
+		le += sizeof(struct timespec)/4;
 		PMCLOG_READSTRING(le, ev->pl_u.pl_i.pl_cpuid, PMC_CPUID_LEN);
 		memcpy(ev->pl_u.pl_i.pl_cpuid, le, PMC_CPUID_LEN);
 		ps->ps_cpuid = strdup(ev->pl_u.pl_i.pl_cpuid);
@@ -336,11 +340,13 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
 	case PMCLOG_TYPE_MAP_IN:
 		PMCLOG_GET_PATHLEN(pathlen,evlen,pmclog_map_in);
 		PMCLOG_READ32(le,ev->pl_u.pl_mi.pl_pid);
+		PMCLOG_READ32(le,noop);
 		PMCLOG_READADDR(le,ev->pl_u.pl_mi.pl_start);
 		PMCLOG_READSTRING(le, ev->pl_u.pl_mi.pl_pathname, pathlen);
 		break;
 	case PMCLOG_TYPE_MAP_OUT:
 		PMCLOG_READ32(le,ev->pl_u.pl_mo.pl_pid);
+		PMCLOG_READ32(le,noop);
 		PMCLOG_READADDR(le,ev->pl_u.pl_mo.pl_start);
 		PMCLOG_READADDR(le,ev->pl_u.pl_mo.pl_end);
 		break;
@@ -348,6 +354,7 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
 		PMCLOG_READ32(le,ev->pl_u.pl_a.pl_pmcid);
 		PMCLOG_READ32(le,ev->pl_u.pl_a.pl_event);
 		PMCLOG_READ32(le,ev->pl_u.pl_a.pl_flags);
+		PMCLOG_READ32(le,noop);
 		PMCLOG_READ64(le,ev->pl_u.pl_a.pl_rate);
 		ev->pl_u.pl_a.pl_evname = pmc_pmu_event_get_by_idx(ps->ps_cpuid, ev->pl_u.pl_a.pl_event);
 		if (ev->pl_u.pl_a.pl_evname != NULL)
@@ -363,6 +370,7 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
 		PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_pmcid);
 		PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_event);
 		PMCLOG_READ32(le,ev->pl_u.pl_ad.pl_flags);
+		PMCLOG_READ32(le,noop);
 		PMCLOG_READSTRING(le,ev->pl_u.pl_ad.pl_evname,PMC_NAME_MAX);
 		break;
 	case PMCLOG_TYPE_PMCATTACH:
@@ -376,8 +384,8 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
 		PMCLOG_READ32(le,ev->pl_u.pl_d.pl_pid);
 		break;
 	case PMCLOG_TYPE_PROCCSW:
-		PMCLOG_READ32(le,ev->pl_u.pl_c.pl_pmcid);
 		PMCLOG_READ64(le,ev->pl_u.pl_c.pl_value);
+		PMCLOG_READ32(le,ev->pl_u.pl_c.pl_pmcid);
 		PMCLOG_READ32(le,ev->pl_u.pl_c.pl_pid);
 		PMCLOG_READ32(le,ev->pl_u.pl_c.pl_tid);
 		break;
@@ -385,14 +393,12 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
 		PMCLOG_GET_PATHLEN(pathlen,evlen,pmclog_procexec);
 		PMCLOG_READ32(le,ev->pl_u.pl_x.pl_pid);
 		PMCLOG_READ32(le,ev->pl_u.pl_x.pl_pmcid);
-		PMCLOG_READ32(le,noop);
 		PMCLOG_READADDR(le,ev->pl_u.pl_x.pl_entryaddr);
 		PMCLOG_READSTRING(le,ev->pl_u.pl_x.pl_pathname,pathlen);
 		break;
 	case PMCLOG_TYPE_PROCEXIT:
 		PMCLOG_READ32(le,ev->pl_u.pl_e.pl_pmcid);
 		PMCLOG_READ32(le,ev->pl_u.pl_e.pl_pid);
-		PMCLOG_READ32(le,noop);
 		PMCLOG_READ64(le,ev->pl_u.pl_e.pl_value);
 		break;
 	case PMCLOG_TYPE_PROCFORK:
@@ -409,6 +415,7 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
 		PMCLOG_READ32(le,ev->pl_u.pl_tc.pl_tid);
 		PMCLOG_READ32(le,ev->pl_u.pl_tc.pl_pid);
 		PMCLOG_READ32(le,ev->pl_u.pl_tc.pl_flags);
+		PMCLOG_READ32(le,noop);
 		memcpy(ev->pl_u.pl_tc.pl_tdname, le, MAXCOMLEN+1);
 		break;
 	case PMCLOG_TYPE_THR_EXIT:
@@ -417,7 +424,6 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
 	case PMCLOG_TYPE_PROC_CREATE:
 		PMCLOG_READ32(le,ev->pl_u.pl_pc.pl_pid);
 		PMCLOG_READ32(le,ev->pl_u.pl_pc.pl_flags);
-		PMCLOG_READ32(le,noop);
 		memcpy(ev->pl_u.pl_pc.pl_pcomm, le, MAXCOMLEN+1);
 		break;
 	default:	/* unknown record type */

Modified: head/lib/libpmc/pmclog.h
==============================================================================
--- head/lib/libpmc/pmclog.h	Thu Jun  7 00:55:17 2018	(r334748)
+++ head/lib/libpmc/pmclog.h	Thu Jun  7 02:03:22 2018	(r334749)
@@ -64,6 +64,8 @@ struct pmclog_ev_closelog {
 struct pmclog_ev_initialize {
 	uint32_t	pl_version;
 	uint32_t	pl_arch;
+	uint64_t	pl_tsc_freq;
+	struct timespec pl_ts;
 	char		pl_cpuid[PATH_MAX];
 };
 

Modified: head/sys/dev/hwpmc/hwpmc_logging.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_logging.c	Thu Jun  7 00:55:17 2018	(r334748)
+++ head/sys/dev/hwpmc/hwpmc_logging.c	Thu Jun  7 02:03:22 2018	(r334749)
@@ -61,6 +61,10 @@ __FBSDID("$FreeBSD$");
 #include <sys/unistd.h>
 #include <sys/vnode.h>
 
+#if defined(__i386__) || defined(__amd64__)
+#include <machine/clock.h>
+#endif
+
 #ifdef NUMA
 #define NDOMAINS vm_ndomains
 #define curdomain PCPU_GET(domain)
@@ -124,29 +128,38 @@ static struct mtx pmc_kthread_mtx;	/* sleep lock */
 	 ((L) & 0xFFFF))
 
 /* reserve LEN bytes of space and initialize the entry header */
-#define	_PMCLOG_RESERVE_SAFE(PO,TYPE,LEN,ACTION) do {			\
+#define	_PMCLOG_RESERVE_SAFE(PO,TYPE,LEN,ACTION, TSC) do {	\
 		uint32_t *_le;						\
 		int _len = roundup((LEN), sizeof(uint32_t));	\
+		struct pmclog_header *ph;							\
 		if ((_le = pmclog_reserve((PO), _len)) == NULL) {	\
-			ACTION;						\
-		}							\
-		*_le = _PMCLOG_TO_HEADER(TYPE,_len);			\
-		_le += 3	/* skip over timestamp */
+			ACTION;											\
+		}													\
+		ph = (struct pmclog_header *)_le;					\
+		ph->pl_header =_PMCLOG_TO_HEADER(TYPE,_len);	\
+		ph->pl_tsc = (TSC);									\
+		_le += sizeof(*ph)/4	/* skip over timestamp */
 
 /* reserve LEN bytes of space and initialize the entry header */
 #define	_PMCLOG_RESERVE(PO,TYPE,LEN,ACTION) do {			\
 		uint32_t *_le;						\
-		int _len = roundup((LEN), sizeof(uint32_t));		\
+		int _len = roundup((LEN), sizeof(uint32_t));	\
+		uint64_t tsc;										\
+		struct pmclog_header *ph;							\
+		tsc = pmc_rdtsc();									\
 		spinlock_enter();									\
 		if ((_le = pmclog_reserve((PO), _len)) == NULL) {	\
 			spinlock_exit();								\
 			ACTION;											\
 		}												\
-		*_le = _PMCLOG_TO_HEADER(TYPE,_len);			\
-		_le += 3	/* skip over timestamp */
+		ph = (struct pmclog_header *)_le;					\
+		ph->pl_header =_PMCLOG_TO_HEADER(TYPE,_len);	\
+		ph->pl_tsc = tsc;									\
+		_le += sizeof(*ph)/4	/* skip over timestamp */
 
 
-#define	PMCLOG_RESERVE_SAFE(P,T,L)		_PMCLOG_RESERVE_SAFE(P,T,L,return)
+
+#define	PMCLOG_RESERVE_SAFE(P,T,L,TSC)		_PMCLOG_RESERVE_SAFE(P,T,L,return,TSC)
 #define	PMCLOG_RESERVE(P,T,L)		_PMCLOG_RESERVE(P,T,L,return)
 #define	PMCLOG_RESERVE_WITH_ERROR(P,T,L) _PMCLOG_RESERVE(P,T,L,		\
 	error=ENOMEM;goto error)
@@ -181,32 +194,32 @@ static struct mtx pmc_kthread_mtx;	/* sleep lock */
 		} while (0)
 
 
+#define TSDELTA 4
 /*
  * Assertions about the log file format.
  */
-
-CTASSERT(sizeof(struct pmclog_callchain) == 8*4 +
+CTASSERT(sizeof(struct pmclog_callchain) == 7*4 + TSDELTA +
     PMC_CALLCHAIN_DEPTH_MAX*sizeof(uintfptr_t));
-CTASSERT(sizeof(struct pmclog_closelog) == 4*4);
-CTASSERT(sizeof(struct pmclog_dropnotify) == 4*4);
-CTASSERT(sizeof(struct pmclog_map_in) == PATH_MAX +
-    4*4 + sizeof(uintfptr_t));
+CTASSERT(sizeof(struct pmclog_closelog) == 3*4 + TSDELTA);
+CTASSERT(sizeof(struct pmclog_dropnotify) == 3*4 + TSDELTA);
+CTASSERT(sizeof(struct pmclog_map_in) == PATH_MAX + TSDELTA +
+    5*4 + sizeof(uintfptr_t));
 CTASSERT(offsetof(struct pmclog_map_in,pl_pathname) ==
-    4*4 + sizeof(uintfptr_t));
-CTASSERT(sizeof(struct pmclog_map_out) == 4*4 + 2*sizeof(uintfptr_t));
-CTASSERT(sizeof(struct pmclog_pmcallocate) == 8*4);
-CTASSERT(sizeof(struct pmclog_pmcattach) == 6*4 + PATH_MAX);
-CTASSERT(offsetof(struct pmclog_pmcattach,pl_pathname) == 6*4);
-CTASSERT(sizeof(struct pmclog_pmcdetach) == 6*4);
-CTASSERT(sizeof(struct pmclog_proccsw) == 6*4 + 8);
-CTASSERT(sizeof(struct pmclog_procexec) == 6*4 + PATH_MAX +
+    5*4 + TSDELTA + sizeof(uintfptr_t));
+CTASSERT(sizeof(struct pmclog_map_out) == 5*4 + 2*sizeof(uintfptr_t) + TSDELTA);
+CTASSERT(sizeof(struct pmclog_pmcallocate) == 9*4 + TSDELTA);
+CTASSERT(sizeof(struct pmclog_pmcattach) == 5*4 + PATH_MAX + TSDELTA);
+CTASSERT(offsetof(struct pmclog_pmcattach,pl_pathname) == 5*4 + TSDELTA);
+CTASSERT(sizeof(struct pmclog_pmcdetach) == 5*4 + TSDELTA);
+CTASSERT(sizeof(struct pmclog_proccsw) == 7*4 + 8 + TSDELTA);
+CTASSERT(sizeof(struct pmclog_procexec) == 5*4 + PATH_MAX +
+    sizeof(uintfptr_t) + TSDELTA);
+CTASSERT(offsetof(struct pmclog_procexec,pl_pathname) == 5*4 + TSDELTA +
     sizeof(uintfptr_t));
-CTASSERT(offsetof(struct pmclog_procexec,pl_pathname) == 6*4 +
-    sizeof(uintfptr_t));
-CTASSERT(sizeof(struct pmclog_procexit) == 6*4 + 8);
-CTASSERT(sizeof(struct pmclog_procfork) == 6*4);
-CTASSERT(sizeof(struct pmclog_sysexit) == 4*4);
-CTASSERT(sizeof(struct pmclog_userdata) == 4*4);
+CTASSERT(sizeof(struct pmclog_procexit) == 5*4 + 8 + TSDELTA);
+CTASSERT(sizeof(struct pmclog_procfork) == 5*4 + TSDELTA);
+CTASSERT(sizeof(struct pmclog_sysexit) == 6*4);
+CTASSERT(sizeof(struct pmclog_userdata) == 6*4);
 
 /*
  * Log buffer structure
@@ -545,8 +558,6 @@ static uint32_t *
 pmclog_reserve(struct pmc_owner *po, int length)
 {
 	uintptr_t newptr, oldptr;
-	uint32_t *lh;
-	struct timespec ts;
 	struct pmclog_buffer *plb, **pplb;
 
 	PMCDBG2(LOG,ALL,1, "po=%p len=%d", po, length);
@@ -612,11 +623,6 @@ pmclog_reserve(struct pmc_owner *po, int length)
 	oldptr = (uintptr_t) plb->plb_ptr;
 
  done:
-	lh = (uint32_t *) oldptr;
-	lh++;				/* skip header */
-	getnanotime(&ts);		/* fill in the timestamp */
-	*lh++ = ts.tv_sec & 0xFFFFFFFF;
-	*lh++ = ts.tv_nsec & 0xFFFFFFF;
 	return ((uint32_t *) oldptr);
  fail:
 	return (NULL);
@@ -693,6 +699,8 @@ int
 pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
 {
 	struct proc *p;
+	struct timespec ts;
+	uint64_t tsc;
 	int error;
 
 	sx_assert(&pmc_sx, SA_XLOCKED);
@@ -720,12 +728,21 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_o
 	PROC_LOCK(p);
 	p->p_flag |= P_HWPMC;
 	PROC_UNLOCK(p);
-
+	nanotime(&ts);
+	tsc = pmc_rdtsc();
 	/* create a log initialization entry */
 	PMCLOG_RESERVE_WITH_ERROR(po, INITIALIZE,
 	    sizeof(struct pmclog_initialize));
 	PMCLOG_EMIT32(PMC_VERSION);
 	PMCLOG_EMIT32(md->pmd_cputype);
+#if defined(__i386__) || defined(__amd64__)
+	PMCLOG_EMIT64(tsc_freq);
+#else
+	/* other architectures will need to fill this in */
+	PMCLOG_EMIT64(0);
+#endif
+	memcpy(_le, &ts, sizeof(ts));
+	_le += sizeof(ts)/4;
 	PMCLOG_EMITSTRING(pmc_cpuid, PMC_CPUID_LEN);
 	PMCLOG_DESPATCH_SYNC(po);
 
@@ -917,13 +934,11 @@ pmclog_process_callchain(struct pmc *pm, struct pmc_sa
 	    ps->ps_nsamples * sizeof(uintfptr_t);
 	po = pm->pm_owner;
 	flags = PMC_CALLCHAIN_TO_CPUFLAGS(ps->ps_cpu,ps->ps_flags);
-	PMCLOG_RESERVE_SAFE(po, CALLCHAIN, recordlen);
+	PMCLOG_RESERVE_SAFE(po, CALLCHAIN, recordlen, ps->ps_tsc);
 	PMCLOG_EMIT32(ps->ps_pid);
 	PMCLOG_EMIT32(ps->ps_tid);
 	PMCLOG_EMIT32(pm->pm_id);
 	PMCLOG_EMIT32(flags);
-	/* unused for now */
-	PMCLOG_EMIT32(0);
 	for (n = 0; n < ps->ps_nsamples; n++)
 		PMCLOG_EMITADDR(ps->ps_pc[n]);
 	PMCLOG_DESPATCH_SAFE(po);
@@ -957,6 +972,7 @@ pmclog_process_map_in(struct pmc_owner *po, pid_t pid,
 
 	PMCLOG_RESERVE(po, MAP_IN, recordlen);
 	PMCLOG_EMIT32(pid);
+	PMCLOG_EMIT32(0);
 	PMCLOG_EMITADDR(start);
 	PMCLOG_EMITSTRING(path,pathlen);
 	PMCLOG_DESPATCH_SYNC(po);
@@ -970,6 +986,7 @@ pmclog_process_map_out(struct pmc_owner *po, pid_t pid
 
 	PMCLOG_RESERVE(po, MAP_OUT, sizeof(struct pmclog_map_out));
 	PMCLOG_EMIT32(pid);
+	PMCLOG_EMIT32(0);
 	PMCLOG_EMITADDR(start);
 	PMCLOG_EMITADDR(end);
 	PMCLOG_DESPATCH(po);
@@ -991,6 +1008,7 @@ pmclog_process_pmcallocate(struct pmc *pm)
 		PMCLOG_EMIT32(pm->pm_id);
 		PMCLOG_EMIT32(pm->pm_event);
 		PMCLOG_EMIT32(pm->pm_flags);
+		PMCLOG_EMIT32(0);
 		PMCLOG_EMIT64(pm->pm_sc.pm_reloadcount);
 		ps = pmc_soft_ev_acquire(pm->pm_event);
 		if (ps != NULL)
@@ -1005,6 +1023,7 @@ pmclog_process_pmcallocate(struct pmc *pm)
 		PMCLOG_EMIT32(pm->pm_id);
 		PMCLOG_EMIT32(pm->pm_event);
 		PMCLOG_EMIT32(pm->pm_flags);
+		PMCLOG_EMIT32(0);
 		PMCLOG_EMIT64(pm->pm_sc.pm_reloadcount);
 		PMCLOG_DESPATCH_SYNC(po);
 	}
@@ -1026,7 +1045,6 @@ pmclog_process_pmcattach(struct pmc *pm, pid_t pid, ch
 	PMCLOG_RESERVE(po, PMCATTACH, recordlen);
 	PMCLOG_EMIT32(pm->pm_id);
 	PMCLOG_EMIT32(pid);
-	PMCLOG_EMIT32(0);
 	PMCLOG_EMITSTRING(path, pathlen);
 	PMCLOG_DESPATCH_SYNC(po);
 }
@@ -1053,14 +1071,12 @@ pmclog_process_proccreate(struct pmc_owner *po, struct
 		PMCLOG_RESERVE(po, PROC_CREATE, sizeof(struct pmclog_proccreate));
 		PMCLOG_EMIT32(p->p_pid);
 		PMCLOG_EMIT32(p->p_flag);
-		PMCLOG_EMIT32(0);
 		PMCLOG_EMITSTRING(p->p_comm, MAXCOMLEN+1);
 		PMCLOG_DESPATCH_SYNC(po);
 	} else {
 		PMCLOG_RESERVE(po, PROC_CREATE, sizeof(struct pmclog_proccreate));
 		PMCLOG_EMIT32(p->p_pid);
 		PMCLOG_EMIT32(p->p_flag);
-		PMCLOG_EMIT32(0);
 		PMCLOG_EMITSTRING(p->p_comm, MAXCOMLEN+1);
 		PMCLOG_DESPATCH(po);
 	}
@@ -1083,11 +1099,12 @@ pmclog_process_proccsw(struct pmc *pm, struct pmc_proc
 
 	po = pm->pm_owner;
 
-	PMCLOG_RESERVE_SAFE(po, PROCCSW, sizeof(struct pmclog_proccsw));
-	PMCLOG_EMIT32(pm->pm_id);
+	PMCLOG_RESERVE_SAFE(po, PROCCSW, sizeof(struct pmclog_proccsw), pmc_rdtsc());
 	PMCLOG_EMIT64(v);
+	PMCLOG_EMIT32(pm->pm_id);
 	PMCLOG_EMIT32(pp->pp_proc->p_pid);
 	PMCLOG_EMIT32(td->td_tid);
+	PMCLOG_EMIT32(0);
 	PMCLOG_DESPATCH_SCHED_LOCK(po);
 }
 
@@ -1104,7 +1121,6 @@ pmclog_process_procexec(struct pmc_owner *po, pmc_id_t
 	PMCLOG_RESERVE(po, PROCEXEC, recordlen);
 	PMCLOG_EMIT32(pid);
 	PMCLOG_EMIT32(pmid);
-	PMCLOG_EMIT32(0);
 	PMCLOG_EMITADDR(startaddr);
 	PMCLOG_EMITSTRING(path,pathlen);
 	PMCLOG_DESPATCH_SYNC(po);
@@ -1129,7 +1145,6 @@ pmclog_process_procexit(struct pmc *pm, struct pmc_pro
 	PMCLOG_RESERVE(po, PROCEXIT, sizeof(struct pmclog_procexit));
 	PMCLOG_EMIT32(pm->pm_id);
 	PMCLOG_EMIT32(pp->pp_proc->p_pid);
-	PMCLOG_EMIT32(0);
 	PMCLOG_EMIT64(pp->pp_pmcs[ri].pp_pmcval);
 	PMCLOG_DESPATCH(po);
 }
@@ -1170,6 +1185,7 @@ pmclog_process_threadcreate(struct pmc_owner *po, stru
 		PMCLOG_EMIT32(td->td_tid);
 		PMCLOG_EMIT32(p->p_pid);
 		PMCLOG_EMIT32(p->p_flag);
+		PMCLOG_EMIT32(0);
 		PMCLOG_EMITSTRING(td->td_name, MAXCOMLEN+1);
 		PMCLOG_DESPATCH_SYNC(po);
 	} else {
@@ -1177,6 +1193,7 @@ pmclog_process_threadcreate(struct pmc_owner *po, stru
 		PMCLOG_EMIT32(td->td_tid);
 		PMCLOG_EMIT32(p->p_pid);
 		PMCLOG_EMIT32(p->p_flag);
+		PMCLOG_EMIT32(0);
 		PMCLOG_EMITSTRING(td->td_name, MAXCOMLEN+1);
 		PMCLOG_DESPATCH(po);
 	}

Modified: head/sys/dev/hwpmc/hwpmc_mod.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_mod.c	Thu Jun  7 00:55:17 2018	(r334748)
+++ head/sys/dev/hwpmc/hwpmc_mod.c	Thu Jun  7 02:03:22 2018	(r334749)
@@ -809,6 +809,19 @@ pmc_force_context_switch(void)
 	pause("pmcctx", 1);
 }
 
+uint64_t
+pmc_rdtsc(void)
+{
+#if defined(__i386__) || defined(__amd64__)
+	if (__predict_true(amd_feature & AMDID_RDTSCP))
+		return rdtscp();
+	else
+		return rdtsc();
+#else
+	return get_cyclecount();
+#endif
+}
+
 /*
  * Get the file name for an executable.  This is a simple wrapper
  * around vn_fullpath(9).
@@ -4676,6 +4689,8 @@ pmc_add_sample(int cpu, int ring, struct pmc *pm, stru
 	ps->ps_td = td;
 	ps->ps_pid = td->td_proc->p_pid;
 	ps->ps_tid = td->td_tid;
+	ps->ps_tsc = pmc_rdtsc();
+
 	ps->ps_cpu = cpu;
 	ps->ps_flags = inuserspace ? PMC_CC_F_USERSPACE : 0;
 

Modified: head/sys/sys/pmc.h
==============================================================================
--- head/sys/sys/pmc.h	Thu Jun  7 00:55:17 2018	(r334748)
+++ head/sys/sys/pmc.h	Thu Jun  7 02:03:22 2018	(r334749)
@@ -61,7 +61,7 @@
  *
  * The patch version is incremented for every bug fix.
  */
-#define	PMC_VERSION_MAJOR	0x07
+#define	PMC_VERSION_MAJOR	0x08
 #define	PMC_VERSION_MINOR	0x03
 #define	PMC_VERSION_PATCH	0x0000
 
@@ -939,6 +939,7 @@ struct pmc_sample {
 	struct thread		*ps_td;		/* which thread */
 	struct pmc		*ps_pmc;	/* interrupting PMC */
 	uintptr_t		*ps_pc;		/* (const) callchain start */
+	uint64_t		ps_tsc;		/* tsc value */
 };
 
 #define 	PMC_SAMPLE_FREE		((uint16_t) 0)
@@ -1217,5 +1218,6 @@ int	pmc_save_user_callchain(uintptr_t *_cc, int _maxsa
 struct pmc_mdep *pmc_mdep_alloc(int nclasses);
 void pmc_mdep_free(struct pmc_mdep *md);
 void pmc_flush_samples(int cpu);
+uint64_t pmc_rdtsc(void);
 #endif /* _KERNEL */
 #endif /* _SYS_PMC_H_ */

Modified: head/sys/sys/pmclog.h
==============================================================================
--- head/sys/sys/pmclog.h	Thu Jun  7 00:55:17 2018	(r334748)
+++ head/sys/sys/pmclog.h	Thu Jun  7 02:03:22 2018	(r334749)
@@ -42,7 +42,7 @@ enum pmclog_type {
 	PMCLOG_TYPE_CLOSELOG = 1,
 	PMCLOG_TYPE_DROPNOTIFY = 2,
 	PMCLOG_TYPE_INITIALIZE = 3,
-	PMCLOG_TYPE_MAPPINGCHANGE = 4, /* unused in v1 */
+
 	PMCLOG_TYPE_PMCALLOCATE = 5,
 	PMCLOG_TYPE_PMCATTACH = 6,
 	PMCLOG_TYPE_PMCDETACH = 7,
@@ -94,10 +94,13 @@ enum pmclog_type {
  */
 
 #define	PMCLOG_ENTRY_HEADER				\
-	uint32_t		pl_header;		\
-	uint32_t		pl_ts_sec;		\
-	uint32_t		pl_ts_nsec;
+	uint32_t		pl_header;			\
+	uint32_t		pl_spare;			\
+	uint64_t		pl_tsc;			\
 
+struct pmclog_header {
+	PMCLOG_ENTRY_HEADER;
+};
 
 /*
  * The following structures are used to describe the size of each kind
@@ -115,7 +118,6 @@ struct pmclog_callchain {
 	uint32_t		pl_tid;
 	uint32_t		pl_pmcid;
 	uint32_t		pl_cpuflags;
-	uint32_t		pl_cpuflags2;
 	/* 8 byte aligned */
 	uintptr_t		pl_pc[PMC_CALLCHAIN_DEPTH_MAX];
 } __packed;
@@ -127,25 +129,25 @@ struct pmclog_callchain {
 
 struct pmclog_closelog {
 	PMCLOG_ENTRY_HEADER
-	uint32_t		pl_pad;
 };
 
 struct pmclog_dropnotify {
 	PMCLOG_ENTRY_HEADER
-	uint32_t		pl_pad;
 };
 
 struct pmclog_initialize {
 	PMCLOG_ENTRY_HEADER
 	uint32_t		pl_version;	/* driver version */
 	uint32_t		pl_cpu;		/* enum pmc_cputype */
-	uint32_t		pl_pad;
+	uint64_t		pl_tsc_freq;
+	struct timespec	pl_ts;
 	char			pl_cpuid[PMC_CPUID_LEN];
 } __packed;
 
 struct pmclog_map_in {
 	PMCLOG_ENTRY_HEADER
 	uint32_t		pl_pid;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list