Module Name:    src
Committed By:   snj
Date:           Tue Aug  1 23:18:31 UTC 2017

Modified Files:
        src/distrib/sets/lists/base [netbsd-8]: md.amd64
        src/distrib/sets/lists/debug [netbsd-8]: md.amd64
        src/sys/arch/amd64/conf [netbsd-8]: GENERIC files.amd64
        src/sys/arch/i386/conf [netbsd-8]: GENERIC files.i386
        src/sys/arch/i386/i386 [netbsd-8]: i386_trap.S
        src/sys/arch/i386/include [netbsd-8]: frameasm.h
        src/sys/arch/x86/include [netbsd-8]: sysarch.h
        src/sys/arch/x86/x86 [netbsd-8]: pmc.c sys_machdep.c
        src/sys/arch/xen/conf [netbsd-8]: files.compat
        src/sys/secmodel/suser [netbsd-8]: secmodel_suser.c
        src/sys/sys [netbsd-8]: kauth.h
        src/usr.bin/pmc [netbsd-8]: Makefile pmc.1 pmc.c

Log Message:
Pull up following revision(s) (requested by maxv in ticket #164):
        distrib/sets/lists/base/md.amd64: revision 1.269
        distrib/sets/lists/debug/md.amd64: revision 1.97
        sys/arch/amd64/conf/GENERIC: revision 1.460
        sys/arch/amd64/conf/files.amd64: revision 1.89
        sys/arch/i386/conf/GENERIC: revision 1.1157
        sys/arch/i386/conf/files.i386: revision 1.379
        sys/arch/i386/i386/i386_trap.S: revision 1.7-1.8
        sys/arch/i386/include/frameasm.h: revision 1.16
        sys/arch/x86/include/sysarch.h: revision 1.12
        sys/arch/x86/x86/pmc.c: revision 1.8-1.10
        sys/arch/x86/x86/sys_machdep.c: revision 1.36
        sys/arch/xen/conf/files.compat: revision 1.26
        sys/secmodel/suser/secmodel_suser.c: revision 1.43
        sys/sys/kauth.h: revision 1.74
        usr.bin/pmc/Makefile: revision 1.5
        usr.bin/pmc/pmc.1: revision 1.12-1.13
        usr.bin/pmc/pmc.c: revision 1.24-1.25
style
--
style
--
Disable interrupts for T_NMI (inline calltrap). Note that there's still a
way to evade the NMI mode here, if a segment register faults in
INTRFASTEXIT; but we don't care. I didn't test this change, but it seems
fine enough.
--
Make the PMC syscalls privileged.
--
Check argc, and add a message.
--
include opt_pmc.h
--
Build the pmc tool on amd64.
--
Properly handle overflows, and take them into account in userland.
--
Update.
--
Enable PMCs by default.
--
Sort sections. Fix macro usage.


To generate a diff of this commit:
cvs rdiff -u -r1.268 -r1.268.4.1 src/distrib/sets/lists/base/md.amd64
cvs rdiff -u -r1.96 -r1.96.2.1 src/distrib/sets/lists/debug/md.amd64
cvs rdiff -u -r1.459.2.1 -r1.459.2.2 src/sys/arch/amd64/conf/GENERIC
cvs rdiff -u -r1.88 -r1.88.8.1 src/sys/arch/amd64/conf/files.amd64
cvs rdiff -u -r1.1156.2.1 -r1.1156.2.2 src/sys/arch/i386/conf/GENERIC
cvs rdiff -u -r1.378 -r1.378.6.1 src/sys/arch/i386/conf/files.i386
cvs rdiff -u -r1.6 -r1.6.6.1 src/sys/arch/i386/i386/i386_trap.S
cvs rdiff -u -r1.15 -r1.15.46.1 src/sys/arch/i386/include/frameasm.h
cvs rdiff -u -r1.11 -r1.11.6.1 src/sys/arch/x86/include/sysarch.h
cvs rdiff -u -r1.7 -r1.7.2.1 src/sys/arch/x86/x86/pmc.c
cvs rdiff -u -r1.35 -r1.35.6.1 src/sys/arch/x86/x86/sys_machdep.c
cvs rdiff -u -r1.25 -r1.25.8.1 src/sys/arch/xen/conf/files.compat
cvs rdiff -u -r1.42 -r1.42.10.1 src/sys/secmodel/suser/secmodel_suser.c
cvs rdiff -u -r1.73 -r1.73.10.1 src/sys/sys/kauth.h
cvs rdiff -u -r1.4 -r1.4.4.1 src/usr.bin/pmc/Makefile
cvs rdiff -u -r1.11 -r1.11.4.1 src/usr.bin/pmc/pmc.1
cvs rdiff -u -r1.23 -r1.23.4.1 src/usr.bin/pmc/pmc.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/base/md.amd64
diff -u src/distrib/sets/lists/base/md.amd64:1.268 src/distrib/sets/lists/base/md.amd64:1.268.4.1
--- src/distrib/sets/lists/base/md.amd64:1.268	Tue Jan 24 11:09:14 2017
+++ src/distrib/sets/lists/base/md.amd64	Tue Aug  1 23:18:30 2017
@@ -1,9 +1,10 @@
-# $NetBSD: md.amd64,v 1.268 2017/01/24 11:09:14 nonaka Exp $
+# $NetBSD: md.amd64,v 1.268.4.1 2017/08/01 23:18:30 snj Exp $
 ./dev/lms0					base-obsolete		obsolete
 ./dev/mms0					base-obsolete		obsolete
 ./libexec/ld.elf_so-i386			base-sys-shlib		compat,pic
 ./usr/bin/fdformat				base-util-bin
 ./usr/bin/iasl					base-util-bin
+./usr/bin/pmc					base-util-bin
 ./usr/lib/i386/libi386.so.1			base-compat-shlib	compat,pic
 ./usr/lib/i386/libi386.so.1.0			base-compat-shlib	compat,pic
 ./usr/lib/i386/libproc.so.0			base-compat-shlib	compat,pic,dtrace

Index: src/distrib/sets/lists/debug/md.amd64
diff -u src/distrib/sets/lists/debug/md.amd64:1.96 src/distrib/sets/lists/debug/md.amd64:1.96.2.1
--- src/distrib/sets/lists/debug/md.amd64:1.96	Sun May  7 02:05:56 2017
+++ src/distrib/sets/lists/debug/md.amd64	Tue Aug  1 23:18:30 2017
@@ -1,4 +1,4 @@
-# $NetBSD: md.amd64,v 1.96 2017/05/07 02:05:56 kamil Exp $
+# $NetBSD: md.amd64,v 1.96.2.1 2017/08/01 23:18:30 snj Exp $
 ./usr/lib/i386/12.202++_g.a			comp-c-debuglib		debuglib,compat,12.202xx
 ./usr/lib/i386/libi386_g.a			comp-c-debuglib		debuglib,compat
 ./usr/lib/i386/libiberty_g.a			comp-obsolete		obsolete
@@ -6,6 +6,7 @@
 ./usr/libdata/debug/libexec/ld.elf_so-i386.debug	comp-sys-debug		debug,compat
 ./usr/libdata/debug/usr/bin/fdformat.debug	comp-util-debug		debug
 ./usr/libdata/debug/usr/bin/iasl.debug		comp-util-debug		debug
+./usr/libdata/debug/usr/bin/pmc.debug		comp-util-debug		debug
 ./usr/libdata/debug/usr/lib/i386/libi386.so.1.0.debug	comp-compat-shlib	compat,pic,debug
 ./usr/libdata/debug/usr/lib/i386/libpam.so.4.1.debug	comp-compat-shlib	compat,pic,debug,pam
 ./usr/libdata/debug/usr/lib/i386/libproc.so.0.0.debug	comp-compat-shlib	compat,pic,debug,dtrace

Index: src/sys/arch/amd64/conf/GENERIC
diff -u src/sys/arch/amd64/conf/GENERIC:1.459.2.1 src/sys/arch/amd64/conf/GENERIC:1.459.2.2
--- src/sys/arch/amd64/conf/GENERIC:1.459.2.1	Wed Jul  5 13:58:48 2017
+++ src/sys/arch/amd64/conf/GENERIC	Tue Aug  1 23:18:30 2017
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.459.2.1 2017/07/05 13:58:48 martin Exp $
+# $NetBSD: GENERIC,v 1.459.2.2 2017/08/01 23:18:30 snj Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@ include 	"arch/amd64/conf/std.amd64"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"GENERIC-$Revision: 1.459.2.1 $"
+#ident		"GENERIC-$Revision: 1.459.2.2 $"
 
 maxusers	64		# estimated number of users
 
@@ -81,7 +81,7 @@ est0		at cpu0		# Intel Enhanced SpeedSte
 powernow0	at cpu0		# AMD PowerNow! and Cool'n'Quiet (non-ACPI)
 vmt0		at cpu0		# VMware Tools
 
-#options 	PMC		# performance-monitoring counters support
+options 	PMC		# performance-monitoring counters support
 
 # Alternate buffer queue strategies for better responsiveness under high
 # disk I/O load.

Index: src/sys/arch/amd64/conf/files.amd64
diff -u src/sys/arch/amd64/conf/files.amd64:1.88 src/sys/arch/amd64/conf/files.amd64:1.88.8.1
--- src/sys/arch/amd64/conf/files.amd64:1.88	Thu Dec 15 12:04:17 2016
+++ src/sys/arch/amd64/conf/files.amd64	Tue Aug  1 23:18:30 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: files.amd64,v 1.88 2016/12/15 12:04:17 kamil Exp $
+#	$NetBSD: files.amd64,v 1.88.8.1 2017/08/01 23:18:30 snj Exp $
 #
 # new style config file for amd64 architecture
 #
@@ -24,6 +24,7 @@ defparam opt_physmem.h	PHYSMEM_MAX_ADDR 
 # with the i386 (they include the opt_*.h for these)
 #
 
+defflag			PMC
 defflag			USER_LDT
 defflag eisa.h EISA
 

Index: src/sys/arch/i386/conf/GENERIC
diff -u src/sys/arch/i386/conf/GENERIC:1.1156.2.1 src/sys/arch/i386/conf/GENERIC:1.1156.2.2
--- src/sys/arch/i386/conf/GENERIC:1.1156.2.1	Wed Jul  5 13:58:48 2017
+++ src/sys/arch/i386/conf/GENERIC	Tue Aug  1 23:18:30 2017
@@ -1,4 +1,4 @@
-# $NetBSD: GENERIC,v 1.1156.2.1 2017/07/05 13:58:48 martin Exp $
+# $NetBSD: GENERIC,v 1.1156.2.2 2017/08/01 23:18:30 snj Exp $
 #
 # GENERIC machine description file
 #
@@ -22,7 +22,7 @@ include 	"arch/i386/conf/std.i386"
 
 options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident		"GENERIC-$Revision: 1.1156.2.1 $"
+#ident		"GENERIC-$Revision: 1.1156.2.2 $"
 
 maxusers	64		# estimated number of users
 
@@ -42,7 +42,7 @@ viac7temp*	at cpu?		# VIA C7 temperature
 vmt0		at cpu0		# VMware Tools
 
 options 	MTRR		# memory-type range register syscall support
-#options 	PMC		# performance-monitoring counters support
+options 	PMC		# performance-monitoring counters support
 
 options 	MULTIBOOT	# Multiboot support (see multiboot(8))
 

Index: src/sys/arch/i386/conf/files.i386
diff -u src/sys/arch/i386/conf/files.i386:1.378 src/sys/arch/i386/conf/files.i386:1.378.6.1
--- src/sys/arch/i386/conf/files.i386:1.378	Fri Mar 10 14:40:56 2017
+++ src/sys/arch/i386/conf/files.i386	Tue Aug  1 23:18:30 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: files.i386,v 1.378 2017/03/10 14:40:56 maxv Exp $
+#	$NetBSD: files.i386,v 1.378.6.1 2017/08/01 23:18:30 snj Exp $
 #
 # new style config file for i386 architecture
 #
@@ -21,6 +21,8 @@ obsolete defflag	XBOX
 # VM86 emulation
 defflag			VM86
 
+defflag			PMC
+
 # User-settable LDT (used by WINE)
 defflag			USER_LDT
 

Index: src/sys/arch/i386/i386/i386_trap.S
diff -u src/sys/arch/i386/i386/i386_trap.S:1.6 src/sys/arch/i386/i386/i386_trap.S:1.6.6.1
--- src/sys/arch/i386/i386/i386_trap.S:1.6	Mon Feb 27 06:46:59 2017
+++ src/sys/arch/i386/i386/i386_trap.S	Tue Aug  1 23:18:30 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: i386_trap.S,v 1.6 2017/02/27 06:46:59 chs Exp $	*/
+/*	$NetBSD: i386_trap.S,v 1.6.6.1 2017/08/01 23:18:30 snj Exp $	*/
 
 /*
  * Copyright 2002 (c) Wasabi Systems, Inc.
@@ -35,7 +35,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-/*-
+/*
  * Copyright (c) 1998, 2007, 2009 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
@@ -66,7 +66,7 @@
 
 #if 0
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: i386_trap.S,v 1.6 2017/02/27 06:46:59 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i386_trap.S,v 1.6.6.1 2017/08/01 23:18:30 snj Exp $");
 #endif
 
 /*
@@ -78,10 +78,10 @@ __KERNEL_RCSID(0, "$NetBSD: i386_trap.S,
  * (possibly the next clock tick).  Thus, we disable interrupt before checking,
  * and only enable them again on the final `iret' or before calling the AST
  * handler.
- */ 
+ */
 
-#define TRAP(a)			pushl $(a) ; jmp _C_LABEL(alltraps)
-#define ZTRAP(a)		pushl $0 ; TRAP(a)
+#define TRAP(a)		pushl $(a) ; jmp _C_LABEL(alltraps)
+#define ZTRAP(a)	pushl $0 ; TRAP(a)
 
 #ifdef IPKDB
 #define BPTTRAP(a)	pushl $0; pushl $(a); jmp _C_LABEL(bpttraps)
@@ -89,29 +89,49 @@ __KERNEL_RCSID(0, "$NetBSD: i386_trap.S,
 #define BPTTRAP(a)	ZTRAP(a)
 #endif
 
-
 	.text
 IDTVEC(trap00)
 	ZTRAP(T_DIVIDE)
 IDTVEC_END(trap00)
+
 IDTVEC(trap01)
 	BPTTRAP(T_TRCTRAP)
 IDTVEC_END(trap01)
+
+/*
+ * Non Maskable Interrupts are a special case: they can be triggered even
+ * with interrupts disabled, and once triggered they block further NMIs
+ * until an 'iret' instruction is executed.
+ *
+ * Therefore we don't enable interrupts, because the CPU could switch to
+ * another LWP, call 'iret' and unintentionally leave the NMI mode.
+ */
 IDTVEC(trap02)
-	pushl $0
-	pushl $(T_NMI)
+	pushl	$0
+	pushl	$(T_NMI)
 	INTRENTRY
-	jmp _C_LABEL(calltrap)
+
+	addl	$1,CPUVAR(NTRAP)	/* statistical info */
+	adcl	$0,CPUVAR(NTRAP)+4
+	pushl	%esp
+	call	_C_LABEL(trap)
+	addl	$4,%esp
+
+	INTRFASTEXIT
 IDTVEC_END(trap02)
+
 IDTVEC(trap03)
 	BPTTRAP(T_BPTFLT)
 IDTVEC_END(trap03)
+
 IDTVEC(trap04)
 	ZTRAP(T_OFLOW)
 IDTVEC_END(trap04)
+
 IDTVEC(trap05)
 	ZTRAP(T_BOUND)
 IDTVEC_END(trap05)
+
 /*
  * Privileged instruction fault.
  */
@@ -124,21 +144,21 @@ IDTVEC(trap06)
 
 	/* Check if this is a user fault. */
 	/* XXX this was 0x0020 in FreeBSD */
-	cmpl	$GSEL(GCODE_SEL, SEL_KPL), 4(%esp)   /* Check code segment. */
+	cmpl	$GSEL(GCODE_SEL, SEL_KPL),4(%esp) /* Check code segment. */
 
 	/* If so, just handle it as a normal trap. */
 	jne	norm_ill
-              
+
 	/*
 	 * This is a kernel instruction fault that might have been caused
 	 * by a DTrace provider.
 	 */
-	
+
 	/*
 	 * Set our jump address for the jump back in the event that
 	 * the exception wasn't caused by DTrace at all.
 	 */
-	movl	$norm_ill, dtrace_invop_calltrap_addr
+	movl	$norm_ill,dtrace_invop_calltrap_addr
 
 	/* Jump to the code hooked in by DTrace. */
 	jmpl	*dtrace_invop_jump_addr
@@ -154,8 +174,9 @@ IDTVEC(trap06)
 	ZTRAP(T_PRIVINFLT)
 IDTVEC_END(trap06)
 #endif
+
 IDTVEC(trap07)
-	pushl	$0			# dummy error code
+	pushl	$0			/* dummy error code */
 	pushl	$T_DNA
 	INTRENTRY
 #ifdef DIAGNOSTIC
@@ -166,24 +187,31 @@ IDTVEC(trap07)
 	addl	$4,%esp
 	jmp	_C_LABEL(trapreturn)
 IDTVEC_END(trap07)
+
 IDTVEC(trap08)
 	TRAP(T_DOUBLEFLT)
 IDTVEC_END(trap08)
+
 IDTVEC(trap09)
 	ZTRAP(T_FPOPFLT)
 IDTVEC_END(trap09)
+
 IDTVEC(trap0a)
 	TRAP(T_TSSFLT)
 IDTVEC_END(trap0a)
+
 IDTVEC(trap0b)
 	TRAP(T_SEGNPFLT)
 IDTVEC_END(trap0b)
+
 IDTVEC(trap0c)
 	TRAP(T_STKFLT)
 IDTVEC_END(trap0c)
+
 IDTVEC(trap0d)
 	TRAP(T_PROTFLT)
 IDTVEC_END(trap0d)
+
 IDTVEC(trap0e)
 #ifndef XEN
 	pushl	$T_PAGEFLT
@@ -197,9 +225,9 @@ IDTVEC(trap0e)
 	jne	calltrap
 	movb	$T_PRIVINFLT,TF_TRAPNO(%esp)
 	jmp	calltrap
-#else /* !XEN */
+#else
 	TRAP(T_PAGEFLT)
-#endif /* !XEN */
+#endif
 IDTVEC_END(trap0e)
 
 IDTVEC(intrspurious)
@@ -208,11 +236,11 @@ IDTVEC(trap0f)
 	 * The Pentium Pro local APIC may erroneously call this vector for a
 	 * default IR7.  Just ignore it.
 	 *
-	 * (The local APIC does this when CPL is raised while it's on the 
-	 * way to delivering an interrupt.. presumably enough has been set 
+	 * (The local APIC does this when CPL is raised while it's on the
+	 * way to delivering an interrupt.. presumably enough has been set
 	 * up that it's inconvenient to abort delivery completely..)
 	 */
-	pushl	$0			# dummy error code
+	pushl	$0			/* dummy error code */
 	pushl	$T_ASTFLT
 	INTRENTRY
 	STI(%eax)
@@ -229,18 +257,19 @@ IDTVEC(trap10)
 	 * error.  It would be better to handle npx interrupts as traps but
 	 * this is difficult for nested interrupts.
 	 */
-	pushl	$0			# dummy error code
+	pushl	$0			/* dummy error code */
 	pushl	$T_ARITHTRAP
 .Ldo_fputrap:
 	INTRENTRY
 	movl	CPUVAR(ILEVEL),%ebx
 	pushl	%esp
-	addl	$1,CPUVAR(NTRAP)	# statistical info
+	addl	$1,CPUVAR(NTRAP)	/* statistical info */
 	adcl	$0,CPUVAR(NTRAP)+4
 	call	_C_LABEL(fputrap)
 	addl	$4,%esp
 	jmp	_C_LABEL(trapreturn)
 IDTVEC_END(trap10)
+
 IDTVEC(trap11)
 	TRAP(T_ALIGNFLT)
 IDTVEC_END(trap11)
@@ -248,8 +277,9 @@ IDTVEC_END(trap11)
 IDTVEC(trap12)
 	ZTRAP(T_MCA)
 IDTVEC_END(trap12)
+
 IDTVEC(trap13)
-	pushl	$0			# dummy error code
+	pushl	$0			/* dummy error code */
 	pushl	$T_XMM
 	jmp	.Ldo_fputrap
 IDTVEC_END(trap13)
@@ -308,7 +338,7 @@ IDTVEC(exceptions)
 	.long	_C_LABEL(Xtrap1e), _C_LABEL(Xtrap1f)
 IDTVEC_END(exceptions)
 
- 
+
 IDTVEC(tss_trap08)
 1:
 	str	%ax
@@ -331,7 +361,7 @@ IDTVEC_END(tss_trap08)
  * Typically the code will have raised a SIGSEGV which will be actioned
  * by the code below.
  */
-	.type	_C_LABEL(trap_return_fault_return), @function
+	.type	_C_LABEL(trap_return_fault_return),@function
 LABEL(trap_return_fault_return)
 	mov	4(%esp),%esp	/* frame for user return */
 	jmp	_C_LABEL(trapreturn)
@@ -344,8 +374,8 @@ NENTRY(alltraps)
 calltrap:
 #ifdef DIAGNOSTIC
 	movl	CPUVAR(ILEVEL),%ebx
-#endif /* DIAGNOSTIC */
-	addl	$1,CPUVAR(NTRAP)	# statistical info
+#endif
+	addl	$1,CPUVAR(NTRAP)	/* statistical info */
 	adcl	$0,CPUVAR(NTRAP)+4
 	pushl	%esp
 	call	_C_LABEL(trap)
@@ -367,7 +397,7 @@ _C_LABEL(trapreturn):	.globl	trapreturn
 5:	CLEAR_ASTPENDING(%eax)
 	STI(%eax)
 	movl	$T_ASTFLT,TF_TRAPNO(%esp)
-	addl	$1,CPUVAR(NTRAP)	# statistical info
+	addl	$1,CPUVAR(NTRAP)	/* statistical info */
 	adcl	$0,CPUVAR(NTRAP)+4
 	pushl	%esp
 	call	_C_LABEL(trap)
@@ -377,25 +407,25 @@ _C_LABEL(trapreturn):	.globl	trapreturn
 	jnz	9f
 #ifdef XEN
 	STIC(%eax)
-	jz      6f
-	call    _C_LABEL(stipending)
-	testl   %eax,%eax
-	jz      6f
+	jz	6f
+	call	_C_LABEL(stipending)
+	testl	%eax,%eax
+	jz	6f
 	/* process pending interrupts */
 	CLI(%eax)
-	movl    CPUVAR(ILEVEL), %ebx
-	movl    $.Lalltraps_resume, %esi # address to resume loop at
+	movl	CPUVAR(ILEVEL),%ebx
+	movl	$.Lalltraps_resume,%esi /* address to resume loop at */
 .Lalltraps_resume:
-	movl    %ebx,%eax               # get cpl
-	movl    CPUVAR(IUNMASK)(,%eax,4),%eax
-	andl    CPUVAR(IPENDING),%eax   # any non-masked bits left?
+	movl	%ebx,%eax		/* get cpl */
+	movl	CPUVAR(IUNMASK)(,%eax,4),%eax
+	andl	CPUVAR(IPENDING),%eax	/* any non-masked bits left? */
 	jz	7f
-	bsrl    %eax,%eax
-	btrl    %eax,CPUVAR(IPENDING)
-	movl    CPUVAR(ISOURCES)(,%eax,4),%eax
-	jmp     *IS_RESUME(%eax)
-7:      movl    %ebx, CPUVAR(ILEVEL) #restore cpl
-	jmp     _C_LABEL(trapreturn)
+	bsrl	%eax,%eax
+	btrl	%eax,CPUVAR(IPENDING)
+	movl	CPUVAR(ISOURCES)(,%eax,4),%eax
+	jmp	*IS_RESUME(%eax)
+7:	movl	%ebx,CPUVAR(ILEVEL)	/* restore cpl */
+	jmp	_C_LABEL(trapreturn)
 #endif /* XEN */
 #ifndef DIAGNOSTIC
 6:	INTRFASTEXIT

Index: src/sys/arch/i386/include/frameasm.h
diff -u src/sys/arch/i386/include/frameasm.h:1.15 src/sys/arch/i386/include/frameasm.h:1.15.46.1
--- src/sys/arch/i386/include/frameasm.h:1.15	Tue Jul 26 12:57:35 2011
+++ src/sys/arch/i386/include/frameasm.h	Tue Aug  1 23:18:30 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: frameasm.h,v 1.15 2011/07/26 12:57:35 yamt Exp $	*/
+/*	$NetBSD: frameasm.h,v 1.15.46.1 2017/08/01 23:18:30 snj Exp $	*/
 
 #ifndef _I386_FRAMEASM_H_
 #define _I386_FRAMEASM_H_
@@ -9,22 +9,22 @@
 #endif
 
 #if !defined(XEN)
-#define CLI(reg)        cli
-#define STI(reg)        sti
+#define CLI(reg)	cli
+#define STI(reg)	sti
 #else
 /* XXX assym.h */
-#define TRAP_INSTR      int $0x82
-#define XEN_BLOCK_EVENTS(reg)   movb $1,EVTCHN_UPCALL_MASK(reg)
-#define XEN_UNBLOCK_EVENTS(reg) movb $0,EVTCHN_UPCALL_MASK(reg)
-#define XEN_TEST_PENDING(reg)   testb $0xFF,EVTCHN_UPCALL_PENDING(reg)
-
-#define CLI(reg)        movl    CPUVAR(VCPU),reg ;  \
-                        XEN_BLOCK_EVENTS(reg)
-#define STI(reg)        movl    CPUVAR(VCPU),reg ;  \
+#define TRAP_INSTR	int	$0x82
+#define XEN_BLOCK_EVENTS(reg)	movb	$1,EVTCHN_UPCALL_MASK(reg)
+#define XEN_UNBLOCK_EVENTS(reg)	movb	$0,EVTCHN_UPCALL_MASK(reg)
+#define XEN_TEST_PENDING(reg)	testb	$0xFF,EVTCHN_UPCALL_PENDING(reg)
+
+#define CLI(reg)	movl	CPUVAR(VCPU),reg ;  \
+			XEN_BLOCK_EVENTS(reg)
+#define STI(reg)	movl	CPUVAR(VCPU),reg ;  \
 			XEN_UNBLOCK_EVENTS(reg)
-#define STIC(reg)       movl    CPUVAR(VCPU),reg ;  \
+#define STIC(reg)	movl	CPUVAR(VCPU),reg ;  \
 			XEN_UNBLOCK_EVENTS(reg)  ; \
-			testb $0xff,EVTCHN_UPCALL_PENDING(reg)
+			testb	$0xff,EVTCHN_UPCALL_PENDING(reg)
 #endif
 
 #ifndef TRAPLOG
@@ -60,7 +60,7 @@
 	rdmsr			;			\
 	movl	%eax,TREC_IBT(%ebx)
 #endif
-		
+
 /*
  * These are used on interrupt or trap entry or exit.
  */

Index: src/sys/arch/x86/include/sysarch.h
diff -u src/sys/arch/x86/include/sysarch.h:1.11 src/sys/arch/x86/include/sysarch.h:1.11.6.1
--- src/sys/arch/x86/include/sysarch.h:1.11	Fri Mar 10 13:09:11 2017
+++ src/sys/arch/x86/include/sysarch.h	Tue Aug  1 23:18:30 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sysarch.h,v 1.11 2017/03/10 13:09:11 maxv Exp $	*/
+/*	$NetBSD: sysarch.h,v 1.11.6.1 2017/08/01 23:18:30 snj Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -134,6 +134,7 @@ struct _X86_SYSARCH_L(pmc_info_args) {
 	int vers;
 	int type;
 	uint32_t nctrs;
+	uint64_t nsamp;
 };
 
 #define	PMC_VERSION		1

Index: src/sys/arch/x86/x86/pmc.c
diff -u src/sys/arch/x86/x86/pmc.c:1.7 src/sys/arch/x86/x86/pmc.c:1.7.2.1
--- src/sys/arch/x86/x86/pmc.c:1.7	Tue May 23 08:54:39 2017
+++ src/sys/arch/x86/x86/pmc.c	Tue Aug  1 23:18:30 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmc.c,v 1.7 2017/05/23 08:54:39 nonaka Exp $	*/
+/*	$NetBSD: pmc.c,v 1.7.2.1 2017/08/01 23:18:30 snj Exp $	*/
 
 /*
  * Copyright (c) 2017 The NetBSD Foundation, Inc.
@@ -63,24 +63,32 @@
  */
 
 /*
- * Interface to x86 CPU Performance Counters.
+ * Interface to x86 CPU Performance Counters. System-wide only, for now.
+ *
+ * For each PMC on each CPU, two pieces of information are returned to userland:
+ * the number of overflows, and the current value of the PMC. It means that the
+ * total number of events for the given PMC on the given CPU is computable the
+ * following way:
+ *     tot_n_events = NEVENTS_SAMPLE * overfl + ctrval
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmc.c,v 1.7 2017/05/23 08:54:39 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmc.c,v 1.7.2.1 2017/08/01 23:18:30 snj Exp $");
+
+#include "opt_pmc.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/proc.h>
 #include <sys/cpu.h>
 #include <sys/xcall.h>
+#include <sys/kauth.h>
 
 #include <machine/cpufunc.h>
 #include <machine/cpuvar.h>
 #include <machine/specialreg.h>
 #include <machine/sysarch.h>
 #include <machine/pmc.h>
-#include <machine/cpu_counter.h>
 #include <machine/cputypes.h>
 #include <machine/i82489reg.h>
 #include <machine/i82489var.h>
@@ -89,8 +97,12 @@ __KERNEL_RCSID(0, "$NetBSD: pmc.c,v 1.7 
 
 #define NEVENTS_SAMPLE	500000
 
+/*
+ * Structure describing a PMC.
+ */
 typedef struct {
 	bool running;
+	size_t n;		/* pmc number */
 	uint32_t evtmsr;	/* event selector MSR */
 	uint64_t evtval;	/* event selector value */
 	uint32_t ctrmsr;	/* counter MSR */
@@ -99,21 +111,36 @@ typedef struct {
 	uint64_t ctrmask;
 } pmc_state_t;
 
-static nmi_handler_t *pmc_nmi_handle;
-static uint32_t pmc_lapic_image[MAXCPUS];
+/*
+ * Per-CPU structure that describes the values of each PMC, plus the state
+ * of the LAPIC before enabling PMCs.
+ */
+typedef struct {
+	x86_pmc_cpuval_t val[PMC_NCOUNTERS];	/* values returned to user */ 
+	uint64_t nmioverfl[PMC_NCOUNTERS];	/* incremented by NMI intr */
+	uint32_t lapic_image;			/* saved content of LAPIC */
+} pmc_cpu_t;
+
+static pmc_state_t pmc_state[PMC_NCOUNTERS];
+static pmc_cpu_t pmc_cpu[MAXCPUS];
 
-static x86_pmc_cpuval_t pmc_val_cpus[MAXCPUS] __aligned(CACHE_LINE_SIZE);
+static nmi_handler_t *pmc_nmi_handle;
 static kmutex_t pmc_lock;
 
-static pmc_state_t pmc_state[PMC_NCOUNTERS];
 static uint32_t pmc_ncounters __read_mostly;
 static int pmc_type __read_mostly;
 
+/*
+ * Handle PMC overflows. Called from NMI interrupt context, with interrupts
+ * disabled.
+ */
 static int
 pmc_nmi(const struct trapframe *tf, void *dummy)
 {
 	struct cpu_info *ci = curcpu();
 	pmc_state_t *pmc;
+	pmc_cpu_t *cpu;
+	uint64_t ctr;
 	size_t i;
 
 	if (pmc_type == PMC_TYPE_NONE) {
@@ -124,7 +151,11 @@ pmc_nmi(const struct trapframe *tf, void
 		if (!pmc->running) {
 			continue;
 		}
-		/* XXX make sure it really comes from this PMC */
+		ctr = rdmsr(pmc->ctrmsr);
+		/* If the highest bit is zero, then it's this PMC */
+		if ((ctr & ((pmc->ctrmask + 1) >> 1)) != 0) {
+			continue;
+		}
 		break;
 	}
 	if (i == pmc_ncounters) {
@@ -132,7 +163,8 @@ pmc_nmi(const struct trapframe *tf, void
 	}
 
 	/* Count the overflow, and restart the counter */
-	pmc_val_cpus[cpu_index(ci)].overfl++;
+	cpu = &pmc_cpu[cpu_index(ci)];
+	cpu->nmioverfl[i]++;
 	wrmsr(pmc->ctrmsr, pmc->ctrinitval);
 
 	return 1;
@@ -143,9 +175,37 @@ pmc_read_cpu(void *arg1, void *arg2)
 {
 	pmc_state_t *pmc = (pmc_state_t *)arg1;
 	struct cpu_info *ci = curcpu();
+	pmc_cpu_t *cpu = &pmc_cpu[cpu_index(ci)];
+	uint64_t evtmsr, en;
+
+	switch (pmc_type) {
+	case PMC_TYPE_I686:
+		en = PMC6_EVTSEL_EN;
+		break;
+
+	case PMC_TYPE_K7:
+		en = K7_EVTSEL_EN;
+		break;
+
+	case PMC_TYPE_F10H:
+		en = F10H_EVTSEL_EN;
+		break;
+	}
+
+	evtmsr = rdmsr(pmc->evtmsr);
+
+	/*
+	 * Quickly disable the counter, to avoid getting an NMI after setting
+	 * ctrval.
+	 */
+	wrmsr(pmc->evtmsr, evtmsr & ~en);
 
-	pmc_val_cpus[cpu_index(ci)].ctrval =
+	cpu->val[pmc->n].ctrval =
 	    (rdmsr(pmc->ctrmsr) & pmc->ctrmask) - pmc->ctrinitval;
+	cpu->val[pmc->n].overfl = cpu->nmioverfl[pmc->n];
+
+	/* Re-enable the counter */
+	wrmsr(pmc->evtmsr, evtmsr);
 }
 
 static void
@@ -154,9 +214,14 @@ pmc_apply_cpu(void *arg1, void *arg2)
 	pmc_state_t *pmc = (pmc_state_t *)arg1;
 	bool start = (bool)arg2;
 	struct cpu_info *ci = curcpu();
+	pmc_cpu_t *cpu = &pmc_cpu[cpu_index(ci)];
 
 	if (start) {
-		pmc_lapic_image[cpu_index(ci)] = lapic_readreg(LAPIC_PCINT);
+		cpu->lapic_image = lapic_readreg(LAPIC_PCINT);
+		cpu->val[pmc->n].ctrval = 0;
+		cpu->val[pmc->n].overfl = 0;
+		cpu->nmioverfl[pmc->n] = 0;
+
 		lapic_writereg(LAPIC_PCINT, LAPIC_DLMODE_NMI);
 	}
 
@@ -169,11 +234,8 @@ pmc_apply_cpu(void *arg1, void *arg2)
 		break;
 	}
 
-	pmc_val_cpus[cpu_index(ci)].ctrval = 0;
-	pmc_val_cpus[cpu_index(ci)].overfl = 0;
-
 	if (!start) {
-		lapic_writereg(LAPIC_PCINT, pmc_lapic_image[cpu_index(ci)]);
+		lapic_writereg(LAPIC_PCINT, cpu->lapic_image);
 	}
 }
 
@@ -287,6 +349,7 @@ pmc_init(void)
 		pmc_type = PMC_TYPE_I686;
 		pmc_ncounters = 2;
 		for (i = 0; i < pmc_ncounters; i++) {
+			pmc_state[i].n = i;
 			pmc_state[i].evtmsr = MSR_EVNTSEL0 + i;
 			pmc_state[i].ctrmsr = MSR_PERFCTR0 + i;
 			pmc_state[i].ctrmaxval = (UINT64_C(1) << 40) - 1;
@@ -297,6 +360,7 @@ pmc_init(void)
 			pmc_type = PMC_TYPE_F10H;
 			pmc_ncounters = 4;
 			for (i = 0; i < pmc_ncounters; i++) {
+				pmc_state[i].n = i;
 				pmc_state[i].evtmsr = MSR_F10H_EVNTSEL0 + i;
 				pmc_state[i].ctrmsr = MSR_F10H_PERFCTR0 + i;
 				pmc_state[i].ctrmaxval =
@@ -308,6 +372,7 @@ pmc_init(void)
 			pmc_type = PMC_TYPE_K7;
 			pmc_ncounters = 4;
 			for (i = 0; i < pmc_ncounters; i++) {
+				pmc_state[i].n = i;
 				pmc_state[i].evtmsr = MSR_K7_EVNTSEL0 + i;
 				pmc_state[i].ctrmsr = MSR_K7_PERFCTR0 + i;
 				pmc_state[i].ctrmaxval =
@@ -325,12 +390,19 @@ int
 sys_pmc_info(struct lwp *l, struct x86_pmc_info_args *uargs, register_t *retval)
 {
 	struct x86_pmc_info_args rv;
+	int error;
+
+	error = kauth_authorize_machdep(l->l_cred, KAUTH_MACHDEP_X86PMC,
+	    NULL, NULL, NULL, NULL);
+	if (error)
+		return error;
 
 	memset(&rv, 0, sizeof(rv));
 
 	rv.vers = PMC_VERSION;
 	rv.type = pmc_type;
 	rv.nctrs = pmc_ncounters;
+	rv.nsamp = NEVENTS_SAMPLE;
 
 	return copyout(&rv, uargs, sizeof(rv));
 }
@@ -344,6 +416,11 @@ sys_pmc_startstop(struct lwp *l, struct 
 	bool start;
 	int error;
 
+	error = kauth_authorize_machdep(l->l_cred, KAUTH_MACHDEP_X86PMC,
+	    NULL, NULL, NULL, NULL);
+	if (error)
+		return error;
+
 	if (pmc_type == PMC_TYPE_NONE)
 		return ENODEV;
 
@@ -383,9 +460,15 @@ sys_pmc_read(struct lwp *l, struct x86_p
 {
 	struct x86_pmc_read_args args;
 	pmc_state_t *pmc;
-	size_t nval;
+	pmc_cpu_t *cpu;
+	size_t i, nval;
 	int error;
 
+	error = kauth_authorize_machdep(l->l_cred, KAUTH_MACHDEP_X86PMC,
+	    NULL, NULL, NULL, NULL);
+	if (error)
+		return error;
+
 	if (pmc_type == PMC_TYPE_NONE)
 		return ENODEV;
 
@@ -405,8 +488,16 @@ sys_pmc_read(struct lwp *l, struct x86_p
 
 	if (pmc->running) {
 		pmc_read(pmc);
-		error = copyout(&pmc_val_cpus, args.values,
-		    nval * sizeof(x86_pmc_cpuval_t));
+
+		for (i = 0; i < nval; i++) {
+			cpu = &pmc_cpu[i];
+
+			error = copyout(&cpu->val[pmc->n], args.values + i,
+			    sizeof(x86_pmc_cpuval_t));
+			if (error)
+				break;
+		}
+
 		args.nval = nval;
 	} else {
 		error = ENOENT;

Index: src/sys/arch/x86/x86/sys_machdep.c
diff -u src/sys/arch/x86/x86/sys_machdep.c:1.35 src/sys/arch/x86/x86/sys_machdep.c:1.35.6.1
--- src/sys/arch/x86/x86/sys_machdep.c:1.35	Fri Mar 10 14:54:12 2017
+++ src/sys/arch/x86/x86/sys_machdep.c	Tue Aug  1 23:18:30 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_machdep.c,v 1.35 2017/03/10 14:54:12 maxv Exp $	*/
+/*	$NetBSD: sys_machdep.c,v 1.35.6.1 2017/08/01 23:18:30 snj Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2009 The NetBSD Foundation, Inc.
@@ -30,9 +30,10 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.35 2017/03/10 14:54:12 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.35.6.1 2017/08/01 23:18:30 snj Exp $");
 
 #include "opt_mtrr.h"
+#include "opt_pmc.h"
 #include "opt_user_ldt.h"
 #include "opt_compat_netbsd.h"
 #ifdef i386

Index: src/sys/arch/xen/conf/files.compat
diff -u src/sys/arch/xen/conf/files.compat:1.25 src/sys/arch/xen/conf/files.compat:1.25.8.1
--- src/sys/arch/xen/conf/files.compat:1.25	Tue Dec 13 10:54:27 2016
+++ src/sys/arch/xen/conf/files.compat	Tue Aug  1 23:18:30 2017
@@ -1,4 +1,4 @@
-#	$NetBSD: files.compat,v 1.25 2016/12/13 10:54:27 kamil Exp $
+#	$NetBSD: files.compat,v 1.25.8.1 2017/08/01 23:18:30 snj Exp $
 #	NetBSD: files.x86,v 1.10 2003/10/08 17:30:00 bouyer Exp 
 
 # options for MP configuration through the MP spec
@@ -28,6 +28,8 @@ defflag	opt_pcifixup.h		XXXOPT_PCIFIXUP
 # VM86 emulation
 defflag	opt_vm86.h			XXXVM86
 
+defflag opt_pmc.h			XXXPMC
+
 # User-settable LDT (used by WINE)
 defflag	opt_user_ldt.h			XXXUSER_LDT
 

Index: src/sys/secmodel/suser/secmodel_suser.c
diff -u src/sys/secmodel/suser/secmodel_suser.c:1.42 src/sys/secmodel/suser/secmodel_suser.c:1.42.10.1
--- src/sys/secmodel/suser/secmodel_suser.c:1.42	Mon Aug 17 06:16:03 2015
+++ src/sys/secmodel/suser/secmodel_suser.c	Tue Aug  1 23:18:30 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_suser.c,v 1.42 2015/08/17 06:16:03 knakahara Exp $ */
+/* $NetBSD: secmodel_suser.c,v 1.42.10.1 2017/08/01 23:18:30 snj Exp $ */
 /*-
  * Copyright (c) 2006 Elad Efrat <e...@netbsd.org>
  * All rights reserved.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.42 2015/08/17 06:16:03 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.42.10.1 2017/08/01 23:18:30 snj Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -834,13 +834,13 @@ int
 secmodel_suser_machdep_cb(kauth_cred_t cred, kauth_action_t action,
     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
 {
-        bool isroot;
-        int result;
+	bool isroot;
+	int result;
 
-        isroot = suser_isroot(cred);
-        result = KAUTH_RESULT_DEFER;
+	isroot = suser_isroot(cred);
+	result = KAUTH_RESULT_DEFER;
 
-        switch (action) {
+	switch (action) {
 	case KAUTH_MACHDEP_CPU_UCODE_APPLY:
 	case KAUTH_MACHDEP_IOPERM_GET:
 	case KAUTH_MACHDEP_LDT_GET:
@@ -853,6 +853,7 @@ secmodel_suser_machdep_cb(kauth_cred_t c
 	case KAUTH_MACHDEP_NVRAM:
 	case KAUTH_MACHDEP_UNMANAGEDMEM:
 	case KAUTH_MACHDEP_PXG:
+	case KAUTH_MACHDEP_X86PMC:
 		if (isroot)
 			result = KAUTH_RESULT_ALLOW;
 		break;
@@ -875,11 +876,11 @@ int
 secmodel_suser_device_cb(kauth_cred_t cred, kauth_action_t action,
     void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
 {
-        bool isroot;
-        int result;
+	bool isroot;
+	int result;
 
-        isroot = suser_isroot(cred);
-        result = KAUTH_RESULT_DEFER;
+	isroot = suser_isroot(cred);
+	result = KAUTH_RESULT_DEFER;
 
 	switch (action) {
 	case KAUTH_DEVICE_BLUETOOTH_SETPRIV:

Index: src/sys/sys/kauth.h
diff -u src/sys/sys/kauth.h:1.73 src/sys/sys/kauth.h:1.73.10.1
--- src/sys/sys/kauth.h:1.73	Tue Oct  6 22:13:39 2015
+++ src/sys/sys/kauth.h	Tue Aug  1 23:18:31 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: kauth.h,v 1.73 2015/10/06 22:13:39 christos Exp $ */
+/* $NetBSD: kauth.h,v 1.73.10.1 2017/08/01 23:18:31 snj Exp $ */
 
 /*-
  * Copyright (c) 2005, 2006 Elad Efrat <e...@netbsd.org>  
@@ -321,6 +321,7 @@ enum {
 	KAUTH_MACHDEP_NVRAM,
 	KAUTH_MACHDEP_UNMANAGEDMEM,
 	KAUTH_MACHDEP_PXG,
+	KAUTH_MACHDEP_X86PMC
 };
 
 /*

Index: src/usr.bin/pmc/Makefile
diff -u src/usr.bin/pmc/Makefile:1.4 src/usr.bin/pmc/Makefile:1.4.4.1
--- src/usr.bin/pmc/Makefile:1.4	Wed Mar  8 16:05:29 2017
+++ src/usr.bin/pmc/Makefile	Tue Aug  1 23:18:31 2017
@@ -1,6 +1,6 @@
-#	$NetBSD: Makefile,v 1.4 2017/03/08 16:05:29 maxv Exp $
+#	$NetBSD: Makefile,v 1.4.4.1 2017/08/01 23:18:31 snj Exp $
 
-.if (${MACHINE_ARCH} == "i386")
+.if (${MACHINE_ARCH} == "i386") || (${MACHINE_ARCH} == "x86_64")
 PROG=	pmc
 .else
 MAN=	pmc.1

Index: src/usr.bin/pmc/pmc.1
diff -u src/usr.bin/pmc/pmc.1:1.11 src/usr.bin/pmc/pmc.1:1.11.4.1
--- src/usr.bin/pmc/pmc.1:1.11	Fri Mar 10 15:34:17 2017
+++ src/usr.bin/pmc/pmc.1	Tue Aug  1 23:18:31 2017
@@ -1,4 +1,4 @@
-.\"	$NetBSD: pmc.1,v 1.11 2017/03/10 15:34:17 wiz Exp $
+.\"	$NetBSD: pmc.1,v 1.11.4.1 2017/08/01 23:18:31 snj Exp $
 .\"
 .\" Copyright (c) 2017 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -58,7 +58,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd March 10, 2017
+.Dd July 12, 2017
 .Dt PMC 1
 .Os
 .Sh NAME
@@ -71,7 +71,8 @@
 .Sh DESCRIPTION
 The
 .Nm
-command can be used to control and inspect the state of CPUs in the system.
+tool can be used to control and inspect the state of the
+Performance-Monitoring Counters (PMCs) in the system.
 .Pp
 The first argument,
 .Ar command ,
@@ -95,24 +96,34 @@ specifies the source of the event; it mu
 Stop any performance counters that are currently running, and display the
 values of these counters.
 .El
+.Sh FILES
+.Pa src/sys/arch/x86/x86/pmc.c
+x86 implementation.
+.Pp
+.Pa src/usr.bin/pmc/pmc.c
+pmc tool.
 .Sh EXAMPLES
 The following command prints the available counters.
-.Dl $ pmc list
+.Dl # pmc list
 .Pp
 The following command starts two counters.
 The former will count the 'l2cache-access' events that are triggered from
 userland, the latter will count the 'l1cache-access' events triggered from
 both userland and the kernel.
-.Dl $ pmc start l2cache-access:u l1cache-access:uk
+.Dl # pmc start l2cache-access:u l1cache-access:uk
 .Pp
 Note that the two following commands are not exactly identical.
-.Dl $ pmc start l1cache-access:u l1cache-access:k
-.Dl $ pmc start l1cache-access:uk
+.Dl # pmc start l1cache-access:u l1cache-access:k
+.Dl # pmc start l1cache-access:uk
 The former will start two different counters that have a different source but
 track the same event.
 The latter will start one counter that tracks the event from all sources;
 it therefore does the sum of the two counters from the first command, but
 takes only one counter to do so.
+.Sh INTERPRETING RESULTS
+For each PMC on each CPU, the value reported by the
+.Nm
+tool is the number of events counted, encoded in a 64bit integer.
 .Sh DIAGNOSTICS
 .Bl -diag
 .It PMC support not compiled into the kernel
@@ -132,9 +143,10 @@ The
 .Nm
 command first appeared in
 .Nx 1.6 .
-It was revamped in 2017.
+It was revamped in
+.Nx 8.0 .
 .Sh BUGS
 The
 .Nm
 command currently only supports performance-monitoring counters
-on the i386 architecture.
+on the i386 and amd64 architectures.

Index: src/usr.bin/pmc/pmc.c
diff -u src/usr.bin/pmc/pmc.c:1.23 src/usr.bin/pmc/pmc.c:1.23.4.1
--- src/usr.bin/pmc/pmc.c:1.23	Fri Mar 24 18:30:44 2017
+++ src/usr.bin/pmc/pmc.c	Tue Aug  1 23:18:31 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmc.c,v 1.23 2017/03/24 18:30:44 maxv Exp $	*/
+/*	$NetBSD: pmc.c,v 1.23.4.1 2017/08/01 23:18:31 snj Exp $	*/
 
 /*
  * Copyright (c) 2017 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
 #include <sys/cdefs.h>
 
 #ifndef lint
-__RCSID("$NetBSD: pmc.c,v 1.23 2017/03/24 18:30:44 maxv Exp $");
+__RCSID("$NetBSD: pmc.c,v 1.23.4.1 2017/08/01 23:18:31 snj Exp $");
 #endif
 
 #include <inttypes.h>
@@ -379,6 +379,7 @@ static int x86_pmc_startstop(x86_pmc_sta
 static int x86_pmc_read(x86_pmc_read_args_t *);
 
 static uint32_t pmc_ncounters;
+static size_t pmc_nsamples;
 
 static struct cmdtab {
 	const char *label;
@@ -428,6 +429,7 @@ pmc_start(const pmc_name2val_cpu_t *pncp
 	uint32_t flags;
 	size_t n, i;
 
+	/* Get the source for each counter (kernel or userland) */
 	for (n = 0; n < pmc_ncounters; n++) {
 		if (argv[n] == NULL)
 			break;
@@ -437,6 +439,7 @@ pmc_start(const pmc_name2val_cpu_t *pncp
 			usage();
 	}
 
+	/* Initialize each pmcarg structure */
 	for (i = 0; i < n; i++) {
 		pmcarg = &pmcargs[i];
 		event = tokens[i][0];
@@ -460,6 +463,7 @@ pmc_start(const pmc_name2val_cpu_t *pncp
 		pmcarg->flags = flags;
 	}
 
+	/* Finally, start each counter */
 	for (i = 0; i < n; i++) {
 		pmcarg = &pmcargs[i];
 		if (x86_pmc_startstop(pmcarg) < 0)
@@ -475,6 +479,7 @@ pmc_stop(const pmc_name2val_cpu_t *pncp,
 	x86_pmc_startstop_args_t pmcstop;
 	x86_pmc_read_args_t pmcread;
 	size_t i, j, n, nval = 0;
+	uint64_t val;
 
 	/* Read the values. */
 	for (n = 0; n < pmc_ncounters; n++) {
@@ -510,7 +515,9 @@ pmc_stop(const pmc_name2val_cpu_t *pncp,
 	for (i = 0; i < n; i++) {
 		printf("%zu\t\t", i);
 		for (j = 0; j < nval; j++) {
-			printf("%" PRIu64 "\t\t", cpuval[i][j].ctrval);
+			val = cpuval[i][j].overfl * pmc_nsamples +
+			    cpuval[i][j].ctrval;
+			printf("%" PRIu64 "\t\t", val);
 		}
 		printf("\n");
 	}
@@ -585,11 +592,21 @@ main(int argc, char **argv)
 	setprogname(argv[0]);
 	argv += 1;
 
-	if (x86_pmc_info(&pmcinfo) < 0)
-		errx(EXIT_FAILURE, "PMC support not compiled into the kernel");
+	if (argc < 2)
+		usage();
+
+	if (x86_pmc_info(&pmcinfo) < 0) {
+		if (errno == EPERM)
+			errx(EXIT_FAILURE,
+			    "PMC operations require root privileges");
+		else
+			errx(EXIT_FAILURE,
+			    "PMC support not compiled into the kernel");
+	}
 	if (pmcinfo.vers != 1)
 		errx(EXIT_FAILURE, "Wrong PMC version");
 	pmc_ncounters = pmcinfo.nctrs;
+	pmc_nsamples = pmcinfo.nsamp;
 
 	pncp = pmc_lookup_cpu(pmcinfo.type);
 	if (pncp == NULL)

Reply via email to