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 <[email protected]>
* 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 <[email protected]>
@@ -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)