aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/lguest/.gitignore1
-rw-r--r--tools/lib/traceevent/.gitignore1
-rw-r--r--tools/perf/.gitignore4
-rw-r--r--tools/perf/Documentation/perf-annotate.txt6
-rw-r--r--tools/perf/Documentation/perf-probe.txt6
-rw-r--r--tools/perf/Documentation/perf-report.txt21
-rw-r--r--tools/perf/Documentation/perf-script.txt18
-rw-r--r--tools/perf/Makefile37
-rw-r--r--tools/perf/arch/arm/util/dwarf-regs.c3
-rw-r--r--tools/perf/builtin-annotate.c15
-rw-r--r--tools/perf/builtin-lock.c8
-rw-r--r--tools/perf/builtin-probe.c17
-rw-r--r--tools/perf/builtin-record.c28
-rw-r--r--tools/perf/builtin-report.c72
-rw-r--r--tools/perf/builtin-sched.c24
-rw-r--r--tools/perf/builtin-script.c121
-rw-r--r--tools/perf/builtin-stat.c27
-rw-r--r--tools/perf/builtin-test.c251
-rw-r--r--tools/perf/builtin-top.c11
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c230
-rw-r--r--tools/perf/util/callchain.h6
-rw-r--r--tools/perf/util/config.c32
-rw-r--r--tools/perf/util/dwarf-aux.c843
-rw-r--r--tools/perf/util/dwarf-aux.h111
-rw-r--r--tools/perf/util/event.c5
-rw-r--r--tools/perf/util/event.h2
-rw-r--r--tools/perf/util/evlist.c37
-rw-r--r--tools/perf/util/evlist.h3
-rw-r--r--tools/perf/util/evsel.c58
-rw-r--r--tools/perf/util/evsel.h1
-rw-r--r--tools/perf/util/header.c24
-rw-r--r--tools/perf/util/hist.c6
-rw-r--r--tools/perf/util/include/linux/compiler.h2
-rw-r--r--tools/perf/util/parse-events.c47
-rw-r--r--tools/perf/util/parse-events.h6
-rw-r--r--tools/perf/util/probe-event.c173
-rw-r--r--tools/perf/util/probe-event.h1
-rw-r--r--tools/perf/util/probe-finder.c981
-rw-r--r--tools/perf/util/probe-finder.h45
-rw-r--r--tools/perf/util/python.c134
-rw-r--r--tools/perf/util/session.c132
-rw-r--r--tools/perf/util/session.h12
-rw-r--r--tools/perf/util/setup.py21
-rw-r--r--tools/perf/util/sort.c233
-rw-r--r--tools/perf/util/sort.h14
-rw-r--r--tools/perf/util/string.c19
-rw-r--r--tools/perf/util/symbol.c221
-rw-r--r--tools/perf/util/symbol.h1
-rw-r--r--tools/perf/util/trace-event-info.c120
-rw-r--r--tools/perf/util/trace-event-parse.c4
-rw-r--r--tools/perf/util/ui/browsers/top.c1
-rw-r--r--tools/perf/util/util.h1
-rw-r--r--tools/power/cpupower/.gitignore29
-rw-r--r--tools/power/cpupower/Makefile280
-rw-r--r--tools/power/cpupower/README49
-rw-r--r--tools/power/cpupower/ToDo11
-rw-r--r--tools/power/cpupower/bench/Makefile29
-rw-r--r--tools/power/cpupower/bench/README-BENCH124
-rw-r--r--tools/power/cpupower/bench/benchmark.c194
-rw-r--r--tools/power/cpupower/bench/benchmark.h29
-rw-r--r--tools/power/cpupower/bench/config.h36
-rw-r--r--tools/power/cpupower/bench/cpufreq-bench_plot.sh104
-rw-r--r--tools/power/cpupower/bench/cpufreq-bench_script.sh101
-rw-r--r--tools/power/cpupower/bench/example.cfg11
-rw-r--r--tools/power/cpupower/bench/main.c202
-rw-r--r--tools/power/cpupower/bench/parse.c225
-rw-r--r--tools/power/cpupower/bench/parse.h53
-rw-r--r--tools/power/cpupower/bench/system.c191
-rw-r--r--tools/power/cpupower/bench/system.h29
-rw-r--r--tools/power/cpupower/debug/i386/Makefile20
-rw-r--r--tools/power/cpupower/debug/i386/centrino-decode.c113
-rw-r--r--tools/power/cpupower/debug/i386/dump_psb.c196
-rw-r--r--tools/power/cpupower/debug/i386/intel_gsic.c78
-rw-r--r--tools/power/cpupower/debug/i386/powernow-k8-decode.c96
-rw-r--r--tools/power/cpupower/debug/kernel/Makefile23
-rw-r--r--tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c113
-rw-r--r--tools/power/cpupower/debug/x86_64/Makefile14
-rw-r--r--tools/power/cpupower/lib/cpufreq.c208
-rw-r--r--tools/power/cpupower/lib/cpufreq.h223
-rw-r--r--tools/power/cpupower/lib/sysfs.c672
-rw-r--r--tools/power/cpupower/lib/sysfs.h31
-rw-r--r--tools/power/cpupower/man/cpupower-frequency-info.176
-rw-r--r--tools/power/cpupower/man/cpupower-frequency-set.154
-rw-r--r--tools/power/cpupower/man/cpupower-info.119
-rw-r--r--tools/power/cpupower/man/cpupower-monitor.1179
-rw-r--r--tools/power/cpupower/man/cpupower-set.1103
-rw-r--r--tools/power/cpupower/man/cpupower.172
-rw-r--r--tools/power/cpupower/po/cs.po944
-rw-r--r--tools/power/cpupower/po/de.po961
-rw-r--r--tools/power/cpupower/po/fr.po947
-rw-r--r--tools/power/cpupower/po/it.po961
-rw-r--r--tools/power/cpupower/po/pt.po957
-rw-r--r--tools/power/cpupower/utils/builtin.h11
-rw-r--r--tools/power/cpupower/utils/cpufreq-info.c668
-rw-r--r--tools/power/cpupower/utils/cpufreq-set.c331
-rw-r--r--tools/power/cpupower/utils/cpuidle-info.c222
-rw-r--r--tools/power/cpupower/utils/cpupower-info.c135
-rw-r--r--tools/power/cpupower/utils/cpupower-set.c134
-rw-r--r--tools/power/cpupower/utils/cpupower.c214
-rw-r--r--tools/power/cpupower/utils/helpers/amd.c137
-rw-r--r--tools/power/cpupower/utils/helpers/bitmask.c292
-rw-r--r--tools/power/cpupower/utils/helpers/bitmask.h33
-rw-r--r--tools/power/cpupower/utils/helpers/cpuid.c176
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h190
-rw-r--r--tools/power/cpupower/utils/helpers/misc.c27
-rw-r--r--tools/power/cpupower/utils/helpers/msr.c115
-rw-r--r--tools/power/cpupower/utils/helpers/pci.c44
-rw-r--r--tools/power/cpupower/utils/helpers/sysfs.c408
-rw-r--r--tools/power/cpupower/utils/helpers/sysfs.h30
-rw-r--r--tools/power/cpupower/utils/helpers/topology.c111
-rw-r--r--tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c338
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c196
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c440
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h68
-rw-r--r--tools/power/cpupower/utils/idle_monitor/idle_monitors.def7
-rw-r--r--tools/power/cpupower/utils/idle_monitor/idle_monitors.h18
-rw-r--r--tools/power/cpupower/utils/idle_monitor/mperf_monitor.c338
-rw-r--r--tools/power/cpupower/utils/idle_monitor/nhm_idle.c216
-rw-r--r--tools/power/cpupower/utils/idle_monitor/snb_idle.c190
-rwxr-xr-xtools/power/cpupower/utils/version-gen.sh35
-rw-r--r--tools/power/x86/turbostat/turbostat.c46
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c5
-rw-r--r--tools/slub/slabinfo.c59
-rwxr-xr-xtools/testing/ktest/ktest.pl970
-rw-r--r--tools/testing/ktest/sample.conf142
-rw-r--r--tools/testing/selftests/mqueue/.gitignore2
-rw-r--r--tools/virtio/linux/hrtimer.h0
-rw-r--r--tools/virtio/linux/module.h0
128 files changed, 17831 insertions, 1471 deletions
diff --git a/tools/lguest/.gitignore b/tools/lguest/.gitignore
new file mode 100644
index 00000000000..115587fd5f6
--- /dev/null
+++ b/tools/lguest/.gitignore
@@ -0,0 +1 @@
lguest
diff --git a/tools/lib/traceevent/.gitignore b/tools/lib/traceevent/.gitignore
new file mode 100644
index 00000000000..35f56be5a4c
--- /dev/null
+++ b/tools/lib/traceevent/.gitignore
@@ -0,0 +1 @@
TRACEEVENT-CFLAGS
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 416684be0ad..8f8fbc227a4 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -19,3 +19,7 @@ TAGS
19cscope* 19cscope*
20config.mak 20config.mak
21config.mak.autogen 21config.mak.autogen
22*-bison.*
23*-flex.*
24*.pyc
25*.pyo
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index 6f5a498608b..85c5f026930 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -66,6 +66,12 @@ OPTIONS
66 used. This interfaces starts by centering on the line with more 66 used. This interfaces starts by centering on the line with more
67 samples, TAB/UNTAB cycles through the lines with more samples. 67 samples, TAB/UNTAB cycles through the lines with more samples.
68 68
69-c::
70--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
71 be provided as a comma-separated list with no space: 0,1. Ranges of
72 CPUs are specified with -: 0-2. Default is to report samples on all
73 CPUs.
74
69SEE ALSO 75SEE ALSO
70-------- 76--------
71linkperf:perf-record[1], linkperf:perf-report[1] 77linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 02bafce4b34..2780d9ce48b 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -34,9 +34,11 @@ OPTIONS
34 Specify vmlinux path which has debuginfo (Dwarf binary). 34 Specify vmlinux path which has debuginfo (Dwarf binary).
35 35
36-m:: 36-m::
37--module=MODNAME:: 37--module=MODNAME|PATH::
38 Specify module name in which perf-probe searches probe points 38 Specify module name in which perf-probe searches probe points
39 or lines. 39 or lines. If a path of module file is passed, perf-probe
40 treat it as an offline module (this means you can add a probe on
41 a module which has not been loaded yet).
40 42
41-s:: 43-s::
42--source=PATH:: 44--source=PATH::
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 8ba03d6e539..04253c07d19 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -80,15 +80,24 @@ OPTIONS
80--dump-raw-trace:: 80--dump-raw-trace::
81 Dump raw trace in ASCII. 81 Dump raw trace in ASCII.
82 82
83-g [type,min]:: 83-g [type,min,order]::
84--call-graph:: 84--call-graph::
85 Display call chains using type and min percent threshold. 85 Display call chains using type, min percent threshold and order.
86 type can be either: 86 type can be either:
87 - flat: single column, linear exposure of call chains. 87 - flat: single column, linear exposure of call chains.
88 - graph: use a graph tree, displaying absolute overhead rates. 88 - graph: use a graph tree, displaying absolute overhead rates.
89 - fractal: like graph, but displays relative rates. Each branch of 89 - fractal: like graph, but displays relative rates. Each branch of
90 the tree is considered as a new profiled object. + 90 the tree is considered as a new profiled object. +
91 Default: fractal,0.5. 91
92 order can be either:
93 - callee: callee based call graph.
94 - caller: inverted caller based call graph.
95
96 Default: fractal,0.5,callee.
97
98-G::
99--inverted::
100 alias for inverted caller based call graph.
92 101
93--pretty=<key>:: 102--pretty=<key>::
94 Pretty printing style. key: normal, raw 103 Pretty printing style. key: normal, raw
@@ -119,6 +128,12 @@ OPTIONS
119--symfs=<directory>:: 128--symfs=<directory>::
120 Look for files with symbols relative to this directory. 129 Look for files with symbols relative to this directory.
121 130
131-c::
132--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
133 be provided as a comma-separated list with no space: 0,1. Ranges of
134 CPUs are specified with -: 0-2. Default is to report samples on all
135 CPUs.
136
122SEE ALSO 137SEE ALSO
123-------- 138--------
124linkperf:perf-stat[1] 139linkperf:perf-stat[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 86c87e214b1..db017867d9e 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -115,10 +115,10 @@ OPTIONS
115-f:: 115-f::
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, sym. Field 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr.
119 list can be prepended with the type, trace, sw or hw, 119 Field list can be prepended with the type, trace, sw or hw,
120 to indicate to which event type the field list applies. 120 to indicate to which event type the field list applies.
121 e.g., -f sw:comm,tid,time,sym and -f trace:time,cpu,trace 121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
122 122
123 perf script -f <fields> 123 perf script -f <fields>
124 124
@@ -132,17 +132,17 @@ OPTIONS
132 The arguments are processed in the order received. A later usage can 132 The arguments are processed in the order received. A later usage can
133 reset a prior request. e.g.: 133 reset a prior request. e.g.:
134 134
135 -f trace: -f comm,tid,time,sym 135 -f trace: -f comm,tid,time,ip,sym
136 136
137 The first -f suppresses trace events (field list is ""), but then the 137 The first -f suppresses trace events (field list is ""), but then the
138 second invocation sets the fields to comm,tid,time,sym. In this case a 138 second invocation sets the fields to comm,tid,time,ip,sym. In this case a
139 warning is given to the user: 139 warning is given to the user:
140 140
141 "Overriding previous field request for all events." 141 "Overriding previous field request for all events."
142 142
143 Alternativey, consider the order: 143 Alternativey, consider the order:
144 144
145 -f comm,tid,time,sym -f trace: 145 -f comm,tid,time,ip,sym -f trace:
146 146
147 The first -f sets the fields for all events and the second -f 147 The first -f sets the fields for all events and the second -f
148 suppresses trace events. The user is given a warning message about 148 suppresses trace events. The user is given a warning message about
@@ -182,6 +182,12 @@ OPTIONS
182--hide-call-graph:: 182--hide-call-graph::
183 When printing symbols do not display call chain. 183 When printing symbols do not display call chain.
184 184
185-c::
186--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
187 be provided as a comma-separated list with no space: 0,1. Ranges of
188 CPUs are specified with -: 0-2. Default is to report samples on all
189 CPUs.
190
185SEE ALSO 191SEE ALSO
186-------- 192--------
187linkperf:perf-record[1], linkperf:perf-script-perl[1], 193linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 940257b5774..e9d5c271db6 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -30,6 +30,8 @@ endif
30# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds. 30# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
31# 31#
32# Define NO_DWARF if you do not want debug-info analysis feature at all. 32# Define NO_DWARF if you do not want debug-info analysis feature at all.
33#
34# Define WERROR=0 to disable treating any warnings as errors.
33 35
34$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE 36$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
35 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) 37 @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
@@ -52,7 +54,10 @@ ifeq ($(ARCH),i386)
52endif 54endif
53ifeq ($(ARCH),x86_64) 55ifeq ($(ARCH),x86_64)
54 ARCH := x86 56 ARCH := x86
55 IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) 57 IS_X86_64 := 0
58 ifeq (, $(findstring m32,$(EXTRA_CFLAGS)))
59 IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1)
60 endif
56 ifeq (${IS_X86_64}, 1) 61 ifeq (${IS_X86_64}, 1)
57 RAW_ARCH := x86_64 62 RAW_ARCH := x86_64
58 ARCH_CFLAGS := -DARCH_X86_64 63 ARCH_CFLAGS := -DARCH_X86_64
@@ -60,6 +65,11 @@ ifeq ($(ARCH),x86_64)
60 endif 65 endif
61endif 66endif
62 67
68# Treat warnings as errors unless directed not to
69ifneq ($(WERROR),0)
70 CFLAGS_WERROR := -Werror
71endif
72
63# 73#
64# Include saner warnings here, which can catch bugs: 74# Include saner warnings here, which can catch bugs:
65# 75#
@@ -92,7 +102,7 @@ ifndef PERF_DEBUG
92 CFLAGS_OPTIMIZE = -O6 102 CFLAGS_OPTIMIZE = -O6
93endif 103endif
94 104
95CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 105CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
96EXTLIBS = -lpthread -lrt -lelf -lm 106EXTLIBS = -lpthread -lrt -lelf -lm
97ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 107ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
98ALL_LDFLAGS = $(LDFLAGS) 108ALL_LDFLAGS = $(LDFLAGS)
@@ -178,9 +188,9 @@ strip-libs = $(filter-out -l%,$(1))
178 188
179$(OUTPUT)python/perf.so: $(PYRF_OBJS) 189$(OUTPUT)python/perf.so: $(PYRF_OBJS)
180 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ 190 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
181 --quiet build_ext \ 191 --quiet build_ext; \
182 --build-lib='$(OUTPUT)python' \ 192 mkdir -p $(OUTPUT)python && \
183 --build-temp='$(OUTPUT)python/temp' 193 cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/
184# 194#
185# No Perl scripts right now: 195# No Perl scripts right now:
186# 196#
@@ -279,6 +289,7 @@ LIB_H += util/thread.h
279LIB_H += util/thread_map.h 289LIB_H += util/thread_map.h
280LIB_H += util/trace-event.h 290LIB_H += util/trace-event.h
281LIB_H += util/probe-finder.h 291LIB_H += util/probe-finder.h
292LIB_H += util/dwarf-aux.h
282LIB_H += util/probe-event.h 293LIB_H += util/probe-event.h
283LIB_H += util/pstack.h 294LIB_H += util/pstack.h
284LIB_H += util/cpumap.h 295LIB_H += util/cpumap.h
@@ -435,6 +446,7 @@ else
435 BASIC_CFLAGS += -DDWARF_SUPPORT 446 BASIC_CFLAGS += -DDWARF_SUPPORT
436 EXTLIBS += -lelf -ldw 447 EXTLIBS += -lelf -ldw
437 LIB_OBJS += $(OUTPUT)util/probe-finder.o 448 LIB_OBJS += $(OUTPUT)util/probe-finder.o
449 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
438endif # PERF_HAVE_DWARF_REGS 450endif # PERF_HAVE_DWARF_REGS
439endif # NO_DWARF 451endif # NO_DWARF
440 452
@@ -504,9 +516,13 @@ else
504 516
505 PYTHON_WORD := $(call shell-wordify,$(PYTHON)) 517 PYTHON_WORD := $(call shell-wordify,$(PYTHON))
506 518
507 python-clean := $(PYTHON_WORD) util/setup.py clean \ 519 # python extension build directories
508 --build-lib='$(OUTPUT)python' \ 520 PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/
509 --build-temp='$(OUTPUT)python/temp' 521 PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/
522 PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/
523 export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP
524
525 python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so
510 526
511 ifdef NO_LIBPYTHON 527 ifdef NO_LIBPYTHON
512 $(call disable-python) 528 $(call disable-python)
@@ -863,6 +879,9 @@ install: all
863 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python' 879 $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'
864 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' 880 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
865 881
882install-python_ext:
883 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
884
866install-doc: 885install-doc:
867 $(MAKE) -C Documentation install 886 $(MAKE) -C Documentation install
868 887
@@ -890,7 +909,7 @@ quick-install-html:
890### Cleaning rules 909### Cleaning rules
891 910
892clean: 911clean:
893 $(RM) $(OUTPUT){*.o,*/*.o,*/*/*.o,*/*/*/*.o,$(LIB_FILE),perf-archive} 912 $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS)
894 $(RM) $(ALL_PROGRAMS) perf 913 $(RM) $(ALL_PROGRAMS) perf
895 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* 914 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
896 $(MAKE) -C Documentation/ clean 915 $(MAKE) -C Documentation/ clean
diff --git a/tools/perf/arch/arm/util/dwarf-regs.c b/tools/perf/arch/arm/util/dwarf-regs.c
index fff6450c8c9..e8d5c551c69 100644
--- a/tools/perf/arch/arm/util/dwarf-regs.c
+++ b/tools/perf/arch/arm/util/dwarf-regs.c
@@ -8,7 +8,10 @@
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10 10
11#include <stdlib.h>
12#ifndef __UCLIBC__
11#include <libio.h> 13#include <libio.h>
14#endif
12#include <dwarf-regs.h> 15#include <dwarf-regs.h>
13 16
14struct pt_regs_dwarfnum { 17struct pt_regs_dwarfnum {
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 7b139e1e7e8..555aefd7fe0 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -28,6 +28,8 @@
28#include "util/hist.h" 28#include "util/hist.h"
29#include "util/session.h" 29#include "util/session.h"
30 30
31#include <linux/bitmap.h>
32
31static char const *input_name = "perf.data"; 33static char const *input_name = "perf.data";
32 34
33static bool force, use_tui, use_stdio; 35static bool force, use_tui, use_stdio;
@@ -38,6 +40,9 @@ static bool print_line;
38 40
39static const char *sym_hist_filter; 41static const char *sym_hist_filter;
40 42
43static const char *cpu_list;
44static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
45
41static int perf_evlist__add_sample(struct perf_evlist *evlist, 46static int perf_evlist__add_sample(struct perf_evlist *evlist,
42 struct perf_sample *sample, 47 struct perf_sample *sample,
43 struct perf_evsel *evsel, 48 struct perf_evsel *evsel,
@@ -90,6 +95,9 @@ static int process_sample_event(union perf_event *event,
90 return -1; 95 return -1;
91 } 96 }
92 97
98 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
99 return 0;
100
93 if (!al.filtered && 101 if (!al.filtered &&
94 perf_evlist__add_sample(session->evlist, sample, evsel, &al)) { 102 perf_evlist__add_sample(session->evlist, sample, evsel, &al)) {
95 pr_warning("problem incrementing symbol count, " 103 pr_warning("problem incrementing symbol count, "
@@ -177,6 +185,12 @@ static int __cmd_annotate(void)
177 if (session == NULL) 185 if (session == NULL)
178 return -ENOMEM; 186 return -ENOMEM;
179 187
188 if (cpu_list) {
189 ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
190 if (ret)
191 goto out_delete;
192 }
193
180 ret = perf_session__process_events(session, &event_ops); 194 ret = perf_session__process_events(session, &event_ops);
181 if (ret) 195 if (ret)
182 goto out_delete; 196 goto out_delete;
@@ -252,6 +266,7 @@ static const struct option options[] = {
252 "print matching source lines (may be slow)"), 266 "print matching source lines (may be slow)"),
253 OPT_BOOLEAN('P', "full-paths", &full_paths, 267 OPT_BOOLEAN('P', "full-paths", &full_paths,
254 "Don't shorten the displayed pathnames"), 268 "Don't shorten the displayed pathnames"),
269 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
255 OPT_END() 270 OPT_END()
256}; 271};
257 272
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 9ac05aafd9b..899080ace26 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -942,10 +942,10 @@ static const char *record_args[] = {
942 "-f", 942 "-f",
943 "-m", "1024", 943 "-m", "1024",
944 "-c", "1", 944 "-c", "1",
945 "-e", "lock:lock_acquire:r", 945 "-e", "lock:lock_acquire",
946 "-e", "lock:lock_acquired:r", 946 "-e", "lock:lock_acquired",
947 "-e", "lock:lock_contended:r", 947 "-e", "lock:lock_contended",
948 "-e", "lock:lock_release:r", 948 "-e", "lock:lock_release",
949}; 949};
950 950
951static int __cmd_record(int argc, const char **argv) 951static int __cmd_record(int argc, const char **argv)
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 2c0e64d0b4a..710ae3d0a48 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -134,10 +134,18 @@ static int opt_show_lines(const struct option *opt __used,
134{ 134{
135 int ret = 0; 135 int ret = 0;
136 136
137 if (str) 137 if (!str)
138 ret = parse_line_range_desc(str, &params.line_range); 138 return 0;
139 INIT_LIST_HEAD(&params.line_range.line_list); 139
140 if (params.show_lines) {
141 pr_warning("Warning: more than one --line options are"
142 " detected. Only the first one is valid.\n");
143 return 0;
144 }
145
140 params.show_lines = true; 146 params.show_lines = true;
147 ret = parse_line_range_desc(str, &params.line_range);
148 INIT_LIST_HEAD(&params.line_range.line_list);
141 149
142 return ret; 150 return ret;
143} 151}
@@ -242,7 +250,8 @@ static const struct option options[] = {
242 OPT_STRING('s', "source", &symbol_conf.source_prefix, 250 OPT_STRING('s', "source", &symbol_conf.source_prefix,
243 "directory", "path to kernel source"), 251 "directory", "path to kernel source"),
244 OPT_STRING('m', "module", &params.target_module, 252 OPT_STRING('m', "module", &params.target_module,
245 "modname", "target module name"), 253 "modname|path",
254 "target module name (for online) or path (for offline)"),
246#endif 255#endif
247 OPT__DRY_RUN(&probe_event_dry_run), 256 OPT__DRY_RUN(&probe_event_dry_run),
248 OPT_INTEGER('\0', "max-probes", &params.max_probe_points, 257 OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8e2c8579818..f4c3fbee4ba 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -30,8 +30,6 @@
30#include <sched.h> 30#include <sched.h>
31#include <sys/mman.h> 31#include <sys/mman.h>
32 32
33#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
34
35enum write_mode_t { 33enum write_mode_t {
36 WRITE_FORCE, 34 WRITE_FORCE,
37 WRITE_APPEND 35 WRITE_APPEND
@@ -47,7 +45,7 @@ static int freq = 1000;
47static int output; 45static int output;
48static int pipe_output = 0; 46static int pipe_output = 0;
49static const char *output_name = NULL; 47static const char *output_name = NULL;
50static int group = 0; 48static bool group = false;
51static int realtime_prio = 0; 49static int realtime_prio = 0;
52static bool nodelay = false; 50static bool nodelay = false;
53static bool raw_samples = false; 51static bool raw_samples = false;
@@ -163,6 +161,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
163 struct perf_event_attr *attr = &evsel->attr; 161 struct perf_event_attr *attr = &evsel->attr;
164 int track = !evsel->idx; /* only the first counter needs these */ 162 int track = !evsel->idx; /* only the first counter needs these */
165 163
164 attr->disabled = 1;
166 attr->inherit = !no_inherit; 165 attr->inherit = !no_inherit;
167 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 166 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
168 PERF_FORMAT_TOTAL_TIME_RUNNING | 167 PERF_FORMAT_TOTAL_TIME_RUNNING |
@@ -438,7 +437,6 @@ static void mmap_read_all(void)
438 437
439static int __cmd_record(int argc, const char **argv) 438static int __cmd_record(int argc, const char **argv)
440{ 439{
441 int i;
442 struct stat st; 440 struct stat st;
443 int flags; 441 int flags;
444 int err; 442 int err;
@@ -674,6 +672,8 @@ static int __cmd_record(int argc, const char **argv)
674 } 672 }
675 } 673 }
676 674
675 perf_evlist__enable(evsel_list);
676
677 /* 677 /*
678 * Let the child rip 678 * Let the child rip
679 */ 679 */
@@ -682,7 +682,6 @@ static int __cmd_record(int argc, const char **argv)
682 682
683 for (;;) { 683 for (;;) {
684 int hits = samples; 684 int hits = samples;
685 int thread;
686 685
687 mmap_read_all(); 686 mmap_read_all();
688 687
@@ -693,19 +692,8 @@ static int __cmd_record(int argc, const char **argv)
693 waking++; 692 waking++;
694 } 693 }
695 694
696 if (done) { 695 if (done)
697 for (i = 0; i < evsel_list->cpus->nr; i++) { 696 perf_evlist__disable(evsel_list);
698 struct perf_evsel *pos;
699
700 list_for_each_entry(pos, &evsel_list->entries, node) {
701 for (thread = 0;
702 thread < evsel_list->threads->nr;
703 thread++)
704 ioctl(FD(pos, i, thread),
705 PERF_EVENT_IOC_DISABLE);
706 }
707 }
708 }
709 } 697 }
710 698
711 if (quiet || signr == SIGUSR1) 699 if (quiet || signr == SIGUSR1)
@@ -740,7 +728,7 @@ static bool force, append_file;
740const struct option record_options[] = { 728const struct option record_options[] = {
741 OPT_CALLBACK('e', "event", &evsel_list, "event", 729 OPT_CALLBACK('e', "event", &evsel_list, "event",
742 "event selector. use 'perf list' to list available events", 730 "event selector. use 'perf list' to list available events",
743 parse_events), 731 parse_events_option),
744 OPT_CALLBACK(0, "filter", &evsel_list, "filter", 732 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
745 "event filter", parse_filter), 733 "event filter", parse_filter),
746 OPT_INTEGER('p', "pid", &target_pid, 734 OPT_INTEGER('p', "pid", &target_pid,
@@ -768,6 +756,8 @@ const struct option record_options[] = {
768 "child tasks do not inherit counters"), 756 "child tasks do not inherit counters"),
769 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), 757 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
770 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 758 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
759 OPT_BOOLEAN(0, "group", &group,
760 "put the counters into a counter group"),
771 OPT_BOOLEAN('g', "call-graph", &call_graph, 761 OPT_BOOLEAN('g', "call-graph", &call_graph,
772 "do call-graph (stack chain/backtrace) recording"), 762 "do call-graph (stack chain/backtrace) recording"),
773 OPT_INCR('v', "verbose", &verbose, 763 OPT_INCR('v', "verbose", &verbose,
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 287a173523a..d7ff277bdb7 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -33,6 +33,8 @@
33#include "util/sort.h" 33#include "util/sort.h"
34#include "util/hist.h" 34#include "util/hist.h"
35 35
36#include <linux/bitmap.h>
37
36static char const *input_name = "perf.data"; 38static char const *input_name = "perf.data";
37 39
38static bool force, use_tui, use_stdio; 40static bool force, use_tui, use_stdio;
@@ -45,9 +47,13 @@ static struct perf_read_values show_threads_values;
45static const char default_pretty_printing_style[] = "normal"; 47static const char default_pretty_printing_style[] = "normal";
46static const char *pretty_printing_style = default_pretty_printing_style; 48static const char *pretty_printing_style = default_pretty_printing_style;
47 49
48static char callchain_default_opt[] = "fractal,0.5"; 50static char callchain_default_opt[] = "fractal,0.5,callee";
51static bool inverted_callchain;
49static symbol_filter_t annotate_init; 52static symbol_filter_t annotate_init;
50 53
54static const char *cpu_list;
55static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
56
51static int perf_session__add_hist_entry(struct perf_session *session, 57static int perf_session__add_hist_entry(struct perf_session *session,
52 struct addr_location *al, 58 struct addr_location *al,
53 struct perf_sample *sample, 59 struct perf_sample *sample,
@@ -116,6 +122,9 @@ static int process_sample_event(union perf_event *event,
116 if (al.filtered || (hide_unresolved && al.sym == NULL)) 122 if (al.filtered || (hide_unresolved && al.sym == NULL))
117 return 0; 123 return 0;
118 124
125 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
126 return 0;
127
119 if (al.map != NULL) 128 if (al.map != NULL)
120 al.map->dso->hit = 1; 129 al.map->dso->hit = 1;
121 130
@@ -153,23 +162,22 @@ static int perf_session__setup_sample_type(struct perf_session *self)
153{ 162{
154 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) { 163 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
155 if (sort__has_parent) { 164 if (sort__has_parent) {
156 fprintf(stderr, "selected --sort parent, but no" 165 ui__warning("Selected --sort parent, but no "
157 " callchain data. Did you call" 166 "callchain data. Did you call "
158 " perf record without -g?\n"); 167 "'perf record' without -g?\n");
159 return -EINVAL; 168 return -EINVAL;
160 } 169 }
161 if (symbol_conf.use_callchain) { 170 if (symbol_conf.use_callchain) {
162 fprintf(stderr, "selected -g but no callchain data." 171 ui__warning("Selected -g but no callchain data. Did "
163 " Did you call perf record without" 172 "you call 'perf record' without -g?\n");
164 " -g?\n");
165 return -1; 173 return -1;
166 } 174 }
167 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE && 175 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE &&
168 !symbol_conf.use_callchain) { 176 !symbol_conf.use_callchain) {
169 symbol_conf.use_callchain = true; 177 symbol_conf.use_callchain = true;
170 if (callchain_register_param(&callchain_param) < 0) { 178 if (callchain_register_param(&callchain_param) < 0) {
171 fprintf(stderr, "Can't register callchain" 179 ui__warning("Can't register callchain "
172 " params\n"); 180 "params.\n");
173 return -EINVAL; 181 return -EINVAL;
174 } 182 }
175 } 183 }
@@ -262,6 +270,12 @@ static int __cmd_report(void)
262 if (session == NULL) 270 if (session == NULL)
263 return -ENOMEM; 271 return -ENOMEM;
264 272
273 if (cpu_list) {
274 ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
275 if (ret)
276 goto out_delete;
277 }
278
265 if (show_threads) 279 if (show_threads)
266 perf_read_values_init(&show_threads_values); 280 perf_read_values_init(&show_threads_values);
267 281
@@ -386,13 +400,29 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
386 if (!tok) 400 if (!tok)
387 goto setup; 401 goto setup;
388 402
389 tok2 = strtok(NULL, ",");
390 callchain_param.min_percent = strtod(tok, &endptr); 403 callchain_param.min_percent = strtod(tok, &endptr);
391 if (tok == endptr) 404 if (tok == endptr)
392 return -1; 405 return -1;
393 406
394 if (tok2) 407 /* get the print limit */
408 tok2 = strtok(NULL, ",");
409 if (!tok2)
410 goto setup;
411
412 if (tok2[0] != 'c') {
395 callchain_param.print_limit = strtod(tok2, &endptr); 413 callchain_param.print_limit = strtod(tok2, &endptr);
414 tok2 = strtok(NULL, ",");
415 if (!tok2)
416 goto setup;
417 }
418
419 /* get the call chain order */
420 if (!strcmp(tok2, "caller"))
421 callchain_param.order = ORDER_CALLER;
422 else if (!strcmp(tok2, "callee"))
423 callchain_param.order = ORDER_CALLEE;
424 else
425 return -1;
396setup: 426setup:
397 if (callchain_register_param(&callchain_param) < 0) { 427 if (callchain_register_param(&callchain_param) < 0) {
398 fprintf(stderr, "Can't register callchain params\n"); 428 fprintf(stderr, "Can't register callchain params\n");
@@ -436,9 +466,10 @@ static const struct option options[] = {
436 "regex filter to identify parent, see: '--sort parent'"), 466 "regex filter to identify parent, see: '--sort parent'"),
437 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 467 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
438 "Only display entries with parent-match"), 468 "Only display entries with parent-match"),
439 OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent", 469 OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent, call_order",
440 "Display callchains using output_type (graph, flat, fractal, or none) and min percent threshold. " 470 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. "
441 "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt), 471 "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt),
472 OPT_BOOLEAN('G', "inverted", &inverted_callchain, "alias for inverted call graph"),
442 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 473 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
443 "only consider symbols in these dsos"), 474 "only consider symbols in these dsos"),
444 OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 475 OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
@@ -455,6 +486,7 @@ static const struct option options[] = {
455 "Only display entries resolved to a symbol"), 486 "Only display entries resolved to a symbol"),
456 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 487 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
457 "Look for files with symbols relative to this directory"), 488 "Look for files with symbols relative to this directory"),
489 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
458 OPT_END() 490 OPT_END()
459}; 491};
460 492
@@ -467,6 +499,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
467 else if (use_tui) 499 else if (use_tui)
468 use_browser = 1; 500 use_browser = 1;
469 501
502 if (inverted_callchain)
503 callchain_param.order = ORDER_CALLER;
504
470 if (strcmp(input_name, "-") != 0) 505 if (strcmp(input_name, "-") != 0)
471 setup_browser(true); 506 setup_browser(true);
472 else 507 else
@@ -504,7 +539,14 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
504 if (parent_pattern != default_parent_pattern) { 539 if (parent_pattern != default_parent_pattern) {
505 if (sort_dimension__add("parent") < 0) 540 if (sort_dimension__add("parent") < 0)
506 return -1; 541 return -1;
507 sort_parent.elide = 1; 542
543 /*
544 * Only show the parent fields if we explicitly
545 * sort that way. If we only use parent machinery
546 * for filtering, we don't want it.
547 */
548 if (!strstr(sort_order, "parent"))
549 sort_parent.elide = 1;
508 } else 550 } else
509 symbol_conf.exclude_other = false; 551 symbol_conf.exclude_other = false;
510 552
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index dcfe8873c9a..5177964943e 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1637,23 +1637,29 @@ static struct perf_event_ops event_ops = {
1637 .ordered_samples = true, 1637 .ordered_samples = true,
1638}; 1638};
1639 1639
1640static int read_events(void) 1640static void read_events(bool destroy, struct perf_session **psession)
1641{ 1641{
1642 int err = -EINVAL; 1642 int err = -EINVAL;
1643 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 1643 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
1644 0, false, &event_ops); 1644 0, false, &event_ops);
1645 if (session == NULL) 1645 if (session == NULL)
1646 return -ENOMEM; 1646 die("No Memory");
1647 1647
1648 if (perf_session__has_traces(session, "record -R")) { 1648 if (perf_session__has_traces(session, "record -R")) {
1649 err = perf_session__process_events(session, &event_ops); 1649 err = perf_session__process_events(session, &event_ops);
1650 if (err)
1651 die("Failed to process events, error %d", err);
1652
1650 nr_events = session->hists.stats.nr_events[0]; 1653 nr_events = session->hists.stats.nr_events[0];
1651 nr_lost_events = session->hists.stats.total_lost; 1654 nr_lost_events = session->hists.stats.total_lost;
1652 nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST]; 1655 nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST];
1653 } 1656 }
1654 1657
1655 perf_session__delete(session); 1658 if (destroy)
1656 return err; 1659 perf_session__delete(session);
1660
1661 if (psession)
1662 *psession = session;
1657} 1663}
1658 1664
1659static void print_bad_events(void) 1665static void print_bad_events(void)
@@ -1689,9 +1695,10 @@ static void print_bad_events(void)
1689static void __cmd_lat(void) 1695static void __cmd_lat(void)
1690{ 1696{
1691 struct rb_node *next; 1697 struct rb_node *next;
1698 struct perf_session *session;
1692 1699
1693 setup_pager(); 1700 setup_pager();
1694 read_events(); 1701 read_events(false, &session);
1695 sort_lat(); 1702 sort_lat();
1696 1703
1697 printf("\n ---------------------------------------------------------------------------------------------------------------\n"); 1704 printf("\n ---------------------------------------------------------------------------------------------------------------\n");
@@ -1717,6 +1724,7 @@ static void __cmd_lat(void)
1717 print_bad_events(); 1724 print_bad_events();
1718 printf("\n"); 1725 printf("\n");
1719 1726
1727 perf_session__delete(session);
1720} 1728}
1721 1729
1722static struct trace_sched_handler map_ops = { 1730static struct trace_sched_handler map_ops = {
@@ -1731,7 +1739,7 @@ static void __cmd_map(void)
1731 max_cpu = sysconf(_SC_NPROCESSORS_CONF); 1739 max_cpu = sysconf(_SC_NPROCESSORS_CONF);
1732 1740
1733 setup_pager(); 1741 setup_pager();
1734 read_events(); 1742 read_events(true, NULL);
1735 print_bad_events(); 1743 print_bad_events();
1736} 1744}
1737 1745
@@ -1744,7 +1752,7 @@ static void __cmd_replay(void)
1744 1752
1745 test_calibrations(); 1753 test_calibrations();
1746 1754
1747 read_events(); 1755 read_events(true, NULL);
1748 1756
1749 printf("nr_run_events: %ld\n", nr_run_events); 1757 printf("nr_run_events: %ld\n", nr_run_events);
1750 printf("nr_sleep_events: %ld\n", nr_sleep_events); 1758 printf("nr_sleep_events: %ld\n", nr_sleep_events);
@@ -1769,7 +1777,7 @@ static void __cmd_replay(void)
1769 1777
1770 1778
1771static const char * const sched_usage[] = { 1779static const char * const sched_usage[] = {
1772 "perf sched [<options>] {record|latency|map|replay|trace}", 1780 "perf sched [<options>] {record|latency|map|replay|script}",
1773 NULL 1781 NULL
1774}; 1782};
1775 1783
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 22747de7234..09024ec2ab2 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -13,6 +13,7 @@
13#include "util/util.h" 13#include "util/util.h"
14#include "util/evlist.h" 14#include "util/evlist.h"
15#include "util/evsel.h" 15#include "util/evsel.h"
16#include <linux/bitmap.h>
16 17
17static char const *script_name; 18static char const *script_name;
18static char const *generate_script_lang; 19static char const *generate_script_lang;
@@ -21,6 +22,8 @@ static u64 last_timestamp;
21static u64 nr_unordered; 22static u64 nr_unordered;
22extern const struct option record_options[]; 23extern const struct option record_options[];
23static bool no_callchain; 24static bool no_callchain;
25static const char *cpu_list;
26static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
24 27
25enum perf_output_field { 28enum perf_output_field {
26 PERF_OUTPUT_COMM = 1U << 0, 29 PERF_OUTPUT_COMM = 1U << 0,
@@ -30,7 +33,10 @@ enum perf_output_field {
30 PERF_OUTPUT_CPU = 1U << 4, 33 PERF_OUTPUT_CPU = 1U << 4,
31 PERF_OUTPUT_EVNAME = 1U << 5, 34 PERF_OUTPUT_EVNAME = 1U << 5,
32 PERF_OUTPUT_TRACE = 1U << 6, 35 PERF_OUTPUT_TRACE = 1U << 6,
33 PERF_OUTPUT_SYM = 1U << 7, 36 PERF_OUTPUT_IP = 1U << 7,
37 PERF_OUTPUT_SYM = 1U << 8,
38 PERF_OUTPUT_DSO = 1U << 9,
39 PERF_OUTPUT_ADDR = 1U << 10,
34}; 40};
35 41
36struct output_option { 42struct output_option {
@@ -44,7 +50,10 @@ struct output_option {
44 {.str = "cpu", .field = PERF_OUTPUT_CPU}, 50 {.str = "cpu", .field = PERF_OUTPUT_CPU},
45 {.str = "event", .field = PERF_OUTPUT_EVNAME}, 51 {.str = "event", .field = PERF_OUTPUT_EVNAME},
46 {.str = "trace", .field = PERF_OUTPUT_TRACE}, 52 {.str = "trace", .field = PERF_OUTPUT_TRACE},
53 {.str = "ip", .field = PERF_OUTPUT_IP},
47 {.str = "sym", .field = PERF_OUTPUT_SYM}, 54 {.str = "sym", .field = PERF_OUTPUT_SYM},
55 {.str = "dso", .field = PERF_OUTPUT_DSO},
56 {.str = "addr", .field = PERF_OUTPUT_ADDR},
48}; 57};
49 58
50/* default set to maintain compatibility with current format */ 59/* default set to maintain compatibility with current format */
@@ -60,7 +69,8 @@ static struct {
60 69
61 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 70 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
62 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 71 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
63 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 72 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
73 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
64 74
65 .invalid_fields = PERF_OUTPUT_TRACE, 75 .invalid_fields = PERF_OUTPUT_TRACE,
66 }, 76 },
@@ -70,7 +80,8 @@ static struct {
70 80
71 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 81 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
72 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 82 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
73 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 83 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
84 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
74 85
75 .invalid_fields = PERF_OUTPUT_TRACE, 86 .invalid_fields = PERF_OUTPUT_TRACE,
76 }, 87 },
@@ -88,7 +99,8 @@ static struct {
88 99
89 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 100 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
90 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 101 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
91 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 102 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
103 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
92 104
93 .invalid_fields = PERF_OUTPUT_TRACE, 105 .invalid_fields = PERF_OUTPUT_TRACE,
94 }, 106 },
@@ -157,9 +169,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
157 !perf_session__has_traces(session, "record -R")) 169 !perf_session__has_traces(session, "record -R"))
158 return -EINVAL; 170 return -EINVAL;
159 171
160 if (PRINT_FIELD(SYM)) { 172 if (PRINT_FIELD(IP)) {
161 if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP", 173 if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP",
162 PERF_OUTPUT_SYM)) 174 PERF_OUTPUT_IP))
163 return -EINVAL; 175 return -EINVAL;
164 176
165 if (!no_callchain && 177 if (!no_callchain &&
@@ -167,6 +179,24 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
167 symbol_conf.use_callchain = false; 179 symbol_conf.use_callchain = false;
168 } 180 }
169 181
182 if (PRINT_FIELD(ADDR) &&
183 perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR",
184 PERF_OUTPUT_ADDR))
185 return -EINVAL;
186
187 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
188 pr_err("Display of symbols requested but neither sample IP nor "
189 "sample address\nis selected. Hence, no addresses to convert "
190 "to symbols.\n");
191 return -EINVAL;
192 }
193 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
194 pr_err("Display of DSO requested but neither sample IP nor "
195 "sample address\nis selected. Hence, no addresses to convert "
196 "to DSO.\n");
197 return -EINVAL;
198 }
199
170 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && 200 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
171 perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID", 201 perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID",
172 PERF_OUTPUT_TID|PERF_OUTPUT_PID)) 202 PERF_OUTPUT_TID|PERF_OUTPUT_PID))
@@ -230,7 +260,7 @@ static void print_sample_start(struct perf_sample *sample,
230 if (PRINT_FIELD(COMM)) { 260 if (PRINT_FIELD(COMM)) {
231 if (latency_format) 261 if (latency_format)
232 printf("%8.8s ", thread->comm); 262 printf("%8.8s ", thread->comm);
233 else if (PRINT_FIELD(SYM) && symbol_conf.use_callchain) 263 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain)
234 printf("%s ", thread->comm); 264 printf("%s ", thread->comm);
235 else 265 else
236 printf("%16s ", thread->comm); 266 printf("%16s ", thread->comm);
@@ -271,6 +301,63 @@ static void print_sample_start(struct perf_sample *sample,
271 } 301 }
272} 302}
273 303
304static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
305{
306 if ((attr->type == PERF_TYPE_SOFTWARE) &&
307 ((attr->config == PERF_COUNT_SW_PAGE_FAULTS) ||
308 (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN) ||
309 (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
310 return true;
311
312 return false;
313}
314
315static void print_sample_addr(union perf_event *event,
316 struct perf_sample *sample,
317 struct perf_session *session,
318 struct thread *thread,
319 struct perf_event_attr *attr)
320{
321 struct addr_location al;
322 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
323 const char *symname, *dsoname;
324
325 printf("%16" PRIx64, sample->addr);
326
327 if (!sample_addr_correlates_sym(attr))
328 return;
329
330 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
331 event->ip.pid, sample->addr, &al);
332 if (!al.map)
333 thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE,
334 event->ip.pid, sample->addr, &al);
335
336 al.cpu = sample->cpu;
337 al.sym = NULL;
338
339 if (al.map)
340 al.sym = map__find_symbol(al.map, al.addr, NULL);
341
342 if (PRINT_FIELD(SYM)) {
343 if (al.sym && al.sym->name)
344 symname = al.sym->name;
345 else
346 symname = "";
347
348 printf(" %16s", symname);
349 }
350
351 if (PRINT_FIELD(DSO)) {
352 if (al.map && al.map->dso && al.map->dso->name)
353 dsoname = al.map->dso->name;
354 else
355 dsoname = "";
356
357 printf(" (%s)", dsoname);
358 }
359}
360
274static void process_event(union perf_event *event __unused, 361static void process_event(union perf_event *event __unused,
275 struct perf_sample *sample, 362 struct perf_sample *sample,
276 struct perf_evsel *evsel, 363 struct perf_evsel *evsel,
@@ -288,12 +375,16 @@ static void process_event(union perf_event *event __unused,
288 print_trace_event(sample->cpu, sample->raw_data, 375 print_trace_event(sample->cpu, sample->raw_data,
289 sample->raw_size); 376 sample->raw_size);
290 377
291 if (PRINT_FIELD(SYM)) { 378 if (PRINT_FIELD(ADDR))
379 print_sample_addr(event, sample, session, thread, attr);
380
381 if (PRINT_FIELD(IP)) {
292 if (!symbol_conf.use_callchain) 382 if (!symbol_conf.use_callchain)
293 printf(" "); 383 printf(" ");
294 else 384 else
295 printf("\n"); 385 printf("\n");
296 perf_session__print_symbols(event, sample, session); 386 perf_session__print_ip(event, sample, session,
387 PRINT_FIELD(SYM), PRINT_FIELD(DSO));
297 } 388 }
298 389
299 printf("\n"); 390 printf("\n");
@@ -365,6 +456,10 @@ static int process_sample_event(union perf_event *event,
365 last_timestamp = sample->time; 456 last_timestamp = sample->time;
366 return 0; 457 return 0;
367 } 458 }
459
460 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
461 return 0;
462
368 scripting_ops->process_event(event, sample, evsel, session, thread); 463 scripting_ops->process_event(event, sample, evsel, session, thread);
369 464
370 session->hists.stats.total_period += sample->period; 465 session->hists.stats.total_period += sample->period;
@@ -985,8 +1080,9 @@ static const struct option options[] = {
985 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1080 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
986 "Look for files with symbols relative to this directory"), 1081 "Look for files with symbols relative to this directory"),
987 OPT_CALLBACK('f', "fields", NULL, "str", 1082 OPT_CALLBACK('f', "fields", NULL, "str",
988 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,sym", 1083 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr",
989 parse_output_fields), 1084 parse_output_fields),
1085 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
990 1086
991 OPT_END() 1087 OPT_END()
992}; 1088};
@@ -1167,6 +1263,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1167 if (session == NULL) 1263 if (session == NULL)
1168 return -ENOMEM; 1264 return -ENOMEM;
1169 1265
1266 if (cpu_list) {
1267 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap))
1268 return -1;
1269 }
1270
1170 if (!no_callchain) 1271 if (!no_callchain)
1171 symbol_conf.use_callchain = true; 1272 symbol_conf.use_callchain = true;
1172 else 1273 else
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a9f06715e44..5deb17d9e79 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -61,6 +61,8 @@
61#include <locale.h> 61#include <locale.h>
62 62
63#define DEFAULT_SEPARATOR " " 63#define DEFAULT_SEPARATOR " "
64#define CNTR_NOT_SUPPORTED "<not supported>"
65#define CNTR_NOT_COUNTED "<not counted>"
64 66
65static struct perf_event_attr default_attrs[] = { 67static struct perf_event_attr default_attrs[] = {
66 68
@@ -191,6 +193,7 @@ static int big_num_opt = -1;
191static const char *cpu_list; 193static const char *cpu_list;
192static const char *csv_sep = NULL; 194static const char *csv_sep = NULL;
193static bool csv_output = false; 195static bool csv_output = false;
196static bool group = false;
194 197
195static volatile int done = 0; 198static volatile int done = 0;
196 199
@@ -278,14 +281,14 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
278 attr->inherit = !no_inherit; 281 attr->inherit = !no_inherit;
279 282
280 if (system_wide) 283 if (system_wide)
281 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false); 284 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, group);
282 285
283 if (target_pid == -1 && target_tid == -1) { 286 if (target_pid == -1 && target_tid == -1) {
284 attr->disabled = 1; 287 attr->disabled = 1;
285 attr->enable_on_exec = 1; 288 attr->enable_on_exec = 1;
286 } 289 }
287 290
288 return perf_evsel__open_per_thread(evsel, evsel_list->threads, false); 291 return perf_evsel__open_per_thread(evsel, evsel_list->threads, group);
289} 292}
290 293
291/* 294/*
@@ -448,6 +451,7 @@ static int run_perf_stat(int argc __used, const char **argv)
448 if (verbose) 451 if (verbose)
449 ui__warning("%s event is not supported by the kernel.\n", 452 ui__warning("%s event is not supported by the kernel.\n",
450 event_name(counter)); 453 event_name(counter));
454 counter->supported = false;
451 continue; 455 continue;
452 } 456 }
453 457
@@ -466,6 +470,7 @@ static int run_perf_stat(int argc __used, const char **argv)
466 die("Not all events could be opened.\n"); 470 die("Not all events could be opened.\n");
467 return -1; 471 return -1;
468 } 472 }
473 counter->supported = true;
469 } 474 }
470 475
471 if (perf_evlist__set_filters(evsel_list)) { 476 if (perf_evlist__set_filters(evsel_list)) {
@@ -513,7 +518,10 @@ static void print_noise_pct(double total, double avg)
513 if (avg) 518 if (avg)
514 pct = 100.0*total/avg; 519 pct = 100.0*total/avg;
515 520
516 fprintf(stderr, " ( +-%6.2f%% )", pct); 521 if (csv_output)
522 fprintf(stderr, "%s%.2f%%", csv_sep, pct);
523 else
524 fprintf(stderr, " ( +-%6.2f%% )", pct);
517} 525}
518 526
519static void print_noise(struct perf_evsel *evsel, double avg) 527static void print_noise(struct perf_evsel *evsel, double avg)
@@ -861,7 +869,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
861 if (scaled == -1) { 869 if (scaled == -1) {
862 fprintf(stderr, "%*s%s%*s", 870 fprintf(stderr, "%*s%s%*s",
863 csv_output ? 0 : 18, 871 csv_output ? 0 : 18,
864 "<not counted>", 872 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
865 csv_sep, 873 csv_sep,
866 csv_output ? 0 : -24, 874 csv_output ? 0 : -24,
867 event_name(counter)); 875 event_name(counter));
@@ -878,13 +886,13 @@ static void print_counter_aggr(struct perf_evsel *counter)
878 else 886 else
879 abs_printout(-1, counter, avg); 887 abs_printout(-1, counter, avg);
880 888
889 print_noise(counter, avg);
890
881 if (csv_output) { 891 if (csv_output) {
882 fputc('\n', stderr); 892 fputc('\n', stderr);
883 return; 893 return;
884 } 894 }
885 895
886 print_noise(counter, avg);
887
888 if (scaled) { 896 if (scaled) {
889 double avg_enabled, avg_running; 897 double avg_enabled, avg_running;
890 898
@@ -914,7 +922,8 @@ static void print_counter(struct perf_evsel *counter)
914 csv_output ? 0 : -4, 922 csv_output ? 0 : -4,
915 evsel_list->cpus->map[cpu], csv_sep, 923 evsel_list->cpus->map[cpu], csv_sep,
916 csv_output ? 0 : 18, 924 csv_output ? 0 : 18,
917 "<not counted>", csv_sep, 925 counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
926 csv_sep,
918 csv_output ? 0 : -24, 927 csv_output ? 0 : -24,
919 event_name(counter)); 928 event_name(counter));
920 929
@@ -1024,7 +1033,7 @@ static int stat__set_big_num(const struct option *opt __used,
1024static const struct option options[] = { 1033static const struct option options[] = {
1025 OPT_CALLBACK('e', "event", &evsel_list, "event", 1034 OPT_CALLBACK('e', "event", &evsel_list, "event",
1026 "event selector. use 'perf list' to list available events", 1035 "event selector. use 'perf list' to list available events",
1027 parse_events), 1036 parse_events_option),
1028 OPT_CALLBACK(0, "filter", &evsel_list, "filter", 1037 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
1029 "event filter", parse_filter), 1038 "event filter", parse_filter),
1030 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 1039 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
@@ -1035,6 +1044,8 @@ static const struct option options[] = {
1035 "stat events on existing thread id"), 1044 "stat events on existing thread id"),
1036 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1045 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1037 "system-wide collection from all CPUs"), 1046 "system-wide collection from all CPUs"),
1047 OPT_BOOLEAN('g', "group", &group,
1048 "put the counters into a counter group"),
1038 OPT_BOOLEAN('c', "scale", &scale, 1049 OPT_BOOLEAN('c', "scale", &scale,
1039 "scale/normalize counters"), 1050 "scale/normalize counters"),
1040 OPT_INCR('v', "verbose", &verbose, 1051 OPT_INCR('v', "verbose", &verbose,
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 2da9162262b..efe696f936e 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -12,6 +12,7 @@
12#include "util/parse-events.h" 12#include "util/parse-events.h"
13#include "util/symbol.h" 13#include "util/symbol.h"
14#include "util/thread_map.h" 14#include "util/thread_map.h"
15#include "../../include/linux/hw_breakpoint.h"
15 16
16static long page_size; 17static long page_size;
17 18
@@ -245,8 +246,8 @@ static int trace_event__id(const char *evname)
245 int err = -1, fd; 246 int err = -1, fd;
246 247
247 if (asprintf(&filename, 248 if (asprintf(&filename,
248 "/sys/kernel/debug/tracing/events/syscalls/%s/id", 249 "%s/syscalls/%s/id",
249 evname) < 0) 250 debugfs_path, evname) < 0)
250 return -1; 251 return -1;
251 252
252 fd = open(filename, O_RDONLY); 253 fd = open(filename, O_RDONLY);
@@ -560,7 +561,7 @@ static int test__basic_mmap(void)
560 } 561 }
561 562
562 err = perf_event__parse_sample(event, attr.sample_type, sample_size, 563 err = perf_event__parse_sample(event, attr.sample_type, sample_size,
563 false, &sample); 564 false, &sample, false);
564 if (err) { 565 if (err) {
565 pr_err("Can't parse sample, err = %d\n", err); 566 pr_err("Can't parse sample, err = %d\n", err);
566 goto out_munmap; 567 goto out_munmap;
@@ -600,6 +601,246 @@ out_free_threads:
600#undef nsyscalls 601#undef nsyscalls
601} 602}
602 603
604#define TEST_ASSERT_VAL(text, cond) \
605do { \
606 if (!cond) { \
607 pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
608 return -1; \
609 } \
610} while (0)
611
612static int test__checkevent_tracepoint(struct perf_evlist *evlist)
613{
614 struct perf_evsel *evsel = list_entry(evlist->entries.next,
615 struct perf_evsel, node);
616
617 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
618 TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
619 TEST_ASSERT_VAL("wrong sample_type",
620 (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
621 evsel->attr.sample_type);
622 TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
623 return 0;
624}
625
626static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
627{
628 struct perf_evsel *evsel;
629
630 TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
631
632 list_for_each_entry(evsel, &evlist->entries, node) {
633 TEST_ASSERT_VAL("wrong type",
634 PERF_TYPE_TRACEPOINT == evsel->attr.type);
635 TEST_ASSERT_VAL("wrong sample_type",
636 (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU)
637 == evsel->attr.sample_type);
638 TEST_ASSERT_VAL("wrong sample_period",
639 1 == evsel->attr.sample_period);
640 }
641 return 0;
642}
643
644static int test__checkevent_raw(struct perf_evlist *evlist)
645{
646 struct perf_evsel *evsel = list_entry(evlist->entries.next,
647 struct perf_evsel, node);
648
649 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
650 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
651 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
652 return 0;
653}
654
655static int test__checkevent_numeric(struct perf_evlist *evlist)
656{
657 struct perf_evsel *evsel = list_entry(evlist->entries.next,
658 struct perf_evsel, node);
659
660 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
661 TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type);
662 TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config);
663 return 0;
664}
665
666static int test__checkevent_symbolic_name(struct perf_evlist *evlist)
667{
668 struct perf_evsel *evsel = list_entry(evlist->entries.next,
669 struct perf_evsel, node);
670
671 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
672 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
673 TEST_ASSERT_VAL("wrong config",
674 PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
675 return 0;
676}
677
678static int test__checkevent_symbolic_alias(struct perf_evlist *evlist)
679{
680 struct perf_evsel *evsel = list_entry(evlist->entries.next,
681 struct perf_evsel, node);
682
683 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
684 TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type);
685 TEST_ASSERT_VAL("wrong config",
686 PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config);
687 return 0;
688}
689
690static int test__checkevent_genhw(struct perf_evlist *evlist)
691{
692 struct perf_evsel *evsel = list_entry(evlist->entries.next,
693 struct perf_evsel, node);
694
695 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
696 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type);
697 TEST_ASSERT_VAL("wrong config", (1 << 16) == evsel->attr.config);
698 return 0;
699}
700
701static int test__checkevent_breakpoint(struct perf_evlist *evlist)
702{
703 struct perf_evsel *evsel = list_entry(evlist->entries.next,
704 struct perf_evsel, node);
705
706 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
707 TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
708 TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
709 TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) ==
710 evsel->attr.bp_type);
711 TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_4 ==
712 evsel->attr.bp_len);
713 return 0;
714}
715
716static int test__checkevent_breakpoint_x(struct perf_evlist *evlist)
717{
718 struct perf_evsel *evsel = list_entry(evlist->entries.next,
719 struct perf_evsel, node);
720
721 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
722 TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type);
723 TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
724 TEST_ASSERT_VAL("wrong bp_type",
725 HW_BREAKPOINT_X == evsel->attr.bp_type);
726 TEST_ASSERT_VAL("wrong bp_len", sizeof(long) == evsel->attr.bp_len);
727 return 0;
728}
729
730static int test__checkevent_breakpoint_r(struct perf_evlist *evlist)
731{
732 struct perf_evsel *evsel = list_entry(evlist->entries.next,
733 struct perf_evsel, node);
734
735 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
736 TEST_ASSERT_VAL("wrong type",
737 PERF_TYPE_BREAKPOINT == evsel->attr.type);
738 TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
739 TEST_ASSERT_VAL("wrong bp_type",
740 HW_BREAKPOINT_R == evsel->attr.bp_type);
741 TEST_ASSERT_VAL("wrong bp_len",
742 HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
743 return 0;
744}
745
746static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
747{
748 struct perf_evsel *evsel = list_entry(evlist->entries.next,
749 struct perf_evsel, node);
750
751 TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
752 TEST_ASSERT_VAL("wrong type",
753 PERF_TYPE_BREAKPOINT == evsel->attr.type);
754 TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
755 TEST_ASSERT_VAL("wrong bp_type",
756 HW_BREAKPOINT_W == evsel->attr.bp_type);
757 TEST_ASSERT_VAL("wrong bp_len",
758 HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
759 return 0;
760}
761
762static struct test__event_st {
763 const char *name;
764 __u32 type;
765 int (*check)(struct perf_evlist *evlist);
766} test__events[] = {
767 {
768 .name = "syscalls:sys_enter_open",
769 .check = test__checkevent_tracepoint,
770 },
771 {
772 .name = "syscalls:*",
773 .check = test__checkevent_tracepoint_multi,
774 },
775 {
776 .name = "r1",
777 .check = test__checkevent_raw,
778 },
779 {
780 .name = "1:1",
781 .check = test__checkevent_numeric,
782 },
783 {
784 .name = "instructions",
785 .check = test__checkevent_symbolic_name,
786 },
787 {
788 .name = "faults",
789 .check = test__checkevent_symbolic_alias,
790 },
791 {
792 .name = "L1-dcache-load-miss",
793 .check = test__checkevent_genhw,
794 },
795 {
796 .name = "mem:0",
797 .check = test__checkevent_breakpoint,
798 },
799 {
800 .name = "mem:0:x",
801 .check = test__checkevent_breakpoint_x,
802 },
803 {
804 .name = "mem:0:r",
805 .check = test__checkevent_breakpoint_r,
806 },
807 {
808 .name = "mem:0:w",
809 .check = test__checkevent_breakpoint_w,
810 },
811};
812
813#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
814
815static int test__parse_events(void)
816{
817 struct perf_evlist *evlist;
818 u_int i;
819 int ret = 0;
820
821 for (i = 0; i < TEST__EVENTS_CNT; i++) {
822 struct test__event_st *e = &test__events[i];
823
824 evlist = perf_evlist__new(NULL, NULL);
825 if (evlist == NULL)
826 break;
827
828 ret = parse_events(evlist, e->name, 0);
829 if (ret) {
830 pr_debug("failed to parse event '%s', err %d\n",
831 e->name, ret);
832 break;
833 }
834
835 ret = e->check(evlist);
836 if (ret)
837 break;
838
839 perf_evlist__delete(evlist);
840 }
841
842 return ret;
843}
603static struct test { 844static struct test {
604 const char *desc; 845 const char *desc;
605 int (*func)(void); 846 int (*func)(void);
@@ -621,6 +862,10 @@ static struct test {
621 .func = test__basic_mmap, 862 .func = test__basic_mmap,
622 }, 863 },
623 { 864 {
865 .desc = "parse events tests",
866 .func = test__parse_events,
867 },
868 {
624 .func = NULL, 869 .func = NULL,
625 }, 870 },
626}; 871};
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index f2f3f4937aa..d28013b7d61 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -191,7 +191,8 @@ static void __zero_source_counters(struct sym_entry *syme)
191 symbol__annotate_zero_histograms(sym); 191 symbol__annotate_zero_histograms(sym);
192} 192}
193 193
194static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) 194static void record_precise_ip(struct sym_entry *syme, struct map *map,
195 int counter, u64 ip)
195{ 196{
196 struct annotation *notes; 197 struct annotation *notes;
197 struct symbol *sym; 198 struct symbol *sym;
@@ -205,8 +206,8 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
205 if (pthread_mutex_trylock(&notes->lock)) 206 if (pthread_mutex_trylock(&notes->lock))
206 return; 207 return;
207 208
208 ip = syme->map->map_ip(syme->map, ip); 209 ip = map->map_ip(map, ip);
209 symbol__inc_addr_samples(sym, syme->map, counter, ip); 210 symbol__inc_addr_samples(sym, map, counter, ip);
210 211
211 pthread_mutex_unlock(&notes->lock); 212 pthread_mutex_unlock(&notes->lock);
212} 213}
@@ -810,7 +811,7 @@ static void perf_event__process_sample(const union perf_event *event,
810 evsel = perf_evlist__id2evsel(top.evlist, sample->id); 811 evsel = perf_evlist__id2evsel(top.evlist, sample->id);
811 assert(evsel != NULL); 812 assert(evsel != NULL);
812 syme->count[evsel->idx]++; 813 syme->count[evsel->idx]++;
813 record_precise_ip(syme, evsel->idx, ip); 814 record_precise_ip(syme, al.map, evsel->idx, ip);
814 pthread_mutex_lock(&top.active_symbols_lock); 815 pthread_mutex_lock(&top.active_symbols_lock);
815 if (list_empty(&syme->node) || !syme->node.next) { 816 if (list_empty(&syme->node) || !syme->node.next) {
816 static bool first = true; 817 static bool first = true;
@@ -990,7 +991,7 @@ static const char * const top_usage[] = {
990static const struct option options[] = { 991static const struct option options[] = {
991 OPT_CALLBACK('e', "event", &top.evlist, "event", 992 OPT_CALLBACK('e', "event", &top.evlist, "event",
992 "event selector. use 'perf list' to list available events", 993 "event selector. use 'perf list' to list available events",
993 parse_events), 994 parse_events_option),
994 OPT_INTEGER('c', "count", &default_interval, 995 OPT_INTEGER('c', "count", &default_interval,
995 "event period to sample"), 996 "event period to sample"),
996 OPT_INTEGER('p', "pid", &top.target_pid, 997 OPT_INTEGER('p', "pid", &top.target_pid,
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
new file mode 100644
index 00000000000..0d1cdbee2f5
--- /dev/null
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -0,0 +1,230 @@
1#include <linux/compiler.h>
2#include <linux/rbtree.h>
3#include <string.h>
4#include "map.h"
5#include "symbol.h"
6#include "util.h"
7#include "tests.h"
8#include "debug.h"
9#include "machine.h"
10
11static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused,
12 struct symbol *sym)
13{
14 bool *visited = symbol__priv(sym);
15 *visited = true;
16 return 0;
17}
18
19int test__vmlinux_matches_kallsyms(void)
20{
21 int err = -1;
22 struct rb_node *nd;
23 struct symbol *sym;
24 struct map *kallsyms_map, *vmlinux_map;
25 struct machine kallsyms, vmlinux;
26 enum map_type type = MAP__FUNCTION;
27 struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
28
29 /*
30 * Step 1:
31 *
32 * Init the machines that will hold kernel, modules obtained from
33 * both vmlinux + .ko files and from /proc/kallsyms split by modules.
34 */
35 machine__init(&kallsyms, "", HOST_KERNEL_ID);
36 machine__init(&vmlinux, "", HOST_KERNEL_ID);
37
38 /*
39 * Step 2:
40 *
41 * Create the kernel maps for kallsyms and the DSO where we will then
42 * load /proc/kallsyms. Also create the modules maps from /proc/modules
43 * and find the .ko files that match them in /lib/modules/`uname -r`/.
44 */
45 if (machine__create_kernel_maps(&kallsyms) < 0) {
46 pr_debug("machine__create_kernel_maps ");
47 return -1;
48 }
49
50 /*
51 * Step 3:
52 *
53 * Load and split /proc/kallsyms into multiple maps, one per module.
54 */
55 if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) {
56 pr_debug("dso__load_kallsyms ");
57 goto out;
58 }
59
60 /*
61 * Step 4:
62 *
63 * kallsyms will be internally on demand sorted by name so that we can
64 * find the reference relocation * symbol, i.e. the symbol we will use
65 * to see if the running kernel was relocated by checking if it has the
66 * same value in the vmlinux file we load.
67 */
68 kallsyms_map = machine__kernel_map(&kallsyms, type);
69
70 sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL);
71 if (sym == NULL) {
72 pr_debug("dso__find_symbol_by_name ");
73 goto out;
74 }
75
76 ref_reloc_sym.addr = sym->start;
77
78 /*
79 * Step 5:
80 *
81 * Now repeat step 2, this time for the vmlinux file we'll auto-locate.
82 */
83 if (machine__create_kernel_maps(&vmlinux) < 0) {
84 pr_debug("machine__create_kernel_maps ");
85 goto out;
86 }
87
88 vmlinux_map = machine__kernel_map(&vmlinux, type);
89 map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym;
90
91 /*
92 * Step 6:
93 *
94 * Locate a vmlinux file in the vmlinux path that has a buildid that
95 * matches the one of the running kernel.
96 *
97 * While doing that look if we find the ref reloc symbol, if we find it
98 * we'll have its ref_reloc_symbol.unrelocated_addr and then
99 * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines
100 * to fixup the symbols.
101 */
102 if (machine__load_vmlinux_path(&vmlinux, type,
103 vmlinux_matches_kallsyms_filter) <= 0) {
104 pr_debug("machine__load_vmlinux_path ");
105 goto out;
106 }
107
108 err = 0;
109 /*
110 * Step 7:
111 *
112 * Now look at the symbols in the vmlinux DSO and check if we find all of them
113 * in the kallsyms dso. For the ones that are in both, check its names and
114 * end addresses too.
115 */
116 for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) {
117 struct symbol *pair, *first_pair;
118 bool backwards = true;
119
120 sym = rb_entry(nd, struct symbol, rb_node);
121
122 if (sym->start == sym->end)
123 continue;
124
125 first_pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL);
126 pair = first_pair;
127
128 if (pair && pair->start == sym->start) {
129next_pair:
130 if (strcmp(sym->name, pair->name) == 0) {
131 /*
132 * kallsyms don't have the symbol end, so we
133 * set that by using the next symbol start - 1,
134 * in some cases we get this up to a page
135 * wrong, trace_kmalloc when I was developing
136 * this code was one such example, 2106 bytes
137 * off the real size. More than that and we
138 * _really_ have a problem.
139 */
140 s64 skew = sym->end - pair->end;
141 if (llabs(skew) < page_size)
142 continue;
143
144 pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n",
145 sym->start, sym->name, sym->end, pair->end);
146 } else {
147 struct rb_node *nnd;
148detour:
149 nnd = backwards ? rb_prev(&pair->rb_node) :
150 rb_next(&pair->rb_node);
151 if (nnd) {
152 struct symbol *next = rb_entry(nnd, struct symbol, rb_node);
153
154 if (next->start == sym->start) {
155 pair = next;
156 goto next_pair;
157 }
158 }
159
160 if (backwards) {
161 backwards = false;
162 pair = first_pair;
163 goto detour;
164 }
165
166 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
167 sym->start, sym->name, pair->name);
168 }
169 } else
170 pr_debug("%#" PRIx64 ": %s not on kallsyms\n", sym->start, sym->name);
171
172 err = -1;
173 }
174
175 if (!verbose)
176 goto out;
177
178 pr_info("Maps only in vmlinux:\n");
179
180 for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {
181 struct map *pos = rb_entry(nd, struct map, rb_node), *pair;
182 /*
183 * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while
184 * the kernel will have the path for the vmlinux file being used,
185 * so use the short name, less descriptive but the same ("[kernel]" in
186 * both cases.
187 */
188 pair = map_groups__find_by_name(&kallsyms.kmaps, type,
189 (pos->dso->kernel ?
190 pos->dso->short_name :
191 pos->dso->name));
192 if (pair)
193 pair->priv = 1;
194 else
195 map__fprintf(pos, stderr);
196 }
197
198 pr_info("Maps in vmlinux with a different name in kallsyms:\n");
199
200 for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {
201 struct map *pos = rb_entry(nd, struct map, rb_node), *pair;
202
203 pair = map_groups__find(&kallsyms.kmaps, type, pos->start);
204 if (pair == NULL || pair->priv)
205 continue;
206
207 if (pair->start == pos->start) {
208 pair->priv = 1;
209 pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as",
210 pos->start, pos->end, pos->pgoff, pos->dso->name);
211 if (pos->pgoff != pair->pgoff || pos->end != pair->end)
212 pr_info(": \n*%" PRIx64 "-%" PRIx64 " %" PRIx64 "",
213 pair->start, pair->end, pair->pgoff);
214 pr_info(" %s\n", pair->dso->name);
215 pair->priv = 1;
216 }
217 }
218
219 pr_info("Maps only in kallsyms:\n");
220
221 for (nd = rb_first(&kallsyms.kmaps.maps[type]);
222 nd; nd = rb_next(nd)) {
223 struct map *pos = rb_entry(nd, struct map, rb_node);
224
225 if (!pos->priv)
226 map__fprintf(pos, stderr);
227 }
228out:
229 return err;
230}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 1a79df9f739..9b4ff16cac9 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -14,6 +14,11 @@ enum chain_mode {
14 CHAIN_GRAPH_REL 14 CHAIN_GRAPH_REL
15}; 15};
16 16
17enum chain_order {
18 ORDER_CALLER,
19 ORDER_CALLEE
20};
21
17struct callchain_node { 22struct callchain_node {
18 struct callchain_node *parent; 23 struct callchain_node *parent;
19 struct list_head siblings; 24 struct list_head siblings;
@@ -41,6 +46,7 @@ struct callchain_param {
41 u32 print_limit; 46 u32 print_limit;
42 double min_percent; 47 double min_percent;
43 sort_chain_func_t sort; 48 sort_chain_func_t sort;
49 enum chain_order order;
44}; 50};
45 51
46struct callchain_list { 52struct callchain_list {
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index e02d78cae70..fe02903f7d0 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -399,7 +399,6 @@ static int perf_config_global(void)
399int perf_config(config_fn_t fn, void *data) 399int perf_config(config_fn_t fn, void *data)
400{ 400{
401 int ret = 0, found = 0; 401 int ret = 0, found = 0;
402 char *repo_config = NULL;
403 const char *home = NULL; 402 const char *home = NULL;
404 403
405 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ 404 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
@@ -414,19 +413,32 @@ int perf_config(config_fn_t fn, void *data)
414 home = getenv("HOME"); 413 home = getenv("HOME");
415 if (perf_config_global() && home) { 414 if (perf_config_global() && home) {
416 char *user_config = strdup(mkpath("%s/.perfconfig", home)); 415 char *user_config = strdup(mkpath("%s/.perfconfig", home));
417 if (!access(user_config, R_OK)) { 416 struct stat st;
418 ret += perf_config_from_file(fn, user_config, data); 417
419 found += 1; 418 if (user_config == NULL) {
419 warning("Not enough memory to process %s/.perfconfig, "
420 "ignoring it.", home);
421 goto out;
420 } 422 }
421 free(user_config);
422 }
423 423
424 repo_config = perf_pathdup("config"); 424 if (stat(user_config, &st) < 0)
425 if (!access(repo_config, R_OK)) { 425 goto out_free;
426 ret += perf_config_from_file(fn, repo_config, data); 426
427 if (st.st_uid && (st.st_uid != geteuid())) {
428 warning("File %s not owned by current user or root, "
429 "ignoring it.", user_config);
430 goto out_free;
431 }
432
433 if (!st.st_size)
434 goto out_free;
435
436 ret += perf_config_from_file(fn, user_config, data);
427 found += 1; 437 found += 1;
438out_free:
439 free(user_config);
428 } 440 }
429 free(repo_config); 441out:
430 if (found == 0) 442 if (found == 0)
431 return -1; 443 return -1;
432 return ret; 444 return ret;
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
new file mode 100644
index 00000000000..ee51e9b4dc0
--- /dev/null
+++ b/tools/perf/util/dwarf-aux.c
@@ -0,0 +1,843 @@
1/*
2 * dwarf-aux.c : libdw auxiliary interfaces
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 */
19
20#include <stdbool.h>
21#include "util.h"
22#include "debug.h"
23#include "dwarf-aux.h"
24
25/**
26 * cu_find_realpath - Find the realpath of the target file
27 * @cu_die: A DIE(dwarf information entry) of CU(compilation Unit)
28 * @fname: The tail filename of the target file
29 *
30 * Find the real(long) path of @fname in @cu_die.
31 */
32const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
33{
34 Dwarf_Files *files;
35 size_t nfiles, i;
36 const char *src = NULL;
37 int ret;
38
39 if (!fname)
40 return NULL;
41
42 ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
43 if (ret != 0)
44 return NULL;
45
46 for (i = 0; i < nfiles; i++) {
47 src = dwarf_filesrc(files, i, NULL, NULL);
48 if (strtailcmp(src, fname) == 0)
49 break;
50 }
51 if (i == nfiles)
52 return NULL;
53 return src;
54}
55
56/**
57 * cu_get_comp_dir - Get the path of compilation directory
58 * @cu_die: a CU DIE
59 *
60 * Get the path of compilation directory of given @cu_die.
61 * Since this depends on DW_AT_comp_dir, older gcc will not
62 * embedded it. In that case, this returns NULL.
63 */
64const char *cu_get_comp_dir(Dwarf_Die *cu_die)
65{
66 Dwarf_Attribute attr;
67 if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
68 return NULL;
69 return dwarf_formstring(&attr);
70}
71
72/**
73 * cu_find_lineinfo - Get a line number and file name for given address
74 * @cu_die: a CU DIE
75 * @addr: An address
76 * @fname: a pointer which returns the file name string
77 * @lineno: a pointer which returns the line number
78 *
79 * Find a line number and file name for @addr in @cu_die.
80 */
81int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr,
82 const char **fname, int *lineno)
83{
84 Dwarf_Line *line;
85 Dwarf_Addr laddr;
86
87 line = dwarf_getsrc_die(cu_die, (Dwarf_Addr)addr);
88 if (line && dwarf_lineaddr(line, &laddr) == 0 &&
89 addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
90 *fname = dwarf_linesrc(line, NULL, NULL);
91 if (!*fname)
92 /* line number is useless without filename */
93 *lineno = 0;
94 }
95
96 return *lineno ?: -ENOENT;
97}
98
99static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data);
100
101/**
102 * cu_walk_functions_at - Walk on function DIEs at given address
103 * @cu_die: A CU DIE
104 * @addr: An address
105 * @callback: A callback which called with found DIEs
106 * @data: A user data
107 *
108 * Walk on function DIEs at given @addr in @cu_die. Passed DIEs
109 * should be subprogram or inlined-subroutines.
110 */
111int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
112 int (*callback)(Dwarf_Die *, void *), void *data)
113{
114 Dwarf_Die die_mem;
115 Dwarf_Die *sc_die;
116 int ret = -ENOENT;
117
118 /* Inlined function could be recursive. Trace it until fail */
119 for (sc_die = die_find_realfunc(cu_die, addr, &die_mem);
120 sc_die != NULL;
121 sc_die = die_find_child(sc_die, __die_find_inline_cb, &addr,
122 &die_mem)) {
123 ret = callback(sc_die, data);
124 if (ret)
125 break;
126 }
127
128 return ret;
129
130}
131
132/**
133 * die_compare_name - Compare diename and tname
134 * @dw_die: a DIE
135 * @tname: a string of target name
136 *
137 * Compare the name of @dw_die and @tname. Return false if @dw_die has no name.
138 */
139bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
140{
141 const char *name;
142 name = dwarf_diename(dw_die);
143 return name ? (strcmp(tname, name) == 0) : false;
144}
145
146/**
147 * die_get_call_lineno - Get callsite line number of inline-function instance
148 * @in_die: a DIE of an inlined function instance
149 *
150 * Get call-site line number of @in_die. This means from where the inline
151 * function is called.
152 */
153int die_get_call_lineno(Dwarf_Die *in_die)
154{
155 Dwarf_Attribute attr;
156 Dwarf_Word ret;
157
158 if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
159 return -ENOENT;
160
161 dwarf_formudata(&attr, &ret);
162 return (int)ret;
163}
164
165/**
166 * die_get_type - Get type DIE
167 * @vr_die: a DIE of a variable
168 * @die_mem: where to store a type DIE
169 *
170 * Get a DIE of the type of given variable (@vr_die), and store
171 * it to die_mem. Return NULL if fails to get a type DIE.
172 */
173Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
174{
175 Dwarf_Attribute attr;
176
177 if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
178 dwarf_formref_die(&attr, die_mem))
179 return die_mem;
180 else
181 return NULL;
182}
183
184/* Get a type die, but skip qualifiers */
185static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
186{
187 int tag;
188
189 do {
190 vr_die = die_get_type(vr_die, die_mem);
191 if (!vr_die)
192 break;
193 tag = dwarf_tag(vr_die);
194 } while (tag == DW_TAG_const_type ||
195 tag == DW_TAG_restrict_type ||
196 tag == DW_TAG_volatile_type ||
197 tag == DW_TAG_shared_type);
198
199 return vr_die;
200}
201
202/**
203 * die_get_real_type - Get a type die, but skip qualifiers and typedef
204 * @vr_die: a DIE of a variable
205 * @die_mem: where to store a type DIE
206 *
207 * Get a DIE of the type of given variable (@vr_die), and store
208 * it to die_mem. Return NULL if fails to get a type DIE.
209 * If the type is qualifiers (e.g. const) or typedef, this skips it
210 * and tries to find real type (structure or basic types, e.g. int).
211 */
212Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
213{
214 do {
215 vr_die = __die_get_real_type(vr_die, die_mem);
216 } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
217
218 return vr_die;
219}
220
221/* Get attribute and translate it as a udata */
222static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
223 Dwarf_Word *result)
224{
225 Dwarf_Attribute attr;
226
227 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
228 dwarf_formudata(&attr, result) != 0)
229 return -ENOENT;
230
231 return 0;
232}
233
234/* Get attribute and translate it as a sdata */
235static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name,
236 Dwarf_Sword *result)
237{
238 Dwarf_Attribute attr;
239
240 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
241 dwarf_formsdata(&attr, result) != 0)
242 return -ENOENT;
243
244 return 0;
245}
246
247/**
248 * die_is_signed_type - Check whether a type DIE is signed or not
249 * @tp_die: a DIE of a type
250 *
251 * Get the encoding of @tp_die and return true if the encoding
252 * is signed.
253 */
254bool die_is_signed_type(Dwarf_Die *tp_die)
255{
256 Dwarf_Word ret;
257
258 if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
259 return false;
260
261 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
262 ret == DW_ATE_signed_fixed);
263}
264
265/**
266 * die_get_data_member_location - Get the data-member offset
267 * @mb_die: a DIE of a member of a data structure
268 * @offs: The offset of the member in the data structure
269 *
270 * Get the offset of @mb_die in the data structure including @mb_die, and
271 * stores result offset to @offs. If any error occurs this returns errno.
272 */
273int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
274{
275 Dwarf_Attribute attr;
276 Dwarf_Op *expr;
277 size_t nexpr;
278 int ret;
279
280 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
281 return -ENOENT;
282
283 if (dwarf_formudata(&attr, offs) != 0) {
284 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
285 ret = dwarf_getlocation(&attr, &expr, &nexpr);
286 if (ret < 0 || nexpr == 0)
287 return -ENOENT;
288
289 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
290 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
291 expr[0].atom, nexpr);
292 return -ENOTSUP;
293 }
294 *offs = (Dwarf_Word)expr[0].number;
295 }
296 return 0;
297}
298
299/* Get the call file index number in CU DIE */
300static int die_get_call_fileno(Dwarf_Die *in_die)
301{
302 Dwarf_Sword idx;
303
304 if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0)
305 return (int)idx;
306 else
307 return -ENOENT;
308}
309
310/* Get the declared file index number in CU DIE */
311static int die_get_decl_fileno(Dwarf_Die *pdie)
312{
313 Dwarf_Sword idx;
314
315 if (die_get_attr_sdata(pdie, DW_AT_decl_file, &idx) == 0)
316 return (int)idx;
317 else
318 return -ENOENT;
319}
320
321/**
322 * die_get_call_file - Get callsite file name of inlined function instance
323 * @in_die: a DIE of an inlined function instance
324 *
325 * Get call-site file name of @in_die. This means from which file the inline
326 * function is called.
327 */
328const char *die_get_call_file(Dwarf_Die *in_die)
329{
330 Dwarf_Die cu_die;
331 Dwarf_Files *files;
332 int idx;
333
334 idx = die_get_call_fileno(in_die);
335 if (idx < 0 || !dwarf_diecu(in_die, &cu_die, NULL, NULL) ||
336 dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
337 return NULL;
338
339 return dwarf_filesrc(files, idx, NULL, NULL);
340}
341
342
343/**
344 * die_find_child - Generic DIE search function in DIE tree
345 * @rt_die: a root DIE
346 * @callback: a callback function
347 * @data: a user data passed to the callback function
348 * @die_mem: a buffer for result DIE
349 *
350 * Trace DIE tree from @rt_die and call @callback for each child DIE.
351 * If @callback returns DIE_FIND_CB_END, this stores the DIE into
352 * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE,
353 * this continues to trace the tree. Optionally, @callback can return
354 * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only
355 * the children and trace only the siblings respectively.
356 * Returns NULL if @callback can't find any appropriate DIE.
357 */
358Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
359 int (*callback)(Dwarf_Die *, void *),
360 void *data, Dwarf_Die *die_mem)
361{
362 Dwarf_Die child_die;
363 int ret;
364
365 ret = dwarf_child(rt_die, die_mem);
366 if (ret != 0)
367 return NULL;
368
369 do {
370 ret = callback(die_mem, data);
371 if (ret == DIE_FIND_CB_END)
372 return die_mem;
373
374 if ((ret & DIE_FIND_CB_CHILD) &&
375 die_find_child(die_mem, callback, data, &child_die)) {
376 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
377 return die_mem;
378 }
379 } while ((ret & DIE_FIND_CB_SIBLING) &&
380 dwarf_siblingof(die_mem, die_mem) == 0);
381
382 return NULL;
383}
384
385struct __addr_die_search_param {
386 Dwarf_Addr addr;
387 Dwarf_Die *die_mem;
388};
389
390/* die_find callback for non-inlined function search */
391static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
392{
393 struct __addr_die_search_param *ad = data;
394
395 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
396 dwarf_haspc(fn_die, ad->addr)) {
397 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
398 return DWARF_CB_ABORT;
399 }
400 return DWARF_CB_OK;
401}
402
403/**
404 * die_find_realfunc - Search a non-inlined function at given address
405 * @cu_die: a CU DIE which including @addr
406 * @addr: target address
407 * @die_mem: a buffer for result DIE
408 *
409 * Search a non-inlined function DIE which includes @addr. Stores the
410 * DIE to @die_mem and returns it if found. Returns NULl if failed.
411 */
412Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
413 Dwarf_Die *die_mem)
414{
415 struct __addr_die_search_param ad;
416 ad.addr = addr;
417 ad.die_mem = die_mem;
418 /* dwarf_getscopes can't find subprogram. */
419 if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
420 return NULL;
421 else
422 return die_mem;
423}
424
425/* die_find callback for inline function search */
426static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
427{
428 Dwarf_Addr *addr = data;
429
430 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
431 dwarf_haspc(die_mem, *addr))
432 return DIE_FIND_CB_END;
433
434 return DIE_FIND_CB_CONTINUE;
435}
436
437/**
438 * die_find_inlinefunc - Search an inlined function at given address
439 * @cu_die: a CU DIE which including @addr
440 * @addr: target address
441 * @die_mem: a buffer for result DIE
442 *
443 * Search an inlined function DIE which includes @addr. Stores the
444 * DIE to @die_mem and returns it if found. Returns NULl if failed.
445 * If several inlined functions are expanded recursively, this trace
446 * it and returns deepest one.
447 */
448Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
449 Dwarf_Die *die_mem)
450{
451 Dwarf_Die tmp_die;
452
453 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
454 if (!sp_die)
455 return NULL;
456
457 /* Inlined function could be recursive. Trace it until fail */
458 while (sp_die) {
459 memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
460 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
461 &tmp_die);
462 }
463
464 return die_mem;
465}
466
467struct __instance_walk_param {
468 void *addr;
469 int (*callback)(Dwarf_Die *, void *);
470 void *data;
471 int retval;
472};
473
474static int __die_walk_instances_cb(Dwarf_Die *inst, void *data)
475{
476 struct __instance_walk_param *iwp = data;
477 Dwarf_Attribute attr_mem;
478 Dwarf_Die origin_mem;
479 Dwarf_Attribute *attr;
480 Dwarf_Die *origin;
481 int tmp;
482
483 attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem);
484 if (attr == NULL)
485 return DIE_FIND_CB_CONTINUE;
486
487 origin = dwarf_formref_die(attr, &origin_mem);
488 if (origin == NULL || origin->addr != iwp->addr)
489 return DIE_FIND_CB_CONTINUE;
490
491 /* Ignore redundant instances */
492 if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) {
493 dwarf_decl_line(origin, &tmp);
494 if (die_get_call_lineno(inst) == tmp) {
495 tmp = die_get_decl_fileno(origin);
496 if (die_get_call_fileno(inst) == tmp)
497 return DIE_FIND_CB_CONTINUE;
498 }
499 }
500
501 iwp->retval = iwp->callback(inst, iwp->data);
502
503 return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE;
504}
505
506/**
507 * die_walk_instances - Walk on instances of given DIE
508 * @or_die: an abstract original DIE
509 * @callback: a callback function which is called with instance DIE
510 * @data: user data
511 *
512 * Walk on the instances of give @in_die. @in_die must be an inlined function
513 * declartion. This returns the return value of @callback if it returns
514 * non-zero value, or -ENOENT if there is no instance.
515 */
516int die_walk_instances(Dwarf_Die *or_die, int (*callback)(Dwarf_Die *, void *),
517 void *data)
518{
519 Dwarf_Die cu_die;
520 Dwarf_Die die_mem;
521 struct __instance_walk_param iwp = {
522 .addr = or_die->addr,
523 .callback = callback,
524 .data = data,
525 .retval = -ENOENT,
526 };
527
528 if (dwarf_diecu(or_die, &cu_die, NULL, NULL) == NULL)
529 return -ENOENT;
530
531 die_find_child(&cu_die, __die_walk_instances_cb, &iwp, &die_mem);
532
533 return iwp.retval;
534}
535
536/* Line walker internal parameters */
537struct __line_walk_param {
538 bool recursive;
539 line_walk_callback_t callback;
540 void *data;
541 int retval;
542};
543
544static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
545{
546 struct __line_walk_param *lw = data;
547 Dwarf_Addr addr = 0;
548 const char *fname;
549 int lineno;
550
551 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
552 fname = die_get_call_file(in_die);
553 lineno = die_get_call_lineno(in_die);
554 if (fname && lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
555 lw->retval = lw->callback(fname, lineno, addr, lw->data);
556 if (lw->retval != 0)
557 return DIE_FIND_CB_END;
558 }
559 }
560 if (!lw->recursive)
561 /* Don't need to search recursively */
562 return DIE_FIND_CB_SIBLING;
563
564 if (addr) {
565 fname = dwarf_decl_file(in_die);
566 if (fname && dwarf_decl_line(in_die, &lineno) == 0) {
567 lw->retval = lw->callback(fname, lineno, addr, lw->data);
568 if (lw->retval != 0)
569 return DIE_FIND_CB_END;
570 }
571 }
572
573 /* Continue to search nested inlined function call-sites */
574 return DIE_FIND_CB_CONTINUE;
575}
576
577/* Walk on lines of blocks included in given DIE */
578static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive,
579 line_walk_callback_t callback, void *data)
580{
581 struct __line_walk_param lw = {
582 .recursive = recursive,
583 .callback = callback,
584 .data = data,
585 .retval = 0,
586 };
587 Dwarf_Die die_mem;
588 Dwarf_Addr addr;
589 const char *fname;
590 int lineno;
591
592 /* Handle function declaration line */
593 fname = dwarf_decl_file(sp_die);
594 if (fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
595 dwarf_entrypc(sp_die, &addr) == 0) {
596 lw.retval = callback(fname, lineno, addr, data);
597 if (lw.retval != 0)
598 goto done;
599 }
600 die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
601done:
602 return lw.retval;
603}
604
605static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
606{
607 struct __line_walk_param *lw = data;
608
609 lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data);
610 if (lw->retval != 0)
611 return DWARF_CB_ABORT;
612
613 return DWARF_CB_OK;
614}
615
616/**
617 * die_walk_lines - Walk on lines inside given DIE
618 * @rt_die: a root DIE (CU, subprogram or inlined_subroutine)
619 * @callback: callback routine
620 * @data: user data
621 *
622 * Walk on all lines inside given @rt_die and call @callback on each line.
623 * If the @rt_die is a function, walk only on the lines inside the function,
624 * otherwise @rt_die must be a CU DIE.
625 * Note that this walks not only dwarf line list, but also function entries
626 * and inline call-site.
627 */
628int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
629{
630 Dwarf_Lines *lines;
631 Dwarf_Line *line;
632 Dwarf_Addr addr;
633 const char *fname;
634 int lineno, ret = 0;
635 Dwarf_Die die_mem, *cu_die;
636 size_t nlines, i;
637
638 /* Get the CU die */
639 if (dwarf_tag(rt_die) != DW_TAG_compile_unit)
640 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
641 else
642 cu_die = rt_die;
643 if (!cu_die) {
644 pr_debug2("Failed to get CU from given DIE.\n");
645 return -EINVAL;
646 }
647
648 /* Get lines list in the CU */
649 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
650 pr_debug2("Failed to get source lines on this CU.\n");
651 return -ENOENT;
652 }
653 pr_debug2("Get %zd lines from this CU\n", nlines);
654
655 /* Walk on the lines on lines list */
656 for (i = 0; i < nlines; i++) {
657 line = dwarf_onesrcline(lines, i);
658 if (line == NULL ||
659 dwarf_lineno(line, &lineno) != 0 ||
660 dwarf_lineaddr(line, &addr) != 0) {
661 pr_debug2("Failed to get line info. "
662 "Possible error in debuginfo.\n");
663 continue;
664 }
665 /* Filter lines based on address */
666 if (rt_die != cu_die)
667 /*
668 * Address filtering
669 * The line is included in given function, and
670 * no inline block includes it.
671 */
672 if (!dwarf_haspc(rt_die, addr) ||
673 die_find_inlinefunc(rt_die, addr, &die_mem))
674 continue;
675 /* Get source line */
676 fname = dwarf_linesrc(line, NULL, NULL);
677
678 ret = callback(fname, lineno, addr, data);
679 if (ret != 0)
680 return ret;
681 }
682
683 /*
684 * Dwarf lines doesn't include function declarations and inlined
685 * subroutines. We have to check functions list or given function.
686 */
687 if (rt_die != cu_die)
688 /*
689 * Don't need walk functions recursively, because nested
690 * inlined functions don't have lines of the specified DIE.
691 */
692 ret = __die_walk_funclines(rt_die, false, callback, data);
693 else {
694 struct __line_walk_param param = {
695 .callback = callback,
696 .data = data,
697 .retval = 0,
698 };
699 dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
700 ret = param.retval;
701 }
702
703 return ret;
704}
705
706struct __find_variable_param {
707 const char *name;
708 Dwarf_Addr addr;
709};
710
711static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
712{
713 struct __find_variable_param *fvp = data;
714 int tag;
715
716 tag = dwarf_tag(die_mem);
717 if ((tag == DW_TAG_formal_parameter ||
718 tag == DW_TAG_variable) &&
719 die_compare_name(die_mem, fvp->name))
720 return DIE_FIND_CB_END;
721
722 if (dwarf_haspc(die_mem, fvp->addr))
723 return DIE_FIND_CB_CONTINUE;
724 else
725 return DIE_FIND_CB_SIBLING;
726}
727
728/**
729 * die_find_variable_at - Find a given name variable at given address
730 * @sp_die: a function DIE
731 * @name: variable name
732 * @addr: address
733 * @die_mem: a buffer for result DIE
734 *
735 * Find a variable DIE called @name at @addr in @sp_die.
736 */
737Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
738 Dwarf_Addr addr, Dwarf_Die *die_mem)
739{
740 struct __find_variable_param fvp = { .name = name, .addr = addr};
741
742 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
743 die_mem);
744}
745
746static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
747{
748 const char *name = data;
749
750 if ((dwarf_tag(die_mem) == DW_TAG_member) &&
751 die_compare_name(die_mem, name))
752 return DIE_FIND_CB_END;
753
754 return DIE_FIND_CB_SIBLING;
755}
756
757/**
758 * die_find_member - Find a given name member in a data structure
759 * @st_die: a data structure type DIE
760 * @name: member name
761 * @die_mem: a buffer for result DIE
762 *
763 * Find a member DIE called @name in @st_die.
764 */
765Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
766 Dwarf_Die *die_mem)
767{
768 return die_find_child(st_die, __die_find_member_cb, (void *)name,
769 die_mem);
770}
771
772/**
773 * die_get_typename - Get the name of given variable DIE
774 * @vr_die: a variable DIE
775 * @buf: a buffer for result type name
776 * @len: a max-length of @buf
777 *
778 * Get the name of @vr_die and stores it to @buf. Return the actual length
779 * of type name if succeeded. Return -E2BIG if @len is not enough long, and
780 * Return -ENOENT if failed to find type name.
781 * Note that the result will stores typedef name if possible, and stores
782 * "*(function_type)" if the type is a function pointer.
783 */
784int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
785{
786 Dwarf_Die type;
787 int tag, ret, ret2;
788 const char *tmp = "";
789
790 if (__die_get_real_type(vr_die, &type) == NULL)
791 return -ENOENT;
792
793 tag = dwarf_tag(&type);
794 if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
795 tmp = "*";
796 else if (tag == DW_TAG_subroutine_type) {
797 /* Function pointer */
798 ret = snprintf(buf, len, "(function_type)");
799 return (ret >= len) ? -E2BIG : ret;
800 } else {
801 if (!dwarf_diename(&type))
802 return -ENOENT;
803 if (tag == DW_TAG_union_type)
804 tmp = "union ";
805 else if (tag == DW_TAG_structure_type)
806 tmp = "struct ";
807 /* Write a base name */
808 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
809 return (ret >= len) ? -E2BIG : ret;
810 }
811 ret = die_get_typename(&type, buf, len);
812 if (ret > 0) {
813 ret2 = snprintf(buf + ret, len - ret, "%s", tmp);
814 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
815 }
816 return ret;
817}
818
819/**
820 * die_get_varname - Get the name and type of given variable DIE
821 * @vr_die: a variable DIE
822 * @buf: a buffer for type and variable name
823 * @len: the max-length of @buf
824 *
825 * Get the name and type of @vr_die and stores it in @buf as "type\tname".
826 */
827int die_get_varname(Dwarf_Die *vr_die, char *buf, int len)
828{
829 int ret, ret2;
830
831 ret = die_get_typename(vr_die, buf, len);
832 if (ret < 0) {
833 pr_debug("Failed to get type, make it unknown.\n");
834 ret = snprintf(buf, len, "(unknown_type)");
835 }
836 if (ret > 0) {
837 ret2 = snprintf(buf + ret, len - ret, "\t%s",
838 dwarf_diename(vr_die));
839 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
840 }
841 return ret;
842}
843
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
new file mode 100644
index 00000000000..6ce1717784b
--- /dev/null
+++ b/tools/perf/util/dwarf-aux.h
@@ -0,0 +1,111 @@
1#ifndef _DWARF_AUX_H
2#define _DWARF_AUX_H
3/*
4 * dwarf-aux.h : libdw auxiliary interfaces
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
22#include <dwarf.h>
23#include <elfutils/libdw.h>
24#include <elfutils/libdwfl.h>
25#include <elfutils/version.h>
26
27/* Find the realpath of the target file */
28extern const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname);
29
30/* Get DW_AT_comp_dir (should be NULL with older gcc) */
31extern const char *cu_get_comp_dir(Dwarf_Die *cu_die);
32
33/* Get a line number and file name for given address */
34extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
35 const char **fname, int *lineno);
36
37/* Walk on funcitons at given address */
38extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
39 int (*callback)(Dwarf_Die *, void *), void *data);
40
41/* Compare diename and tname */
42extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
43
44/* Get callsite line number of inline-function instance */
45extern int die_get_call_lineno(Dwarf_Die *in_die);
46
47/* Get callsite file name of inlined function instance */
48extern const char *die_get_call_file(Dwarf_Die *in_die);
49
50/* Get type die */
51extern Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem);
52
53/* Get a type die, but skip qualifiers and typedef */
54extern Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem);
55
56/* Check whether the DIE is signed or not */
57extern bool die_is_signed_type(Dwarf_Die *tp_die);
58
59/* Get data_member_location offset */
60extern int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs);
61
62/* Return values for die_find_child() callbacks */
63enum {
64 DIE_FIND_CB_END = 0, /* End of Search */
65 DIE_FIND_CB_CHILD = 1, /* Search only children */
66 DIE_FIND_CB_SIBLING = 2, /* Search only siblings */
67 DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */
68};
69
70/* Search child DIEs */
71extern Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
72 int (*callback)(Dwarf_Die *, void *),
73 void *data, Dwarf_Die *die_mem);
74
75/* Search a non-inlined function including given address */
76extern Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
77 Dwarf_Die *die_mem);
78
79/* Search an inlined function including given address */
80extern Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
81 Dwarf_Die *die_mem);
82
83/* Walk on the instances of given DIE */
84extern int die_walk_instances(Dwarf_Die *in_die,
85 int (*callback)(Dwarf_Die *, void *), void *data);
86
87/* Walker on lines (Note: line number will not be sorted) */
88typedef int (* line_walk_callback_t) (const char *fname, int lineno,
89 Dwarf_Addr addr, void *data);
90
91/*
92 * Walk on lines inside given DIE. If the DIE is a subprogram, walk only on
93 * the lines inside the subprogram, otherwise the DIE must be a CU DIE.
94 */
95extern int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback,
96 void *data);
97
98/* Find a variable called 'name' at given address */
99extern Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
100 Dwarf_Addr addr, Dwarf_Die *die_mem);
101
102/* Find a member called 'name' */
103extern Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
104 Dwarf_Die *die_mem);
105
106/* Get the name of given variable DIE */
107extern int die_get_typename(Dwarf_Die *vr_die, char *buf, int len);
108
109/* Get the name and type of given variable DIE, stored as "type\tname" */
110extern int die_get_varname(Dwarf_Die *vr_die, char *buf, int len);
111#endif
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 3c1b8a63210..437f8ca679a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -169,12 +169,17 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
169 continue; 169 continue;
170 pbf += n + 3; 170 pbf += n + 3;
171 if (*pbf == 'x') { /* vm_exec */ 171 if (*pbf == 'x') { /* vm_exec */
172 char anonstr[] = "//anon\n";
172 char *execname = strchr(bf, '/'); 173 char *execname = strchr(bf, '/');
173 174
174 /* Catch VDSO */ 175 /* Catch VDSO */
175 if (execname == NULL) 176 if (execname == NULL)
176 execname = strstr(bf, "[vdso]"); 177 execname = strstr(bf, "[vdso]");
177 178
179 /* Catch anonymous mmaps */
180 if ((execname == NULL) && !strstr(bf, "["))
181 execname = anonstr;
182
178 if (execname == NULL) 183 if (execname == NULL)
179 continue; 184 continue;
180 185
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 1d7f66488a8..357a85b8524 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -186,6 +186,6 @@ const char *perf_event__name(unsigned int id);
186 186
187int perf_event__parse_sample(const union perf_event *event, u64 type, 187int perf_event__parse_sample(const union perf_event *event, u64 type,
188 int sample_size, bool sample_id_all, 188 int sample_size, bool sample_id_all,
189 struct perf_sample *sample); 189 struct perf_sample *sample, bool swapped);
190 190
191#endif /* __PERF_RECORD_H */ 191#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index b021ea9265c..72e9f4886b6 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -85,10 +85,45 @@ int perf_evlist__add_default(struct perf_evlist *evlist)
85 struct perf_evsel *evsel = perf_evsel__new(&attr, 0); 85 struct perf_evsel *evsel = perf_evsel__new(&attr, 0);
86 86
87 if (evsel == NULL) 87 if (evsel == NULL)
88 return -ENOMEM; 88 goto error;
89
90 /* use strdup() because free(evsel) assumes name is allocated */
91 evsel->name = strdup("cycles");
92 if (!evsel->name)
93 goto error_free;
89 94
90 perf_evlist__add(evlist, evsel); 95 perf_evlist__add(evlist, evsel);
91 return 0; 96 return 0;
97error_free:
98 perf_evsel__delete(evsel);
99error:
100 return -ENOMEM;
101}
102
103void perf_evlist__disable(struct perf_evlist *evlist)
104{
105 int cpu, thread;
106 struct perf_evsel *pos;
107
108 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
109 list_for_each_entry(pos, &evlist->entries, node) {
110 for (thread = 0; thread < evlist->threads->nr; thread++)
111 ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_DISABLE);
112 }
113 }
114}
115
116void perf_evlist__enable(struct perf_evlist *evlist)
117{
118 int cpu, thread;
119 struct perf_evsel *pos;
120
121 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
122 list_for_each_entry(pos, &evlist->entries, node) {
123 for (thread = 0; thread < evlist->threads->nr; thread++)
124 ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_ENABLE);
125 }
126 }
92} 127}
93 128
94int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 129int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index b2b862374f3..f3491500274 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -53,6 +53,9 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
53int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite); 53int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
54void perf_evlist__munmap(struct perf_evlist *evlist); 54void perf_evlist__munmap(struct perf_evlist *evlist);
55 55
56void perf_evlist__disable(struct perf_evlist *evlist);
57void perf_evlist__enable(struct perf_evlist *evlist);
58
56static inline void perf_evlist__set_maps(struct perf_evlist *evlist, 59static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
57 struct cpu_map *cpus, 60 struct cpu_map *cpus,
58 struct thread_map *threads) 61 struct thread_map *threads)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 0239eb87b23..e389815078d 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -7,6 +7,8 @@
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9 9
10#include <byteswap.h>
11#include "asm/bug.h"
10#include "evsel.h" 12#include "evsel.h"
11#include "evlist.h" 13#include "evlist.h"
12#include "util.h" 14#include "util.h"
@@ -342,10 +344,20 @@ static bool sample_overlap(const union perf_event *event,
342 344
343int perf_event__parse_sample(const union perf_event *event, u64 type, 345int perf_event__parse_sample(const union perf_event *event, u64 type,
344 int sample_size, bool sample_id_all, 346 int sample_size, bool sample_id_all,
345 struct perf_sample *data) 347 struct perf_sample *data, bool swapped)
346{ 348{
347 const u64 *array; 349 const u64 *array;
348 350
351 /*
352 * used for cross-endian analysis. See git commit 65014ab3
353 * for why this goofiness is needed.
354 */
355 union {
356 u64 val64;
357 u32 val32[2];
358 } u;
359
360
349 data->cpu = data->pid = data->tid = -1; 361 data->cpu = data->pid = data->tid = -1;
350 data->stream_id = data->id = data->time = -1ULL; 362 data->stream_id = data->id = data->time = -1ULL;
351 363
@@ -366,9 +378,16 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
366 } 378 }
367 379
368 if (type & PERF_SAMPLE_TID) { 380 if (type & PERF_SAMPLE_TID) {
369 u32 *p = (u32 *)array; 381 u.val64 = *array;
370 data->pid = p[0]; 382 if (swapped) {
371 data->tid = p[1]; 383 /* undo swap of u64, then swap on individual u32s */
384 u.val64 = bswap_64(u.val64);
385 u.val32[0] = bswap_32(u.val32[0]);
386 u.val32[1] = bswap_32(u.val32[1]);
387 }
388
389 data->pid = u.val32[0];
390 data->tid = u.val32[1];
372 array++; 391 array++;
373 } 392 }
374 393
@@ -377,6 +396,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
377 array++; 396 array++;
378 } 397 }
379 398
399 data->addr = 0;
380 if (type & PERF_SAMPLE_ADDR) { 400 if (type & PERF_SAMPLE_ADDR) {
381 data->addr = *array; 401 data->addr = *array;
382 array++; 402 array++;
@@ -394,8 +414,15 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
394 } 414 }
395 415
396 if (type & PERF_SAMPLE_CPU) { 416 if (type & PERF_SAMPLE_CPU) {
397 u32 *p = (u32 *)array; 417
398 data->cpu = *p; 418 u.val64 = *array;
419 if (swapped) {
420 /* undo swap of u64, then swap on individual u32s */
421 u.val64 = bswap_64(u.val64);
422 u.val32[0] = bswap_32(u.val32[0]);
423 }
424
425 data->cpu = u.val32[0];
399 array++; 426 array++;
400 } 427 }
401 428
@@ -422,18 +449,27 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
422 } 449 }
423 450
424 if (type & PERF_SAMPLE_RAW) { 451 if (type & PERF_SAMPLE_RAW) {
425 u32 *p = (u32 *)array; 452 const u64 *pdata;
453
454 u.val64 = *array;
455 if (WARN_ONCE(swapped,
456 "Endianness of raw data not corrected!\n")) {
457 /* undo swap of u64, then swap on individual u32s */
458 u.val64 = bswap_64(u.val64);
459 u.val32[0] = bswap_32(u.val32[0]);
460 u.val32[1] = bswap_32(u.val32[1]);
461 }
426 462
427 if (sample_overlap(event, array, sizeof(u32))) 463 if (sample_overlap(event, array, sizeof(u32)))
428 return -EFAULT; 464 return -EFAULT;
429 465
430 data->raw_size = *p; 466 data->raw_size = u.val32[0];
431 p++; 467 pdata = (void *) array + sizeof(u32);
432 468
433 if (sample_overlap(event, p, data->raw_size)) 469 if (sample_overlap(event, pdata, data->raw_size))
434 return -EFAULT; 470 return -EFAULT;
435 471
436 data->raw_data = p; 472 data->raw_data = (void *) pdata;
437 } 473 }
438 474
439 return 0; 475 return 0;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 7e9366e4490..e9a31554e26 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -61,6 +61,7 @@ struct perf_evsel {
61 off_t id_offset; 61 off_t id_offset;
62 }; 62 };
63 struct cgroup_sel *cgrp; 63 struct cgroup_sel *cgrp;
64 bool supported;
64}; 65};
65 66
66struct cpu_map; 67struct cpu_map;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index afb0849fe53..b6c1ad123ca 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -189,8 +189,8 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
189 const char *name, bool is_kallsyms) 189 const char *name, bool is_kallsyms)
190{ 190{
191 const size_t size = PATH_MAX; 191 const size_t size = PATH_MAX;
192 char *realname, *filename = malloc(size), 192 char *realname, *filename = zalloc(size),
193 *linkname = malloc(size), *targetname; 193 *linkname = zalloc(size), *targetname;
194 int len, err = -1; 194 int len, err = -1;
195 195
196 if (is_kallsyms) { 196 if (is_kallsyms) {
@@ -254,8 +254,8 @@ static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
254int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) 254int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
255{ 255{
256 const size_t size = PATH_MAX; 256 const size_t size = PATH_MAX;
257 char *filename = malloc(size), 257 char *filename = zalloc(size),
258 *linkname = malloc(size); 258 *linkname = zalloc(size);
259 int err = -1; 259 int err = -1;
260 260
261 if (filename == NULL || linkname == NULL) 261 if (filename == NULL || linkname == NULL)
@@ -726,7 +726,16 @@ static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
726 return -1; 726 return -1;
727 727
728 bev.header = old_bev.header; 728 bev.header = old_bev.header;
729 bev.pid = 0; 729
730 /*
731 * As the pid is the missing value, we need to fill
732 * it properly. The header.misc value give us nice hint.
733 */
734 bev.pid = HOST_KERNEL_ID;
735 if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
736 bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
737 bev.pid = DEFAULT_GUEST_KERNEL_ID;
738
730 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id)); 739 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
731 __event_process_build_id(&bev, filename, session); 740 __event_process_build_id(&bev, filename, session);
732 741
@@ -877,9 +886,12 @@ int perf_session__read_header(struct perf_session *session, int fd)
877 struct perf_evsel *evsel; 886 struct perf_evsel *evsel;
878 off_t tmp; 887 off_t tmp;
879 888
880 if (perf_header__getbuffer64(header, fd, &f_attr, sizeof(f_attr))) 889 if (readn(fd, &f_attr, sizeof(f_attr)) <= 0)
881 goto out_errno; 890 goto out_errno;
882 891
892 if (header->needs_swap)
893 perf_event__attr_swap(&f_attr.attr);
894
883 tmp = lseek(fd, 0, SEEK_CUR); 895 tmp = lseek(fd, 0, SEEK_CUR);
884 evsel = perf_evsel__new(&f_attr.attr, i); 896 evsel = perf_evsel__new(&f_attr.attr, i);
885 897
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 627a02e03c5..677e1da6bb3 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -14,7 +14,8 @@ enum hist_filter {
14 14
15struct callchain_param callchain_param = { 15struct callchain_param callchain_param = {
16 .mode = CHAIN_GRAPH_REL, 16 .mode = CHAIN_GRAPH_REL,
17 .min_percent = 0.5 17 .min_percent = 0.5,
18 .order = ORDER_CALLEE
18}; 19};
19 20
20u16 hists__col_len(struct hists *self, enum hist_column col) 21u16 hists__col_len(struct hists *self, enum hist_column col)
@@ -846,6 +847,9 @@ print_entries:
846 for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { 847 for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
847 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 848 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
848 849
850 if (h->filtered)
851 continue;
852
849 if (show_displacement) { 853 if (show_displacement) {
850 if (h->pair != NULL) 854 if (h->pair != NULL)
851 displacement = ((long)h->pair->position - 855 displacement = ((long)h->pair->position -
diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h
index 791f9dd27eb..547628e97f3 100644
--- a/tools/perf/util/include/linux/compiler.h
+++ b/tools/perf/util/include/linux/compiler.h
@@ -5,7 +5,9 @@
5#define __always_inline inline 5#define __always_inline inline
6#endif 6#endif
7#define __user 7#define __user
8#ifndef __attribute_const__
8#define __attribute_const__ 9#define __attribute_const__
10#endif
9 11
10#define __used __attribute__((__unused__)) 12#define __used __attribute__((__unused__))
11 13
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 41982c373fa..928918b796b 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -86,22 +86,24 @@ static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
86 86
87#define MAX_ALIASES 8 87#define MAX_ALIASES 8
88 88
89static const char *hw_cache[][MAX_ALIASES] = { 89static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = {
90 { "L1-dcache", "l1-d", "l1d", "L1-data", }, 90 { "L1-dcache", "l1-d", "l1d", "L1-data", },
91 { "L1-icache", "l1-i", "l1i", "L1-instruction", }, 91 { "L1-icache", "l1-i", "l1i", "L1-instruction", },
92 { "LLC", "L2" }, 92 { "LLC", "L2", },
93 { "dTLB", "d-tlb", "Data-TLB", }, 93 { "dTLB", "d-tlb", "Data-TLB", },
94 { "iTLB", "i-tlb", "Instruction-TLB", }, 94 { "iTLB", "i-tlb", "Instruction-TLB", },
95 { "branch", "branches", "bpu", "btb", "bpc", }, 95 { "branch", "branches", "bpu", "btb", "bpc", },
96 { "node", },
96}; 97};
97 98
98static const char *hw_cache_op[][MAX_ALIASES] = { 99static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = {
99 { "load", "loads", "read", }, 100 { "load", "loads", "read", },
100 { "store", "stores", "write", }, 101 { "store", "stores", "write", },
101 { "prefetch", "prefetches", "speculative-read", "speculative-load", }, 102 { "prefetch", "prefetches", "speculative-read", "speculative-load", },
102}; 103};
103 104
104static const char *hw_cache_result[][MAX_ALIASES] = { 105static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
106 [MAX_ALIASES] = {
105 { "refs", "Reference", "ops", "access", }, 107 { "refs", "Reference", "ops", "access", },
106 { "misses", "miss", }, 108 { "misses", "miss", },
107}; 109};
@@ -124,6 +126,7 @@ static unsigned long hw_cache_stat[C(MAX)] = {
124 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), 126 [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
125 [C(ITLB)] = (CACHE_READ), 127 [C(ITLB)] = (CACHE_READ),
126 [C(BPU)] = (CACHE_READ), 128 [C(BPU)] = (CACHE_READ),
129 [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
127}; 130};
128 131
129#define for_each_subsystem(sys_dir, sys_dirent, sys_next) \ 132#define for_each_subsystem(sys_dir, sys_dirent, sys_next) \
@@ -393,7 +396,7 @@ parse_generic_hw_event(const char **str, struct perf_event_attr *attr)
393 PERF_COUNT_HW_CACHE_OP_MAX); 396 PERF_COUNT_HW_CACHE_OP_MAX);
394 if (cache_op >= 0) { 397 if (cache_op >= 0) {
395 if (!is_cache_op_valid(cache_type, cache_op)) 398 if (!is_cache_op_valid(cache_type, cache_op))
396 return 0; 399 return EVT_FAILED;
397 continue; 400 continue;
398 } 401 }
399 } 402 }
@@ -475,7 +478,7 @@ parse_single_tracepoint_event(char *sys_name,
475/* sys + ':' + event + ':' + flags*/ 478/* sys + ':' + event + ':' + flags*/
476#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128) 479#define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128)
477static enum event_result 480static enum event_result
478parse_multiple_tracepoint_event(const struct option *opt, char *sys_name, 481parse_multiple_tracepoint_event(struct perf_evlist *evlist, char *sys_name,
479 const char *evt_exp, char *flags) 482 const char *evt_exp, char *flags)
480{ 483{
481 char evt_path[MAXPATHLEN]; 484 char evt_path[MAXPATHLEN];
@@ -509,7 +512,7 @@ parse_multiple_tracepoint_event(const struct option *opt, char *sys_name,
509 if (len < 0) 512 if (len < 0)
510 return EVT_FAILED; 513 return EVT_FAILED;
511 514
512 if (parse_events(opt, event_opt, 0)) 515 if (parse_events(evlist, event_opt, 0))
513 return EVT_FAILED; 516 return EVT_FAILED;
514 } 517 }
515 518
@@ -517,7 +520,7 @@ parse_multiple_tracepoint_event(const struct option *opt, char *sys_name,
517} 520}
518 521
519static enum event_result 522static enum event_result
520parse_tracepoint_event(const struct option *opt, const char **strp, 523parse_tracepoint_event(struct perf_evlist *evlist, const char **strp,
521 struct perf_event_attr *attr) 524 struct perf_event_attr *attr)
522{ 525{
523 const char *evt_name; 526 const char *evt_name;
@@ -557,8 +560,8 @@ parse_tracepoint_event(const struct option *opt, const char **strp,
557 return EVT_FAILED; 560 return EVT_FAILED;
558 if (strpbrk(evt_name, "*?")) { 561 if (strpbrk(evt_name, "*?")) {
559 *strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */ 562 *strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */
560 return parse_multiple_tracepoint_event(opt, sys_name, evt_name, 563 return parse_multiple_tracepoint_event(evlist, sys_name,
561 flags); 564 evt_name, flags);
562 } else { 565 } else {
563 return parse_single_tracepoint_event(sys_name, evt_name, 566 return parse_single_tracepoint_event(sys_name, evt_name,
564 evt_length, attr, strp); 567 evt_length, attr, strp);
@@ -694,7 +697,11 @@ parse_raw_event(const char **strp, struct perf_event_attr *attr)
694 return EVT_FAILED; 697 return EVT_FAILED;
695 n = hex2u64(str + 1, &config); 698 n = hex2u64(str + 1, &config);
696 if (n > 0) { 699 if (n > 0) {
697 *strp = str + n + 1; 700 const char *end = str + n + 1;
701 if (*end != '\0' && *end != ',' && *end != ':')
702 return EVT_FAILED;
703
704 *strp = end;
698 attr->type = PERF_TYPE_RAW; 705 attr->type = PERF_TYPE_RAW;
699 attr->config = config; 706 attr->config = config;
700 return EVT_HANDLED; 707 return EVT_HANDLED;
@@ -778,12 +785,12 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr)
778 * Symbolic names are (almost) exactly matched. 785 * Symbolic names are (almost) exactly matched.
779 */ 786 */
780static enum event_result 787static enum event_result
781parse_event_symbols(const struct option *opt, const char **str, 788parse_event_symbols(struct perf_evlist *evlist, const char **str,
782 struct perf_event_attr *attr) 789 struct perf_event_attr *attr)
783{ 790{
784 enum event_result ret; 791 enum event_result ret;
785 792
786 ret = parse_tracepoint_event(opt, str, attr); 793 ret = parse_tracepoint_event(evlist, str, attr);
787 if (ret != EVT_FAILED) 794 if (ret != EVT_FAILED)
788 goto modifier; 795 goto modifier;
789 796
@@ -822,9 +829,8 @@ modifier:
822 return ret; 829 return ret;
823} 830}
824 831
825int parse_events(const struct option *opt, const char *str, int unset __used) 832int parse_events(struct perf_evlist *evlist , const char *str, int unset __used)
826{ 833{
827 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
828 struct perf_event_attr attr; 834 struct perf_event_attr attr;
829 enum event_result ret; 835 enum event_result ret;
830 const char *ostr; 836 const char *ostr;
@@ -832,7 +838,7 @@ int parse_events(const struct option *opt, const char *str, int unset __used)
832 for (;;) { 838 for (;;) {
833 ostr = str; 839 ostr = str;
834 memset(&attr, 0, sizeof(attr)); 840 memset(&attr, 0, sizeof(attr));
835 ret = parse_event_symbols(opt, &str, &attr); 841 ret = parse_event_symbols(evlist, &str, &attr);
836 if (ret == EVT_FAILED) 842 if (ret == EVT_FAILED)
837 return -1; 843 return -1;
838 844
@@ -863,6 +869,13 @@ int parse_events(const struct option *opt, const char *str, int unset __used)
863 return 0; 869 return 0;
864} 870}
865 871
872int parse_events_option(const struct option *opt, const char *str,
873 int unset __used)
874{
875 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
876 return parse_events(evlist, str, unset);
877}
878
866int parse_filter(const struct option *opt, const char *str, 879int parse_filter(const struct option *opt, const char *str,
867 int unset __used) 880 int unset __used)
868{ 881{
@@ -1088,6 +1101,4 @@ void print_events(const char *event_glob)
1088 printf("\n"); 1101 printf("\n");
1089 1102
1090 print_tracepoint_events(NULL, NULL); 1103 print_tracepoint_events(NULL, NULL);
1091
1092 exit(129);
1093} 1104}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 746d3fcbfc2..2f8e375e038 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -8,6 +8,7 @@
8 8
9struct list_head; 9struct list_head;
10struct perf_evsel; 10struct perf_evsel;
11struct perf_evlist;
11 12
12struct option; 13struct option;
13 14
@@ -24,7 +25,10 @@ const char *event_type(int type);
24const char *event_name(struct perf_evsel *event); 25const char *event_name(struct perf_evsel *event);
25extern const char *__event_name(int type, u64 config); 26extern const char *__event_name(int type, u64 config);
26 27
27extern int parse_events(const struct option *opt, const char *str, int unset); 28extern int parse_events_option(const struct option *opt, const char *str,
29 int unset);
30extern int parse_events(struct perf_evlist *evlist, const char *str,
31 int unset);
28extern int parse_filter(const struct option *opt, const char *str, int unset); 32extern int parse_filter(const struct option *opt, const char *str, int unset);
29 33
30#define EVENTS_HELP_MAX (128*1024) 34#define EVENTS_HELP_MAX (128*1024)
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index f0223166e76..eb25900e221 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -117,6 +117,10 @@ static struct map *kernel_get_module_map(const char *module)
117 struct rb_node *nd; 117 struct rb_node *nd;
118 struct map_groups *grp = &machine.kmaps; 118 struct map_groups *grp = &machine.kmaps;
119 119
120 /* A file path -- this is an offline module */
121 if (module && strchr(module, '/'))
122 return machine__new_module(&machine, 0, module);
123
120 if (!module) 124 if (!module)
121 module = "kernel"; 125 module = "kernel";
122 126
@@ -170,16 +174,24 @@ const char *kernel_get_module_path(const char *module)
170} 174}
171 175
172#ifdef DWARF_SUPPORT 176#ifdef DWARF_SUPPORT
173static int open_vmlinux(const char *module) 177/* Open new debuginfo of given module */
178static struct debuginfo *open_debuginfo(const char *module)
174{ 179{
175 const char *path = kernel_get_module_path(module); 180 const char *path;
176 if (!path) { 181
177 pr_err("Failed to find path of %s module.\n", 182 /* A file path -- this is an offline module */
178 module ?: "kernel"); 183 if (module && strchr(module, '/'))
179 return -ENOENT; 184 path = module;
185 else {
186 path = kernel_get_module_path(module);
187
188 if (!path) {
189 pr_err("Failed to find path of %s module.\n",
190 module ?: "kernel");
191 return NULL;
192 }
180 } 193 }
181 pr_debug("Try to open %s\n", path); 194 return debuginfo__new(path);
182 return open(path, O_RDONLY);
183} 195}
184 196
185/* 197/*
@@ -193,13 +205,24 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
193 struct map *map; 205 struct map *map;
194 u64 addr; 206 u64 addr;
195 int ret = -ENOENT; 207 int ret = -ENOENT;
208 struct debuginfo *dinfo;
196 209
197 sym = __find_kernel_function_by_name(tp->symbol, &map); 210 sym = __find_kernel_function_by_name(tp->symbol, &map);
198 if (sym) { 211 if (sym) {
199 addr = map->unmap_ip(map, sym->start + tp->offset); 212 addr = map->unmap_ip(map, sym->start + tp->offset);
200 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol, 213 pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol,
201 tp->offset, addr); 214 tp->offset, addr);
202 ret = find_perf_probe_point((unsigned long)addr, pp); 215
216 dinfo = debuginfo__new_online_kernel(addr);
217 if (dinfo) {
218 ret = debuginfo__find_probe_point(dinfo,
219 (unsigned long)addr, pp);
220 debuginfo__delete(dinfo);
221 } else {
222 pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n",
223 addr);
224 ret = -ENOENT;
225 }
203 } 226 }
204 if (ret <= 0) { 227 if (ret <= 0) {
205 pr_debug("Failed to find corresponding probes from " 228 pr_debug("Failed to find corresponding probes from "
@@ -214,30 +237,70 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp,
214 return 0; 237 return 0;
215} 238}
216 239
240static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
241 int ntevs, const char *module)
242{
243 int i, ret = 0;
244 char *tmp;
245
246 if (!module)
247 return 0;
248
249 tmp = strrchr(module, '/');
250 if (tmp) {
251 /* This is a module path -- get the module name */
252 module = strdup(tmp + 1);
253 if (!module)
254 return -ENOMEM;
255 tmp = strchr(module, '.');
256 if (tmp)
257 *tmp = '\0';
258 tmp = (char *)module; /* For free() */
259 }
260
261 for (i = 0; i < ntevs; i++) {
262 tevs[i].point.module = strdup(module);
263 if (!tevs[i].point.module) {
264 ret = -ENOMEM;
265 break;
266 }
267 }
268
269 if (tmp)
270 free(tmp);
271
272 return ret;
273}
274
217/* Try to find perf_probe_event with debuginfo */ 275/* Try to find perf_probe_event with debuginfo */
218static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 276static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
219 struct probe_trace_event **tevs, 277 struct probe_trace_event **tevs,
220 int max_tevs, const char *module) 278 int max_tevs, const char *module)
221{ 279{
222 bool need_dwarf = perf_probe_event_need_dwarf(pev); 280 bool need_dwarf = perf_probe_event_need_dwarf(pev);
223 int fd, ntevs; 281 struct debuginfo *dinfo = open_debuginfo(module);
282 int ntevs, ret = 0;
224 283
225 fd = open_vmlinux(module); 284 if (!dinfo) {
226 if (fd < 0) {
227 if (need_dwarf) { 285 if (need_dwarf) {
228 pr_warning("Failed to open debuginfo file.\n"); 286 pr_warning("Failed to open debuginfo file.\n");
229 return fd; 287 return -ENOENT;
230 } 288 }
231 pr_debug("Could not open vmlinux. Try to use symbols.\n"); 289 pr_debug("Could not open debuginfo. Try to use symbols.\n");
232 return 0; 290 return 0;
233 } 291 }
234 292
235 /* Searching trace events corresponding to probe event */ 293 /* Searching trace events corresponding to a probe event */
236 ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); 294 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
295
296 debuginfo__delete(dinfo);
237 297
238 if (ntevs > 0) { /* Succeeded to find trace events */ 298 if (ntevs > 0) { /* Succeeded to find trace events */
239 pr_debug("find %d probe_trace_events.\n", ntevs); 299 pr_debug("find %d probe_trace_events.\n", ntevs);
240 return ntevs; 300 if (module)
301 ret = add_module_to_probe_trace_events(*tevs, ntevs,
302 module);
303 return ret < 0 ? ret : ntevs;
241 } 304 }
242 305
243 if (ntevs == 0) { /* No error but failed to find probe point. */ 306 if (ntevs == 0) { /* No error but failed to find probe point. */
@@ -371,8 +434,9 @@ int show_line_range(struct line_range *lr, const char *module)
371{ 434{
372 int l = 1; 435 int l = 1;
373 struct line_node *ln; 436 struct line_node *ln;
437 struct debuginfo *dinfo;
374 FILE *fp; 438 FILE *fp;
375 int fd, ret; 439 int ret;
376 char *tmp; 440 char *tmp;
377 441
378 /* Search a line range */ 442 /* Search a line range */
@@ -380,13 +444,14 @@ int show_line_range(struct line_range *lr, const char *module)
380 if (ret < 0) 444 if (ret < 0)
381 return ret; 445 return ret;
382 446
383 fd = open_vmlinux(module); 447 dinfo = open_debuginfo(module);
384 if (fd < 0) { 448 if (!dinfo) {
385 pr_warning("Failed to open debuginfo file.\n"); 449 pr_warning("Failed to open debuginfo file.\n");
386 return fd; 450 return -ENOENT;
387 } 451 }
388 452
389 ret = find_line_range(fd, lr); 453 ret = debuginfo__find_line_range(dinfo, lr);
454 debuginfo__delete(dinfo);
390 if (ret == 0) { 455 if (ret == 0) {
391 pr_warning("Specified source line is not found.\n"); 456 pr_warning("Specified source line is not found.\n");
392 return -ENOENT; 457 return -ENOENT;
@@ -448,7 +513,8 @@ end:
448 return ret; 513 return ret;
449} 514}
450 515
451static int show_available_vars_at(int fd, struct perf_probe_event *pev, 516static int show_available_vars_at(struct debuginfo *dinfo,
517 struct perf_probe_event *pev,
452 int max_vls, struct strfilter *_filter, 518 int max_vls, struct strfilter *_filter,
453 bool externs) 519 bool externs)
454{ 520{
@@ -463,7 +529,8 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,
463 return -EINVAL; 529 return -EINVAL;
464 pr_debug("Searching variables at %s\n", buf); 530 pr_debug("Searching variables at %s\n", buf);
465 531
466 ret = find_available_vars_at(fd, pev, &vls, max_vls, externs); 532 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
533 max_vls, externs);
467 if (ret <= 0) { 534 if (ret <= 0) {
468 pr_err("Failed to find variables at %s (%d)\n", buf, ret); 535 pr_err("Failed to find variables at %s (%d)\n", buf, ret);
469 goto end; 536 goto end;
@@ -504,24 +571,26 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
504 int max_vls, const char *module, 571 int max_vls, const char *module,
505 struct strfilter *_filter, bool externs) 572 struct strfilter *_filter, bool externs)
506{ 573{
507 int i, fd, ret = 0; 574 int i, ret = 0;
575 struct debuginfo *dinfo;
508 576
509 ret = init_vmlinux(); 577 ret = init_vmlinux();
510 if (ret < 0) 578 if (ret < 0)
511 return ret; 579 return ret;
512 580
581 dinfo = open_debuginfo(module);
582 if (!dinfo) {
583 pr_warning("Failed to open debuginfo file.\n");
584 return -ENOENT;
585 }
586
513 setup_pager(); 587 setup_pager();
514 588
515 for (i = 0; i < npevs && ret >= 0; i++) { 589 for (i = 0; i < npevs && ret >= 0; i++)
516 fd = open_vmlinux(module); 590 ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
517 if (fd < 0) {
518 pr_warning("Failed to open debug information file.\n");
519 ret = fd;
520 break;
521 }
522 ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter,
523 externs); 591 externs);
524 } 592
593 debuginfo__delete(dinfo);
525 return ret; 594 return ret;
526} 595}
527 596
@@ -990,7 +1059,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
990 1059
991/* Parse probe_events event into struct probe_point */ 1060/* Parse probe_events event into struct probe_point */
992static int parse_probe_trace_command(const char *cmd, 1061static int parse_probe_trace_command(const char *cmd,
993 struct probe_trace_event *tev) 1062 struct probe_trace_event *tev)
994{ 1063{
995 struct probe_trace_point *tp = &tev->point; 1064 struct probe_trace_point *tp = &tev->point;
996 char pr; 1065 char pr;
@@ -1023,8 +1092,14 @@ static int parse_probe_trace_command(const char *cmd,
1023 1092
1024 tp->retprobe = (pr == 'r'); 1093 tp->retprobe = (pr == 'r');
1025 1094
1026 /* Scan function name and offset */ 1095 /* Scan module name(if there), function name and offset */
1027 ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol, 1096 p = strchr(argv[1], ':');
1097 if (p) {
1098 tp->module = strndup(argv[1], p - argv[1]);
1099 p++;
1100 } else
1101 p = argv[1];
1102 ret = sscanf(p, "%a[^+]+%lu", (float *)(void *)&tp->symbol,
1028 &tp->offset); 1103 &tp->offset);
1029 if (ret == 1) 1104 if (ret == 1)
1030 tp->offset = 0; 1105 tp->offset = 0;
@@ -1269,9 +1344,10 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1269 if (buf == NULL) 1344 if (buf == NULL)
1270 return NULL; 1345 return NULL;
1271 1346
1272 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu", 1347 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu",
1273 tp->retprobe ? 'r' : 'p', 1348 tp->retprobe ? 'r' : 'p',
1274 tev->group, tev->event, 1349 tev->group, tev->event,
1350 tp->module ?: "", tp->module ? ":" : "",
1275 tp->symbol, tp->offset); 1351 tp->symbol, tp->offset);
1276 if (len <= 0) 1352 if (len <= 0)
1277 goto error; 1353 goto error;
@@ -1378,6 +1454,8 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
1378 free(tev->group); 1454 free(tev->group);
1379 if (tev->point.symbol) 1455 if (tev->point.symbol)
1380 free(tev->point.symbol); 1456 free(tev->point.symbol);
1457 if (tev->point.module)
1458 free(tev->point.module);
1381 for (i = 0; i < tev->nargs; i++) { 1459 for (i = 0; i < tev->nargs; i++) {
1382 if (tev->args[i].name) 1460 if (tev->args[i].name)
1383 free(tev->args[i].name); 1461 free(tev->args[i].name);
@@ -1729,7 +1807,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1729 /* Convert perf_probe_event with debuginfo */ 1807 /* Convert perf_probe_event with debuginfo */
1730 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module); 1808 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module);
1731 if (ret != 0) 1809 if (ret != 0)
1732 return ret; 1810 return ret; /* Found in debuginfo or got an error */
1733 1811
1734 /* Allocate trace event buffer */ 1812 /* Allocate trace event buffer */
1735 tev = *tevs = zalloc(sizeof(struct probe_trace_event)); 1813 tev = *tevs = zalloc(sizeof(struct probe_trace_event));
@@ -1742,6 +1820,15 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
1742 ret = -ENOMEM; 1820 ret = -ENOMEM;
1743 goto error; 1821 goto error;
1744 } 1822 }
1823
1824 if (module) {
1825 tev->point.module = strdup(module);
1826 if (tev->point.module == NULL) {
1827 ret = -ENOMEM;
1828 goto error;
1829 }
1830 }
1831
1745 tev->point.offset = pev->point.offset; 1832 tev->point.offset = pev->point.offset;
1746 tev->point.retprobe = pev->point.retprobe; 1833 tev->point.retprobe = pev->point.retprobe;
1747 tev->nargs = pev->nargs; 1834 tev->nargs = pev->nargs;
@@ -1869,8 +1956,10 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
1869 1956
1870 pr_debug("Writing event: %s\n", buf); 1957 pr_debug("Writing event: %s\n", buf);
1871 ret = write(fd, buf, strlen(buf)); 1958 ret = write(fd, buf, strlen(buf));
1872 if (ret < 0) 1959 if (ret < 0) {
1960 ret = -errno;
1873 goto error; 1961 goto error;
1962 }
1874 1963
1875 printf("Remove event: %s\n", ent->s); 1964 printf("Remove event: %s\n", ent->s);
1876 return 0; 1965 return 0;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 3434fc9d79d..a7dee835f49 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -10,6 +10,7 @@ extern bool probe_event_dry_run;
10/* kprobe-tracer tracing point */ 10/* kprobe-tracer tracing point */
11struct probe_trace_point { 11struct probe_trace_point {
12 char *symbol; /* Base symbol */ 12 char *symbol; /* Base symbol */
13 char *module; /* Module name */
13 unsigned long offset; /* Offset from symbol */ 14 unsigned long offset; /* Offset from symbol */
14 bool retprobe; /* Return probe flag */ 15 bool retprobe; /* Return probe flag */
15}; 16};
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 3b9d0b800d5..5d732621a46 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -43,21 +43,6 @@
43/* Kprobe tracer basic type is up to u64 */ 43/* Kprobe tracer basic type is up to u64 */
44#define MAX_BASIC_TYPE_BITS 64 44#define MAX_BASIC_TYPE_BITS 64
45 45
46/*
47 * Compare the tail of two strings.
48 * Return 0 if whole of either string is same as another's tail part.
49 */
50static int strtailcmp(const char *s1, const char *s2)
51{
52 int i1 = strlen(s1);
53 int i2 = strlen(s2);
54 while (--i1 >= 0 && --i2 >= 0) {
55 if (s1[i1] != s2[i2])
56 return s1[i1] - s2[i2];
57 }
58 return 0;
59}
60
61/* Line number list operations */ 46/* Line number list operations */
62 47
63/* Add a line to line number list */ 48/* Add a line to line number list */
@@ -131,29 +116,37 @@ static const Dwfl_Callbacks offline_callbacks = {
131}; 116};
132 117
133/* Get a Dwarf from offline image */ 118/* Get a Dwarf from offline image */
134static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias) 119static int debuginfo__init_offline_dwarf(struct debuginfo *self,
120 const char *path)
135{ 121{
136 Dwfl_Module *mod; 122 Dwfl_Module *mod;
137 Dwarf *dbg = NULL; 123 int fd;
138 124
139 if (!dwflp) 125 fd = open(path, O_RDONLY);
140 return NULL; 126 if (fd < 0)
127 return fd;
141 128
142 *dwflp = dwfl_begin(&offline_callbacks); 129 self->dwfl = dwfl_begin(&offline_callbacks);
143 if (!*dwflp) 130 if (!self->dwfl)
144 return NULL; 131 goto error;
145 132
146 mod = dwfl_report_offline(*dwflp, "", "", fd); 133 mod = dwfl_report_offline(self->dwfl, "", "", fd);
147 if (!mod) 134 if (!mod)
148 goto error; 135 goto error;
149 136
150 dbg = dwfl_module_getdwarf(mod, bias); 137 self->dbg = dwfl_module_getdwarf(mod, &self->bias);
151 if (!dbg) { 138 if (!self->dbg)
139 goto error;
140
141 return 0;
152error: 142error:
153 dwfl_end(*dwflp); 143 if (self->dwfl)
154 *dwflp = NULL; 144 dwfl_end(self->dwfl);
155 } 145 else
156 return dbg; 146 close(fd);
147 memset(self, 0, sizeof(*self));
148
149 return -ENOENT;
157} 150}
158 151
159#if _ELFUTILS_PREREQ(0, 148) 152#if _ELFUTILS_PREREQ(0, 148)
@@ -189,597 +182,81 @@ static const Dwfl_Callbacks kernel_callbacks = {
189}; 182};
190 183
191/* Get a Dwarf from live kernel image */ 184/* Get a Dwarf from live kernel image */
192static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp, 185static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
193 Dwarf_Addr *bias) 186 Dwarf_Addr addr)
194{ 187{
195 Dwarf *dbg; 188 self->dwfl = dwfl_begin(&kernel_callbacks);
196 189 if (!self->dwfl)
197 if (!dwflp) 190 return -EINVAL;
198 return NULL;
199
200 *dwflp = dwfl_begin(&kernel_callbacks);
201 if (!*dwflp)
202 return NULL;
203 191
204 /* Load the kernel dwarves: Don't care the result here */ 192 /* Load the kernel dwarves: Don't care the result here */
205 dwfl_linux_kernel_report_kernel(*dwflp); 193 dwfl_linux_kernel_report_kernel(self->dwfl);
206 dwfl_linux_kernel_report_modules(*dwflp); 194 dwfl_linux_kernel_report_modules(self->dwfl);
207 195
208 dbg = dwfl_addrdwarf(*dwflp, addr, bias); 196 self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias);
209 /* Here, check whether we could get a real dwarf */ 197 /* Here, check whether we could get a real dwarf */
210 if (!dbg) { 198 if (!self->dbg) {
211 pr_debug("Failed to find kernel dwarf at %lx\n", 199 pr_debug("Failed to find kernel dwarf at %lx\n",
212 (unsigned long)addr); 200 (unsigned long)addr);
213 dwfl_end(*dwflp); 201 dwfl_end(self->dwfl);
214 *dwflp = NULL; 202 memset(self, 0, sizeof(*self));
203 return -ENOENT;
215 } 204 }
216 return dbg; 205
206 return 0;
217} 207}
218#else 208#else
219/* With older elfutils, this just support kernel module... */ 209/* With older elfutils, this just support kernel module... */
220static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp, 210static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
221 Dwarf_Addr *bias) 211 Dwarf_Addr addr __used)
222{ 212{
223 int fd;
224 const char *path = kernel_get_module_path("kernel"); 213 const char *path = kernel_get_module_path("kernel");
225 214
226 if (!path) { 215 if (!path) {
227 pr_err("Failed to find vmlinux path\n"); 216 pr_err("Failed to find vmlinux path\n");
228 return NULL; 217 return -ENOENT;
229 } 218 }
230 219
231 pr_debug2("Use file %s for debuginfo\n", path); 220 pr_debug2("Use file %s for debuginfo\n", path);
232 fd = open(path, O_RDONLY); 221 return debuginfo__init_offline_dwarf(self, path);
233 if (fd < 0)
234 return NULL;
235
236 return dwfl_init_offline_dwarf(fd, dwflp, bias);
237} 222}
238#endif 223#endif
239 224
240/* Dwarf wrappers */ 225struct debuginfo *debuginfo__new(const char *path)
241
242/* Find the realpath of the target file. */
243static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
244{ 226{
245 Dwarf_Files *files; 227 struct debuginfo *self = zalloc(sizeof(struct debuginfo));
246 size_t nfiles, i; 228 if (!self)
247 const char *src = NULL;
248 int ret;
249
250 if (!fname)
251 return NULL; 229 return NULL;
252 230
253 ret = dwarf_getsrcfiles(cu_die, &files, &nfiles); 231 if (debuginfo__init_offline_dwarf(self, path) < 0) {
254 if (ret != 0) 232 free(self);
255 return NULL; 233 self = NULL;
256
257 for (i = 0; i < nfiles; i++) {
258 src = dwarf_filesrc(files, i, NULL, NULL);
259 if (strtailcmp(src, fname) == 0)
260 break;
261 } 234 }
262 if (i == nfiles)
263 return NULL;
264 return src;
265}
266 235
267/* Get DW_AT_comp_dir (should be NULL with older gcc) */ 236 return self;
268static const char *cu_get_comp_dir(Dwarf_Die *cu_die)
269{
270 Dwarf_Attribute attr;
271 if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
272 return NULL;
273 return dwarf_formstring(&attr);
274} 237}
275 238
276/* Get a line number and file name for given address */ 239struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
277static int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
278 const char **fname, int *lineno)
279{ 240{
280 Dwarf_Line *line; 241 struct debuginfo *self = zalloc(sizeof(struct debuginfo));
281 Dwarf_Addr laddr; 242 if (!self)
282
283 line = dwarf_getsrc_die(cudie, (Dwarf_Addr)addr);
284 if (line && dwarf_lineaddr(line, &laddr) == 0 &&
285 addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
286 *fname = dwarf_linesrc(line, NULL, NULL);
287 if (!*fname)
288 /* line number is useless without filename */
289 *lineno = 0;
290 }
291
292 return *lineno ?: -ENOENT;
293}
294
295/* Compare diename and tname */
296static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
297{
298 const char *name;
299 name = dwarf_diename(dw_die);
300 return name ? (strcmp(tname, name) == 0) : false;
301}
302
303/* Get callsite line number of inline-function instance */
304static int die_get_call_lineno(Dwarf_Die *in_die)
305{
306 Dwarf_Attribute attr;
307 Dwarf_Word ret;
308
309 if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
310 return -ENOENT;
311
312 dwarf_formudata(&attr, &ret);
313 return (int)ret;
314}
315
316/* Get type die */
317static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
318{
319 Dwarf_Attribute attr;
320
321 if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
322 dwarf_formref_die(&attr, die_mem))
323 return die_mem;
324 else
325 return NULL; 243 return NULL;
326}
327
328/* Get a type die, but skip qualifiers */
329static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
330{
331 int tag;
332
333 do {
334 vr_die = die_get_type(vr_die, die_mem);
335 if (!vr_die)
336 break;
337 tag = dwarf_tag(vr_die);
338 } while (tag == DW_TAG_const_type ||
339 tag == DW_TAG_restrict_type ||
340 tag == DW_TAG_volatile_type ||
341 tag == DW_TAG_shared_type);
342
343 return vr_die;
344}
345
346/* Get a type die, but skip qualifiers and typedef */
347static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
348{
349 do {
350 vr_die = __die_get_real_type(vr_die, die_mem);
351 } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
352
353 return vr_die;
354}
355
356static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
357 Dwarf_Word *result)
358{
359 Dwarf_Attribute attr;
360
361 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
362 dwarf_formudata(&attr, result) != 0)
363 return -ENOENT;
364
365 return 0;
366}
367 244
368static bool die_is_signed_type(Dwarf_Die *tp_die) 245 if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) {
369{ 246 free(self);
370 Dwarf_Word ret; 247 self = NULL;
371
372 if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
373 return false;
374
375 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
376 ret == DW_ATE_signed_fixed);
377}
378
379static int die_get_byte_size(Dwarf_Die *tp_die)
380{
381 Dwarf_Word ret;
382
383 if (die_get_attr_udata(tp_die, DW_AT_byte_size, &ret))
384 return 0;
385
386 return (int)ret;
387}
388
389static int die_get_bit_size(Dwarf_Die *tp_die)
390{
391 Dwarf_Word ret;
392
393 if (die_get_attr_udata(tp_die, DW_AT_bit_size, &ret))
394 return 0;
395
396 return (int)ret;
397}
398
399static int die_get_bit_offset(Dwarf_Die *tp_die)
400{
401 Dwarf_Word ret;
402
403 if (die_get_attr_udata(tp_die, DW_AT_bit_offset, &ret))
404 return 0;
405
406 return (int)ret;
407}
408
409/* Get data_member_location offset */
410static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
411{
412 Dwarf_Attribute attr;
413 Dwarf_Op *expr;
414 size_t nexpr;
415 int ret;
416
417 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
418 return -ENOENT;
419
420 if (dwarf_formudata(&attr, offs) != 0) {
421 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
422 ret = dwarf_getlocation(&attr, &expr, &nexpr);
423 if (ret < 0 || nexpr == 0)
424 return -ENOENT;
425
426 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
427 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
428 expr[0].atom, nexpr);
429 return -ENOTSUP;
430 }
431 *offs = (Dwarf_Word)expr[0].number;
432 }
433 return 0;
434}
435
436/* Return values for die_find callbacks */
437enum {
438 DIE_FIND_CB_FOUND = 0, /* End of Search */
439 DIE_FIND_CB_CHILD = 1, /* Search only children */
440 DIE_FIND_CB_SIBLING = 2, /* Search only siblings */
441 DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */
442};
443
444/* Search a child die */
445static Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
446 int (*callback)(Dwarf_Die *, void *),
447 void *data, Dwarf_Die *die_mem)
448{
449 Dwarf_Die child_die;
450 int ret;
451
452 ret = dwarf_child(rt_die, die_mem);
453 if (ret != 0)
454 return NULL;
455
456 do {
457 ret = callback(die_mem, data);
458 if (ret == DIE_FIND_CB_FOUND)
459 return die_mem;
460
461 if ((ret & DIE_FIND_CB_CHILD) &&
462 die_find_child(die_mem, callback, data, &child_die)) {
463 memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
464 return die_mem;
465 }
466 } while ((ret & DIE_FIND_CB_SIBLING) &&
467 dwarf_siblingof(die_mem, die_mem) == 0);
468
469 return NULL;
470}
471
472struct __addr_die_search_param {
473 Dwarf_Addr addr;
474 Dwarf_Die *die_mem;
475};
476
477static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
478{
479 struct __addr_die_search_param *ad = data;
480
481 if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
482 dwarf_haspc(fn_die, ad->addr)) {
483 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
484 return DWARF_CB_ABORT;
485 } 248 }
486 return DWARF_CB_OK;
487}
488 249
489/* Search a real subprogram including this line, */ 250 return self;
490static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
491 Dwarf_Die *die_mem)
492{
493 struct __addr_die_search_param ad;
494 ad.addr = addr;
495 ad.die_mem = die_mem;
496 /* dwarf_getscopes can't find subprogram. */
497 if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
498 return NULL;
499 else
500 return die_mem;
501} 251}
502 252
503/* die_find callback for inline function search */ 253void debuginfo__delete(struct debuginfo *self)
504static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
505{ 254{
506 Dwarf_Addr *addr = data; 255 if (self) {
507 256 if (self->dwfl)
508 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine && 257 dwfl_end(self->dwfl);
509 dwarf_haspc(die_mem, *addr)) 258 free(self);
510 return DIE_FIND_CB_FOUND;
511
512 return DIE_FIND_CB_CONTINUE;
513}
514
515/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */
516static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
517 Dwarf_Die *die_mem)
518{
519 Dwarf_Die tmp_die;
520
521 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
522 if (!sp_die)
523 return NULL;
524
525 /* Inlined function could be recursive. Trace it until fail */
526 while (sp_die) {
527 memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
528 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
529 &tmp_die);
530 }
531
532 return die_mem;
533}
534
535/* Walker on lines (Note: line number will not be sorted) */
536typedef int (* line_walk_handler_t) (const char *fname, int lineno,
537 Dwarf_Addr addr, void *data);
538
539struct __line_walk_param {
540 const char *fname;
541 line_walk_handler_t handler;
542 void *data;
543 int retval;
544};
545
546static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
547{
548 struct __line_walk_param *lw = data;
549 Dwarf_Addr addr;
550 int lineno;
551
552 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
553 lineno = die_get_call_lineno(in_die);
554 if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
555 lw->retval = lw->handler(lw->fname, lineno, addr,
556 lw->data);
557 if (lw->retval != 0)
558 return DIE_FIND_CB_FOUND;
559 }
560 } 259 }
561 return DIE_FIND_CB_SIBLING;
562}
563
564/* Walk on lines of blocks included in given DIE */
565static int __die_walk_funclines(Dwarf_Die *sp_die,
566 line_walk_handler_t handler, void *data)
567{
568 struct __line_walk_param lw = {
569 .handler = handler,
570 .data = data,
571 .retval = 0,
572 };
573 Dwarf_Die die_mem;
574 Dwarf_Addr addr;
575 int lineno;
576
577 /* Handle function declaration line */
578 lw.fname = dwarf_decl_file(sp_die);
579 if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
580 dwarf_entrypc(sp_die, &addr) == 0) {
581 lw.retval = handler(lw.fname, lineno, addr, data);
582 if (lw.retval != 0)
583 goto done;
584 }
585 die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
586done:
587 return lw.retval;
588}
589
590static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
591{
592 struct __line_walk_param *lw = data;
593
594 lw->retval = __die_walk_funclines(sp_die, lw->handler, lw->data);
595 if (lw->retval != 0)
596 return DWARF_CB_ABORT;
597
598 return DWARF_CB_OK;
599}
600
601/*
602 * Walk on lines inside given PDIE. If the PDIE is subprogram, walk only on
603 * the lines inside the subprogram, otherwise PDIE must be a CU DIE.
604 */
605static int die_walk_lines(Dwarf_Die *pdie, line_walk_handler_t handler,
606 void *data)
607{
608 Dwarf_Lines *lines;
609 Dwarf_Line *line;
610 Dwarf_Addr addr;
611 const char *fname;
612 int lineno, ret = 0;
613 Dwarf_Die die_mem, *cu_die;
614 size_t nlines, i;
615
616 /* Get the CU die */
617 if (dwarf_tag(pdie) == DW_TAG_subprogram)
618 cu_die = dwarf_diecu(pdie, &die_mem, NULL, NULL);
619 else
620 cu_die = pdie;
621 if (!cu_die) {
622 pr_debug2("Failed to get CU from subprogram\n");
623 return -EINVAL;
624 }
625
626 /* Get lines list in the CU */
627 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
628 pr_debug2("Failed to get source lines on this CU.\n");
629 return -ENOENT;
630 }
631 pr_debug2("Get %zd lines from this CU\n", nlines);
632
633 /* Walk on the lines on lines list */
634 for (i = 0; i < nlines; i++) {
635 line = dwarf_onesrcline(lines, i);
636 if (line == NULL ||
637 dwarf_lineno(line, &lineno) != 0 ||
638 dwarf_lineaddr(line, &addr) != 0) {
639 pr_debug2("Failed to get line info. "
640 "Possible error in debuginfo.\n");
641 continue;
642 }
643 /* Filter lines based on address */
644 if (pdie != cu_die)
645 /*
646 * Address filtering
647 * The line is included in given function, and
648 * no inline block includes it.
649 */
650 if (!dwarf_haspc(pdie, addr) ||
651 die_find_inlinefunc(pdie, addr, &die_mem))
652 continue;
653 /* Get source line */
654 fname = dwarf_linesrc(line, NULL, NULL);
655
656 ret = handler(fname, lineno, addr, data);
657 if (ret != 0)
658 return ret;
659 }
660
661 /*
662 * Dwarf lines doesn't include function declarations and inlined
663 * subroutines. We have to check functions list or given function.
664 */
665 if (pdie != cu_die)
666 ret = __die_walk_funclines(pdie, handler, data);
667 else {
668 struct __line_walk_param param = {
669 .handler = handler,
670 .data = data,
671 .retval = 0,
672 };
673 dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
674 ret = param.retval;
675 }
676
677 return ret;
678}
679
680struct __find_variable_param {
681 const char *name;
682 Dwarf_Addr addr;
683};
684
685static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
686{
687 struct __find_variable_param *fvp = data;
688 int tag;
689
690 tag = dwarf_tag(die_mem);
691 if ((tag == DW_TAG_formal_parameter ||
692 tag == DW_TAG_variable) &&
693 die_compare_name(die_mem, fvp->name))
694 return DIE_FIND_CB_FOUND;
695
696 if (dwarf_haspc(die_mem, fvp->addr))
697 return DIE_FIND_CB_CONTINUE;
698 else
699 return DIE_FIND_CB_SIBLING;
700}
701
702/* Find a variable called 'name' at given address */
703static Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
704 Dwarf_Addr addr, Dwarf_Die *die_mem)
705{
706 struct __find_variable_param fvp = { .name = name, .addr = addr};
707
708 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
709 die_mem);
710}
711
712static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
713{
714 const char *name = data;
715
716 if ((dwarf_tag(die_mem) == DW_TAG_member) &&
717 die_compare_name(die_mem, name))
718 return DIE_FIND_CB_FOUND;
719
720 return DIE_FIND_CB_SIBLING;
721}
722
723/* Find a member called 'name' */
724static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
725 Dwarf_Die *die_mem)
726{
727 return die_find_child(st_die, __die_find_member_cb, (void *)name,
728 die_mem);
729}
730
731/* Get the name of given variable DIE */
732static int die_get_typename(Dwarf_Die *vr_die, char *buf, int len)
733{
734 Dwarf_Die type;
735 int tag, ret, ret2;
736 const char *tmp = "";
737
738 if (__die_get_real_type(vr_die, &type) == NULL)
739 return -ENOENT;
740
741 tag = dwarf_tag(&type);
742 if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
743 tmp = "*";
744 else if (tag == DW_TAG_subroutine_type) {
745 /* Function pointer */
746 ret = snprintf(buf, len, "(function_type)");
747 return (ret >= len) ? -E2BIG : ret;
748 } else {
749 if (!dwarf_diename(&type))
750 return -ENOENT;
751 if (tag == DW_TAG_union_type)
752 tmp = "union ";
753 else if (tag == DW_TAG_structure_type)
754 tmp = "struct ";
755 /* Write a base name */
756 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
757 return (ret >= len) ? -E2BIG : ret;
758 }
759 ret = die_get_typename(&type, buf, len);
760 if (ret > 0) {
761 ret2 = snprintf(buf + ret, len - ret, "%s", tmp);
762 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
763 }
764 return ret;
765}
766
767/* Get the name and type of given variable DIE, stored as "type\tname" */
768static int die_get_varname(Dwarf_Die *vr_die, char *buf, int len)
769{
770 int ret, ret2;
771
772 ret = die_get_typename(vr_die, buf, len);
773 if (ret < 0) {
774 pr_debug("Failed to get type, make it unknown.\n");
775 ret = snprintf(buf, len, "(unknown_type)");
776 }
777 if (ret > 0) {
778 ret2 = snprintf(buf + ret, len - ret, "\t%s",
779 dwarf_diename(vr_die));
780 ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret;
781 }
782 return ret;
783} 260}
784 261
785/* 262/*
@@ -897,6 +374,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
897 struct probe_trace_arg_ref **ref_ptr = &tvar->ref; 374 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
898 Dwarf_Die type; 375 Dwarf_Die type;
899 char buf[16]; 376 char buf[16];
377 int bsize, boffs, total;
900 int ret; 378 int ret;
901 379
902 /* TODO: check all types */ 380 /* TODO: check all types */
@@ -906,11 +384,15 @@ static int convert_variable_type(Dwarf_Die *vr_die,
906 return (tvar->type == NULL) ? -ENOMEM : 0; 384 return (tvar->type == NULL) ? -ENOMEM : 0;
907 } 385 }
908 386
909 if (die_get_bit_size(vr_die) != 0) { 387 bsize = dwarf_bitsize(vr_die);
388 if (bsize > 0) {
910 /* This is a bitfield */ 389 /* This is a bitfield */
911 ret = snprintf(buf, 16, "b%d@%d/%zd", die_get_bit_size(vr_die), 390 boffs = dwarf_bitoffset(vr_die);
912 die_get_bit_offset(vr_die), 391 total = dwarf_bytesize(vr_die);
913 BYTES_TO_BITS(die_get_byte_size(vr_die))); 392 if (boffs < 0 || total < 0)
393 return -ENOENT;
394 ret = snprintf(buf, 16, "b%d@%d/%zd", bsize, boffs,
395 BYTES_TO_BITS(total));
914 goto formatted; 396 goto formatted;
915 } 397 }
916 398
@@ -958,10 +440,11 @@ static int convert_variable_type(Dwarf_Die *vr_die,
958 return (tvar->type == NULL) ? -ENOMEM : 0; 440 return (tvar->type == NULL) ? -ENOMEM : 0;
959 } 441 }
960 442
961 ret = BYTES_TO_BITS(die_get_byte_size(&type)); 443 ret = dwarf_bytesize(&type);
962 if (!ret) 444 if (ret <= 0)
963 /* No size ... try to use default type */ 445 /* No size ... try to use default type */
964 return 0; 446 return 0;
447 ret = BYTES_TO_BITS(ret);
965 448
966 /* Check the bitwidth */ 449 /* Check the bitwidth */
967 if (ret > MAX_BASIC_TYPE_BITS) { 450 if (ret > MAX_BASIC_TYPE_BITS) {
@@ -1025,7 +508,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
1025 else 508 else
1026 *ref_ptr = ref; 509 *ref_ptr = ref;
1027 } 510 }
1028 ref->offset += die_get_byte_size(&type) * field->index; 511 ref->offset += dwarf_bytesize(&type) * field->index;
1029 if (!field->next) 512 if (!field->next)
1030 /* Save vr_die for converting types */ 513 /* Save vr_die for converting types */
1031 memcpy(die_mem, vr_die, sizeof(*die_mem)); 514 memcpy(die_mem, vr_die, sizeof(*die_mem));
@@ -1129,12 +612,12 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
1129 return ret; 612 return ret;
1130} 613}
1131 614
1132/* Find a variable in a subprogram die */ 615/* Find a variable in a scope DIE */
1133static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) 616static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
1134{ 617{
1135 Dwarf_Die vr_die, *scopes; 618 Dwarf_Die vr_die;
1136 char buf[32], *ptr; 619 char buf[32], *ptr;
1137 int ret, nscopes; 620 int ret = 0;
1138 621
1139 if (!is_c_varname(pf->pvar->var)) { 622 if (!is_c_varname(pf->pvar->var)) {
1140 /* Copy raw parameters */ 623 /* Copy raw parameters */
@@ -1169,30 +652,16 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
1169 if (pf->tvar->name == NULL) 652 if (pf->tvar->name == NULL)
1170 return -ENOMEM; 653 return -ENOMEM;
1171 654
1172 pr_debug("Searching '%s' variable in context.\n", 655 pr_debug("Searching '%s' variable in context.\n", pf->pvar->var);
1173 pf->pvar->var);
1174 /* Search child die for local variables and parameters. */ 656 /* Search child die for local variables and parameters. */
1175 if (die_find_variable_at(sp_die, pf->pvar->var, pf->addr, &vr_die)) 657 if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
1176 ret = convert_variable(&vr_die, pf); 658 /* Search again in global variables */
1177 else { 659 if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
1178 /* Search upper class */ 660 ret = -ENOENT;
1179 nscopes = dwarf_getscopes_die(sp_die, &scopes);
1180 while (nscopes-- > 1) {
1181 pr_debug("Searching variables in %s\n",
1182 dwarf_diename(&scopes[nscopes]));
1183 /* We should check this scope, so give dummy address */
1184 if (die_find_variable_at(&scopes[nscopes],
1185 pf->pvar->var, 0,
1186 &vr_die)) {
1187 ret = convert_variable(&vr_die, pf);
1188 goto found;
1189 }
1190 }
1191 if (scopes)
1192 free(scopes);
1193 ret = -ENOENT;
1194 } 661 }
1195found: 662 if (ret >= 0)
663 ret = convert_variable(&vr_die, pf);
664
1196 if (ret < 0) 665 if (ret < 0)
1197 pr_warning("Failed to find '%s' in this function.\n", 666 pr_warning("Failed to find '%s' in this function.\n",
1198 pf->pvar->var); 667 pf->pvar->var);
@@ -1235,27 +704,30 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
1235 return 0; 704 return 0;
1236} 705}
1237 706
1238/* Call probe_finder callback with real subprogram DIE */ 707/* Call probe_finder callback with scope DIE */
1239static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf) 708static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
1240{ 709{
1241 Dwarf_Die die_mem;
1242 Dwarf_Attribute fb_attr; 710 Dwarf_Attribute fb_attr;
1243 size_t nops; 711 size_t nops;
1244 int ret; 712 int ret;
1245 713
1246 /* If no real subprogram, find a real one */ 714 if (!sc_die) {
1247 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) { 715 pr_err("Caller must pass a scope DIE. Program error.\n");
1248 sp_die = die_find_real_subprogram(&pf->cu_die, 716 return -EINVAL;
1249 pf->addr, &die_mem); 717 }
1250 if (!sp_die) { 718
719 /* If not a real subprogram, find a real one */
720 if (dwarf_tag(sc_die) != DW_TAG_subprogram) {
721 if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) {
1251 pr_warning("Failed to find probe point in any " 722 pr_warning("Failed to find probe point in any "
1252 "functions.\n"); 723 "functions.\n");
1253 return -ENOENT; 724 return -ENOENT;
1254 } 725 }
1255 } 726 } else
727 memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
1256 728
1257 /* Get the frame base attribute/ops */ 729 /* Get the frame base attribute/ops from subprogram */
1258 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr); 730 dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr);
1259 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); 731 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
1260 if (ret <= 0 || nops == 0) { 732 if (ret <= 0 || nops == 0) {
1261 pf->fb_ops = NULL; 733 pf->fb_ops = NULL;
@@ -1273,7 +745,7 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
1273 } 745 }
1274 746
1275 /* Call finder's callback handler */ 747 /* Call finder's callback handler */
1276 ret = pf->callback(sp_die, pf); 748 ret = pf->callback(sc_die, pf);
1277 749
1278 /* *pf->fb_ops will be cached in libdw. Don't free it. */ 750 /* *pf->fb_ops will be cached in libdw. Don't free it. */
1279 pf->fb_ops = NULL; 751 pf->fb_ops = NULL;
@@ -1281,17 +753,82 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
1281 return ret; 753 return ret;
1282} 754}
1283 755
756struct find_scope_param {
757 const char *function;
758 const char *file;
759 int line;
760 int diff;
761 Dwarf_Die *die_mem;
762 bool found;
763};
764
765static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
766{
767 struct find_scope_param *fsp = data;
768 const char *file;
769 int lno;
770
771 /* Skip if declared file name does not match */
772 if (fsp->file) {
773 file = dwarf_decl_file(fn_die);
774 if (!file || strcmp(fsp->file, file) != 0)
775 return 0;
776 }
777 /* If the function name is given, that's what user expects */
778 if (fsp->function) {
779 if (die_compare_name(fn_die, fsp->function)) {
780 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
781 fsp->found = true;
782 return 1;
783 }
784 } else {
785 /* With the line number, find the nearest declared DIE */
786 dwarf_decl_line(fn_die, &lno);
787 if (lno < fsp->line && fsp->diff > fsp->line - lno) {
788 /* Keep a candidate and continue */
789 fsp->diff = fsp->line - lno;
790 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
791 fsp->found = true;
792 }
793 }
794 return 0;
795}
796
797/* Find an appropriate scope fits to given conditions */
798static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem)
799{
800 struct find_scope_param fsp = {
801 .function = pf->pev->point.function,
802 .file = pf->fname,
803 .line = pf->lno,
804 .diff = INT_MAX,
805 .die_mem = die_mem,
806 .found = false,
807 };
808
809 cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, &fsp);
810
811 return fsp.found ? die_mem : NULL;
812}
813
1284static int probe_point_line_walker(const char *fname, int lineno, 814static int probe_point_line_walker(const char *fname, int lineno,
1285 Dwarf_Addr addr, void *data) 815 Dwarf_Addr addr, void *data)
1286{ 816{
1287 struct probe_finder *pf = data; 817 struct probe_finder *pf = data;
818 Dwarf_Die *sc_die, die_mem;
1288 int ret; 819 int ret;
1289 820
1290 if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0) 821 if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
1291 return 0; 822 return 0;
1292 823
1293 pf->addr = addr; 824 pf->addr = addr;
1294 ret = call_probe_finder(NULL, pf); 825 sc_die = find_best_scope(pf, &die_mem);
826 if (!sc_die) {
827 pr_warning("Failed to find scope of probe point.\n");
828 return -ENOENT;
829 }
830
831 ret = call_probe_finder(sc_die, pf);
1295 832
1296 /* Continue if no error, because the line will be in inline function */ 833 /* Continue if no error, because the line will be in inline function */
1297 return ret < 0 ? ret : 0; 834 return ret < 0 ? ret : 0;
@@ -1345,6 +882,7 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
1345 Dwarf_Addr addr, void *data) 882 Dwarf_Addr addr, void *data)
1346{ 883{
1347 struct probe_finder *pf = data; 884 struct probe_finder *pf = data;
885 Dwarf_Die *sc_die, die_mem;
1348 int ret; 886 int ret;
1349 887
1350 if (!line_list__has_line(&pf->lcache, lineno) || 888 if (!line_list__has_line(&pf->lcache, lineno) ||
@@ -1354,7 +892,14 @@ static int probe_point_lazy_walker(const char *fname, int lineno,
1354 pr_debug("Probe line found: line:%d addr:0x%llx\n", 892 pr_debug("Probe line found: line:%d addr:0x%llx\n",
1355 lineno, (unsigned long long)addr); 893 lineno, (unsigned long long)addr);
1356 pf->addr = addr; 894 pf->addr = addr;
1357 ret = call_probe_finder(NULL, pf); 895 pf->lno = lineno;
896 sc_die = find_best_scope(pf, &die_mem);
897 if (!sc_die) {
898 pr_warning("Failed to find scope of probe point.\n");
899 return -ENOENT;
900 }
901
902 ret = call_probe_finder(sc_die, pf);
1358 903
1359 /* 904 /*
1360 * Continue if no error, because the lazy pattern will match 905 * Continue if no error, because the lazy pattern will match
@@ -1379,42 +924,39 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
1379 return die_walk_lines(sp_die, probe_point_lazy_walker, pf); 924 return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
1380} 925}
1381 926
1382/* Callback parameter with return value */
1383struct dwarf_callback_param {
1384 void *data;
1385 int retval;
1386};
1387
1388static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) 927static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
1389{ 928{
1390 struct dwarf_callback_param *param = data; 929 struct probe_finder *pf = data;
1391 struct probe_finder *pf = param->data;
1392 struct perf_probe_point *pp = &pf->pev->point; 930 struct perf_probe_point *pp = &pf->pev->point;
1393 Dwarf_Addr addr; 931 Dwarf_Addr addr;
932 int ret;
1394 933
1395 if (pp->lazy_line) 934 if (pp->lazy_line)
1396 param->retval = find_probe_point_lazy(in_die, pf); 935 ret = find_probe_point_lazy(in_die, pf);
1397 else { 936 else {
1398 /* Get probe address */ 937 /* Get probe address */
1399 if (dwarf_entrypc(in_die, &addr) != 0) { 938 if (dwarf_entrypc(in_die, &addr) != 0) {
1400 pr_warning("Failed to get entry address of %s.\n", 939 pr_warning("Failed to get entry address of %s.\n",
1401 dwarf_diename(in_die)); 940 dwarf_diename(in_die));
1402 param->retval = -ENOENT; 941 return -ENOENT;
1403 return DWARF_CB_ABORT;
1404 } 942 }
1405 pf->addr = addr; 943 pf->addr = addr;
1406 pf->addr += pp->offset; 944 pf->addr += pp->offset;
1407 pr_debug("found inline addr: 0x%jx\n", 945 pr_debug("found inline addr: 0x%jx\n",
1408 (uintmax_t)pf->addr); 946 (uintmax_t)pf->addr);
1409 947
1410 param->retval = call_probe_finder(in_die, pf); 948 ret = call_probe_finder(in_die, pf);
1411 if (param->retval < 0)
1412 return DWARF_CB_ABORT;
1413 } 949 }
1414 950
1415 return DWARF_CB_OK; 951 return ret;
1416} 952}
1417 953
954/* Callback parameter with return value for libdw */
955struct dwarf_callback_param {
956 void *data;
957 int retval;
958};
959
1418/* Search function from function name */ 960/* Search function from function name */
1419static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) 961static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1420{ 962{
@@ -1451,14 +993,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1451 /* TODO: Check the address in this function */ 993 /* TODO: Check the address in this function */
1452 param->retval = call_probe_finder(sp_die, pf); 994 param->retval = call_probe_finder(sp_die, pf);
1453 } 995 }
1454 } else { 996 } else
1455 struct dwarf_callback_param _param = {.data = (void *)pf,
1456 .retval = 0};
1457 /* Inlined function: search instances */ 997 /* Inlined function: search instances */
1458 dwarf_func_inline_instances(sp_die, probe_point_inline_cb, 998 param->retval = die_walk_instances(sp_die,
1459 &_param); 999 probe_point_inline_cb, (void *)pf);
1460 param->retval = _param.retval;
1461 }
1462 1000
1463 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */ 1001 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
1464} 1002}
@@ -1504,28 +1042,18 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
1504} 1042}
1505 1043
1506/* Find probe points from debuginfo */ 1044/* Find probe points from debuginfo */
1507static int find_probes(int fd, struct probe_finder *pf) 1045static int debuginfo__find_probes(struct debuginfo *self,
1046 struct probe_finder *pf)
1508{ 1047{
1509 struct perf_probe_point *pp = &pf->pev->point; 1048 struct perf_probe_point *pp = &pf->pev->point;
1510 Dwarf_Off off, noff; 1049 Dwarf_Off off, noff;
1511 size_t cuhl; 1050 size_t cuhl;
1512 Dwarf_Die *diep; 1051 Dwarf_Die *diep;
1513 Dwarf *dbg = NULL;
1514 Dwfl *dwfl;
1515 Dwarf_Addr bias; /* Currently ignored */
1516 int ret = 0; 1052 int ret = 0;
1517 1053
1518 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1519 if (!dbg) {
1520 pr_warning("No debug information found in the vmlinux - "
1521 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1522 close(fd); /* Without dwfl_end(), fd isn't closed. */
1523 return -EBADF;
1524 }
1525
1526#if _ELFUTILS_PREREQ(0, 142) 1054#if _ELFUTILS_PREREQ(0, 142)
1527 /* Get the call frame information from this dwarf */ 1055 /* Get the call frame information from this dwarf */
1528 pf->cfi = dwarf_getcfi(dbg); 1056 pf->cfi = dwarf_getcfi(self->dbg);
1529#endif 1057#endif
1530 1058
1531 off = 0; 1059 off = 0;
@@ -1544,7 +1072,8 @@ static int find_probes(int fd, struct probe_finder *pf)
1544 .data = pf, 1072 .data = pf,
1545 }; 1073 };
1546 1074
1547 dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); 1075 dwarf_getpubnames(self->dbg, pubname_search_cb,
1076 &pubname_param, 0);
1548 if (pubname_param.found) { 1077 if (pubname_param.found) {
1549 ret = probe_point_search_cb(&pf->sp_die, &probe_param); 1078 ret = probe_point_search_cb(&pf->sp_die, &probe_param);
1550 if (ret) 1079 if (ret)
@@ -1553,9 +1082,9 @@ static int find_probes(int fd, struct probe_finder *pf)
1553 } 1082 }
1554 1083
1555 /* Loop on CUs (Compilation Unit) */ 1084 /* Loop on CUs (Compilation Unit) */
1556 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { 1085 while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
1557 /* Get the DIE(Debugging Information Entry) of this CU */ 1086 /* Get the DIE(Debugging Information Entry) of this CU */
1558 diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die); 1087 diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die);
1559 if (!diep) 1088 if (!diep)
1560 continue; 1089 continue;
1561 1090
@@ -1582,14 +1111,12 @@ static int find_probes(int fd, struct probe_finder *pf)
1582 1111
1583found: 1112found:
1584 line_list__free(&pf->lcache); 1113 line_list__free(&pf->lcache);
1585 if (dwfl)
1586 dwfl_end(dwfl);
1587 1114
1588 return ret; 1115 return ret;
1589} 1116}
1590 1117
1591/* Add a found probe point into trace event list */ 1118/* Add a found probe point into trace event list */
1592static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf) 1119static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
1593{ 1120{
1594 struct trace_event_finder *tf = 1121 struct trace_event_finder *tf =
1595 container_of(pf, struct trace_event_finder, pf); 1122 container_of(pf, struct trace_event_finder, pf);
@@ -1604,8 +1131,9 @@ static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
1604 } 1131 }
1605 tev = &tf->tevs[tf->ntevs++]; 1132 tev = &tf->tevs[tf->ntevs++];
1606 1133
1607 ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe, 1134 /* Trace point should be converted from subprogram DIE */
1608 &tev->point); 1135 ret = convert_to_trace_point(&pf->sp_die, pf->addr,
1136 pf->pev->point.retprobe, &tev->point);
1609 if (ret < 0) 1137 if (ret < 0)
1610 return ret; 1138 return ret;
1611 1139
@@ -1620,7 +1148,8 @@ static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
1620 for (i = 0; i < pf->pev->nargs; i++) { 1148 for (i = 0; i < pf->pev->nargs; i++) {
1621 pf->pvar = &pf->pev->args[i]; 1149 pf->pvar = &pf->pev->args[i];
1622 pf->tvar = &tev->args[i]; 1150 pf->tvar = &tev->args[i];
1623 ret = find_variable(sp_die, pf); 1151 /* Variable should be found from scope DIE */
1152 ret = find_variable(sc_die, pf);
1624 if (ret != 0) 1153 if (ret != 0)
1625 return ret; 1154 return ret;
1626 } 1155 }
@@ -1629,8 +1158,9 @@ static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf)
1629} 1158}
1630 1159
1631/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 1160/* Find probe_trace_events specified by perf_probe_event from debuginfo */
1632int find_probe_trace_events(int fd, struct perf_probe_event *pev, 1161int debuginfo__find_trace_events(struct debuginfo *self,
1633 struct probe_trace_event **tevs, int max_tevs) 1162 struct perf_probe_event *pev,
1163 struct probe_trace_event **tevs, int max_tevs)
1634{ 1164{
1635 struct trace_event_finder tf = { 1165 struct trace_event_finder tf = {
1636 .pf = {.pev = pev, .callback = add_probe_trace_event}, 1166 .pf = {.pev = pev, .callback = add_probe_trace_event},
@@ -1645,7 +1175,7 @@ int find_probe_trace_events(int fd, struct perf_probe_event *pev,
1645 tf.tevs = *tevs; 1175 tf.tevs = *tevs;
1646 tf.ntevs = 0; 1176 tf.ntevs = 0;
1647 1177
1648 ret = find_probes(fd, &tf.pf); 1178 ret = debuginfo__find_probes(self, &tf.pf);
1649 if (ret < 0) { 1179 if (ret < 0) {
1650 free(*tevs); 1180 free(*tevs);
1651 *tevs = NULL; 1181 *tevs = NULL;
@@ -1687,13 +1217,13 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1687} 1217}
1688 1218
1689/* Add a found vars into available variables list */ 1219/* Add a found vars into available variables list */
1690static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf) 1220static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
1691{ 1221{
1692 struct available_var_finder *af = 1222 struct available_var_finder *af =
1693 container_of(pf, struct available_var_finder, pf); 1223 container_of(pf, struct available_var_finder, pf);
1694 struct variable_list *vl; 1224 struct variable_list *vl;
1695 Dwarf_Die die_mem, *scopes = NULL; 1225 Dwarf_Die die_mem;
1696 int ret, nscopes; 1226 int ret;
1697 1227
1698 /* Check number of tevs */ 1228 /* Check number of tevs */
1699 if (af->nvls == af->max_vls) { 1229 if (af->nvls == af->max_vls) {
@@ -1702,8 +1232,9 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
1702 } 1232 }
1703 vl = &af->vls[af->nvls++]; 1233 vl = &af->vls[af->nvls++];
1704 1234
1705 ret = convert_to_trace_point(sp_die, pf->addr, pf->pev->point.retprobe, 1235 /* Trace point should be converted from subprogram DIE */
1706 &vl->point); 1236 ret = convert_to_trace_point(&pf->sp_die, pf->addr,
1237 pf->pev->point.retprobe, &vl->point);
1707 if (ret < 0) 1238 if (ret < 0)
1708 return ret; 1239 return ret;
1709 1240
@@ -1715,19 +1246,14 @@ static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf)
1715 if (vl->vars == NULL) 1246 if (vl->vars == NULL)
1716 return -ENOMEM; 1247 return -ENOMEM;
1717 af->child = true; 1248 af->child = true;
1718 die_find_child(sp_die, collect_variables_cb, (void *)af, &die_mem); 1249 die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);
1719 1250
1720 /* Find external variables */ 1251 /* Find external variables */
1721 if (!af->externs) 1252 if (!af->externs)
1722 goto out; 1253 goto out;
1723 /* Don't need to search child DIE for externs. */ 1254 /* Don't need to search child DIE for externs. */
1724 af->child = false; 1255 af->child = false;
1725 nscopes = dwarf_getscopes_die(sp_die, &scopes); 1256 die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);
1726 while (nscopes-- > 1)
1727 die_find_child(&scopes[nscopes], collect_variables_cb,
1728 (void *)af, &die_mem);
1729 if (scopes)
1730 free(scopes);
1731 1257
1732out: 1258out:
1733 if (strlist__empty(vl->vars)) { 1259 if (strlist__empty(vl->vars)) {
@@ -1739,9 +1265,10 @@ out:
1739} 1265}
1740 1266
1741/* Find available variables at given probe point */ 1267/* Find available variables at given probe point */
1742int find_available_vars_at(int fd, struct perf_probe_event *pev, 1268int debuginfo__find_available_vars_at(struct debuginfo *self,
1743 struct variable_list **vls, int max_vls, 1269 struct perf_probe_event *pev,
1744 bool externs) 1270 struct variable_list **vls,
1271 int max_vls, bool externs)
1745{ 1272{
1746 struct available_var_finder af = { 1273 struct available_var_finder af = {
1747 .pf = {.pev = pev, .callback = add_available_vars}, 1274 .pf = {.pev = pev, .callback = add_available_vars},
@@ -1756,7 +1283,7 @@ int find_available_vars_at(int fd, struct perf_probe_event *pev,
1756 af.vls = *vls; 1283 af.vls = *vls;
1757 af.nvls = 0; 1284 af.nvls = 0;
1758 1285
1759 ret = find_probes(fd, &af.pf); 1286 ret = debuginfo__find_probes(self, &af.pf);
1760 if (ret < 0) { 1287 if (ret < 0) {
1761 /* Free vlist for error */ 1288 /* Free vlist for error */
1762 while (af.nvls--) { 1289 while (af.nvls--) {
@@ -1774,28 +1301,19 @@ int find_available_vars_at(int fd, struct perf_probe_event *pev,
1774} 1301}
1775 1302
1776/* Reverse search */ 1303/* Reverse search */
1777int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt) 1304int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
1305 struct perf_probe_point *ppt)
1778{ 1306{
1779 Dwarf_Die cudie, spdie, indie; 1307 Dwarf_Die cudie, spdie, indie;
1780 Dwarf *dbg = NULL; 1308 Dwarf_Addr _addr, baseaddr;
1781 Dwfl *dwfl = NULL;
1782 Dwarf_Addr _addr, baseaddr, bias = 0;
1783 const char *fname = NULL, *func = NULL, *tmp; 1309 const char *fname = NULL, *func = NULL, *tmp;
1784 int baseline = 0, lineno = 0, ret = 0; 1310 int baseline = 0, lineno = 0, ret = 0;
1785 1311
1786 /* Open the live linux kernel */
1787 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
1788 if (!dbg) {
1789 pr_warning("No debug information found in the vmlinux - "
1790 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1791 ret = -EINVAL;
1792 goto end;
1793 }
1794
1795 /* Adjust address with bias */ 1312 /* Adjust address with bias */
1796 addr += bias; 1313 addr += self->bias;
1314
1797 /* Find cu die */ 1315 /* Find cu die */
1798 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) { 1316 if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) {
1799 pr_warning("Failed to find debug information for address %lx\n", 1317 pr_warning("Failed to find debug information for address %lx\n",
1800 addr); 1318 addr);
1801 ret = -EINVAL; 1319 ret = -EINVAL;
@@ -1807,7 +1325,7 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1807 /* Don't care whether it failed or not */ 1325 /* Don't care whether it failed or not */
1808 1326
1809 /* Find a corresponding function (name, baseline and baseaddr) */ 1327 /* Find a corresponding function (name, baseline and baseaddr) */
1810 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { 1328 if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) {
1811 /* Get function entry information */ 1329 /* Get function entry information */
1812 tmp = dwarf_diename(&spdie); 1330 tmp = dwarf_diename(&spdie);
1813 if (!tmp || 1331 if (!tmp ||
@@ -1871,8 +1389,6 @@ post:
1871 } 1389 }
1872 } 1390 }
1873end: 1391end:
1874 if (dwfl)
1875 dwfl_end(dwfl);
1876 if (ret == 0 && (fname || func)) 1392 if (ret == 0 && (fname || func))
1877 ret = 1; /* Found a point */ 1393 ret = 1; /* Found a point */
1878 return ret; 1394 return ret;
@@ -1929,10 +1445,14 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1929 1445
1930static int line_range_inline_cb(Dwarf_Die *in_die, void *data) 1446static int line_range_inline_cb(Dwarf_Die *in_die, void *data)
1931{ 1447{
1932 struct dwarf_callback_param *param = data; 1448 find_line_range_by_line(in_die, data);
1933 1449
1934 param->retval = find_line_range_by_line(in_die, param->data); 1450 /*
1935 return DWARF_CB_ABORT; /* No need to find other instances */ 1451 * We have to check all instances of inlined function, because
1452 * some execution paths can be optimized out depends on the
1453 * function argument of instances
1454 */
1455 return 0;
1936} 1456}
1937 1457
1938/* Search function from function name */ 1458/* Search function from function name */
@@ -1960,15 +1480,10 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1960 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e); 1480 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e);
1961 lr->start = lf->lno_s; 1481 lr->start = lf->lno_s;
1962 lr->end = lf->lno_e; 1482 lr->end = lf->lno_e;
1963 if (dwarf_func_inline(sp_die)) { 1483 if (dwarf_func_inline(sp_die))
1964 struct dwarf_callback_param _param; 1484 param->retval = die_walk_instances(sp_die,
1965 _param.data = (void *)lf; 1485 line_range_inline_cb, lf);
1966 _param.retval = 0; 1486 else
1967 dwarf_func_inline_instances(sp_die,
1968 line_range_inline_cb,
1969 &_param);
1970 param->retval = _param.retval;
1971 } else
1972 param->retval = find_line_range_by_line(sp_die, lf); 1487 param->retval = find_line_range_by_line(sp_die, lf);
1973 return DWARF_CB_ABORT; 1488 return DWARF_CB_ABORT;
1974 } 1489 }
@@ -1982,26 +1497,15 @@ static int find_line_range_by_func(struct line_finder *lf)
1982 return param.retval; 1497 return param.retval;
1983} 1498}
1984 1499
1985int find_line_range(int fd, struct line_range *lr) 1500int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
1986{ 1501{
1987 struct line_finder lf = {.lr = lr, .found = 0}; 1502 struct line_finder lf = {.lr = lr, .found = 0};
1988 int ret = 0; 1503 int ret = 0;
1989 Dwarf_Off off = 0, noff; 1504 Dwarf_Off off = 0, noff;
1990 size_t cuhl; 1505 size_t cuhl;
1991 Dwarf_Die *diep; 1506 Dwarf_Die *diep;
1992 Dwarf *dbg = NULL;
1993 Dwfl *dwfl;
1994 Dwarf_Addr bias; /* Currently ignored */
1995 const char *comp_dir; 1507 const char *comp_dir;
1996 1508
1997 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1998 if (!dbg) {
1999 pr_warning("No debug information found in the vmlinux - "
2000 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
2001 close(fd); /* Without dwfl_end(), fd isn't closed. */
2002 return -EBADF;
2003 }
2004
2005 /* Fastpath: lookup by function name from .debug_pubnames section */ 1509 /* Fastpath: lookup by function name from .debug_pubnames section */
2006 if (lr->function) { 1510 if (lr->function) {
2007 struct pubname_callback_param pubname_param = { 1511 struct pubname_callback_param pubname_param = {
@@ -2010,7 +1514,8 @@ int find_line_range(int fd, struct line_range *lr)
2010 struct dwarf_callback_param line_range_param = { 1514 struct dwarf_callback_param line_range_param = {
2011 .data = (void *)&lf, .retval = 0}; 1515 .data = (void *)&lf, .retval = 0};
2012 1516
2013 dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); 1517 dwarf_getpubnames(self->dbg, pubname_search_cb,
1518 &pubname_param, 0);
2014 if (pubname_param.found) { 1519 if (pubname_param.found) {
2015 line_range_search_cb(&lf.sp_die, &line_range_param); 1520 line_range_search_cb(&lf.sp_die, &line_range_param);
2016 if (lf.found) 1521 if (lf.found)
@@ -2020,11 +1525,12 @@ int find_line_range(int fd, struct line_range *lr)
2020 1525
2021 /* Loop on CUs (Compilation Unit) */ 1526 /* Loop on CUs (Compilation Unit) */
2022 while (!lf.found && ret >= 0) { 1527 while (!lf.found && ret >= 0) {
2023 if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) 1528 if (dwarf_nextcu(self->dbg, off, &noff, &cuhl,
1529 NULL, NULL, NULL) != 0)
2024 break; 1530 break;
2025 1531
2026 /* Get the DIE(Debugging Information Entry) of this CU */ 1532 /* Get the DIE(Debugging Information Entry) of this CU */
2027 diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die); 1533 diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die);
2028 if (!diep) 1534 if (!diep)
2029 continue; 1535 continue;
2030 1536
@@ -2058,7 +1564,6 @@ found:
2058 } 1564 }
2059 1565
2060 pr_debug("path: %s\n", lr->path); 1566 pr_debug("path: %s\n", lr->path);
2061 dwfl_end(dwfl);
2062 return (ret < 0) ? ret : lf.found; 1567 return (ret < 0) ? ret : lf.found;
2063} 1568}
2064 1569
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 605730a366d..1132c8f0ce8 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -16,33 +16,48 @@ static inline int is_c_varname(const char *name)
16} 16}
17 17
18#ifdef DWARF_SUPPORT 18#ifdef DWARF_SUPPORT
19
20#include "dwarf-aux.h"
21
22/* TODO: export debuginfo data structure even if no dwarf support */
23
24/* debug information structure */
25struct debuginfo {
26 Dwarf *dbg;
27 Dwfl *dwfl;
28 Dwarf_Addr bias;
29};
30
31extern struct debuginfo *debuginfo__new(const char *path);
32extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr);
33extern void debuginfo__delete(struct debuginfo *self);
34
19/* Find probe_trace_events specified by perf_probe_event from debuginfo */ 35/* Find probe_trace_events specified by perf_probe_event from debuginfo */
20extern int find_probe_trace_events(int fd, struct perf_probe_event *pev, 36extern int debuginfo__find_trace_events(struct debuginfo *self,
21 struct probe_trace_event **tevs, 37 struct perf_probe_event *pev,
22 int max_tevs); 38 struct probe_trace_event **tevs,
39 int max_tevs);
23 40
24/* Find a perf_probe_point from debuginfo */ 41/* Find a perf_probe_point from debuginfo */
25extern int find_perf_probe_point(unsigned long addr, 42extern int debuginfo__find_probe_point(struct debuginfo *self,
26 struct perf_probe_point *ppt); 43 unsigned long addr,
44 struct perf_probe_point *ppt);
27 45
28/* Find a line range */ 46/* Find a line range */
29extern int find_line_range(int fd, struct line_range *lr); 47extern int debuginfo__find_line_range(struct debuginfo *self,
48 struct line_range *lr);
30 49
31/* Find available variables */ 50/* Find available variables */
32extern int find_available_vars_at(int fd, struct perf_probe_event *pev, 51extern int debuginfo__find_available_vars_at(struct debuginfo *self,
33 struct variable_list **vls, int max_points, 52 struct perf_probe_event *pev,
34 bool externs); 53 struct variable_list **vls,
35 54 int max_points, bool externs);
36#include <dwarf.h>
37#include <elfutils/libdw.h>
38#include <elfutils/libdwfl.h>
39#include <elfutils/version.h>
40 55
41struct probe_finder { 56struct probe_finder {
42 struct perf_probe_event *pev; /* Target probe event */ 57 struct perf_probe_event *pev; /* Target probe event */
43 58
44 /* Callback when a probe point is found */ 59 /* Callback when a probe point is found */
45 int (*callback)(Dwarf_Die *sp_die, struct probe_finder *pf); 60 int (*callback)(Dwarf_Die *sc_die, struct probe_finder *pf);
46 61
47 /* For function searching */ 62 /* For function searching */
48 int lno; /* Line number */ 63 int lno; /* Line number */
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index a9ac0504aab..7624324efad 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -187,16 +187,119 @@ static PyTypeObject pyrf_throttle_event__type = {
187 .tp_repr = (reprfunc)pyrf_throttle_event__repr, 187 .tp_repr = (reprfunc)pyrf_throttle_event__repr,
188}; 188};
189 189
190static char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object.");
191
192static PyMemberDef pyrf_lost_event__members[] = {
193 sample_members
194 member_def(lost_event, id, T_ULONGLONG, "event id"),
195 member_def(lost_event, lost, T_ULONGLONG, "number of lost events"),
196 { .name = NULL, },
197};
198
199static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent)
200{
201 PyObject *ret;
202 char *s;
203
204 if (asprintf(&s, "{ type: lost, id: %#" PRIx64 ", "
205 "lost: %#" PRIx64 " }",
206 pevent->event.lost.id, pevent->event.lost.lost) < 0) {
207 ret = PyErr_NoMemory();
208 } else {
209 ret = PyString_FromString(s);
210 free(s);
211 }
212 return ret;
213}
214
215static PyTypeObject pyrf_lost_event__type = {
216 PyVarObject_HEAD_INIT(NULL, 0)
217 .tp_name = "perf.lost_event",
218 .tp_basicsize = sizeof(struct pyrf_event),
219 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
220 .tp_doc = pyrf_lost_event__doc,
221 .tp_members = pyrf_lost_event__members,
222 .tp_repr = (reprfunc)pyrf_lost_event__repr,
223};
224
225static char pyrf_read_event__doc[] = PyDoc_STR("perf read event object.");
226
227static PyMemberDef pyrf_read_event__members[] = {
228 sample_members
229 member_def(read_event, pid, T_UINT, "event pid"),
230 member_def(read_event, tid, T_UINT, "event tid"),
231 { .name = NULL, },
232};
233
234static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent)
235{
236 return PyString_FromFormat("{ type: read, pid: %u, tid: %u }",
237 pevent->event.read.pid,
238 pevent->event.read.tid);
239 /*
240 * FIXME: return the array of read values,
241 * making this method useful ;-)
242 */
243}
244
245static PyTypeObject pyrf_read_event__type = {
246 PyVarObject_HEAD_INIT(NULL, 0)
247 .tp_name = "perf.read_event",
248 .tp_basicsize = sizeof(struct pyrf_event),
249 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
250 .tp_doc = pyrf_read_event__doc,
251 .tp_members = pyrf_read_event__members,
252 .tp_repr = (reprfunc)pyrf_read_event__repr,
253};
254
255static char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object.");
256
257static PyMemberDef pyrf_sample_event__members[] = {
258 sample_members
259 member_def(perf_event_header, type, T_UINT, "event type"),
260 { .name = NULL, },
261};
262
263static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent)
264{
265 PyObject *ret;
266 char *s;
267
268 if (asprintf(&s, "{ type: sample }") < 0) {
269 ret = PyErr_NoMemory();
270 } else {
271 ret = PyString_FromString(s);
272 free(s);
273 }
274 return ret;
275}
276
277static PyTypeObject pyrf_sample_event__type = {
278 PyVarObject_HEAD_INIT(NULL, 0)
279 .tp_name = "perf.sample_event",
280 .tp_basicsize = sizeof(struct pyrf_event),
281 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
282 .tp_doc = pyrf_sample_event__doc,
283 .tp_members = pyrf_sample_event__members,
284 .tp_repr = (reprfunc)pyrf_sample_event__repr,
285};
286
190static int pyrf_event__setup_types(void) 287static int pyrf_event__setup_types(void)
191{ 288{
192 int err; 289 int err;
193 pyrf_mmap_event__type.tp_new = 290 pyrf_mmap_event__type.tp_new =
194 pyrf_task_event__type.tp_new = 291 pyrf_task_event__type.tp_new =
195 pyrf_comm_event__type.tp_new = 292 pyrf_comm_event__type.tp_new =
293 pyrf_lost_event__type.tp_new =
294 pyrf_read_event__type.tp_new =
295 pyrf_sample_event__type.tp_new =
196 pyrf_throttle_event__type.tp_new = PyType_GenericNew; 296 pyrf_throttle_event__type.tp_new = PyType_GenericNew;
197 err = PyType_Ready(&pyrf_mmap_event__type); 297 err = PyType_Ready(&pyrf_mmap_event__type);
198 if (err < 0) 298 if (err < 0)
199 goto out; 299 goto out;
300 err = PyType_Ready(&pyrf_lost_event__type);
301 if (err < 0)
302 goto out;
200 err = PyType_Ready(&pyrf_task_event__type); 303 err = PyType_Ready(&pyrf_task_event__type);
201 if (err < 0) 304 if (err < 0)
202 goto out; 305 goto out;
@@ -206,20 +309,26 @@ static int pyrf_event__setup_types(void)
206 err = PyType_Ready(&pyrf_throttle_event__type); 309 err = PyType_Ready(&pyrf_throttle_event__type);
207 if (err < 0) 310 if (err < 0)
208 goto out; 311 goto out;
312 err = PyType_Ready(&pyrf_read_event__type);
313 if (err < 0)
314 goto out;
315 err = PyType_Ready(&pyrf_sample_event__type);
316 if (err < 0)
317 goto out;
209out: 318out:
210 return err; 319 return err;
211} 320}
212 321
213static PyTypeObject *pyrf_event__type[] = { 322static PyTypeObject *pyrf_event__type[] = {
214 [PERF_RECORD_MMAP] = &pyrf_mmap_event__type, 323 [PERF_RECORD_MMAP] = &pyrf_mmap_event__type,
215 [PERF_RECORD_LOST] = &pyrf_mmap_event__type, 324 [PERF_RECORD_LOST] = &pyrf_lost_event__type,
216 [PERF_RECORD_COMM] = &pyrf_comm_event__type, 325 [PERF_RECORD_COMM] = &pyrf_comm_event__type,
217 [PERF_RECORD_EXIT] = &pyrf_task_event__type, 326 [PERF_RECORD_EXIT] = &pyrf_task_event__type,
218 [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type, 327 [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type,
219 [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type, 328 [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
220 [PERF_RECORD_FORK] = &pyrf_task_event__type, 329 [PERF_RECORD_FORK] = &pyrf_task_event__type,
221 [PERF_RECORD_READ] = &pyrf_mmap_event__type, 330 [PERF_RECORD_READ] = &pyrf_read_event__type,
222 [PERF_RECORD_SAMPLE] = &pyrf_mmap_event__type, 331 [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type,
223}; 332};
224 333
225static PyObject *pyrf_event__new(union perf_event *event) 334static PyObject *pyrf_event__new(union perf_event *event)
@@ -247,7 +356,7 @@ struct pyrf_cpu_map {
247static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, 356static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
248 PyObject *args, PyObject *kwargs) 357 PyObject *args, PyObject *kwargs)
249{ 358{
250 static char *kwlist[] = { "cpustr", NULL, NULL, }; 359 static char *kwlist[] = { "cpustr", NULL };
251 char *cpustr = NULL; 360 char *cpustr = NULL;
252 361
253 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", 362 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
@@ -316,7 +425,7 @@ struct pyrf_thread_map {
316static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, 425static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
317 PyObject *args, PyObject *kwargs) 426 PyObject *args, PyObject *kwargs)
318{ 427{
319 static char *kwlist[] = { "pid", "tid", NULL, NULL, }; 428 static char *kwlist[] = { "pid", "tid", NULL };
320 int pid = -1, tid = -1; 429 int pid = -1, tid = -1;
321 430
322 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", 431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii",
@@ -418,7 +527,9 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
418 "wakeup_events", 527 "wakeup_events",
419 "bp_type", 528 "bp_type",
420 "bp_addr", 529 "bp_addr",
421 "bp_len", NULL, NULL, }; 530 "bp_len",
531 NULL
532 };
422 u64 sample_period = 0; 533 u64 sample_period = 0;
423 u32 disabled = 0, 534 u32 disabled = 0,
424 inherit = 0, 535 inherit = 0,
@@ -499,7 +610,7 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
499 struct thread_map *threads = NULL; 610 struct thread_map *threads = NULL;
500 PyObject *pcpus = NULL, *pthreads = NULL; 611 PyObject *pcpus = NULL, *pthreads = NULL;
501 int group = 0, inherit = 0; 612 int group = 0, inherit = 0;
502 static char *kwlist[] = {"cpus", "threads", "group", "inherit", NULL, NULL}; 613 static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL };
503 614
504 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, 615 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
505 &pcpus, &pthreads, &group, &inherit)) 616 &pcpus, &pthreads, &group, &inherit))
@@ -582,8 +693,7 @@ static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
582 PyObject *args, PyObject *kwargs) 693 PyObject *args, PyObject *kwargs)
583{ 694{
584 struct perf_evlist *evlist = &pevlist->evlist; 695 struct perf_evlist *evlist = &pevlist->evlist;
585 static char *kwlist[] = {"pages", "overwrite", 696 static char *kwlist[] = { "pages", "overwrite", NULL };
586 NULL, NULL};
587 int pages = 128, overwrite = false; 697 int pages = 128, overwrite = false;
588 698
589 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist, 699 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
@@ -603,7 +713,7 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
603 PyObject *args, PyObject *kwargs) 713 PyObject *args, PyObject *kwargs)
604{ 714{
605 struct perf_evlist *evlist = &pevlist->evlist; 715 struct perf_evlist *evlist = &pevlist->evlist;
606 static char *kwlist[] = {"timeout", NULL, NULL}; 716 static char *kwlist[] = { "timeout", NULL };
607 int timeout = -1, n; 717 int timeout = -1, n;
608 718
609 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout)) 719 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
@@ -674,7 +784,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
674 struct perf_evlist *evlist = &pevlist->evlist; 784 struct perf_evlist *evlist = &pevlist->evlist;
675 union perf_event *event; 785 union perf_event *event;
676 int sample_id_all = 1, cpu; 786 int sample_id_all = 1, cpu;
677 static char *kwlist[] = {"cpu", "sample_id_all", NULL, NULL}; 787 static char *kwlist[] = { "cpu", "sample_id_all", NULL };
678 int err; 788 int err;
679 789
680 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, 790 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
@@ -693,7 +803,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
693 first = list_entry(evlist->entries.next, struct perf_evsel, node); 803 first = list_entry(evlist->entries.next, struct perf_evsel, node);
694 err = perf_event__parse_sample(event, first->attr.sample_type, 804 err = perf_event__parse_sample(event, first->attr.sample_type,
695 perf_evsel__sample_size(first), 805 perf_evsel__sample_size(first),
696 sample_id_all, &pevent->sample); 806 sample_id_all, &pevent->sample, false);
697 if (err) 807 if (err)
698 return PyErr_Format(PyExc_OSError, 808 return PyErr_Format(PyExc_OSError,
699 "perf: can't parse sample, err=%d", err); 809 "perf: can't parse sample, err=%d", err);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f5a8fbdd3f7..72458d9da5b 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -12,6 +12,7 @@
12#include "session.h" 12#include "session.h"
13#include "sort.h" 13#include "sort.h"
14#include "util.h" 14#include "util.h"
15#include "cpumap.h"
15 16
16static int perf_session__open(struct perf_session *self, bool force) 17static int perf_session__open(struct perf_session *self, bool force)
17{ 18{
@@ -247,9 +248,14 @@ int perf_session__resolve_callchain(struct perf_session *self,
247 callchain_cursor_reset(&self->callchain_cursor); 248 callchain_cursor_reset(&self->callchain_cursor);
248 249
249 for (i = 0; i < chain->nr; i++) { 250 for (i = 0; i < chain->nr; i++) {
250 u64 ip = chain->ips[i]; 251 u64 ip;
251 struct addr_location al; 252 struct addr_location al;
252 253
254 if (callchain_param.order == ORDER_CALLEE)
255 ip = chain->ips[i];
256 else
257 ip = chain->ips[chain->nr - i - 1];
258
253 if (ip >= PERF_CONTEXT_MAX) { 259 if (ip >= PERF_CONTEXT_MAX) {
254 switch (ip) { 260 switch (ip) {
255 case PERF_CONTEXT_HV: 261 case PERF_CONTEXT_HV:
@@ -407,20 +413,26 @@ static void perf_event__read_swap(union perf_event *event)
407 event->read.id = bswap_64(event->read.id); 413 event->read.id = bswap_64(event->read.id);
408} 414}
409 415
410static void perf_event__attr_swap(union perf_event *event) 416/* exported for swapping attributes in file header */
417void perf_event__attr_swap(struct perf_event_attr *attr)
418{
419 attr->type = bswap_32(attr->type);
420 attr->size = bswap_32(attr->size);
421 attr->config = bswap_64(attr->config);
422 attr->sample_period = bswap_64(attr->sample_period);
423 attr->sample_type = bswap_64(attr->sample_type);
424 attr->read_format = bswap_64(attr->read_format);
425 attr->wakeup_events = bswap_32(attr->wakeup_events);
426 attr->bp_type = bswap_32(attr->bp_type);
427 attr->bp_addr = bswap_64(attr->bp_addr);
428 attr->bp_len = bswap_64(attr->bp_len);
429}
430
431static void perf_event__hdr_attr_swap(union perf_event *event)
411{ 432{
412 size_t size; 433 size_t size;
413 434
414 event->attr.attr.type = bswap_32(event->attr.attr.type); 435 perf_event__attr_swap(&event->attr.attr);
415 event->attr.attr.size = bswap_32(event->attr.attr.size);
416 event->attr.attr.config = bswap_64(event->attr.attr.config);
417 event->attr.attr.sample_period = bswap_64(event->attr.attr.sample_period);
418 event->attr.attr.sample_type = bswap_64(event->attr.attr.sample_type);
419 event->attr.attr.read_format = bswap_64(event->attr.attr.read_format);
420 event->attr.attr.wakeup_events = bswap_32(event->attr.attr.wakeup_events);
421 event->attr.attr.bp_type = bswap_32(event->attr.attr.bp_type);
422 event->attr.attr.bp_addr = bswap_64(event->attr.attr.bp_addr);
423 event->attr.attr.bp_len = bswap_64(event->attr.attr.bp_len);
424 436
425 size = event->header.size; 437 size = event->header.size;
426 size -= (void *)&event->attr.id - (void *)event; 438 size -= (void *)&event->attr.id - (void *)event;
@@ -448,7 +460,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
448 [PERF_RECORD_LOST] = perf_event__all64_swap, 460 [PERF_RECORD_LOST] = perf_event__all64_swap,
449 [PERF_RECORD_READ] = perf_event__read_swap, 461 [PERF_RECORD_READ] = perf_event__read_swap,
450 [PERF_RECORD_SAMPLE] = perf_event__all64_swap, 462 [PERF_RECORD_SAMPLE] = perf_event__all64_swap,
451 [PERF_RECORD_HEADER_ATTR] = perf_event__attr_swap, 463 [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
452 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, 464 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
453 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, 465 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
454 [PERF_RECORD_HEADER_BUILD_ID] = NULL, 466 [PERF_RECORD_HEADER_BUILD_ID] = NULL,
@@ -708,9 +720,9 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
708 if (!dump_trace) 720 if (!dump_trace)
709 return; 721 return;
710 722
711 printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 "\n", 723 printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n",
712 event->header.misc, sample->pid, sample->tid, sample->ip, 724 event->header.misc, sample->pid, sample->tid, sample->ip,
713 sample->period); 725 sample->period, sample->addr);
714 726
715 if (session->sample_type & PERF_SAMPLE_CALLCHAIN) 727 if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
716 callchain__printf(sample); 728 callchain__printf(sample);
@@ -1202,9 +1214,10 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1202 return NULL; 1214 return NULL;
1203} 1215}
1204 1216
1205void perf_session__print_symbols(union perf_event *event, 1217void perf_session__print_ip(union perf_event *event,
1206 struct perf_sample *sample, 1218 struct perf_sample *sample,
1207 struct perf_session *session) 1219 struct perf_session *session,
1220 int print_sym, int print_dso)
1208{ 1221{
1209 struct addr_location al; 1222 struct addr_location al;
1210 const char *symname, *dsoname; 1223 const char *symname, *dsoname;
@@ -1233,32 +1246,83 @@ void perf_session__print_symbols(union perf_event *event,
1233 if (!node) 1246 if (!node)
1234 break; 1247 break;
1235 1248
1236 if (node->sym && node->sym->name) 1249 printf("\t%16" PRIx64, node->ip);
1237 symname = node->sym->name; 1250 if (print_sym) {
1251 if (node->sym && node->sym->name)
1252 symname = node->sym->name;
1253 else
1254 symname = "";
1255
1256 printf(" %s", symname);
1257 }
1258 if (print_dso) {
1259 if (node->map && node->map->dso && node->map->dso->name)
1260 dsoname = node->map->dso->name;
1261 else
1262 dsoname = "";
1263
1264 printf(" (%s)", dsoname);
1265 }
1266 printf("\n");
1267
1268 callchain_cursor_advance(cursor);
1269 }
1270
1271 } else {
1272 printf("%16" PRIx64, sample->ip);
1273 if (print_sym) {
1274 if (al.sym && al.sym->name)
1275 symname = al.sym->name;
1238 else 1276 else
1239 symname = ""; 1277 symname = "";
1240 1278
1241 if (node->map && node->map->dso && node->map->dso->name) 1279 printf(" %s", symname);
1242 dsoname = node->map->dso->name; 1280 }
1281
1282 if (print_dso) {
1283 if (al.map && al.map->dso && al.map->dso->name)
1284 dsoname = al.map->dso->name;
1243 else 1285 else
1244 dsoname = ""; 1286 dsoname = "";
1245 1287
1246 printf("\t%16" PRIx64 " %s (%s)\n", node->ip, symname, dsoname); 1288 printf(" (%s)", dsoname);
1289 }
1290 }
1291}
1247 1292
1248 callchain_cursor_advance(cursor); 1293int perf_session__cpu_bitmap(struct perf_session *session,
1294 const char *cpu_list, unsigned long *cpu_bitmap)
1295{
1296 int i;
1297 struct cpu_map *map;
1298
1299 for (i = 0; i < PERF_TYPE_MAX; ++i) {
1300 struct perf_evsel *evsel;
1301
1302 evsel = perf_session__find_first_evtype(session, i);
1303 if (!evsel)
1304 continue;
1305
1306 if (!(evsel->attr.sample_type & PERF_SAMPLE_CPU)) {
1307 pr_err("File does not contain CPU events. "
1308 "Remove -c option to proceed.\n");
1309 return -1;
1249 } 1310 }
1311 }
1250 1312
1251 } else { 1313 map = cpu_map__new(cpu_list);
1252 if (al.sym && al.sym->name)
1253 symname = al.sym->name;
1254 else
1255 symname = "";
1256 1314
1257 if (al.map && al.map->dso && al.map->dso->name) 1315 for (i = 0; i < map->nr; i++) {
1258 dsoname = al.map->dso->name; 1316 int cpu = map->map[i];
1259 else 1317
1260 dsoname = ""; 1318 if (cpu >= MAX_NR_CPUS) {
1319 pr_err("Requested CPU %d too large. "
1320 "Consider raising MAX_NR_CPUS\n", cpu);
1321 return -1;
1322 }
1261 1323
1262 printf("%16" PRIx64 " %s (%s)", al.addr, symname, dsoname); 1324 set_bit(cpu, cpu_bitmap);
1263 } 1325 }
1326
1327 return 0;
1264} 1328}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 66d4e149087..974d0cbee5e 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -112,6 +112,7 @@ int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
112 u64 addr); 112 u64 addr);
113 113
114void mem_bswap_64(void *src, int byte_size); 114void mem_bswap_64(void *src, int byte_size);
115void perf_event__attr_swap(struct perf_event_attr *attr);
115 116
116int perf_session__create_kernel_maps(struct perf_session *self); 117int perf_session__create_kernel_maps(struct perf_session *self);
117 118
@@ -161,14 +162,19 @@ static inline int perf_session__parse_sample(struct perf_session *session,
161{ 162{
162 return perf_event__parse_sample(event, session->sample_type, 163 return perf_event__parse_sample(event, session->sample_type,
163 session->sample_size, 164 session->sample_size,
164 session->sample_id_all, sample); 165 session->sample_id_all, sample,
166 session->header.needs_swap);
165} 167}
166 168
167struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 169struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
168 unsigned int type); 170 unsigned int type);
169 171
170void perf_session__print_symbols(union perf_event *event, 172void perf_session__print_ip(union perf_event *event,
171 struct perf_sample *sample, 173 struct perf_sample *sample,
172 struct perf_session *session); 174 struct perf_session *session,
175 int print_sym, int print_dso);
176
177int perf_session__cpu_bitmap(struct perf_session *session,
178 const char *cpu_list, unsigned long *cpu_bitmap);
173 179
174#endif /* __PERF_SESSION_H */ 180#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index bbc982f5dd8..95d37007492 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -3,9 +3,27 @@
3from distutils.core import setup, Extension 3from distutils.core import setup, Extension
4from os import getenv 4from os import getenv
5 5
6from distutils.command.build_ext import build_ext as _build_ext
7from distutils.command.install_lib import install_lib as _install_lib
8
9class build_ext(_build_ext):
10 def finalize_options(self):
11 _build_ext.finalize_options(self)
12 self.build_lib = build_lib
13 self.build_temp = build_tmp
14
15class install_lib(_install_lib):
16 def finalize_options(self):
17 _install_lib.finalize_options(self)
18 self.build_dir = build_lib
19
20
6cflags = ['-fno-strict-aliasing', '-Wno-write-strings'] 21cflags = ['-fno-strict-aliasing', '-Wno-write-strings']
7cflags += getenv('CFLAGS', '').split() 22cflags += getenv('CFLAGS', '').split()
8 23
24build_lib = getenv('PYTHON_EXTBUILD_LIB')
25build_tmp = getenv('PYTHON_EXTBUILD_TMP')
26
9perf = Extension('perf', 27perf = Extension('perf',
10 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', 28 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c',
11 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c', 29 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
@@ -21,4 +39,5 @@ setup(name='perf',
21 author_email='acme@redhat.com', 39 author_email='acme@redhat.com',
22 license='GPLv2', 40 license='GPLv2',
23 url='http://perf.wiki.kernel.org', 41 url='http://perf.wiki.kernel.org',
24 ext_modules=[perf]) 42 ext_modules=[perf],
43 cmdclass={'build_ext': build_ext, 'install_lib': install_lib})
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index f44fa541d56..1ee8f1e40f1 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -15,95 +15,6 @@ char * field_sep;
15 15
16LIST_HEAD(hist_entry__sort_list); 16LIST_HEAD(hist_entry__sort_list);
17 17
18static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
19 size_t size, unsigned int width);
20static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
21 size_t size, unsigned int width);
22static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
23 size_t size, unsigned int width);
24static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
25 size_t size, unsigned int width);
26static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
27 size_t size, unsigned int width);
28static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf,
29 size_t size, unsigned int width);
30
31struct sort_entry sort_thread = {
32 .se_header = "Command: Pid",
33 .se_cmp = sort__thread_cmp,
34 .se_snprintf = hist_entry__thread_snprintf,
35 .se_width_idx = HISTC_THREAD,
36};
37
38struct sort_entry sort_comm = {
39 .se_header = "Command",
40 .se_cmp = sort__comm_cmp,
41 .se_collapse = sort__comm_collapse,
42 .se_snprintf = hist_entry__comm_snprintf,
43 .se_width_idx = HISTC_COMM,
44};
45
46struct sort_entry sort_dso = {
47 .se_header = "Shared Object",
48 .se_cmp = sort__dso_cmp,
49 .se_snprintf = hist_entry__dso_snprintf,
50 .se_width_idx = HISTC_DSO,
51};
52
53struct sort_entry sort_sym = {
54 .se_header = "Symbol",
55 .se_cmp = sort__sym_cmp,
56 .se_snprintf = hist_entry__sym_snprintf,
57 .se_width_idx = HISTC_SYMBOL,
58};
59
60struct sort_entry sort_parent = {
61 .se_header = "Parent symbol",
62 .se_cmp = sort__parent_cmp,
63 .se_snprintf = hist_entry__parent_snprintf,
64 .se_width_idx = HISTC_PARENT,
65};
66
67struct sort_entry sort_cpu = {
68 .se_header = "CPU",
69 .se_cmp = sort__cpu_cmp,
70 .se_snprintf = hist_entry__cpu_snprintf,
71 .se_width_idx = HISTC_CPU,
72};
73
74struct sort_dimension {
75 const char *name;
76 struct sort_entry *entry;
77 int taken;
78};
79
80static struct sort_dimension sort_dimensions[] = {
81 { .name = "pid", .entry = &sort_thread, },
82 { .name = "comm", .entry = &sort_comm, },
83 { .name = "dso", .entry = &sort_dso, },
84 { .name = "symbol", .entry = &sort_sym, },
85 { .name = "parent", .entry = &sort_parent, },
86 { .name = "cpu", .entry = &sort_cpu, },
87};
88
89int64_t cmp_null(void *l, void *r)
90{
91 if (!l && !r)
92 return 0;
93 else if (!l)
94 return -1;
95 else
96 return 1;
97}
98
99/* --sort pid */
100
101int64_t
102sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
103{
104 return right->thread->pid - left->thread->pid;
105}
106
107static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) 18static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
108{ 19{
109 int n; 20 int n;
@@ -125,6 +36,24 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
125 return n; 36 return n;
126} 37}
127 38
39static int64_t cmp_null(void *l, void *r)
40{
41 if (!l && !r)
42 return 0;
43 else if (!l)
44 return -1;
45 else
46 return 1;
47}
48
49/* --sort pid */
50
51static int64_t
52sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
53{
54 return right->thread->pid - left->thread->pid;
55}
56
128static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, 57static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
129 size_t size, unsigned int width) 58 size_t size, unsigned int width)
130{ 59{
@@ -132,15 +61,50 @@ static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf,
132 self->thread->comm ?: "", self->thread->pid); 61 self->thread->comm ?: "", self->thread->pid);
133} 62}
134 63
64struct sort_entry sort_thread = {
65 .se_header = "Command: Pid",
66 .se_cmp = sort__thread_cmp,
67 .se_snprintf = hist_entry__thread_snprintf,
68 .se_width_idx = HISTC_THREAD,
69};
70
71/* --sort comm */
72
73static int64_t
74sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
75{
76 return right->thread->pid - left->thread->pid;
77}
78
79static int64_t
80sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
81{
82 char *comm_l = left->thread->comm;
83 char *comm_r = right->thread->comm;
84
85 if (!comm_l || !comm_r)
86 return cmp_null(comm_l, comm_r);
87
88 return strcmp(comm_l, comm_r);
89}
90
135static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf, 91static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf,
136 size_t size, unsigned int width) 92 size_t size, unsigned int width)
137{ 93{
138 return repsep_snprintf(bf, size, "%*s", width, self->thread->comm); 94 return repsep_snprintf(bf, size, "%*s", width, self->thread->comm);
139} 95}
140 96
97struct sort_entry sort_comm = {
98 .se_header = "Command",
99 .se_cmp = sort__comm_cmp,
100 .se_collapse = sort__comm_collapse,
101 .se_snprintf = hist_entry__comm_snprintf,
102 .se_width_idx = HISTC_COMM,
103};
104
141/* --sort dso */ 105/* --sort dso */
142 106
143int64_t 107static int64_t
144sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) 108sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
145{ 109{
146 struct dso *dso_l = left->ms.map ? left->ms.map->dso : NULL; 110 struct dso *dso_l = left->ms.map ? left->ms.map->dso : NULL;
@@ -173,18 +137,31 @@ static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf,
173 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); 137 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]");
174} 138}
175 139
140struct sort_entry sort_dso = {
141 .se_header = "Shared Object",
142 .se_cmp = sort__dso_cmp,
143 .se_snprintf = hist_entry__dso_snprintf,
144 .se_width_idx = HISTC_DSO,
145};
146
176/* --sort symbol */ 147/* --sort symbol */
177 148
178int64_t 149static int64_t
179sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 150sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
180{ 151{
181 u64 ip_l, ip_r; 152 u64 ip_l, ip_r;
182 153
154 if (!left->ms.sym && !right->ms.sym)
155 return right->level - left->level;
156
157 if (!left->ms.sym || !right->ms.sym)
158 return cmp_null(left->ms.sym, right->ms.sym);
159
183 if (left->ms.sym == right->ms.sym) 160 if (left->ms.sym == right->ms.sym)
184 return 0; 161 return 0;
185 162
186 ip_l = left->ms.sym ? left->ms.sym->start : left->ip; 163 ip_l = left->ms.sym->start;
187 ip_r = right->ms.sym ? right->ms.sym->start : right->ip; 164 ip_r = right->ms.sym->start;
188 165
189 return (int64_t)(ip_r - ip_l); 166 return (int64_t)(ip_r - ip_l);
190} 167}
@@ -211,29 +188,16 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf,
211 return ret; 188 return ret;
212} 189}
213 190
214/* --sort comm */ 191struct sort_entry sort_sym = {
215 192 .se_header = "Symbol",
216int64_t 193 .se_cmp = sort__sym_cmp,
217sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) 194 .se_snprintf = hist_entry__sym_snprintf,
218{ 195 .se_width_idx = HISTC_SYMBOL,
219 return right->thread->pid - left->thread->pid; 196};
220}
221
222int64_t
223sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
224{
225 char *comm_l = left->thread->comm;
226 char *comm_r = right->thread->comm;
227
228 if (!comm_l || !comm_r)
229 return cmp_null(comm_l, comm_r);
230
231 return strcmp(comm_l, comm_r);
232}
233 197
234/* --sort parent */ 198/* --sort parent */
235 199
236int64_t 200static int64_t
237sort__parent_cmp(struct hist_entry *left, struct hist_entry *right) 201sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
238{ 202{
239 struct symbol *sym_l = left->parent; 203 struct symbol *sym_l = left->parent;
@@ -252,9 +216,16 @@ static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf,
252 self->parent ? self->parent->name : "[other]"); 216 self->parent ? self->parent->name : "[other]");
253} 217}
254 218
219struct sort_entry sort_parent = {
220 .se_header = "Parent symbol",
221 .se_cmp = sort__parent_cmp,
222 .se_snprintf = hist_entry__parent_snprintf,
223 .se_width_idx = HISTC_PARENT,
224};
225
255/* --sort cpu */ 226/* --sort cpu */
256 227
257int64_t 228static int64_t
258sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right) 229sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
259{ 230{
260 return right->cpu - left->cpu; 231 return right->cpu - left->cpu;
@@ -266,6 +237,28 @@ static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf,
266 return repsep_snprintf(bf, size, "%-*d", width, self->cpu); 237 return repsep_snprintf(bf, size, "%-*d", width, self->cpu);
267} 238}
268 239
240struct sort_entry sort_cpu = {
241 .se_header = "CPU",
242 .se_cmp = sort__cpu_cmp,
243 .se_snprintf = hist_entry__cpu_snprintf,
244 .se_width_idx = HISTC_CPU,
245};
246
247struct sort_dimension {
248 const char *name;
249 struct sort_entry *entry;
250 int taken;
251};
252
253static struct sort_dimension sort_dimensions[] = {
254 { .name = "pid", .entry = &sort_thread, },
255 { .name = "comm", .entry = &sort_comm, },
256 { .name = "dso", .entry = &sort_dso, },
257 { .name = "symbol", .entry = &sort_sym, },
258 { .name = "parent", .entry = &sort_parent, },
259 { .name = "cpu", .entry = &sort_cpu, },
260};
261
269int sort_dimension__add(const char *tok) 262int sort_dimension__add(const char *tok)
270{ 263{
271 unsigned int i; 264 unsigned int i;
@@ -273,15 +266,9 @@ int sort_dimension__add(const char *tok)
273 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { 266 for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) {
274 struct sort_dimension *sd = &sort_dimensions[i]; 267 struct sort_dimension *sd = &sort_dimensions[i];
275 268
276 if (sd->taken)
277 continue;
278
279 if (strncasecmp(tok, sd->name, strlen(tok))) 269 if (strncasecmp(tok, sd->name, strlen(tok)))
280 continue; 270 continue;
281 271
282 if (sd->entry->se_collapse)
283 sort__need_collapse = 1;
284
285 if (sd->entry == &sort_parent) { 272 if (sd->entry == &sort_parent) {
286 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED); 273 int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
287 if (ret) { 274 if (ret) {
@@ -294,6 +281,12 @@ int sort_dimension__add(const char *tok)
294 sort__has_parent = 1; 281 sort__has_parent = 1;
295 } 282 }
296 283
284 if (sd->taken)
285 return 0;
286
287 if (sd->entry->se_collapse)
288 sort__need_collapse = 1;
289
297 if (list_empty(&hist_entry__sort_list)) { 290 if (list_empty(&hist_entry__sort_list)) {
298 if (!strcmp(sd->name, "pid")) 291 if (!strcmp(sd->name, "pid"))
299 sort__first_dimension = SORT_PID; 292 sort__first_dimension = SORT_PID;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 0b91053a7d1..77d0388ad41 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -103,20 +103,6 @@ extern struct sort_entry sort_thread;
103extern struct list_head hist_entry__sort_list; 103extern struct list_head hist_entry__sort_list;
104 104
105void setup_sorting(const char * const usagestr[], const struct option *opts); 105void setup_sorting(const char * const usagestr[], const struct option *opts);
106
107extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int);
108extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int);
109extern size_t sort__dso_print(FILE *, struct hist_entry *, unsigned int);
110extern size_t sort__sym_print(FILE *, struct hist_entry *, unsigned int __used);
111extern int64_t cmp_null(void *, void *);
112extern int64_t sort__thread_cmp(struct hist_entry *, struct hist_entry *);
113extern int64_t sort__comm_cmp(struct hist_entry *, struct hist_entry *);
114extern int64_t sort__comm_collapse(struct hist_entry *, struct hist_entry *);
115extern int64_t sort__dso_cmp(struct hist_entry *, struct hist_entry *);
116extern int64_t sort__sym_cmp(struct hist_entry *, struct hist_entry *);
117extern int64_t sort__parent_cmp(struct hist_entry *, struct hist_entry *);
118int64_t sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right);
119extern size_t sort__parent_print(FILE *, struct hist_entry *, unsigned int);
120extern int sort_dimension__add(const char *); 106extern int sort_dimension__add(const char *);
121void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, 107void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list,
122 const char *list_name, FILE *fp); 108 const char *list_name, FILE *fp);
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index b9a985dadd0..d5836382ff2 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -294,3 +294,22 @@ bool strlazymatch(const char *str, const char *pat)
294{ 294{
295 return __match_glob(str, pat, true); 295 return __match_glob(str, pat, true);
296} 296}
297
298/**
299 * strtailcmp - Compare the tail of two strings
300 * @s1: 1st string to be compared
301 * @s2: 2nd string to be compared
302 *
303 * Return 0 if whole of either string is same as another's tail part.
304 */
305int strtailcmp(const char *s1, const char *s2)
306{
307 int i1 = strlen(s1);
308 int i2 = strlen(s2);
309 while (--i1 >= 0 && --i2 >= 0) {
310 if (s1[i1] != s2[i2])
311 return s1[i1] - s2[i2];
312 }
313 return 0;
314}
315
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index eec196329fd..40eeaf07725 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -74,16 +74,104 @@ static void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
74 74
75bool symbol_type__is_a(char symbol_type, enum map_type map_type) 75bool symbol_type__is_a(char symbol_type, enum map_type map_type)
76{ 76{
77 symbol_type = toupper(symbol_type);
78
77 switch (map_type) { 79 switch (map_type) {
78 case MAP__FUNCTION: 80 case MAP__FUNCTION:
79 return symbol_type == 'T' || symbol_type == 'W'; 81 return symbol_type == 'T' || symbol_type == 'W';
80 case MAP__VARIABLE: 82 case MAP__VARIABLE:
81 return symbol_type == 'D' || symbol_type == 'd'; 83 return symbol_type == 'D';
82 default: 84 default:
83 return false; 85 return false;
84 } 86 }
85} 87}
86 88
89static int prefix_underscores_count(const char *str)
90{
91 const char *tail = str;
92
93 while (*tail == '_')
94 tail++;
95
96 return tail - str;
97}
98
99#define SYMBOL_A 0
100#define SYMBOL_B 1
101
102static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
103{
104 s64 a;
105 s64 b;
106
107 /* Prefer a symbol with non zero length */
108 a = syma->end - syma->start;
109 b = symb->end - symb->start;
110 if ((b == 0) && (a > 0))
111 return SYMBOL_A;
112 else if ((a == 0) && (b > 0))
113 return SYMBOL_B;
114
115 /* Prefer a non weak symbol over a weak one */
116 a = syma->binding == STB_WEAK;
117 b = symb->binding == STB_WEAK;
118 if (b && !a)
119 return SYMBOL_A;
120 if (a && !b)
121 return SYMBOL_B;
122
123 /* Prefer a global symbol over a non global one */
124 a = syma->binding == STB_GLOBAL;
125 b = symb->binding == STB_GLOBAL;
126 if (a && !b)
127 return SYMBOL_A;
128 if (b && !a)
129 return SYMBOL_B;
130
131 /* Prefer a symbol with less underscores */
132 a = prefix_underscores_count(syma->name);
133 b = prefix_underscores_count(symb->name);
134 if (b > a)
135 return SYMBOL_A;
136 else if (a > b)
137 return SYMBOL_B;
138
139 /* If all else fails, choose the symbol with the longest name */
140 if (strlen(syma->name) >= strlen(symb->name))
141 return SYMBOL_A;
142 else
143 return SYMBOL_B;
144}
145
146static void symbols__fixup_duplicate(struct rb_root *symbols)
147{
148 struct rb_node *nd;
149 struct symbol *curr, *next;
150
151 nd = rb_first(symbols);
152
153 while (nd) {
154 curr = rb_entry(nd, struct symbol, rb_node);
155again:
156 nd = rb_next(&curr->rb_node);
157 next = rb_entry(nd, struct symbol, rb_node);
158
159 if (!nd)
160 break;
161
162 if (curr->start != next->start)
163 continue;
164
165 if (choose_best_symbol(curr, next) == SYMBOL_A) {
166 rb_erase(&next->rb_node, symbols);
167 goto again;
168 } else {
169 nd = rb_next(&curr->rb_node);
170 rb_erase(&curr->rb_node, symbols);
171 }
172 }
173}
174
87static void symbols__fixup_end(struct rb_root *symbols) 175static void symbols__fixup_end(struct rb_root *symbols)
88{ 176{
89 struct rb_node *nd, *prevnd = rb_first(symbols); 177 struct rb_node *nd, *prevnd = rb_first(symbols);
@@ -438,18 +526,11 @@ int kallsyms__parse(const char *filename, void *arg,
438 char *line = NULL; 526 char *line = NULL;
439 size_t n; 527 size_t n;
440 int err = -1; 528 int err = -1;
441 u64 prev_start = 0;
442 char prev_symbol_type = 0;
443 char *prev_symbol_name;
444 FILE *file = fopen(filename, "r"); 529 FILE *file = fopen(filename, "r");
445 530
446 if (file == NULL) 531 if (file == NULL)
447 goto out_failure; 532 goto out_failure;
448 533
449 prev_symbol_name = malloc(KSYM_NAME_LEN);
450 if (prev_symbol_name == NULL)
451 goto out_close;
452
453 err = 0; 534 err = 0;
454 535
455 while (!feof(file)) { 536 while (!feof(file)) {
@@ -470,7 +551,7 @@ int kallsyms__parse(const char *filename, void *arg,
470 if (len + 2 >= line_len) 551 if (len + 2 >= line_len)
471 continue; 552 continue;
472 553
473 symbol_type = toupper(line[len]); 554 symbol_type = line[len];
474 len += 2; 555 len += 2;
475 symbol_name = line + len; 556 symbol_name = line + len;
476 len = line_len - len; 557 len = line_len - len;
@@ -480,24 +561,18 @@ int kallsyms__parse(const char *filename, void *arg,
480 break; 561 break;
481 } 562 }
482 563
483 if (prev_symbol_type) { 564 /*
484 u64 end = start; 565 * module symbols are not sorted so we add all
485 if (end != prev_start) 566 * symbols with zero length and rely on
486 --end; 567 * symbols__fixup_end() to fix it up.
487 err = process_symbol(arg, prev_symbol_name, 568 */
488 prev_symbol_type, prev_start, end); 569 err = process_symbol(arg, symbol_name,
489 if (err) 570 symbol_type, start, start);
490 break; 571 if (err)
491 } 572 break;
492
493 memcpy(prev_symbol_name, symbol_name, len + 1);
494 prev_symbol_type = symbol_type;
495 prev_start = start;
496 } 573 }
497 574
498 free(prev_symbol_name);
499 free(line); 575 free(line);
500out_close:
501 fclose(file); 576 fclose(file);
502 return err; 577 return err;
503 578
@@ -703,6 +778,9 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
703 if (dso__load_all_kallsyms(dso, filename, map) < 0) 778 if (dso__load_all_kallsyms(dso, filename, map) < 0)
704 return -1; 779 return -1;
705 780
781 symbols__fixup_duplicate(&dso->symbols[map->type]);
782 symbols__fixup_end(&dso->symbols[map->type]);
783
706 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 784 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
707 dso->symtab_type = SYMTAB__GUEST_KALLSYMS; 785 dso->symtab_type = SYMTAB__GUEST_KALLSYMS;
708 else 786 else
@@ -1092,8 +1170,7 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
1092 if (dso->has_build_id) { 1170 if (dso->has_build_id) {
1093 u8 build_id[BUILD_ID_SIZE]; 1171 u8 build_id[BUILD_ID_SIZE];
1094 1172
1095 if (elf_read_build_id(elf, build_id, 1173 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0)
1096 BUILD_ID_SIZE) != BUILD_ID_SIZE)
1097 goto out_elf_end; 1174 goto out_elf_end;
1098 1175
1099 if (!dso__build_id_equal(dso, build_id)) 1176 if (!dso__build_id_equal(dso, build_id))
@@ -1111,6 +1188,8 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name,
1111 } 1188 }
1112 1189
1113 opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx); 1190 opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx);
1191 if (opdshdr.sh_type != SHT_PROGBITS)
1192 opdsec = NULL;
1114 if (opdsec) 1193 if (opdsec)
1115 opddata = elf_rawdata(opdsec, NULL); 1194 opddata = elf_rawdata(opdsec, NULL);
1116 1195
@@ -1276,6 +1355,7 @@ new_symbol:
1276 * For misannotated, zeroed, ASM function sizes. 1355 * For misannotated, zeroed, ASM function sizes.
1277 */ 1356 */
1278 if (nr > 0) { 1357 if (nr > 0) {
1358 symbols__fixup_duplicate(&dso->symbols[map->type]);
1279 symbols__fixup_end(&dso->symbols[map->type]); 1359 symbols__fixup_end(&dso->symbols[map->type]);
1280 if (kmap) { 1360 if (kmap) {
1281 /* 1361 /*
@@ -1362,8 +1442,8 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
1362 ptr = data->d_buf; 1442 ptr = data->d_buf;
1363 while (ptr < (data->d_buf + data->d_size)) { 1443 while (ptr < (data->d_buf + data->d_size)) {
1364 GElf_Nhdr *nhdr = ptr; 1444 GElf_Nhdr *nhdr = ptr;
1365 int namesz = NOTE_ALIGN(nhdr->n_namesz), 1445 size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
1366 descsz = NOTE_ALIGN(nhdr->n_descsz); 1446 descsz = NOTE_ALIGN(nhdr->n_descsz);
1367 const char *name; 1447 const char *name;
1368 1448
1369 ptr += sizeof(*nhdr); 1449 ptr += sizeof(*nhdr);
@@ -1372,8 +1452,10 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
1372 if (nhdr->n_type == NT_GNU_BUILD_ID && 1452 if (nhdr->n_type == NT_GNU_BUILD_ID &&
1373 nhdr->n_namesz == sizeof("GNU")) { 1453 nhdr->n_namesz == sizeof("GNU")) {
1374 if (memcmp(name, "GNU", sizeof("GNU")) == 0) { 1454 if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
1375 memcpy(bf, ptr, BUILD_ID_SIZE); 1455 size_t sz = min(size, descsz);
1376 err = BUILD_ID_SIZE; 1456 memcpy(bf, ptr, sz);
1457 memset(bf + sz, 0, size - sz);
1458 err = descsz;
1377 break; 1459 break;
1378 } 1460 }
1379 } 1461 }
@@ -1425,7 +1507,7 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
1425 while (1) { 1507 while (1) {
1426 char bf[BUFSIZ]; 1508 char bf[BUFSIZ];
1427 GElf_Nhdr nhdr; 1509 GElf_Nhdr nhdr;
1428 int namesz, descsz; 1510 size_t namesz, descsz;
1429 1511
1430 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr)) 1512 if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
1431 break; 1513 break;
@@ -1434,15 +1516,16 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
1434 descsz = NOTE_ALIGN(nhdr.n_descsz); 1516 descsz = NOTE_ALIGN(nhdr.n_descsz);
1435 if (nhdr.n_type == NT_GNU_BUILD_ID && 1517 if (nhdr.n_type == NT_GNU_BUILD_ID &&
1436 nhdr.n_namesz == sizeof("GNU")) { 1518 nhdr.n_namesz == sizeof("GNU")) {
1437 if (read(fd, bf, namesz) != namesz) 1519 if (read(fd, bf, namesz) != (ssize_t)namesz)
1438 break; 1520 break;
1439 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) { 1521 if (memcmp(bf, "GNU", sizeof("GNU")) == 0) {
1440 if (read(fd, build_id, 1522 size_t sz = min(descsz, size);
1441 BUILD_ID_SIZE) == BUILD_ID_SIZE) { 1523 if (read(fd, build_id, sz) == (ssize_t)sz) {
1524 memset(build_id + sz, 0, size - sz);
1442 err = 0; 1525 err = 0;
1443 break; 1526 break;
1444 } 1527 }
1445 } else if (read(fd, bf, descsz) != descsz) 1528 } else if (read(fd, bf, descsz) != (ssize_t)descsz)
1446 break; 1529 break;
1447 } else { 1530 } else {
1448 int n = namesz + descsz; 1531 int n = namesz + descsz;
@@ -1504,6 +1587,17 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1504 dso->adjust_symbols = 0; 1587 dso->adjust_symbols = 0;
1505 1588
1506 if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { 1589 if (strncmp(dso->name, "/tmp/perf-", 10) == 0) {
1590 struct stat st;
1591
1592 if (lstat(dso->name, &st) < 0)
1593 return -1;
1594
1595 if (st.st_uid && (st.st_uid != geteuid())) {
1596 pr_warning("File %s not owned by current user or root, "
1597 "ignoring it.\n", dso->name);
1598 return -1;
1599 }
1600
1507 ret = dso__load_perf_map(dso, map, filter); 1601 ret = dso__load_perf_map(dso, map, filter);
1508 dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : 1602 dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT :
1509 SYMTAB__NOT_FOUND; 1603 SYMTAB__NOT_FOUND;
@@ -2170,27 +2264,22 @@ size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
2170 return ret; 2264 return ret;
2171} 2265}
2172 2266
2173struct dso *dso__new_kernel(const char *name) 2267static struct dso*
2268dso__kernel_findnew(struct machine *machine, const char *name,
2269 const char *short_name, int dso_type)
2174{ 2270{
2175 struct dso *dso = dso__new(name ?: "[kernel.kallsyms]"); 2271 /*
2176 2272 * The kernel dso could be created by build_id processing.
2177 if (dso != NULL) { 2273 */
2178 dso__set_short_name(dso, "[kernel]"); 2274 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name);
2179 dso->kernel = DSO_TYPE_KERNEL;
2180 }
2181
2182 return dso;
2183}
2184 2275
2185static struct dso *dso__new_guest_kernel(struct machine *machine, 2276 /*
2186 const char *name) 2277 * We need to run this in all cases, since during the build_id
2187{ 2278 * processing we had no idea this was the kernel dso.
2188 char bf[PATH_MAX]; 2279 */
2189 struct dso *dso = dso__new(name ?: machine__mmap_name(machine, bf,
2190 sizeof(bf)));
2191 if (dso != NULL) { 2280 if (dso != NULL) {
2192 dso__set_short_name(dso, "[guest.kernel]"); 2281 dso__set_short_name(dso, short_name);
2193 dso->kernel = DSO_TYPE_GUEST_KERNEL; 2282 dso->kernel = dso_type;
2194 } 2283 }
2195 2284
2196 return dso; 2285 return dso;
@@ -2208,24 +2297,36 @@ void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
2208 dso->has_build_id = true; 2297 dso->has_build_id = true;
2209} 2298}
2210 2299
2211static struct dso *machine__create_kernel(struct machine *machine) 2300static struct dso *machine__get_kernel(struct machine *machine)
2212{ 2301{
2213 const char *vmlinux_name = NULL; 2302 const char *vmlinux_name = NULL;
2214 struct dso *kernel; 2303 struct dso *kernel;
2215 2304
2216 if (machine__is_host(machine)) { 2305 if (machine__is_host(machine)) {
2217 vmlinux_name = symbol_conf.vmlinux_name; 2306 vmlinux_name = symbol_conf.vmlinux_name;
2218 kernel = dso__new_kernel(vmlinux_name); 2307 if (!vmlinux_name)
2308 vmlinux_name = "[kernel.kallsyms]";
2309
2310 kernel = dso__kernel_findnew(machine, vmlinux_name,
2311 "[kernel]",
2312 DSO_TYPE_KERNEL);
2219 } else { 2313 } else {
2314 char bf[PATH_MAX];
2315
2220 if (machine__is_default_guest(machine)) 2316 if (machine__is_default_guest(machine))
2221 vmlinux_name = symbol_conf.default_guest_vmlinux_name; 2317 vmlinux_name = symbol_conf.default_guest_vmlinux_name;
2222 kernel = dso__new_guest_kernel(machine, vmlinux_name); 2318 if (!vmlinux_name)
2319 vmlinux_name = machine__mmap_name(machine, bf,
2320 sizeof(bf));
2321
2322 kernel = dso__kernel_findnew(machine, vmlinux_name,
2323 "[guest.kernel]",
2324 DSO_TYPE_GUEST_KERNEL);
2223 } 2325 }
2224 2326
2225 if (kernel != NULL) { 2327 if (kernel != NULL && (!kernel->has_build_id))
2226 dso__read_running_kernel_build_id(kernel, machine); 2328 dso__read_running_kernel_build_id(kernel, machine);
2227 dsos__add(&machine->kernel_dsos, kernel); 2329
2228 }
2229 return kernel; 2330 return kernel;
2230} 2331}
2231 2332
@@ -2329,7 +2430,7 @@ void machine__destroy_kernel_maps(struct machine *machine)
2329 2430
2330int machine__create_kernel_maps(struct machine *machine) 2431int machine__create_kernel_maps(struct machine *machine)
2331{ 2432{
2332 struct dso *kernel = machine__create_kernel(machine); 2433 struct dso *kernel = machine__get_kernel(machine);
2333 2434
2334 if (kernel == NULL || 2435 if (kernel == NULL ||
2335 __machine__create_kernel_maps(machine, kernel) < 0) 2436 __machine__create_kernel_maps(machine, kernel) < 0)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 325ee36a9d2..4f377d92e75 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -155,7 +155,6 @@ struct dso {
155}; 155};
156 156
157struct dso *dso__new(const char *name); 157struct dso *dso__new(const char *name);
158struct dso *dso__new_kernel(const char *name);
159void dso__delete(struct dso *dso); 158void dso__delete(struct dso *dso);
160 159
161int dso__name_len(const struct dso *dso); 160int dso__name_len(const struct dso *dso);
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index 35729f4c40c..3403f814ad7 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -183,106 +183,59 @@ int bigendian(void)
183 return *ptr == 0x01020304; 183 return *ptr == 0x01020304;
184} 184}
185 185
186static unsigned long long copy_file_fd(int fd) 186/* unfortunately, you can not stat debugfs or proc files for size */
187static void record_file(const char *file, size_t hdr_sz)
187{ 188{
188 unsigned long long size = 0; 189 unsigned long long size = 0;
189 char buf[BUFSIZ]; 190 char buf[BUFSIZ], *sizep;
190 int r; 191 off_t hdr_pos = lseek(output_fd, 0, SEEK_CUR);
191 192 int r, fd;
192 do {
193 r = read(fd, buf, BUFSIZ);
194 if (r > 0) {
195 size += r;
196 write_or_die(buf, r);
197 }
198 } while (r > 0);
199
200 return size;
201}
202
203static unsigned long long copy_file(const char *file)
204{
205 unsigned long long size = 0;
206 int fd;
207 193
208 fd = open(file, O_RDONLY); 194 fd = open(file, O_RDONLY);
209 if (fd < 0) 195 if (fd < 0)
210 die("Can't read '%s'", file); 196 die("Can't read '%s'", file);
211 size = copy_file_fd(fd);
212 close(fd);
213 197
214 return size; 198 /* put in zeros for file size, then fill true size later */
215} 199 write_or_die(&size, hdr_sz);
216
217static unsigned long get_size_fd(int fd)
218{
219 unsigned long long size = 0;
220 char buf[BUFSIZ];
221 int r;
222 200
223 do { 201 do {
224 r = read(fd, buf, BUFSIZ); 202 r = read(fd, buf, BUFSIZ);
225 if (r > 0) 203 if (r > 0) {
226 size += r; 204 size += r;
205 write_or_die(buf, r);
206 }
227 } while (r > 0); 207 } while (r > 0);
228
229 lseek(fd, 0, SEEK_SET);
230
231 return size;
232}
233
234static unsigned long get_size(const char *file)
235{
236 unsigned long long size = 0;
237 int fd;
238
239 fd = open(file, O_RDONLY);
240 if (fd < 0)
241 die("Can't read '%s'", file);
242 size = get_size_fd(fd);
243 close(fd); 208 close(fd);
244 209
245 return size; 210 /* ugh, handle big-endian hdr_size == 4 */
211 sizep = (char*)&size;
212 if (bigendian())
213 sizep += sizeof(u64) - hdr_sz;
214
215 if (pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0)
216 die("writing to %s", output_file);
246} 217}
247 218
248static void read_header_files(void) 219static void read_header_files(void)
249{ 220{
250 unsigned long long size, check_size;
251 char *path; 221 char *path;
252 int fd; 222 struct stat st;
253 223
254 path = get_tracing_file("events/header_page"); 224 path = get_tracing_file("events/header_page");
255 fd = open(path, O_RDONLY); 225 if (stat(path, &st) < 0)
256 if (fd < 0)
257 die("can't read '%s'", path); 226 die("can't read '%s'", path);
258 227
259 /* unfortunately, you can not stat debugfs files for size */
260 size = get_size_fd(fd);
261
262 write_or_die("header_page", 12); 228 write_or_die("header_page", 12);
263 write_or_die(&size, 8); 229 record_file(path, 8);
264 check_size = copy_file_fd(fd);
265 close(fd);
266
267 if (size != check_size)
268 die("wrong size for '%s' size=%lld read=%lld",
269 path, size, check_size);
270 put_tracing_file(path); 230 put_tracing_file(path);
271 231
272 path = get_tracing_file("events/header_event"); 232 path = get_tracing_file("events/header_event");
273 fd = open(path, O_RDONLY); 233 if (stat(path, &st) < 0)
274 if (fd < 0)
275 die("can't read '%s'", path); 234 die("can't read '%s'", path);
276 235
277 size = get_size_fd(fd);
278
279 write_or_die("header_event", 13); 236 write_or_die("header_event", 13);
280 write_or_die(&size, 8); 237 record_file(path, 8);
281 check_size = copy_file_fd(fd);
282 if (size != check_size)
283 die("wrong size for '%s'", path);
284 put_tracing_file(path); 238 put_tracing_file(path);
285 close(fd);
286} 239}
287 240
288static bool name_in_tp_list(char *sys, struct tracepoint_path *tps) 241static bool name_in_tp_list(char *sys, struct tracepoint_path *tps)
@@ -298,7 +251,6 @@ static bool name_in_tp_list(char *sys, struct tracepoint_path *tps)
298 251
299static void copy_event_system(const char *sys, struct tracepoint_path *tps) 252static void copy_event_system(const char *sys, struct tracepoint_path *tps)
300{ 253{
301 unsigned long long size, check_size;
302 struct dirent *dent; 254 struct dirent *dent;
303 struct stat st; 255 struct stat st;
304 char *format; 256 char *format;
@@ -338,14 +290,8 @@ static void copy_event_system(const char *sys, struct tracepoint_path *tps)
338 sprintf(format, "%s/%s/format", sys, dent->d_name); 290 sprintf(format, "%s/%s/format", sys, dent->d_name);
339 ret = stat(format, &st); 291 ret = stat(format, &st);
340 292
341 if (ret >= 0) { 293 if (ret >= 0)
342 /* unfortunately, you can not stat debugfs files for size */ 294 record_file(format, 8);
343 size = get_size(format);
344 write_or_die(&size, 8);
345 check_size = copy_file(format);
346 if (size != check_size)
347 die("error in size of file '%s'", format);
348 }
349 295
350 free(format); 296 free(format);
351 } 297 }
@@ -426,7 +372,7 @@ static void read_event_files(struct tracepoint_path *tps)
426 372
427static void read_proc_kallsyms(void) 373static void read_proc_kallsyms(void)
428{ 374{
429 unsigned int size, check_size; 375 unsigned int size;
430 const char *path = "/proc/kallsyms"; 376 const char *path = "/proc/kallsyms";
431 struct stat st; 377 struct stat st;
432 int ret; 378 int ret;
@@ -438,17 +384,12 @@ static void read_proc_kallsyms(void)
438 write_or_die(&size, 4); 384 write_or_die(&size, 4);
439 return; 385 return;
440 } 386 }
441 size = get_size(path); 387 record_file(path, 4);
442 write_or_die(&size, 4);
443 check_size = copy_file(path);
444 if (size != check_size)
445 die("error in size of file '%s'", path);
446
447} 388}
448 389
449static void read_ftrace_printk(void) 390static void read_ftrace_printk(void)
450{ 391{
451 unsigned int size, check_size; 392 unsigned int size;
452 char *path; 393 char *path;
453 struct stat st; 394 struct stat st;
454 int ret; 395 int ret;
@@ -461,11 +402,8 @@ static void read_ftrace_printk(void)
461 write_or_die(&size, 4); 402 write_or_die(&size, 4);
462 goto out; 403 goto out;
463 } 404 }
464 size = get_size(path); 405 record_file(path, 4);
465 write_or_die(&size, 4); 406
466 check_size = copy_file(path);
467 if (size != check_size)
468 die("error in size of file '%s'", path);
469out: 407out:
470 put_tracing_file(path); 408 put_tracing_file(path);
471} 409}
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 0a7ed5b5e28..bf54c48871d 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -1537,6 +1537,8 @@ process_flags(struct event *event, struct print_arg *arg, char **tok)
1537 field = malloc_or_die(sizeof(*field)); 1537 field = malloc_or_die(sizeof(*field));
1538 1538
1539 type = process_arg(event, field, &token); 1539 type = process_arg(event, field, &token);
1540 while (type == EVENT_OP)
1541 type = process_op(event, field, &token);
1540 if (test_type_token(type, token, EVENT_DELIM, ",")) 1542 if (test_type_token(type, token, EVENT_DELIM, ","))
1541 goto out_free; 1543 goto out_free;
1542 1544
@@ -1580,6 +1582,8 @@ process_symbols(struct event *event, struct print_arg *arg, char **tok)
1580 field = malloc_or_die(sizeof(*field)); 1582 field = malloc_or_die(sizeof(*field));
1581 1583
1582 type = process_arg(event, field, &token); 1584 type = process_arg(event, field, &token);
1585 while (type == EVENT_OP)
1586 type = process_op(event, field, &token);
1583 if (test_type_token(type, token, EVENT_DELIM, ",")) 1587 if (test_type_token(type, token, EVENT_DELIM, ","))
1584 goto out_free; 1588 goto out_free;
1585 1589
diff --git a/tools/perf/util/ui/browsers/top.c b/tools/perf/util/ui/browsers/top.c
index 5a06538532a..88403cf8396 100644
--- a/tools/perf/util/ui/browsers/top.c
+++ b/tools/perf/util/ui/browsers/top.c
@@ -208,6 +208,5 @@ int perf_top__tui_browser(struct perf_top *top)
208 }, 208 },
209 }; 209 };
210 210
211 ui_helpline__push("Press <- or ESC to exit");
212 return perf_top_browser__run(&browser); 211 return perf_top_browser__run(&browser);
213} 212}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index fc784284ac8..0128906bac8 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -238,6 +238,7 @@ char **argv_split(const char *str, int *argcp);
238void argv_free(char **argv); 238void argv_free(char **argv);
239bool strglobmatch(const char *str, const char *pat); 239bool strglobmatch(const char *str, const char *pat);
240bool strlazymatch(const char *str, const char *pat); 240bool strlazymatch(const char *str, const char *pat);
241int strtailcmp(const char *s1, const char *s2);
241unsigned long convert_unit(unsigned long value, char *unit); 242unsigned long convert_unit(unsigned long value, char *unit);
242int readn(int fd, void *buf, size_t size); 243int readn(int fd, void *buf, size_t size);
243 244
diff --git a/tools/power/cpupower/.gitignore b/tools/power/cpupower/.gitignore
new file mode 100644
index 00000000000..d42073f1260
--- /dev/null
+++ b/tools/power/cpupower/.gitignore
@@ -0,0 +1,29 @@
1.libs
2libcpupower.so
3libcpupower.so.0
4libcpupower.so.0.0.0
5build/ccdv
6cpufreq-info
7cpufreq-set
8cpufreq-aperf
9lib/.libs
10lib/cpufreq.lo
11lib/cpufreq.o
12lib/proc.lo
13lib/proc.o
14lib/sysfs.lo
15lib/sysfs.o
16po/cpupowerutils.pot
17po/*.gmo
18utils/cpufreq-info.o
19utils/cpufreq-set.o
20utils/cpufreq-aperf.o
21cpupower
22bench/cpufreq-bench
23debug/kernel/Module.symvers
24debug/i386/centrino-decode
25debug/i386/dump_psb
26debug/i386/intel_gsic
27debug/i386/powernow-k8-decode
28debug/x86_64/centrino-decode
29debug/x86_64/powernow-k8-decode
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
new file mode 100644
index 00000000000..e8a03aceceb
--- /dev/null
+++ b/tools/power/cpupower/Makefile
@@ -0,0 +1,280 @@
1# Makefile for cpupower
2#
3# Copyright (C) 2005,2006 Dominik Brodowski <linux@dominikbrodowski.net>
4#
5# Based largely on the Makefile for udev by:
6#
7# Copyright (C) 2003,2004 Greg Kroah-Hartman <greg@kroah.com>
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; version 2 of the License.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16# General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21#
22
23# --- CONFIGURATION BEGIN ---
24
25# Set the following to `true' to make a unstripped, unoptimized
26# binary. Leave this set to `false' for production use.
27DEBUG ?= true
28
29# make the build silent. Set this to something else to make it noisy again.
30V ?= false
31
32# Internationalization support (output in different languages).
33# Requires gettext.
34NLS ?= true
35
36# Set the following to 'true' to build/install the
37# cpufreq-bench benchmarking tool
38CPUFREQ_BENCH ?= true
39
40# Prefix to the directories we're installing to
41DESTDIR ?=
42
43# --- CONFIGURATION END ---
44
45
46
47# Package-related definitions. Distributions can modify the version
48# and _should_ modify the PACKAGE_BUGREPORT definition
49
50VERSION= $(shell ./utils/version-gen.sh)
51LIB_MAJ= 0.0.0
52LIB_MIN= 0
53
54PACKAGE = cpupower
55PACKAGE_BUGREPORT = cpufreq@vger.kernel.org
56LANGUAGES = de fr it cs pt
57
58
59# Directory definitions. These are default and most probably
60# do not need to be changed. Please note that DESTDIR is
61# added in front of any of them
62
63bindir ?= /usr/bin
64sbindir ?= /usr/sbin
65mandir ?= /usr/man
66includedir ?= /usr/include
67libdir ?= /usr/lib
68localedir ?= /usr/share/locale
69docdir ?= /usr/share/doc/packages/cpupower
70confdir ?= /etc/
71
72# Toolchain: what tools do we use, and what options do they need:
73
74CP = cp -fpR
75INSTALL = /usr/bin/install -c
76INSTALL_PROGRAM = ${INSTALL}
77INSTALL_DATA = ${INSTALL} -m 644
78INSTALL_SCRIPT = ${INSTALL_PROGRAM}
79
80# If you are running a cross compiler, you may want to set this
81# to something more interesting, like "arm-linux-". If you want
82# to compile vs uClibc, that can be done here as well.
83CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc-
84CC = $(CROSS)gcc
85LD = $(CROSS)gcc
86AR = $(CROSS)ar
87STRIP = $(CROSS)strip
88RANLIB = $(CROSS)ranlib
89HOSTCC = gcc
90
91
92# Now we set up the build system
93#
94
95# set up PWD so that older versions of make will work with our build.
96PWD = $(shell pwd)
97
98GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo po/$$HLANG.gmo; done;}
99
100export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS
101
102# check if compiler option is supported
103cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;}
104
105# use '-Os' optimization if available, else use -O2
106OPTIMIZATION := $(call cc-supports,-Os,-O2)
107
108WARNINGS := -Wall -Wchar-subscripts -Wpointer-arith -Wsign-compare
109WARNINGS += $(call cc-supports,-Wno-pointer-sign)
110WARNINGS += $(call cc-supports,-Wdeclaration-after-statement)
111WARNINGS += -Wshadow
112
113CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \
114 -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE
115
116UTIL_OBJS = utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \
117 utils/helpers/sysfs.o utils/helpers/misc.o utils/helpers/cpuid.o \
118 utils/helpers/pci.o utils/helpers/bitmask.o \
119 utils/idle_monitor/nhm_idle.o utils/idle_monitor/snb_idle.o \
120 utils/idle_monitor/amd_fam14h_idle.o utils/idle_monitor/cpuidle_sysfs.o \
121 utils/idle_monitor/mperf_monitor.o utils/idle_monitor/cpupower-monitor.o \
122 utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \
123 utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o
124
125UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \
126 utils/helpers/bitmask.h \
127 utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def
128
129UTIL_SRC := $(UTIL_OBJS:.o=.c)
130
131LIB_HEADERS = lib/cpufreq.h lib/sysfs.h
132LIB_SRC = lib/cpufreq.c lib/sysfs.c
133LIB_OBJS = lib/cpufreq.o lib/sysfs.o
134
135CFLAGS += -pipe
136
137ifeq ($(strip $(NLS)),true)
138 INSTALL_NLS += install-gmo
139 COMPILE_NLS += create-gmo
140 CFLAGS += -DNLS
141endif
142
143ifeq ($(strip $(CPUFREQ_BENCH)),true)
144 INSTALL_BENCH += install-bench
145 COMPILE_BENCH += compile-bench
146endif
147
148CFLAGS += $(WARNINGS)
149
150ifeq ($(strip $(V)),false)
151 QUIET=@
152 ECHO=@echo
153else
154 QUIET=
155 ECHO=@\#
156endif
157export QUIET ECHO
158
159# if DEBUG is enabled, then we do not strip or optimize
160ifeq ($(strip $(DEBUG)),true)
161 CFLAGS += -O1 -g -DDEBUG
162 STRIPCMD = /bin/true -Since_we_are_debugging
163else
164 CFLAGS += $(OPTIMIZATION) -fomit-frame-pointer
165 STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment
166endif
167
168
169# the actual make rules
170
171all: libcpupower cpupower $(COMPILE_NLS) $(COMPILE_BENCH)
172
173lib/%.o: $(LIB_SRC) $(LIB_HEADERS)
174 $(ECHO) " CC " $@
175 $(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c
176
177libcpupower.so.$(LIB_MAJ): $(LIB_OBJS)
178 $(ECHO) " LD " $@
179 $(QUIET) $(CC) -shared $(CFLAGS) $(LDFLAGS) -o $@ \
180 -Wl,-soname,libcpupower.so.$(LIB_MIN) $(LIB_OBJS)
181 @ln -sf $@ libcpupower.so
182 @ln -sf $@ libcpupower.so.$(LIB_MIN)
183
184libcpupower: libcpupower.so.$(LIB_MAJ)
185
186# Let all .o files depend on its .c file and all headers
187# Might be worth to put this into utils/Makefile at some point of time
188$(UTIL_OBJS): $(UTIL_HEADERS)
189
190.c.o:
191 $(ECHO) " CC " $@
192 $(QUIET) $(CC) $(CFLAGS) -I./lib -I ./utils -o $@ -c $*.c
193
194cpupower: $(UTIL_OBJS) libcpupower.so.$(LIB_MAJ)
195 $(ECHO) " CC " $@
196 $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -lcpupower -lrt -lpci -L. -o $@ $(UTIL_OBJS)
197 $(QUIET) $(STRIPCMD) $@
198
199po/$(PACKAGE).pot: $(UTIL_SRC)
200 $(ECHO) " GETTEXT " $@
201 $(QUIET) xgettext --default-domain=$(PACKAGE) --add-comments \
202 --keyword=_ --keyword=N_ $(UTIL_SRC) && \
203 test -f $(PACKAGE).po && \
204 mv -f $(PACKAGE).po po/$(PACKAGE).pot
205
206po/%.gmo: po/%.po
207 $(ECHO) " MSGFMT " $@
208 $(QUIET) msgfmt -o $@ po/$*.po
209
210create-gmo: ${GMO_FILES}
211
212update-po: po/$(PACKAGE).pot
213 $(ECHO) " MSGMRG " $@
214 $(QUIET) @for HLANG in $(LANGUAGES); do \
215 echo -n "Updating $$HLANG "; \
216 if msgmerge po/$$HLANG.po po/$(PACKAGE).pot -o \
217 po/$$HLANG.new.po; then \
218 mv -f po/$$HLANG.new.po po/$$HLANG.po; \
219 else \
220 echo "msgmerge for $$HLANG failed!"; \
221 rm -f po/$$HLANG.new.po; \
222 fi; \
223 done;
224
225compile-bench: libcpupower.so.$(LIB_MAJ)
226 @V=$(V) confdir=$(confdir) $(MAKE) -C bench
227
228clean:
229 -find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \
230 | xargs rm -f
231 -rm -f $(UTIL_BINS)
232 -rm -f $(IDLE_OBJS)
233 -rm -f cpupower
234 -rm -f libcpupower.so*
235 -rm -rf po/*.gmo po/*.pot
236 $(MAKE) -C bench clean
237
238
239install-lib:
240 $(INSTALL) -d $(DESTDIR)${libdir}
241 $(CP) libcpupower.so* $(DESTDIR)${libdir}/
242 $(INSTALL) -d $(DESTDIR)${includedir}
243 $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h
244
245install-tools:
246 $(INSTALL) -d $(DESTDIR)${bindir}
247 $(INSTALL_PROGRAM) cpupower $(DESTDIR)${bindir}
248
249install-man:
250 $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1
251 $(INSTALL_DATA) -D man/cpupower-frequency-set.1 $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1
252 $(INSTALL_DATA) -D man/cpupower-frequency-info.1 $(DESTDIR)${mandir}/man1/cpupower-frequency-info.1
253 $(INSTALL_DATA) -D man/cpupower-set.1 $(DESTDIR)${mandir}/man1/cpupower-set.1
254 $(INSTALL_DATA) -D man/cpupower-info.1 $(DESTDIR)${mandir}/man1/cpupower-info.1
255 $(INSTALL_DATA) -D man/cpupower-monitor.1 $(DESTDIR)${mandir}/man1/cpupower-monitor.1
256
257install-gmo:
258 $(INSTALL) -d $(DESTDIR)${localedir}
259 for HLANG in $(LANGUAGES); do \
260 echo '$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo'; \
261 $(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
262 done;
263
264install-bench:
265 @#DESTDIR must be set from outside to survive
266 @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench install
267
268install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH)
269
270uninstall:
271 - rm -f $(DESTDIR)${libdir}/libcpupower.*
272 - rm -f $(DESTDIR)${includedir}/cpufreq.h
273 - rm -f $(DESTDIR)${bindir}/utils/cpupower
274 - rm -f $(DESTDIR)${mandir}/man1/cpufreq-set.1
275 - rm -f $(DESTDIR)${mandir}/man1/cpufreq-info.1
276 - for HLANG in $(LANGUAGES); do \
277 rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \
278 done;
279
280.PHONY: all utils libcpupower update-po create-gmo install-lib install-tools install-man install-gmo install uninstall clean
diff --git a/tools/power/cpupower/README b/tools/power/cpupower/README
new file mode 100644
index 00000000000..fd9d4c0d668
--- /dev/null
+++ b/tools/power/cpupower/README
@@ -0,0 +1,49 @@
1The cpufrequtils package (homepage:
2http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufrequtils.html )
3consists of the following elements:
4
5requirements
6------------
7
8On x86 pciutils is needed at runtime (-lpci).
9For compilation pciutils-devel (pci/pci.h) and a gcc version
10providing cpuid.h is needed.
11For both it's not explicitly checked for (yet).
12
13
14libcpufreq
15----------
16
17"libcpufreq" is a library which offers a unified access method for userspace
18tools and programs to the cpufreq core and drivers in the Linux kernel. This
19allows for code reduction in userspace tools, a clean implementation of
20the interaction to the cpufreq core, and support for both the sysfs and proc
21interfaces [depending on configuration, see below].
22
23
24compilation and installation
25----------------------------
26
27make
28su
29make install
30
31should suffice on most systems. It builds default libcpufreq,
32cpufreq-set and cpufreq-info files and installs them in /usr/lib and
33/usr/bin, respectively. If you want to set up the paths differently and/or
34want to configure the package to your specific needs, you need to open
35"Makefile" with an editor of your choice and edit the block marked
36CONFIGURATION.
37
38
39THANKS
40------
41Many thanks to Mattia Dongili who wrote the autotoolization and
42libtoolization, the manpages and the italian language file for cpufrequtils;
43to Dave Jones for his feedback and his dump_psb tool; to Bruno Ducrot for his
44powernow-k8-decode and intel_gsic tools as well as the french language file;
45and to various others commenting on the previous (pre-)releases of
46cpufrequtils.
47
48
49 Dominik Brodowski
diff --git a/tools/power/cpupower/ToDo b/tools/power/cpupower/ToDo
new file mode 100644
index 00000000000..874b78b586e
--- /dev/null
+++ b/tools/power/cpupower/ToDo
@@ -0,0 +1,11 @@
1ToDos sorted by priority:
2
3- Use bitmask functions to parse CPU topology more robust
4 (current implementation has issues on AMD)
5- Try to read out boost states and frequencies on Intel
6- Adjust README
7- Somewhere saw the ability to read power consumption of
8 RAM from HW on Intel SandyBridge -> another monitor?
9- Add another c1e debug idle monitor
10 -> Is by design racy with BIOS, but could be added
11 with a --force option and some "be careful" messages
diff --git a/tools/power/cpupower/bench/Makefile b/tools/power/cpupower/bench/Makefile
new file mode 100644
index 00000000000..2b67606fc3e
--- /dev/null
+++ b/tools/power/cpupower/bench/Makefile
@@ -0,0 +1,29 @@
1LIBS = -L../ -lm -lcpupower
2
3OBJS = main.o parse.o system.o benchmark.o
4CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\"
5
6%.o : %.c
7 $(ECHO) " CC " $@
8 $(QUIET) $(CC) -c $(CFLAGS) $< -o $@
9
10cpufreq-bench: $(OBJS)
11 $(ECHO) " CC " $@
12 $(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS)
13
14all: cpufreq-bench
15
16install:
17 mkdir -p $(DESTDIR)/$(sbindir)
18 mkdir -p $(DESTDIR)/$(bindir)
19 mkdir -p $(DESTDIR)/$(docdir)
20 mkdir -p $(DESTDIR)/$(confdir)
21 install -m 755 cpufreq-bench $(DESTDIR)/$(sbindir)/cpufreq-bench
22 install -m 755 cpufreq-bench_plot.sh $(DESTDIR)/$(bindir)/cpufreq-bench_plot.sh
23 install -m 644 README-BENCH $(DESTDIR)/$(docdir)/README-BENCH
24 install -m 755 cpufreq-bench_script.sh $(DESTDIR)/$(docdir)/cpufreq-bench_script.sh
25 install -m 644 example.cfg $(DESTDIR)/$(confdir)/cpufreq-bench.conf
26
27clean:
28 rm -f *.o
29 rm -f cpufreq-bench
diff --git a/tools/power/cpupower/bench/README-BENCH b/tools/power/cpupower/bench/README-BENCH
new file mode 100644
index 00000000000..8093ec73817
--- /dev/null
+++ b/tools/power/cpupower/bench/README-BENCH
@@ -0,0 +1,124 @@
1This is cpufreq-bench, a microbenchmark for the cpufreq framework.
2
3Purpose
4=======
5
6What is this benchmark for:
7 - Identify worst case performance loss when doing dynamic frequency
8 scaling using Linux kernel governors
9 - Identify average reaction time of a governor to CPU load changes
10 - (Stress) Testing whether a cpufreq low level driver or governor works
11 as expected
12 - Identify cpufreq related performance regressions between kernels
13 - Possibly Real time priority testing? -> what happens if there are
14 processes with a higher prio than the governor's kernel thread
15 - ...
16
17What this benchmark does *not* cover:
18 - Power saving related regressions (In fact as better the performance
19 throughput is, the worse the power savings will be, but the first should
20 mostly count more...)
21 - Real world (workloads)
22
23
24Description
25===========
26
27cpufreq-bench helps to test the condition of a given cpufreq governor.
28For that purpose, it compares the performance governor to a configured
29powersave module.
30
31
32How it works
33============
34You can specify load (100% CPU load) and sleep (0% CPU load) times in us which
35will be run X time in a row (cycles):
36
37 sleep=25000
38 load=25000
39 cycles=20
40
41This part of the configuration file will create 25ms load/sleep turns,
42repeated 20 times.
43
44Adding this:
45 sleep_step=25000
46 load_step=25000
47 rounds=5
48Will increase load and sleep time by 25ms 5 times.
49Together you get following test:
5025ms load/sleep time repeated 20 times (cycles).
5150ms load/sleep time repeated 20 times (cycles).
52..
53100ms load/sleep time repeated 20 times (cycles).
54
55First it is calibrated how long a specific CPU intensive calculation
56takes on this machine and needs to be run in a loop using the performance
57governor.
58Then the above test runs are processed using the performance governor
59and the governor to test. The time the calculation really needed
60with the dynamic freq scaling governor is compared with the time needed
61on full performance and you get the overall performance loss.
62
63
64Example of expected results with ondemand governor:
65
66This shows expected results of the first two test run rounds from
67above config, you there have:
68
69100% CPU load (load) | 0 % CPU load (sleep) | round
70 25 ms | 25 ms | 1
71 50 ms | 50 ms | 2
72
73For example if ondemand governor is configured to have a 50ms
74sampling rate you get:
75
76In round 1, ondemand should have rather static 50% load and probably
77won't ever switch up (as long as up_threshold is above).
78
79In round 2, if the ondemand sampling times exactly match the load/sleep
80trigger of the cpufreq-bench, you will see no performance loss (compare with
81below possible ondemand sample kick ins (1)):
82
83But if ondemand always kicks in in the middle of the load sleep cycles, it
84will always see 50% loads and you get worst performance impact never
85switching up (compare with below possible ondemand sample kick ins (2))::
86
87 50 50 50 50ms ->time
88load -----| |-----| |-----| |-----|
89 | | | | | | |
90sleep |-----| |-----| |-----| |----
91 |-----|-----|-----|-----|-----|-----|-----|---- ondemand sampling (1)
92 100 0 100 0 100 0 100 load seen by ondemand(%)
93 |-----|-----|-----|-----|-----|-----|-----|-- ondemand sampling (2)
94 50 50 50 50 50 50 50 load seen by ondemand(%)
95
96You can easily test all kind of load/sleep times and check whether your
97governor in average behaves as expected.
98
99
100ToDo
101====
102
103Provide a gnuplot utility script for easy generation of plots to present
104the outcome nicely.
105
106
107cpufreq-bench Command Usage
108===========================
109-l, --load=<long int> initial load time in us
110-s, --sleep=<long int> initial sleep time in us
111-x, --load-step=<long int> time to be added to load time, in us
112-y, --sleep-step=<long int> time to be added to sleep time, in us
113-c, --cpu=<unsigned int> CPU Number to use, starting at 0
114-p, --prio=<priority> scheduler priority, HIGH, LOW or DEFAULT
115-g, --governor=<governor> cpufreq governor to test
116-n, --cycles=<int> load/sleep cycles to get an avarage value to compare
117-r, --rounds<int> load/sleep rounds
118-f, --file=<configfile> config file to use
119-o, --output=<dir> output dir, must exist
120-v, --verbose verbose output on/off
121
122Due to the high priority, the application may not be responsible for some time.
123After the benchmark, the logfile is saved in OUTPUTDIR/benchmark_TIMESTAMP.log
124
diff --git a/tools/power/cpupower/bench/benchmark.c b/tools/power/cpupower/bench/benchmark.c
new file mode 100644
index 00000000000..81b1c48607d
--- /dev/null
+++ b/tools/power/cpupower/bench/benchmark.c
@@ -0,0 +1,194 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <stdio.h>
21#include <unistd.h>
22#include <math.h>
23
24#include "config.h"
25#include "system.h"
26#include "benchmark.h"
27
28/* Print out progress if we log into a file */
29#define show_progress(total_time, progress_time) \
30if (config->output != stdout) { \
31 fprintf(stdout, "Progress: %02lu %%\r", \
32 (progress_time * 100) / total_time); \
33 fflush(stdout); \
34}
35
36/**
37 * compute how many rounds of calculation we should do
38 * to get the given load time
39 *
40 * @param load aimed load time in µs
41 *
42 * @retval rounds of calculation
43 **/
44
45unsigned int calculate_timespace(long load, struct config *config)
46{
47 int i;
48 long long now, then;
49 unsigned int estimated = GAUGECOUNT;
50 unsigned int rounds = 0;
51 unsigned int timed = 0;
52
53 if (config->verbose)
54 printf("calibrating load of %lius, please wait...\n", load);
55
56 /* get the initial calculation time for a specific number of rounds */
57 now = get_time();
58 ROUNDS(estimated);
59 then = get_time();
60
61 timed = (unsigned int)(then - now);
62
63 /* approximation of the wanted load time by comparing with the
64 * initial calculation time */
65 for (i = 0; i < 4; i++) {
66 rounds = (unsigned int)(load * estimated / timed);
67 dprintf("calibrating with %u rounds\n", rounds);
68 now = get_time();
69 ROUNDS(rounds);
70 then = get_time();
71
72 timed = (unsigned int)(then - now);
73 estimated = rounds;
74 }
75 if (config->verbose)
76 printf("calibration done\n");
77
78 return estimated;
79}
80
81/**
82 * benchmark
83 * generates a specific sleep an load time with the performance
84 * governor and compares the used time for same calculations done
85 * with the configured powersave governor
86 *
87 * @param config config values for the benchmark
88 *
89 **/
90
91void start_benchmark(struct config *config)
92{
93 unsigned int _round, cycle;
94 long long now, then;
95 long sleep_time = 0, load_time = 0;
96 long performance_time = 0, powersave_time = 0;
97 unsigned int calculations;
98 unsigned long total_time = 0, progress_time = 0;
99
100 sleep_time = config->sleep;
101 load_time = config->load;
102
103 /* For the progress bar */
104 for (_round = 1; _round <= config->rounds; _round++)
105 total_time += _round * (config->sleep + config->load);
106 total_time *= 2; /* powersave and performance cycles */
107
108 for (_round = 0; _round < config->rounds; _round++) {
109 performance_time = 0LL;
110 powersave_time = 0LL;
111
112 show_progress(total_time, progress_time);
113
114 /* set the cpufreq governor to "performance" which disables
115 * P-State switching. */
116 if (set_cpufreq_governor("performance", config->cpu) != 0)
117 return;
118
119 /* calibrate the calculation time. the resulting calculation
120 * _rounds should produce a load which matches the configured
121 * load time */
122 calculations = calculate_timespace(load_time, config);
123
124 if (config->verbose)
125 printf("_round %i: doing %u cycles with %u calculations"
126 " for %lius\n", _round + 1, config->cycles,
127 calculations, load_time);
128
129 fprintf(config->output, "%u %li %li ",
130 _round, load_time, sleep_time);
131
132 if (config->verbose)
133 printf("avarage: %lius, rps:%li\n",
134 load_time / calculations,
135 1000000 * calculations / load_time);
136
137 /* do some sleep/load cycles with the performance governor */
138 for (cycle = 0; cycle < config->cycles; cycle++) {
139 now = get_time();
140 usleep(sleep_time);
141 ROUNDS(calculations);
142 then = get_time();
143 performance_time += then - now - sleep_time;
144 if (config->verbose)
145 printf("performance cycle took %lius, "
146 "sleep: %lius, "
147 "load: %lius, rounds: %u\n",
148 (long)(then - now), sleep_time,
149 load_time, calculations);
150 }
151 fprintf(config->output, "%li ",
152 performance_time / config->cycles);
153
154 progress_time += sleep_time + load_time;
155 show_progress(total_time, progress_time);
156
157 /* set the powersave governor which activates P-State switching
158 * again */
159 if (set_cpufreq_governor(config->governor, config->cpu) != 0)
160 return;
161
162 /* again, do some sleep/load cycles with the
163 * powersave governor */
164 for (cycle = 0; cycle < config->cycles; cycle++) {
165 now = get_time();
166 usleep(sleep_time);
167 ROUNDS(calculations);
168 then = get_time();
169 powersave_time += then - now - sleep_time;
170 if (config->verbose)
171 printf("powersave cycle took %lius, "
172 "sleep: %lius, "
173 "load: %lius, rounds: %u\n",
174 (long)(then - now), sleep_time,
175 load_time, calculations);
176 }
177
178 progress_time += sleep_time + load_time;
179
180 /* compare the avarage sleep/load cycles */
181 fprintf(config->output, "%li ",
182 powersave_time / config->cycles);
183 fprintf(config->output, "%.3f\n",
184 performance_time * 100.0 / powersave_time);
185 fflush(config->output);
186
187 if (config->verbose)
188 printf("performance is at %.2f%%\n",
189 performance_time * 100.0 / powersave_time);
190
191 sleep_time += config->sleep_step;
192 load_time += config->load_step;
193 }
194}
diff --git a/tools/power/cpupower/bench/benchmark.h b/tools/power/cpupower/bench/benchmark.h
new file mode 100644
index 00000000000..51d7f50ac2b
--- /dev/null
+++ b/tools/power/cpupower/bench/benchmark.h
@@ -0,0 +1,29 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20/* load loop, this schould take about 1 to 2ms to complete */
21#define ROUNDS(x) {unsigned int rcnt; \
22 for (rcnt = 0; rcnt < x*1000; rcnt++) { \
23 (void)(((int)(pow(rcnt, rcnt) * \
24 sqrt(rcnt*7230970)) ^ 7230716) ^ \
25 (int)atan2(rcnt, rcnt)); \
26 } } \
27
28
29void start_benchmark(struct config *config);
diff --git a/tools/power/cpupower/bench/config.h b/tools/power/cpupower/bench/config.h
new file mode 100644
index 00000000000..ee6f258e533
--- /dev/null
+++ b/tools/power/cpupower/bench/config.h
@@ -0,0 +1,36 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20/* initial loop count for the load calibration */
21#define GAUGECOUNT 1500
22
23/* default scheduling policy SCHED_OTHER */
24#define SCHEDULER SCHED_OTHER
25
26#define PRIORITY_DEFAULT 0
27#define PRIORITY_HIGH sched_get_priority_max(SCHEDULER)
28#define PRIORITY_LOW sched_get_priority_min(SCHEDULER)
29
30/* enable further debug messages */
31#ifdef DEBUG
32#define dprintf printf
33#else
34#define dprintf(...) do { } while (0)
35#endif
36
diff --git a/tools/power/cpupower/bench/cpufreq-bench_plot.sh b/tools/power/cpupower/bench/cpufreq-bench_plot.sh
new file mode 100644
index 00000000000..410021a12f4
--- /dev/null
+++ b/tools/power/cpupower/bench/cpufreq-bench_plot.sh
@@ -0,0 +1,104 @@
1#!/bin/bash
2
3# This program is free software: you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2, or (at your option)
6# any later version.
7
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16# 02110-1301, USA.
17
18# Author/Copyright(c): 2009, Thomas Renninger <trenn@suse.de>, Novell Inc.
19
20# Helper script to easily create nice plots of your cpufreq-bench results
21
22dir=`mktemp -d`
23output_file="cpufreq-bench.png"
24global_title="cpufreq-bench plot"
25picture_type="jpeg"
26file[0]=""
27
28function usage()
29{
30 echo "cpufreq-bench_plot.sh [OPTIONS] logfile [measure_title] [logfile [measure_title]] ...]"
31 echo
32 echo "Options"
33 echo " -o output_file"
34 echo " -t global_title"
35 echo " -p picture_type [jpeg|gif|png|postscript|...]"
36 exit 1
37}
38
39if [ $# -eq 0 ];then
40 echo "No benchmark results file provided"
41 echo
42 usage
43fi
44
45while getopts o:t:p: name ; do
46 case $name in
47 o)
48 output_file="$OPTARG".$picture_type
49 ;;
50 t)
51 global_title="$OPTARG"
52 ;;
53 p)
54 picture_type="$OPTARG"
55 ;;
56 ?)
57 usage
58 ;;
59 esac
60done
61shift $(($OPTIND -1))
62
63plots=0
64while [ "$1" ];do
65 if [ ! -f "$1" ];then
66 echo "File $1 does not exist"
67 usage
68 fi
69 file[$plots]="$1"
70 title[$plots]="$2"
71 # echo "File: ${file[$plots]} - ${title[plots]}"
72 shift;shift
73 plots=$((plots + 1))
74done
75
76echo "set terminal $picture_type" >> $dir/plot_script.gpl
77echo "set output \"$output_file\"" >> $dir/plot_script.gpl
78echo "set title \"$global_title\"" >> $dir/plot_script.gpl
79echo "set xlabel \"sleep/load time\"" >> $dir/plot_script.gpl
80echo "set ylabel \"Performance (%)\"" >> $dir/plot_script.gpl
81
82for((plot=0;plot<$plots;plot++));do
83
84 # Sanity check
85 ###### I am to dump to get this redirected to stderr/stdout in one awk call... #####
86 cat ${file[$plot]} |grep -v "^#" |awk '{if ($2 != $3) printf("Error in measure %d:Load time %s does not equal sleep time %s, plot will not be correct\n", $1, $2, $3); ERR=1}'
87 ###### I am to dump to get this redirected in one awk call... #####
88
89 # Parse out load time (which must be equal to sleep time for a plot), divide it by 1000
90 # to get ms and parse out the performance in percentage and write it to a temp file for plotting
91 cat ${file[$plot]} |grep -v "^#" |awk '{printf "%lu %.1f\n",$2/1000, $6}' >$dir/data_$plot
92
93 if [ $plot -eq 0 ];then
94 echo -n "plot " >> $dir/plot_script.gpl
95 fi
96 echo -n "\"$dir/data_$plot\" title \"${title[$plot]}\" with lines" >> $dir/plot_script.gpl
97 if [ $(($plot + 1)) -ne $plots ];then
98 echo -n ", " >> $dir/plot_script.gpl
99 fi
100done
101echo >> $dir/plot_script.gpl
102
103gnuplot $dir/plot_script.gpl
104rm -r $dir \ No newline at end of file
diff --git a/tools/power/cpupower/bench/cpufreq-bench_script.sh b/tools/power/cpupower/bench/cpufreq-bench_script.sh
new file mode 100644
index 00000000000..de20d2a0687
--- /dev/null
+++ b/tools/power/cpupower/bench/cpufreq-bench_script.sh
@@ -0,0 +1,101 @@
1#!/bin/bash
2
3# This program is free software: you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2, or (at your option)
6# any later version.
7
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16# 02110-1301, USA.
17
18# Author/Copyright(c): 2009, Thomas Renninger <trenn@suse.de>, Novell Inc.
19
20# Ondemand up_threshold and sampling rate test script for cpufreq-bench
21# mircobenchmark.
22# Modify the general variables at the top or extend or copy out parts
23# if you want to test other things
24#
25
26# Default with latest kernels is 95, before micro account patches
27# it was 80, cmp. with git commit 808009131046b62ac434dbc796
28UP_THRESHOLD="60 80 95"
29# Depending on the kernel and the HW sampling rate could be restricted
30# and cannot be set that low...
31# E.g. before git commit cef9615a853ebc4972084f7 one could only set
32# min sampling rate of 80000 if CONFIG_HZ=250
33SAMPLING_RATE="20000 80000"
34
35function measure()
36{
37 local -i up_threshold_set
38 local -i sampling_rate_set
39
40 for up_threshold in $UP_THRESHOLD;do
41 for sampling_rate in $SAMPLING_RATE;do
42 # Set values in sysfs
43 echo $up_threshold >/sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold
44 echo $sampling_rate >/sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate
45 up_threshold_set=$(cat /sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold)
46 sampling_rate_set=$(cat /sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate)
47
48 # Verify set values in sysfs
49 if [ ${up_threshold_set} -eq ${up_threshold} ];then
50 echo "up_threshold: $up_threshold, set in sysfs: ${up_threshold_set}"
51 else
52 echo "WARNING: Tried to set up_threshold: $up_threshold, set in sysfs: ${up_threshold_set}"
53 fi
54 if [ ${sampling_rate_set} -eq ${sampling_rate} ];then
55 echo "sampling_rate: $sampling_rate, set in sysfs: ${sampling_rate_set}"
56 else
57 echo "WARNING: Tried to set sampling_rate: $sampling_rate, set in sysfs: ${sampling_rate_set}"
58 fi
59
60 # Benchmark
61 cpufreq-bench -o /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}
62 done
63 done
64}
65
66function create_plots()
67{
68 local command
69
70 for up_threshold in $UP_THRESHOLD;do
71 command="cpufreq-bench_plot.sh -o \"sampling_rate_${SAMPLING_RATE}_up_threshold_${up_threshold}\" -t \"Ondemand sampling_rate: ${SAMPLING_RATE} comparison - Up_threshold: $up_threshold %\""
72 for sampling_rate in $SAMPLING_RATE;do
73 command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"sampling_rate = $sampling_rate\""
74 done
75 echo $command
76 eval "$command"
77 echo
78 done
79
80 for sampling_rate in $SAMPLING_RATE;do
81 command="cpufreq-bench_plot.sh -o \"up_threshold_${UP_THRESHOLD}_sampling_rate_${sampling_rate}\" -t \"Ondemand up_threshold: ${UP_THRESHOLD} % comparison - sampling_rate: $sampling_rate\""
82 for up_threshold in $UP_THRESHOLD;do
83 command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"up_threshold = $up_threshold\""
84 done
85 echo $command
86 eval "$command"
87 echo
88 done
89
90 command="cpufreq-bench_plot.sh -o \"up_threshold_${UP_THRESHOLD}_sampling_rate_${SAMPLING_RATE}\" -t \"Ondemand up_threshold: ${UP_THRESHOLD} and sampling_rate ${SAMPLING_RATE} comparison\""
91 for sampling_rate in $SAMPLING_RATE;do
92 for up_threshold in $UP_THRESHOLD;do
93 command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"up_threshold = $up_threshold - sampling_rate = $sampling_rate\""
94 done
95 done
96 echo "$command"
97 eval "$command"
98}
99
100measure
101create_plots \ No newline at end of file
diff --git a/tools/power/cpupower/bench/example.cfg b/tools/power/cpupower/bench/example.cfg
new file mode 100644
index 00000000000..f91f6436068
--- /dev/null
+++ b/tools/power/cpupower/bench/example.cfg
@@ -0,0 +1,11 @@
1sleep = 50000
2load = 50000
3cpu = 0
4priority = LOW
5output = /var/log/cpufreq-bench
6sleep_step = 50000
7load_step = 50000
8cycles = 20
9rounds = 40
10verbose = 0
11governor = ondemand
diff --git a/tools/power/cpupower/bench/main.c b/tools/power/cpupower/bench/main.c
new file mode 100644
index 00000000000..24910313a52
--- /dev/null
+++ b/tools/power/cpupower/bench/main.c
@@ -0,0 +1,202 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <unistd.h>
24#include <getopt.h>
25#include <errno.h>
26
27#include "config.h"
28#include "system.h"
29#include "benchmark.h"
30
31static struct option long_options[] = {
32 {"output", 1, 0, 'o'},
33 {"sleep", 1, 0, 's'},
34 {"load", 1, 0, 'l'},
35 {"verbose", 0, 0, 'v'},
36 {"cpu", 1, 0, 'c'},
37 {"governor", 1, 0, 'g'},
38 {"prio", 1, 0, 'p'},
39 {"file", 1, 0, 'f'},
40 {"cycles", 1, 0, 'n'},
41 {"rounds", 1, 0, 'r'},
42 {"load-step", 1, 0, 'x'},
43 {"sleep-step", 1, 0, 'y'},
44 {"help", 0, 0, 'h'},
45 {0, 0, 0, 0}
46};
47
48/*******************************************************************
49 usage
50*******************************************************************/
51
52void usage()
53{
54 printf("usage: ./bench\n");
55 printf("Options:\n");
56 printf(" -l, --load=<long int>\t\tinitial load time in us\n");
57 printf(" -s, --sleep=<long int>\t\tinitial sleep time in us\n");
58 printf(" -x, --load-step=<long int>\ttime to be added to load time, in us\n");
59 printf(" -y, --sleep-step=<long int>\ttime to be added to sleep time, in us\n");
60 printf(" -c, --cpu=<cpu #>\t\t\tCPU Nr. to use, starting at 0\n");
61 printf(" -p, --prio=<priority>\t\t\tscheduler priority, HIGH, LOW or DEFAULT\n");
62 printf(" -g, --governor=<governor>\t\tcpufreq governor to test\n");
63 printf(" -n, --cycles=<int>\t\t\tload/sleep cycles\n");
64 printf(" -r, --rounds<int>\t\t\tload/sleep rounds\n");
65 printf(" -f, --file=<configfile>\t\tconfig file to use\n");
66 printf(" -o, --output=<dir>\t\t\toutput path. Filename will be OUTPUTPATH/benchmark_TIMESTAMP.log\n");
67 printf(" -v, --verbose\t\t\t\tverbose output on/off\n");
68 printf(" -h, --help\t\t\t\tPrint this help screen\n");
69 exit(1);
70}
71
72/*******************************************************************
73 main
74*******************************************************************/
75
76int main(int argc, char **argv)
77{
78 int c;
79 int option_index = 0;
80 struct config *config = NULL;
81
82 config = prepare_default_config();
83
84 if (config == NULL)
85 return EXIT_FAILURE;
86
87 while (1) {
88 c = getopt_long (argc, argv, "hg:o:s:l:vc:p:f:n:r:x:y:",
89 long_options, &option_index);
90 if (c == -1)
91 break;
92
93 switch (c) {
94 case 'o':
95 if (config->output != NULL)
96 fclose(config->output);
97
98 config->output = prepare_output(optarg);
99
100 if (config->output == NULL)
101 return EXIT_FAILURE;
102
103 dprintf("user output path -> %s\n", optarg);
104 break;
105 case 's':
106 sscanf(optarg, "%li", &config->sleep);
107 dprintf("user sleep time -> %s\n", optarg);
108 break;
109 case 'l':
110 sscanf(optarg, "%li", &config->load);
111 dprintf("user load time -> %s\n", optarg);
112 break;
113 case 'c':
114 sscanf(optarg, "%u", &config->cpu);
115 dprintf("user cpu -> %s\n", optarg);
116 break;
117 case 'g':
118 strncpy(config->governor, optarg, 14);
119 dprintf("user governor -> %s\n", optarg);
120 break;
121 case 'p':
122 if (string_to_prio(optarg) != SCHED_ERR) {
123 config->prio = string_to_prio(optarg);
124 dprintf("user prio -> %s\n", optarg);
125 } else {
126 if (config != NULL) {
127 if (config->output != NULL)
128 fclose(config->output);
129 free(config);
130 }
131 usage();
132 }
133 break;
134 case 'n':
135 sscanf(optarg, "%u", &config->cycles);
136 dprintf("user cycles -> %s\n", optarg);
137 break;
138 case 'r':
139 sscanf(optarg, "%u", &config->rounds);
140 dprintf("user rounds -> %s\n", optarg);
141 break;
142 case 'x':
143 sscanf(optarg, "%li", &config->load_step);
144 dprintf("user load_step -> %s\n", optarg);
145 break;
146 case 'y':
147 sscanf(optarg, "%li", &config->sleep_step);
148 dprintf("user sleep_step -> %s\n", optarg);
149 break;
150 case 'f':
151 if (prepare_config(optarg, config))
152 return EXIT_FAILURE;
153 break;
154 case 'v':
155 config->verbose = 1;
156 dprintf("verbose output enabled\n");
157 break;
158 case 'h':
159 case '?':
160 default:
161 if (config != NULL) {
162 if (config->output != NULL)
163 fclose(config->output);
164 free(config);
165 }
166 usage();
167 }
168 }
169
170 if (config->verbose) {
171 printf("starting benchmark with parameters:\n");
172 printf("config:\n\t"
173 "sleep=%li\n\t"
174 "load=%li\n\t"
175 "sleep_step=%li\n\t"
176 "load_step=%li\n\t"
177 "cpu=%u\n\t"
178 "cycles=%u\n\t"
179 "rounds=%u\n\t"
180 "governor=%s\n\n",
181 config->sleep,
182 config->load,
183 config->sleep_step,
184 config->load_step,
185 config->cpu,
186 config->cycles,
187 config->rounds,
188 config->governor);
189 }
190
191 prepare_user(config);
192 prepare_system(config);
193 start_benchmark(config);
194
195 if (config->output != stdout)
196 fclose(config->output);
197
198 free(config);
199
200 return EXIT_SUCCESS;
201}
202
diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c
new file mode 100644
index 00000000000..543bba14ae2
--- /dev/null
+++ b/tools/power/cpupower/bench/parse.c
@@ -0,0 +1,225 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <stdarg.h>
23#include <string.h>
24#include <time.h>
25#include <dirent.h>
26
27#include <sys/utsname.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30
31#include "parse.h"
32#include "config.h"
33
34/**
35 * converts priority string to priority
36 *
37 * @param str string that represents a scheduler priority
38 *
39 * @retval priority
40 * @retval SCHED_ERR when the priority doesn't exit
41 **/
42
43enum sched_prio string_to_prio(const char *str)
44{
45 if (strncasecmp("high", str, strlen(str)) == 0)
46 return SCHED_HIGH;
47 else if (strncasecmp("default", str, strlen(str)) == 0)
48 return SCHED_DEFAULT;
49 else if (strncasecmp("low", str, strlen(str)) == 0)
50 return SCHED_LOW;
51 else
52 return SCHED_ERR;
53}
54
55/**
56 * create and open logfile
57 *
58 * @param dir directory in which the logfile should be created
59 *
60 * @retval logfile on success
61 * @retval NULL when the file can't be created
62 **/
63
64FILE *prepare_output(const char *dirname)
65{
66 FILE *output = NULL;
67 int len;
68 char *filename;
69 struct utsname sysdata;
70 DIR *dir;
71
72 dir = opendir(dirname);
73 if (dir == NULL) {
74 if (mkdir(dirname, 0755)) {
75 perror("mkdir");
76 fprintf(stderr, "error: Cannot create dir %s\n",
77 dirname);
78 return NULL;
79 }
80 }
81
82 len = strlen(dirname) + 30;
83 filename = malloc(sizeof(char) * len);
84
85 if (uname(&sysdata) == 0) {
86 len += strlen(sysdata.nodename) + strlen(sysdata.release);
87 filename = realloc(filename, sizeof(char) * len);
88
89 if (filename == NULL) {
90 perror("realloc");
91 return NULL;
92 }
93
94 snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log",
95 dirname, sysdata.nodename, sysdata.release, time(NULL));
96 } else {
97 snprintf(filename, len - 1, "%s/benchmark_%li.log",
98 dirname, time(NULL));
99 }
100
101 dprintf("logilename: %s\n", filename);
102
103 output = fopen(filename, "w+");
104 if (output == NULL) {
105 perror("fopen");
106 fprintf(stderr, "error: unable to open logfile\n");
107 }
108
109 fprintf(stdout, "Logfile: %s\n", filename);
110
111 free(filename);
112 fprintf(output, "#round load sleep performance powersave percentage\n");
113 return output;
114}
115
116/**
117 * returns the default config
118 *
119 * @retval default config on success
120 * @retval NULL when the output file can't be created
121 **/
122
123struct config *prepare_default_config()
124{
125 struct config *config = malloc(sizeof(struct config));
126
127 dprintf("loading defaults\n");
128
129 config->sleep = 500000;
130 config->load = 500000;
131 config->sleep_step = 500000;
132 config->load_step = 500000;
133 config->cycles = 5;
134 config->rounds = 50;
135 config->cpu = 0;
136 config->prio = SCHED_HIGH;
137 config->verbose = 0;
138 strncpy(config->governor, "ondemand", 8);
139
140 config->output = stdout;
141
142#ifdef DEFAULT_CONFIG_FILE
143 if (prepare_config(DEFAULT_CONFIG_FILE, config))
144 return NULL;
145#endif
146 return config;
147}
148
149/**
150 * parses config file and returns the config to the caller
151 *
152 * @param path config file name
153 *
154 * @retval 1 on error
155 * @retval 0 on success
156 **/
157
158int prepare_config(const char *path, struct config *config)
159{
160 size_t len = 0;
161 char *opt, *val, *line = NULL;
162 FILE *configfile = fopen(path, "r");
163
164 if (config == NULL) {
165 fprintf(stderr, "error: config is NULL\n");
166 return 1;
167 }
168
169 if (configfile == NULL) {
170 perror("fopen");
171 fprintf(stderr, "error: unable to read configfile\n");
172 free(config);
173 return 1;
174 }
175
176 while (getline(&line, &len, configfile) != -1) {
177 if (line[0] == '#' || line[0] == ' ')
178 continue;
179
180 sscanf(line, "%as = %as", &opt, &val);
181
182 dprintf("parsing: %s -> %s\n", opt, val);
183
184 if (strncmp("sleep", opt, strlen(opt)) == 0)
185 sscanf(val, "%li", &config->sleep);
186
187 else if (strncmp("load", opt, strlen(opt)) == 0)
188 sscanf(val, "%li", &config->load);
189
190 else if (strncmp("load_step", opt, strlen(opt)) == 0)
191 sscanf(val, "%li", &config->load_step);
192
193 else if (strncmp("sleep_step", opt, strlen(opt)) == 0)
194 sscanf(val, "%li", &config->sleep_step);
195
196 else if (strncmp("cycles", opt, strlen(opt)) == 0)
197 sscanf(val, "%u", &config->cycles);
198
199 else if (strncmp("rounds", opt, strlen(opt)) == 0)
200 sscanf(val, "%u", &config->rounds);
201
202 else if (strncmp("verbose", opt, strlen(opt)) == 0)
203 sscanf(val, "%u", &config->verbose);
204
205 else if (strncmp("output", opt, strlen(opt)) == 0)
206 config->output = prepare_output(val);
207
208 else if (strncmp("cpu", opt, strlen(opt)) == 0)
209 sscanf(val, "%u", &config->cpu);
210
211 else if (strncmp("governor", opt, 14) == 0)
212 strncpy(config->governor, val, 14);
213
214 else if (strncmp("priority", opt, strlen(opt)) == 0) {
215 if (string_to_prio(val) != SCHED_ERR)
216 config->prio = string_to_prio(val);
217 }
218 }
219
220 free(line);
221 free(opt);
222 free(val);
223
224 return 0;
225}
diff --git a/tools/power/cpupower/bench/parse.h b/tools/power/cpupower/bench/parse.h
new file mode 100644
index 00000000000..a8dc632d9ee
--- /dev/null
+++ b/tools/power/cpupower/bench/parse.h
@@ -0,0 +1,53 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20/* struct that holds the required config parameters */
21struct config
22{
23 long sleep; /* sleep time in µs */
24 long load; /* load time in µs */
25 long sleep_step; /* time value which changes the
26 * sleep time after every round in µs */
27 long load_step; /* time value which changes the
28 * load time after every round in µs */
29 unsigned int cycles; /* calculation cycles with the same sleep/load time */
30 unsigned int rounds; /* calculation rounds with iterated sleep/load time */
31 unsigned int cpu; /* cpu for which the affinity is set */
32 char governor[15]; /* cpufreq governor */
33 enum sched_prio /* possible scheduler priorities */
34 {
35 SCHED_ERR = -1,
36 SCHED_HIGH,
37 SCHED_DEFAULT,
38 SCHED_LOW
39 } prio;
40
41 unsigned int verbose; /* verbose output */
42 FILE *output; /* logfile */
43 char *output_filename; /* logfile name, must be freed at the end
44 if output != NULL and output != stdout*/
45};
46
47enum sched_prio string_to_prio(const char *str);
48
49FILE *prepare_output(const char *dir);
50
51int prepare_config(const char *path, struct config *config);
52struct config *prepare_default_config();
53
diff --git a/tools/power/cpupower/bench/system.c b/tools/power/cpupower/bench/system.c
new file mode 100644
index 00000000000..f01e3f4be84
--- /dev/null
+++ b/tools/power/cpupower/bench/system.c
@@ -0,0 +1,191 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include <stdio.h>
21#include <time.h>
22#include <sys/time.h>
23#include <sys/types.h>
24#include <unistd.h>
25
26#include <sched.h>
27
28#include <cpufreq.h>
29
30#include "config.h"
31#include "system.h"
32
33/**
34 * returns time since epoch in µs
35 *
36 * @retval time
37 **/
38
39long long int get_time()
40{
41 struct timeval now;
42
43 gettimeofday(&now, NULL);
44
45 return (long long int)(now.tv_sec * 1000000LL + now.tv_usec);
46}
47
48/**
49 * sets the cpufreq governor
50 *
51 * @param governor cpufreq governor name
52 * @param cpu cpu for which the governor should be set
53 *
54 * @retval 0 on success
55 * @retval -1 when failed
56 **/
57
58int set_cpufreq_governor(char *governor, unsigned int cpu)
59{
60
61 dprintf("set %s as cpufreq governor\n", governor);
62
63 if (cpufreq_cpu_exists(cpu) != 0) {
64 perror("cpufreq_cpu_exists");
65 fprintf(stderr, "error: cpu %u does not exist\n", cpu);
66 return -1;
67 }
68
69 if (cpufreq_modify_policy_governor(cpu, governor) != 0) {
70 perror("cpufreq_modify_policy_governor");
71 fprintf(stderr, "error: unable to set %s governor\n", governor);
72 return -1;
73 }
74
75 return 0;
76}
77
78/**
79 * sets cpu affinity for the process
80 *
81 * @param cpu cpu# to which the affinity should be set
82 *
83 * @retval 0 on success
84 * @retval -1 when setting the affinity failed
85 **/
86
87int set_cpu_affinity(unsigned int cpu)
88{
89 cpu_set_t cpuset;
90
91 CPU_ZERO(&cpuset);
92 CPU_SET(cpu, &cpuset);
93
94 dprintf("set affinity to cpu #%u\n", cpu);
95
96 if (sched_setaffinity(getpid(), sizeof(cpu_set_t), &cpuset) < 0) {
97 perror("sched_setaffinity");
98 fprintf(stderr, "warning: unable to set cpu affinity\n");
99 return -1;
100 }
101
102 return 0;
103}
104
105/**
106 * sets the process priority parameter
107 *
108 * @param priority priority value
109 *
110 * @retval 0 on success
111 * @retval -1 when setting the priority failed
112 **/
113
114int set_process_priority(int priority)
115{
116 struct sched_param param;
117
118 dprintf("set scheduler priority to %i\n", priority);
119
120 param.sched_priority = priority;
121
122 if (sched_setscheduler(0, SCHEDULER, &param) < 0) {
123 perror("sched_setscheduler");
124 fprintf(stderr, "warning: unable to set scheduler priority\n");
125 return -1;
126 }
127
128 return 0;
129}
130
131/**
132 * notifies the user that the benchmark may run some time
133 *
134 * @param config benchmark config values
135 *
136 **/
137
138void prepare_user(const struct config *config)
139{
140 unsigned long sleep_time = 0;
141 unsigned long load_time = 0;
142 unsigned int round;
143
144 for (round = 0; round < config->rounds; round++) {
145 sleep_time += 2 * config->cycles *
146 (config->sleep + config->sleep_step * round);
147 load_time += 2 * config->cycles *
148 (config->load + config->load_step * round) +
149 (config->load + config->load_step * round * 4);
150 }
151
152 if (config->verbose || config->output != stdout)
153 printf("approx. test duration: %im\n",
154 (int)((sleep_time + load_time) / 60000000));
155}
156
157/**
158 * sets up the cpu affinity and scheduler priority
159 *
160 * @param config benchmark config values
161 *
162 **/
163
164void prepare_system(const struct config *config)
165{
166 if (config->verbose)
167 printf("set cpu affinity to cpu #%u\n", config->cpu);
168
169 set_cpu_affinity(config->cpu);
170
171 switch (config->prio) {
172 case SCHED_HIGH:
173 if (config->verbose)
174 printf("high priority condition requested\n");
175
176 set_process_priority(PRIORITY_HIGH);
177 break;
178 case SCHED_LOW:
179 if (config->verbose)
180 printf("low priority condition requested\n");
181
182 set_process_priority(PRIORITY_LOW);
183 break;
184 default:
185 if (config->verbose)
186 printf("default priority condition requested\n");
187
188 set_process_priority(PRIORITY_DEFAULT);
189 }
190}
191
diff --git a/tools/power/cpupower/bench/system.h b/tools/power/cpupower/bench/system.h
new file mode 100644
index 00000000000..3a8c858b78f
--- /dev/null
+++ b/tools/power/cpupower/bench/system.h
@@ -0,0 +1,29 @@
1/* cpufreq-bench CPUFreq microbenchmark
2 *
3 * Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20#include "parse.h"
21
22long long get_time();
23
24int set_cpufreq_governor(char *governor, unsigned int cpu);
25int set_cpu_affinity(unsigned int cpu);
26int set_process_priority(int priority);
27
28void prepare_user(const struct config *config);
29void prepare_system(const struct config *config);
diff --git a/tools/power/cpupower/debug/i386/Makefile b/tools/power/cpupower/debug/i386/Makefile
new file mode 100644
index 00000000000..d08cc1ead9b
--- /dev/null
+++ b/tools/power/cpupower/debug/i386/Makefile
@@ -0,0 +1,20 @@
1default: all
2
3centrino-decode: centrino-decode.c
4 $(CC) $(CFLAGS) -o centrino-decode centrino-decode.c
5
6dump_psb: dump_psb.c
7 $(CC) $(CFLAGS) -o dump_psb dump_psb.c
8
9intel_gsic: intel_gsic.c
10 $(CC) $(CFLAGS) -o intel_gsic -llrmi intel_gsic.c
11
12powernow-k8-decode: powernow-k8-decode.c
13 $(CC) $(CFLAGS) -o powernow-k8-decode powernow-k8-decode.c
14
15all: centrino-decode dump_psb intel_gsic powernow-k8-decode
16
17clean:
18 rm -rf centrino-decode dump_psb intel_gsic powernow-k8-decode
19
20.PHONY: all default clean
diff --git a/tools/power/cpupower/debug/i386/centrino-decode.c b/tools/power/cpupower/debug/i386/centrino-decode.c
new file mode 100644
index 00000000000..7ef24cce492
--- /dev/null
+++ b/tools/power/cpupower/debug/i386/centrino-decode.c
@@ -0,0 +1,113 @@
1/*
2 * (C) 2003 - 2004 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Based on code found in
7 * linux/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
8 * and originally developed by Jeremy Fitzhardinge.
9 *
10 * USAGE: simply run it to decode the current settings on CPU 0,
11 * or pass the CPU number as argument, or pass the MSR content
12 * as argument.
13 */
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <stdint.h>
18#include <unistd.h>
19#include <errno.h>
20#include <fcntl.h>
21
22#include <sys/types.h>
23#include <sys/stat.h>
24
25#define MCPU 32
26
27#define MSR_IA32_PERF_STATUS 0x198
28
29static int rdmsr(unsigned int cpu, unsigned int msr,
30 unsigned int *lo, unsigned int *hi)
31{
32 int fd;
33 char file[20];
34 unsigned long long val;
35 int retval = -1;
36
37 *lo = *hi = 0;
38
39 if (cpu > MCPU)
40 goto err1;
41
42 sprintf(file, "/dev/cpu/%d/msr", cpu);
43 fd = open(file, O_RDONLY);
44
45 if (fd < 0)
46 goto err1;
47
48 if (lseek(fd, msr, SEEK_CUR) == -1)
49 goto err2;
50
51 if (read(fd, &val, 8) != 8)
52 goto err2;
53
54 *lo = (uint32_t )(val & 0xffffffffull);
55 *hi = (uint32_t )(val>>32 & 0xffffffffull);
56
57 retval = 0;
58err2:
59 close(fd);
60err1:
61 return retval;
62}
63
64static void decode (unsigned int msr)
65{
66 unsigned int multiplier;
67 unsigned int mv;
68
69 multiplier = ((msr >> 8) & 0xFF);
70
71 mv = (((msr & 0xFF) * 16) + 700);
72
73 printf("0x%x means multiplier %d @ %d mV\n", msr, multiplier, mv);
74}
75
76static int decode_live(unsigned int cpu)
77{
78 unsigned int lo, hi;
79 int err;
80
81 err = rdmsr(cpu, MSR_IA32_PERF_STATUS, &lo, &hi);
82
83 if (err) {
84 printf("can't get MSR_IA32_PERF_STATUS for cpu %d\n", cpu);
85 printf("Possible trouble: you don't run an Enhanced SpeedStep capable cpu\n");
86 printf("or you are not root, or the msr driver is not present\n");
87 return 1;
88 }
89
90 decode(lo);
91
92 return 0;
93}
94
95int main (int argc, char **argv)
96{
97 unsigned int cpu, mode = 0;
98
99 if (argc < 2)
100 cpu = 0;
101 else {
102 cpu = strtoul(argv[1], NULL, 0);
103 if (cpu >= MCPU)
104 mode = 1;
105 }
106
107 if (mode)
108 decode(cpu);
109 else
110 decode_live(cpu);
111
112 return 0;
113}
diff --git a/tools/power/cpupower/debug/i386/dump_psb.c b/tools/power/cpupower/debug/i386/dump_psb.c
new file mode 100644
index 00000000000..8d6a4751425
--- /dev/null
+++ b/tools/power/cpupower/debug/i386/dump_psb.c
@@ -0,0 +1,196 @@
1/*
2 * dump_psb. (c) 2004, Dave Jones, Red Hat Inc.
3 * Licensed under the GPL v2.
4 */
5
6#include <fcntl.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <unistd.h>
11
12#define _GNU_SOURCE
13#include <getopt.h>
14
15#include <sys/mman.h>
16
17#define LEN (0x100000 - 0xc0000)
18#define OFFSET (0xc0000)
19
20#ifndef __packed
21#define __packed __attribute((packed))
22#endif
23
24static long relevant;
25
26static const int fid_to_mult[32] = {
27 110, 115, 120, 125, 50, 55, 60, 65,
28 70, 75, 80, 85, 90, 95, 100, 105,
29 30, 190, 40, 200, 130, 135, 140, 210,
30 150, 225, 160, 165, 170, 180, -1, -1,
31};
32
33static const int vid_to_voltage[32] = {
34 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
35 1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
36 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
37 1075, 1050, 1024, 1000, 975, 950, 925, 0,
38};
39
40struct psb_header {
41 char signature[10];
42 u_char version;
43 u_char flags;
44 u_short settlingtime;
45 u_char res1;
46 u_char numpst;
47} __packed;
48
49struct pst_header {
50 u_int32_t cpuid;
51 u_char fsb;
52 u_char maxfid;
53 u_char startvid;
54 u_char numpstates;
55} __packed;
56
57static u_int fsb;
58static u_int sgtc;
59
60static int
61decode_pst(char *p, int npstates)
62{
63 int i;
64 int freq, fid, vid;
65
66 for (i = 0; i < npstates; ++i) {
67 fid = *p++;
68 vid = *p++;
69 freq = 100 * fid_to_mult[fid] * fsb;
70
71 printf(" %2d %8dkHz FID %02x (%2d.%01d) VID %02x (%4dmV)\n",
72 i,
73 freq,
74 fid, fid_to_mult[fid]/10, fid_to_mult[fid]%10,
75 vid, vid_to_voltage[vid]);
76 }
77
78 return 0;
79}
80
81static
82void decode_psb(char *p, int numpst)
83{
84 int i;
85 struct psb_header *psb;
86 struct pst_header *pst;
87
88 psb = (struct psb_header*) p;
89
90 if (psb->version != 0x12)
91 return;
92
93 printf("PSB version: %hhx flags: %hhx settling time %hhuus res1 %hhx num pst %hhu\n",
94 psb->version,
95 psb->flags,
96 psb->settlingtime,
97 psb->res1,
98 psb->numpst);
99 sgtc = psb->settlingtime * 100;
100
101 if (sgtc < 10000)
102 sgtc = 10000;
103
104 p = ((char *) psb) + sizeof(struct psb_header);
105
106 if (numpst < 0)
107 numpst = psb->numpst;
108 else
109 printf("Overriding number of pst :%d\n", numpst);
110
111 for (i = 0; i < numpst; i++) {
112 pst = (struct pst_header*) p;
113
114 if (relevant != 0) {
115 if (relevant!= pst->cpuid)
116 goto next_one;
117 }
118
119 printf(" PST %d cpuid %.3x fsb %hhu mfid %hhx svid %hhx numberstates %hhu\n",
120 i+1,
121 pst->cpuid,
122 pst->fsb,
123 pst->maxfid,
124 pst->startvid,
125 pst->numpstates);
126
127 fsb = pst->fsb;
128 decode_pst(p + sizeof(struct pst_header), pst->numpstates);
129
130next_one:
131 p += sizeof(struct pst_header) + 2*pst->numpstates;
132 }
133
134}
135
136static struct option info_opts[] = {
137 {.name = "numpst", .has_arg=no_argument, .flag=NULL, .val='n'},
138};
139
140void print_help(void)
141{
142 printf ("Usage: dump_psb [options]\n");
143 printf ("Options:\n");
144 printf (" -n, --numpst Set number of PST tables to scan\n");
145 printf (" -r, --relevant Only display PSTs relevant to cpuid N\n");
146}
147
148int
149main(int argc, char *argv[])
150{
151 int fd;
152 int numpst=-1;
153 int ret=0, cont=1;
154 char *mem = NULL;
155 char *p;
156
157 do {
158 ret = getopt_long(argc, argv, "hr:n:", info_opts, NULL);
159 switch (ret){
160 case '?':
161 case 'h':
162 print_help();
163 cont = 0;
164 break;
165 case 'r':
166 relevant = strtol(optarg, NULL, 16);
167 break;
168 case 'n':
169 numpst = strtol(optarg, NULL, 10);
170 break;
171 case -1:
172 cont = 0;
173 break;
174 }
175
176 } while(cont);
177
178 fd = open("/dev/mem", O_RDONLY);
179 if (fd < 0) {
180 printf ("Couldn't open /dev/mem. Are you root?\n");
181 exit(1);
182 }
183
184 mem = mmap(mem, 0x100000 - 0xc0000, PROT_READ, MAP_SHARED, fd, 0xc0000);
185 close(fd);
186
187 for (p = mem; p - mem < LEN; p+=16) {
188 if (memcmp(p, "AMDK7PNOW!", 10) == 0) {
189 decode_psb(p, numpst);
190 break;
191 }
192 }
193
194 munmap(mem, LEN);
195 return 0;
196}
diff --git a/tools/power/cpupower/debug/i386/intel_gsic.c b/tools/power/cpupower/debug/i386/intel_gsic.c
new file mode 100644
index 00000000000..53f5293c9c9
--- /dev/null
+++ b/tools/power/cpupower/debug/i386/intel_gsic.c
@@ -0,0 +1,78 @@
1/*
2 * (C) 2003 Bruno Ducrot
3 * (C) 2004 Dominik Brodowski <linux@dominikbrodowski.de>
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 *
7 * Based on code found in
8 * linux/include/asm-i386/ist.h and linux/arch/i386/kernel/setup.c
9 * and originally developed by Andy Grover <andrew.grover@intel.com>
10 */
11
12#include <stdio.h>
13#include <string.h>
14#include <lrmi.h>
15
16int main (void)
17{
18 struct LRMI_regs r;
19 int retval;
20
21 if (!LRMI_init())
22 return 0;
23
24 memset(&r, 0, sizeof(r));
25
26 r.eax = 0x0000E980;
27 r.edx = 0x47534943;
28
29 retval = LRMI_int(0x15, &r);
30
31 if (!retval) {
32 printf("Failed!\n");
33 return 0;
34 }
35 if (r.eax == 0x47534943) {
36 printf("BIOS supports GSIC call:\n");
37 printf("\tsignature: %c%c%c%c\n",
38 (r.eax >> 24) & 0xff,
39 (r.eax >> 16) & 0xff,
40 (r.eax >> 8) & 0xff,
41 (r.eax) & 0xff);
42 printf("\tcommand port = 0x%.4x\n",
43 r.ebx & 0xffff);
44 printf("\tcommand = 0x%.4x\n",
45 (r.ebx >> 16) & 0xffff);
46 printf("\tevent port = 0x%.8x\n", r.ecx);
47 printf("\tflags = 0x%.8x\n", r.edx);
48 if (((r.ebx >> 16) & 0xffff) != 0x82) {
49 printf("non-default command value. If speedstep-smi "
50 "doesn't work out of the box,\nyou may want to "
51 "try out the default value by passing "
52 "smi_cmd=0x82 to the module\n ON YOUR OWN "
53 "RISK.\n");
54 }
55 if ((r.ebx & 0xffff) != 0xb2) {
56 printf("non-default command port. If speedstep-smi "
57 "doesn't work out of the box,\nyou may want to "
58 "try out the default value by passing "
59 "smi_port=0x82 to the module\n ON YOUR OWN "
60 "RISK.\n");
61 }
62 } else {
63 printf("BIOS DOES NOT support GSIC call. Dumping registers anyway:\n");
64 printf("eax = 0x%.8x\n", r.eax);
65 printf("ebx = 0x%.8x\n", r.ebx);
66 printf("ecx = 0x%.8x\n", r.ecx);
67 printf("edx = 0x%.8x\n", r.edx);
68 printf("Note also that some BIOS do not support the initial "
69 "GSIC call, but the newer\nspeeedstep-smi driver may "
70 "work.\nFor this, you need to pass some arguments to "
71 "the speedstep-smi driver:\n");
72 printf("\tsmi_cmd=0x?? smi_port=0x?? smi_sig=1\n");
73 printf("\nUnfortunately, you have to know what exactly are "
74 "smi_cmd and smi_port, and this\nis system "
75 "dependant.\n");
76 }
77 return 1;
78}
diff --git a/tools/power/cpupower/debug/i386/powernow-k8-decode.c b/tools/power/cpupower/debug/i386/powernow-k8-decode.c
new file mode 100644
index 00000000000..638a6b3bfd9
--- /dev/null
+++ b/tools/power/cpupower/debug/i386/powernow-k8-decode.c
@@ -0,0 +1,96 @@
1/*
2 * (C) 2004 Bruno Ducrot <ducrot@poupinou.org>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Based on code found in
7 * linux/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
8 * and originally developed by Paul Devriendt
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <stdint.h>
14#include <unistd.h>
15#include <errno.h>
16#include <fcntl.h>
17
18#include <sys/types.h>
19#include <sys/stat.h>
20
21#define MCPU 32
22
23#define MSR_FIDVID_STATUS 0xc0010042
24
25#define MSR_S_HI_CURRENT_VID 0x0000001f
26#define MSR_S_LO_CURRENT_FID 0x0000003f
27
28static int get_fidvid(uint32_t cpu, uint32_t *fid, uint32_t *vid)
29{
30 int err = 1;
31 uint64_t msr = 0;
32 int fd;
33 char file[20];
34
35 if (cpu > MCPU)
36 goto out;
37
38 sprintf(file, "/dev/cpu/%d/msr", cpu);
39
40 fd = open(file, O_RDONLY);
41 if (fd < 0)
42 goto out;
43 lseek(fd, MSR_FIDVID_STATUS, SEEK_CUR);
44 if (read(fd, &msr, 8) != 8)
45 goto err1;
46
47 *fid = ((uint32_t )(msr & 0xffffffffull)) & MSR_S_LO_CURRENT_FID;
48 *vid = ((uint32_t )(msr>>32 & 0xffffffffull)) & MSR_S_HI_CURRENT_VID;
49 err = 0;
50err1:
51 close(fd);
52out:
53 return err;
54}
55
56
57/* Return a frequency in MHz, given an input fid */
58static uint32_t find_freq_from_fid(uint32_t fid)
59{
60 return 800 + (fid * 100);
61}
62
63/* Return a voltage in miliVolts, given an input vid */
64static uint32_t find_millivolts_from_vid(uint32_t vid)
65{
66 return 1550-vid*25;
67}
68
69int main (int argc, char *argv[])
70{
71 int err;
72 int cpu;
73 uint32_t fid, vid;
74
75 if (argc < 2)
76 cpu = 0;
77 else
78 cpu = strtoul(argv[1], NULL, 0);
79
80 err = get_fidvid(cpu, &fid, &vid);
81
82 if (err) {
83 printf("can't get fid, vid from MSR\n");
84 printf("Possible trouble: you don't run a powernow-k8 capable cpu\n");
85 printf("or you are not root, or the msr driver is not present\n");
86 exit(1);
87 }
88
89
90 printf("cpu %d currently at %d MHz and %d mV\n",
91 cpu,
92 find_freq_from_fid(fid),
93 find_millivolts_from_vid(vid));
94
95 return 0;
96}
diff --git a/tools/power/cpupower/debug/kernel/Makefile b/tools/power/cpupower/debug/kernel/Makefile
new file mode 100644
index 00000000000..96b146fe6f8
--- /dev/null
+++ b/tools/power/cpupower/debug/kernel/Makefile
@@ -0,0 +1,23 @@
1obj-m :=
2
3KDIR := /lib/modules/$(shell uname -r)/build
4PWD := $(shell pwd)
5KMISC := /lib/modules/$(shell uname -r)/cpufrequtils/
6
7ifeq ("$(CONFIG_X86_TSC)", "y")
8 obj-m += cpufreq-test_tsc.o
9endif
10
11default:
12 $(MAKE) -C $(KDIR) M=$(PWD)
13
14clean:
15 - rm -rf *.o *.ko .tmp-versions .*.cmd .*.mod.* *.mod.c
16 - rm -rf .tmp_versions* Module.symvers modules.order
17
18install: default
19 install -d $(KMISC)
20 install -m 644 -c *.ko $(KMISC)
21 /sbin/depmod -a
22
23all: default
diff --git a/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c
new file mode 100644
index 00000000000..66cace601e5
--- /dev/null
+++ b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c
@@ -0,0 +1,113 @@
1/*
2 * test module to check whether the TSC-based delay routine continues
3 * to work properly after cpufreq transitions. Needs ACPI to work
4 * properly.
5 *
6 * Based partly on the Power Management Timer (PMTMR) code to be found
7 * in arch/i386/kernel/timers/timer_pm.c on recent 2.6. kernels, especially
8 * code written by John Stultz. The read_pmtmr function was copied verbatim
9 * from that file.
10 *
11 * (C) 2004 Dominik Brodowski
12 *
13 * To use:
14 * 1.) pass clock=tsc to the kernel on your bootloader
15 * 2.) modprobe this module (it'll fail)
16 * 3.) change CPU frequency
17 * 4.) modprobe this module again
18 * 5.) if the third value, "diff_pmtmr", changes between 2. and 4., the
19 * TSC-based delay routine on the Linux kernel does not correctly
20 * handle the cpufreq transition. Please report this to
21 * cpufreq@vger.kernel.org
22 */
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/delay.h>
28
29#include <asm/io.h>
30
31#include <acpi/acpi_bus.h>
32#include <acpi/acpi_drivers.h>
33
34static int pm_tmr_ioport = 0;
35
36/*helper function to safely read acpi pm timesource*/
37static u32 read_pmtmr(void)
38{
39 u32 v1=0,v2=0,v3=0;
40 /* It has been reported that because of various broken
41 * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time
42 * source is not latched, so you must read it multiple
43 * times to insure a safe value is read.
44 */
45 do {
46 v1 = inl(pm_tmr_ioport);
47 v2 = inl(pm_tmr_ioport);
48 v3 = inl(pm_tmr_ioport);
49 } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
50 || (v3 > v1 && v3 < v2));
51
52 /* mask the output to 24 bits */
53 return (v2 & 0xFFFFFF);
54}
55
56static int __init cpufreq_test_tsc(void)
57{
58 u32 now, then, diff;
59 u64 now_tsc, then_tsc, diff_tsc;
60 int i;
61
62 /* the following code snipped is copied from arch/x86/kernel/acpi/boot.c
63 of Linux v2.6.25. */
64
65 /* detect the location of the ACPI PM Timer */
66 if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) {
67 /* FADT rev. 2 */
68 if (acpi_gbl_FADT.xpm_timer_block.space_id !=
69 ACPI_ADR_SPACE_SYSTEM_IO)
70 return 0;
71
72 pm_tmr_ioport = acpi_gbl_FADT.xpm_timer_block.address;
73 /*
74 * "X" fields are optional extensions to the original V1.0
75 * fields, so we must selectively expand V1.0 fields if the
76 * corresponding X field is zero.
77 */
78 if (!pm_tmr_ioport)
79 pm_tmr_ioport = acpi_gbl_FADT.pm_timer_block;
80 } else {
81 /* FADT rev. 1 */
82 pm_tmr_ioport = acpi_gbl_FADT.pm_timer_block;
83 }
84
85 printk(KERN_DEBUG "start--> \n");
86 then = read_pmtmr();
87 rdtscll(then_tsc);
88 for (i=0;i<20;i++) {
89 mdelay(100);
90 now = read_pmtmr();
91 rdtscll(now_tsc);
92 diff = (now - then) & 0xFFFFFF;
93 diff_tsc = now_tsc - then_tsc;
94 printk(KERN_DEBUG "t1: %08u t2: %08u diff_pmtmr: %08u diff_tsc: %016llu\n", then, now, diff, diff_tsc);
95 then = now;
96 then_tsc = now_tsc;
97 }
98 printk(KERN_DEBUG "<-- end \n");
99 return -ENODEV;
100}
101
102static void __exit cpufreq_none(void)
103{
104 return;
105}
106
107module_init(cpufreq_test_tsc)
108module_exit(cpufreq_none)
109
110
111MODULE_AUTHOR("Dominik Brodowski");
112MODULE_DESCRIPTION("Verify the TSC cpufreq notifier working correctly -- needs ACPI-enabled system");
113MODULE_LICENSE ("GPL");
diff --git a/tools/power/cpupower/debug/x86_64/Makefile b/tools/power/cpupower/debug/x86_64/Makefile
new file mode 100644
index 00000000000..3326217dd31
--- /dev/null
+++ b/tools/power/cpupower/debug/x86_64/Makefile
@@ -0,0 +1,14 @@
1default: all
2
3centrino-decode: ../i386/centrino-decode.c
4 $(CC) $(CFLAGS) -o $@ $<
5
6powernow-k8-decode: ../i386/powernow-k8-decode.c
7 $(CC) $(CFLAGS) -o $@ $<
8
9all: centrino-decode powernow-k8-decode
10
11clean:
12 rm -rf centrino-decode powernow-k8-decode
13
14.PHONY: all default clean
diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
new file mode 100644
index 00000000000..d961101d1ce
--- /dev/null
+++ b/tools/power/cpupower/lib/cpufreq.c
@@ -0,0 +1,208 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7
8#include <stdio.h>
9#include <errno.h>
10#include <stdlib.h>
11#include <string.h>
12
13#include "cpufreq.h"
14#include "sysfs.h"
15
16int cpufreq_cpu_exists(unsigned int cpu)
17{
18 return sysfs_cpu_exists(cpu);
19}
20
21unsigned long cpufreq_get_freq_kernel(unsigned int cpu)
22{
23 return sysfs_get_freq_kernel(cpu);
24}
25
26unsigned long cpufreq_get_freq_hardware(unsigned int cpu)
27{
28 return sysfs_get_freq_hardware(cpu);
29}
30
31unsigned long cpufreq_get_transition_latency(unsigned int cpu)
32{
33 return sysfs_get_freq_transition_latency(cpu);
34}
35
36int cpufreq_get_hardware_limits(unsigned int cpu,
37 unsigned long *min,
38 unsigned long *max)
39{
40 if ((!min) || (!max))
41 return -EINVAL;
42 return sysfs_get_freq_hardware_limits(cpu, min, max);
43}
44
45char *cpufreq_get_driver(unsigned int cpu)
46{
47 return sysfs_get_freq_driver(cpu);
48}
49
50void cpufreq_put_driver(char *ptr)
51{
52 if (!ptr)
53 return;
54 free(ptr);
55}
56
57struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu)
58{
59 return sysfs_get_freq_policy(cpu);
60}
61
62void cpufreq_put_policy(struct cpufreq_policy *policy)
63{
64 if ((!policy) || (!policy->governor))
65 return;
66
67 free(policy->governor);
68 policy->governor = NULL;
69 free(policy);
70}
71
72struct cpufreq_available_governors *cpufreq_get_available_governors(unsigned
73 int cpu)
74{
75 return sysfs_get_freq_available_governors(cpu);
76}
77
78void cpufreq_put_available_governors(struct cpufreq_available_governors *any)
79{
80 struct cpufreq_available_governors *tmp, *next;
81
82 if (!any)
83 return;
84
85 tmp = any->first;
86 while (tmp) {
87 next = tmp->next;
88 if (tmp->governor)
89 free(tmp->governor);
90 free(tmp);
91 tmp = next;
92 }
93}
94
95
96struct cpufreq_available_frequencies
97*cpufreq_get_available_frequencies(unsigned int cpu)
98{
99 return sysfs_get_available_frequencies(cpu);
100}
101
102void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies
103 *any) {
104 struct cpufreq_available_frequencies *tmp, *next;
105
106 if (!any)
107 return;
108
109 tmp = any->first;
110 while (tmp) {
111 next = tmp->next;
112 free(tmp);
113 tmp = next;
114 }
115}
116
117
118struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned int cpu)
119{
120 return sysfs_get_freq_affected_cpus(cpu);
121}
122
123void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any)
124{
125 struct cpufreq_affected_cpus *tmp, *next;
126
127 if (!any)
128 return;
129
130 tmp = any->first;
131 while (tmp) {
132 next = tmp->next;
133 free(tmp);
134 tmp = next;
135 }
136}
137
138
139struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned int cpu)
140{
141 return sysfs_get_freq_related_cpus(cpu);
142}
143
144void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any)
145{
146 cpufreq_put_affected_cpus(any);
147}
148
149
150int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy)
151{
152 if (!policy || !(policy->governor))
153 return -EINVAL;
154
155 return sysfs_set_freq_policy(cpu, policy);
156}
157
158
159int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq)
160{
161 return sysfs_modify_freq_policy_min(cpu, min_freq);
162}
163
164
165int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq)
166{
167 return sysfs_modify_freq_policy_max(cpu, max_freq);
168}
169
170
171int cpufreq_modify_policy_governor(unsigned int cpu, char *governor)
172{
173 if ((!governor) || (strlen(governor) > 19))
174 return -EINVAL;
175
176 return sysfs_modify_freq_policy_governor(cpu, governor);
177}
178
179int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency)
180{
181 return sysfs_set_frequency(cpu, target_frequency);
182}
183
184struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
185 unsigned long long *total_time)
186{
187 return sysfs_get_freq_stats(cpu, total_time);
188}
189
190void cpufreq_put_stats(struct cpufreq_stats *any)
191{
192 struct cpufreq_stats *tmp, *next;
193
194 if (!any)
195 return;
196
197 tmp = any->first;
198 while (tmp) {
199 next = tmp->next;
200 free(tmp);
201 tmp = next;
202 }
203}
204
205unsigned long cpufreq_get_transitions(unsigned int cpu)
206{
207 return sysfs_get_freq_transitions(cpu);
208}
diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h
new file mode 100644
index 00000000000..3aae8e7a083
--- /dev/null
+++ b/tools/power/cpupower/lib/cpufreq.h
@@ -0,0 +1,223 @@
1/*
2 * cpufreq.h - definitions for libcpufreq
3 *
4 * Copyright (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef _CPUFREQ_H
21#define _CPUFREQ_H 1
22
23struct cpufreq_policy {
24 unsigned long min;
25 unsigned long max;
26 char *governor;
27};
28
29struct cpufreq_available_governors {
30 char *governor;
31 struct cpufreq_available_governors *next;
32 struct cpufreq_available_governors *first;
33};
34
35struct cpufreq_available_frequencies {
36 unsigned long frequency;
37 struct cpufreq_available_frequencies *next;
38 struct cpufreq_available_frequencies *first;
39};
40
41
42struct cpufreq_affected_cpus {
43 unsigned int cpu;
44 struct cpufreq_affected_cpus *next;
45 struct cpufreq_affected_cpus *first;
46};
47
48struct cpufreq_stats {
49 unsigned long frequency;
50 unsigned long long time_in_state;
51 struct cpufreq_stats *next;
52 struct cpufreq_stats *first;
53};
54
55
56
57#ifdef __cplusplus
58extern "C" {
59#endif
60
61/*
62 * returns 0 if the specified CPU is present (it doesn't say
63 * whether it is online!), and an error value if not.
64 */
65
66extern int cpufreq_cpu_exists(unsigned int cpu);
67
68/* determine current CPU frequency
69 * - _kernel variant means kernel's opinion of CPU frequency
70 * - _hardware variant means actual hardware CPU frequency,
71 * which is only available to root.
72 *
73 * returns 0 on failure, else frequency in kHz.
74 */
75
76extern unsigned long cpufreq_get_freq_kernel(unsigned int cpu);
77
78extern unsigned long cpufreq_get_freq_hardware(unsigned int cpu);
79
80#define cpufreq_get(cpu) cpufreq_get_freq_kernel(cpu);
81
82
83/* determine CPU transition latency
84 *
85 * returns 0 on failure, else transition latency in 10^(-9) s = nanoseconds
86 */
87extern unsigned long cpufreq_get_transition_latency(unsigned int cpu);
88
89
90/* determine hardware CPU frequency limits
91 *
92 * These may be limited further by thermal, energy or other
93 * considerations by cpufreq policy notifiers in the kernel.
94 */
95
96extern int cpufreq_get_hardware_limits(unsigned int cpu,
97 unsigned long *min,
98 unsigned long *max);
99
100
101/* determine CPUfreq driver used
102 *
103 * Remember to call cpufreq_put_driver when no longer needed
104 * to avoid memory leakage, please.
105 */
106
107extern char *cpufreq_get_driver(unsigned int cpu);
108
109extern void cpufreq_put_driver(char *ptr);
110
111
112/* determine CPUfreq policy currently used
113 *
114 * Remember to call cpufreq_put_policy when no longer needed
115 * to avoid memory leakage, please.
116 */
117
118
119extern struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu);
120
121extern void cpufreq_put_policy(struct cpufreq_policy *policy);
122
123
124/* determine CPUfreq governors currently available
125 *
126 * may be modified by modprobe'ing or rmmod'ing other governors. Please
127 * free allocated memory by calling cpufreq_put_available_governors
128 * after use.
129 */
130
131
132extern struct cpufreq_available_governors
133*cpufreq_get_available_governors(unsigned int cpu);
134
135extern void cpufreq_put_available_governors(
136 struct cpufreq_available_governors *first);
137
138
139/* determine CPU frequency states available
140 *
141 * Only present on _some_ ->target() cpufreq drivers. For information purposes
142 * only. Please free allocated memory by calling
143 * cpufreq_put_available_frequencies after use.
144 */
145
146extern struct cpufreq_available_frequencies
147*cpufreq_get_available_frequencies(unsigned int cpu);
148
149extern void cpufreq_put_available_frequencies(
150 struct cpufreq_available_frequencies *first);
151
152
153/* determine affected CPUs
154 *
155 * Remember to call cpufreq_put_affected_cpus when no longer needed
156 * to avoid memory leakage, please.
157 */
158
159extern struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned
160 int cpu);
161
162extern void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first);
163
164
165/* determine related CPUs
166 *
167 * Remember to call cpufreq_put_related_cpus when no longer needed
168 * to avoid memory leakage, please.
169 */
170
171extern struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned
172 int cpu);
173
174extern void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first);
175
176
177/* determine stats for cpufreq subsystem
178 *
179 * This is not available in all kernel versions or configurations.
180 */
181
182extern struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu,
183 unsigned long long *total_time);
184
185extern void cpufreq_put_stats(struct cpufreq_stats *stats);
186
187extern unsigned long cpufreq_get_transitions(unsigned int cpu);
188
189
190/* set new cpufreq policy
191 *
192 * Tries to set the passed policy as new policy as close as possible,
193 * but results may differ depending e.g. on governors being available.
194 */
195
196extern int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy);
197
198
199/* modify a policy by only changing min/max freq or governor
200 *
201 * Does not check whether result is what was intended.
202 */
203
204extern int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq);
205extern int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq);
206extern int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
207
208
209/* set a specific frequency
210 *
211 * Does only work if userspace governor can be used and no external
212 * interference (other calls to this function or to set/modify_policy)
213 * occurs. Also does not work on ->range() cpufreq drivers.
214 */
215
216extern int cpufreq_set_frequency(unsigned int cpu,
217 unsigned long target_frequency);
218
219#ifdef __cplusplus
220}
221#endif
222
223#endif /* _CPUFREQ_H */
diff --git a/tools/power/cpupower/lib/sysfs.c b/tools/power/cpupower/lib/sysfs.c
new file mode 100644
index 00000000000..870713a75a8
--- /dev/null
+++ b/tools/power/cpupower/lib/sysfs.c
@@ -0,0 +1,672 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7#include <stdio.h>
8#include <errno.h>
9#include <stdlib.h>
10#include <string.h>
11#include <limits.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16
17#include "cpufreq.h"
18
19#define PATH_TO_CPU "/sys/devices/system/cpu/"
20#define MAX_LINE_LEN 4096
21#define SYSFS_PATH_MAX 255
22
23
24static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
25{
26 int fd;
27 ssize_t numread;
28
29 fd = open(path, O_RDONLY);
30 if (fd == -1)
31 return 0;
32
33 numread = read(fd, buf, buflen - 1);
34 if (numread < 1) {
35 close(fd);
36 return 0;
37 }
38
39 buf[numread] = '\0';
40 close(fd);
41
42 return (unsigned int) numread;
43}
44
45
46/* CPUFREQ sysfs access **************************************************/
47
48/* helper function to read file from /sys into given buffer */
49/* fname is a relative path under "cpuX/cpufreq" dir */
50static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
51 char *buf, size_t buflen)
52{
53 char path[SYSFS_PATH_MAX];
54
55 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
56 cpu, fname);
57 return sysfs_read_file(path, buf, buflen);
58}
59
60/* helper function to write a new value to a /sys file */
61/* fname is a relative path under "cpuX/cpufreq" dir */
62static unsigned int sysfs_cpufreq_write_file(unsigned int cpu,
63 const char *fname,
64 const char *value, size_t len)
65{
66 char path[SYSFS_PATH_MAX];
67 int fd;
68 ssize_t numwrite;
69
70 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
71 cpu, fname);
72
73 fd = open(path, O_WRONLY);
74 if (fd == -1)
75 return 0;
76
77 numwrite = write(fd, value, len);
78 if (numwrite < 1) {
79 close(fd);
80 return 0;
81 }
82
83 close(fd);
84
85 return (unsigned int) numwrite;
86}
87
88/* read access to files which contain one numeric value */
89
90enum cpufreq_value {
91 CPUINFO_CUR_FREQ,
92 CPUINFO_MIN_FREQ,
93 CPUINFO_MAX_FREQ,
94 CPUINFO_LATENCY,
95 SCALING_CUR_FREQ,
96 SCALING_MIN_FREQ,
97 SCALING_MAX_FREQ,
98 STATS_NUM_TRANSITIONS,
99 MAX_CPUFREQ_VALUE_READ_FILES
100};
101
102static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
103 [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
104 [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
105 [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
106 [CPUINFO_LATENCY] = "cpuinfo_transition_latency",
107 [SCALING_CUR_FREQ] = "scaling_cur_freq",
108 [SCALING_MIN_FREQ] = "scaling_min_freq",
109 [SCALING_MAX_FREQ] = "scaling_max_freq",
110 [STATS_NUM_TRANSITIONS] = "stats/total_trans"
111};
112
113
114static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
115 enum cpufreq_value which)
116{
117 unsigned long value;
118 unsigned int len;
119 char linebuf[MAX_LINE_LEN];
120 char *endp;
121
122 if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
123 return 0;
124
125 len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
126 linebuf, sizeof(linebuf));
127
128 if (len == 0)
129 return 0;
130
131 value = strtoul(linebuf, &endp, 0);
132
133 if (endp == linebuf || errno == ERANGE)
134 return 0;
135
136 return value;
137}
138
139/* read access to files which contain one string */
140
141enum cpufreq_string {
142 SCALING_DRIVER,
143 SCALING_GOVERNOR,
144 MAX_CPUFREQ_STRING_FILES
145};
146
147static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
148 [SCALING_DRIVER] = "scaling_driver",
149 [SCALING_GOVERNOR] = "scaling_governor",
150};
151
152
153static char *sysfs_cpufreq_get_one_string(unsigned int cpu,
154 enum cpufreq_string which)
155{
156 char linebuf[MAX_LINE_LEN];
157 char *result;
158 unsigned int len;
159
160 if (which >= MAX_CPUFREQ_STRING_FILES)
161 return NULL;
162
163 len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which],
164 linebuf, sizeof(linebuf));
165 if (len == 0)
166 return NULL;
167
168 result = strdup(linebuf);
169 if (result == NULL)
170 return NULL;
171
172 if (result[strlen(result) - 1] == '\n')
173 result[strlen(result) - 1] = '\0';
174
175 return result;
176}
177
178/* write access */
179
180enum cpufreq_write {
181 WRITE_SCALING_MIN_FREQ,
182 WRITE_SCALING_MAX_FREQ,
183 WRITE_SCALING_GOVERNOR,
184 WRITE_SCALING_SET_SPEED,
185 MAX_CPUFREQ_WRITE_FILES
186};
187
188static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = {
189 [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
190 [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
191 [WRITE_SCALING_GOVERNOR] = "scaling_governor",
192 [WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
193};
194
195static int sysfs_cpufreq_write_one_value(unsigned int cpu,
196 enum cpufreq_write which,
197 const char *new_value, size_t len)
198{
199 if (which >= MAX_CPUFREQ_WRITE_FILES)
200 return 0;
201
202 if (sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which],
203 new_value, len) != len)
204 return -ENODEV;
205
206 return 0;
207};
208
209unsigned long sysfs_get_freq_kernel(unsigned int cpu)
210{
211 return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ);
212}
213
214unsigned long sysfs_get_freq_hardware(unsigned int cpu)
215{
216 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ);
217}
218
219unsigned long sysfs_get_freq_transition_latency(unsigned int cpu)
220{
221 return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
222}
223
224int sysfs_get_freq_hardware_limits(unsigned int cpu,
225 unsigned long *min,
226 unsigned long *max)
227{
228 if ((!min) || (!max))
229 return -EINVAL;
230
231 *min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ);
232 if (!*min)
233 return -ENODEV;
234
235 *max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
236 if (!*max)
237 return -ENODEV;
238
239 return 0;
240}
241
242char *sysfs_get_freq_driver(unsigned int cpu)
243{
244 return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER);
245}
246
247struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu)
248{
249 struct cpufreq_policy *policy;
250
251 policy = malloc(sizeof(struct cpufreq_policy));
252 if (!policy)
253 return NULL;
254
255 policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR);
256 if (!policy->governor) {
257 free(policy);
258 return NULL;
259 }
260 policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
261 policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ);
262 if ((!policy->min) || (!policy->max)) {
263 free(policy->governor);
264 free(policy);
265 return NULL;
266 }
267
268 return policy;
269}
270
271struct cpufreq_available_governors *
272sysfs_get_freq_available_governors(unsigned int cpu) {
273 struct cpufreq_available_governors *first = NULL;
274 struct cpufreq_available_governors *current = NULL;
275 char linebuf[MAX_LINE_LEN];
276 unsigned int pos, i;
277 unsigned int len;
278
279 len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors",
280 linebuf, sizeof(linebuf));
281 if (len == 0)
282 return NULL;
283
284 pos = 0;
285 for (i = 0; i < len; i++) {
286 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
287 if (i - pos < 2)
288 continue;
289 if (current) {
290 current->next = malloc(sizeof(*current));
291 if (!current->next)
292 goto error_out;
293 current = current->next;
294 } else {
295 first = malloc(sizeof(*first));
296 if (!first)
297 goto error_out;
298 current = first;
299 }
300 current->first = first;
301 current->next = NULL;
302
303 current->governor = malloc(i - pos + 1);
304 if (!current->governor)
305 goto error_out;
306
307 memcpy(current->governor, linebuf + pos, i - pos);
308 current->governor[i - pos] = '\0';
309 pos = i + 1;
310 }
311 }
312
313 return first;
314
315 error_out:
316 while (first) {
317 current = first->next;
318 if (first->governor)
319 free(first->governor);
320 free(first);
321 first = current;
322 }
323 return NULL;
324}
325
326
327struct cpufreq_available_frequencies *
328sysfs_get_available_frequencies(unsigned int cpu) {
329 struct cpufreq_available_frequencies *first = NULL;
330 struct cpufreq_available_frequencies *current = NULL;
331 char one_value[SYSFS_PATH_MAX];
332 char linebuf[MAX_LINE_LEN];
333 unsigned int pos, i;
334 unsigned int len;
335
336 len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies",
337 linebuf, sizeof(linebuf));
338 if (len == 0)
339 return NULL;
340
341 pos = 0;
342 for (i = 0; i < len; i++) {
343 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
344 if (i - pos < 2)
345 continue;
346 if (i - pos >= SYSFS_PATH_MAX)
347 goto error_out;
348 if (current) {
349 current->next = malloc(sizeof(*current));
350 if (!current->next)
351 goto error_out;
352 current = current->next;
353 } else {
354 first = malloc(sizeof(*first));
355 if (!first)
356 goto error_out;
357 current = first;
358 }
359 current->first = first;
360 current->next = NULL;
361
362 memcpy(one_value, linebuf + pos, i - pos);
363 one_value[i - pos] = '\0';
364 if (sscanf(one_value, "%lu", &current->frequency) != 1)
365 goto error_out;
366
367 pos = i + 1;
368 }
369 }
370
371 return first;
372
373 error_out:
374 while (first) {
375 current = first->next;
376 free(first);
377 first = current;
378 }
379 return NULL;
380}
381
382static struct cpufreq_affected_cpus *sysfs_get_cpu_list(unsigned int cpu,
383 const char *file)
384{
385 struct cpufreq_affected_cpus *first = NULL;
386 struct cpufreq_affected_cpus *current = NULL;
387 char one_value[SYSFS_PATH_MAX];
388 char linebuf[MAX_LINE_LEN];
389 unsigned int pos, i;
390 unsigned int len;
391
392 len = sysfs_cpufreq_read_file(cpu, file, linebuf, sizeof(linebuf));
393 if (len == 0)
394 return NULL;
395
396 pos = 0;
397 for (i = 0; i < len; i++) {
398 if (i == len || linebuf[i] == ' ' || linebuf[i] == '\n') {
399 if (i - pos < 1)
400 continue;
401 if (i - pos >= SYSFS_PATH_MAX)
402 goto error_out;
403 if (current) {
404 current->next = malloc(sizeof(*current));
405 if (!current->next)
406 goto error_out;
407 current = current->next;
408 } else {
409 first = malloc(sizeof(*first));
410 if (!first)
411 goto error_out;
412 current = first;
413 }
414 current->first = first;
415 current->next = NULL;
416
417 memcpy(one_value, linebuf + pos, i - pos);
418 one_value[i - pos] = '\0';
419
420 if (sscanf(one_value, "%u", &current->cpu) != 1)
421 goto error_out;
422
423 pos = i + 1;
424 }
425 }
426
427 return first;
428
429 error_out:
430 while (first) {
431 current = first->next;
432 free(first);
433 first = current;
434 }
435 return NULL;
436}
437
438struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(unsigned int cpu)
439{
440 return sysfs_get_cpu_list(cpu, "affected_cpus");
441}
442
443struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(unsigned int cpu)
444{
445 return sysfs_get_cpu_list(cpu, "related_cpus");
446}
447
448struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
449 unsigned long long *total_time) {
450 struct cpufreq_stats *first = NULL;
451 struct cpufreq_stats *current = NULL;
452 char one_value[SYSFS_PATH_MAX];
453 char linebuf[MAX_LINE_LEN];
454 unsigned int pos, i;
455 unsigned int len;
456
457 len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state",
458 linebuf, sizeof(linebuf));
459 if (len == 0)
460 return NULL;
461
462 *total_time = 0;
463 pos = 0;
464 for (i = 0; i < len; i++) {
465 if (i == strlen(linebuf) || linebuf[i] == '\n') {
466 if (i - pos < 2)
467 continue;
468 if ((i - pos) >= SYSFS_PATH_MAX)
469 goto error_out;
470 if (current) {
471 current->next = malloc(sizeof(*current));
472 if (!current->next)
473 goto error_out;
474 current = current->next;
475 } else {
476 first = malloc(sizeof(*first));
477 if (!first)
478 goto error_out;
479 current = first;
480 }
481 current->first = first;
482 current->next = NULL;
483
484 memcpy(one_value, linebuf + pos, i - pos);
485 one_value[i - pos] = '\0';
486 if (sscanf(one_value, "%lu %llu",
487 &current->frequency,
488 &current->time_in_state) != 2)
489 goto error_out;
490
491 *total_time = *total_time + current->time_in_state;
492 pos = i + 1;
493 }
494 }
495
496 return first;
497
498 error_out:
499 while (first) {
500 current = first->next;
501 free(first);
502 first = current;
503 }
504 return NULL;
505}
506
507unsigned long sysfs_get_freq_transitions(unsigned int cpu)
508{
509 return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
510}
511
512static int verify_gov(char *new_gov, char *passed_gov)
513{
514 unsigned int i, j = 0;
515
516 if (!passed_gov || (strlen(passed_gov) > 19))
517 return -EINVAL;
518
519 strncpy(new_gov, passed_gov, 20);
520 for (i = 0; i < 20; i++) {
521 if (j) {
522 new_gov[i] = '\0';
523 continue;
524 }
525 if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z'))
526 continue;
527
528 if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z'))
529 continue;
530
531 if (new_gov[i] == '-')
532 continue;
533
534 if (new_gov[i] == '_')
535 continue;
536
537 if (new_gov[i] == '\0') {
538 j = 1;
539 continue;
540 }
541 return -EINVAL;
542 }
543 new_gov[19] = '\0';
544 return 0;
545}
546
547int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor)
548{
549 char new_gov[SYSFS_PATH_MAX];
550
551 if (!governor)
552 return -EINVAL;
553
554 if (verify_gov(new_gov, governor))
555 return -EINVAL;
556
557 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
558 new_gov, strlen(new_gov));
559};
560
561int sysfs_modify_freq_policy_max(unsigned int cpu, unsigned long max_freq)
562{
563 char value[SYSFS_PATH_MAX];
564
565 snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
566
567 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
568 value, strlen(value));
569};
570
571
572int sysfs_modify_freq_policy_min(unsigned int cpu, unsigned long min_freq)
573{
574 char value[SYSFS_PATH_MAX];
575
576 snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
577
578 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ,
579 value, strlen(value));
580};
581
582
583int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy)
584{
585 char min[SYSFS_PATH_MAX];
586 char max[SYSFS_PATH_MAX];
587 char gov[SYSFS_PATH_MAX];
588 int ret;
589 unsigned long old_min;
590 int write_max_first;
591
592 if (!policy || !(policy->governor))
593 return -EINVAL;
594
595 if (policy->max < policy->min)
596 return -EINVAL;
597
598 if (verify_gov(gov, policy->governor))
599 return -EINVAL;
600
601 snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
602 snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
603
604 old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
605 write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
606
607 if (write_max_first) {
608 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
609 max, strlen(max));
610 if (ret)
611 return ret;
612 }
613
614 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min,
615 strlen(min));
616 if (ret)
617 return ret;
618
619 if (!write_max_first) {
620 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
621 max, strlen(max));
622 if (ret)
623 return ret;
624 }
625
626 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
627 gov, strlen(gov));
628}
629
630int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency)
631{
632 struct cpufreq_policy *pol = sysfs_get_freq_policy(cpu);
633 char userspace_gov[] = "userspace";
634 char freq[SYSFS_PATH_MAX];
635 int ret;
636
637 if (!pol)
638 return -ENODEV;
639
640 if (strncmp(pol->governor, userspace_gov, 9) != 0) {
641 ret = sysfs_modify_freq_policy_governor(cpu, userspace_gov);
642 if (ret) {
643 cpufreq_put_policy(pol);
644 return ret;
645 }
646 }
647
648 cpufreq_put_policy(pol);
649
650 snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
651
652 return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED,
653 freq, strlen(freq));
654}
655
656/* CPUFREQ sysfs access **************************************************/
657
658/* General sysfs access **************************************************/
659int sysfs_cpu_exists(unsigned int cpu)
660{
661 char file[SYSFS_PATH_MAX];
662 struct stat statbuf;
663
664 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/", cpu);
665
666 if (stat(file, &statbuf) != 0)
667 return -ENOSYS;
668
669 return S_ISDIR(statbuf.st_mode) ? 0 : -ENOSYS;
670}
671
672/* General sysfs access **************************************************/
diff --git a/tools/power/cpupower/lib/sysfs.h b/tools/power/cpupower/lib/sysfs.h
new file mode 100644
index 00000000000..c76a5e0af50
--- /dev/null
+++ b/tools/power/cpupower/lib/sysfs.h
@@ -0,0 +1,31 @@
1/* General */
2extern unsigned int sysfs_cpu_exists(unsigned int cpu);
3
4/* CPUfreq */
5extern unsigned long sysfs_get_freq_kernel(unsigned int cpu);
6extern unsigned long sysfs_get_freq_hardware(unsigned int cpu);
7extern unsigned long sysfs_get_freq_transition_latency(unsigned int cpu);
8extern int sysfs_get_freq_hardware_limits(unsigned int cpu,
9 unsigned long *min, unsigned long *max);
10extern char *sysfs_get_freq_driver(unsigned int cpu);
11extern struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu);
12extern struct cpufreq_available_governors *sysfs_get_freq_available_governors(
13 unsigned int cpu);
14extern struct cpufreq_available_frequencies *sysfs_get_available_frequencies(
15 unsigned int cpu);
16extern struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(
17 unsigned int cpu);
18extern struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(
19 unsigned int cpu);
20extern struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
21 unsigned long long *total_time);
22extern unsigned long sysfs_get_freq_transitions(unsigned int cpu);
23extern int sysfs_set_freq_policy(unsigned int cpu,
24 struct cpufreq_policy *policy);
25extern int sysfs_modify_freq_policy_min(unsigned int cpu,
26 unsigned long min_freq);
27extern int sysfs_modify_freq_policy_max(unsigned int cpu,
28 unsigned long max_freq);
29extern int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor);
30extern int sysfs_set_frequency(unsigned int cpu,
31 unsigned long target_frequency);
diff --git a/tools/power/cpupower/man/cpupower-frequency-info.1 b/tools/power/cpupower/man/cpupower-frequency-info.1
new file mode 100644
index 00000000000..bb60a8d1e45
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower-frequency-info.1
@@ -0,0 +1,76 @@
1.TH "cpupower-frequency-info" "1" "0.1" "Mattia Dongili" ""
2.SH "NAME"
3.LP
4cpupower frequency\-info \- Utility to retrieve cpufreq kernel information
5.SH "SYNTAX"
6.LP
7cpupower [ \-c cpulist ] frequency\-info [\fIoptions\fP]
8.SH "DESCRIPTION"
9.LP
10A small tool which prints out cpufreq information helpful to developers and interested users.
11.SH "OPTIONS"
12.LP
13.TP
14\fB\-e\fR \fB\-\-debug\fR
15Prints out debug information.
16.TP
17\fB\-f\fR \fB\-\-freq\fR
18Get frequency the CPU currently runs at, according to the cpufreq core.
19.TP
20\fB\-w\fR \fB\-\-hwfreq\fR
21Get frequency the CPU currently runs at, by reading it from hardware (only available to root).
22.TP
23\fB\-l\fR \fB\-\-hwlimits\fR
24Determine the minimum and maximum CPU frequency allowed.
25.TP
26\fB\-d\fR \fB\-\-driver\fR
27Determines the used cpufreq kernel driver.
28.TP
29\fB\-p\fR \fB\-\-policy\fR
30Gets the currently used cpufreq policy.
31.TP
32\fB\-g\fR \fB\-\-governors\fR
33Determines available cpufreq governors.
34.TP
35\fB\-a\fR \fB\-\-related\-cpus\fR
36Determines which CPUs run at the same hardware frequency.
37.TP
38\fB\-a\fR \fB\-\-affected\-cpus\fR
39Determines which CPUs need to have their frequency coordinated by software.
40.TP
41\fB\-s\fR \fB\-\-stats\fR
42Shows cpufreq statistics if available.
43.TP
44\fB\-y\fR \fB\-\-latency\fR
45Determines the maximum latency on CPU frequency changes.
46.TP
47\fB\-o\fR \fB\-\-proc\fR
48Prints out information like provided by the /proc/cpufreq interface in 2.4. and early 2.6. kernels.
49.TP
50\fB\-m\fR \fB\-\-human\fR
51human\-readable output for the \-f, \-w, \-s and \-y parameters.
52.TP
53\fB\-h\fR \fB\-\-help\fR
54Prints out the help screen.
55.SH "REMARKS"
56.LP
57By default only values of core zero are displayed. How to display settings of
58other cores is described in the cpupower(1) manpage in the \-\-cpu option section.
59.LP
60You can't specify more than one of the output specific options \-o \-e \-a \-g \-p \-d \-l \-w \-f \-y.
61.LP
62You also can't specify the \-o option combined with the \-c option.
63.SH "FILES"
64.nf
65\fI/sys/devices/system/cpu/cpu*/cpufreq/\fP
66\fI/proc/cpufreq\fP (deprecated)
67\fI/proc/sys/cpu/\fP (deprecated)
68.fi
69.SH "AUTHORS"
70.nf
71Dominik Brodowski <linux@brodo.de> \- author
72Mattia Dongili<malattia@gmail.com> \- first autolibtoolization
73.fi
74.SH "SEE ALSO"
75.LP
76cpupower\-frequency\-set(1), cpupower(1)
diff --git a/tools/power/cpupower/man/cpupower-frequency-set.1 b/tools/power/cpupower/man/cpupower-frequency-set.1
new file mode 100644
index 00000000000..685f469093a
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower-frequency-set.1
@@ -0,0 +1,54 @@
1.TH "cpupower-freqency-set" "1" "0.1" "Mattia Dongili" ""
2.SH "NAME"
3.LP
4cpupower frequency\-set \- A small tool which allows to modify cpufreq settings.
5.SH "SYNTAX"
6.LP
7cpupower [ \-c cpu ] frequency\-set [\fIoptions\fP]
8.SH "DESCRIPTION"
9.LP
10cpupower frequency\-set allows you to modify cpufreq settings without having to type e.g. "/sys/devices/system/cpu/cpu0/cpufreq/scaling_set_speed" all the time.
11.SH "OPTIONS"
12.LP
13.TP
14\fB\-d\fR \fB\-\-min\fR <FREQ>
15new minimum CPU frequency the governor may select.
16.TP
17\fB\-u\fR \fB\-\-max\fR <FREQ>
18new maximum CPU frequency the governor may select.
19.TP
20\fB\-g\fR \fB\-\-governor\fR <GOV>
21new cpufreq governor.
22.TP
23\fB\-f\fR \fB\-\-freq\fR <FREQ>
24specific frequency to be set. Requires userspace governor to be available and loaded.
25.TP
26\fB\-r\fR \fB\-\-related\fR
27modify all hardware-related CPUs at the same time
28.TP
29\fB\-h\fR \fB\-\-help\fR
30Prints out the help screen.
31.SH "REMARKS"
32.LP
33By default values are applied on all cores. How to modify single core
34configurations is described in the cpupower(1) manpage in the \-\-cpu option section.
35.LP
36The \-f FREQ, \-\-freq FREQ parameter cannot be combined with any other parameter.
37.LP
38FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz by postfixing the value with the wanted unit name, without any space (frequency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).
39.LP
40On Linux kernels up to 2.6.29, the \-r or \-\-related parameter is ignored.
41.SH "FILES"
42.nf
43\fI/sys/devices/system/cpu/cpu*/cpufreq/\fP
44\fI/proc/cpufreq\fP (deprecated)
45\fI/proc/sys/cpu/\fP (deprecated)
46.fi
47.SH "AUTHORS"
48.nf
49Dominik Brodowski <linux@brodo.de> \- author
50Mattia Dongili<malattia@gmail.com> \- first autolibtoolization
51.fi
52.SH "SEE ALSO"
53.LP
54cpupower\-frequency\-info(1), cpupower(1)
diff --git a/tools/power/cpupower/man/cpupower-info.1 b/tools/power/cpupower/man/cpupower-info.1
new file mode 100644
index 00000000000..58e21196f17
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower-info.1
@@ -0,0 +1,19 @@
1.TH CPUPOWER\-INFO "1" "22/02/2011" "" "cpupower Manual"
2.SH NAME
3cpupower\-info \- Shows processor power related kernel or hardware configurations
4.SH SYNOPSIS
5.ft B
6.B cpupower info [ \-b ] [ \-s ] [ \-m ]
7
8.SH DESCRIPTION
9\fBcpupower info \fP shows kernel configurations or processor hardware
10registers affecting processor power saving policies.
11
12Some options are platform wide, some affect single cores. By default values
13of core zero are displayed only. cpupower --cpu all cpuinfo will show the
14settings of all cores, see cpupower(1) how to choose specific cores.
15
16.SH "SEE ALSO"
17Options are described in detail in:
18
19cpupower(1), cpupower-set(1)
diff --git a/tools/power/cpupower/man/cpupower-monitor.1 b/tools/power/cpupower/man/cpupower-monitor.1
new file mode 100644
index 00000000000..d5cfa265c3d
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower-monitor.1
@@ -0,0 +1,179 @@
1.TH CPUPOWER\-MONITOR "1" "22/02/2011" "" "cpupower Manual"
2.SH NAME
3cpupower\-monitor \- Report processor frequency and idle statistics
4.SH SYNOPSIS
5.ft B
6.B cpupower monitor
7.RB "\-l"
8
9.B cpupower monitor
10.RB [ "\-m <mon1>," [ "<mon2>,..." ] ]
11.RB [ "\-i seconds" ]
12.br
13.B cpupower monitor
14.RB [ "\-m <mon1>," [ "<mon2>,..." ] ]
15.RB command
16.br
17.SH DESCRIPTION
18\fBcpupower-monitor \fP reports processor topology, frequency and idle power
19state statistics. Either \fBcommand\fP is forked and
20statistics are printed upon its completion, or statistics are printed periodically.
21
22\fBcpupower-monitor \fP implements independent processor sleep state and
23frequency counters. Some are retrieved from kernel statistics, some are
24directly reading out hardware registers. Use \-l to get an overview which are
25supported on your system.
26
27.SH Options
28.PP
29\-l
30.RS 4
31List available monitors on your system. Additional details about each monitor
32are shown:
33.RS 2
34.IP \(bu
35The name in quotation marks which can be passed to the \-m parameter.
36.IP \(bu
37The number of different counters the monitor supports in brackets.
38.IP \(bu
39The amount of time in seconds the counters might overflow, due to
40implementation constraints.
41.IP \(bu
42The name and a description of each counter and its processor hierarchy level
43coverage in square brackets:
44.RS 4
45.IP \(bu
46[T] \-> Thread
47.IP \(bu
48[C] \-> Core
49.IP \(bu
50[P] \-> Processor Package (Socket)
51.IP \(bu
52[M] \-> Machine/Platform wide counter
53.RE
54.RE
55.RE
56.PP
57\-m <mon1>,<mon2>,...
58.RS 4
59Only display specific monitors. Use the monitor string(s) provided by \-l option.
60.RE
61.PP
62\-i seconds
63.RS 4
64Measure intervall.
65.RE
66.PP
67command
68.RS 4
69Measure idle and frequency characteristics of an arbitrary command/workload.
70The executable \fBcommand\fP is forked and upon its exit, statistics gathered since it was
71forked are displayed.
72.RE
73.PP
74\-v
75.RS 4
76Increase verbosity if the binary was compiled with the DEBUG option set.
77.RE
78
79.SH MONITOR DESCRIPTIONS
80.SS "Idle_Stats"
81Shows statistics of the cpuidle kernel subsystem. Values are retrieved from
82/sys/devices/system/cpu/cpu*/cpuidle/state*/.
83The kernel updates these values every time an idle state is entered or
84left. Therefore there can be some inaccuracy when cores are in an idle
85state for some time when the measure starts or ends. In worst case it can happen
86that one core stayed in an idle state for the whole measure time and the idle
87state usage time as exported by the kernel did not get updated. In this case
88a state residency of 0 percent is shown while it was 100.
89
90.SS "Mperf"
91The name comes from the aperf/mperf (average and maximum) MSR registers used
92which are available on recent X86 processors. It shows the average frequency
93(including boost frequencies).
94The fact that on all recent hardware the mperf timer stops ticking in any idle
95state it is also used to show C0 (processor is active) and Cx (processor is in
96any sleep state) times. These counters do not have the inaccuracy restrictions
97the "Idle_Stats" counters may show.
98May work poorly on Linux-2.6.20 through 2.6.29, as the \fBacpi-cpufreq \fP
99kernel frequency driver periodically cleared aperf/mperf registers in those
100kernels.
101
102.SS "Nehalem" "SandyBridge"
103Intel Core and Package sleep state counters.
104Threads (hyperthreaded cores) may not be able to enter deeper core states if
105its sibling is utilized.
106Deepest package sleep states may in reality show up as machine/platform wide
107sleep states and can only be entered if all cores are idle. Look up Intel
108manuals (some are provided in the References section) for further details.
109
110.SS "Ontario" "Liano"
111AMD laptop and desktop processor (family 12h and 14h) sleep state counters.
112The registers are accessed via PCI and therefore can still be read out while
113cores have been offlined.
114
115There is one special counter: NBP1 (North Bridge P1).
116This one always returns 0 or 1, depending on whether the North Bridge P1
117power state got entered at least once during measure time.
118Being able to enter NBP1 state also depends on graphics power management.
119Therefore this counter can be used to verify whether the graphics' driver
120power management is working as expected.
121
122.SH EXAMPLES
123
124cpupower monitor -l" may show:
125.RS 4
126Monitor "Mperf" (3 states) \- Might overflow after 922000000 s
127
128 ...
129
130Monitor "Idle_Stats" (3 states) \- Might overflow after 4294967295 s
131
132 ...
133
134.RE
135cpupower monitor \-m "Idle_Stats,Mperf" scp /tmp/test /nfs/tmp
136
137Monitor the scp command, show both Mperf and Idle_Stats states counter
138statistics, but in exchanged order.
139
140
141
142.RE
143Be careful that the typical command to fully utilize one CPU by doing:
144
145cpupower monitor cat /dev/zero >/dev/null
146
147Does not work as expected, because the measured output is redirected to
148/dev/null. This could get workarounded by putting the line into an own, tiny
149shell script. Hit CTRL\-c to terminate the command and get the measure output
150displayed.
151
152.SH REFERENCES
153"BIOS and Kernel Developer’s Guide (BKDG) for AMD Family 14h Processors"
154http://support.amd.com/us/Processor_TechDocs/43170.pdf
155
156"Intel® Turbo Boost Technology
157in Intel® Core™ Microarchitecture (Nehalem) Based Processors"
158http://download.intel.com/design/processor/applnots/320354.pdf
159
160"Intel® 64 and IA-32 Architectures Software Developer's Manual
161Volume 3B: System Programming Guide"
162http://www.intel.com/products/processor/manuals
163
164.SH FILES
165.ta
166.nf
167/dev/cpu/*/msr
168/sys/devices/system/cpu/cpu*/cpuidle/state*/.
169.fi
170
171.SH "SEE ALSO"
172powertop(8), msr(4), vmstat(8)
173.PP
174.SH AUTHORS
175.nf
176Written by Thomas Renninger <trenn@suse.de>
177
178Nehalem, SandyBridge monitors and command passing
179based on turbostat.8 from Len Brown <len.brown@intel.com>
diff --git a/tools/power/cpupower/man/cpupower-set.1 b/tools/power/cpupower/man/cpupower-set.1
new file mode 100644
index 00000000000..c4954a9fe4e
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower-set.1
@@ -0,0 +1,103 @@
1.TH CPUPOWER\-SET "1" "22/02/2011" "" "cpupower Manual"
2.SH NAME
3cpupower\-set \- Set processor power related kernel or hardware configurations
4.SH SYNOPSIS
5.ft B
6.B cpupower set [ \-b VAL ] [ \-s VAL ] [ \-m VAL ]
7
8
9.SH DESCRIPTION
10\fBcpupower set \fP sets kernel configurations or directly accesses hardware
11registers affecting processor power saving policies.
12
13Some options are platform wide, some affect single cores. By default values
14are applied on all cores. How to modify single core configurations is
15described in the cpupower(1) manpage in the \-\-cpu option section. Whether an
16option affects the whole system or can be applied to individual cores is
17described in the Options sections.
18
19Use \fBcpupower info \fP to read out current settings and whether they are
20supported on the system at all.
21
22.SH Options
23.PP
24\-\-perf-bias, \-b
25.RS 4
26Sets a register on supported Intel processore which allows software to convey
27its policy for the relative importance of performance versus energy savings to
28the processor.
29
30The range of valid numbers is 0-15, where 0 is maximum
31performance and 15 is maximum energy efficiency.
32
33The processor uses this information in model-specific ways
34when it must select trade-offs between performance and
35energy efficiency.
36
37This policy hint does not supersede Processor Performance states
38(P-states) or CPU Idle power states (C-states), but allows
39software to have influence where it would otherwise be unable
40to express a preference.
41
42For example, this setting may tell the hardware how
43aggressively or conservatively to control frequency
44in the "turbo range" above the explicitly OS-controlled
45P-state frequency range. It may also tell the hardware
46how aggressively it should enter the OS requested C-states.
47
48This option can be applied to individual cores only via the \-\-cpu option,
49cpupower(1).
50
51Setting the performance bias value on one CPU can modify the setting on
52related CPUs as well (for example all CPUs on one socket), because of
53hardware restrictions.
54Use \fBcpupower -c all info -b\fP to verify.
55
56This options needs the msr kernel driver (CONFIG_X86_MSR) loaded.
57.RE
58.PP
59\-\-sched\-mc, \-m [ VAL ]
60.RE
61\-\-sched\-smt, \-s [ VAL ]
62.RS 4
63\-\-sched\-mc utilizes cores in one processor package/socket first before
64processes are scheduled to other processor packages/sockets.
65
66\-\-sched\-smt utilizes thread siblings of one processor core first before
67processes are scheduled to other cores.
68
69The impact on power consumption and performance (positiv or negativ) heavily
70depends on processor support for deep sleep states, frequency scaling and
71frequency boost modes and their dependencies between other thread siblings
72and processor cores.
73
74Taken over from kernel documentation:
75
76Adjust the kernel's multi-core scheduler support.
77
78Possible values are:
79.RS 2
800 - No power saving load balance (default value)
81
821 - Fill one thread/core/package first for long running threads
83
842 - Also bias task wakeups to semi-idle cpu package for power
85savings
86.RE
87
88sched_mc_power_savings is dependent upon SCHED_MC, which is
89itself architecture dependent.
90
91sched_smt_power_savings is dependent upon SCHED_SMT, which
92is itself architecture dependent.
93
94The two files are independent of each other. It is possible
95that one file may be present without the other.
96
97.SH "SEE ALSO"
98cpupower-info(1), cpupower-monitor(1), powertop(1)
99.PP
100.SH AUTHORS
101.nf
102\-\-perf\-bias parts written by Len Brown <len.brown@intel.com>
103Thomas Renninger <trenn@suse.de>
diff --git a/tools/power/cpupower/man/cpupower.1 b/tools/power/cpupower/man/cpupower.1
new file mode 100644
index 00000000000..baf741d06e8
--- /dev/null
+++ b/tools/power/cpupower/man/cpupower.1
@@ -0,0 +1,72 @@
1.TH CPUPOWER "1" "07/03/2011" "" "cpupower Manual"
2.SH NAME
3cpupower \- Shows and sets processor power related values
4.SH SYNOPSIS
5.ft B
6.B cpupower [ \-c cpulist ] <command> [ARGS]
7
8.B cpupower \-v|\-\-version
9
10.B cpupower \-h|\-\-help
11
12.SH DESCRIPTION
13\fBcpupower \fP is a collection of tools to examine and tune power saving
14related features of your processor.
15
16The manpages of the commands (cpupower\-<command>(1)) provide detailed
17descriptions of supported features. Run \fBcpupower help\fP to get an overview
18of supported commands.
19
20.SH Options
21.PP
22\-\-help, \-h
23.RS 4
24Shows supported commands and general usage.
25.RE
26.PP
27\-\-cpu cpulist, \-c cpulist
28.RS 4
29Only show or set values for specific cores.
30This option is not supported by all commands, details can be found in the
31manpages of the commands.
32
33Some commands access all cores (typically the *\-set commands), some only
34the first core (typically the *\-info commands) by default.
35
36The syntax for <cpulist> is based on how the kernel exports CPU bitmasks via
37sysfs files. Some examples:
38.RS 4
39.TP 16
40Input
41Equivalent to
42.TP
43all
44all cores
45.TP
460\-3
470,1,2,3
48.TP
490\-7:2
500,2,4,6
51.TP
521,3,5-7
531,3,5,6,7
54.TP
550\-3:2,8\-15:4
560,2,8,12
57.RE
58.RE
59.PP
60\-\-version, \-v
61.RS 4
62Print the package name and version number.
63
64.SH "SEE ALSO"
65cpupower-set(1), cpupower-info(1), cpupower-idle(1),
66cpupower-frequency-set(1), cpupower-frequency-info(1), cpupower-monitor(1),
67powertop(1)
68.PP
69.SH AUTHORS
70.nf
71\-\-perf\-bias parts written by Len Brown <len.brown@intel.com>
72Thomas Renninger <trenn@suse.de>
diff --git a/tools/power/cpupower/po/cs.po b/tools/power/cpupower/po/cs.po
new file mode 100644
index 00000000000..cb22c45c506
--- /dev/null
+++ b/tools/power/cpupower/po/cs.po
@@ -0,0 +1,944 @@
1# translation of cs.po to Czech
2# Czech translation for cpufrequtils package
3# Czech messages for cpufrequtils.
4# Copyright (C) 2007 kavol
5# This file is distributed under the same license as the cpufrequtils package.
6#
7# Karel Volný <kavol@seznam.cz>, 2007, 2008.
8msgid ""
9msgstr ""
10"Project-Id-Version: cs\n"
11"Report-Msgid-Bugs-To: \n"
12"POT-Creation-Date: 2011-03-08 17:03+0100\n"
13"PO-Revision-Date: 2008-06-11 16:26+0200\n"
14"Last-Translator: Karel Volný <kavol@seznam.cz>\n"
15"Language-Team: Czech <diskuze@lists.l10n.cz>\n"
16"Language: cs\n"
17"MIME-Version: 1.0\n"
18"Content-Type: text/plain; charset=UTF-8\n"
19"Content-Transfer-Encoding: 8bit\n"
20"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
21"X-Generator: KBabel 1.11.4\n"
22
23#: utils/idle_monitor/nhm_idle.c:36
24msgid "Processor Core C3"
25msgstr ""
26
27#: utils/idle_monitor/nhm_idle.c:43
28msgid "Processor Core C6"
29msgstr ""
30
31#: utils/idle_monitor/nhm_idle.c:51
32msgid "Processor Package C3"
33msgstr ""
34
35#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
36msgid "Processor Package C6"
37msgstr ""
38
39#: utils/idle_monitor/snb_idle.c:33
40msgid "Processor Core C7"
41msgstr ""
42
43#: utils/idle_monitor/snb_idle.c:40
44msgid "Processor Package C2"
45msgstr ""
46
47#: utils/idle_monitor/snb_idle.c:47
48msgid "Processor Package C7"
49msgstr ""
50
51#: utils/idle_monitor/amd_fam14h_idle.c:56
52msgid "Package in sleep state (PC1 or deeper)"
53msgstr ""
54
55#: utils/idle_monitor/amd_fam14h_idle.c:63
56msgid "Processor Package C1"
57msgstr ""
58
59#: utils/idle_monitor/amd_fam14h_idle.c:77
60msgid "North Bridge P1 boolean counter (returns 0 or 1)"
61msgstr ""
62
63#: utils/idle_monitor/mperf_monitor.c:35
64msgid "Processor Core not idle"
65msgstr ""
66
67#: utils/idle_monitor/mperf_monitor.c:42
68msgid "Processor Core in an idle state"
69msgstr ""
70
71#: utils/idle_monitor/mperf_monitor.c:50
72msgid "Average Frequency (including boost) in MHz"
73msgstr ""
74
75#: utils/idle_monitor/cpupower-monitor.c:66
76#, c-format
77msgid ""
78"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
79"interval_sec | -c command ...]\n"
80msgstr ""
81
82#: utils/idle_monitor/cpupower-monitor.c:69
83#, c-format
84msgid ""
85"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
86"interval_sec | -c command ...]\n"
87msgstr ""
88
89#: utils/idle_monitor/cpupower-monitor.c:71
90#, c-format
91msgid "\t -v: be more verbose\n"
92msgstr ""
93
94#: utils/idle_monitor/cpupower-monitor.c:73
95#, c-format
96msgid "\t -h: print this help\n"
97msgstr ""
98
99#: utils/idle_monitor/cpupower-monitor.c:74
100#, c-format
101msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
102msgstr ""
103
104#: utils/idle_monitor/cpupower-monitor.c:75
105#, c-format
106msgid "\t -t: show CPU topology/hierarchy\n"
107msgstr ""
108
109#: utils/idle_monitor/cpupower-monitor.c:76
110#, c-format
111msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
112msgstr ""
113
114#: utils/idle_monitor/cpupower-monitor.c:77
115#, c-format
116msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
117msgstr ""
118
119#: utils/idle_monitor/cpupower-monitor.c:79
120#, c-format
121msgid ""
122"only one of: -t, -l, -m are allowed\n"
123"If none of them is passed,"
124msgstr ""
125
126#: utils/idle_monitor/cpupower-monitor.c:80
127#, c-format
128msgid " all supported monitors are shown\n"
129msgstr ""
130
131#: utils/idle_monitor/cpupower-monitor.c:197
132#, c-format
133msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
134msgstr ""
135
136#: utils/idle_monitor/cpupower-monitor.c:207
137#, c-format
138msgid " *is offline\n"
139msgstr ""
140
141#: utils/idle_monitor/cpupower-monitor.c:236
142#, c-format
143msgid "%s: max monitor name length (%d) exceeded\n"
144msgstr ""
145
146#: utils/idle_monitor/cpupower-monitor.c:250
147#, c-format
148msgid "No matching monitor found in %s, try -l option\n"
149msgstr ""
150
151#: utils/idle_monitor/cpupower-monitor.c:266
152#, c-format
153msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
154msgstr ""
155
156#: utils/idle_monitor/cpupower-monitor.c:319
157#, c-format
158msgid "%s took %.5f seconds and exited with status %d\n"
159msgstr ""
160
161#: utils/idle_monitor/cpupower-monitor.c:406
162#, c-format
163msgid "Cannot read number of available processors\n"
164msgstr ""
165
166#: utils/idle_monitor/cpupower-monitor.c:417
167#, c-format
168msgid "Available monitor %s needs root access\n"
169msgstr ""
170
171#: utils/idle_monitor/cpupower-monitor.c:428
172#, c-format
173msgid "No HW Cstate monitors found\n"
174msgstr ""
175
176#: utils/cpupower.c:78
177#, c-format
178msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
179msgstr ""
180
181#: utils/cpupower.c:79
182#, c-format
183msgid "cpupower --version\n"
184msgstr ""
185
186#: utils/cpupower.c:80
187#, c-format
188msgid "Supported subcommands are:\n"
189msgstr ""
190
191#: utils/cpupower.c:83
192#, c-format
193msgid ""
194"\n"
195"Some subcommands can make use of the -c cpulist option.\n"
196msgstr ""
197
198#: utils/cpupower.c:84
199#, c-format
200msgid "Look at the general cpupower manpage how to use it\n"
201msgstr ""
202
203#: utils/cpupower.c:85
204#, c-format
205msgid "and read up the subcommand's manpage whether it is supported.\n"
206msgstr ""
207
208#: utils/cpupower.c:86
209#, c-format
210msgid ""
211"\n"
212"Use cpupower help subcommand for getting help for above subcommands.\n"
213msgstr ""
214
215#: utils/cpupower.c:91
216#, c-format
217msgid "Report errors and bugs to %s, please.\n"
218msgstr ""
219"Chyby v programu prosím hlaste na %s (anglicky).\n"
220"Chyby v pÅ™ekladu prosím hlaste na kavol@seznam.cz (Äesky ;-)\n"
221
222#: utils/cpupower.c:114
223#, c-format
224msgid "Error parsing cpu list\n"
225msgstr ""
226
227#: utils/cpupower.c:172
228#, c-format
229msgid "Subcommand %s needs root privileges\n"
230msgstr ""
231
232#: utils/cpufreq-info.c:31
233#, c-format
234msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
235msgstr "Nelze zjistit poÄet CPU (%s: %s), pÅ™edpokládá se 1.\n"
236
237#: utils/cpufreq-info.c:63
238#, c-format
239msgid ""
240" minimum CPU frequency - maximum CPU frequency - governor\n"
241msgstr ""
242" minimální frekvence CPU - maximální frekvence CPU - regulátor\n"
243
244#: utils/cpufreq-info.c:151
245#, c-format
246msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
247msgstr ""
248
249#. P state changes via MSR are identified via cpuid 80000007
250#. on Intel and AMD, but we assume boost capable machines can do that
251#. if (cpuid_eax(0x80000000) >= 0x80000007
252#. && (cpuid_edx(0x80000007) & (1 << 7)))
253#.
254#: utils/cpufreq-info.c:161
255#, c-format
256msgid " boost state support: \n"
257msgstr ""
258
259#: utils/cpufreq-info.c:163
260#, c-format
261msgid " Supported: %s\n"
262msgstr ""
263
264#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
265msgid "yes"
266msgstr ""
267
268#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
269msgid "no"
270msgstr ""
271
272#: utils/cpufreq-info.c:164
273#, fuzzy, c-format
274msgid " Active: %s\n"
275msgstr " ovladaÄ: %s\n"
276
277#: utils/cpufreq-info.c:177
278#, c-format
279msgid " Boost States: %d\n"
280msgstr ""
281
282#: utils/cpufreq-info.c:178
283#, c-format
284msgid " Total States: %d\n"
285msgstr ""
286
287#: utils/cpufreq-info.c:181
288#, c-format
289msgid " Pstate-Pb%d: %luMHz (boost state)\n"
290msgstr ""
291
292#: utils/cpufreq-info.c:184
293#, c-format
294msgid " Pstate-P%d: %luMHz\n"
295msgstr ""
296
297#: utils/cpufreq-info.c:211
298#, c-format
299msgid " no or unknown cpufreq driver is active on this CPU\n"
300msgstr " pro tento CPU není aktivní žádný známý ovladaÄ cpufreq\n"
301
302#: utils/cpufreq-info.c:213
303#, c-format
304msgid " driver: %s\n"
305msgstr " ovladaÄ: %s\n"
306
307#: utils/cpufreq-info.c:219
308#, fuzzy, c-format
309msgid " CPUs which run at the same hardware frequency: "
310msgstr " CPU, které musí měnit frekvenci zároveň: "
311
312#: utils/cpufreq-info.c:230
313#, fuzzy, c-format
314msgid " CPUs which need to have their frequency coordinated by software: "
315msgstr " CPU, které musí měnit frekvenci zároveň: "
316
317#: utils/cpufreq-info.c:241
318#, c-format
319msgid " maximum transition latency: "
320msgstr ""
321
322#: utils/cpufreq-info.c:247
323#, c-format
324msgid " hardware limits: "
325msgstr " hardwarové meze: "
326
327#: utils/cpufreq-info.c:256
328#, c-format
329msgid " available frequency steps: "
330msgstr " dostupné frekvence: "
331
332#: utils/cpufreq-info.c:269
333#, c-format
334msgid " available cpufreq governors: "
335msgstr " dostupné regulátory: "
336
337#: utils/cpufreq-info.c:280
338#, c-format
339msgid " current policy: frequency should be within "
340msgstr " souÄasná taktika: frekvence by mÄ›la být mezi "
341
342#: utils/cpufreq-info.c:282
343#, c-format
344msgid " and "
345msgstr " a "
346
347#: utils/cpufreq-info.c:286
348#, c-format
349msgid ""
350"The governor \"%s\" may decide which speed to use\n"
351" within this range.\n"
352msgstr ""
353" Regulátor \"%s\" může rozhodnout jakou frekvenci použít\n"
354" v těchto mezích.\n"
355
356#: utils/cpufreq-info.c:293
357#, c-format
358msgid " current CPU frequency is "
359msgstr " souÄasná frekvence CPU je "
360
361#: utils/cpufreq-info.c:296
362#, c-format
363msgid " (asserted by call to hardware)"
364msgstr " (zjištěno hardwarovým voláním)"
365
366#: utils/cpufreq-info.c:304
367#, c-format
368msgid " cpufreq stats: "
369msgstr " statistika cpufreq: "
370
371#: utils/cpufreq-info.c:472
372#, fuzzy, c-format
373msgid "Usage: cpupower freqinfo [options]\n"
374msgstr "Užití: cpufreq-info [pÅ™epínaÄe]\n"
375
376#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
377#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
378#, c-format
379msgid "Options:\n"
380msgstr "PÅ™epínaÄe:\n"
381
382#: utils/cpufreq-info.c:474
383#, fuzzy, c-format
384msgid " -e, --debug Prints out debug information [default]\n"
385msgstr " -e, --debug Vypíše ladicí informace\n"
386
387#: utils/cpufreq-info.c:475
388#, c-format
389msgid ""
390" -f, --freq Get frequency the CPU currently runs at, according\n"
391" to the cpufreq core *\n"
392msgstr ""
393" -f, --freq Zjistí aktuální frekvenci, na které CPU běží\n"
394" podle cpufreq *\n"
395
396#: utils/cpufreq-info.c:477
397#, c-format
398msgid ""
399" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n"
400" it from hardware (only available to root) *\n"
401msgstr ""
402" -w, --hwfreq Zjistí aktuální frekvenci, na které CPU běží\n"
403" z hardware (dostupné jen uživateli root) *\n"
404
405#: utils/cpufreq-info.c:479
406#, c-format
407msgid ""
408" -l, --hwlimits Determine the minimum and maximum CPU frequency "
409"allowed *\n"
410msgstr ""
411" -l, --hwlimits Zjistí minimální a maximální dostupnou frekvenci CPU "
412"*\n"
413
414#: utils/cpufreq-info.c:480
415#, c-format
416msgid " -d, --driver Determines the used cpufreq kernel driver *\n"
417msgstr " -d, --driver Zjistí aktivní ovladaÄ cpufreq *\n"
418
419#: utils/cpufreq-info.c:481
420#, c-format
421msgid " -p, --policy Gets the currently used cpufreq policy *\n"
422msgstr " -p, --policy Zjistí aktuální taktiku cpufreq *\n"
423
424#: utils/cpufreq-info.c:482
425#, c-format
426msgid " -g, --governors Determines available cpufreq governors *\n"
427msgstr " -g, --governors Zjistí dostupné regulátory cpufreq *\n"
428
429#: utils/cpufreq-info.c:483
430#, fuzzy, c-format
431msgid ""
432" -r, --related-cpus Determines which CPUs run at the same hardware "
433"frequency *\n"
434msgstr ""
435" -a, --affected-cpus Zjistí, které CPU musí měnit frekvenci zároveň *\n"
436
437#: utils/cpufreq-info.c:484
438#, fuzzy, c-format
439msgid ""
440" -a, --affected-cpus Determines which CPUs need to have their frequency\n"
441" coordinated by software *\n"
442msgstr ""
443" -a, --affected-cpus Zjistí, které CPU musí měnit frekvenci zároveň *\n"
444
445#: utils/cpufreq-info.c:486
446#, c-format
447msgid " -s, --stats Shows cpufreq statistics if available\n"
448msgstr " -s, --stats Zobrazí statistiku cpufreq, je-li dostupná\n"
449
450#: utils/cpufreq-info.c:487
451#, fuzzy, c-format
452msgid ""
453" -y, --latency Determines the maximum latency on CPU frequency "
454"changes *\n"
455msgstr ""
456" -l, --hwlimits Zjistí minimální a maximální dostupnou frekvenci CPU "
457"*\n"
458
459#: utils/cpufreq-info.c:488
460#, c-format
461msgid " -b, --boost Checks for turbo or boost modes *\n"
462msgstr ""
463
464#: utils/cpufreq-info.c:489
465#, c-format
466msgid ""
467" -o, --proc Prints out information like provided by the /proc/"
468"cpufreq\n"
469" interface in 2.4. and early 2.6. kernels\n"
470msgstr ""
471" -o, --proc Vypíše informace ve formátu, jaký používalo rozhraní\n"
472" /proc/cpufreq v kernelech Å™ady 2.4 a Äasné 2.6\n"
473
474#: utils/cpufreq-info.c:491
475#, fuzzy, c-format
476msgid ""
477" -m, --human human-readable output for the -f, -w, -s and -y "
478"parameters\n"
479msgstr ""
480" -m, --human Výstup parametrů -f, -w a -s v „lidmi Äitelném“ "
481"formátu\n"
482
483#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
484#, c-format
485msgid " -h, --help Prints out this screen\n"
486msgstr " -h, --help Vypíše tuto nápovědu\n"
487
488#: utils/cpufreq-info.c:495
489#, c-format
490msgid ""
491"If no argument or only the -c, --cpu parameter is given, debug output about\n"
492"cpufreq is printed which is useful e.g. for reporting bugs.\n"
493msgstr ""
494"Není-li zadán žádný parametr nebo je-li zadán pouze pÅ™epínaÄ -c, --cpu, "
495"jsou\n"
496"vypsány ladicí informace, což může být užiteÄné například pÅ™i hlášení chyb.\n"
497
498#: utils/cpufreq-info.c:497
499#, c-format
500msgid ""
501"For the arguments marked with *, omitting the -c or --cpu argument is\n"
502"equivalent to setting it to zero\n"
503msgstr ""
504"Není-li pÅ™i použití pÅ™epínaÄů oznaÄených * zadán parametr -c nebo --cpu,\n"
505"předpokládá se jeho hodnota 0.\n"
506
507#: utils/cpufreq-info.c:580
508#, c-format
509msgid ""
510"The argument passed to this tool can't be combined with passing a --cpu "
511"argument\n"
512msgstr "Zadaný parametr nemůže být použit zároveň s pÅ™epínaÄem -c nebo --cpu\n"
513
514#: utils/cpufreq-info.c:596
515#, c-format
516msgid ""
517"You can't specify more than one --cpu parameter and/or\n"
518"more than one output-specific argument\n"
519msgstr ""
520"Nelze zadat více než jeden parametr -c nebo --cpu\n"
521"anebo více než jeden parametr urÄující výstup\n"
522
523#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
524#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
525#, c-format
526msgid "invalid or unknown argument\n"
527msgstr "neplatný nebo neznámý parametr\n"
528
529#: utils/cpufreq-info.c:617
530#, c-format
531msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
532msgstr "nelze analyzovat CPU %d, vypadá to, že není přítomen\n"
533
534#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
535#, c-format
536msgid "analyzing CPU %d:\n"
537msgstr "analyzuji CPU %d:\n"
538
539#: utils/cpufreq-set.c:25
540#, fuzzy, c-format
541msgid "Usage: cpupower frequency-set [options]\n"
542msgstr "Užití: cpufreq-set [pÅ™epínaÄe]\n"
543
544#: utils/cpufreq-set.c:27
545#, c-format
546msgid ""
547" -d FREQ, --min FREQ new minimum CPU frequency the governor may "
548"select\n"
549msgstr ""
550" -d FREQ, --min FREQ Nová nejnižší frekvence, kterou může regulátor "
551"vybrat\n"
552
553#: utils/cpufreq-set.c:28
554#, c-format
555msgid ""
556" -u FREQ, --max FREQ new maximum CPU frequency the governor may "
557"select\n"
558msgstr ""
559" -u FREQ, --max FREQ Nová nejvyšší frekvence, kterou může regulátor "
560"zvolit\n"
561
562#: utils/cpufreq-set.c:29
563#, c-format
564msgid " -g GOV, --governor GOV new cpufreq governor\n"
565msgstr " -g GOV, --governors GOV Nový regulátor cpufreq\n"
566
567#: utils/cpufreq-set.c:30
568#, c-format
569msgid ""
570" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n"
571" governor to be available and loaded\n"
572msgstr ""
573" -f FREQ, --freq FREQ Frekvence, která má být nastavena. Vyžaduje, aby "
574"byl\n"
575" v jádře nahrán regulátor ‚userspace‘.\n"
576
577#: utils/cpufreq-set.c:32
578#, c-format
579msgid " -r, --related Switches all hardware-related CPUs\n"
580msgstr ""
581
582#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
583#, fuzzy, c-format
584msgid " -h, --help Prints out this screen\n"
585msgstr " -h, --help Vypíše tuto nápovědu\n"
586
587#: utils/cpufreq-set.c:35
588#, fuzzy, c-format
589msgid ""
590"Notes:\n"
591"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
592msgstr ""
593"Není-li pÅ™i použití pÅ™epínaÄů oznaÄených * zadán parametr -c nebo --cpu,\n"
594"předpokládá se jeho hodnota 0.\n"
595
596#: utils/cpufreq-set.c:37
597#, fuzzy, c-format
598msgid ""
599"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
600"parameter\n"
601" except the -c CPU, --cpu CPU parameter\n"
602"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
603" by postfixing the value with the wanted unit name, without any space\n"
604" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
605msgstr ""
606"Poznámky:\n"
607"1. Vynechání parametru -c nebo --cpu je ekvivalentní jeho nastavení na 0\n"
608"2. PÅ™epínaÄ -f nebo --freq nemůže být použit zároveň s žádným jiným vyjma -"
609"c\n"
610" nebo --cpu\n"
611"3. Frekvence (FREQ) mohou být zadány v Hz, kHz (výchozí), MHz, GHz nebo THz\n"
612" pÅ™ipojením názvu jednotky bez mezery mezi Äíslem a jednotkou\n"
613" (FREQ v kHz =^ Hz * 0,001 = ^ MHz * 1000 =^ GHz * 1000000)\n"
614
615#: utils/cpufreq-set.c:57
616#, c-format
617msgid ""
618"Error setting new values. Common errors:\n"
619"- Do you have proper administration rights? (super-user?)\n"
620"- Is the governor you requested available and modprobed?\n"
621"- Trying to set an invalid policy?\n"
622"- Trying to set a specific frequency, but userspace governor is not "
623"available,\n"
624" for example because of hardware which cannot be set to a specific "
625"frequency\n"
626" or because the userspace governor isn't loaded?\n"
627msgstr ""
628"Chyba při nastavování nových hodnot. Obvyklé problémy:\n"
629"- Máte patÅ™iÄná administrátorská práva? (root?)\n"
630"- Je požadovaný regulátor dostupný v jádře? (modprobe?)\n"
631"- Snažíte se nastavit neplatnou taktiku?\n"
632"- Snažíte se nastavit urÄitou frekvenci, ale není dostupný\n"
633" regulátor ‚userspace‘, například protože není nahrán v jádře,\n"
634" nebo nelze na tomto hardware nastavit urÄitou frekvenci?\n"
635
636#: utils/cpufreq-set.c:170
637#, c-format
638msgid "wrong, unknown or unhandled CPU?\n"
639msgstr "neznámý nebo nepodporovaný CPU?\n"
640
641#: utils/cpufreq-set.c:302
642#, c-format
643msgid ""
644"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
645"-g/--governor parameters\n"
646msgstr ""
647"pÅ™epínaÄ -f/--freq nemůže být použit zároveň\n"
648"s pÅ™epínaÄem -d/--min, -u/--max nebo -g/--governor\n"
649
650#: utils/cpufreq-set.c:308
651#, c-format
652msgid ""
653"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
654"-g/--governor must be passed\n"
655msgstr ""
656"Musí být zadán alespoň jeden pÅ™epínaÄ\n"
657"-f/--freq, -d/--min, -u/--max nebo -g/--governor\n"
658
659#: utils/cpufreq-set.c:347
660#, c-format
661msgid "Setting cpu: %d\n"
662msgstr ""
663
664#: utils/cpupower-set.c:22
665#, c-format
666msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
667msgstr ""
668
669#: utils/cpupower-set.c:24
670#, c-format
671msgid ""
672" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n"
673" Intel models [0-15], see manpage for details\n"
674msgstr ""
675
676#: utils/cpupower-set.c:26
677#, c-format
678msgid ""
679" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n"
680msgstr ""
681
682#: utils/cpupower-set.c:27
683#, c-format
684msgid ""
685" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler "
686"policy.\n"
687msgstr ""
688
689#: utils/cpupower-set.c:80
690#, c-format
691msgid "--perf-bias param out of range [0-%d]\n"
692msgstr ""
693
694#: utils/cpupower-set.c:91
695#, c-format
696msgid "--sched-mc param out of range [0-%d]\n"
697msgstr ""
698
699#: utils/cpupower-set.c:102
700#, c-format
701msgid "--sched-smt param out of range [0-%d]\n"
702msgstr ""
703
704#: utils/cpupower-set.c:121
705#, c-format
706msgid "Error setting sched-mc %s\n"
707msgstr ""
708
709#: utils/cpupower-set.c:127
710#, c-format
711msgid "Error setting sched-smt %s\n"
712msgstr ""
713
714#: utils/cpupower-set.c:146
715#, c-format
716msgid "Error setting perf-bias value on CPU %d\n"
717msgstr ""
718
719#: utils/cpupower-info.c:21
720#, c-format
721msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
722msgstr ""
723
724#: utils/cpupower-info.c:23
725#, c-format
726msgid ""
727" -b, --perf-bias Gets CPU's power vs performance policy on some\n"
728" Intel models [0-15], see manpage for details\n"
729msgstr ""
730
731#: utils/cpupower-info.c:25
732#, fuzzy, c-format
733msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n"
734msgstr " -p, --policy Zjistí aktuální taktiku cpufreq *\n"
735
736#: utils/cpupower-info.c:26
737#, c-format
738msgid ""
739" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n"
740msgstr ""
741
742#: utils/cpupower-info.c:28
743#, c-format
744msgid ""
745"\n"
746"Passing no option will show all info, by default only on core 0\n"
747msgstr ""
748
749#: utils/cpupower-info.c:102
750#, c-format
751msgid "System's multi core scheduler setting: "
752msgstr ""
753
754#. if sysfs file is missing it's: errno == ENOENT
755#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
756#, c-format
757msgid "not supported\n"
758msgstr ""
759
760#: utils/cpupower-info.c:111
761#, c-format
762msgid "System's thread sibling scheduler setting: "
763msgstr ""
764
765#: utils/cpupower-info.c:126
766#, c-format
767msgid "Intel's performance bias setting needs root privileges\n"
768msgstr ""
769
770#: utils/cpupower-info.c:128
771#, c-format
772msgid "System does not support Intel's performance bias setting\n"
773msgstr ""
774
775#: utils/cpupower-info.c:147
776#, c-format
777msgid "Could not read perf-bias value\n"
778msgstr ""
779
780#: utils/cpupower-info.c:150
781#, c-format
782msgid "perf-bias: %d\n"
783msgstr ""
784
785#: utils/cpuidle-info.c:28
786#, fuzzy, c-format
787msgid "Analyzing CPU %d:\n"
788msgstr "analyzuji CPU %d:\n"
789
790#: utils/cpuidle-info.c:32
791#, c-format
792msgid "CPU %u: No idle states\n"
793msgstr ""
794
795#: utils/cpuidle-info.c:36
796#, c-format
797msgid "CPU %u: Can't read idle state info\n"
798msgstr ""
799
800#: utils/cpuidle-info.c:41
801#, c-format
802msgid "Could not determine max idle state %u\n"
803msgstr ""
804
805#: utils/cpuidle-info.c:46
806#, c-format
807msgid "Number of idle states: %d\n"
808msgstr ""
809
810#: utils/cpuidle-info.c:48
811#, fuzzy, c-format
812msgid "Available idle states:"
813msgstr " dostupné frekvence: "
814
815#: utils/cpuidle-info.c:71
816#, c-format
817msgid "Flags/Description: %s\n"
818msgstr ""
819
820#: utils/cpuidle-info.c:74
821#, c-format
822msgid "Latency: %lu\n"
823msgstr ""
824
825#: utils/cpuidle-info.c:76
826#, c-format
827msgid "Usage: %lu\n"
828msgstr ""
829
830#: utils/cpuidle-info.c:78
831#, c-format
832msgid "Duration: %llu\n"
833msgstr ""
834
835#: utils/cpuidle-info.c:90
836#, c-format
837msgid "Could not determine cpuidle driver\n"
838msgstr ""
839
840#: utils/cpuidle-info.c:94
841#, fuzzy, c-format
842msgid "CPUidle driver: %s\n"
843msgstr " ovladaÄ: %s\n"
844
845#: utils/cpuidle-info.c:99
846#, c-format
847msgid "Could not determine cpuidle governor\n"
848msgstr ""
849
850#: utils/cpuidle-info.c:103
851#, c-format
852msgid "CPUidle governor: %s\n"
853msgstr ""
854
855#: utils/cpuidle-info.c:122
856#, c-format
857msgid "CPU %u: Can't read C-state info\n"
858msgstr ""
859
860#. printf("Cstates: %d\n", cstates);
861#: utils/cpuidle-info.c:127
862#, c-format
863msgid "active state: C0\n"
864msgstr ""
865
866#: utils/cpuidle-info.c:128
867#, c-format
868msgid "max_cstate: C%u\n"
869msgstr ""
870
871#: utils/cpuidle-info.c:129
872#, c-format
873msgid "maximum allowed latency: %lu usec\n"
874msgstr ""
875
876#: utils/cpuidle-info.c:130
877#, c-format
878msgid "states:\t\n"
879msgstr ""
880
881#: utils/cpuidle-info.c:132
882#, c-format
883msgid " C%d: type[C%d] "
884msgstr ""
885
886#: utils/cpuidle-info.c:134
887#, c-format
888msgid "promotion[--] demotion[--] "
889msgstr ""
890
891#: utils/cpuidle-info.c:135
892#, c-format
893msgid "latency[%03lu] "
894msgstr ""
895
896#: utils/cpuidle-info.c:137
897#, c-format
898msgid "usage[%08lu] "
899msgstr ""
900
901#: utils/cpuidle-info.c:139
902#, c-format
903msgid "duration[%020Lu] \n"
904msgstr ""
905
906#: utils/cpuidle-info.c:147
907#, fuzzy, c-format
908msgid "Usage: cpupower idleinfo [options]\n"
909msgstr "Užití: cpufreq-info [pÅ™epínaÄe]\n"
910
911#: utils/cpuidle-info.c:149
912#, fuzzy, c-format
913msgid " -s, --silent Only show general C-state information\n"
914msgstr " -e, --debug Vypíše ladicí informace\n"
915
916#: utils/cpuidle-info.c:150
917#, fuzzy, c-format
918msgid ""
919" -o, --proc Prints out information like provided by the /proc/"
920"acpi/processor/*/power\n"
921" interface in older kernels\n"
922msgstr ""
923" -o, --proc Vypíše informace ve formátu, jaký používalo rozhraní\n"
924" /proc/cpufreq v kernelech Å™ady 2.4 a Äasné 2.6\n"
925
926#: utils/cpuidle-info.c:209
927#, fuzzy, c-format
928msgid "You can't specify more than one output-specific argument\n"
929msgstr ""
930"Nelze zadat více než jeden parametr -c nebo --cpu\n"
931"anebo více než jeden parametr urÄující výstup\n"
932
933#~ msgid ""
934#~ " -c CPU, --cpu CPU CPU number which information shall be determined "
935#~ "about\n"
936#~ msgstr ""
937#~ " -c CPU, --cpu CPU Číslo CPU, o kterém se mají zjistit informace\n"
938
939#~ msgid ""
940#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be "
941#~ "modified\n"
942#~ msgstr ""
943#~ " -c CPU, --cpu CPU Číslo CPU pro který se má provést nastavení "
944#~ "cpufreq\n"
diff --git a/tools/power/cpupower/po/de.po b/tools/power/cpupower/po/de.po
new file mode 100644
index 00000000000..78c09e51663
--- /dev/null
+++ b/tools/power/cpupower/po/de.po
@@ -0,0 +1,961 @@
1# German translations for cpufrequtils package
2# German messages for cpufrequtils.
3# Copyright (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.net>
4# This file is distributed under the same license as the cpufrequtils package.
5#
6msgid ""
7msgstr ""
8"Project-Id-Version: cpufrequtils 006\n"
9"Report-Msgid-Bugs-To: \n"
10"POT-Creation-Date: 2011-03-08 17:03+0100\n"
11"PO-Revision-Date: 2009-08-08 17:18+0100\n"
12"Last-Translator: <linux@dominikbrodowski.net>\n"
13"Language-Team: NONE\n"
14"Language: \n"
15"MIME-Version: 1.0\n"
16"Content-Type: text/plain; charset=ISO-8859-1\n"
17"Content-Transfer-Encoding: 8bit\n"
18"Plural-Forms: nplurals=2; plural=(n != 1);\n"
19
20#: utils/idle_monitor/nhm_idle.c:36
21msgid "Processor Core C3"
22msgstr ""
23
24#: utils/idle_monitor/nhm_idle.c:43
25msgid "Processor Core C6"
26msgstr ""
27
28#: utils/idle_monitor/nhm_idle.c:51
29msgid "Processor Package C3"
30msgstr ""
31
32#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
33msgid "Processor Package C6"
34msgstr ""
35
36#: utils/idle_monitor/snb_idle.c:33
37msgid "Processor Core C7"
38msgstr ""
39
40#: utils/idle_monitor/snb_idle.c:40
41msgid "Processor Package C2"
42msgstr ""
43
44#: utils/idle_monitor/snb_idle.c:47
45msgid "Processor Package C7"
46msgstr ""
47
48#: utils/idle_monitor/amd_fam14h_idle.c:56
49msgid "Package in sleep state (PC1 or deeper)"
50msgstr ""
51
52#: utils/idle_monitor/amd_fam14h_idle.c:63
53msgid "Processor Package C1"
54msgstr ""
55
56#: utils/idle_monitor/amd_fam14h_idle.c:77
57msgid "North Bridge P1 boolean counter (returns 0 or 1)"
58msgstr ""
59
60#: utils/idle_monitor/mperf_monitor.c:35
61msgid "Processor Core not idle"
62msgstr ""
63
64#: utils/idle_monitor/mperf_monitor.c:42
65msgid "Processor Core in an idle state"
66msgstr ""
67
68#: utils/idle_monitor/mperf_monitor.c:50
69msgid "Average Frequency (including boost) in MHz"
70msgstr ""
71
72#: utils/idle_monitor/cpupower-monitor.c:66
73#, c-format
74msgid ""
75"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
76"interval_sec | -c command ...]\n"
77msgstr ""
78
79#: utils/idle_monitor/cpupower-monitor.c:69
80#, c-format
81msgid ""
82"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
83"interval_sec | -c command ...]\n"
84msgstr ""
85
86#: utils/idle_monitor/cpupower-monitor.c:71
87#, c-format
88msgid "\t -v: be more verbose\n"
89msgstr ""
90
91#: utils/idle_monitor/cpupower-monitor.c:73
92#, c-format
93msgid "\t -h: print this help\n"
94msgstr ""
95
96#: utils/idle_monitor/cpupower-monitor.c:74
97#, c-format
98msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
99msgstr ""
100
101#: utils/idle_monitor/cpupower-monitor.c:75
102#, c-format
103msgid "\t -t: show CPU topology/hierarchy\n"
104msgstr ""
105
106#: utils/idle_monitor/cpupower-monitor.c:76
107#, c-format
108msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
109msgstr ""
110
111#: utils/idle_monitor/cpupower-monitor.c:77
112#, c-format
113msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
114msgstr ""
115
116#: utils/idle_monitor/cpupower-monitor.c:79
117#, c-format
118msgid ""
119"only one of: -t, -l, -m are allowed\n"
120"If none of them is passed,"
121msgstr ""
122
123#: utils/idle_monitor/cpupower-monitor.c:80
124#, c-format
125msgid " all supported monitors are shown\n"
126msgstr ""
127
128#: utils/idle_monitor/cpupower-monitor.c:197
129#, c-format
130msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
131msgstr ""
132
133#: utils/idle_monitor/cpupower-monitor.c:207
134#, c-format
135msgid " *is offline\n"
136msgstr ""
137
138#: utils/idle_monitor/cpupower-monitor.c:236
139#, c-format
140msgid "%s: max monitor name length (%d) exceeded\n"
141msgstr ""
142
143#: utils/idle_monitor/cpupower-monitor.c:250
144#, c-format
145msgid "No matching monitor found in %s, try -l option\n"
146msgstr ""
147
148#: utils/idle_monitor/cpupower-monitor.c:266
149#, c-format
150msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
151msgstr ""
152
153#: utils/idle_monitor/cpupower-monitor.c:319
154#, c-format
155msgid "%s took %.5f seconds and exited with status %d\n"
156msgstr ""
157
158#: utils/idle_monitor/cpupower-monitor.c:406
159#, c-format
160msgid "Cannot read number of available processors\n"
161msgstr ""
162
163#: utils/idle_monitor/cpupower-monitor.c:417
164#, c-format
165msgid "Available monitor %s needs root access\n"
166msgstr ""
167
168#: utils/idle_monitor/cpupower-monitor.c:428
169#, c-format
170msgid "No HW Cstate monitors found\n"
171msgstr ""
172
173#: utils/cpupower.c:78
174#, c-format
175msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
176msgstr ""
177
178#: utils/cpupower.c:79
179#, c-format
180msgid "cpupower --version\n"
181msgstr ""
182
183#: utils/cpupower.c:80
184#, c-format
185msgid "Supported subcommands are:\n"
186msgstr ""
187
188#: utils/cpupower.c:83
189#, c-format
190msgid ""
191"\n"
192"Some subcommands can make use of the -c cpulist option.\n"
193msgstr ""
194
195#: utils/cpupower.c:84
196#, c-format
197msgid "Look at the general cpupower manpage how to use it\n"
198msgstr ""
199
200#: utils/cpupower.c:85
201#, c-format
202msgid "and read up the subcommand's manpage whether it is supported.\n"
203msgstr ""
204
205#: utils/cpupower.c:86
206#, c-format
207msgid ""
208"\n"
209"Use cpupower help subcommand for getting help for above subcommands.\n"
210msgstr ""
211
212#: utils/cpupower.c:91
213#, c-format
214msgid "Report errors and bugs to %s, please.\n"
215msgstr "Bitte melden Sie Fehler an %s.\n"
216
217#: utils/cpupower.c:114
218#, c-format
219msgid "Error parsing cpu list\n"
220msgstr ""
221
222#: utils/cpupower.c:172
223#, c-format
224msgid "Subcommand %s needs root privileges\n"
225msgstr ""
226
227#: utils/cpufreq-info.c:31
228#, c-format
229msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
230msgstr ""
231"Konnte nicht die Anzahl der CPUs herausfinden (%s : %s), nehme daher 1 an.\n"
232
233#: utils/cpufreq-info.c:63
234#, c-format
235msgid ""
236" minimum CPU frequency - maximum CPU frequency - governor\n"
237msgstr ""
238" minimale CPU-Taktfreq. - maximale CPU-Taktfreq. - Regler \n"
239
240#: utils/cpufreq-info.c:151
241#, c-format
242msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
243msgstr ""
244
245#. P state changes via MSR are identified via cpuid 80000007
246#. on Intel and AMD, but we assume boost capable machines can do that
247#. if (cpuid_eax(0x80000000) >= 0x80000007
248#. && (cpuid_edx(0x80000007) & (1 << 7)))
249#.
250#: utils/cpufreq-info.c:161
251#, c-format
252msgid " boost state support: \n"
253msgstr ""
254
255#: utils/cpufreq-info.c:163
256#, c-format
257msgid " Supported: %s\n"
258msgstr ""
259
260#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
261msgid "yes"
262msgstr ""
263
264#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
265msgid "no"
266msgstr ""
267
268#: utils/cpufreq-info.c:164
269#, fuzzy, c-format
270msgid " Active: %s\n"
271msgstr " Treiber: %s\n"
272
273#: utils/cpufreq-info.c:177
274#, c-format
275msgid " Boost States: %d\n"
276msgstr ""
277
278#: utils/cpufreq-info.c:178
279#, c-format
280msgid " Total States: %d\n"
281msgstr ""
282
283#: utils/cpufreq-info.c:181
284#, c-format
285msgid " Pstate-Pb%d: %luMHz (boost state)\n"
286msgstr ""
287
288#: utils/cpufreq-info.c:184
289#, c-format
290msgid " Pstate-P%d: %luMHz\n"
291msgstr ""
292
293#: utils/cpufreq-info.c:211
294#, c-format
295msgid " no or unknown cpufreq driver is active on this CPU\n"
296msgstr " kein oder nicht bestimmbarer cpufreq-Treiber aktiv\n"
297
298#: utils/cpufreq-info.c:213
299#, c-format
300msgid " driver: %s\n"
301msgstr " Treiber: %s\n"
302
303#: utils/cpufreq-info.c:219
304#, c-format
305msgid " CPUs which run at the same hardware frequency: "
306msgstr " Folgende CPUs laufen mit der gleichen Hardware-Taktfrequenz: "
307
308#: utils/cpufreq-info.c:230
309#, c-format
310msgid " CPUs which need to have their frequency coordinated by software: "
311msgstr " Die Taktfrequenz folgender CPUs werden per Software koordiniert: "
312
313#: utils/cpufreq-info.c:241
314#, c-format
315msgid " maximum transition latency: "
316msgstr " Maximale Dauer eines Taktfrequenzwechsels: "
317
318#: utils/cpufreq-info.c:247
319#, c-format
320msgid " hardware limits: "
321msgstr " Hardwarebedingte Grenzen der Taktfrequenz: "
322
323#: utils/cpufreq-info.c:256
324#, c-format
325msgid " available frequency steps: "
326msgstr " mögliche Taktfrequenzen: "
327
328#: utils/cpufreq-info.c:269
329#, c-format
330msgid " available cpufreq governors: "
331msgstr " mögliche Regler: "
332
333#: utils/cpufreq-info.c:280
334#, c-format
335msgid " current policy: frequency should be within "
336msgstr " momentane Taktik: die Frequenz soll innerhalb "
337
338#: utils/cpufreq-info.c:282
339#, c-format
340msgid " and "
341msgstr " und "
342
343#: utils/cpufreq-info.c:286
344#, c-format
345msgid ""
346"The governor \"%s\" may decide which speed to use\n"
347" within this range.\n"
348msgstr ""
349" liegen. Der Regler \"%s\" kann frei entscheiden,\n"
350" welche Taktfrequenz innerhalb dieser Grenze verwendet "
351"wird.\n"
352
353#: utils/cpufreq-info.c:293
354#, c-format
355msgid " current CPU frequency is "
356msgstr " momentane Taktfrequenz ist "
357
358#: utils/cpufreq-info.c:296
359#, c-format
360msgid " (asserted by call to hardware)"
361msgstr " (verifiziert durch Nachfrage bei der Hardware)"
362
363#: utils/cpufreq-info.c:304
364#, c-format
365msgid " cpufreq stats: "
366msgstr " Statistik:"
367
368#: utils/cpufreq-info.c:472
369#, fuzzy, c-format
370msgid "Usage: cpupower freqinfo [options]\n"
371msgstr "Aufruf: cpufreq-info [Optionen]\n"
372
373#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
374#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
375#, c-format
376msgid "Options:\n"
377msgstr "Optionen:\n"
378
379#: utils/cpufreq-info.c:474
380#, fuzzy, c-format
381msgid " -e, --debug Prints out debug information [default]\n"
382msgstr ""
383" -e, --debug Erzeugt detaillierte Informationen, hilfreich\n"
384" zum Aufspüren von Fehlern\n"
385
386#: utils/cpufreq-info.c:475
387#, c-format
388msgid ""
389" -f, --freq Get frequency the CPU currently runs at, according\n"
390" to the cpufreq core *\n"
391msgstr ""
392" -f, --freq Findet die momentane CPU-Taktfrquenz heraus (nach\n"
393" Meinung des Betriebssystems) *\n"
394
395#: utils/cpufreq-info.c:477
396#, c-format
397msgid ""
398" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n"
399" it from hardware (only available to root) *\n"
400msgstr ""
401" -w, --hwfreq Findet die momentane CPU-Taktfrequenz heraus\n"
402" (verifiziert durch Nachfrage bei der Hardware)\n"
403" [nur der Administrator kann dies tun] *\n"
404
405#: utils/cpufreq-info.c:479
406#, c-format
407msgid ""
408" -l, --hwlimits Determine the minimum and maximum CPU frequency "
409"allowed *\n"
410msgstr ""
411" -l, --hwlimits Findet die minimale und maximale Taktfrequenz heraus "
412"*\n"
413
414#: utils/cpufreq-info.c:480
415#, c-format
416msgid " -d, --driver Determines the used cpufreq kernel driver *\n"
417msgstr " -d, --driver Findet den momentanen Treiber heraus *\n"
418
419#: utils/cpufreq-info.c:481
420#, c-format
421msgid " -p, --policy Gets the currently used cpufreq policy *\n"
422msgstr " -p, --policy Findet die momentane Taktik heraus *\n"
423
424#: utils/cpufreq-info.c:482
425#, c-format
426msgid " -g, --governors Determines available cpufreq governors *\n"
427msgstr " -g, --governors Erzeugt eine Liste mit verfügbaren Reglern *\n"
428
429#: utils/cpufreq-info.c:483
430#, c-format
431msgid ""
432" -r, --related-cpus Determines which CPUs run at the same hardware "
433"frequency *\n"
434msgstr ""
435" -r, --related-cpus Findet heraus, welche CPUs mit derselben "
436"physikalischen\n"
437" Taktfrequenz laufen *\n"
438
439#: utils/cpufreq-info.c:484
440#, c-format
441msgid ""
442" -a, --affected-cpus Determines which CPUs need to have their frequency\n"
443" coordinated by software *\n"
444msgstr ""
445" -a, --affected-cpus Findet heraus, von welchen CPUs die Taktfrequenz "
446"durch\n"
447" Software koordiniert werden muss *\n"
448
449#: utils/cpufreq-info.c:486
450#, c-format
451msgid " -s, --stats Shows cpufreq statistics if available\n"
452msgstr ""
453" -s, --stats Zeigt, sofern möglich, Statistiken über cpufreq an.\n"
454
455#: utils/cpufreq-info.c:487
456#, c-format
457msgid ""
458" -y, --latency Determines the maximum latency on CPU frequency "
459"changes *\n"
460msgstr ""
461" -y, --latency Findet die maximale Dauer eines Taktfrequenzwechsels "
462"heraus *\n"
463
464#: utils/cpufreq-info.c:488
465#, c-format
466msgid " -b, --boost Checks for turbo or boost modes *\n"
467msgstr ""
468
469#: utils/cpufreq-info.c:489
470#, c-format
471msgid ""
472" -o, --proc Prints out information like provided by the /proc/"
473"cpufreq\n"
474" interface in 2.4. and early 2.6. kernels\n"
475msgstr ""
476" -o, --proc Erzeugt Informationen in einem ähnlichem Format zu "
477"dem\n"
478" der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n"
479" Kernel-Versionen\n"
480
481#: utils/cpufreq-info.c:491
482#, c-format
483msgid ""
484" -m, --human human-readable output for the -f, -w, -s and -y "
485"parameters\n"
486msgstr ""
487" -m, --human Formatiert Taktfrequenz- und Zeitdauerangaben in "
488"besser\n"
489" lesbarer Form (MHz, GHz; us, ms)\n"
490
491#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
492#, c-format
493msgid " -h, --help Prints out this screen\n"
494msgstr " -h, --help Gibt diese Kurzübersicht aus\n"
495
496#: utils/cpufreq-info.c:495
497#, c-format
498msgid ""
499"If no argument or only the -c, --cpu parameter is given, debug output about\n"
500"cpufreq is printed which is useful e.g. for reporting bugs.\n"
501msgstr ""
502"Sofern kein anderer Parameter als '-c, --cpu' angegeben wird, liefert "
503"dieses\n"
504"Programm Informationen, die z.B. zum Berichten von Fehlern nützlich sind.\n"
505
506#: utils/cpufreq-info.c:497
507#, c-format
508msgid ""
509"For the arguments marked with *, omitting the -c or --cpu argument is\n"
510"equivalent to setting it to zero\n"
511msgstr ""
512"Bei den mit * markierten Parametern wird '--cpu 0' angenommen, soweit nicht\n"
513"mittels -c oder --cpu etwas anderes angegeben wird\n"
514
515#: utils/cpufreq-info.c:580
516#, c-format
517msgid ""
518"The argument passed to this tool can't be combined with passing a --cpu "
519"argument\n"
520msgstr "Diese Option kann nicht mit der --cpu-Option kombiniert werden\n"
521
522#: utils/cpufreq-info.c:596
523#, c-format
524msgid ""
525"You can't specify more than one --cpu parameter and/or\n"
526"more than one output-specific argument\n"
527msgstr ""
528"Man kann nicht mehr als einen --cpu-Parameter und/oder mehr als einen\n"
529"informationsspezifischen Parameter gleichzeitig angeben\n"
530
531#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
532#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
533#, c-format
534msgid "invalid or unknown argument\n"
535msgstr "unbekannter oder falscher Parameter\n"
536
537#: utils/cpufreq-info.c:617
538#, c-format
539msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
540msgstr ""
541"Konnte nicht die CPU %d analysieren, da sie (scheinbar?) nicht existiert.\n"
542
543#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
544#, c-format
545msgid "analyzing CPU %d:\n"
546msgstr "analysiere CPU %d:\n"
547
548#: utils/cpufreq-set.c:25
549#, fuzzy, c-format
550msgid "Usage: cpupower frequency-set [options]\n"
551msgstr "Aufruf: cpufreq-set [Optionen]\n"
552
553#: utils/cpufreq-set.c:27
554#, c-format
555msgid ""
556" -d FREQ, --min FREQ new minimum CPU frequency the governor may "
557"select\n"
558msgstr ""
559" -d FREQ, --min FREQ neue minimale Taktfrequenz, die der Regler\n"
560" auswählen darf\n"
561
562#: utils/cpufreq-set.c:28
563#, c-format
564msgid ""
565" -u FREQ, --max FREQ new maximum CPU frequency the governor may "
566"select\n"
567msgstr ""
568" -u FREQ, --max FREQ neue maximale Taktfrequenz, die der Regler\n"
569" auswählen darf\n"
570
571#: utils/cpufreq-set.c:29
572#, c-format
573msgid " -g GOV, --governor GOV new cpufreq governor\n"
574msgstr " -g GOV, --governors GOV wechsle zu Regler GOV\n"
575
576#: utils/cpufreq-set.c:30
577#, c-format
578msgid ""
579" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n"
580" governor to be available and loaded\n"
581msgstr ""
582" -f FREQ, --freq FREQ setze exakte Taktfrequenz. Benötigt den Regler\n"
583" 'userspace'.\n"
584
585#: utils/cpufreq-set.c:32
586#, c-format
587msgid " -r, --related Switches all hardware-related CPUs\n"
588msgstr ""
589" -r, --related Setze Werte für alle CPUs, deren Taktfrequenz\n"
590" hardwarebedingt identisch ist.\n"
591
592#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
593#, c-format
594msgid " -h, --help Prints out this screen\n"
595msgstr " -h, --help Gibt diese Kurzübersicht aus\n"
596
597#: utils/cpufreq-set.c:35
598#, fuzzy, c-format
599msgid ""
600"Notes:\n"
601"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
602msgstr ""
603"Bei den mit * markierten Parametern wird '--cpu 0' angenommen, soweit nicht\n"
604"mittels -c oder --cpu etwas anderes angegeben wird\n"
605
606#: utils/cpufreq-set.c:37
607#, fuzzy, c-format
608msgid ""
609"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
610"parameter\n"
611" except the -c CPU, --cpu CPU parameter\n"
612"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
613" by postfixing the value with the wanted unit name, without any space\n"
614" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
615msgstr ""
616"Hinweise:\n"
617"1. Sofern kein -c oder --cpu-Parameter angegeben ist, wird '--cpu 0'\n"
618" angenommen\n"
619"2. Der Parameter -f bzw. --freq kann mit keinem anderen als dem Parameter\n"
620" -c bzw. --cpu kombiniert werden\n"
621"3. FREQuenzen können in Hz, kHz (Standard), MHz, GHz oder THz eingegeben\n"
622" werden, indem der Wert und unmittelbar anschließend (ohne Leerzeichen!)\n"
623" die Einheit angegeben werden. (Bsp: 1GHz )\n"
624" (FREQuenz in kHz =^ MHz * 1000 =^ GHz * 1000000).\n"
625
626#: utils/cpufreq-set.c:57
627#, c-format
628msgid ""
629"Error setting new values. Common errors:\n"
630"- Do you have proper administration rights? (super-user?)\n"
631"- Is the governor you requested available and modprobed?\n"
632"- Trying to set an invalid policy?\n"
633"- Trying to set a specific frequency, but userspace governor is not "
634"available,\n"
635" for example because of hardware which cannot be set to a specific "
636"frequency\n"
637" or because the userspace governor isn't loaded?\n"
638msgstr ""
639"Beim Einstellen ist ein Fehler aufgetreten. Typische Fehlerquellen sind:\n"
640"- nicht ausreichende Rechte (Administrator)\n"
641"- der Regler ist nicht verfügbar bzw. nicht geladen\n"
642"- die angegebene Taktik ist inkorrekt\n"
643"- eine spezifische Frequenz wurde angegeben, aber der Regler 'userspace'\n"
644" kann entweder hardwarebedingt nicht genutzt werden oder ist nicht geladen\n"
645
646#: utils/cpufreq-set.c:170
647#, c-format
648msgid "wrong, unknown or unhandled CPU?\n"
649msgstr "unbekannte oder nicht regelbare CPU\n"
650
651#: utils/cpufreq-set.c:302
652#, c-format
653msgid ""
654"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
655"-g/--governor parameters\n"
656msgstr ""
657"Der -f bzw. --freq-Parameter kann nicht mit den Parametern -d/--min, -u/--"
658"max\n"
659"oder -g/--governor kombiniert werden\n"
660
661#: utils/cpufreq-set.c:308
662#, c-format
663msgid ""
664"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
665"-g/--governor must be passed\n"
666msgstr ""
667"Es muss mindestens ein Parameter aus -f/--freq, -d/--min, -u/--max oder\n"
668"-g/--governor angegeben werden.\n"
669
670#: utils/cpufreq-set.c:347
671#, c-format
672msgid "Setting cpu: %d\n"
673msgstr ""
674
675#: utils/cpupower-set.c:22
676#, c-format
677msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
678msgstr ""
679
680#: utils/cpupower-set.c:24
681#, c-format
682msgid ""
683" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n"
684" Intel models [0-15], see manpage for details\n"
685msgstr ""
686
687#: utils/cpupower-set.c:26
688#, c-format
689msgid ""
690" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n"
691msgstr ""
692
693#: utils/cpupower-set.c:27
694#, c-format
695msgid ""
696" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler "
697"policy.\n"
698msgstr ""
699
700#: utils/cpupower-set.c:80
701#, c-format
702msgid "--perf-bias param out of range [0-%d]\n"
703msgstr ""
704
705#: utils/cpupower-set.c:91
706#, c-format
707msgid "--sched-mc param out of range [0-%d]\n"
708msgstr ""
709
710#: utils/cpupower-set.c:102
711#, c-format
712msgid "--sched-smt param out of range [0-%d]\n"
713msgstr ""
714
715#: utils/cpupower-set.c:121
716#, c-format
717msgid "Error setting sched-mc %s\n"
718msgstr ""
719
720#: utils/cpupower-set.c:127
721#, c-format
722msgid "Error setting sched-smt %s\n"
723msgstr ""
724
725#: utils/cpupower-set.c:146
726#, c-format
727msgid "Error setting perf-bias value on CPU %d\n"
728msgstr ""
729
730#: utils/cpupower-info.c:21
731#, c-format
732msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
733msgstr ""
734
735#: utils/cpupower-info.c:23
736#, c-format
737msgid ""
738" -b, --perf-bias Gets CPU's power vs performance policy on some\n"
739" Intel models [0-15], see manpage for details\n"
740msgstr ""
741
742#: utils/cpupower-info.c:25
743#, fuzzy, c-format
744msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n"
745msgstr " -p, --policy Findet die momentane Taktik heraus *\n"
746
747#: utils/cpupower-info.c:26
748#, c-format
749msgid ""
750" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n"
751msgstr ""
752
753#: utils/cpupower-info.c:28
754#, c-format
755msgid ""
756"\n"
757"Passing no option will show all info, by default only on core 0\n"
758msgstr ""
759
760#: utils/cpupower-info.c:102
761#, c-format
762msgid "System's multi core scheduler setting: "
763msgstr ""
764
765#. if sysfs file is missing it's: errno == ENOENT
766#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
767#, c-format
768msgid "not supported\n"
769msgstr ""
770
771#: utils/cpupower-info.c:111
772#, c-format
773msgid "System's thread sibling scheduler setting: "
774msgstr ""
775
776#: utils/cpupower-info.c:126
777#, c-format
778msgid "Intel's performance bias setting needs root privileges\n"
779msgstr ""
780
781#: utils/cpupower-info.c:128
782#, c-format
783msgid "System does not support Intel's performance bias setting\n"
784msgstr ""
785
786#: utils/cpupower-info.c:147
787#, c-format
788msgid "Could not read perf-bias value\n"
789msgstr ""
790
791#: utils/cpupower-info.c:150
792#, c-format
793msgid "perf-bias: %d\n"
794msgstr ""
795
796#: utils/cpuidle-info.c:28
797#, fuzzy, c-format
798msgid "Analyzing CPU %d:\n"
799msgstr "analysiere CPU %d:\n"
800
801#: utils/cpuidle-info.c:32
802#, c-format
803msgid "CPU %u: No idle states\n"
804msgstr ""
805
806#: utils/cpuidle-info.c:36
807#, c-format
808msgid "CPU %u: Can't read idle state info\n"
809msgstr ""
810
811#: utils/cpuidle-info.c:41
812#, c-format
813msgid "Could not determine max idle state %u\n"
814msgstr ""
815
816#: utils/cpuidle-info.c:46
817#, c-format
818msgid "Number of idle states: %d\n"
819msgstr ""
820
821#: utils/cpuidle-info.c:48
822#, fuzzy, c-format
823msgid "Available idle states:"
824msgstr " mögliche Taktfrequenzen: "
825
826#: utils/cpuidle-info.c:71
827#, c-format
828msgid "Flags/Description: %s\n"
829msgstr ""
830
831#: utils/cpuidle-info.c:74
832#, c-format
833msgid "Latency: %lu\n"
834msgstr ""
835
836#: utils/cpuidle-info.c:76
837#, c-format
838msgid "Usage: %lu\n"
839msgstr ""
840
841#: utils/cpuidle-info.c:78
842#, c-format
843msgid "Duration: %llu\n"
844msgstr ""
845
846#: utils/cpuidle-info.c:90
847#, c-format
848msgid "Could not determine cpuidle driver\n"
849msgstr ""
850
851#: utils/cpuidle-info.c:94
852#, fuzzy, c-format
853msgid "CPUidle driver: %s\n"
854msgstr " Treiber: %s\n"
855
856#: utils/cpuidle-info.c:99
857#, c-format
858msgid "Could not determine cpuidle governor\n"
859msgstr ""
860
861#: utils/cpuidle-info.c:103
862#, c-format
863msgid "CPUidle governor: %s\n"
864msgstr ""
865
866#: utils/cpuidle-info.c:122
867#, c-format
868msgid "CPU %u: Can't read C-state info\n"
869msgstr ""
870
871#. printf("Cstates: %d\n", cstates);
872#: utils/cpuidle-info.c:127
873#, c-format
874msgid "active state: C0\n"
875msgstr ""
876
877#: utils/cpuidle-info.c:128
878#, c-format
879msgid "max_cstate: C%u\n"
880msgstr ""
881
882#: utils/cpuidle-info.c:129
883#, fuzzy, c-format
884msgid "maximum allowed latency: %lu usec\n"
885msgstr " Maximale Dauer eines Taktfrequenzwechsels: "
886
887#: utils/cpuidle-info.c:130
888#, c-format
889msgid "states:\t\n"
890msgstr ""
891
892#: utils/cpuidle-info.c:132
893#, c-format
894msgid " C%d: type[C%d] "
895msgstr ""
896
897#: utils/cpuidle-info.c:134
898#, c-format
899msgid "promotion[--] demotion[--] "
900msgstr ""
901
902#: utils/cpuidle-info.c:135
903#, c-format
904msgid "latency[%03lu] "
905msgstr ""
906
907#: utils/cpuidle-info.c:137
908#, c-format
909msgid "usage[%08lu] "
910msgstr ""
911
912#: utils/cpuidle-info.c:139
913#, c-format
914msgid "duration[%020Lu] \n"
915msgstr ""
916
917#: utils/cpuidle-info.c:147
918#, fuzzy, c-format
919msgid "Usage: cpupower idleinfo [options]\n"
920msgstr "Aufruf: cpufreq-info [Optionen]\n"
921
922#: utils/cpuidle-info.c:149
923#, fuzzy, c-format
924msgid " -s, --silent Only show general C-state information\n"
925msgstr ""
926" -e, --debug Erzeugt detaillierte Informationen, hilfreich\n"
927" zum Aufspüren von Fehlern\n"
928
929#: utils/cpuidle-info.c:150
930#, fuzzy, c-format
931msgid ""
932" -o, --proc Prints out information like provided by the /proc/"
933"acpi/processor/*/power\n"
934" interface in older kernels\n"
935msgstr ""
936" -o, --proc Erzeugt Informationen in einem ähnlichem Format zu "
937"dem\n"
938" der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n"
939" Kernel-Versionen\n"
940
941#: utils/cpuidle-info.c:209
942#, fuzzy, c-format
943msgid "You can't specify more than one output-specific argument\n"
944msgstr ""
945"Man kann nicht mehr als einen --cpu-Parameter und/oder mehr als einen\n"
946"informationsspezifischen Parameter gleichzeitig angeben\n"
947
948#~ msgid ""
949#~ " -c CPU, --cpu CPU CPU number which information shall be determined "
950#~ "about\n"
951#~ msgstr ""
952#~ " -c CPU, --cpu CPU Nummer der CPU, über die Informationen "
953#~ "herausgefunden werden sollen\n"
954
955#~ msgid ""
956#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be "
957#~ "modified\n"
958#~ msgstr ""
959#~ " -c CPU, --cpu CPU Nummer der CPU, deren Taktfrequenz-"
960#~ "Einstellung\n"
961#~ " werden soll\n"
diff --git a/tools/power/cpupower/po/fr.po b/tools/power/cpupower/po/fr.po
new file mode 100644
index 00000000000..245ad20a9bf
--- /dev/null
+++ b/tools/power/cpupower/po/fr.po
@@ -0,0 +1,947 @@
1# French translations for cpufrequtils package
2# Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER
3# This file is distributed under the same license as the cpufrequtils package.
4# Ducrot Bruno <ducrot@poupinou.org>, 2004.
5#
6#, fuzzy
7msgid ""
8msgstr ""
9"Project-Id-Version: cpufrequtils 0.1-pre2\n"
10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2011-03-08 17:03+0100\n"
12"PO-Revision-Date: 2004-11-17 15:53+1000\n"
13"Last-Translator: Bruno Ducrot <ducrot@poupinou.org>\n"
14"Language-Team: NONE\n"
15"Language: \n"
16"MIME-Version: 1.0\n"
17"Content-Type: text/plain; charset=ISO-8859-1\n"
18"Content-Transfer-Encoding: 8bit\n"
19
20#: utils/idle_monitor/nhm_idle.c:36
21msgid "Processor Core C3"
22msgstr ""
23
24#: utils/idle_monitor/nhm_idle.c:43
25msgid "Processor Core C6"
26msgstr ""
27
28#: utils/idle_monitor/nhm_idle.c:51
29msgid "Processor Package C3"
30msgstr ""
31
32#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
33msgid "Processor Package C6"
34msgstr ""
35
36#: utils/idle_monitor/snb_idle.c:33
37msgid "Processor Core C7"
38msgstr ""
39
40#: utils/idle_monitor/snb_idle.c:40
41msgid "Processor Package C2"
42msgstr ""
43
44#: utils/idle_monitor/snb_idle.c:47
45msgid "Processor Package C7"
46msgstr ""
47
48#: utils/idle_monitor/amd_fam14h_idle.c:56
49msgid "Package in sleep state (PC1 or deeper)"
50msgstr ""
51
52#: utils/idle_monitor/amd_fam14h_idle.c:63
53msgid "Processor Package C1"
54msgstr ""
55
56#: utils/idle_monitor/amd_fam14h_idle.c:77
57msgid "North Bridge P1 boolean counter (returns 0 or 1)"
58msgstr ""
59
60#: utils/idle_monitor/mperf_monitor.c:35
61msgid "Processor Core not idle"
62msgstr ""
63
64#: utils/idle_monitor/mperf_monitor.c:42
65msgid "Processor Core in an idle state"
66msgstr ""
67
68#: utils/idle_monitor/mperf_monitor.c:50
69msgid "Average Frequency (including boost) in MHz"
70msgstr ""
71
72#: utils/idle_monitor/cpupower-monitor.c:66
73#, c-format
74msgid ""
75"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
76"interval_sec | -c command ...]\n"
77msgstr ""
78
79#: utils/idle_monitor/cpupower-monitor.c:69
80#, c-format
81msgid ""
82"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
83"interval_sec | -c command ...]\n"
84msgstr ""
85
86#: utils/idle_monitor/cpupower-monitor.c:71
87#, c-format
88msgid "\t -v: be more verbose\n"
89msgstr ""
90
91#: utils/idle_monitor/cpupower-monitor.c:73
92#, c-format
93msgid "\t -h: print this help\n"
94msgstr ""
95
96#: utils/idle_monitor/cpupower-monitor.c:74
97#, c-format
98msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
99msgstr ""
100
101#: utils/idle_monitor/cpupower-monitor.c:75
102#, c-format
103msgid "\t -t: show CPU topology/hierarchy\n"
104msgstr ""
105
106#: utils/idle_monitor/cpupower-monitor.c:76
107#, c-format
108msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
109msgstr ""
110
111#: utils/idle_monitor/cpupower-monitor.c:77
112#, c-format
113msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
114msgstr ""
115
116#: utils/idle_monitor/cpupower-monitor.c:79
117#, c-format
118msgid ""
119"only one of: -t, -l, -m are allowed\n"
120"If none of them is passed,"
121msgstr ""
122
123#: utils/idle_monitor/cpupower-monitor.c:80
124#, c-format
125msgid " all supported monitors are shown\n"
126msgstr ""
127
128#: utils/idle_monitor/cpupower-monitor.c:197
129#, c-format
130msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
131msgstr ""
132
133#: utils/idle_monitor/cpupower-monitor.c:207
134#, c-format
135msgid " *is offline\n"
136msgstr ""
137
138#: utils/idle_monitor/cpupower-monitor.c:236
139#, c-format
140msgid "%s: max monitor name length (%d) exceeded\n"
141msgstr ""
142
143#: utils/idle_monitor/cpupower-monitor.c:250
144#, c-format
145msgid "No matching monitor found in %s, try -l option\n"
146msgstr ""
147
148#: utils/idle_monitor/cpupower-monitor.c:266
149#, c-format
150msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
151msgstr ""
152
153#: utils/idle_monitor/cpupower-monitor.c:319
154#, c-format
155msgid "%s took %.5f seconds and exited with status %d\n"
156msgstr ""
157
158#: utils/idle_monitor/cpupower-monitor.c:406
159#, c-format
160msgid "Cannot read number of available processors\n"
161msgstr ""
162
163#: utils/idle_monitor/cpupower-monitor.c:417
164#, c-format
165msgid "Available monitor %s needs root access\n"
166msgstr ""
167
168#: utils/idle_monitor/cpupower-monitor.c:428
169#, c-format
170msgid "No HW Cstate monitors found\n"
171msgstr ""
172
173#: utils/cpupower.c:78
174#, c-format
175msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
176msgstr ""
177
178#: utils/cpupower.c:79
179#, c-format
180msgid "cpupower --version\n"
181msgstr ""
182
183#: utils/cpupower.c:80
184#, c-format
185msgid "Supported subcommands are:\n"
186msgstr ""
187
188#: utils/cpupower.c:83
189#, c-format
190msgid ""
191"\n"
192"Some subcommands can make use of the -c cpulist option.\n"
193msgstr ""
194
195#: utils/cpupower.c:84
196#, c-format
197msgid "Look at the general cpupower manpage how to use it\n"
198msgstr ""
199
200#: utils/cpupower.c:85
201#, c-format
202msgid "and read up the subcommand's manpage whether it is supported.\n"
203msgstr ""
204
205#: utils/cpupower.c:86
206#, c-format
207msgid ""
208"\n"
209"Use cpupower help subcommand for getting help for above subcommands.\n"
210msgstr ""
211
212#: utils/cpupower.c:91
213#, c-format
214msgid "Report errors and bugs to %s, please.\n"
215msgstr "Veuillez rapportez les erreurs et les bogues à %s, s'il vous plait.\n"
216
217#: utils/cpupower.c:114
218#, c-format
219msgid "Error parsing cpu list\n"
220msgstr ""
221
222#: utils/cpupower.c:172
223#, c-format
224msgid "Subcommand %s needs root privileges\n"
225msgstr ""
226
227#: utils/cpufreq-info.c:31
228#, c-format
229msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
230msgstr "Détermination du nombre de CPUs (%s : %s) impossible. Assume 1\n"
231
232#: utils/cpufreq-info.c:63
233#, c-format
234msgid ""
235" minimum CPU frequency - maximum CPU frequency - governor\n"
236msgstr ""
237" Fréquence CPU minimale - Fréquence CPU maximale - régulateur\n"
238
239#: utils/cpufreq-info.c:151
240#, c-format
241msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
242msgstr ""
243
244#. P state changes via MSR are identified via cpuid 80000007
245#. on Intel and AMD, but we assume boost capable machines can do that
246#. if (cpuid_eax(0x80000000) >= 0x80000007
247#. && (cpuid_edx(0x80000007) & (1 << 7)))
248#.
249#: utils/cpufreq-info.c:161
250#, c-format
251msgid " boost state support: \n"
252msgstr ""
253
254#: utils/cpufreq-info.c:163
255#, c-format
256msgid " Supported: %s\n"
257msgstr ""
258
259#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
260msgid "yes"
261msgstr ""
262
263#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
264msgid "no"
265msgstr ""
266
267#: utils/cpufreq-info.c:164
268#, fuzzy, c-format
269msgid " Active: %s\n"
270msgstr " pilote : %s\n"
271
272#: utils/cpufreq-info.c:177
273#, c-format
274msgid " Boost States: %d\n"
275msgstr ""
276
277#: utils/cpufreq-info.c:178
278#, c-format
279msgid " Total States: %d\n"
280msgstr ""
281
282#: utils/cpufreq-info.c:181
283#, c-format
284msgid " Pstate-Pb%d: %luMHz (boost state)\n"
285msgstr ""
286
287#: utils/cpufreq-info.c:184
288#, c-format
289msgid " Pstate-P%d: %luMHz\n"
290msgstr ""
291
292#: utils/cpufreq-info.c:211
293#, c-format
294msgid " no or unknown cpufreq driver is active on this CPU\n"
295msgstr " pas de pilotes cpufreq reconnu pour ce CPU\n"
296
297#: utils/cpufreq-info.c:213
298#, c-format
299msgid " driver: %s\n"
300msgstr " pilote : %s\n"
301
302#: utils/cpufreq-info.c:219
303#, fuzzy, c-format
304msgid " CPUs which run at the same hardware frequency: "
305msgstr " CPUs qui doivent changer de fréquences en même temps : "
306
307#: utils/cpufreq-info.c:230
308#, fuzzy, c-format
309msgid " CPUs which need to have their frequency coordinated by software: "
310msgstr " CPUs qui doivent changer de fréquences en même temps : "
311
312#: utils/cpufreq-info.c:241
313#, c-format
314msgid " maximum transition latency: "
315msgstr ""
316
317#: utils/cpufreq-info.c:247
318#, c-format
319msgid " hardware limits: "
320msgstr " limitation matérielle : "
321
322#: utils/cpufreq-info.c:256
323#, c-format
324msgid " available frequency steps: "
325msgstr " plage de fréquence : "
326
327#: utils/cpufreq-info.c:269
328#, c-format
329msgid " available cpufreq governors: "
330msgstr " régulateurs disponibles : "
331
332#: utils/cpufreq-info.c:280
333#, c-format
334msgid " current policy: frequency should be within "
335msgstr " tactique actuelle : la fréquence doit être comprise entre "
336
337#: utils/cpufreq-info.c:282
338#, c-format
339msgid " and "
340msgstr " et "
341
342#: utils/cpufreq-info.c:286
343#, c-format
344msgid ""
345"The governor \"%s\" may decide which speed to use\n"
346" within this range.\n"
347msgstr ""
348"Le régulateur \"%s\" est libre de choisir la vitesse\n"
349" dans cette plage de fréquences.\n"
350
351#: utils/cpufreq-info.c:293
352#, c-format
353msgid " current CPU frequency is "
354msgstr " la fréquence actuelle de ce CPU est "
355
356#: utils/cpufreq-info.c:296
357#, c-format
358msgid " (asserted by call to hardware)"
359msgstr " (vérifié par un appel direct du matériel)"
360
361#: utils/cpufreq-info.c:304
362#, c-format
363msgid " cpufreq stats: "
364msgstr " des statistique concernant cpufreq:"
365
366#: utils/cpufreq-info.c:472
367#, fuzzy, c-format
368msgid "Usage: cpupower freqinfo [options]\n"
369msgstr "Usage : cpufreq-info [options]\n"
370
371#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
372#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
373#, c-format
374msgid "Options:\n"
375msgstr "Options :\n"
376
377#: utils/cpufreq-info.c:474
378#, fuzzy, c-format
379msgid " -e, --debug Prints out debug information [default]\n"
380msgstr " -e, --debug Afficher les informations de déboguage\n"
381
382#: utils/cpufreq-info.c:475
383#, c-format
384msgid ""
385" -f, --freq Get frequency the CPU currently runs at, according\n"
386" to the cpufreq core *\n"
387msgstr ""
388" -f, --freq Obtenir la fréquence actuelle du CPU selon le point\n"
389" de vue du coeur du système de cpufreq *\n"
390
391#: utils/cpufreq-info.c:477
392#, c-format
393msgid ""
394" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n"
395" it from hardware (only available to root) *\n"
396msgstr ""
397" -w, --hwfreq Obtenir la fréquence actuelle du CPU directement par\n"
398" le matériel (doit être root) *\n"
399
400#: utils/cpufreq-info.c:479
401#, c-format
402msgid ""
403" -l, --hwlimits Determine the minimum and maximum CPU frequency "
404"allowed *\n"
405msgstr ""
406" -l, --hwlimits Affiche les fréquences minimales et maximales du CPU "
407"*\n"
408
409#: utils/cpufreq-info.c:480
410#, c-format
411msgid " -d, --driver Determines the used cpufreq kernel driver *\n"
412msgstr " -d, --driver Affiche le pilote cpufreq utilisé *\n"
413
414#: utils/cpufreq-info.c:481
415#, c-format
416msgid " -p, --policy Gets the currently used cpufreq policy *\n"
417msgstr " -p, --policy Affiche la tactique actuelle de cpufreq *\n"
418
419#: utils/cpufreq-info.c:482
420#, c-format
421msgid " -g, --governors Determines available cpufreq governors *\n"
422msgstr ""
423" -g, --governors Affiche les régulateurs disponibles de cpufreq *\n"
424
425#: utils/cpufreq-info.c:483
426#, fuzzy, c-format
427msgid ""
428" -r, --related-cpus Determines which CPUs run at the same hardware "
429"frequency *\n"
430msgstr ""
431" -a, --affected-cpus Affiche quels sont les CPUs qui doivent changer de\n"
432" fréquences en même temps *\n"
433
434#: utils/cpufreq-info.c:484
435#, fuzzy, c-format
436msgid ""
437" -a, --affected-cpus Determines which CPUs need to have their frequency\n"
438" coordinated by software *\n"
439msgstr ""
440" -a, --affected-cpus Affiche quels sont les CPUs qui doivent changer de\n"
441" fréquences en même temps *\n"
442
443#: utils/cpufreq-info.c:486
444#, c-format
445msgid " -s, --stats Shows cpufreq statistics if available\n"
446msgstr ""
447" -s, --stats Indique des statistiques concernant cpufreq, si\n"
448" disponibles\n"
449
450#: utils/cpufreq-info.c:487
451#, fuzzy, c-format
452msgid ""
453" -y, --latency Determines the maximum latency on CPU frequency "
454"changes *\n"
455msgstr ""
456" -l, --hwlimits Affiche les fréquences minimales et maximales du CPU "
457"*\n"
458
459#: utils/cpufreq-info.c:488
460#, c-format
461msgid " -b, --boost Checks for turbo or boost modes *\n"
462msgstr ""
463
464#: utils/cpufreq-info.c:489
465#, c-format
466msgid ""
467" -o, --proc Prints out information like provided by the /proc/"
468"cpufreq\n"
469" interface in 2.4. and early 2.6. kernels\n"
470msgstr ""
471" -o, --proc Affiche les informations en utilisant l'interface\n"
472" fournie par /proc/cpufreq, présente dans les "
473"versions\n"
474" 2.4 et les anciennes versions 2.6 du noyau\n"
475
476#: utils/cpufreq-info.c:491
477#, fuzzy, c-format
478msgid ""
479" -m, --human human-readable output for the -f, -w, -s and -y "
480"parameters\n"
481msgstr ""
482" -m, --human affiche dans un format lisible pour un humain\n"
483" pour les options -f, -w et -s (MHz, GHz)\n"
484
485#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
486#, c-format
487msgid " -h, --help Prints out this screen\n"
488msgstr " -h, --help affiche l'aide-mémoire\n"
489
490#: utils/cpufreq-info.c:495
491#, c-format
492msgid ""
493"If no argument or only the -c, --cpu parameter is given, debug output about\n"
494"cpufreq is printed which is useful e.g. for reporting bugs.\n"
495msgstr ""
496"Par défaut, les informations de déboguage seront affichées si aucun\n"
497"argument, ou bien si seulement l'argument -c (--cpu) est donné, afin de\n"
498"faciliter les rapports de bogues par exemple\n"
499
500#: utils/cpufreq-info.c:497
501#, c-format
502msgid ""
503"For the arguments marked with *, omitting the -c or --cpu argument is\n"
504"equivalent to setting it to zero\n"
505msgstr "Les arguments avec un * utiliseront le CPU 0 si -c (--cpu) est omis\n"
506
507#: utils/cpufreq-info.c:580
508#, c-format
509msgid ""
510"The argument passed to this tool can't be combined with passing a --cpu "
511"argument\n"
512msgstr "Cette option est incompatible avec --cpu\n"
513
514#: utils/cpufreq-info.c:596
515#, c-format
516msgid ""
517"You can't specify more than one --cpu parameter and/or\n"
518"more than one output-specific argument\n"
519msgstr ""
520"On ne peut indiquer plus d'un paramètre --cpu, tout comme l'on ne peut\n"
521"spécifier plus d'un argument de formatage\n"
522
523#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
524#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
525#, c-format
526msgid "invalid or unknown argument\n"
527msgstr "option invalide\n"
528
529#: utils/cpufreq-info.c:617
530#, c-format
531msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
532msgstr "analyse du CPU %d impossible puisqu'il ne semble pas être présent\n"
533
534#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
535#, c-format
536msgid "analyzing CPU %d:\n"
537msgstr "analyse du CPU %d :\n"
538
539#: utils/cpufreq-set.c:25
540#, fuzzy, c-format
541msgid "Usage: cpupower frequency-set [options]\n"
542msgstr "Usage : cpufreq-set [options]\n"
543
544#: utils/cpufreq-set.c:27
545#, c-format
546msgid ""
547" -d FREQ, --min FREQ new minimum CPU frequency the governor may "
548"select\n"
549msgstr ""
550" -d FREQ, --min FREQ nouvelle fréquence minimale du CPU à utiliser\n"
551" par le régulateur\n"
552
553#: utils/cpufreq-set.c:28
554#, c-format
555msgid ""
556" -u FREQ, --max FREQ new maximum CPU frequency the governor may "
557"select\n"
558msgstr ""
559" -u FREQ, --max FREQ nouvelle fréquence maximale du CPU à utiliser\n"
560" par le régulateur\n"
561
562#: utils/cpufreq-set.c:29
563#, c-format
564msgid " -g GOV, --governor GOV new cpufreq governor\n"
565msgstr " -g GOV, --governor GOV active le régulateur GOV\n"
566
567#: utils/cpufreq-set.c:30
568#, c-format
569msgid ""
570" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n"
571" governor to be available and loaded\n"
572msgstr ""
573" -f FREQ, --freq FREQ fixe la fréquence du processeur à FREQ. Il faut\n"
574" que le régulateur « userspace » soit disponible \n"
575" et activé.\n"
576
577#: utils/cpufreq-set.c:32
578#, c-format
579msgid " -r, --related Switches all hardware-related CPUs\n"
580msgstr ""
581
582#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
583#, fuzzy, c-format
584msgid " -h, --help Prints out this screen\n"
585msgstr " -h, --help affiche l'aide-mémoire\n"
586
587#: utils/cpufreq-set.c:35
588#, fuzzy, c-format
589msgid ""
590"Notes:\n"
591"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
592msgstr "Les arguments avec un * utiliseront le CPU 0 si -c (--cpu) est omis\n"
593
594#: utils/cpufreq-set.c:37
595#, fuzzy, c-format
596msgid ""
597"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
598"parameter\n"
599" except the -c CPU, --cpu CPU parameter\n"
600"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
601" by postfixing the value with the wanted unit name, without any space\n"
602" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
603msgstr ""
604"Remarque :\n"
605"1. Le CPU numéro 0 sera utilisé par défaut si -c (ou --cpu) est omis ;\n"
606"2. l'argument -f FREQ (ou --freq FREQ) ne peut être utilisé qu'avec --cpu ;\n"
607"3. on pourra préciser l'unité des fréquences en postfixant sans aucune "
608"espace\n"
609" les valeurs par hz, kHz (par défaut), MHz, GHz ou THz\n"
610" (kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
611
612#: utils/cpufreq-set.c:57
613#, c-format
614msgid ""
615"Error setting new values. Common errors:\n"
616"- Do you have proper administration rights? (super-user?)\n"
617"- Is the governor you requested available and modprobed?\n"
618"- Trying to set an invalid policy?\n"
619"- Trying to set a specific frequency, but userspace governor is not "
620"available,\n"
621" for example because of hardware which cannot be set to a specific "
622"frequency\n"
623" or because the userspace governor isn't loaded?\n"
624msgstr ""
625"En ajustant les nouveaux paramètres, une erreur est apparue. Les sources\n"
626"d'erreur typique sont :\n"
627"- droit d'administration insuffisant (êtes-vous root ?) ;\n"
628"- le régulateur choisi n'est pas disponible, ou bien n'est pas disponible "
629"en\n"
630" tant que module noyau ;\n"
631"- la tactique n'est pas disponible ;\n"
632"- vous voulez utiliser l'option -f/--freq, mais le régulateur « userspace »\n"
633" n'est pas disponible, par exemple parce que le matériel ne le supporte\n"
634" pas, ou bien n'est tout simplement pas chargé.\n"
635
636#: utils/cpufreq-set.c:170
637#, c-format
638msgid "wrong, unknown or unhandled CPU?\n"
639msgstr "CPU inconnu ou non supporté ?\n"
640
641#: utils/cpufreq-set.c:302
642#, c-format
643msgid ""
644"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
645"-g/--governor parameters\n"
646msgstr ""
647"l'option -f/--freq est incompatible avec les options -d/--min, -u/--max et\n"
648"-g/--governor\n"
649
650#: utils/cpufreq-set.c:308
651#, c-format
652msgid ""
653"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
654"-g/--governor must be passed\n"
655msgstr ""
656"L'un de ces paramètres est obligatoire : -f/--freq, -d/--min, -u/--max et\n"
657"-g/--governor\n"
658
659#: utils/cpufreq-set.c:347
660#, c-format
661msgid "Setting cpu: %d\n"
662msgstr ""
663
664#: utils/cpupower-set.c:22
665#, c-format
666msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
667msgstr ""
668
669#: utils/cpupower-set.c:24
670#, c-format
671msgid ""
672" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n"
673" Intel models [0-15], see manpage for details\n"
674msgstr ""
675
676#: utils/cpupower-set.c:26
677#, c-format
678msgid ""
679" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n"
680msgstr ""
681
682#: utils/cpupower-set.c:27
683#, c-format
684msgid ""
685" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler "
686"policy.\n"
687msgstr ""
688
689#: utils/cpupower-set.c:80
690#, c-format
691msgid "--perf-bias param out of range [0-%d]\n"
692msgstr ""
693
694#: utils/cpupower-set.c:91
695#, c-format
696msgid "--sched-mc param out of range [0-%d]\n"
697msgstr ""
698
699#: utils/cpupower-set.c:102
700#, c-format
701msgid "--sched-smt param out of range [0-%d]\n"
702msgstr ""
703
704#: utils/cpupower-set.c:121
705#, c-format
706msgid "Error setting sched-mc %s\n"
707msgstr ""
708
709#: utils/cpupower-set.c:127
710#, c-format
711msgid "Error setting sched-smt %s\n"
712msgstr ""
713
714#: utils/cpupower-set.c:146
715#, c-format
716msgid "Error setting perf-bias value on CPU %d\n"
717msgstr ""
718
719#: utils/cpupower-info.c:21
720#, c-format
721msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
722msgstr ""
723
724#: utils/cpupower-info.c:23
725#, c-format
726msgid ""
727" -b, --perf-bias Gets CPU's power vs performance policy on some\n"
728" Intel models [0-15], see manpage for details\n"
729msgstr ""
730
731#: utils/cpupower-info.c:25
732#, fuzzy, c-format
733msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n"
734msgstr " -p, --policy Affiche la tactique actuelle de cpufreq *\n"
735
736#: utils/cpupower-info.c:26
737#, c-format
738msgid ""
739" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n"
740msgstr ""
741
742#: utils/cpupower-info.c:28
743#, c-format
744msgid ""
745"\n"
746"Passing no option will show all info, by default only on core 0\n"
747msgstr ""
748
749#: utils/cpupower-info.c:102
750#, c-format
751msgid "System's multi core scheduler setting: "
752msgstr ""
753
754#. if sysfs file is missing it's: errno == ENOENT
755#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
756#, c-format
757msgid "not supported\n"
758msgstr ""
759
760#: utils/cpupower-info.c:111
761#, c-format
762msgid "System's thread sibling scheduler setting: "
763msgstr ""
764
765#: utils/cpupower-info.c:126
766#, c-format
767msgid "Intel's performance bias setting needs root privileges\n"
768msgstr ""
769
770#: utils/cpupower-info.c:128
771#, c-format
772msgid "System does not support Intel's performance bias setting\n"
773msgstr ""
774
775#: utils/cpupower-info.c:147
776#, c-format
777msgid "Could not read perf-bias value\n"
778msgstr ""
779
780#: utils/cpupower-info.c:150
781#, c-format
782msgid "perf-bias: %d\n"
783msgstr ""
784
785#: utils/cpuidle-info.c:28
786#, fuzzy, c-format
787msgid "Analyzing CPU %d:\n"
788msgstr "analyse du CPU %d :\n"
789
790#: utils/cpuidle-info.c:32
791#, c-format
792msgid "CPU %u: No idle states\n"
793msgstr ""
794
795#: utils/cpuidle-info.c:36
796#, c-format
797msgid "CPU %u: Can't read idle state info\n"
798msgstr ""
799
800#: utils/cpuidle-info.c:41
801#, c-format
802msgid "Could not determine max idle state %u\n"
803msgstr ""
804
805#: utils/cpuidle-info.c:46
806#, c-format
807msgid "Number of idle states: %d\n"
808msgstr ""
809
810#: utils/cpuidle-info.c:48
811#, fuzzy, c-format
812msgid "Available idle states:"
813msgstr " plage de fréquence : "
814
815#: utils/cpuidle-info.c:71
816#, c-format
817msgid "Flags/Description: %s\n"
818msgstr ""
819
820#: utils/cpuidle-info.c:74
821#, c-format
822msgid "Latency: %lu\n"
823msgstr ""
824
825#: utils/cpuidle-info.c:76
826#, c-format
827msgid "Usage: %lu\n"
828msgstr ""
829
830#: utils/cpuidle-info.c:78
831#, c-format
832msgid "Duration: %llu\n"
833msgstr ""
834
835#: utils/cpuidle-info.c:90
836#, c-format
837msgid "Could not determine cpuidle driver\n"
838msgstr ""
839
840#: utils/cpuidle-info.c:94
841#, fuzzy, c-format
842msgid "CPUidle driver: %s\n"
843msgstr " pilote : %s\n"
844
845#: utils/cpuidle-info.c:99
846#, c-format
847msgid "Could not determine cpuidle governor\n"
848msgstr ""
849
850#: utils/cpuidle-info.c:103
851#, c-format
852msgid "CPUidle governor: %s\n"
853msgstr ""
854
855#: utils/cpuidle-info.c:122
856#, c-format
857msgid "CPU %u: Can't read C-state info\n"
858msgstr ""
859
860#. printf("Cstates: %d\n", cstates);
861#: utils/cpuidle-info.c:127
862#, c-format
863msgid "active state: C0\n"
864msgstr ""
865
866#: utils/cpuidle-info.c:128
867#, c-format
868msgid "max_cstate: C%u\n"
869msgstr ""
870
871#: utils/cpuidle-info.c:129
872#, c-format
873msgid "maximum allowed latency: %lu usec\n"
874msgstr ""
875
876#: utils/cpuidle-info.c:130
877#, c-format
878msgid "states:\t\n"
879msgstr ""
880
881#: utils/cpuidle-info.c:132
882#, c-format
883msgid " C%d: type[C%d] "
884msgstr ""
885
886#: utils/cpuidle-info.c:134
887#, c-format
888msgid "promotion[--] demotion[--] "
889msgstr ""
890
891#: utils/cpuidle-info.c:135
892#, c-format
893msgid "latency[%03lu] "
894msgstr ""
895
896#: utils/cpuidle-info.c:137
897#, c-format
898msgid "usage[%08lu] "
899msgstr ""
900
901#: utils/cpuidle-info.c:139
902#, c-format
903msgid "duration[%020Lu] \n"
904msgstr ""
905
906#: utils/cpuidle-info.c:147
907#, fuzzy, c-format
908msgid "Usage: cpupower idleinfo [options]\n"
909msgstr "Usage : cpufreq-info [options]\n"
910
911#: utils/cpuidle-info.c:149
912#, fuzzy, c-format
913msgid " -s, --silent Only show general C-state information\n"
914msgstr " -e, --debug Afficher les informations de déboguage\n"
915
916#: utils/cpuidle-info.c:150
917#, fuzzy, c-format
918msgid ""
919" -o, --proc Prints out information like provided by the /proc/"
920"acpi/processor/*/power\n"
921" interface in older kernels\n"
922msgstr ""
923" -o, --proc Affiche les informations en utilisant l'interface\n"
924" fournie par /proc/cpufreq, présente dans les "
925"versions\n"
926" 2.4 et les anciennes versions 2.6 du noyau\n"
927
928#: utils/cpuidle-info.c:209
929#, fuzzy, c-format
930msgid "You can't specify more than one output-specific argument\n"
931msgstr ""
932"On ne peut indiquer plus d'un paramètre --cpu, tout comme l'on ne peut\n"
933"spécifier plus d'un argument de formatage\n"
934
935#~ msgid ""
936#~ " -c CPU, --cpu CPU CPU number which information shall be determined "
937#~ "about\n"
938#~ msgstr ""
939#~ " -c CPU, --cpu CPU Numéro du CPU pour lequel l'information sera "
940#~ "affichée\n"
941
942#~ msgid ""
943#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be "
944#~ "modified\n"
945#~ msgstr ""
946#~ " -c CPU, --cpu CPU numéro du CPU à prendre en compte pour les\n"
947#~ " changements\n"
diff --git a/tools/power/cpupower/po/it.po b/tools/power/cpupower/po/it.po
new file mode 100644
index 00000000000..f80c4ddb9bd
--- /dev/null
+++ b/tools/power/cpupower/po/it.po
@@ -0,0 +1,961 @@
1# Italian translations for cpufrequtils package
2# Copyright (C) 2004-2009
3# This file is distributed under the same license as the cpufrequtils package.
4# Mattia Dongili <malattia@gmail.com>.
5#
6#
7msgid ""
8msgstr ""
9"Project-Id-Version: cpufrequtils 0.3\n"
10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2011-03-08 17:03+0100\n"
12"PO-Revision-Date: 2009-08-15 12:00+0900\n"
13"Last-Translator: Mattia Dongili <malattia@gmail.com>\n"
14"Language-Team: NONE\n"
15"Language: \n"
16"MIME-Version: 1.0\n"
17"Content-Type: text/plain; charset=UTF-8\n"
18"Content-Transfer-Encoding: 8bit\n"
19
20#: utils/idle_monitor/nhm_idle.c:36
21msgid "Processor Core C3"
22msgstr ""
23
24#: utils/idle_monitor/nhm_idle.c:43
25msgid "Processor Core C6"
26msgstr ""
27
28#: utils/idle_monitor/nhm_idle.c:51
29msgid "Processor Package C3"
30msgstr ""
31
32#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
33msgid "Processor Package C6"
34msgstr ""
35
36#: utils/idle_monitor/snb_idle.c:33
37msgid "Processor Core C7"
38msgstr ""
39
40#: utils/idle_monitor/snb_idle.c:40
41msgid "Processor Package C2"
42msgstr ""
43
44#: utils/idle_monitor/snb_idle.c:47
45msgid "Processor Package C7"
46msgstr ""
47
48#: utils/idle_monitor/amd_fam14h_idle.c:56
49msgid "Package in sleep state (PC1 or deeper)"
50msgstr ""
51
52#: utils/idle_monitor/amd_fam14h_idle.c:63
53msgid "Processor Package C1"
54msgstr ""
55
56#: utils/idle_monitor/amd_fam14h_idle.c:77
57msgid "North Bridge P1 boolean counter (returns 0 or 1)"
58msgstr ""
59
60#: utils/idle_monitor/mperf_monitor.c:35
61msgid "Processor Core not idle"
62msgstr ""
63
64#: utils/idle_monitor/mperf_monitor.c:42
65msgid "Processor Core in an idle state"
66msgstr ""
67
68#: utils/idle_monitor/mperf_monitor.c:50
69msgid "Average Frequency (including boost) in MHz"
70msgstr ""
71
72#: utils/idle_monitor/cpupower-monitor.c:66
73#, c-format
74msgid ""
75"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
76"interval_sec | -c command ...]\n"
77msgstr ""
78
79#: utils/idle_monitor/cpupower-monitor.c:69
80#, c-format
81msgid ""
82"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
83"interval_sec | -c command ...]\n"
84msgstr ""
85
86#: utils/idle_monitor/cpupower-monitor.c:71
87#, c-format
88msgid "\t -v: be more verbose\n"
89msgstr ""
90
91#: utils/idle_monitor/cpupower-monitor.c:73
92#, c-format
93msgid "\t -h: print this help\n"
94msgstr ""
95
96#: utils/idle_monitor/cpupower-monitor.c:74
97#, c-format
98msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
99msgstr ""
100
101#: utils/idle_monitor/cpupower-monitor.c:75
102#, c-format
103msgid "\t -t: show CPU topology/hierarchy\n"
104msgstr ""
105
106#: utils/idle_monitor/cpupower-monitor.c:76
107#, c-format
108msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
109msgstr ""
110
111#: utils/idle_monitor/cpupower-monitor.c:77
112#, c-format
113msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
114msgstr ""
115
116#: utils/idle_monitor/cpupower-monitor.c:79
117#, c-format
118msgid ""
119"only one of: -t, -l, -m are allowed\n"
120"If none of them is passed,"
121msgstr ""
122
123#: utils/idle_monitor/cpupower-monitor.c:80
124#, c-format
125msgid " all supported monitors are shown\n"
126msgstr ""
127
128#: utils/idle_monitor/cpupower-monitor.c:197
129#, c-format
130msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
131msgstr ""
132
133#: utils/idle_monitor/cpupower-monitor.c:207
134#, c-format
135msgid " *is offline\n"
136msgstr ""
137
138#: utils/idle_monitor/cpupower-monitor.c:236
139#, c-format
140msgid "%s: max monitor name length (%d) exceeded\n"
141msgstr ""
142
143#: utils/idle_monitor/cpupower-monitor.c:250
144#, c-format
145msgid "No matching monitor found in %s, try -l option\n"
146msgstr ""
147
148#: utils/idle_monitor/cpupower-monitor.c:266
149#, c-format
150msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
151msgstr ""
152
153#: utils/idle_monitor/cpupower-monitor.c:319
154#, c-format
155msgid "%s took %.5f seconds and exited with status %d\n"
156msgstr ""
157
158#: utils/idle_monitor/cpupower-monitor.c:406
159#, c-format
160msgid "Cannot read number of available processors\n"
161msgstr ""
162
163#: utils/idle_monitor/cpupower-monitor.c:417
164#, c-format
165msgid "Available monitor %s needs root access\n"
166msgstr ""
167
168#: utils/idle_monitor/cpupower-monitor.c:428
169#, c-format
170msgid "No HW Cstate monitors found\n"
171msgstr ""
172
173#: utils/cpupower.c:78
174#, c-format
175msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
176msgstr ""
177
178#: utils/cpupower.c:79
179#, c-format
180msgid "cpupower --version\n"
181msgstr ""
182
183#: utils/cpupower.c:80
184#, c-format
185msgid "Supported subcommands are:\n"
186msgstr ""
187
188#: utils/cpupower.c:83
189#, c-format
190msgid ""
191"\n"
192"Some subcommands can make use of the -c cpulist option.\n"
193msgstr ""
194
195#: utils/cpupower.c:84
196#, c-format
197msgid "Look at the general cpupower manpage how to use it\n"
198msgstr ""
199
200#: utils/cpupower.c:85
201#, c-format
202msgid "and read up the subcommand's manpage whether it is supported.\n"
203msgstr ""
204
205#: utils/cpupower.c:86
206#, c-format
207msgid ""
208"\n"
209"Use cpupower help subcommand for getting help for above subcommands.\n"
210msgstr ""
211
212#: utils/cpupower.c:91
213#, c-format
214msgid "Report errors and bugs to %s, please.\n"
215msgstr "Per favore, comunicare errori e malfunzionamenti a %s.\n"
216
217#: utils/cpupower.c:114
218#, c-format
219msgid "Error parsing cpu list\n"
220msgstr ""
221
222#: utils/cpupower.c:172
223#, c-format
224msgid "Subcommand %s needs root privileges\n"
225msgstr ""
226
227#: utils/cpufreq-info.c:31
228#, c-format
229msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
230msgstr "Impossibile determinare il numero di CPU (%s: %s), assumo sia 1\n"
231
232#: utils/cpufreq-info.c:63
233#, c-format
234msgid ""
235" minimum CPU frequency - maximum CPU frequency - governor\n"
236msgstr ""
237" frequenza minima CPU - frequenza massima CPU - gestore\n"
238
239#: utils/cpufreq-info.c:151
240#, c-format
241msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
242msgstr ""
243
244#. P state changes via MSR are identified via cpuid 80000007
245#. on Intel and AMD, but we assume boost capable machines can do that
246#. if (cpuid_eax(0x80000000) >= 0x80000007
247#. && (cpuid_edx(0x80000007) & (1 << 7)))
248#.
249#: utils/cpufreq-info.c:161
250#, c-format
251msgid " boost state support: \n"
252msgstr ""
253
254#: utils/cpufreq-info.c:163
255#, c-format
256msgid " Supported: %s\n"
257msgstr ""
258
259#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
260msgid "yes"
261msgstr ""
262
263#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
264msgid "no"
265msgstr ""
266
267#: utils/cpufreq-info.c:164
268#, fuzzy, c-format
269msgid " Active: %s\n"
270msgstr " modulo %s\n"
271
272#: utils/cpufreq-info.c:177
273#, c-format
274msgid " Boost States: %d\n"
275msgstr ""
276
277#: utils/cpufreq-info.c:178
278#, c-format
279msgid " Total States: %d\n"
280msgstr ""
281
282#: utils/cpufreq-info.c:181
283#, c-format
284msgid " Pstate-Pb%d: %luMHz (boost state)\n"
285msgstr ""
286
287#: utils/cpufreq-info.c:184
288#, c-format
289msgid " Pstate-P%d: %luMHz\n"
290msgstr ""
291
292#: utils/cpufreq-info.c:211
293#, c-format
294msgid " no or unknown cpufreq driver is active on this CPU\n"
295msgstr " nessun modulo o modulo cpufreq sconosciuto per questa CPU\n"
296
297#: utils/cpufreq-info.c:213
298#, c-format
299msgid " driver: %s\n"
300msgstr " modulo %s\n"
301
302#: utils/cpufreq-info.c:219
303#, c-format
304msgid " CPUs which run at the same hardware frequency: "
305msgstr " CPU che operano alla stessa frequenza hardware: "
306
307#: utils/cpufreq-info.c:230
308#, c-format
309msgid " CPUs which need to have their frequency coordinated by software: "
310msgstr " CPU che è necessario siano coordinate dal software: "
311
312#: utils/cpufreq-info.c:241
313#, c-format
314msgid " maximum transition latency: "
315msgstr " latenza massima durante la transizione: "
316
317#: utils/cpufreq-info.c:247
318#, c-format
319msgid " hardware limits: "
320msgstr " limiti hardware: "
321
322#: utils/cpufreq-info.c:256
323#, c-format
324msgid " available frequency steps: "
325msgstr " frequenze disponibili: "
326
327#: utils/cpufreq-info.c:269
328#, c-format
329msgid " available cpufreq governors: "
330msgstr " gestori disponibili: "
331
332#: utils/cpufreq-info.c:280
333#, c-format
334msgid " current policy: frequency should be within "
335msgstr " gestore attuale: la frequenza deve mantenersi tra "
336
337#: utils/cpufreq-info.c:282
338#, c-format
339msgid " and "
340msgstr " e "
341
342#: utils/cpufreq-info.c:286
343#, c-format
344msgid ""
345"The governor \"%s\" may decide which speed to use\n"
346" within this range.\n"
347msgstr ""
348" Il gestore \"%s\" può decidere quale velocità usare\n"
349" in questo intervallo.\n"
350
351#: utils/cpufreq-info.c:293
352#, c-format
353msgid " current CPU frequency is "
354msgstr " la frequenza attuale della CPU è "
355
356#: utils/cpufreq-info.c:296
357#, c-format
358msgid " (asserted by call to hardware)"
359msgstr " (ottenuta da una chiamata diretta all'hardware)"
360
361#: utils/cpufreq-info.c:304
362#, c-format
363msgid " cpufreq stats: "
364msgstr " statistiche cpufreq:"
365
366#: utils/cpufreq-info.c:472
367#, fuzzy, c-format
368msgid "Usage: cpupower freqinfo [options]\n"
369msgstr "Uso: cpufreq-info [opzioni]\n"
370
371#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
372#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
373#, c-format
374msgid "Options:\n"
375msgstr "Opzioni:\n"
376
377#: utils/cpufreq-info.c:474
378#, fuzzy, c-format
379msgid " -e, --debug Prints out debug information [default]\n"
380msgstr " -e, --debug Mostra informazioni di debug\n"
381
382#: utils/cpufreq-info.c:475
383#, c-format
384msgid ""
385" -f, --freq Get frequency the CPU currently runs at, according\n"
386" to the cpufreq core *\n"
387msgstr ""
388" -f, --freq Mostra la frequenza attuale della CPU secondo\n"
389" il modulo cpufreq *\n"
390
391#: utils/cpufreq-info.c:477
392#, c-format
393msgid ""
394" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n"
395" it from hardware (only available to root) *\n"
396msgstr ""
397" -w, --hwfreq Mostra la frequenza attuale della CPU leggendola\n"
398" dall'hardware (disponibile solo per l'utente root) *\n"
399
400#: utils/cpufreq-info.c:479
401#, c-format
402msgid ""
403" -l, --hwlimits Determine the minimum and maximum CPU frequency "
404"allowed *\n"
405msgstr ""
406" -l, --hwlimits Determina le frequenze minima e massima possibili per "
407"la CPU *\n"
408
409#: utils/cpufreq-info.c:480
410#, c-format
411msgid " -d, --driver Determines the used cpufreq kernel driver *\n"
412msgstr ""
413" -d, --driver Determina il modulo cpufreq del kernel in uso *\n"
414
415#: utils/cpufreq-info.c:481
416#, c-format
417msgid " -p, --policy Gets the currently used cpufreq policy *\n"
418msgstr ""
419" -p, --policy Mostra il gestore cpufreq attualmente in uso *\n"
420
421#: utils/cpufreq-info.c:482
422#, c-format
423msgid " -g, --governors Determines available cpufreq governors *\n"
424msgstr " -g, --governors Determina i gestori cpufreq disponibili *\n"
425
426#: utils/cpufreq-info.c:483
427#, c-format
428msgid ""
429" -r, --related-cpus Determines which CPUs run at the same hardware "
430"frequency *\n"
431msgstr ""
432" -r, --related-cpus Determina quali CPU operano alla stessa frequenza *\n"
433
434#: utils/cpufreq-info.c:484
435#, c-format
436msgid ""
437" -a, --affected-cpus Determines which CPUs need to have their frequency\n"
438" coordinated by software *\n"
439msgstr ""
440" -a, --affected-cpus Determina quali CPU devono avere la frequenza\n"
441" coordinata dal software *\n"
442
443#: utils/cpufreq-info.c:486
444#, c-format
445msgid " -s, --stats Shows cpufreq statistics if available\n"
446msgstr " -s, --stats Mostra le statistiche se disponibili\n"
447
448#: utils/cpufreq-info.c:487
449#, c-format
450msgid ""
451" -y, --latency Determines the maximum latency on CPU frequency "
452"changes *\n"
453msgstr ""
454" -y, --latency Determina la latenza massima durante i cambi di "
455"frequenza *\n"
456
457#: utils/cpufreq-info.c:488
458#, c-format
459msgid " -b, --boost Checks for turbo or boost modes *\n"
460msgstr ""
461
462#: utils/cpufreq-info.c:489
463#, c-format
464msgid ""
465" -o, --proc Prints out information like provided by the /proc/"
466"cpufreq\n"
467" interface in 2.4. and early 2.6. kernels\n"
468msgstr ""
469" -o, --proc Stampa le informazioni come se provenissero dalla\n"
470" interfaccia cpufreq /proc/ presente nei kernel\n"
471" 2.4 ed i primi 2.6\n"
472
473#: utils/cpufreq-info.c:491
474#, c-format
475msgid ""
476" -m, --human human-readable output for the -f, -w, -s and -y "
477"parameters\n"
478msgstr ""
479" -m, --human formatta l'output delle opzioni -f, -w, -s e -y in "
480"maniera\n"
481" leggibile da un essere umano\n"
482
483#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
484#, c-format
485msgid " -h, --help Prints out this screen\n"
486msgstr " -h, --help Stampa questa schermata\n"
487
488#: utils/cpufreq-info.c:495
489#, c-format
490msgid ""
491"If no argument or only the -c, --cpu parameter is given, debug output about\n"
492"cpufreq is printed which is useful e.g. for reporting bugs.\n"
493msgstr ""
494"Se non viene specificata nessuna opzione o viene specificata solo l'opzione -"
495"c, --cpu,\n"
496"le informazioni di debug per cpufreq saranno utili ad esempio a riportare i "
497"bug.\n"
498
499#: utils/cpufreq-info.c:497
500#, c-format
501msgid ""
502"For the arguments marked with *, omitting the -c or --cpu argument is\n"
503"equivalent to setting it to zero\n"
504msgstr ""
505"Per le opzioni segnalate con *, omettere l'opzione -c o --cpu è come "
506"specificarla\n"
507"con il valore 0\n"
508
509#: utils/cpufreq-info.c:580
510#, c-format
511msgid ""
512"The argument passed to this tool can't be combined with passing a --cpu "
513"argument\n"
514msgstr ""
515"L'opzione specificata a questo programma non può essere combinata con --cpu\n"
516
517#: utils/cpufreq-info.c:596
518#, c-format
519msgid ""
520"You can't specify more than one --cpu parameter and/or\n"
521"more than one output-specific argument\n"
522msgstr ""
523"Non è possibile specificare più di una volta l'opzione --cpu e/o\n"
524"specificare più di un parametro di output specifico\n"
525
526#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
527#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
528#, c-format
529msgid "invalid or unknown argument\n"
530msgstr "opzione sconosciuta o non valida\n"
531
532#: utils/cpufreq-info.c:617
533#, c-format
534msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
535msgstr "impossibile analizzare la CPU %d poiché non sembra essere presente\n"
536
537#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
538#, c-format
539msgid "analyzing CPU %d:\n"
540msgstr "analisi della CPU %d:\n"
541
542#: utils/cpufreq-set.c:25
543#, fuzzy, c-format
544msgid "Usage: cpupower frequency-set [options]\n"
545msgstr "Uso: cpufreq-set [opzioni]\n"
546
547#: utils/cpufreq-set.c:27
548#, c-format
549msgid ""
550" -d FREQ, --min FREQ new minimum CPU frequency the governor may "
551"select\n"
552msgstr ""
553" -d FREQ, --min FREQ la nuova frequenza minima che il gestore cpufreq "
554"può scegliere\n"
555
556#: utils/cpufreq-set.c:28
557#, c-format
558msgid ""
559" -u FREQ, --max FREQ new maximum CPU frequency the governor may "
560"select\n"
561msgstr ""
562" -u FREQ, --max FREQ la nuova frequenza massima che il gestore cpufreq "
563"può scegliere\n"
564
565#: utils/cpufreq-set.c:29
566#, c-format
567msgid " -g GOV, --governor GOV new cpufreq governor\n"
568msgstr " -g GOV, --governor GOV nuovo gestore cpufreq\n"
569
570#: utils/cpufreq-set.c:30
571#, c-format
572msgid ""
573" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n"
574" governor to be available and loaded\n"
575msgstr ""
576" -f FREQ, --freq FREQ specifica la frequenza a cui impostare la CPU.\n"
577" È necessario che il gestore userspace sia "
578"disponibile e caricato\n"
579
580#: utils/cpufreq-set.c:32
581#, c-format
582msgid " -r, --related Switches all hardware-related CPUs\n"
583msgstr ""
584" -r, --related Modifica tutte le CPU coordinate dall'hardware\n"
585
586#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
587#, c-format
588msgid " -h, --help Prints out this screen\n"
589msgstr " -h, --help Stampa questa schermata\n"
590
591#: utils/cpufreq-set.c:35
592#, fuzzy, c-format
593msgid ""
594"Notes:\n"
595"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
596msgstr ""
597"Per le opzioni segnalate con *, omettere l'opzione -c o --cpu è come "
598"specificarla\n"
599"con il valore 0\n"
600
601#: utils/cpufreq-set.c:37
602#, fuzzy, c-format
603msgid ""
604"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
605"parameter\n"
606" except the -c CPU, --cpu CPU parameter\n"
607"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
608" by postfixing the value with the wanted unit name, without any space\n"
609" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
610msgstr ""
611"Note:\n"
612"1. Omettere l'opzione -c o --cpu è equivalente a impostarlo a 0\n"
613"2. l'opzione -f FREQ, --freq FREQ non può essere specificata con altre "
614"opzioni\n"
615" ad eccezione dell'opzione -c CPU o --cpu CPU\n"
616"3. le FREQuenze possono essere specuficate in Hz, kHz (default), MHz, GHz, "
617"or THz\n"
618" postponendo l'unità di misura al valore senza nessuno spazio fra loro\n"
619" (FREQuenza in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
620
621#: utils/cpufreq-set.c:57
622#, c-format
623msgid ""
624"Error setting new values. Common errors:\n"
625"- Do you have proper administration rights? (super-user?)\n"
626"- Is the governor you requested available and modprobed?\n"
627"- Trying to set an invalid policy?\n"
628"- Trying to set a specific frequency, but userspace governor is not "
629"available,\n"
630" for example because of hardware which cannot be set to a specific "
631"frequency\n"
632" or because the userspace governor isn't loaded?\n"
633msgstr ""
634"Si sono verificati degli errori impostando i nuovi valori.\n"
635"Alcuni errori comuni possono essere:\n"
636"- Hai i necessari diritti di amministrazione? (super-user?)\n"
637"- Il gestore che hai richiesto è disponibile e caricato?\n"
638"- Stai provando ad impostare una politica di gestione non valida?\n"
639"- Stai provando a impostare una specifica frequenza ma il gestore\n"
640" userspace non è disponibile, per esempio a causa dell'hardware\n"
641" che non supporta frequenze fisse o a causa del fatto che\n"
642" il gestore userspace non è caricato?\n"
643
644#: utils/cpufreq-set.c:170
645#, c-format
646msgid "wrong, unknown or unhandled CPU?\n"
647msgstr "CPU errata, sconosciuta o non gestita?\n"
648
649#: utils/cpufreq-set.c:302
650#, c-format
651msgid ""
652"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
653"-g/--governor parameters\n"
654msgstr ""
655"l'opzione -f/--freq non può venire combinata con i parametri\n"
656" -d/--min, -u/--max o -g/--governor\n"
657
658#: utils/cpufreq-set.c:308
659#, c-format
660msgid ""
661"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
662"-g/--governor must be passed\n"
663msgstr ""
664"Almeno una delle opzioni -f/--freq, -d/--min, -u/--max, e -g/--governor\n"
665"deve essere specificata\n"
666
667#: utils/cpufreq-set.c:347
668#, c-format
669msgid "Setting cpu: %d\n"
670msgstr ""
671
672#: utils/cpupower-set.c:22
673#, c-format
674msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
675msgstr ""
676
677#: utils/cpupower-set.c:24
678#, c-format
679msgid ""
680" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n"
681" Intel models [0-15], see manpage for details\n"
682msgstr ""
683
684#: utils/cpupower-set.c:26
685#, c-format
686msgid ""
687" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n"
688msgstr ""
689
690#: utils/cpupower-set.c:27
691#, c-format
692msgid ""
693" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler "
694"policy.\n"
695msgstr ""
696
697#: utils/cpupower-set.c:80
698#, c-format
699msgid "--perf-bias param out of range [0-%d]\n"
700msgstr ""
701
702#: utils/cpupower-set.c:91
703#, c-format
704msgid "--sched-mc param out of range [0-%d]\n"
705msgstr ""
706
707#: utils/cpupower-set.c:102
708#, c-format
709msgid "--sched-smt param out of range [0-%d]\n"
710msgstr ""
711
712#: utils/cpupower-set.c:121
713#, c-format
714msgid "Error setting sched-mc %s\n"
715msgstr ""
716
717#: utils/cpupower-set.c:127
718#, c-format
719msgid "Error setting sched-smt %s\n"
720msgstr ""
721
722#: utils/cpupower-set.c:146
723#, c-format
724msgid "Error setting perf-bias value on CPU %d\n"
725msgstr ""
726
727#: utils/cpupower-info.c:21
728#, c-format
729msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
730msgstr ""
731
732#: utils/cpupower-info.c:23
733#, c-format
734msgid ""
735" -b, --perf-bias Gets CPU's power vs performance policy on some\n"
736" Intel models [0-15], see manpage for details\n"
737msgstr ""
738
739#: utils/cpupower-info.c:25
740#, fuzzy, c-format
741msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n"
742msgstr ""
743" -p, --policy Mostra il gestore cpufreq attualmente in uso *\n"
744
745#: utils/cpupower-info.c:26
746#, c-format
747msgid ""
748" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n"
749msgstr ""
750
751#: utils/cpupower-info.c:28
752#, c-format
753msgid ""
754"\n"
755"Passing no option will show all info, by default only on core 0\n"
756msgstr ""
757
758#: utils/cpupower-info.c:102
759#, c-format
760msgid "System's multi core scheduler setting: "
761msgstr ""
762
763#. if sysfs file is missing it's: errno == ENOENT
764#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
765#, c-format
766msgid "not supported\n"
767msgstr ""
768
769#: utils/cpupower-info.c:111
770#, c-format
771msgid "System's thread sibling scheduler setting: "
772msgstr ""
773
774#: utils/cpupower-info.c:126
775#, c-format
776msgid "Intel's performance bias setting needs root privileges\n"
777msgstr ""
778
779#: utils/cpupower-info.c:128
780#, c-format
781msgid "System does not support Intel's performance bias setting\n"
782msgstr ""
783
784#: utils/cpupower-info.c:147
785#, c-format
786msgid "Could not read perf-bias value\n"
787msgstr ""
788
789#: utils/cpupower-info.c:150
790#, c-format
791msgid "perf-bias: %d\n"
792msgstr ""
793
794#: utils/cpuidle-info.c:28
795#, fuzzy, c-format
796msgid "Analyzing CPU %d:\n"
797msgstr "analisi della CPU %d:\n"
798
799#: utils/cpuidle-info.c:32
800#, c-format
801msgid "CPU %u: No idle states\n"
802msgstr ""
803
804#: utils/cpuidle-info.c:36
805#, c-format
806msgid "CPU %u: Can't read idle state info\n"
807msgstr ""
808
809#: utils/cpuidle-info.c:41
810#, c-format
811msgid "Could not determine max idle state %u\n"
812msgstr ""
813
814#: utils/cpuidle-info.c:46
815#, c-format
816msgid "Number of idle states: %d\n"
817msgstr ""
818
819#: utils/cpuidle-info.c:48
820#, fuzzy, c-format
821msgid "Available idle states:"
822msgstr " frequenze disponibili: "
823
824#: utils/cpuidle-info.c:71
825#, c-format
826msgid "Flags/Description: %s\n"
827msgstr ""
828
829#: utils/cpuidle-info.c:74
830#, c-format
831msgid "Latency: %lu\n"
832msgstr ""
833
834#: utils/cpuidle-info.c:76
835#, c-format
836msgid "Usage: %lu\n"
837msgstr ""
838
839#: utils/cpuidle-info.c:78
840#, c-format
841msgid "Duration: %llu\n"
842msgstr ""
843
844#: utils/cpuidle-info.c:90
845#, c-format
846msgid "Could not determine cpuidle driver\n"
847msgstr ""
848
849#: utils/cpuidle-info.c:94
850#, fuzzy, c-format
851msgid "CPUidle driver: %s\n"
852msgstr " modulo %s\n"
853
854#: utils/cpuidle-info.c:99
855#, c-format
856msgid "Could not determine cpuidle governor\n"
857msgstr ""
858
859#: utils/cpuidle-info.c:103
860#, c-format
861msgid "CPUidle governor: %s\n"
862msgstr ""
863
864#: utils/cpuidle-info.c:122
865#, c-format
866msgid "CPU %u: Can't read C-state info\n"
867msgstr ""
868
869#. printf("Cstates: %d\n", cstates);
870#: utils/cpuidle-info.c:127
871#, c-format
872msgid "active state: C0\n"
873msgstr ""
874
875#: utils/cpuidle-info.c:128
876#, c-format
877msgid "max_cstate: C%u\n"
878msgstr ""
879
880#: utils/cpuidle-info.c:129
881#, fuzzy, c-format
882msgid "maximum allowed latency: %lu usec\n"
883msgstr " latenza massima durante la transizione: "
884
885#: utils/cpuidle-info.c:130
886#, c-format
887msgid "states:\t\n"
888msgstr ""
889
890#: utils/cpuidle-info.c:132
891#, c-format
892msgid " C%d: type[C%d] "
893msgstr ""
894
895#: utils/cpuidle-info.c:134
896#, c-format
897msgid "promotion[--] demotion[--] "
898msgstr ""
899
900#: utils/cpuidle-info.c:135
901#, c-format
902msgid "latency[%03lu] "
903msgstr ""
904
905#: utils/cpuidle-info.c:137
906#, c-format
907msgid "usage[%08lu] "
908msgstr ""
909
910#: utils/cpuidle-info.c:139
911#, c-format
912msgid "duration[%020Lu] \n"
913msgstr ""
914
915#: utils/cpuidle-info.c:147
916#, fuzzy, c-format
917msgid "Usage: cpupower idleinfo [options]\n"
918msgstr "Uso: cpufreq-info [opzioni]\n"
919
920#: utils/cpuidle-info.c:149
921#, fuzzy, c-format
922msgid " -s, --silent Only show general C-state information\n"
923msgstr " -e, --debug Mostra informazioni di debug\n"
924
925#: utils/cpuidle-info.c:150
926#, fuzzy, c-format
927msgid ""
928" -o, --proc Prints out information like provided by the /proc/"
929"acpi/processor/*/power\n"
930" interface in older kernels\n"
931msgstr ""
932" -o, --proc Stampa le informazioni come se provenissero dalla\n"
933" interfaccia cpufreq /proc/ presente nei kernel\n"
934" 2.4 ed i primi 2.6\n"
935
936#: utils/cpuidle-info.c:209
937#, fuzzy, c-format
938msgid "You can't specify more than one output-specific argument\n"
939msgstr ""
940"Non è possibile specificare più di una volta l'opzione --cpu e/o\n"
941"specificare più di un parametro di output specifico\n"
942
943#~ msgid ""
944#~ " -c CPU, --cpu CPU CPU number which information shall be determined "
945#~ "about\n"
946#~ msgstr ""
947#~ " -c CPU, --cpu CPU Numero di CPU per la quale ottenere le "
948#~ "informazioni\n"
949
950#~ msgid ""
951#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be "
952#~ "modified\n"
953#~ msgstr ""
954#~ " -c CPU, --cpu CPU numero di CPU per la quale modificare le "
955#~ "impostazioni\n"
956
957#, fuzzy
958#~ msgid " CPUs which coordinate software frequency requirements: "
959#~ msgstr ""
960#~ " CPU per le quali e` necessario cambiare la frequenza "
961#~ "contemporaneamente: "
diff --git a/tools/power/cpupower/po/pt.po b/tools/power/cpupower/po/pt.po
new file mode 100644
index 00000000000..990f5267ffe
--- /dev/null
+++ b/tools/power/cpupower/po/pt.po
@@ -0,0 +1,957 @@
1# Brazilian Portuguese translations for cpufrequtils package
2# Copyright (C) 2008 THE cpufrequtils'S COPYRIGHT HOLDER
3# This file is distributed under the same license as the cpufrequtils package.
4# Claudio Eduardo <claudioeddy@gmail.com>, 2009.
5#
6#
7msgid ""
8msgstr ""
9"Project-Id-Version: cpufrequtils 004\n"
10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2011-03-08 17:03+0100\n"
12"PO-Revision-Date: 2008-06-14 22:16-0400\n"
13"Last-Translator: Claudio Eduardo <claudioeddy@gmail.com>\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
17
18#: utils/idle_monitor/nhm_idle.c:36
19msgid "Processor Core C3"
20msgstr ""
21
22#: utils/idle_monitor/nhm_idle.c:43
23msgid "Processor Core C6"
24msgstr ""
25
26#: utils/idle_monitor/nhm_idle.c:51
27msgid "Processor Package C3"
28msgstr ""
29
30#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
31msgid "Processor Package C6"
32msgstr ""
33
34#: utils/idle_monitor/snb_idle.c:33
35msgid "Processor Core C7"
36msgstr ""
37
38#: utils/idle_monitor/snb_idle.c:40
39msgid "Processor Package C2"
40msgstr ""
41
42#: utils/idle_monitor/snb_idle.c:47
43msgid "Processor Package C7"
44msgstr ""
45
46#: utils/idle_monitor/amd_fam14h_idle.c:56
47msgid "Package in sleep state (PC1 or deeper)"
48msgstr ""
49
50#: utils/idle_monitor/amd_fam14h_idle.c:63
51msgid "Processor Package C1"
52msgstr ""
53
54#: utils/idle_monitor/amd_fam14h_idle.c:77
55msgid "North Bridge P1 boolean counter (returns 0 or 1)"
56msgstr ""
57
58#: utils/idle_monitor/mperf_monitor.c:35
59msgid "Processor Core not idle"
60msgstr ""
61
62#: utils/idle_monitor/mperf_monitor.c:42
63msgid "Processor Core in an idle state"
64msgstr ""
65
66#: utils/idle_monitor/mperf_monitor.c:50
67msgid "Average Frequency (including boost) in MHz"
68msgstr ""
69
70#: utils/idle_monitor/cpupower-monitor.c:66
71#, c-format
72msgid ""
73"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
74"interval_sec | -c command ...]\n"
75msgstr ""
76
77#: utils/idle_monitor/cpupower-monitor.c:69
78#, c-format
79msgid ""
80"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
81"interval_sec | -c command ...]\n"
82msgstr ""
83
84#: utils/idle_monitor/cpupower-monitor.c:71
85#, c-format
86msgid "\t -v: be more verbose\n"
87msgstr ""
88
89#: utils/idle_monitor/cpupower-monitor.c:73
90#, c-format
91msgid "\t -h: print this help\n"
92msgstr ""
93
94#: utils/idle_monitor/cpupower-monitor.c:74
95#, c-format
96msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
97msgstr ""
98
99#: utils/idle_monitor/cpupower-monitor.c:75
100#, c-format
101msgid "\t -t: show CPU topology/hierarchy\n"
102msgstr ""
103
104#: utils/idle_monitor/cpupower-monitor.c:76
105#, c-format
106msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
107msgstr ""
108
109#: utils/idle_monitor/cpupower-monitor.c:77
110#, c-format
111msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
112msgstr ""
113
114#: utils/idle_monitor/cpupower-monitor.c:79
115#, c-format
116msgid ""
117"only one of: -t, -l, -m are allowed\n"
118"If none of them is passed,"
119msgstr ""
120
121#: utils/idle_monitor/cpupower-monitor.c:80
122#, c-format
123msgid " all supported monitors are shown\n"
124msgstr ""
125
126#: utils/idle_monitor/cpupower-monitor.c:197
127#, c-format
128msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
129msgstr ""
130
131#: utils/idle_monitor/cpupower-monitor.c:207
132#, c-format
133msgid " *is offline\n"
134msgstr ""
135
136#: utils/idle_monitor/cpupower-monitor.c:236
137#, c-format
138msgid "%s: max monitor name length (%d) exceeded\n"
139msgstr ""
140
141#: utils/idle_monitor/cpupower-monitor.c:250
142#, c-format
143msgid "No matching monitor found in %s, try -l option\n"
144msgstr ""
145
146#: utils/idle_monitor/cpupower-monitor.c:266
147#, c-format
148msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
149msgstr ""
150
151#: utils/idle_monitor/cpupower-monitor.c:319
152#, c-format
153msgid "%s took %.5f seconds and exited with status %d\n"
154msgstr ""
155
156#: utils/idle_monitor/cpupower-monitor.c:406
157#, c-format
158msgid "Cannot read number of available processors\n"
159msgstr ""
160
161#: utils/idle_monitor/cpupower-monitor.c:417
162#, c-format
163msgid "Available monitor %s needs root access\n"
164msgstr ""
165
166#: utils/idle_monitor/cpupower-monitor.c:428
167#, c-format
168msgid "No HW Cstate monitors found\n"
169msgstr ""
170
171#: utils/cpupower.c:78
172#, c-format
173msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
174msgstr ""
175
176#: utils/cpupower.c:79
177#, c-format
178msgid "cpupower --version\n"
179msgstr ""
180
181#: utils/cpupower.c:80
182#, c-format
183msgid "Supported subcommands are:\n"
184msgstr ""
185
186#: utils/cpupower.c:83
187#, c-format
188msgid ""
189"\n"
190"Some subcommands can make use of the -c cpulist option.\n"
191msgstr ""
192
193#: utils/cpupower.c:84
194#, c-format
195msgid "Look at the general cpupower manpage how to use it\n"
196msgstr ""
197
198#: utils/cpupower.c:85
199#, c-format
200msgid "and read up the subcommand's manpage whether it is supported.\n"
201msgstr ""
202
203#: utils/cpupower.c:86
204#, c-format
205msgid ""
206"\n"
207"Use cpupower help subcommand for getting help for above subcommands.\n"
208msgstr ""
209
210#: utils/cpupower.c:91
211#, c-format
212msgid "Report errors and bugs to %s, please.\n"
213msgstr "Reporte erros e bugs para %s, por favor.\n"
214
215#: utils/cpupower.c:114
216#, c-format
217msgid "Error parsing cpu list\n"
218msgstr ""
219
220#: utils/cpupower.c:172
221#, c-format
222msgid "Subcommand %s needs root privileges\n"
223msgstr ""
224
225#: utils/cpufreq-info.c:31
226#, c-format
227msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
228msgstr "Não foi possível contar o número de CPUs (%s: %s), assumindo 1\n"
229
230#: utils/cpufreq-info.c:63
231#, c-format
232msgid ""
233" minimum CPU frequency - maximum CPU frequency - governor\n"
234msgstr ""
235" frequência mínina do CPU - frequência máxima do CPU - "
236"regulador\n"
237
238#: utils/cpufreq-info.c:151
239#, c-format
240msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
241msgstr ""
242
243#. P state changes via MSR are identified via cpuid 80000007
244#. on Intel and AMD, but we assume boost capable machines can do that
245#. if (cpuid_eax(0x80000000) >= 0x80000007
246#. && (cpuid_edx(0x80000007) & (1 << 7)))
247#.
248#: utils/cpufreq-info.c:161
249#, c-format
250msgid " boost state support: \n"
251msgstr ""
252
253#: utils/cpufreq-info.c:163
254#, c-format
255msgid " Supported: %s\n"
256msgstr ""
257
258#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
259msgid "yes"
260msgstr ""
261
262#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
263msgid "no"
264msgstr ""
265
266#: utils/cpufreq-info.c:164
267#, fuzzy, c-format
268msgid " Active: %s\n"
269msgstr " driver: %s\n"
270
271#: utils/cpufreq-info.c:177
272#, c-format
273msgid " Boost States: %d\n"
274msgstr ""
275
276#: utils/cpufreq-info.c:178
277#, c-format
278msgid " Total States: %d\n"
279msgstr ""
280
281#: utils/cpufreq-info.c:181
282#, c-format
283msgid " Pstate-Pb%d: %luMHz (boost state)\n"
284msgstr ""
285
286#: utils/cpufreq-info.c:184
287#, c-format
288msgid " Pstate-P%d: %luMHz\n"
289msgstr ""
290
291#: utils/cpufreq-info.c:211
292#, c-format
293msgid " no or unknown cpufreq driver is active on this CPU\n"
294msgstr " nenhum ou driver do cpufreq deconhecido está ativo nesse CPU\n"
295
296#: utils/cpufreq-info.c:213
297#, c-format
298msgid " driver: %s\n"
299msgstr " driver: %s\n"
300
301#: utils/cpufreq-info.c:219
302#, c-format
303msgid " CPUs which run at the same hardware frequency: "
304msgstr " CPUs que rodam na mesma frequência de hardware: "
305
306#: utils/cpufreq-info.c:230
307#, c-format
308msgid " CPUs which need to have their frequency coordinated by software: "
309msgstr " CPUs que precisam ter suas frequências coordenadas por software: "
310
311#: utils/cpufreq-info.c:241
312#, c-format
313msgid " maximum transition latency: "
314msgstr " maior latência de transição: "
315
316#: utils/cpufreq-info.c:247
317#, c-format
318msgid " hardware limits: "
319msgstr " limites do hardware: "
320
321#: utils/cpufreq-info.c:256
322#, c-format
323msgid " available frequency steps: "
324msgstr " níveis de frequência disponíveis: "
325
326#: utils/cpufreq-info.c:269
327#, c-format
328msgid " available cpufreq governors: "
329msgstr " reguladores do cpufreq disponíveis: "
330
331#: utils/cpufreq-info.c:280
332#, c-format
333msgid " current policy: frequency should be within "
334msgstr " política de frequência atual deve estar entre "
335
336#: utils/cpufreq-info.c:282
337#, c-format
338msgid " and "
339msgstr " e "
340
341#: utils/cpufreq-info.c:286
342#, c-format
343msgid ""
344"The governor \"%s\" may decide which speed to use\n"
345" within this range.\n"
346msgstr ""
347"O regulador \"%s\" deve decidir qual velocidade usar\n"
348" dentro desse limite.\n"
349
350#: utils/cpufreq-info.c:293
351#, c-format
352msgid " current CPU frequency is "
353msgstr " frequência atual do CPU é "
354
355#: utils/cpufreq-info.c:296
356#, c-format
357msgid " (asserted by call to hardware)"
358msgstr " (declarado por chamada ao hardware)"
359
360#: utils/cpufreq-info.c:304
361#, c-format
362msgid " cpufreq stats: "
363msgstr " status do cpufreq: "
364
365#: utils/cpufreq-info.c:472
366#, fuzzy, c-format
367msgid "Usage: cpupower freqinfo [options]\n"
368msgstr "Uso: cpufreq-info [opções]\n"
369
370#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
371#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
372#, c-format
373msgid "Options:\n"
374msgstr "Opções:\n"
375
376#: utils/cpufreq-info.c:474
377#, fuzzy, c-format
378msgid " -e, --debug Prints out debug information [default]\n"
379msgstr " -e, --debug Mostra informação de debug\n"
380
381#: utils/cpufreq-info.c:475
382#, c-format
383msgid ""
384" -f, --freq Get frequency the CPU currently runs at, according\n"
385" to the cpufreq core *\n"
386msgstr ""
387" -f, --freq Obtem a frequência na qual o CPU roda no momento, de "
388"acordo\n"
389" com o núcleo do cpufreq *\n"
390
391#: utils/cpufreq-info.c:477
392#, c-format
393msgid ""
394" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n"
395" it from hardware (only available to root) *\n"
396msgstr ""
397" -w, --hwfreq Obtem a frequência na qual o CPU está operando no "
398"momento,\n"
399" através de leitura no hardware (disponível somente "
400"para root) *\n"
401
402#: utils/cpufreq-info.c:479
403#, c-format
404msgid ""
405" -l, --hwlimits Determine the minimum and maximum CPU frequency "
406"allowed *\n"
407msgstr ""
408" -l, --hwlimits Determina a frequência mínima e máxima do CPU "
409"permitida *\n"
410
411#: utils/cpufreq-info.c:480
412#, c-format
413msgid " -d, --driver Determines the used cpufreq kernel driver *\n"
414msgstr ""
415" -d, --driver Determina o driver do kernel do cpufreq usado *\n"
416
417#: utils/cpufreq-info.c:481
418#, c-format
419msgid " -p, --policy Gets the currently used cpufreq policy *\n"
420msgstr ""
421"--p, --policy Obtem a política do cpufreq em uso no momento *\n"
422
423#: utils/cpufreq-info.c:482
424#, c-format
425msgid " -g, --governors Determines available cpufreq governors *\n"
426msgstr ""
427" -g, --governors Determina reguladores do cpufreq disponíveis *\n"
428
429#: utils/cpufreq-info.c:483
430#, c-format
431msgid ""
432" -r, --related-cpus Determines which CPUs run at the same hardware "
433"frequency *\n"
434msgstr ""
435" -r, --related-cpus Determina quais CPUs rodam na mesma frequência de "
436"hardware *\n"
437
438#: utils/cpufreq-info.c:484
439#, c-format
440msgid ""
441" -a, --affected-cpus Determines which CPUs need to have their frequency\n"
442" coordinated by software *\n"
443msgstr ""
444" -a, --affected-cpus Determina quais CPUs precisam ter suas frequências\n"
445" coordenadas por software *\n"
446
447#: utils/cpufreq-info.c:486
448#, c-format
449msgid " -s, --stats Shows cpufreq statistics if available\n"
450msgstr " -s, --stats Mostra estatísticas do cpufreq se disponíveis\n"
451
452#: utils/cpufreq-info.c:487
453#, c-format
454msgid ""
455" -y, --latency Determines the maximum latency on CPU frequency "
456"changes *\n"
457msgstr ""
458" -y, --latency Determina a latência máxima nas trocas de frequência "
459"do CPU *\n"
460
461#: utils/cpufreq-info.c:488
462#, c-format
463msgid " -b, --boost Checks for turbo or boost modes *\n"
464msgstr ""
465
466#: utils/cpufreq-info.c:489
467#, c-format
468msgid ""
469" -o, --proc Prints out information like provided by the /proc/"
470"cpufreq\n"
471" interface in 2.4. and early 2.6. kernels\n"
472msgstr ""
473" -o, --proc Mostra informação do tipo provida pela interface /"
474"proc/cpufreq\n"
475" em kernels 2.4. e mais recentes 2.6\n"
476
477#: utils/cpufreq-info.c:491
478#, c-format
479msgid ""
480" -m, --human human-readable output for the -f, -w, -s and -y "
481"parameters\n"
482msgstr ""
483" -m, --human saída legível para humanos para os parâmetros -f, -w, "
484"-s e -y\n"
485
486#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152
487#, c-format
488msgid " -h, --help Prints out this screen\n"
489msgstr " -h, --help Imprime essa tela\n"
490
491#: utils/cpufreq-info.c:495
492#, c-format
493msgid ""
494"If no argument or only the -c, --cpu parameter is given, debug output about\n"
495"cpufreq is printed which is useful e.g. for reporting bugs.\n"
496msgstr ""
497"Se nenhum argumento ou somente o parâmetro -c, --cpu é dado, informação de "
498"debug sobre\n"
499"o cpufreq é mostrada, o que é útil por exemplo para reportar bugs.\n"
500
501#: utils/cpufreq-info.c:497
502#, c-format
503msgid ""
504"For the arguments marked with *, omitting the -c or --cpu argument is\n"
505"equivalent to setting it to zero\n"
506msgstr ""
507"Para os argumentos marcados com *, omitir o argumento -c ou --cpu é\n"
508"equivalente a setá-lo como zero\n"
509
510#: utils/cpufreq-info.c:580
511#, c-format
512msgid ""
513"The argument passed to this tool can't be combined with passing a --cpu "
514"argument\n"
515msgstr ""
516"O argumento usado pra essa ferramenta não pode ser combinado com um "
517"argumento --cpu\n"
518
519#: utils/cpufreq-info.c:596
520#, c-format
521msgid ""
522"You can't specify more than one --cpu parameter and/or\n"
523"more than one output-specific argument\n"
524msgstr ""
525"Você não pode especificar mais do que um parâmetro --cpu e/ou\n"
526"mais do que um argumento de saída específico\n"
527
528#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
529#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
530#, c-format
531msgid "invalid or unknown argument\n"
532msgstr "argumento inválido ou desconhecido\n"
533
534#: utils/cpufreq-info.c:617
535#, c-format
536msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
537msgstr ""
538"não foi possível analisar o CPU % já que o mesmo parece não estar presente\n"
539
540#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
541#, c-format
542msgid "analyzing CPU %d:\n"
543msgstr "analisando o CPU %d:\n"
544
545#: utils/cpufreq-set.c:25
546#, fuzzy, c-format
547msgid "Usage: cpupower frequency-set [options]\n"
548msgstr "Uso: cpufreq-set [opções]\n"
549
550#: utils/cpufreq-set.c:27
551#, c-format
552msgid ""
553" -d FREQ, --min FREQ new minimum CPU frequency the governor may "
554"select\n"
555msgstr ""
556" -d FREQ, --min FREQ nova frequência mínima do CPU que o regulador "
557"deve selecionar\n"
558
559#: utils/cpufreq-set.c:28
560#, c-format
561msgid ""
562" -u FREQ, --max FREQ new maximum CPU frequency the governor may "
563"select\n"
564msgstr ""
565" -u FREQ, --max FREQ nova frequência máxima do CPU que o regulador "
566"deve escolher\n"
567
568#: utils/cpufreq-set.c:29
569#, c-format
570msgid " -g GOV, --governor GOV new cpufreq governor\n"
571msgstr " -g GOV, --governor GOV novo regulador do cpufreq\n"
572
573#: utils/cpufreq-set.c:30
574#, c-format
575msgid ""
576" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n"
577" governor to be available and loaded\n"
578msgstr ""
579" -f FREQ, --freq FREQ frequência específica para ser setada. Necessita "
580"que o regulador em\n"
581" nível de usuário esteja disponível e carregado\n"
582
583#: utils/cpufreq-set.c:32
584#, c-format
585msgid " -r, --related Switches all hardware-related CPUs\n"
586msgstr ""
587" -r, --related Modifica todos os CPUs relacionados ao hardware\n"
588
589#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
590#, c-format
591msgid " -h, --help Prints out this screen\n"
592msgstr " -h, --help Mostra essa tela\n"
593
594#: utils/cpufreq-set.c:35
595#, fuzzy, c-format
596msgid ""
597"Notes:\n"
598"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
599msgstr ""
600"Para os argumentos marcados com *, omitir o argumento -c ou --cpu é\n"
601"equivalente a setá-lo como zero\n"
602
603#: utils/cpufreq-set.c:37
604#, fuzzy, c-format
605msgid ""
606"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other "
607"parameter\n"
608" except the -c CPU, --cpu CPU parameter\n"
609"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n"
610" by postfixing the value with the wanted unit name, without any space\n"
611" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
612msgstr ""
613"Notas:\n"
614"1. Omitir o argumento -c or --cpu é equivalente a setá-lo como zero\n"
615"2. O parâmetro -f FREQ, --freq FREQ não pode ser combinado com qualquer "
616"outro parâmetro\n"
617" exceto com o parâmetro -c CPU, --cpu CPU\n"
618"3. FREQuências podem ser usadas em Hz, kHz (padrão), MHz, GHz, o THz\n"
619" colocando o nome desejado da unidade após o valor, sem qualquer espaço\n"
620" (FREQuência em kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n"
621
622#: utils/cpufreq-set.c:57
623#, c-format
624msgid ""
625"Error setting new values. Common errors:\n"
626"- Do you have proper administration rights? (super-user?)\n"
627"- Is the governor you requested available and modprobed?\n"
628"- Trying to set an invalid policy?\n"
629"- Trying to set a specific frequency, but userspace governor is not "
630"available,\n"
631" for example because of hardware which cannot be set to a specific "
632"frequency\n"
633" or because the userspace governor isn't loaded?\n"
634msgstr ""
635"Erro ao setar novos valores. Erros comuns:\n"
636"- Você tem direitos administrativos necessários? (super-usuário?)\n"
637"- O regulador que você requesitou está disponível e foi \"modprobed\"?\n"
638"- Tentando setar uma política inválida?\n"
639"- Tentando setar uma frequência específica, mas o regulador em nível de "
640"usuário não está disponível,\n"
641" por exemplo devido ao hardware que não pode ser setado pra uma frequência "
642"específica\n"
643" ou porque o regulador em nível de usuário não foi carregado?\n"
644
645#: utils/cpufreq-set.c:170
646#, c-format
647msgid "wrong, unknown or unhandled CPU?\n"
648msgstr "CPU errado, desconhecido ou inesperado?\n"
649
650#: utils/cpufreq-set.c:302
651#, c-format
652msgid ""
653"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
654"-g/--governor parameters\n"
655msgstr ""
656"o parâmetro -f/--freq não pode ser combinado com os parâmetros -d/--min, -"
657"u/--max ou\n"
658"-g/--governor\n"
659
660#: utils/cpufreq-set.c:308
661#, c-format
662msgid ""
663"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
664"-g/--governor must be passed\n"
665msgstr ""
666"Pelo menos um parâmetro entre -f/--freq, -d/--min, -u/--max, e\n"
667"-g/--governor deve ser usado\n"
668
669#: utils/cpufreq-set.c:347
670#, c-format
671msgid "Setting cpu: %d\n"
672msgstr ""
673
674#: utils/cpupower-set.c:22
675#, c-format
676msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
677msgstr ""
678
679#: utils/cpupower-set.c:24
680#, c-format
681msgid ""
682" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n"
683" Intel models [0-15], see manpage for details\n"
684msgstr ""
685
686#: utils/cpupower-set.c:26
687#, c-format
688msgid ""
689" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n"
690msgstr ""
691
692#: utils/cpupower-set.c:27
693#, c-format
694msgid ""
695" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler "
696"policy.\n"
697msgstr ""
698
699#: utils/cpupower-set.c:80
700#, c-format
701msgid "--perf-bias param out of range [0-%d]\n"
702msgstr ""
703
704#: utils/cpupower-set.c:91
705#, c-format
706msgid "--sched-mc param out of range [0-%d]\n"
707msgstr ""
708
709#: utils/cpupower-set.c:102
710#, c-format
711msgid "--sched-smt param out of range [0-%d]\n"
712msgstr ""
713
714#: utils/cpupower-set.c:121
715#, c-format
716msgid "Error setting sched-mc %s\n"
717msgstr ""
718
719#: utils/cpupower-set.c:127
720#, c-format
721msgid "Error setting sched-smt %s\n"
722msgstr ""
723
724#: utils/cpupower-set.c:146
725#, c-format
726msgid "Error setting perf-bias value on CPU %d\n"
727msgstr ""
728
729#: utils/cpupower-info.c:21
730#, c-format
731msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
732msgstr ""
733
734#: utils/cpupower-info.c:23
735#, c-format
736msgid ""
737" -b, --perf-bias Gets CPU's power vs performance policy on some\n"
738" Intel models [0-15], see manpage for details\n"
739msgstr ""
740
741#: utils/cpupower-info.c:25
742#, fuzzy, c-format
743msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n"
744msgstr ""
745"--p, --policy Obtem a política do cpufreq em uso no momento *\n"
746
747#: utils/cpupower-info.c:26
748#, c-format
749msgid ""
750" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n"
751msgstr ""
752
753#: utils/cpupower-info.c:28
754#, c-format
755msgid ""
756"\n"
757"Passing no option will show all info, by default only on core 0\n"
758msgstr ""
759
760#: utils/cpupower-info.c:102
761#, c-format
762msgid "System's multi core scheduler setting: "
763msgstr ""
764
765#. if sysfs file is missing it's: errno == ENOENT
766#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
767#, c-format
768msgid "not supported\n"
769msgstr ""
770
771#: utils/cpupower-info.c:111
772#, c-format
773msgid "System's thread sibling scheduler setting: "
774msgstr ""
775
776#: utils/cpupower-info.c:126
777#, c-format
778msgid "Intel's performance bias setting needs root privileges\n"
779msgstr ""
780
781#: utils/cpupower-info.c:128
782#, c-format
783msgid "System does not support Intel's performance bias setting\n"
784msgstr ""
785
786#: utils/cpupower-info.c:147
787#, c-format
788msgid "Could not read perf-bias value\n"
789msgstr ""
790
791#: utils/cpupower-info.c:150
792#, c-format
793msgid "perf-bias: %d\n"
794msgstr ""
795
796#: utils/cpuidle-info.c:28
797#, fuzzy, c-format
798msgid "Analyzing CPU %d:\n"
799msgstr "analisando o CPU %d:\n"
800
801#: utils/cpuidle-info.c:32
802#, c-format
803msgid "CPU %u: No idle states\n"
804msgstr ""
805
806#: utils/cpuidle-info.c:36
807#, c-format
808msgid "CPU %u: Can't read idle state info\n"
809msgstr ""
810
811#: utils/cpuidle-info.c:41
812#, c-format
813msgid "Could not determine max idle state %u\n"
814msgstr ""
815
816#: utils/cpuidle-info.c:46
817#, c-format
818msgid "Number of idle states: %d\n"
819msgstr ""
820
821#: utils/cpuidle-info.c:48
822#, fuzzy, c-format
823msgid "Available idle states:"
824msgstr " níveis de frequência disponíveis: "
825
826#: utils/cpuidle-info.c:71
827#, c-format
828msgid "Flags/Description: %s\n"
829msgstr ""
830
831#: utils/cpuidle-info.c:74
832#, c-format
833msgid "Latency: %lu\n"
834msgstr ""
835
836#: utils/cpuidle-info.c:76
837#, c-format
838msgid "Usage: %lu\n"
839msgstr ""
840
841#: utils/cpuidle-info.c:78
842#, c-format
843msgid "Duration: %llu\n"
844msgstr ""
845
846#: utils/cpuidle-info.c:90
847#, c-format
848msgid "Could not determine cpuidle driver\n"
849msgstr ""
850
851#: utils/cpuidle-info.c:94
852#, fuzzy, c-format
853msgid "CPUidle driver: %s\n"
854msgstr " driver: %s\n"
855
856#: utils/cpuidle-info.c:99
857#, c-format
858msgid "Could not determine cpuidle governor\n"
859msgstr ""
860
861#: utils/cpuidle-info.c:103
862#, c-format
863msgid "CPUidle governor: %s\n"
864msgstr ""
865
866#: utils/cpuidle-info.c:122
867#, c-format
868msgid "CPU %u: Can't read C-state info\n"
869msgstr ""
870
871#. printf("Cstates: %d\n", cstates);
872#: utils/cpuidle-info.c:127
873#, c-format
874msgid "active state: C0\n"
875msgstr ""
876
877#: utils/cpuidle-info.c:128
878#, c-format
879msgid "max_cstate: C%u\n"
880msgstr ""
881
882#: utils/cpuidle-info.c:129
883#, fuzzy, c-format
884msgid "maximum allowed latency: %lu usec\n"
885msgstr " maior latência de transição: "
886
887#: utils/cpuidle-info.c:130
888#, c-format
889msgid "states:\t\n"
890msgstr ""
891
892#: utils/cpuidle-info.c:132
893#, c-format
894msgid " C%d: type[C%d] "
895msgstr ""
896
897#: utils/cpuidle-info.c:134
898#, c-format
899msgid "promotion[--] demotion[--] "
900msgstr ""
901
902#: utils/cpuidle-info.c:135
903#, c-format
904msgid "latency[%03lu] "
905msgstr ""
906
907#: utils/cpuidle-info.c:137
908#, c-format
909msgid "usage[%08lu] "
910msgstr ""
911
912#: utils/cpuidle-info.c:139
913#, c-format
914msgid "duration[%020Lu] \n"
915msgstr ""
916
917#: utils/cpuidle-info.c:147
918#, fuzzy, c-format
919msgid "Usage: cpupower idleinfo [options]\n"
920msgstr "Uso: cpufreq-info [opções]\n"
921
922#: utils/cpuidle-info.c:149
923#, fuzzy, c-format
924msgid " -s, --silent Only show general C-state information\n"
925msgstr " -e, --debug Mostra informação de debug\n"
926
927#: utils/cpuidle-info.c:150
928#, fuzzy, c-format
929msgid ""
930" -o, --proc Prints out information like provided by the /proc/"
931"acpi/processor/*/power\n"
932" interface in older kernels\n"
933msgstr ""
934" -o, --proc Mostra informação do tipo provida pela interface /"
935"proc/cpufreq\n"
936" em kernels 2.4. e mais recentes 2.6\n"
937
938#: utils/cpuidle-info.c:209
939#, fuzzy, c-format
940msgid "You can't specify more than one output-specific argument\n"
941msgstr ""
942"Você não pode especificar mais do que um parâmetro --cpu e/ou\n"
943"mais do que um argumento de saída específico\n"
944
945#~ msgid ""
946#~ " -c CPU, --cpu CPU CPU number which information shall be determined "
947#~ "about\n"
948#~ msgstr ""
949#~ " -c CPU, --cpu CPU número do CPU sobre o qual as inforções devem ser "
950#~ "determinadas\n"
951
952#~ msgid ""
953#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be "
954#~ "modified\n"
955#~ msgstr ""
956#~ " -c CPU, --cpu CPU número do CPU onde as configurações do cpufreq "
957#~ "vão ser modificadas\n"
diff --git a/tools/power/cpupower/utils/builtin.h b/tools/power/cpupower/utils/builtin.h
new file mode 100644
index 00000000000..c10496fbe3c
--- /dev/null
+++ b/tools/power/cpupower/utils/builtin.h
@@ -0,0 +1,11 @@
1#ifndef BUILTIN_H
2#define BUILTIN_H
3
4extern int cmd_set(int argc, const char **argv);
5extern int cmd_info(int argc, const char **argv);
6extern int cmd_freq_set(int argc, const char **argv);
7extern int cmd_freq_info(int argc, const char **argv);
8extern int cmd_idle_info(int argc, const char **argv);
9extern int cmd_monitor(int argc, const char **argv);
10
11#endif
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
new file mode 100644
index 00000000000..28953c9a7bd
--- /dev/null
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -0,0 +1,668 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7
8#include <unistd.h>
9#include <stdio.h>
10#include <errno.h>
11#include <stdlib.h>
12#include <string.h>
13
14#include <getopt.h>
15
16#include "cpufreq.h"
17#include "helpers/helpers.h"
18#include "helpers/bitmask.h"
19
20#define LINE_LEN 10
21
22static unsigned int count_cpus(void)
23{
24 FILE *fp;
25 char value[LINE_LEN];
26 unsigned int ret = 0;
27 unsigned int cpunr = 0;
28
29 fp = fopen("/proc/stat", "r");
30 if (!fp) {
31 printf(_("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno));
32 return 1;
33 }
34
35 while (!feof(fp)) {
36 if (!fgets(value, LINE_LEN, fp))
37 continue;
38 value[LINE_LEN - 1] = '\0';
39 if (strlen(value) < (LINE_LEN - 2))
40 continue;
41 if (strstr(value, "cpu "))
42 continue;
43 if (sscanf(value, "cpu%d ", &cpunr) != 1)
44 continue;
45 if (cpunr > ret)
46 ret = cpunr;
47 }
48 fclose(fp);
49
50 /* cpu count starts from 0, on error return 1 (UP) */
51 return ret + 1;
52}
53
54
55static void proc_cpufreq_output(void)
56{
57 unsigned int cpu, nr_cpus;
58 struct cpufreq_policy *policy;
59 unsigned int min_pctg = 0;
60 unsigned int max_pctg = 0;
61 unsigned long min, max;
62
63 printf(_(" minimum CPU frequency - maximum CPU frequency - governor\n"));
64
65 nr_cpus = count_cpus();
66 for (cpu = 0; cpu < nr_cpus; cpu++) {
67 policy = cpufreq_get_policy(cpu);
68 if (!policy)
69 continue;
70
71 if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
72 max = 0;
73 } else {
74 min_pctg = (policy->min * 100) / max;
75 max_pctg = (policy->max * 100) / max;
76 }
77 printf("CPU%3d %9lu kHz (%3d %%) - %9lu kHz (%3d %%) - %s\n",
78 cpu , policy->min, max ? min_pctg : 0, policy->max,
79 max ? max_pctg : 0, policy->governor);
80
81 cpufreq_put_policy(policy);
82 }
83}
84
85static void print_speed(unsigned long speed)
86{
87 unsigned long tmp;
88
89 if (speed > 1000000) {
90 tmp = speed % 10000;
91 if (tmp >= 5000)
92 speed += 10000;
93 printf("%u.%02u GHz", ((unsigned int) speed/1000000),
94 ((unsigned int) (speed%1000000)/10000));
95 } else if (speed > 100000) {
96 tmp = speed % 1000;
97 if (tmp >= 500)
98 speed += 1000;
99 printf("%u MHz", ((unsigned int) speed / 1000));
100 } else if (speed > 1000) {
101 tmp = speed % 100;
102 if (tmp >= 50)
103 speed += 100;
104 printf("%u.%01u MHz", ((unsigned int) speed/1000),
105 ((unsigned int) (speed%1000)/100));
106 } else
107 printf("%lu kHz", speed);
108
109 return;
110}
111
112static void print_duration(unsigned long duration)
113{
114 unsigned long tmp;
115
116 if (duration > 1000000) {
117 tmp = duration % 10000;
118 if (tmp >= 5000)
119 duration += 10000;
120 printf("%u.%02u ms", ((unsigned int) duration/1000000),
121 ((unsigned int) (duration%1000000)/10000));
122 } else if (duration > 100000) {
123 tmp = duration % 1000;
124 if (tmp >= 500)
125 duration += 1000;
126 printf("%u us", ((unsigned int) duration / 1000));
127 } else if (duration > 1000) {
128 tmp = duration % 100;
129 if (tmp >= 50)
130 duration += 100;
131 printf("%u.%01u us", ((unsigned int) duration/1000),
132 ((unsigned int) (duration%1000)/100));
133 } else
134 printf("%lu ns", duration);
135
136 return;
137}
138
139/* --boost / -b */
140
141static int get_boost_mode(unsigned int cpu)
142{
143 int support, active, b_states = 0, ret, pstate_no, i;
144 /* ToDo: Make this more global */
145 unsigned long pstates[MAX_HW_PSTATES] = {0,};
146
147 if (cpupower_cpu_info.vendor != X86_VENDOR_AMD &&
148 cpupower_cpu_info.vendor != X86_VENDOR_INTEL)
149 return 0;
150
151 ret = cpufreq_has_boost_support(cpu, &support, &active, &b_states);
152 if (ret) {
153 printf(_("Error while evaluating Boost Capabilities"
154 " on CPU %d -- are you root?\n"), cpu);
155 return ret;
156 }
157 /* P state changes via MSR are identified via cpuid 80000007
158 on Intel and AMD, but we assume boost capable machines can do that
159 if (cpuid_eax(0x80000000) >= 0x80000007
160 && (cpuid_edx(0x80000007) & (1 << 7)))
161 */
162
163 printf(_(" boost state support:\n"));
164
165 printf(_(" Supported: %s\n"), support ? _("yes") : _("no"));
166 printf(_(" Active: %s\n"), active ? _("yes") : _("no"));
167
168 if (cpupower_cpu_info.vendor == X86_VENDOR_AMD &&
169 cpupower_cpu_info.family >= 0x10) {
170 ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states,
171 pstates, &pstate_no);
172 if (ret)
173 return ret;
174
175 printf(_(" Boost States: %d\n"), b_states);
176 printf(_(" Total States: %d\n"), pstate_no);
177 for (i = 0; i < pstate_no; i++) {
178 if (i < b_states)
179 printf(_(" Pstate-Pb%d: %luMHz (boost state)"
180 "\n"), i, pstates[i]);
181 else
182 printf(_(" Pstate-P%d: %luMHz\n"),
183 i - b_states, pstates[i]);
184 }
185 } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO) {
186 double bclk;
187 unsigned long long intel_turbo_ratio = 0;
188 unsigned int ratio;
189
190 /* Any way to autodetect this ? */
191 if (cpupower_cpu_info.caps & CPUPOWER_CAP_IS_SNB)
192 bclk = 100.00;
193 else
194 bclk = 133.33;
195 intel_turbo_ratio = msr_intel_get_turbo_ratio(cpu);
196 dprint (" Ratio: 0x%llx - bclk: %f\n",
197 intel_turbo_ratio, bclk);
198
199 ratio = (intel_turbo_ratio >> 24) & 0xFF;
200 if (ratio)
201 printf(_(" %.0f MHz max turbo 4 active cores\n"),
202 ratio * bclk);
203
204 ratio = (intel_turbo_ratio >> 16) & 0xFF;
205 if (ratio)
206 printf(_(" %.0f MHz max turbo 3 active cores\n"),
207 ratio * bclk);
208
209 ratio = (intel_turbo_ratio >> 8) & 0xFF;
210 if (ratio)
211 printf(_(" %.0f MHz max turbo 2 active cores\n"),
212 ratio * bclk);
213
214 ratio = (intel_turbo_ratio >> 0) & 0xFF;
215 if (ratio)
216 printf(_(" %.0f MHz max turbo 1 active cores\n"),
217 ratio * bclk);
218 }
219 return 0;
220}
221
222static void debug_output_one(unsigned int cpu)
223{
224 char *driver;
225 struct cpufreq_affected_cpus *cpus;
226 struct cpufreq_available_frequencies *freqs;
227 unsigned long min, max, freq_kernel, freq_hardware;
228 unsigned long total_trans, latency;
229 unsigned long long total_time;
230 struct cpufreq_policy *policy;
231 struct cpufreq_available_governors *governors;
232 struct cpufreq_stats *stats;
233
234 if (cpufreq_cpu_exists(cpu))
235 return;
236
237 freq_kernel = cpufreq_get_freq_kernel(cpu);
238 freq_hardware = cpufreq_get_freq_hardware(cpu);
239
240 driver = cpufreq_get_driver(cpu);
241 if (!driver) {
242 printf(_(" no or unknown cpufreq driver is active on this CPU\n"));
243 } else {
244 printf(_(" driver: %s\n"), driver);
245 cpufreq_put_driver(driver);
246 }
247
248 cpus = cpufreq_get_related_cpus(cpu);
249 if (cpus) {
250 printf(_(" CPUs which run at the same hardware frequency: "));
251 while (cpus->next) {
252 printf("%d ", cpus->cpu);
253 cpus = cpus->next;
254 }
255 printf("%d\n", cpus->cpu);
256 cpufreq_put_related_cpus(cpus);
257 }
258
259 cpus = cpufreq_get_affected_cpus(cpu);
260 if (cpus) {
261 printf(_(" CPUs which need to have their frequency coordinated by software: "));
262 while (cpus->next) {
263 printf("%d ", cpus->cpu);
264 cpus = cpus->next;
265 }
266 printf("%d\n", cpus->cpu);
267 cpufreq_put_affected_cpus(cpus);
268 }
269
270 latency = cpufreq_get_transition_latency(cpu);
271 if (latency) {
272 printf(_(" maximum transition latency: "));
273 print_duration(latency);
274 printf(".\n");
275 }
276
277 if (!(cpufreq_get_hardware_limits(cpu, &min, &max))) {
278 printf(_(" hardware limits: "));
279 print_speed(min);
280 printf(" - ");
281 print_speed(max);
282 printf("\n");
283 }
284
285 freqs = cpufreq_get_available_frequencies(cpu);
286 if (freqs) {
287 printf(_(" available frequency steps: "));
288 while (freqs->next) {
289 print_speed(freqs->frequency);
290 printf(", ");
291 freqs = freqs->next;
292 }
293 print_speed(freqs->frequency);
294 printf("\n");
295 cpufreq_put_available_frequencies(freqs);
296 }
297
298 governors = cpufreq_get_available_governors(cpu);
299 if (governors) {
300 printf(_(" available cpufreq governors: "));
301 while (governors->next) {
302 printf("%s, ", governors->governor);
303 governors = governors->next;
304 }
305 printf("%s\n", governors->governor);
306 cpufreq_put_available_governors(governors);
307 }
308
309 policy = cpufreq_get_policy(cpu);
310 if (policy) {
311 printf(_(" current policy: frequency should be within "));
312 print_speed(policy->min);
313 printf(_(" and "));
314 print_speed(policy->max);
315
316 printf(".\n ");
317 printf(_("The governor \"%s\" may"
318 " decide which speed to use\n within this range.\n"),
319 policy->governor);
320 cpufreq_put_policy(policy);
321 }
322
323 if (freq_kernel || freq_hardware) {
324 printf(_(" current CPU frequency is "));
325 if (freq_hardware) {
326 print_speed(freq_hardware);
327 printf(_(" (asserted by call to hardware)"));
328 } else
329 print_speed(freq_kernel);
330 printf(".\n");
331 }
332 stats = cpufreq_get_stats(cpu, &total_time);
333 if (stats) {
334 printf(_(" cpufreq stats: "));
335 while (stats) {
336 print_speed(stats->frequency);
337 printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time);
338 stats = stats->next;
339 if (stats)
340 printf(", ");
341 }
342 cpufreq_put_stats(stats);
343 total_trans = cpufreq_get_transitions(cpu);
344 if (total_trans)
345 printf(" (%lu)\n", total_trans);
346 else
347 printf("\n");
348 }
349 get_boost_mode(cpu);
350
351}
352
353/* --freq / -f */
354
355static int get_freq_kernel(unsigned int cpu, unsigned int human)
356{
357 unsigned long freq = cpufreq_get_freq_kernel(cpu);
358 if (!freq)
359 return -EINVAL;
360 if (human) {
361 print_speed(freq);
362 printf("\n");
363 } else
364 printf("%lu\n", freq);
365 return 0;
366}
367
368
369/* --hwfreq / -w */
370
371static int get_freq_hardware(unsigned int cpu, unsigned int human)
372{
373 unsigned long freq = cpufreq_get_freq_hardware(cpu);
374 if (!freq)
375 return -EINVAL;
376 if (human) {
377 print_speed(freq);
378 printf("\n");
379 } else
380 printf("%lu\n", freq);
381 return 0;
382}
383
384/* --hwlimits / -l */
385
386static int get_hardware_limits(unsigned int cpu)
387{
388 unsigned long min, max;
389 if (cpufreq_get_hardware_limits(cpu, &min, &max))
390 return -EINVAL;
391 printf("%lu %lu\n", min, max);
392 return 0;
393}
394
395/* --driver / -d */
396
397static int get_driver(unsigned int cpu)
398{
399 char *driver = cpufreq_get_driver(cpu);
400 if (!driver)
401 return -EINVAL;
402 printf("%s\n", driver);
403 cpufreq_put_driver(driver);
404 return 0;
405}
406
407/* --policy / -p */
408
409static int get_policy(unsigned int cpu)
410{
411 struct cpufreq_policy *policy = cpufreq_get_policy(cpu);
412 if (!policy)
413 return -EINVAL;
414 printf("%lu %lu %s\n", policy->min, policy->max, policy->governor);
415 cpufreq_put_policy(policy);
416 return 0;
417}
418
419/* --governors / -g */
420
421static int get_available_governors(unsigned int cpu)
422{
423 struct cpufreq_available_governors *governors =
424 cpufreq_get_available_governors(cpu);
425 if (!governors)
426 return -EINVAL;
427
428 while (governors->next) {
429 printf("%s ", governors->governor);
430 governors = governors->next;
431 }
432 printf("%s\n", governors->governor);
433 cpufreq_put_available_governors(governors);
434 return 0;
435}
436
437
438/* --affected-cpus / -a */
439
440static int get_affected_cpus(unsigned int cpu)
441{
442 struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu);
443 if (!cpus)
444 return -EINVAL;
445
446 while (cpus->next) {
447 printf("%d ", cpus->cpu);
448 cpus = cpus->next;
449 }
450 printf("%d\n", cpus->cpu);
451 cpufreq_put_affected_cpus(cpus);
452 return 0;
453}
454
455/* --related-cpus / -r */
456
457static int get_related_cpus(unsigned int cpu)
458{
459 struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu);
460 if (!cpus)
461 return -EINVAL;
462
463 while (cpus->next) {
464 printf("%d ", cpus->cpu);
465 cpus = cpus->next;
466 }
467 printf("%d\n", cpus->cpu);
468 cpufreq_put_related_cpus(cpus);
469 return 0;
470}
471
472/* --stats / -s */
473
474static int get_freq_stats(unsigned int cpu, unsigned int human)
475{
476 unsigned long total_trans = cpufreq_get_transitions(cpu);
477 unsigned long long total_time;
478 struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time);
479 while (stats) {
480 if (human) {
481 print_speed(stats->frequency);
482 printf(":%.2f%%",
483 (100.0 * stats->time_in_state) / total_time);
484 } else
485 printf("%lu:%llu",
486 stats->frequency, stats->time_in_state);
487 stats = stats->next;
488 if (stats)
489 printf(", ");
490 }
491 cpufreq_put_stats(stats);
492 if (total_trans)
493 printf(" (%lu)\n", total_trans);
494 return 0;
495}
496
497/* --latency / -y */
498
499static int get_latency(unsigned int cpu, unsigned int human)
500{
501 unsigned long latency = cpufreq_get_transition_latency(cpu);
502 if (!latency)
503 return -EINVAL;
504
505 if (human) {
506 print_duration(latency);
507 printf("\n");
508 } else
509 printf("%lu\n", latency);
510 return 0;
511}
512
513static struct option info_opts[] = {
514 { .name = "debug", .has_arg = no_argument, .flag = NULL, .val = 'e'},
515 { .name = "boost", .has_arg = no_argument, .flag = NULL, .val = 'b'},
516 { .name = "freq", .has_arg = no_argument, .flag = NULL, .val = 'f'},
517 { .name = "hwfreq", .has_arg = no_argument, .flag = NULL, .val = 'w'},
518 { .name = "hwlimits", .has_arg = no_argument, .flag = NULL, .val = 'l'},
519 { .name = "driver", .has_arg = no_argument, .flag = NULL, .val = 'd'},
520 { .name = "policy", .has_arg = no_argument, .flag = NULL, .val = 'p'},
521 { .name = "governors", .has_arg = no_argument, .flag = NULL, .val = 'g'},
522 { .name = "related-cpus", .has_arg = no_argument, .flag = NULL, .val = 'r'},
523 { .name = "affected-cpus",.has_arg = no_argument, .flag = NULL, .val = 'a'},
524 { .name = "stats", .has_arg = no_argument, .flag = NULL, .val = 's'},
525 { .name = "latency", .has_arg = no_argument, .flag = NULL, .val = 'y'},
526 { .name = "proc", .has_arg = no_argument, .flag = NULL, .val = 'o'},
527 { .name = "human", .has_arg = no_argument, .flag = NULL, .val = 'm'},
528 { },
529};
530
531int cmd_freq_info(int argc, char **argv)
532{
533 extern char *optarg;
534 extern int optind, opterr, optopt;
535 int ret = 0, cont = 1;
536 unsigned int cpu = 0;
537 unsigned int human = 0;
538 int output_param = 0;
539
540 do {
541 ret = getopt_long(argc, argv, "oefwldpgrasmyb", info_opts, NULL);
542 switch (ret) {
543 case '?':
544 output_param = '?';
545 cont = 0;
546 break;
547 case -1:
548 cont = 0;
549 break;
550 case 'b':
551 case 'o':
552 case 'a':
553 case 'r':
554 case 'g':
555 case 'p':
556 case 'd':
557 case 'l':
558 case 'w':
559 case 'f':
560 case 'e':
561 case 's':
562 case 'y':
563 if (output_param) {
564 output_param = -1;
565 cont = 0;
566 break;
567 }
568 output_param = ret;
569 break;
570 case 'm':
571 if (human) {
572 output_param = -1;
573 cont = 0;
574 break;
575 }
576 human = 1;
577 break;
578 default:
579 fprintf(stderr, "invalid or unknown argument\n");
580 return EXIT_FAILURE;
581 }
582 } while (cont);
583
584 switch (output_param) {
585 case 'o':
586 if (!bitmask_isallclear(cpus_chosen)) {
587 printf(_("The argument passed to this tool can't be "
588 "combined with passing a --cpu argument\n"));
589 return -EINVAL;
590 }
591 break;
592 case 0:
593 output_param = 'e';
594 }
595
596 ret = 0;
597
598 /* Default is: show output of CPU 0 only */
599 if (bitmask_isallclear(cpus_chosen))
600 bitmask_setbit(cpus_chosen, 0);
601
602 switch (output_param) {
603 case -1:
604 printf(_("You can't specify more than one --cpu parameter and/or\n"
605 "more than one output-specific argument\n"));
606 return -EINVAL;
607 case '?':
608 printf(_("invalid or unknown argument\n"));
609 return -EINVAL;
610 case 'o':
611 proc_cpufreq_output();
612 return EXIT_SUCCESS;
613 }
614
615 for (cpu = bitmask_first(cpus_chosen);
616 cpu <= bitmask_last(cpus_chosen); cpu++) {
617
618 if (!bitmask_isbitset(cpus_chosen, cpu))
619 continue;
620 if (cpufreq_cpu_exists(cpu)) {
621 printf(_("couldn't analyze CPU %d as it doesn't seem to be present\n"), cpu);
622 continue;
623 }
624 printf(_("analyzing CPU %d:\n"), cpu);
625
626 switch (output_param) {
627 case 'b':
628 get_boost_mode(cpu);
629 break;
630 case 'e':
631 debug_output_one(cpu);
632 break;
633 case 'a':
634 ret = get_affected_cpus(cpu);
635 break;
636 case 'r':
637 ret = get_related_cpus(cpu);
638 break;
639 case 'g':
640 ret = get_available_governors(cpu);
641 break;
642 case 'p':
643 ret = get_policy(cpu);
644 break;
645 case 'd':
646 ret = get_driver(cpu);
647 break;
648 case 'l':
649 ret = get_hardware_limits(cpu);
650 break;
651 case 'w':
652 ret = get_freq_hardware(cpu, human);
653 break;
654 case 'f':
655 ret = get_freq_kernel(cpu, human);
656 break;
657 case 's':
658 ret = get_freq_stats(cpu, human);
659 break;
660 case 'y':
661 ret = get_latency(cpu, human);
662 break;
663 }
664 if (ret)
665 return ret;
666 }
667 return ret;
668}
diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c
new file mode 100644
index 00000000000..dd1539eb8c6
--- /dev/null
+++ b/tools/power/cpupower/utils/cpufreq-set.c
@@ -0,0 +1,331 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7
8#include <unistd.h>
9#include <stdio.h>
10#include <errno.h>
11#include <stdlib.h>
12#include <limits.h>
13#include <string.h>
14#include <ctype.h>
15
16#include <getopt.h>
17
18#include "cpufreq.h"
19#include "helpers/helpers.h"
20
21#define NORM_FREQ_LEN 32
22
23static struct option set_opts[] = {
24 { .name = "min", .has_arg = required_argument, .flag = NULL, .val = 'd'},
25 { .name = "max", .has_arg = required_argument, .flag = NULL, .val = 'u'},
26 { .name = "governor", .has_arg = required_argument, .flag = NULL, .val = 'g'},
27 { .name = "freq", .has_arg = required_argument, .flag = NULL, .val = 'f'},
28 { .name = "related", .has_arg = no_argument, .flag = NULL, .val='r'},
29 { },
30};
31
32static void print_error(void)
33{
34 printf(_("Error setting new values. Common errors:\n"
35 "- Do you have proper administration rights? (super-user?)\n"
36 "- Is the governor you requested available and modprobed?\n"
37 "- Trying to set an invalid policy?\n"
38 "- Trying to set a specific frequency, but userspace governor is not available,\n"
39 " for example because of hardware which cannot be set to a specific frequency\n"
40 " or because the userspace governor isn't loaded?\n"));
41};
42
43struct freq_units {
44 char *str_unit;
45 int power_of_ten;
46};
47
48const struct freq_units def_units[] = {
49 {"hz", -3},
50 {"khz", 0}, /* default */
51 {"mhz", 3},
52 {"ghz", 6},
53 {"thz", 9},
54 {NULL, 0}
55};
56
57static void print_unknown_arg(void)
58{
59 printf(_("invalid or unknown argument\n"));
60}
61
62static unsigned long string_to_frequency(const char *str)
63{
64 char normalized[NORM_FREQ_LEN];
65 const struct freq_units *unit;
66 const char *scan;
67 char *end;
68 unsigned long freq;
69 int power = 0, match_count = 0, i, cp, pad;
70
71 while (*str == '0')
72 str++;
73
74 for (scan = str; isdigit(*scan) || *scan == '.'; scan++) {
75 if (*scan == '.' && match_count == 0)
76 match_count = 1;
77 else if (*scan == '.' && match_count == 1)
78 return 0;
79 }
80
81 if (*scan) {
82 match_count = 0;
83 for (unit = def_units; unit->str_unit; unit++) {
84 for (i = 0;
85 scan[i] && tolower(scan[i]) == unit->str_unit[i];
86 ++i)
87 continue;
88 if (scan[i])
89 continue;
90 match_count++;
91 power = unit->power_of_ten;
92 }
93 if (match_count != 1)
94 return 0;
95 }
96
97 /* count the number of digits to be copied */
98 for (cp = 0; isdigit(str[cp]); cp++)
99 continue;
100
101 if (str[cp] == '.') {
102 while (power > -1 && isdigit(str[cp+1]))
103 cp++, power--;
104 }
105 if (power >= -1) /* not enough => pad */
106 pad = power + 1;
107 else /* to much => strip */
108 pad = 0, cp += power + 1;
109 /* check bounds */
110 if (cp <= 0 || cp + pad > NORM_FREQ_LEN - 1)
111 return 0;
112
113 /* copy digits */
114 for (i = 0; i < cp; i++, str++) {
115 if (*str == '.')
116 str++;
117 normalized[i] = *str;
118 }
119 /* and pad */
120 for (; i < cp + pad; i++)
121 normalized[i] = '0';
122
123 /* round up, down ? */
124 match_count = (normalized[i-1] >= '5');
125 /* and drop the decimal part */
126 normalized[i-1] = 0; /* cp > 0 && pad >= 0 ==> i > 0 */
127
128 /* final conversion (and applying rounding) */
129 errno = 0;
130 freq = strtoul(normalized, &end, 10);
131 if (errno)
132 return 0;
133 else {
134 if (match_count && freq != ULONG_MAX)
135 freq++;
136 return freq;
137 }
138}
139
140static int do_new_policy(unsigned int cpu, struct cpufreq_policy *new_pol)
141{
142 struct cpufreq_policy *cur_pol = cpufreq_get_policy(cpu);
143 int ret;
144
145 if (!cur_pol) {
146 printf(_("wrong, unknown or unhandled CPU?\n"));
147 return -EINVAL;
148 }
149
150 if (!new_pol->min)
151 new_pol->min = cur_pol->min;
152
153 if (!new_pol->max)
154 new_pol->max = cur_pol->max;
155
156 if (!new_pol->governor)
157 new_pol->governor = cur_pol->governor;
158
159 ret = cpufreq_set_policy(cpu, new_pol);
160
161 cpufreq_put_policy(cur_pol);
162
163 return ret;
164}
165
166
167static int do_one_cpu(unsigned int cpu, struct cpufreq_policy *new_pol,
168 unsigned long freq, unsigned int pc)
169{
170 switch (pc) {
171 case 0:
172 return cpufreq_set_frequency(cpu, freq);
173
174 case 1:
175 /* if only one value of a policy is to be changed, we can
176 * use a "fast path".
177 */
178 if (new_pol->min)
179 return cpufreq_modify_policy_min(cpu, new_pol->min);
180 else if (new_pol->max)
181 return cpufreq_modify_policy_max(cpu, new_pol->max);
182 else if (new_pol->governor)
183 return cpufreq_modify_policy_governor(cpu,
184 new_pol->governor);
185
186 default:
187 /* slow path */
188 return do_new_policy(cpu, new_pol);
189 }
190}
191
192int cmd_freq_set(int argc, char **argv)
193{
194 extern char *optarg;
195 extern int optind, opterr, optopt;
196 int ret = 0, cont = 1;
197 int double_parm = 0, related = 0, policychange = 0;
198 unsigned long freq = 0;
199 char gov[20];
200 unsigned int cpu;
201
202 struct cpufreq_policy new_pol = {
203 .min = 0,
204 .max = 0,
205 .governor = NULL,
206 };
207
208 /* parameter parsing */
209 do {
210 ret = getopt_long(argc, argv, "d:u:g:f:r", set_opts, NULL);
211 switch (ret) {
212 case '?':
213 print_unknown_arg();
214 return -EINVAL;
215 case -1:
216 cont = 0;
217 break;
218 case 'r':
219 if (related)
220 double_parm++;
221 related++;
222 break;
223 case 'd':
224 if (new_pol.min)
225 double_parm++;
226 policychange++;
227 new_pol.min = string_to_frequency(optarg);
228 if (new_pol.min == 0) {
229 print_unknown_arg();
230 return -EINVAL;
231 }
232 break;
233 case 'u':
234 if (new_pol.max)
235 double_parm++;
236 policychange++;
237 new_pol.max = string_to_frequency(optarg);
238 if (new_pol.max == 0) {
239 print_unknown_arg();
240 return -EINVAL;
241 }
242 break;
243 case 'f':
244 if (freq)
245 double_parm++;
246 freq = string_to_frequency(optarg);
247 if (freq == 0) {
248 print_unknown_arg();
249 return -EINVAL;
250 }
251 break;
252 case 'g':
253 if (new_pol.governor)
254 double_parm++;
255 policychange++;
256 if ((strlen(optarg) < 3) || (strlen(optarg) > 18)) {
257 print_unknown_arg();
258 return -EINVAL;
259 }
260 if ((sscanf(optarg, "%s", gov)) != 1) {
261 print_unknown_arg();
262 return -EINVAL;
263 }
264 new_pol.governor = gov;
265 break;
266 }
267 } while (cont);
268
269 /* parameter checking */
270 if (double_parm) {
271 printf("the same parameter was passed more than once\n");
272 return -EINVAL;
273 }
274
275 if (freq && policychange) {
276 printf(_("the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
277 "-g/--governor parameters\n"));
278 return -EINVAL;
279 }
280
281 if (!freq && !policychange) {
282 printf(_("At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
283 "-g/--governor must be passed\n"));
284 return -EINVAL;
285 }
286
287 /* Default is: set all CPUs */
288 if (bitmask_isallclear(cpus_chosen))
289 bitmask_setall(cpus_chosen);
290
291 /* Also set frequency settings for related CPUs if -r is passed */
292 if (related) {
293 for (cpu = bitmask_first(cpus_chosen);
294 cpu <= bitmask_last(cpus_chosen); cpu++) {
295 struct cpufreq_affected_cpus *cpus;
296
297 if (!bitmask_isbitset(cpus_chosen, cpu) ||
298 cpufreq_cpu_exists(cpu))
299 continue;
300
301 cpus = cpufreq_get_related_cpus(cpu);
302 if (!cpus)
303 break;
304 while (cpus->next) {
305 bitmask_setbit(cpus_chosen, cpus->cpu);
306 cpus = cpus->next;
307 }
308 cpufreq_put_related_cpus(cpus);
309 }
310 }
311
312
313 /* loop over CPUs */
314 for (cpu = bitmask_first(cpus_chosen);
315 cpu <= bitmask_last(cpus_chosen); cpu++) {
316
317 if (!bitmask_isbitset(cpus_chosen, cpu) ||
318 cpufreq_cpu_exists(cpu))
319 continue;
320
321 printf(_("Setting cpu: %d\n"), cpu);
322 ret = do_one_cpu(cpu, &new_pol, freq, policychange);
323 if (ret)
324 break;
325 }
326
327 if (ret)
328 print_error();
329
330 return ret;
331}
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c
new file mode 100644
index 00000000000..b028267c137
--- /dev/null
+++ b/tools/power/cpupower/utils/cpuidle-info.c
@@ -0,0 +1,222 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 * (C) 2010 Thomas Renninger <trenn@suse.de>
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 */
7
8
9#include <unistd.h>
10#include <stdio.h>
11#include <errno.h>
12#include <stdlib.h>
13#include <string.h>
14#include <getopt.h>
15#include <cpufreq.h>
16
17#include "helpers/helpers.h"
18#include "helpers/sysfs.h"
19#include "helpers/bitmask.h"
20
21#define LINE_LEN 10
22
23static void cpuidle_cpu_output(unsigned int cpu, int verbose)
24{
25 int idlestates, idlestate;
26 char *tmp;
27
28 printf(_ ("Analyzing CPU %d:\n"), cpu);
29
30 idlestates = sysfs_get_idlestate_count(cpu);
31 if (idlestates == 0) {
32 printf(_("CPU %u: No idle states\n"), cpu);
33 return;
34 } else if (idlestates <= 0) {
35 printf(_("CPU %u: Can't read idle state info\n"), cpu);
36 return;
37 }
38 tmp = sysfs_get_idlestate_name(cpu, idlestates - 1);
39 if (!tmp) {
40 printf(_("Could not determine max idle state %u\n"),
41 idlestates - 1);
42 return;
43 }
44
45 printf(_("Number of idle states: %d\n"), idlestates);
46
47 printf(_("Available idle states:"));
48 for (idlestate = 1; idlestate < idlestates; idlestate++) {
49 tmp = sysfs_get_idlestate_name(cpu, idlestate);
50 if (!tmp)
51 continue;
52 printf(" %s", tmp);
53 free(tmp);
54 }
55 printf("\n");
56
57 if (!verbose)
58 return;
59
60 for (idlestate = 1; idlestate < idlestates; idlestate++) {
61 tmp = sysfs_get_idlestate_name(cpu, idlestate);
62 if (!tmp)
63 continue;
64 printf("%s:\n", tmp);
65 free(tmp);
66
67 tmp = sysfs_get_idlestate_desc(cpu, idlestate);
68 if (!tmp)
69 continue;
70 printf(_("Flags/Description: %s\n"), tmp);
71 free(tmp);
72
73 printf(_("Latency: %lu\n"),
74 sysfs_get_idlestate_latency(cpu, idlestate));
75 printf(_("Usage: %lu\n"),
76 sysfs_get_idlestate_usage(cpu, idlestate));
77 printf(_("Duration: %llu\n"),
78 sysfs_get_idlestate_time(cpu, idlestate));
79 }
80 printf("\n");
81}
82
83static void cpuidle_general_output(void)
84{
85 char *tmp;
86
87 tmp = sysfs_get_cpuidle_driver();
88 if (!tmp) {
89 printf(_("Could not determine cpuidle driver\n"));
90 return;
91 }
92
93 printf(_("CPUidle driver: %s\n"), tmp);
94 free(tmp);
95
96 tmp = sysfs_get_cpuidle_governor();
97 if (!tmp) {
98 printf(_("Could not determine cpuidle governor\n"));
99 return;
100 }
101
102 printf(_("CPUidle governor: %s\n"), tmp);
103 free(tmp);
104}
105
106static void proc_cpuidle_cpu_output(unsigned int cpu)
107{
108 long max_allowed_cstate = 2000000000;
109 int cstates, cstate;
110
111 cstates = sysfs_get_idlestate_count(cpu);
112 if (cstates == 0) {
113 /*
114 * Go on and print same useless info as you'd see with
115 * cat /proc/acpi/processor/../power
116 * printf(_("CPU %u: No C-states available\n"), cpu);
117 * return;
118 */
119 } else if (cstates <= 0) {
120 printf(_("CPU %u: Can't read C-state info\n"), cpu);
121 return;
122 }
123 /* printf("Cstates: %d\n", cstates); */
124
125 printf(_("active state: C0\n"));
126 printf(_("max_cstate: C%u\n"), cstates-1);
127 printf(_("maximum allowed latency: %lu usec\n"), max_allowed_cstate);
128 printf(_("states:\t\n"));
129 for (cstate = 1; cstate < cstates; cstate++) {
130 printf(_(" C%d: "
131 "type[C%d] "), cstate, cstate);
132 printf(_("promotion[--] demotion[--] "));
133 printf(_("latency[%03lu] "),
134 sysfs_get_idlestate_latency(cpu, cstate));
135 printf(_("usage[%08lu] "),
136 sysfs_get_idlestate_usage(cpu, cstate));
137 printf(_("duration[%020Lu] \n"),
138 sysfs_get_idlestate_time(cpu, cstate));
139 }
140}
141
142static struct option info_opts[] = {
143 { .name = "silent", .has_arg = no_argument, .flag = NULL, .val = 's'},
144 { .name = "proc", .has_arg = no_argument, .flag = NULL, .val = 'o'},
145 { },
146};
147
148static inline void cpuidle_exit(int fail)
149{
150 exit(EXIT_FAILURE);
151}
152
153int cmd_idle_info(int argc, char **argv)
154{
155 extern char *optarg;
156 extern int optind, opterr, optopt;
157 int ret = 0, cont = 1, output_param = 0, verbose = 1;
158 unsigned int cpu = 0;
159
160 do {
161 ret = getopt_long(argc, argv, "os", info_opts, NULL);
162 if (ret == -1)
163 break;
164 switch (ret) {
165 case '?':
166 output_param = '?';
167 cont = 0;
168 break;
169 case 's':
170 verbose = 0;
171 break;
172 case -1:
173 cont = 0;
174 break;
175 case 'o':
176 if (output_param) {
177 output_param = -1;
178 cont = 0;
179 break;
180 }
181 output_param = ret;
182 break;
183 }
184 } while (cont);
185
186 switch (output_param) {
187 case -1:
188 printf(_("You can't specify more than one "
189 "output-specific argument\n"));
190 cpuidle_exit(EXIT_FAILURE);
191 case '?':
192 printf(_("invalid or unknown argument\n"));
193 cpuidle_exit(EXIT_FAILURE);
194 }
195
196 /* Default is: show output of CPU 0 only */
197 if (bitmask_isallclear(cpus_chosen))
198 bitmask_setbit(cpus_chosen, 0);
199
200 if (output_param == 0)
201 cpuidle_general_output();
202
203 for (cpu = bitmask_first(cpus_chosen);
204 cpu <= bitmask_last(cpus_chosen); cpu++) {
205
206 if (!bitmask_isbitset(cpus_chosen, cpu) ||
207 cpufreq_cpu_exists(cpu))
208 continue;
209
210 switch (output_param) {
211
212 case 'o':
213 proc_cpuidle_cpu_output(cpu);
214 break;
215 case 0:
216 printf("\n");
217 cpuidle_cpu_output(cpu, verbose);
218 break;
219 }
220 }
221 return EXIT_SUCCESS;
222}
diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c
new file mode 100644
index 00000000000..3f68632c28c
--- /dev/null
+++ b/tools/power/cpupower/utils/cpupower-info.c
@@ -0,0 +1,135 @@
1/*
2 * (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7
8#include <unistd.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <errno.h>
12#include <string.h>
13#include <getopt.h>
14
15#include <cpufreq.h>
16#include "helpers/helpers.h"
17#include "helpers/sysfs.h"
18
19static struct option set_opts[] = {
20 { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'},
21 { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'},
22 { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'},
23 { },
24};
25
26static void print_wrong_arg_exit(void)
27{
28 printf(_("invalid or unknown argument\n"));
29 exit(EXIT_FAILURE);
30}
31
32int cmd_info(int argc, char **argv)
33{
34 extern char *optarg;
35 extern int optind, opterr, optopt;
36 unsigned int cpu;
37
38 union {
39 struct {
40 int sched_mc:1;
41 int sched_smt:1;
42 int perf_bias:1;
43 };
44 int params;
45 } params = {};
46 int ret = 0;
47
48 setlocale(LC_ALL, "");
49 textdomain(PACKAGE);
50
51 /* parameter parsing */
52 while ((ret = getopt_long(argc, argv, "msb", set_opts, NULL)) != -1) {
53 switch (ret) {
54 case 'b':
55 if (params.perf_bias)
56 print_wrong_arg_exit();
57 params.perf_bias = 1;
58 break;
59 case 'm':
60 if (params.sched_mc)
61 print_wrong_arg_exit();
62 params.sched_mc = 1;
63 break;
64 case 's':
65 if (params.sched_smt)
66 print_wrong_arg_exit();
67 params.sched_smt = 1;
68 break;
69 default:
70 print_wrong_arg_exit();
71 }
72 };
73
74 if (!params.params)
75 params.params = 0x7;
76
77 /* Default is: show output of CPU 0 only */
78 if (bitmask_isallclear(cpus_chosen))
79 bitmask_setbit(cpus_chosen, 0);
80
81 if (params.sched_mc) {
82 ret = sysfs_get_sched("mc");
83 printf(_("System's multi core scheduler setting: "));
84 if (ret < 0)
85 /* if sysfs file is missing it's: errno == ENOENT */
86 printf(_("not supported\n"));
87 else
88 printf("%d\n", ret);
89 }
90 if (params.sched_smt) {
91 ret = sysfs_get_sched("smt");
92 printf(_("System's thread sibling scheduler setting: "));
93 if (ret < 0)
94 /* if sysfs file is missing it's: errno == ENOENT */
95 printf(_("not supported\n"));
96 else
97 printf("%d\n", ret);
98 }
99
100 /* Add more per cpu options here */
101 if (!params.perf_bias)
102 return ret;
103
104 if (params.perf_bias) {
105 if (!run_as_root) {
106 params.perf_bias = 0;
107 printf(_("Intel's performance bias setting needs root privileges\n"));
108 } else if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) {
109 printf(_("System does not support Intel's performance"
110 " bias setting\n"));
111 params.perf_bias = 0;
112 }
113 }
114
115 /* loop over CPUs */
116 for (cpu = bitmask_first(cpus_chosen);
117 cpu <= bitmask_last(cpus_chosen); cpu++) {
118
119 if (!bitmask_isbitset(cpus_chosen, cpu) ||
120 cpufreq_cpu_exists(cpu))
121 continue;
122
123 printf(_("analyzing CPU %d:\n"), cpu);
124
125 if (params.perf_bias) {
126 ret = msr_intel_get_perf_bias(cpu);
127 if (ret < 0) {
128 printf(_("Could not read perf-bias value\n"));
129 break;
130 } else
131 printf(_("perf-bias: %d\n"), ret);
132 }
133 }
134 return ret;
135}
diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c
new file mode 100644
index 00000000000..dc4de376211
--- /dev/null
+++ b/tools/power/cpupower/utils/cpupower-set.c
@@ -0,0 +1,134 @@
1/*
2 * (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7
8#include <unistd.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <errno.h>
12#include <string.h>
13#include <getopt.h>
14
15#include <cpufreq.h>
16#include "helpers/helpers.h"
17#include "helpers/sysfs.h"
18#include "helpers/bitmask.h"
19
20static struct option set_opts[] = {
21 { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'},
22 { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'},
23 { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'},
24 { },
25};
26
27static void print_wrong_arg_exit(void)
28{
29 printf(_("invalid or unknown argument\n"));
30 exit(EXIT_FAILURE);
31}
32
33int cmd_set(int argc, char **argv)
34{
35 extern char *optarg;
36 extern int optind, opterr, optopt;
37 unsigned int cpu;
38
39 union {
40 struct {
41 int sched_mc:1;
42 int sched_smt:1;
43 int perf_bias:1;
44 };
45 int params;
46 } params;
47 int sched_mc = 0, sched_smt = 0, perf_bias = 0;
48 int ret = 0;
49
50 setlocale(LC_ALL, "");
51 textdomain(PACKAGE);
52
53 params.params = 0;
54 /* parameter parsing */
55 while ((ret = getopt_long(argc, argv, "m:s:b:",
56 set_opts, NULL)) != -1) {
57 switch (ret) {
58 case 'b':
59 if (params.perf_bias)
60 print_wrong_arg_exit();
61 perf_bias = atoi(optarg);
62 if (perf_bias < 0 || perf_bias > 15) {
63 printf(_("--perf-bias param out "
64 "of range [0-%d]\n"), 15);
65 print_wrong_arg_exit();
66 }
67 params.perf_bias = 1;
68 break;
69 case 'm':
70 if (params.sched_mc)
71 print_wrong_arg_exit();
72 sched_mc = atoi(optarg);
73 if (sched_mc < 0 || sched_mc > 2) {
74 printf(_("--sched-mc param out "
75 "of range [0-%d]\n"), 2);
76 print_wrong_arg_exit();
77 }
78 params.sched_mc = 1;
79 break;
80 case 's':
81 if (params.sched_smt)
82 print_wrong_arg_exit();
83 sched_smt = atoi(optarg);
84 if (sched_smt < 0 || sched_smt > 2) {
85 printf(_("--sched-smt param out "
86 "of range [0-%d]\n"), 2);
87 print_wrong_arg_exit();
88 }
89 params.sched_smt = 1;
90 break;
91 default:
92 print_wrong_arg_exit();
93 }
94 };
95
96 if (!params.params)
97 print_wrong_arg_exit();
98
99 if (params.sched_mc) {
100 ret = sysfs_set_sched("mc", sched_mc);
101 if (ret)
102 fprintf(stderr, _("Error setting sched-mc %s\n"),
103 (ret == -ENODEV) ? "not supported" : "");
104 }
105 if (params.sched_smt) {
106 ret = sysfs_set_sched("smt", sched_smt);
107 if (ret)
108 fprintf(stderr, _("Error setting sched-smt %s\n"),
109 (ret == -ENODEV) ? "not supported" : "");
110 }
111
112 /* Default is: set all CPUs */
113 if (bitmask_isallclear(cpus_chosen))
114 bitmask_setall(cpus_chosen);
115
116 /* loop over CPUs */
117 for (cpu = bitmask_first(cpus_chosen);
118 cpu <= bitmask_last(cpus_chosen); cpu++) {
119
120 if (!bitmask_isbitset(cpus_chosen, cpu) ||
121 cpufreq_cpu_exists(cpu))
122 continue;
123
124 if (params.perf_bias) {
125 ret = msr_intel_set_perf_bias(cpu, perf_bias);
126 if (ret) {
127 fprintf(stderr, _("Error setting perf-bias "
128 "value on CPU %d\n"), cpu);
129 break;
130 }
131 }
132 }
133 return ret;
134}
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c
new file mode 100644
index 00000000000..52bee591c1c
--- /dev/null
+++ b/tools/power/cpupower/utils/cpupower.c
@@ -0,0 +1,214 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Ideas taken over from the perf userspace tool (included in the Linus
7 * kernel git repo): subcommand builtins and param parsing.
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <unistd.h>
14#include <errno.h>
15
16#include "builtin.h"
17#include "helpers/helpers.h"
18#include "helpers/bitmask.h"
19
20struct cmd_struct {
21 const char *cmd;
22 int (*main)(int, const char **);
23 int needs_root;
24};
25
26#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
27
28static int cmd_help(int argc, const char **argv);
29
30/* Global cpu_info object available for all binaries
31 * Info only retrieved from CPU 0
32 *
33 * Values will be zero/unknown on non X86 archs
34 */
35struct cpupower_cpu_info cpupower_cpu_info;
36int run_as_root;
37/* Affected cpus chosen by -c/--cpu param */
38struct bitmask *cpus_chosen;
39
40#ifdef DEBUG
41int be_verbose;
42#endif
43
44static void print_help(void);
45
46static struct cmd_struct commands[] = {
47 { "frequency-info", cmd_freq_info, 0 },
48 { "frequency-set", cmd_freq_set, 1 },
49 { "idle-info", cmd_idle_info, 0 },
50 { "set", cmd_set, 1 },
51 { "info", cmd_info, 0 },
52 { "monitor", cmd_monitor, 0 },
53 { "help", cmd_help, 0 },
54 /* { "bench", cmd_bench, 1 }, */
55};
56
57static void print_help(void)
58{
59 unsigned int i;
60
61#ifdef DEBUG
62 printf(_("Usage:\tcpupower [-d|--debug] [-c|--cpu cpulist ] <command> [<args>]\n"));
63#else
64 printf(_("Usage:\tcpupower [-c|--cpu cpulist ] <command> [<args>]\n"));
65#endif
66 printf(_("Supported commands are:\n"));
67 for (i = 0; i < ARRAY_SIZE(commands); i++)
68 printf("\t%s\n", commands[i].cmd);
69 printf(_("\nNot all commands can make use of the -c cpulist option.\n"));
70 printf(_("\nUse 'cpupower help <command>' for getting help for above commands.\n"));
71}
72
73static int print_man_page(const char *subpage)
74{
75 int len;
76 char *page;
77
78 len = 10; /* enough for "cpupower-" */
79 if (subpage != NULL)
80 len += strlen(subpage);
81
82 page = malloc(len);
83 if (!page)
84 return -ENOMEM;
85
86 sprintf(page, "cpupower");
87 if ((subpage != NULL) && strcmp(subpage, "help")) {
88 strcat(page, "-");
89 strcat(page, subpage);
90 }
91
92 execlp("man", "man", page, NULL);
93
94 /* should not be reached */
95 return -EINVAL;
96}
97
98static int cmd_help(int argc, const char **argv)
99{
100 if (argc > 1) {
101 print_man_page(argv[1]); /* exits within execlp() */
102 return EXIT_FAILURE;
103 }
104
105 print_help();
106 return EXIT_SUCCESS;
107}
108
109static void print_version(void)
110{
111 printf(PACKAGE " " VERSION "\n");
112 printf(_("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
113}
114
115static void handle_options(int *argc, const char ***argv)
116{
117 int ret, x, new_argc = 0;
118
119 if (*argc < 1)
120 return;
121
122 for (x = 0; x < *argc && ((*argv)[x])[0] == '-'; x++) {
123 const char *param = (*argv)[x];
124 if (!strcmp(param, "-h") || !strcmp(param, "--help")) {
125 print_help();
126 exit(EXIT_SUCCESS);
127 } else if (!strcmp(param, "-c") || !strcmp(param, "--cpu")) {
128 if (*argc < 2) {
129 print_help();
130 exit(EXIT_FAILURE);
131 }
132 if (!strcmp((*argv)[x+1], "all"))
133 bitmask_setall(cpus_chosen);
134 else {
135 ret = bitmask_parselist(
136 (*argv)[x+1], cpus_chosen);
137 if (ret < 0) {
138 fprintf(stderr, _("Error parsing cpu "
139 "list\n"));
140 exit(EXIT_FAILURE);
141 }
142 }
143 x += 1;
144 /* Cut out param: cpupower -c 1 info -> cpupower info */
145 new_argc += 2;
146 continue;
147 } else if (!strcmp(param, "-v") ||
148 !strcmp(param, "--version")) {
149 print_version();
150 exit(EXIT_SUCCESS);
151#ifdef DEBUG
152 } else if (!strcmp(param, "-d") || !strcmp(param, "--debug")) {
153 be_verbose = 1;
154 new_argc++;
155 continue;
156#endif
157 } else {
158 fprintf(stderr, "Unknown option: %s\n", param);
159 print_help();
160 exit(EXIT_FAILURE);
161 }
162 }
163 *argc -= new_argc;
164 *argv += new_argc;
165}
166
167int main(int argc, const char *argv[])
168{
169 const char *cmd;
170 unsigned int i, ret;
171
172 cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
173
174 argc--;
175 argv += 1;
176
177 handle_options(&argc, &argv);
178
179 cmd = argv[0];
180
181 if (argc < 1) {
182 print_help();
183 return EXIT_FAILURE;
184 }
185
186 setlocale(LC_ALL, "");
187 textdomain(PACKAGE);
188
189 /* Turn "perf cmd --help" into "perf help cmd" */
190 if (argc > 1 && !strcmp(argv[1], "--help")) {
191 argv[1] = argv[0];
192 argv[0] = cmd = "help";
193 }
194
195 get_cpu_info(0, &cpupower_cpu_info);
196 run_as_root = !getuid();
197
198 for (i = 0; i < ARRAY_SIZE(commands); i++) {
199 struct cmd_struct *p = commands + i;
200 if (strcmp(p->cmd, cmd))
201 continue;
202 if (!run_as_root && p->needs_root) {
203 fprintf(stderr, _("Subcommand %s needs root "
204 "privileges\n"), cmd);
205 return EXIT_FAILURE;
206 }
207 ret = p->main(argc, argv);
208 if (cpus_chosen)
209 bitmask_free(cpus_chosen);
210 return ret;
211 }
212 print_help();
213 return EXIT_FAILURE;
214}
diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c
new file mode 100644
index 00000000000..87d5605bdda
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/amd.c
@@ -0,0 +1,137 @@
1#if defined(__i386__) || defined(__x86_64__)
2#include <unistd.h>
3#include <errno.h>
4#include <stdio.h>
5#include <stdint.h>
6
7#include <pci/pci.h>
8
9#include "helpers/helpers.h"
10
11#define MSR_AMD_PSTATE_STATUS 0xc0010063
12#define MSR_AMD_PSTATE 0xc0010064
13#define MSR_AMD_PSTATE_LIMIT 0xc0010061
14
15union msr_pstate {
16 struct {
17 unsigned fid:6;
18 unsigned did:3;
19 unsigned vid:7;
20 unsigned res1:6;
21 unsigned nbdid:1;
22 unsigned res2:2;
23 unsigned nbvid:7;
24 unsigned iddval:8;
25 unsigned idddiv:2;
26 unsigned res3:21;
27 unsigned en:1;
28 } bits;
29 unsigned long long val;
30};
31
32static int get_did(int family, union msr_pstate pstate)
33{
34 int t;
35
36 if (family == 0x12)
37 t = pstate.val & 0xf;
38 else
39 t = pstate.bits.did;
40
41 return t;
42}
43
44static int get_cof(int family, union msr_pstate pstate)
45{
46 int t;
47 int fid, did;
48
49 did = get_did(family, pstate);
50
51 t = 0x10;
52 fid = pstate.bits.fid;
53 if (family == 0x11)
54 t = 0x8;
55
56 return (100 * (fid + t)) >> did;
57}
58
59/* Needs:
60 * cpu -> the cpu that gets evaluated
61 * cpu_family -> The cpu's family (0x10, 0x12,...)
62 * boots_states -> how much boost states the machines support
63 *
64 * Fills up:
65 * pstates -> a pointer to an array of size MAX_HW_PSTATES
66 * must be initialized with zeros.
67 * All available HW pstates (including boost states)
68 * no -> amount of pstates above array got filled up with
69 *
70 * returns zero on success, -1 on failure
71 */
72int decode_pstates(unsigned int cpu, unsigned int cpu_family,
73 int boost_states, unsigned long *pstates, int *no)
74{
75 int i, psmax, pscur;
76 union msr_pstate pstate;
77 unsigned long long val;
78
79 /* Only read out frequencies from HW when CPU might be boostable
80 to keep the code as short and clean as possible.
81 Otherwise frequencies are exported via ACPI tables.
82 */
83 if (cpu_family < 0x10 || cpu_family == 0x14)
84 return -1;
85
86 if (read_msr(cpu, MSR_AMD_PSTATE_LIMIT, &val))
87 return -1;
88
89 psmax = (val >> 4) & 0x7;
90
91 if (read_msr(cpu, MSR_AMD_PSTATE_STATUS, &val))
92 return -1;
93
94 pscur = val & 0x7;
95
96 pscur += boost_states;
97 psmax += boost_states;
98 for (i = 0; i <= psmax; i++) {
99 if (i >= MAX_HW_PSTATES) {
100 fprintf(stderr, "HW pstates [%d] exceeding max [%d]\n",
101 psmax, MAX_HW_PSTATES);
102 return -1;
103 }
104 if (read_msr(cpu, MSR_AMD_PSTATE + i, &pstate.val))
105 return -1;
106 pstates[i] = get_cof(cpu_family, pstate);
107 }
108 *no = i;
109 return 0;
110}
111
112int amd_pci_get_num_boost_states(int *active, int *states)
113{
114 struct pci_access *pci_acc;
115 int vendor_id = 0x1022;
116 int boost_dev_ids[4] = {0x1204, 0x1604, 0x1704, 0};
117 struct pci_dev *device;
118 uint8_t val = 0;
119
120 *active = *states = 0;
121
122 device = pci_acc_init(&pci_acc, vendor_id, boost_dev_ids);
123
124 if (device == NULL)
125 return -ENODEV;
126
127 val = pci_read_byte(device, 0x15c);
128 if (val & 3)
129 *active = 1;
130 else
131 *active = 0;
132 *states = (val >> 2) & 7;
133
134 pci_cleanup(pci_acc);
135 return 0;
136}
137#endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/helpers/bitmask.c b/tools/power/cpupower/utils/helpers/bitmask.c
new file mode 100644
index 00000000000..5c074c60f90
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/bitmask.c
@@ -0,0 +1,292 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include <helpers/bitmask.h>
6
7/* How many bits in an unsigned long */
8#define bitsperlong (8 * sizeof(unsigned long))
9
10/* howmany(a,b) : how many elements of size b needed to hold all of a */
11#define howmany(x, y) (((x)+((y)-1))/(y))
12
13/* How many longs in mask of n bits */
14#define longsperbits(n) howmany(n, bitsperlong)
15
16#define max(a, b) ((a) > (b) ? (a) : (b))
17
18/*
19 * Allocate and free `struct bitmask *`
20 */
21
22/* Allocate a new `struct bitmask` with a size of n bits */
23struct bitmask *bitmask_alloc(unsigned int n)
24{
25 struct bitmask *bmp;
26
27 bmp = malloc(sizeof(*bmp));
28 if (bmp == 0)
29 return 0;
30 bmp->size = n;
31 bmp->maskp = calloc(longsperbits(n), sizeof(unsigned long));
32 if (bmp->maskp == 0) {
33 free(bmp);
34 return 0;
35 }
36 return bmp;
37}
38
39/* Free `struct bitmask` */
40void bitmask_free(struct bitmask *bmp)
41{
42 if (bmp == 0)
43 return;
44 free(bmp->maskp);
45 bmp->maskp = (unsigned long *)0xdeadcdef; /* double free tripwire */
46 free(bmp);
47}
48
49/*
50 * The routines _getbit() and _setbit() are the only
51 * routines that actually understand the layout of bmp->maskp[].
52 *
53 * On little endian architectures, this could simply be an array of
54 * bytes. But the kernel layout of bitmasks _is_ visible to userspace
55 * via the sched_(set/get)affinity calls in Linux 2.6, and on big
56 * endian architectures, it is painfully obvious that this is an
57 * array of unsigned longs.
58 */
59
60/* Return the value (0 or 1) of bit n in bitmask bmp */
61static unsigned int _getbit(const struct bitmask *bmp, unsigned int n)
62{
63 if (n < bmp->size)
64 return (bmp->maskp[n/bitsperlong] >> (n % bitsperlong)) & 1;
65 else
66 return 0;
67}
68
69/* Set bit n in bitmask bmp to value v (0 or 1) */
70static void _setbit(struct bitmask *bmp, unsigned int n, unsigned int v)
71{
72 if (n < bmp->size) {
73 if (v)
74 bmp->maskp[n/bitsperlong] |= 1UL << (n % bitsperlong);
75 else
76 bmp->maskp[n/bitsperlong] &=
77 ~(1UL << (n % bitsperlong));
78 }
79}
80
81/*
82 * When parsing bitmask lists, only allow numbers, separated by one
83 * of the allowed next characters.
84 *
85 * The parameter 'sret' is the return from a sscanf "%u%c". It is
86 * -1 if the sscanf input string was empty. It is 0 if the first
87 * character in the sscanf input string was not a decimal number.
88 * It is 1 if the unsigned number matching the "%u" was the end of the
89 * input string. It is 2 if one or more additional characters followed
90 * the matched unsigned number. If it is 2, then 'nextc' is the first
91 * character following the number. The parameter 'ok_next_chars'
92 * is the nul-terminated list of allowed next characters.
93 *
94 * The mask term just scanned was ok if and only if either the numbers
95 * matching the %u were all of the input or if the next character in
96 * the input past the numbers was one of the allowed next characters.
97 */
98static int scan_was_ok(int sret, char nextc, const char *ok_next_chars)
99{
100 return sret == 1 ||
101 (sret == 2 && strchr(ok_next_chars, nextc) != NULL);
102}
103
104static const char *nexttoken(const char *q, int sep)
105{
106 if (q)
107 q = strchr(q, sep);
108 if (q)
109 q++;
110 return q;
111}
112
113/* Set a single bit i in bitmask */
114struct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i)
115{
116 _setbit(bmp, i, 1);
117 return bmp;
118}
119
120/* Set all bits in bitmask: bmp = ~0 */
121struct bitmask *bitmask_setall(struct bitmask *bmp)
122{
123 unsigned int i;
124 for (i = 0; i < bmp->size; i++)
125 _setbit(bmp, i, 1);
126 return bmp;
127}
128
129/* Clear all bits in bitmask: bmp = 0 */
130struct bitmask *bitmask_clearall(struct bitmask *bmp)
131{
132 unsigned int i;
133 for (i = 0; i < bmp->size; i++)
134 _setbit(bmp, i, 0);
135 return bmp;
136}
137
138/* True if all bits are clear */
139int bitmask_isallclear(const struct bitmask *bmp)
140{
141 unsigned int i;
142 for (i = 0; i < bmp->size; i++)
143 if (_getbit(bmp, i))
144 return 0;
145 return 1;
146}
147
148/* True if specified bit i is set */
149int bitmask_isbitset(const struct bitmask *bmp, unsigned int i)
150{
151 return _getbit(bmp, i);
152}
153
154/* Number of lowest set bit (min) */
155unsigned int bitmask_first(const struct bitmask *bmp)
156{
157 return bitmask_next(bmp, 0);
158}
159
160/* Number of highest set bit (max) */
161unsigned int bitmask_last(const struct bitmask *bmp)
162{
163 unsigned int i;
164 unsigned int m = bmp->size;
165 for (i = 0; i < bmp->size; i++)
166 if (_getbit(bmp, i))
167 m = i;
168 return m;
169}
170
171/* Number of next set bit at or above given bit i */
172unsigned int bitmask_next(const struct bitmask *bmp, unsigned int i)
173{
174 unsigned int n;
175 for (n = i; n < bmp->size; n++)
176 if (_getbit(bmp, n))
177 break;
178 return n;
179}
180
181/*
182 * Parses a comma-separated list of numbers and ranges of numbers,
183 * with optional ':%u' strides modifying ranges, into provided bitmask.
184 * Some examples of input lists and their equivalent simple list:
185 * Input Equivalent to
186 * 0-3 0,1,2,3
187 * 0-7:2 0,2,4,6
188 * 1,3,5-7 1,3,5,6,7
189 * 0-3:2,8-15:4 0,2,8,12
190 */
191int bitmask_parselist(const char *buf, struct bitmask *bmp)
192{
193 const char *p, *q;
194
195 bitmask_clearall(bmp);
196
197 q = buf;
198 while (p = q, q = nexttoken(q, ','), p) {
199 unsigned int a; /* begin of range */
200 unsigned int b; /* end of range */
201 unsigned int s; /* stride */
202 const char *c1, *c2; /* next tokens after '-' or ',' */
203 char nextc; /* char after sscanf %u match */
204 int sret; /* sscanf return (number of matches) */
205
206 sret = sscanf(p, "%u%c", &a, &nextc);
207 if (!scan_was_ok(sret, nextc, ",-"))
208 goto err;
209 b = a;
210 s = 1;
211 c1 = nexttoken(p, '-');
212 c2 = nexttoken(p, ',');
213 if (c1 != NULL && (c2 == NULL || c1 < c2)) {
214 sret = sscanf(c1, "%u%c", &b, &nextc);
215 if (!scan_was_ok(sret, nextc, ",:"))
216 goto err;
217 c1 = nexttoken(c1, ':');
218 if (c1 != NULL && (c2 == NULL || c1 < c2)) {
219 sret = sscanf(c1, "%u%c", &s, &nextc);
220 if (!scan_was_ok(sret, nextc, ","))
221 goto err;
222 }
223 }
224 if (!(a <= b))
225 goto err;
226 if (b >= bmp->size)
227 goto err;
228 while (a <= b) {
229 _setbit(bmp, a, 1);
230 a += s;
231 }
232 }
233 return 0;
234err:
235 bitmask_clearall(bmp);
236 return -1;
237}
238
239/*
240 * emit(buf, buflen, rbot, rtop, len)
241 *
242 * Helper routine for bitmask_displaylist(). Write decimal number
243 * or range to buf+len, suppressing output past buf+buflen, with optional
244 * comma-prefix. Return len of what would be written to buf, if it
245 * all fit.
246 */
247
248static inline int emit(char *buf, int buflen, int rbot, int rtop, int len)
249{
250 if (len > 0)
251 len += snprintf(buf + len, max(buflen - len, 0), ",");
252 if (rbot == rtop)
253 len += snprintf(buf + len, max(buflen - len, 0), "%d", rbot);
254 else
255 len += snprintf(buf + len, max(buflen - len, 0), "%d-%d",
256 rbot, rtop);
257 return len;
258}
259
260/*
261 * Write decimal list representation of bmp to buf.
262 *
263 * Output format is a comma-separated list of decimal numbers and
264 * ranges. Consecutively set bits are shown as two hyphen-separated
265 * decimal numbers, the smallest and largest bit numbers set in
266 * the range. Output format is compatible with the format
267 * accepted as input by bitmap_parselist().
268 *
269 * The return value is the number of characters which would be
270 * generated for the given input, excluding the trailing '\0', as
271 * per ISO C99.
272 */
273
274int bitmask_displaylist(char *buf, int buflen, const struct bitmask *bmp)
275{
276 int len = 0;
277 /* current bit is 'cur', most recently seen range is [rbot, rtop] */
278 unsigned int cur, rbot, rtop;
279
280 if (buflen > 0)
281 *buf = 0;
282 rbot = cur = bitmask_first(bmp);
283 while (cur < bmp->size) {
284 rtop = cur;
285 cur = bitmask_next(bmp, cur+1);
286 if (cur >= bmp->size || cur > rtop + 1) {
287 len = emit(buf, buflen, rbot, rtop, len);
288 rbot = cur;
289 }
290 }
291 return len;
292}
diff --git a/tools/power/cpupower/utils/helpers/bitmask.h b/tools/power/cpupower/utils/helpers/bitmask.h
new file mode 100644
index 00000000000..eb289df4105
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/bitmask.h
@@ -0,0 +1,33 @@
1#ifndef __CPUPOWER_BITMASK__
2#define __CPUPOWER_BITMASK__
3
4/* Taken over from libbitmask, a project initiated from sgi:
5 * Url: http://oss.sgi.com/projects/cpusets/
6 * Unfortunately it's not very widespread, therefore relevant parts are
7 * pasted here.
8 */
9
10struct bitmask {
11 unsigned int size;
12 unsigned long *maskp;
13};
14
15struct bitmask *bitmask_alloc(unsigned int n);
16void bitmask_free(struct bitmask *bmp);
17
18struct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i);
19struct bitmask *bitmask_setall(struct bitmask *bmp);
20struct bitmask *bitmask_clearall(struct bitmask *bmp);
21
22unsigned int bitmask_first(const struct bitmask *bmp);
23unsigned int bitmask_next(const struct bitmask *bmp, unsigned int i);
24unsigned int bitmask_last(const struct bitmask *bmp);
25int bitmask_isallclear(const struct bitmask *bmp);
26int bitmask_isbitset(const struct bitmask *bmp, unsigned int i);
27
28int bitmask_parselist(const char *buf, struct bitmask *bmp);
29int bitmask_displaylist(char *buf, int len, const struct bitmask *bmp);
30
31
32
33#endif /*__CPUPOWER_BITMASK__ */
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
new file mode 100644
index 00000000000..906895d21cc
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
@@ -0,0 +1,176 @@
1#include <stdio.h>
2#include <errno.h>
3#include <string.h>
4#include <unistd.h>
5#include <stdlib.h>
6
7#include "helpers/helpers.h"
8
9static const char *cpu_vendor_table[X86_VENDOR_MAX] = {
10 "Unknown", "GenuineIntel", "AuthenticAMD",
11};
12
13#if defined(__i386__) || defined(__x86_64__)
14
15/* from gcc */
16#include <cpuid.h>
17
18/*
19 * CPUID functions returning a single datum
20 *
21 * Define unsigned int cpuid_e[abcd]x(unsigned int op)
22 */
23#define cpuid_func(reg) \
24 unsigned int cpuid_##reg(unsigned int op) \
25 { \
26 unsigned int eax, ebx, ecx, edx; \
27 __cpuid(op, eax, ebx, ecx, edx); \
28 return reg; \
29 }
30cpuid_func(eax);
31cpuid_func(ebx);
32cpuid_func(ecx);
33cpuid_func(edx);
34
35#endif /* defined(__i386__) || defined(__x86_64__) */
36
37/* get_cpu_info
38 *
39 * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo
40 *
41 * Returns 0 on success or a negativ error code
42 *
43 * TBD: Should there be a cpuid alternative for this if /proc is not mounted?
44 */
45int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info)
46{
47 FILE *fp;
48 char value[64];
49 unsigned int proc, x;
50 unsigned int unknown = 0xffffff;
51 unsigned int cpuid_level, ext_cpuid_level;
52
53 int ret = -EINVAL;
54
55 cpu_info->vendor = X86_VENDOR_UNKNOWN;
56 cpu_info->family = unknown;
57 cpu_info->model = unknown;
58 cpu_info->stepping = unknown;
59 cpu_info->caps = 0;
60
61 fp = fopen("/proc/cpuinfo", "r");
62 if (!fp)
63 return -EIO;
64
65 while (!feof(fp)) {
66 if (!fgets(value, 64, fp))
67 continue;
68 value[63 - 1] = '\0';
69
70 if (!strncmp(value, "processor\t: ", 12))
71 sscanf(value, "processor\t: %u", &proc);
72
73 if (proc != cpu)
74 continue;
75
76 /* Get CPU vendor */
77 if (!strncmp(value, "vendor_id", 9)) {
78 for (x = 1; x < X86_VENDOR_MAX; x++) {
79 if (strstr(value, cpu_vendor_table[x]))
80 cpu_info->vendor = x;
81 }
82 /* Get CPU family, etc. */
83 } else if (!strncmp(value, "cpu family\t: ", 13)) {
84 sscanf(value, "cpu family\t: %u",
85 &cpu_info->family);
86 } else if (!strncmp(value, "model\t\t: ", 9)) {
87 sscanf(value, "model\t\t: %u",
88 &cpu_info->model);
89 } else if (!strncmp(value, "stepping\t: ", 10)) {
90 sscanf(value, "stepping\t: %u",
91 &cpu_info->stepping);
92
93 /* Exit -> all values must have been set */
94 if (cpu_info->vendor == X86_VENDOR_UNKNOWN ||
95 cpu_info->family == unknown ||
96 cpu_info->model == unknown ||
97 cpu_info->stepping == unknown) {
98 ret = -EINVAL;
99 goto out;
100 }
101
102 ret = 0;
103 goto out;
104 }
105 }
106 ret = -ENODEV;
107out:
108 fclose(fp);
109 /* Get some useful CPU capabilities from cpuid */
110 if (cpu_info->vendor != X86_VENDOR_AMD &&
111 cpu_info->vendor != X86_VENDOR_INTEL)
112 return ret;
113
114 cpuid_level = cpuid_eax(0);
115 ext_cpuid_level = cpuid_eax(0x80000000);
116
117 /* Invariant TSC */
118 if (ext_cpuid_level >= 0x80000007 &&
119 (cpuid_edx(0x80000007) & (1 << 8)))
120 cpu_info->caps |= CPUPOWER_CAP_INV_TSC;
121
122 /* Aperf/Mperf registers support */
123 if (cpuid_level >= 6 && (cpuid_ecx(6) & 0x1))
124 cpu_info->caps |= CPUPOWER_CAP_APERF;
125
126 /* AMD Boost state enable/disable register */
127 if (cpu_info->vendor == X86_VENDOR_AMD) {
128 if (ext_cpuid_level >= 0x80000007 &&
129 (cpuid_edx(0x80000007) & (1 << 9)))
130 cpu_info->caps |= CPUPOWER_CAP_AMD_CBP;
131 }
132
133 if (cpu_info->vendor == X86_VENDOR_INTEL) {
134 if (cpuid_level >= 6 &&
135 (cpuid_eax(6) & (1 << 1)))
136 cpu_info->caps |= CPUPOWER_CAP_INTEL_IDA;
137 }
138
139 if (cpu_info->vendor == X86_VENDOR_INTEL) {
140 /* Intel's perf-bias MSR support */
141 if (cpuid_level >= 6 && (cpuid_ecx(6) & (1 << 3)))
142 cpu_info->caps |= CPUPOWER_CAP_PERF_BIAS;
143
144 /* Intel's Turbo Ratio Limit support */
145 if (cpu_info->family == 6) {
146 switch (cpu_info->model) {
147 case 0x1A: /* Core i7, Xeon 5500 series
148 * Bloomfield, Gainstown NHM-EP
149 */
150 case 0x1E: /* Core i7 and i5 Processor
151 * Clarksfield, Lynnfield, Jasper Forest
152 */
153 case 0x1F: /* Core i7 and i5 Processor - Nehalem */
154 case 0x25: /* Westmere Client
155 * Clarkdale, Arrandale
156 */
157 case 0x2C: /* Westmere EP - Gulftown */
158 cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
159 case 0x2A: /* SNB */
160 case 0x2D: /* SNB Xeon */
161 cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
162 cpu_info->caps |= CPUPOWER_CAP_IS_SNB;
163 break;
164 case 0x2E: /* Nehalem-EX Xeon - Beckton */
165 case 0x2F: /* Westmere-EX Xeon - Eagleton */
166 default:
167 break;
168 }
169 }
170 }
171
172 /* printf("ID: %u - Extid: 0x%x - Caps: 0x%llx\n",
173 cpuid_level, ext_cpuid_level, cpu_info->caps);
174 */
175 return ret;
176}
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
new file mode 100644
index 00000000000..2747e738efb
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -0,0 +1,190 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Miscellaneous helpers which do not fit or are worth
7 * to put into separate headers
8 */
9
10#ifndef __CPUPOWERUTILS_HELPERS__
11#define __CPUPOWERUTILS_HELPERS__
12
13#include <libintl.h>
14#include <locale.h>
15
16#include "helpers/bitmask.h"
17
18/* Internationalization ****************************/
19#ifdef NLS
20
21#define _(String) gettext(String)
22#ifndef gettext_noop
23#define gettext_noop(String) String
24#endif
25#define N_(String) gettext_noop(String)
26
27#else /* !NLS */
28
29#define _(String) String
30#define N_(String) String
31
32#endif
33/* Internationalization ****************************/
34
35extern int run_as_root;
36extern struct bitmask *cpus_chosen;
37
38/* Global verbose (-d) stuff *********************************/
39/*
40 * define DEBUG via global Makefile variable
41 * Debug output is sent to stderr, do:
42 * cpupower monitor 2>/tmp/debug
43 * to split debug output away from normal output
44*/
45#ifdef DEBUG
46extern int be_verbose;
47
48#define dprint(fmt, ...) { \
49 if (be_verbose) { \
50 fprintf(stderr, "%s: " fmt, \
51 __func__, ##__VA_ARGS__); \
52 } \
53 }
54#else
55static inline void dprint(const char *fmt, ...) { }
56#endif
57extern int be_verbose;
58/* Global verbose (-v) stuff *********************************/
59
60/* cpuid and cpuinfo helpers **************************/
61enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
62 X86_VENDOR_AMD, X86_VENDOR_MAX};
63
64#define CPUPOWER_CAP_INV_TSC 0x00000001
65#define CPUPOWER_CAP_APERF 0x00000002
66#define CPUPOWER_CAP_AMD_CBP 0x00000004
67#define CPUPOWER_CAP_PERF_BIAS 0x00000008
68#define CPUPOWER_CAP_HAS_TURBO_RATIO 0x00000010
69#define CPUPOWER_CAP_IS_SNB 0x00000011
70#define CPUPOWER_CAP_INTEL_IDA 0x00000012
71
72#define MAX_HW_PSTATES 10
73
74struct cpupower_cpu_info {
75 enum cpupower_cpu_vendor vendor;
76 unsigned int family;
77 unsigned int model;
78 unsigned int stepping;
79 /* CPU capabilities read out from cpuid */
80 unsigned long long caps;
81};
82
83/* get_cpu_info
84 *
85 * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo
86 *
87 * Returns 0 on success or a negativ error code
88 * Only used on x86, below global's struct values are zero/unknown on
89 * other archs
90 */
91extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info);
92extern struct cpupower_cpu_info cpupower_cpu_info;
93/* cpuid and cpuinfo helpers **************************/
94
95
96/* CPU topology/hierarchy parsing ******************/
97struct cpupower_topology {
98 /* Amount of CPU cores, packages and threads per core in the system */
99 unsigned int cores;
100 unsigned int pkgs;
101 unsigned int threads; /* per core */
102
103 /* Array gets mallocated with cores entries, holding per core info */
104 struct {
105 int pkg;
106 int core;
107 int cpu;
108
109 /* flags */
110 unsigned int is_online:1;
111 } *core_info;
112};
113
114extern int get_cpu_topology(struct cpupower_topology *cpu_top);
115extern void cpu_topology_release(struct cpupower_topology cpu_top);
116/* CPU topology/hierarchy parsing ******************/
117
118/* X86 ONLY ****************************************/
119#if defined(__i386__) || defined(__x86_64__)
120
121#include <pci/pci.h>
122
123/* Read/Write msr ****************************/
124extern int read_msr(int cpu, unsigned int idx, unsigned long long *val);
125extern int write_msr(int cpu, unsigned int idx, unsigned long long val);
126
127extern int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val);
128extern int msr_intel_get_perf_bias(unsigned int cpu);
129extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu);
130
131/* Read/Write msr ****************************/
132
133/* PCI stuff ****************************/
134extern int amd_pci_get_num_boost_states(int *active, int *states);
135extern struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
136 int *dev_ids);
137
138/* PCI stuff ****************************/
139
140/* AMD HW pstate decoding **************************/
141
142extern int decode_pstates(unsigned int cpu, unsigned int cpu_family,
143 int boost_states, unsigned long *pstates, int *no);
144
145/* AMD HW pstate decoding **************************/
146
147extern int cpufreq_has_boost_support(unsigned int cpu, int *support,
148 int *active, int * states);
149/*
150 * CPUID functions returning a single datum
151 */
152unsigned int cpuid_eax(unsigned int op);
153unsigned int cpuid_ebx(unsigned int op);
154unsigned int cpuid_ecx(unsigned int op);
155unsigned int cpuid_edx(unsigned int op);
156
157/* cpuid and cpuinfo helpers **************************/
158/* X86 ONLY ********************************************/
159#else
160static inline int decode_pstates(unsigned int cpu, unsigned int cpu_family,
161 int boost_states, unsigned long *pstates,
162 int *no)
163{ return -1; };
164
165static inline int read_msr(int cpu, unsigned int idx, unsigned long long *val)
166{ return -1; };
167static inline int write_msr(int cpu, unsigned int idx, unsigned long long val)
168{ return -1; };
169static inline int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val)
170{ return -1; };
171static inline int msr_intel_get_perf_bias(unsigned int cpu)
172{ return -1; };
173static inline unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu)
174{ return 0; };
175
176/* Read/Write msr ****************************/
177
178static inline int cpufreq_has_boost_support(unsigned int cpu, int *support,
179 int *active, int * states)
180{ return -1; }
181
182/* cpuid and cpuinfo helpers **************************/
183
184static inline unsigned int cpuid_eax(unsigned int op) { return 0; };
185static inline unsigned int cpuid_ebx(unsigned int op) { return 0; };
186static inline unsigned int cpuid_ecx(unsigned int op) { return 0; };
187static inline unsigned int cpuid_edx(unsigned int op) { return 0; };
188#endif /* defined(__i386__) || defined(__x86_64__) */
189
190#endif /* __CPUPOWERUTILS_HELPERS__ */
diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c
new file mode 100644
index 00000000000..1609243f5c6
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/misc.c
@@ -0,0 +1,27 @@
1#if defined(__i386__) || defined(__x86_64__)
2
3#include "helpers/helpers.h"
4
5int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active,
6 int *states)
7{
8 struct cpupower_cpu_info cpu_info;
9 int ret;
10
11 *support = *active = *states = 0;
12
13 ret = get_cpu_info(0, &cpu_info);
14 if (ret)
15 return ret;
16
17 if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CBP) {
18 *support = 1;
19 amd_pci_get_num_boost_states(active, states);
20 if (ret <= 0)
21 return ret;
22 *support = 1;
23 } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA)
24 *support = *active = 1;
25 return 0;
26}
27#endif /* #if defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/helpers/msr.c b/tools/power/cpupower/utils/helpers/msr.c
new file mode 100644
index 00000000000..31a4b24a8bc
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/msr.c
@@ -0,0 +1,115 @@
1#if defined(__i386__) || defined(__x86_64__)
2
3#include <fcntl.h>
4#include <stdio.h>
5#include <unistd.h>
6#include <stdint.h>
7
8#include "helpers/helpers.h"
9
10/* Intel specific MSRs */
11#define MSR_IA32_PERF_STATUS 0x198
12#define MSR_IA32_MISC_ENABLES 0x1a0
13#define MSR_IA32_ENERGY_PERF_BIAS 0x1b0
14#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1ad
15
16/*
17 * read_msr
18 *
19 * Will return 0 on success and -1 on failure.
20 * Possible errno values could be:
21 * EFAULT -If the read/write did not fully complete
22 * EIO -If the CPU does not support MSRs
23 * ENXIO -If the CPU does not exist
24 */
25
26int read_msr(int cpu, unsigned int idx, unsigned long long *val)
27{
28 int fd;
29 char msr_file_name[64];
30
31 sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
32 fd = open(msr_file_name, O_RDONLY);
33 if (fd < 0)
34 return -1;
35 if (lseek(fd, idx, SEEK_CUR) == -1)
36 goto err;
37 if (read(fd, val, sizeof *val) != sizeof *val)
38 goto err;
39 close(fd);
40 return 0;
41 err:
42 close(fd);
43 return -1;
44}
45
46/*
47 * write_msr
48 *
49 * Will return 0 on success and -1 on failure.
50 * Possible errno values could be:
51 * EFAULT -If the read/write did not fully complete
52 * EIO -If the CPU does not support MSRs
53 * ENXIO -If the CPU does not exist
54 */
55int write_msr(int cpu, unsigned int idx, unsigned long long val)
56{
57 int fd;
58 char msr_file_name[64];
59
60 sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu);
61 fd = open(msr_file_name, O_WRONLY);
62 if (fd < 0)
63 return -1;
64 if (lseek(fd, idx, SEEK_CUR) == -1)
65 goto err;
66 if (write(fd, &val, sizeof val) != sizeof val)
67 goto err;
68 close(fd);
69 return 0;
70 err:
71 close(fd);
72 return -1;
73}
74
75int msr_intel_get_perf_bias(unsigned int cpu)
76{
77 unsigned long long val;
78 int ret;
79
80 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS))
81 return -1;
82
83 ret = read_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &val);
84 if (ret)
85 return ret;
86 return val;
87}
88
89int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val)
90{
91 int ret;
92
93 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS))
94 return -1;
95
96 ret = write_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, val);
97 if (ret)
98 return ret;
99 return 0;
100}
101
102unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu)
103{
104 unsigned long long val;
105 int ret;
106
107 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO))
108 return -1;
109
110 ret = read_msr(cpu, MSR_NEHALEM_TURBO_RATIO_LIMIT, &val);
111 if (ret)
112 return ret;
113 return val;
114}
115#endif
diff --git a/tools/power/cpupower/utils/helpers/pci.c b/tools/power/cpupower/utils/helpers/pci.c
new file mode 100644
index 00000000000..cd2eb6fe41c
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/pci.c
@@ -0,0 +1,44 @@
1#if defined(__i386__) || defined(__x86_64__)
2
3#include <helpers/helpers.h>
4
5/*
6 * pci_acc_init
7 *
8 * PCI access helper function depending on libpci
9 *
10 * **pacc : if a valid pci_dev is returned
11 * *pacc must be passed to pci_acc_cleanup to free it
12 *
13 * vendor_id : the pci vendor id matching the pci device to access
14 * dev_ids : device ids matching the pci device to access
15 *
16 * Returns :
17 * struct pci_dev which can be used with pci_{read,write}_* functions
18 * to access the PCI config space of matching pci devices
19 */
20struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id,
21 int *dev_ids)
22{
23 struct pci_filter filter_nb_link = { -1, -1, -1, -1, vendor_id, 0};
24 struct pci_dev *device;
25 unsigned int i;
26
27 *pacc = pci_alloc();
28 if (*pacc == NULL)
29 return NULL;
30
31 pci_init(*pacc);
32 pci_scan_bus(*pacc);
33
34 for (i = 0; dev_ids[i] != 0; i++) {
35 filter_nb_link.device = dev_ids[i];
36 for (device = (*pacc)->devices; device; device = device->next) {
37 if (pci_filter_match(&filter_nb_link, device))
38 return device;
39 }
40 }
41 pci_cleanup(*pacc);
42 return NULL;
43}
44#endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c
new file mode 100644
index 00000000000..c6343024a61
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/sysfs.c
@@ -0,0 +1,408 @@
1/*
2 * (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
3 * (C) 2011 Thomas Renninger <trenn@novell.com> Novell Inc.
4 *
5 * Licensed under the terms of the GNU GPL License version 2.
6 */
7
8#include <stdio.h>
9#include <errno.h>
10#include <stdlib.h>
11#include <string.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <fcntl.h>
15#include <unistd.h>
16
17#include "helpers/sysfs.h"
18
19unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
20{
21 int fd;
22 ssize_t numread;
23
24 fd = open(path, O_RDONLY);
25 if (fd == -1)
26 return 0;
27
28 numread = read(fd, buf, buflen - 1);
29 if (numread < 1) {
30 close(fd);
31 return 0;
32 }
33
34 buf[numread] = '\0';
35 close(fd);
36
37 return (unsigned int) numread;
38}
39
40static unsigned int sysfs_write_file(const char *path,
41 const char *value, size_t len)
42{
43 int fd;
44 ssize_t numwrite;
45
46 fd = open(path, O_WRONLY);
47 if (fd == -1)
48 return 0;
49
50 numwrite = write(fd, value, len);
51 if (numwrite < 1) {
52 close(fd);
53 return 0;
54 }
55 close(fd);
56 return (unsigned int) numwrite;
57}
58
59/*
60 * Detect whether a CPU is online
61 *
62 * Returns:
63 * 1 -> if CPU is online
64 * 0 -> if CPU is offline
65 * negative errno values in error case
66 */
67int sysfs_is_cpu_online(unsigned int cpu)
68{
69 char path[SYSFS_PATH_MAX];
70 int fd;
71 ssize_t numread;
72 unsigned long long value;
73 char linebuf[MAX_LINE_LEN];
74 char *endp;
75 struct stat statbuf;
76
77 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u", cpu);
78
79 if (stat(path, &statbuf) != 0)
80 return 0;
81
82 /*
83 * kernel without CONFIG_HOTPLUG_CPU
84 * -> cpuX directory exists, but not cpuX/online file
85 */
86 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/online", cpu);
87 if (stat(path, &statbuf) != 0)
88 return 1;
89
90 fd = open(path, O_RDONLY);
91 if (fd == -1)
92 return -errno;
93
94 numread = read(fd, linebuf, MAX_LINE_LEN - 1);
95 if (numread < 1) {
96 close(fd);
97 return -EIO;
98 }
99 linebuf[numread] = '\0';
100 close(fd);
101
102 value = strtoull(linebuf, &endp, 0);
103 if (value > 1 || value < 0)
104 return -EINVAL;
105
106 return value;
107}
108
109/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
110
111/*
112 * helper function to read file from /sys into given buffer
113 * fname is a relative path under "cpuX/cpuidle/stateX/" dir
114 * cstates starting with 0, C0 is not counted as cstate.
115 * This means if you want C1 info, pass 0 as idlestate param
116 */
117unsigned int sysfs_idlestate_read_file(unsigned int cpu, unsigned int idlestate,
118 const char *fname, char *buf, size_t buflen)
119{
120 char path[SYSFS_PATH_MAX];
121 int fd;
122 ssize_t numread;
123
124 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s",
125 cpu, idlestate, fname);
126
127 fd = open(path, O_RDONLY);
128 if (fd == -1)
129 return 0;
130
131 numread = read(fd, buf, buflen - 1);
132 if (numread < 1) {
133 close(fd);
134 return 0;
135 }
136
137 buf[numread] = '\0';
138 close(fd);
139
140 return (unsigned int) numread;
141}
142
143/* read access to files which contain one numeric value */
144
145enum idlestate_value {
146 IDLESTATE_USAGE,
147 IDLESTATE_POWER,
148 IDLESTATE_LATENCY,
149 IDLESTATE_TIME,
150 MAX_IDLESTATE_VALUE_FILES
151};
152
153static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = {
154 [IDLESTATE_USAGE] = "usage",
155 [IDLESTATE_POWER] = "power",
156 [IDLESTATE_LATENCY] = "latency",
157 [IDLESTATE_TIME] = "time",
158};
159
160static unsigned long long sysfs_idlestate_get_one_value(unsigned int cpu,
161 unsigned int idlestate,
162 enum idlestate_value which)
163{
164 unsigned long long value;
165 unsigned int len;
166 char linebuf[MAX_LINE_LEN];
167 char *endp;
168
169 if (which >= MAX_IDLESTATE_VALUE_FILES)
170 return 0;
171
172 len = sysfs_idlestate_read_file(cpu, idlestate,
173 idlestate_value_files[which],
174 linebuf, sizeof(linebuf));
175 if (len == 0)
176 return 0;
177
178 value = strtoull(linebuf, &endp, 0);
179
180 if (endp == linebuf || errno == ERANGE)
181 return 0;
182
183 return value;
184}
185
186/* read access to files which contain one string */
187
188enum idlestate_string {
189 IDLESTATE_DESC,
190 IDLESTATE_NAME,
191 MAX_IDLESTATE_STRING_FILES
192};
193
194static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = {
195 [IDLESTATE_DESC] = "desc",
196 [IDLESTATE_NAME] = "name",
197};
198
199
200static char *sysfs_idlestate_get_one_string(unsigned int cpu,
201 unsigned int idlestate,
202 enum idlestate_string which)
203{
204 char linebuf[MAX_LINE_LEN];
205 char *result;
206 unsigned int len;
207
208 if (which >= MAX_IDLESTATE_STRING_FILES)
209 return NULL;
210
211 len = sysfs_idlestate_read_file(cpu, idlestate,
212 idlestate_string_files[which],
213 linebuf, sizeof(linebuf));
214 if (len == 0)
215 return NULL;
216
217 result = strdup(linebuf);
218 if (result == NULL)
219 return NULL;
220
221 if (result[strlen(result) - 1] == '\n')
222 result[strlen(result) - 1] = '\0';
223
224 return result;
225}
226
227unsigned long sysfs_get_idlestate_latency(unsigned int cpu,
228 unsigned int idlestate)
229{
230 return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_LATENCY);
231}
232
233unsigned long sysfs_get_idlestate_usage(unsigned int cpu,
234 unsigned int idlestate)
235{
236 return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_USAGE);
237}
238
239unsigned long long sysfs_get_idlestate_time(unsigned int cpu,
240 unsigned int idlestate)
241{
242 return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_TIME);
243}
244
245char *sysfs_get_idlestate_name(unsigned int cpu, unsigned int idlestate)
246{
247 return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_NAME);
248}
249
250char *sysfs_get_idlestate_desc(unsigned int cpu, unsigned int idlestate)
251{
252 return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_DESC);
253}
254
255/*
256 * Returns number of supported C-states of CPU core cpu
257 * Negativ in error case
258 * Zero if cpuidle does not export any C-states
259 */
260int sysfs_get_idlestate_count(unsigned int cpu)
261{
262 char file[SYSFS_PATH_MAX];
263 struct stat statbuf;
264 int idlestates = 1;
265
266
267 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle");
268 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
269 return -ENODEV;
270
271 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu);
272 if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
273 return 0;
274
275 while (stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) {
276 snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU
277 "cpu%u/cpuidle/state%d", cpu, idlestates);
278 idlestates++;
279 }
280 idlestates--;
281 return idlestates;
282}
283
284/* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/
285
286/*
287 * helper function to read file from /sys into given buffer
288 * fname is a relative path under "cpu/cpuidle/" dir
289 */
290static unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf,
291 size_t buflen)
292{
293 char path[SYSFS_PATH_MAX];
294
295 snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname);
296
297 return sysfs_read_file(path, buf, buflen);
298}
299
300
301
302/* read access to files which contain one string */
303
304enum cpuidle_string {
305 CPUIDLE_GOVERNOR,
306 CPUIDLE_GOVERNOR_RO,
307 CPUIDLE_DRIVER,
308 MAX_CPUIDLE_STRING_FILES
309};
310
311static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = {
312 [CPUIDLE_GOVERNOR] = "current_governor",
313 [CPUIDLE_GOVERNOR_RO] = "current_governor_ro",
314 [CPUIDLE_DRIVER] = "current_driver",
315};
316
317
318static char *sysfs_cpuidle_get_one_string(enum cpuidle_string which)
319{
320 char linebuf[MAX_LINE_LEN];
321 char *result;
322 unsigned int len;
323
324 if (which >= MAX_CPUIDLE_STRING_FILES)
325 return NULL;
326
327 len = sysfs_cpuidle_read_file(cpuidle_string_files[which],
328 linebuf, sizeof(linebuf));
329 if (len == 0)
330 return NULL;
331
332 result = strdup(linebuf);
333 if (result == NULL)
334 return NULL;
335
336 if (result[strlen(result) - 1] == '\n')
337 result[strlen(result) - 1] = '\0';
338
339 return result;
340}
341
342char *sysfs_get_cpuidle_governor(void)
343{
344 char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO);
345 if (!tmp)
346 return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR);
347 else
348 return tmp;
349}
350
351char *sysfs_get_cpuidle_driver(void)
352{
353 return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER);
354}
355/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
356
357/*
358 * Get sched_mc or sched_smt settings
359 * Pass "mc" or "smt" as argument
360 *
361 * Returns negative value on failure
362 */
363int sysfs_get_sched(const char *smt_mc)
364{
365 unsigned long value;
366 char linebuf[MAX_LINE_LEN];
367 char *endp;
368 char path[SYSFS_PATH_MAX];
369
370 if (strcmp("mc", smt_mc) && strcmp("smt", smt_mc))
371 return -EINVAL;
372
373 snprintf(path, sizeof(path),
374 PATH_TO_CPU "sched_%s_power_savings", smt_mc);
375 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
376 return -1;
377 value = strtoul(linebuf, &endp, 0);
378 if (endp == linebuf || errno == ERANGE)
379 return -1;
380 return value;
381}
382
383/*
384 * Get sched_mc or sched_smt settings
385 * Pass "mc" or "smt" as argument
386 *
387 * Returns negative value on failure
388 */
389int sysfs_set_sched(const char *smt_mc, int val)
390{
391 char linebuf[MAX_LINE_LEN];
392 char path[SYSFS_PATH_MAX];
393 struct stat statbuf;
394
395 if (strcmp("mc", smt_mc) && strcmp("smt", smt_mc))
396 return -EINVAL;
397
398 snprintf(path, sizeof(path),
399 PATH_TO_CPU "sched_%s_power_savings", smt_mc);
400 sprintf(linebuf, "%d", val);
401
402 if (stat(path, &statbuf) != 0)
403 return -ENODEV;
404
405 if (sysfs_write_file(path, linebuf, MAX_LINE_LEN) == 0)
406 return -1;
407 return 0;
408}
diff --git a/tools/power/cpupower/utils/helpers/sysfs.h b/tools/power/cpupower/utils/helpers/sysfs.h
new file mode 100644
index 00000000000..8cb797bbceb
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/sysfs.h
@@ -0,0 +1,30 @@
1#ifndef __CPUPOWER_HELPERS_SYSFS_H__
2#define __CPUPOWER_HELPERS_SYSFS_H__
3
4#define PATH_TO_CPU "/sys/devices/system/cpu/"
5#define MAX_LINE_LEN 255
6#define SYSFS_PATH_MAX 255
7
8extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen);
9
10extern int sysfs_is_cpu_online(unsigned int cpu);
11
12extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu,
13 unsigned int idlestate);
14extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu,
15 unsigned int idlestate);
16extern unsigned long long sysfs_get_idlestate_time(unsigned int cpu,
17 unsigned int idlestate);
18extern char *sysfs_get_idlestate_name(unsigned int cpu,
19 unsigned int idlestate);
20extern char *sysfs_get_idlestate_desc(unsigned int cpu,
21 unsigned int idlestate);
22extern int sysfs_get_idlestate_count(unsigned int cpu);
23
24extern char *sysfs_get_cpuidle_governor(void);
25extern char *sysfs_get_cpuidle_driver(void);
26
27extern int sysfs_get_sched(const char *smt_mc);
28extern int sysfs_set_sched(const char *smt_mc, int val);
29
30#endif /* __CPUPOWER_HELPERS_SYSFS_H__ */
diff --git a/tools/power/cpupower/utils/helpers/topology.c b/tools/power/cpupower/utils/helpers/topology.c
new file mode 100644
index 00000000000..4eae2c47ba4
--- /dev/null
+++ b/tools/power/cpupower/utils/helpers/topology.c
@@ -0,0 +1,111 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * ToDo: Needs to be done more properly for AMD/Intel specifics
7 */
8
9/* Helper struct for qsort, must be in sync with cpupower_topology.cpu_info */
10/* Be careful: Need to pass unsigned to the sort, so that offlined cores are
11 in the end, but double check for -1 for offlined cpus at other places */
12
13#include <stdlib.h>
14#include <stdio.h>
15#include <unistd.h>
16#include <errno.h>
17#include <fcntl.h>
18
19#include <helpers/helpers.h>
20#include <helpers/sysfs.h>
21
22/* returns -1 on failure, 0 on success */
23int sysfs_topology_read_file(unsigned int cpu, const char *fname)
24{
25 unsigned long value;
26 char linebuf[MAX_LINE_LEN];
27 char *endp;
28 char path[SYSFS_PATH_MAX];
29
30 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s",
31 cpu, fname);
32 if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
33 return -1;
34 value = strtoul(linebuf, &endp, 0);
35 if (endp == linebuf || errno == ERANGE)
36 return -1;
37 return value;
38}
39
40struct cpuid_core_info {
41 unsigned int pkg;
42 unsigned int thread;
43 unsigned int cpu;
44 /* flags */
45 unsigned int is_online:1;
46};
47
48static int __compare(const void *t1, const void *t2)
49{
50 struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
51 struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2;
52 if (top1->pkg < top2->pkg)
53 return -1;
54 else if (top1->pkg > top2->pkg)
55 return 1;
56 else if (top1->thread < top2->thread)
57 return -1;
58 else if (top1->thread > top2->thread)
59 return 1;
60 else if (top1->cpu < top2->cpu)
61 return -1;
62 else if (top1->cpu > top2->cpu)
63 return 1;
64 else
65 return 0;
66}
67
68/*
69 * Returns amount of cpus, negative on error, cpu_top must be
70 * passed to cpu_topology_release to free resources
71 *
72 * Array is sorted after ->pkg, ->core, then ->cpu
73 */
74int get_cpu_topology(struct cpupower_topology *cpu_top)
75{
76 int cpu, cpus = sysconf(_SC_NPROCESSORS_CONF);
77
78 cpu_top->core_info = malloc(sizeof(struct cpupower_topology) * cpus);
79 if (cpu_top->core_info == NULL)
80 return -ENOMEM;
81 cpu_top->pkgs = cpu_top->cores = 0;
82 for (cpu = 0; cpu < cpus; cpu++) {
83 cpu_top->core_info[cpu].cpu = cpu;
84 cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
85 cpu_top->core_info[cpu].pkg =
86 sysfs_topology_read_file(cpu, "physical_package_id");
87 if ((int)cpu_top->core_info[cpu].pkg != -1 &&
88 cpu_top->core_info[cpu].pkg > cpu_top->pkgs)
89 cpu_top->pkgs = cpu_top->core_info[cpu].pkg;
90 cpu_top->core_info[cpu].core =
91 sysfs_topology_read_file(cpu, "core_id");
92 }
93 cpu_top->pkgs++;
94
95 qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
96 __compare);
97
98 /* Intel's cores count is not consecutively numbered, there may
99 * be a core_id of 3, but none of 2. Assume there always is 0
100 * Get amount of cores by counting duplicates in a package
101 for (cpu = 0; cpu_top->core_info[cpu].pkg = 0 && cpu < cpus; cpu++) {
102 if (cpu_top->core_info[cpu].core == 0)
103 cpu_top->cores++;
104 */
105 return cpus;
106}
107
108void cpu_topology_release(struct cpupower_topology cpu_top)
109{
110 free(cpu_top.core_info);
111}
diff --git a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
new file mode 100644
index 00000000000..202e555988b
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
@@ -0,0 +1,338 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * PCI initialization based on example code from:
7 * Andreas Herrmann <andreas.herrmann3@amd.com>
8 */
9
10#if defined(__i386__) || defined(__x86_64__)
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <stdint.h>
15#include <time.h>
16#include <string.h>
17
18#include <pci/pci.h>
19
20#include "idle_monitor/cpupower-monitor.h"
21#include "helpers/helpers.h"
22
23/******** PCI parts could go into own file and get shared ***************/
24
25#define PCI_NON_PC0_OFFSET 0xb0
26#define PCI_PC1_OFFSET 0xb4
27#define PCI_PC6_OFFSET 0xb8
28
29#define PCI_MONITOR_ENABLE_REG 0xe0
30
31#define PCI_NON_PC0_ENABLE_BIT 0
32#define PCI_PC1_ENABLE_BIT 1
33#define PCI_PC6_ENABLE_BIT 2
34
35#define PCI_NBP1_STAT_OFFSET 0x98
36#define PCI_NBP1_ACTIVE_BIT 2
37#define PCI_NBP1_ENTERED_BIT 1
38
39#define PCI_NBP1_CAP_OFFSET 0x90
40#define PCI_NBP1_CAPABLE_BIT 31
41
42#define OVERFLOW_MS 343597 /* 32 bit register filled at 12500 HZ
43 (1 tick per 80ns) */
44
45enum amd_fam14h_states {NON_PC0 = 0, PC1, PC6, NBP1,
46 AMD_FAM14H_STATE_NUM};
47
48static int fam14h_get_count_percent(unsigned int self_id, double *percent,
49 unsigned int cpu);
50static int fam14h_nbp1_count(unsigned int id, unsigned long long *count,
51 unsigned int cpu);
52
53static cstate_t amd_fam14h_cstates[AMD_FAM14H_STATE_NUM] = {
54 {
55 .name = "!PC0",
56 .desc = N_("Package in sleep state (PC1 or deeper)"),
57 .id = NON_PC0,
58 .range = RANGE_PACKAGE,
59 .get_count_percent = fam14h_get_count_percent,
60 },
61 {
62 .name = "PC1",
63 .desc = N_("Processor Package C1"),
64 .id = PC1,
65 .range = RANGE_PACKAGE,
66 .get_count_percent = fam14h_get_count_percent,
67 },
68 {
69 .name = "PC6",
70 .desc = N_("Processor Package C6"),
71 .id = PC6,
72 .range = RANGE_PACKAGE,
73 .get_count_percent = fam14h_get_count_percent,
74 },
75 {
76 .name = "NBP1",
77 .desc = N_("North Bridge P1 boolean counter (returns 0 or 1)"),
78 .id = NBP1,
79 .range = RANGE_PACKAGE,
80 .get_count = fam14h_nbp1_count,
81 },
82};
83
84static struct pci_access *pci_acc;
85static int pci_vendor_id = 0x1022;
86static int pci_dev_ids[2] = {0x1716, 0};
87static struct pci_dev *amd_fam14h_pci_dev;
88
89static int nbp1_entered;
90
91struct timespec start_time;
92static unsigned long long timediff;
93
94#ifdef DEBUG
95struct timespec dbg_time;
96long dbg_timediff;
97#endif
98
99static unsigned long long *previous_count[AMD_FAM14H_STATE_NUM];
100static unsigned long long *current_count[AMD_FAM14H_STATE_NUM];
101
102static int amd_fam14h_get_pci_info(struct cstate *state,
103 unsigned int *pci_offset,
104 unsigned int *enable_bit,
105 unsigned int cpu)
106{
107 switch (state->id) {
108 case NON_PC0:
109 *enable_bit = PCI_NON_PC0_ENABLE_BIT;
110 *pci_offset = PCI_NON_PC0_OFFSET;
111 break;
112 case PC1:
113 *enable_bit = PCI_PC1_ENABLE_BIT;
114 *pci_offset = PCI_PC1_OFFSET;
115 break;
116 case PC6:
117 *enable_bit = PCI_PC6_ENABLE_BIT;
118 *pci_offset = PCI_PC6_OFFSET;
119 break;
120 case NBP1:
121 *enable_bit = PCI_NBP1_ENTERED_BIT;
122 *pci_offset = PCI_NBP1_STAT_OFFSET;
123 break;
124 default:
125 return -1;
126 };
127 return 0;
128}
129
130static int amd_fam14h_init(cstate_t *state, unsigned int cpu)
131{
132 int enable_bit, pci_offset, ret;
133 uint32_t val;
134
135 ret = amd_fam14h_get_pci_info(state, &pci_offset, &enable_bit, cpu);
136 if (ret)
137 return ret;
138
139 /* NBP1 needs extra treating -> write 1 to D18F6x98 bit 1 for init */
140 if (state->id == NBP1) {
141 val = pci_read_long(amd_fam14h_pci_dev, pci_offset);
142 val |= 1 << enable_bit;
143 val = pci_write_long(amd_fam14h_pci_dev, pci_offset, val);
144 return ret;
145 }
146
147 /* Enable monitor */
148 val = pci_read_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG);
149 dprint("Init %s: read at offset: 0x%x val: %u\n", state->name,
150 PCI_MONITOR_ENABLE_REG, (unsigned int) val);
151 val |= 1 << enable_bit;
152 pci_write_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG, val);
153
154 dprint("Init %s: offset: 0x%x enable_bit: %d - val: %u (%u)\n",
155 state->name, PCI_MONITOR_ENABLE_REG, enable_bit,
156 (unsigned int) val, cpu);
157
158 /* Set counter to zero */
159 pci_write_long(amd_fam14h_pci_dev, pci_offset, 0);
160 previous_count[state->id][cpu] = 0;
161
162 return 0;
163}
164
165static int amd_fam14h_disable(cstate_t *state, unsigned int cpu)
166{
167 int enable_bit, pci_offset, ret;
168 uint32_t val;
169
170 ret = amd_fam14h_get_pci_info(state, &pci_offset, &enable_bit, cpu);
171 if (ret)
172 return ret;
173
174 val = pci_read_long(amd_fam14h_pci_dev, pci_offset);
175 dprint("%s: offset: 0x%x %u\n", state->name, pci_offset, val);
176 if (state->id == NBP1) {
177 /* was the bit whether NBP1 got entered set? */
178 nbp1_entered = (val & (1 << PCI_NBP1_ACTIVE_BIT)) |
179 (val & (1 << PCI_NBP1_ENTERED_BIT));
180
181 dprint("NBP1 was %sentered - 0x%x - enable_bit: "
182 "%d - pci_offset: 0x%x\n",
183 nbp1_entered ? "" : "not ",
184 val, enable_bit, pci_offset);
185 return ret;
186 }
187 current_count[state->id][cpu] = val;
188
189 dprint("%s: Current - %llu (%u)\n", state->name,
190 current_count[state->id][cpu], cpu);
191 dprint("%s: Previous - %llu (%u)\n", state->name,
192 previous_count[state->id][cpu], cpu);
193
194 val = pci_read_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG);
195 val &= ~(1 << enable_bit);
196 pci_write_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG, val);
197
198 return 0;
199}
200
201static int fam14h_nbp1_count(unsigned int id, unsigned long long *count,
202 unsigned int cpu)
203{
204 if (id == NBP1) {
205 if (nbp1_entered)
206 *count = 1;
207 else
208 *count = 0;
209 return 0;
210 }
211 return -1;
212}
213static int fam14h_get_count_percent(unsigned int id, double *percent,
214 unsigned int cpu)
215{
216 unsigned long diff;
217
218 if (id >= AMD_FAM14H_STATE_NUM)
219 return -1;
220 /* residency count in 80ns -> divide through 12.5 to get us residency */
221 diff = current_count[id][cpu] - previous_count[id][cpu];
222
223 if (timediff == 0)
224 *percent = 0.0;
225 else
226 *percent = 100.0 * diff / timediff / 12.5;
227
228 dprint("Timediff: %llu - res~: %lu us - percent: %.2f %%\n",
229 timediff, diff * 10 / 125, *percent);
230
231 return 0;
232}
233
234static int amd_fam14h_start(void)
235{
236 int num, cpu;
237 clock_gettime(CLOCK_REALTIME, &start_time);
238 for (num = 0; num < AMD_FAM14H_STATE_NUM; num++) {
239 for (cpu = 0; cpu < cpu_count; cpu++)
240 amd_fam14h_init(&amd_fam14h_cstates[num], cpu);
241 }
242#ifdef DEBUG
243 clock_gettime(CLOCK_REALTIME, &dbg_time);
244 dbg_timediff = timespec_diff_us(start_time, dbg_time);
245 dprint("Enabling counters took: %lu us\n",
246 dbg_timediff);
247#endif
248 return 0;
249}
250
251static int amd_fam14h_stop(void)
252{
253 int num, cpu;
254 struct timespec end_time;
255
256 clock_gettime(CLOCK_REALTIME, &end_time);
257
258 for (num = 0; num < AMD_FAM14H_STATE_NUM; num++) {
259 for (cpu = 0; cpu < cpu_count; cpu++)
260 amd_fam14h_disable(&amd_fam14h_cstates[num], cpu);
261 }
262#ifdef DEBUG
263 clock_gettime(CLOCK_REALTIME, &dbg_time);
264 dbg_timediff = timespec_diff_us(end_time, dbg_time);
265 dprint("Disabling counters took: %lu ns\n", dbg_timediff);
266#endif
267 timediff = timespec_diff_us(start_time, end_time);
268 if (timediff / 1000 > OVERFLOW_MS)
269 print_overflow_err((unsigned int)timediff / 1000000,
270 OVERFLOW_MS / 1000);
271
272 return 0;
273}
274
275static int is_nbp1_capable(void)
276{
277 uint32_t val;
278 val = pci_read_long(amd_fam14h_pci_dev, PCI_NBP1_CAP_OFFSET);
279 return val & (1 << 31);
280}
281
282struct cpuidle_monitor *amd_fam14h_register(void)
283{
284 int num;
285
286 if (cpupower_cpu_info.vendor != X86_VENDOR_AMD)
287 return NULL;
288
289 if (cpupower_cpu_info.family == 0x14) {
290 if (cpu_count <= 0 || cpu_count > 2) {
291 fprintf(stderr, "AMD fam14h: Invalid cpu count: %d\n",
292 cpu_count);
293 return NULL;
294 }
295 } else
296 return NULL;
297
298 /* We do not alloc for nbp1 machine wide counter */
299 for (num = 0; num < AMD_FAM14H_STATE_NUM - 1; num++) {
300 previous_count[num] = calloc(cpu_count,
301 sizeof(unsigned long long));
302 current_count[num] = calloc(cpu_count,
303 sizeof(unsigned long long));
304 }
305
306 amd_fam14h_pci_dev = pci_acc_init(&pci_acc, pci_vendor_id, pci_dev_ids);
307 if (amd_fam14h_pci_dev == NULL || pci_acc == NULL)
308 return NULL;
309
310 if (!is_nbp1_capable())
311 amd_fam14h_monitor.hw_states_num = AMD_FAM14H_STATE_NUM - 1;
312
313 amd_fam14h_monitor.name_len = strlen(amd_fam14h_monitor.name);
314 return &amd_fam14h_monitor;
315}
316
317static void amd_fam14h_unregister(void)
318{
319 int num;
320 for (num = 0; num < AMD_FAM14H_STATE_NUM - 1; num++) {
321 free(previous_count[num]);
322 free(current_count[num]);
323 }
324 pci_cleanup(pci_acc);
325}
326
327struct cpuidle_monitor amd_fam14h_monitor = {
328 .name = "Ontario",
329 .hw_states = amd_fam14h_cstates,
330 .hw_states_num = AMD_FAM14H_STATE_NUM,
331 .start = amd_fam14h_start,
332 .stop = amd_fam14h_stop,
333 .do_register = amd_fam14h_register,
334 .unregister = amd_fam14h_unregister,
335 .needs_root = 1,
336 .overflow_s = OVERFLOW_MS / 1000,
337};
338#endif /* #if defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
new file mode 100644
index 00000000000..bcd22a1a397
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
@@ -0,0 +1,196 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <stdint.h>
11#include <string.h>
12#include <limits.h>
13
14#include "helpers/sysfs.h"
15#include "helpers/helpers.h"
16#include "idle_monitor/cpupower-monitor.h"
17
18#define CPUIDLE_STATES_MAX 10
19static cstate_t cpuidle_cstates[CPUIDLE_STATES_MAX];
20struct cpuidle_monitor cpuidle_sysfs_monitor;
21
22static unsigned long long **previous_count;
23static unsigned long long **current_count;
24struct timespec start_time;
25static unsigned long long timediff;
26
27static int cpuidle_get_count_percent(unsigned int id, double *percent,
28 unsigned int cpu)
29{
30 unsigned long long statediff = current_count[cpu][id]
31 - previous_count[cpu][id];
32 dprint("%s: - diff: %llu - percent: %f (%u)\n",
33 cpuidle_cstates[id].name, timediff, *percent, cpu);
34
35 if (timediff == 0)
36 *percent = 0.0;
37 else
38 *percent = ((100.0 * statediff) / timediff);
39
40 dprint("%s: - timediff: %llu - statediff: %llu - percent: %f (%u)\n",
41 cpuidle_cstates[id].name, timediff, statediff, *percent, cpu);
42
43 return 0;
44}
45
46static int cpuidle_start(void)
47{
48 int cpu, state;
49 clock_gettime(CLOCK_REALTIME, &start_time);
50 for (cpu = 0; cpu < cpu_count; cpu++) {
51 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
52 state++) {
53 previous_count[cpu][state] =
54 sysfs_get_idlestate_time(cpu, state);
55 dprint("CPU %d - State: %d - Val: %llu\n",
56 cpu, state, previous_count[cpu][state]);
57 }
58 };
59 return 0;
60}
61
62static int cpuidle_stop(void)
63{
64 int cpu, state;
65 struct timespec end_time;
66 clock_gettime(CLOCK_REALTIME, &end_time);
67 timediff = timespec_diff_us(start_time, end_time);
68
69 for (cpu = 0; cpu < cpu_count; cpu++) {
70 for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
71 state++) {
72 current_count[cpu][state] =
73 sysfs_get_idlestate_time(cpu, state);
74 dprint("CPU %d - State: %d - Val: %llu\n",
75 cpu, state, previous_count[cpu][state]);
76 }
77 };
78 return 0;
79}
80
81void fix_up_intel_idle_driver_name(char *tmp, int num)
82{
83 /* fix up cpuidle name for intel idle driver */
84 if (!strncmp(tmp, "NHM-", 4)) {
85 switch (num) {
86 case 1:
87 strcpy(tmp, "C1");
88 break;
89 case 2:
90 strcpy(tmp, "C3");
91 break;
92 case 3:
93 strcpy(tmp, "C6");
94 break;
95 }
96 } else if (!strncmp(tmp, "SNB-", 4)) {
97 switch (num) {
98 case 1:
99 strcpy(tmp, "C1");
100 break;
101 case 2:
102 strcpy(tmp, "C3");
103 break;
104 case 3:
105 strcpy(tmp, "C6");
106 break;
107 case 4:
108 strcpy(tmp, "C7");
109 break;
110 }
111 } else if (!strncmp(tmp, "ATM-", 4)) {
112 switch (num) {
113 case 1:
114 strcpy(tmp, "C1");
115 break;
116 case 2:
117 strcpy(tmp, "C2");
118 break;
119 case 3:
120 strcpy(tmp, "C4");
121 break;
122 case 4:
123 strcpy(tmp, "C6");
124 break;
125 }
126 }
127}
128
129static struct cpuidle_monitor *cpuidle_register(void)
130{
131 int num;
132 char *tmp;
133
134 /* Assume idle state count is the same for all CPUs */
135 cpuidle_sysfs_monitor.hw_states_num = sysfs_get_idlestate_count(0);
136
137 if (cpuidle_sysfs_monitor.hw_states_num <= 0)
138 return NULL;
139
140 for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) {
141 tmp = sysfs_get_idlestate_name(0, num);
142 if (tmp == NULL)
143 continue;
144
145 fix_up_intel_idle_driver_name(tmp, num);
146 strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);
147 free(tmp);
148
149 tmp = sysfs_get_idlestate_desc(0, num);
150 if (tmp == NULL)
151 continue;
152 strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1);
153 free(tmp);
154
155 cpuidle_cstates[num].range = RANGE_THREAD;
156 cpuidle_cstates[num].id = num;
157 cpuidle_cstates[num].get_count_percent =
158 cpuidle_get_count_percent;
159 };
160
161 /* Free this at program termination */
162 previous_count = malloc(sizeof(long long *) * cpu_count);
163 current_count = malloc(sizeof(long long *) * cpu_count);
164 for (num = 0; num < cpu_count; num++) {
165 previous_count[num] = malloc(sizeof(long long) *
166 cpuidle_sysfs_monitor.hw_states_num);
167 current_count[num] = malloc(sizeof(long long) *
168 cpuidle_sysfs_monitor.hw_states_num);
169 }
170
171 cpuidle_sysfs_monitor.name_len = strlen(cpuidle_sysfs_monitor.name);
172 return &cpuidle_sysfs_monitor;
173}
174
175void cpuidle_unregister(void)
176{
177 int num;
178
179 for (num = 0; num < cpu_count; num++) {
180 free(previous_count[num]);
181 free(current_count[num]);
182 }
183 free(previous_count);
184 free(current_count);
185}
186
187struct cpuidle_monitor cpuidle_sysfs_monitor = {
188 .name = "Idle_Stats",
189 .hw_states = cpuidle_cstates,
190 .start = cpuidle_start,
191 .stop = cpuidle_stop,
192 .do_register = cpuidle_register,
193 .unregister = cpuidle_unregister,
194 .needs_root = 0,
195 .overflow_s = UINT_MAX,
196};
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
new file mode 100644
index 00000000000..0d6571e418d
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
@@ -0,0 +1,440 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Output format inspired by Len Brown's <lenb@kernel.org> turbostat tool.
7 *
8 */
9
10
11#include <stdio.h>
12#include <unistd.h>
13#include <stdlib.h>
14#include <string.h>
15#include <time.h>
16#include <signal.h>
17#include <sys/types.h>
18#include <sys/wait.h>
19#include <libgen.h>
20
21#include "idle_monitor/cpupower-monitor.h"
22#include "idle_monitor/idle_monitors.h"
23#include "helpers/helpers.h"
24
25/* Define pointers to all monitors. */
26#define DEF(x) & x ## _monitor ,
27struct cpuidle_monitor *all_monitors[] = {
28#include "idle_monitors.def"
290
30};
31
32static struct cpuidle_monitor *monitors[MONITORS_MAX];
33static unsigned int avail_monitors;
34
35static char *progname;
36
37enum operation_mode_e { list = 1, show, show_all };
38static int mode;
39static int interval = 1;
40static char *show_monitors_param;
41static struct cpupower_topology cpu_top;
42
43/* ToDo: Document this in the manpage */
44static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', };
45
46static void print_wrong_arg_exit(void)
47{
48 printf(_("invalid or unknown argument\n"));
49 exit(EXIT_FAILURE);
50}
51
52long long timespec_diff_us(struct timespec start, struct timespec end)
53{
54 struct timespec temp;
55 if ((end.tv_nsec - start.tv_nsec) < 0) {
56 temp.tv_sec = end.tv_sec - start.tv_sec - 1;
57 temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
58 } else {
59 temp.tv_sec = end.tv_sec - start.tv_sec;
60 temp.tv_nsec = end.tv_nsec - start.tv_nsec;
61 }
62 return (temp.tv_sec * 1000000) + (temp.tv_nsec / 1000);
63}
64
65void print_n_spaces(int n)
66{
67 int x;
68 for (x = 0; x < n; x++)
69 printf(" ");
70}
71
72/* size of s must be at least n + 1 */
73int fill_string_with_spaces(char *s, int n)
74{
75 int len = strlen(s);
76 if (len > n)
77 return -1;
78 for (; len < n; len++)
79 s[len] = ' ';
80 s[len] = '\0';
81 return 0;
82}
83
84void print_header(int topology_depth)
85{
86 int unsigned mon;
87 int state, need_len, pr_mon_len;
88 cstate_t s;
89 char buf[128] = "";
90 int percent_width = 4;
91
92 fill_string_with_spaces(buf, topology_depth * 5 - 1);
93 printf("%s|", buf);
94
95 for (mon = 0; mon < avail_monitors; mon++) {
96 pr_mon_len = 0;
97 need_len = monitors[mon]->hw_states_num * (percent_width + 3)
98 - 1;
99 if (mon != 0) {
100 printf("|| ");
101 need_len--;
102 }
103 sprintf(buf, "%s", monitors[mon]->name);
104 fill_string_with_spaces(buf, need_len);
105 printf("%s", buf);
106 }
107 printf("\n");
108
109 if (topology_depth > 2)
110 printf("PKG |");
111 if (topology_depth > 1)
112 printf("CORE|");
113 if (topology_depth > 0)
114 printf("CPU |");
115
116 for (mon = 0; mon < avail_monitors; mon++) {
117 if (mon != 0)
118 printf("|| ");
119 else
120 printf(" ");
121 for (state = 0; state < monitors[mon]->hw_states_num; state++) {
122 if (state != 0)
123 printf(" | ");
124 s = monitors[mon]->hw_states[state];
125 sprintf(buf, "%s", s.name);
126 fill_string_with_spaces(buf, percent_width);
127 printf("%s", buf);
128 }
129 printf(" ");
130 }
131 printf("\n");
132}
133
134
135void print_results(int topology_depth, int cpu)
136{
137 unsigned int mon;
138 int state, ret;
139 double percent;
140 unsigned long long result;
141 cstate_t s;
142
143 /* Be careful CPUs may got resorted for pkg value do not just use cpu */
144 if (!bitmask_isbitset(cpus_chosen, cpu_top.core_info[cpu].cpu))
145 return;
146
147 if (topology_depth > 2)
148 printf("%4d|", cpu_top.core_info[cpu].pkg);
149 if (topology_depth > 1)
150 printf("%4d|", cpu_top.core_info[cpu].core);
151 if (topology_depth > 0)
152 printf("%4d|", cpu_top.core_info[cpu].cpu);
153
154 for (mon = 0; mon < avail_monitors; mon++) {
155 if (mon != 0)
156 printf("||");
157
158 for (state = 0; state < monitors[mon]->hw_states_num; state++) {
159 if (state != 0)
160 printf("|");
161
162 s = monitors[mon]->hw_states[state];
163
164 if (s.get_count_percent) {
165 ret = s.get_count_percent(s.id, &percent,
166 cpu_top.core_info[cpu].cpu);
167 if (ret)
168 printf("******");
169 else if (percent >= 100.0)
170 printf("%6.1f", percent);
171 else
172 printf("%6.2f", percent);
173 } else if (s.get_count) {
174 ret = s.get_count(s.id, &result,
175 cpu_top.core_info[cpu].cpu);
176 if (ret)
177 printf("******");
178 else
179 printf("%6llu", result);
180 } else {
181 printf(_("Monitor %s, Counter %s has no count "
182 "function. Implementation error\n"),
183 monitors[mon]->name, s.name);
184 exit(EXIT_FAILURE);
185 }
186 }
187 }
188 /*
189 * The monitor could still provide useful data, for example
190 * AMD HW counters partly sit in PCI config space.
191 * It's up to the monitor plug-in to check .is_online, this one
192 * is just for additional info.
193 */
194 if (!cpu_top.core_info[cpu].is_online) {
195 printf(_(" *is offline\n"));
196 return;
197 } else
198 printf("\n");
199}
200
201
202/* param: string passed by -m param (The list of monitors to show)
203 *
204 * Monitors must have been registered already, matching monitors
205 * are picked out and available monitors array is overridden
206 * with matching ones
207 *
208 * Monitors get sorted in the same order the user passes them
209*/
210
211static void parse_monitor_param(char *param)
212{
213 unsigned int num;
214 int mon, hits = 0;
215 char *tmp = param, *token;
216 struct cpuidle_monitor *tmp_mons[MONITORS_MAX];
217
218
219 for (mon = 0; mon < MONITORS_MAX; mon++, tmp = NULL) {
220 token = strtok(tmp, ",");
221 if (token == NULL)
222 break;
223 if (strlen(token) >= MONITOR_NAME_LEN) {
224 printf(_("%s: max monitor name length"
225 " (%d) exceeded\n"), token, MONITOR_NAME_LEN);
226 continue;
227 }
228
229 for (num = 0; num < avail_monitors; num++) {
230 if (!strcmp(monitors[num]->name, token)) {
231 dprint("Found requested monitor: %s\n", token);
232 tmp_mons[hits] = monitors[num];
233 hits++;
234 }
235 }
236 }
237 if (hits == 0) {
238 printf(_("No matching monitor found in %s, "
239 "try -l option\n"), param);
240 exit(EXIT_FAILURE);
241 }
242 /* Override detected/registerd monitors array with requested one */
243 memcpy(monitors, tmp_mons,
244 sizeof(struct cpuidle_monitor *) * MONITORS_MAX);
245 avail_monitors = hits;
246}
247
248void list_monitors(void)
249{
250 unsigned int mon;
251 int state;
252 cstate_t s;
253
254 for (mon = 0; mon < avail_monitors; mon++) {
255 printf(_("Monitor \"%s\" (%d states) - Might overflow after %u "
256 "s\n"),
257 monitors[mon]->name, monitors[mon]->hw_states_num,
258 monitors[mon]->overflow_s);
259
260 for (state = 0; state < monitors[mon]->hw_states_num; state++) {
261 s = monitors[mon]->hw_states[state];
262 /*
263 * ToDo show more state capabilities:
264 * percent, time (granlarity)
265 */
266 printf("%s\t[%c] -> %s\n", s.name, range_abbr[s.range],
267 gettext(s.desc));
268 }
269 }
270}
271
272int fork_it(char **argv)
273{
274 int status;
275 unsigned int num;
276 unsigned long long timediff;
277 pid_t child_pid;
278 struct timespec start, end;
279
280 child_pid = fork();
281 clock_gettime(CLOCK_REALTIME, &start);
282
283 for (num = 0; num < avail_monitors; num++)
284 monitors[num]->start();
285
286 if (!child_pid) {
287 /* child */
288 execvp(argv[0], argv);
289 } else {
290 /* parent */
291 if (child_pid == -1) {
292 perror("fork");
293 exit(1);
294 }
295
296 signal(SIGINT, SIG_IGN);
297 signal(SIGQUIT, SIG_IGN);
298 if (waitpid(child_pid, &status, 0) == -1) {
299 perror("wait");
300 exit(1);
301 }
302 }
303 clock_gettime(CLOCK_REALTIME, &end);
304 for (num = 0; num < avail_monitors; num++)
305 monitors[num]->stop();
306
307 timediff = timespec_diff_us(start, end);
308 if (WIFEXITED(status))
309 printf(_("%s took %.5f seconds and exited with status %d\n"),
310 argv[0], timediff / (1000.0 * 1000),
311 WEXITSTATUS(status));
312 return 0;
313}
314
315int do_interval_measure(int i)
316{
317 unsigned int num;
318
319 for (num = 0; num < avail_monitors; num++) {
320 dprint("HW C-state residency monitor: %s - States: %d\n",
321 monitors[num]->name, monitors[num]->hw_states_num);
322 monitors[num]->start();
323 }
324 sleep(i);
325 for (num = 0; num < avail_monitors; num++)
326 monitors[num]->stop();
327
328 return 0;
329}
330
331static void cmdline(int argc, char *argv[])
332{
333 int opt;
334 progname = basename(argv[0]);
335
336 while ((opt = getopt(argc, argv, "+li:m:")) != -1) {
337 switch (opt) {
338 case 'l':
339 if (mode)
340 print_wrong_arg_exit();
341 mode = list;
342 break;
343 case 'i':
344 /* only allow -i with -m or no option */
345 if (mode && mode != show)
346 print_wrong_arg_exit();
347 interval = atoi(optarg);
348 break;
349 case 'm':
350 if (mode)
351 print_wrong_arg_exit();
352 mode = show;
353 show_monitors_param = optarg;
354 break;
355 default:
356 print_wrong_arg_exit();
357 }
358 }
359 if (!mode)
360 mode = show_all;
361}
362
363int cmd_monitor(int argc, char **argv)
364{
365 unsigned int num;
366 struct cpuidle_monitor *test_mon;
367 int cpu;
368
369 cmdline(argc, argv);
370 cpu_count = get_cpu_topology(&cpu_top);
371 if (cpu_count < 0) {
372 printf(_("Cannot read number of available processors\n"));
373 return EXIT_FAILURE;
374 }
375
376 /* Default is: monitor all CPUs */
377 if (bitmask_isallclear(cpus_chosen))
378 bitmask_setall(cpus_chosen);
379
380 dprint("System has up to %d CPU cores\n", cpu_count);
381
382 for (num = 0; all_monitors[num]; num++) {
383 dprint("Try to register: %s\n", all_monitors[num]->name);
384 test_mon = all_monitors[num]->do_register();
385 if (test_mon) {
386 if (test_mon->needs_root && !run_as_root) {
387 fprintf(stderr, _("Available monitor %s needs "
388 "root access\n"), test_mon->name);
389 continue;
390 }
391 monitors[avail_monitors] = test_mon;
392 dprint("%s registered\n", all_monitors[num]->name);
393 avail_monitors++;
394 }
395 }
396
397 if (avail_monitors == 0) {
398 printf(_("No HW Cstate monitors found\n"));
399 return 1;
400 }
401
402 if (mode == list) {
403 list_monitors();
404 exit(EXIT_SUCCESS);
405 }
406
407 if (mode == show)
408 parse_monitor_param(show_monitors_param);
409
410 dprint("Packages: %d - Cores: %d - CPUs: %d\n",
411 cpu_top.pkgs, cpu_top.cores, cpu_count);
412
413 /*
414 * if any params left, it must be a command to fork
415 */
416 if (argc - optind)
417 fork_it(argv + optind);
418 else
419 do_interval_measure(interval);
420
421 /* ToDo: Topology parsing needs fixing first to do
422 this more generically */
423 if (cpu_top.pkgs > 1)
424 print_header(3);
425 else
426 print_header(1);
427
428 for (cpu = 0; cpu < cpu_count; cpu++) {
429 if (cpu_top.pkgs > 1)
430 print_results(3, cpu);
431 else
432 print_results(1, cpu);
433 }
434
435 for (num = 0; num < avail_monitors; num++)
436 monitors[num]->unregister();
437
438 cpu_topology_release(cpu_top);
439 return 0;
440}
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
new file mode 100644
index 00000000000..9312ee1f2db
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
@@ -0,0 +1,68 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 */
7
8#ifndef __CPUIDLE_INFO_HW__
9#define __CPUIDLE_INFO_HW__
10
11#include <stdarg.h>
12#include <time.h>
13
14#include "idle_monitor/idle_monitors.h"
15
16#define MONITORS_MAX 20
17#define MONITOR_NAME_LEN 20
18#define CSTATE_NAME_LEN 5
19#define CSTATE_DESC_LEN 60
20
21int cpu_count;
22
23/* Hard to define the right names ...: */
24enum power_range_e {
25 RANGE_THREAD, /* Lowest in topology hierarcy, AMD: core, Intel: thread
26 kernel sysfs: cpu */
27 RANGE_CORE, /* AMD: unit, Intel: core, kernel_sysfs: core_id */
28 RANGE_PACKAGE, /* Package, processor socket */
29 RANGE_MACHINE, /* Machine, platform wide */
30 RANGE_MAX };
31
32typedef struct cstate {
33 int id;
34 enum power_range_e range;
35 char name[CSTATE_NAME_LEN];
36 char desc[CSTATE_DESC_LEN];
37
38 /* either provide a percentage or a general count */
39 int (*get_count_percent)(unsigned int self_id, double *percent,
40 unsigned int cpu);
41 int (*get_count)(unsigned int self_id, unsigned long long *count,
42 unsigned int cpu);
43} cstate_t;
44
45struct cpuidle_monitor {
46 /* Name must not contain whitespaces */
47 char name[MONITOR_NAME_LEN];
48 int name_len;
49 int hw_states_num;
50 cstate_t *hw_states;
51 int (*start) (void);
52 int (*stop) (void);
53 struct cpuidle_monitor* (*do_register) (void);
54 void (*unregister)(void);
55 unsigned int overflow_s;
56 int needs_root;
57};
58
59extern long long timespec_diff_us(struct timespec start, struct timespec end);
60
61#define print_overflow_err(mes, ov) \
62{ \
63 fprintf(stderr, gettext("Measure took %u seconds, but registers could " \
64 "overflow at %u seconds, results " \
65 "could be inaccurate\n"), mes, ov); \
66}
67
68#endif /* __CPUIDLE_INFO_HW__ */
diff --git a/tools/power/cpupower/utils/idle_monitor/idle_monitors.def b/tools/power/cpupower/utils/idle_monitor/idle_monitors.def
new file mode 100644
index 00000000000..e3f8d9b2b18
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/idle_monitors.def
@@ -0,0 +1,7 @@
1#if defined(__i386__) || defined(__x86_64__)
2DEF(amd_fam14h)
3DEF(intel_nhm)
4DEF(intel_snb)
5DEF(mperf)
6#endif
7DEF(cpuidle_sysfs)
diff --git a/tools/power/cpupower/utils/idle_monitor/idle_monitors.h b/tools/power/cpupower/utils/idle_monitor/idle_monitors.h
new file mode 100644
index 00000000000..4fcdeb1e07e
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/idle_monitors.h
@@ -0,0 +1,18 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Based on the idea from Michael Matz <matz@suse.de>
7 *
8 */
9
10#ifndef _CPUIDLE_IDLE_MONITORS_H_
11#define _CPUIDLE_IDLE_MONITORS_H_
12
13#define DEF(x) extern struct cpuidle_monitor x ##_monitor;
14#include "idle_monitors.def"
15#undef DEF
16extern struct cpuidle_monitor *all_monitors[];
17
18#endif /* _CPUIDLE_IDLE_MONITORS_H_ */
diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
new file mode 100644
index 00000000000..5650ab5a2c2
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
@@ -0,0 +1,338 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 */
6
7#if defined(__i386__) || defined(__x86_64__)
8
9#include <stdio.h>
10#include <stdint.h>
11#include <stdlib.h>
12#include <string.h>
13#include <limits.h>
14
15#include <cpufreq.h>
16
17#include "helpers/helpers.h"
18#include "idle_monitor/cpupower-monitor.h"
19
20#define MSR_APERF 0xE8
21#define MSR_MPERF 0xE7
22
23#define MSR_TSC 0x10
24
25#define MSR_AMD_HWCR 0xc0010015
26
27enum mperf_id { C0 = 0, Cx, AVG_FREQ, MPERF_CSTATE_COUNT };
28
29static int mperf_get_count_percent(unsigned int self_id, double *percent,
30 unsigned int cpu);
31static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
32 unsigned int cpu);
33static struct timespec time_start, time_end;
34
35static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = {
36 {
37 .name = "C0",
38 .desc = N_("Processor Core not idle"),
39 .id = C0,
40 .range = RANGE_THREAD,
41 .get_count_percent = mperf_get_count_percent,
42 },
43 {
44 .name = "Cx",
45 .desc = N_("Processor Core in an idle state"),
46 .id = Cx,
47 .range = RANGE_THREAD,
48 .get_count_percent = mperf_get_count_percent,
49 },
50
51 {
52 .name = "Freq",
53 .desc = N_("Average Frequency (including boost) in MHz"),
54 .id = AVG_FREQ,
55 .range = RANGE_THREAD,
56 .get_count = mperf_get_count_freq,
57 },
58};
59
60enum MAX_FREQ_MODE { MAX_FREQ_SYSFS, MAX_FREQ_TSC_REF };
61static int max_freq_mode;
62/*
63 * The max frequency mperf is ticking at (in C0), either retrieved via:
64 * 1) calculated after measurements if we know TSC ticks at mperf/P0 frequency
65 * 2) cpufreq /sys/devices/.../cpu0/cpufreq/cpuinfo_max_freq at init time
66 * 1. Is preferred as it also works without cpufreq subsystem (e.g. on Xen)
67 */
68static unsigned long max_frequency;
69
70static unsigned long long tsc_at_measure_start;
71static unsigned long long tsc_at_measure_end;
72static unsigned long long *mperf_previous_count;
73static unsigned long long *aperf_previous_count;
74static unsigned long long *mperf_current_count;
75static unsigned long long *aperf_current_count;
76
77/* valid flag for all CPUs. If a MSR read failed it will be zero */
78static int *is_valid;
79
80static int mperf_get_tsc(unsigned long long *tsc)
81{
82 int ret;
83 ret = read_msr(0, MSR_TSC, tsc);
84 if (ret)
85 dprint("Reading TSC MSR failed, returning %llu\n", *tsc);
86 return ret;
87}
88
89static int mperf_init_stats(unsigned int cpu)
90{
91 unsigned long long val;
92 int ret;
93
94 ret = read_msr(cpu, MSR_APERF, &val);
95 aperf_previous_count[cpu] = val;
96 ret |= read_msr(cpu, MSR_MPERF, &val);
97 mperf_previous_count[cpu] = val;
98 is_valid[cpu] = !ret;
99
100 return 0;
101}
102
103static int mperf_measure_stats(unsigned int cpu)
104{
105 unsigned long long val;
106 int ret;
107
108 ret = read_msr(cpu, MSR_APERF, &val);
109 aperf_current_count[cpu] = val;
110 ret |= read_msr(cpu, MSR_MPERF, &val);
111 mperf_current_count[cpu] = val;
112 is_valid[cpu] = !ret;
113
114 return 0;
115}
116
117static int mperf_get_count_percent(unsigned int id, double *percent,
118 unsigned int cpu)
119{
120 unsigned long long aperf_diff, mperf_diff, tsc_diff;
121 unsigned long long timediff;
122
123 if (!is_valid[cpu])
124 return -1;
125
126 if (id != C0 && id != Cx)
127 return -1;
128
129 mperf_diff = mperf_current_count[cpu] - mperf_previous_count[cpu];
130 aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];
131
132 if (max_freq_mode == MAX_FREQ_TSC_REF) {
133 tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
134 *percent = 100.0 * mperf_diff / tsc_diff;
135 dprint("%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n",
136 mperf_cstates[id].name, mperf_diff, tsc_diff);
137 } else if (max_freq_mode == MAX_FREQ_SYSFS) {
138 timediff = timespec_diff_us(time_start, time_end);
139 *percent = 100.0 * mperf_diff / timediff;
140 dprint("%s: MAXFREQ - mperf_diff: %llu, time_diff: %llu\n",
141 mperf_cstates[id].name, mperf_diff, timediff);
142 } else
143 return -1;
144
145 if (id == Cx)
146 *percent = 100.0 - *percent;
147
148 dprint("%s: previous: %llu - current: %llu - (%u)\n",
149 mperf_cstates[id].name, mperf_diff, aperf_diff, cpu);
150 dprint("%s: %f\n", mperf_cstates[id].name, *percent);
151 return 0;
152}
153
154static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
155 unsigned int cpu)
156{
157 unsigned long long aperf_diff, mperf_diff, time_diff, tsc_diff;
158
159 if (id != AVG_FREQ)
160 return 1;
161
162 if (!is_valid[cpu])
163 return -1;
164
165 mperf_diff = mperf_current_count[cpu] - mperf_previous_count[cpu];
166 aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];
167
168 if (max_freq_mode == MAX_FREQ_TSC_REF) {
169 /* Calculate max_freq from TSC count */
170 tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
171 time_diff = timespec_diff_us(time_start, time_end);
172 max_frequency = tsc_diff / time_diff;
173 }
174
175 *count = max_frequency * ((double)aperf_diff / mperf_diff);
176 dprint("%s: Average freq based on %s maximum frequency:\n",
177 mperf_cstates[id].name,
178 (max_freq_mode == MAX_FREQ_TSC_REF) ? "TSC calculated" : "sysfs read");
179 dprint("%max_frequency: %lu", max_frequency);
180 dprint("aperf_diff: %llu\n", aperf_diff);
181 dprint("mperf_diff: %llu\n", mperf_diff);
182 dprint("avg freq: %llu\n", *count);
183 return 0;
184}
185
186static int mperf_start(void)
187{
188 int cpu;
189 unsigned long long dbg;
190
191 clock_gettime(CLOCK_REALTIME, &time_start);
192 mperf_get_tsc(&tsc_at_measure_start);
193
194 for (cpu = 0; cpu < cpu_count; cpu++)
195 mperf_init_stats(cpu);
196
197 mperf_get_tsc(&dbg);
198 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start);
199 return 0;
200}
201
202static int mperf_stop(void)
203{
204 unsigned long long dbg;
205 int cpu;
206
207 for (cpu = 0; cpu < cpu_count; cpu++)
208 mperf_measure_stats(cpu);
209
210 mperf_get_tsc(&tsc_at_measure_end);
211 clock_gettime(CLOCK_REALTIME, &time_end);
212
213 mperf_get_tsc(&dbg);
214 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);
215
216 return 0;
217}
218
219/*
220 * Mperf register is defined to tick at P0 (maximum) frequency
221 *
222 * Instead of reading out P0 which can be tricky to read out from HW,
223 * we use TSC counter if it reliably ticks at P0/mperf frequency.
224 *
225 * Still try to fall back to:
226 * /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
227 * on older Intel HW without invariant TSC feature.
228 * Or on AMD machines where TSC does not tick at P0 (do not exist yet, but
229 * it's still double checked (MSR_AMD_HWCR)).
230 *
231 * On these machines the user would still get useful mperf
232 * stats when acpi-cpufreq driver is loaded.
233 */
234static int init_maxfreq_mode(void)
235{
236 int ret;
237 unsigned long long hwcr;
238 unsigned long min;
239
240 if (!cpupower_cpu_info.caps & CPUPOWER_CAP_INV_TSC)
241 goto use_sysfs;
242
243 if (cpupower_cpu_info.vendor == X86_VENDOR_AMD) {
244 /* MSR_AMD_HWCR tells us whether TSC runs at P0/mperf
245 * freq.
246 * A test whether hwcr is accessable/available would be:
247 * (cpupower_cpu_info.family > 0x10 ||
248 * cpupower_cpu_info.family == 0x10 &&
249 * cpupower_cpu_info.model >= 0x2))
250 * This should be the case for all aperf/mperf
251 * capable AMD machines and is therefore safe to test here.
252 * Compare with Linus kernel git commit: acf01734b1747b1ec4
253 */
254 ret = read_msr(0, MSR_AMD_HWCR, &hwcr);
255 /*
256 * If the MSR read failed, assume a Xen system that did
257 * not explicitly provide access to it and assume TSC works
258 */
259 if (ret != 0) {
260 dprint("TSC read 0x%x failed - assume TSC working\n",
261 MSR_AMD_HWCR);
262 return 0;
263 } else if (1 & (hwcr >> 24)) {
264 max_freq_mode = MAX_FREQ_TSC_REF;
265 return 0;
266 } else { /* Use sysfs max frequency if available */ }
267 } else if (cpupower_cpu_info.vendor == X86_VENDOR_INTEL) {
268 /*
269 * On Intel we assume mperf (in C0) is ticking at same
270 * rate than TSC
271 */
272 max_freq_mode = MAX_FREQ_TSC_REF;
273 return 0;
274 }
275use_sysfs:
276 if (cpufreq_get_hardware_limits(0, &min, &max_frequency)) {
277 dprint("Cannot retrieve max freq from cpufreq kernel "
278 "subsystem\n");
279 return -1;
280 }
281 max_freq_mode = MAX_FREQ_SYSFS;
282 return 0;
283}
284
285/*
286 * This monitor provides:
287 *
288 * 1) Average frequency a CPU resided in
289 * This always works if the CPU has aperf/mperf capabilities
290 *
291 * 2) C0 and Cx (any sleep state) time a CPU resided in
292 * Works if mperf timer stops ticking in sleep states which
293 * seem to be the case on all current HW.
294 * Both is directly retrieved from HW registers and is independent
295 * from kernel statistics.
296 */
297struct cpuidle_monitor mperf_monitor;
298struct cpuidle_monitor *mperf_register(void)
299{
300 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_APERF))
301 return NULL;
302
303 if (init_maxfreq_mode())
304 return NULL;
305
306 /* Free this at program termination */
307 is_valid = calloc(cpu_count, sizeof(int));
308 mperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
309 aperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
310 mperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
311 aperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
312
313 mperf_monitor.name_len = strlen(mperf_monitor.name);
314 return &mperf_monitor;
315}
316
317void mperf_unregister(void)
318{
319 free(mperf_previous_count);
320 free(aperf_previous_count);
321 free(mperf_current_count);
322 free(aperf_current_count);
323 free(is_valid);
324}
325
326struct cpuidle_monitor mperf_monitor = {
327 .name = "Mperf",
328 .hw_states_num = MPERF_CSTATE_COUNT,
329 .hw_states = mperf_cstates,
330 .start = mperf_start,
331 .stop = mperf_stop,
332 .do_register = mperf_register,
333 .unregister = mperf_unregister,
334 .needs_root = 1,
335 .overflow_s = 922000000 /* 922337203 seconds TSC overflow
336 at 20GHz */
337};
338#endif /* #if defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/idle_monitor/nhm_idle.c b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
new file mode 100644
index 00000000000..d2a91dd0d56
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
@@ -0,0 +1,216 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Based on Len Brown's <lenb@kernel.org> turbostat tool.
7 */
8
9#if defined(__i386__) || defined(__x86_64__)
10
11#include <stdio.h>
12#include <stdint.h>
13#include <stdlib.h>
14#include <string.h>
15
16#include "helpers/helpers.h"
17#include "idle_monitor/cpupower-monitor.h"
18
19#define MSR_PKG_C3_RESIDENCY 0x3F8
20#define MSR_PKG_C6_RESIDENCY 0x3F9
21#define MSR_CORE_C3_RESIDENCY 0x3FC
22#define MSR_CORE_C6_RESIDENCY 0x3FD
23
24#define MSR_TSC 0x10
25
26#define NHM_CSTATE_COUNT 4
27
28enum intel_nhm_id { C3 = 0, C6, PC3, PC6, TSC = 0xFFFF };
29
30static int nhm_get_count_percent(unsigned int self_id, double *percent,
31 unsigned int cpu);
32
33static cstate_t nhm_cstates[NHM_CSTATE_COUNT] = {
34 {
35 .name = "C3",
36 .desc = N_("Processor Core C3"),
37 .id = C3,
38 .range = RANGE_CORE,
39 .get_count_percent = nhm_get_count_percent,
40 },
41 {
42 .name = "C6",
43 .desc = N_("Processor Core C6"),
44 .id = C6,
45 .range = RANGE_CORE,
46 .get_count_percent = nhm_get_count_percent,
47 },
48
49 {
50 .name = "PC3",
51 .desc = N_("Processor Package C3"),
52 .id = PC3,
53 .range = RANGE_PACKAGE,
54 .get_count_percent = nhm_get_count_percent,
55 },
56 {
57 .name = "PC6",
58 .desc = N_("Processor Package C6"),
59 .id = PC6,
60 .range = RANGE_PACKAGE,
61 .get_count_percent = nhm_get_count_percent,
62 },
63};
64
65static unsigned long long tsc_at_measure_start;
66static unsigned long long tsc_at_measure_end;
67static unsigned long long *previous_count[NHM_CSTATE_COUNT];
68static unsigned long long *current_count[NHM_CSTATE_COUNT];
69/* valid flag for all CPUs. If a MSR read failed it will be zero */
70static int *is_valid;
71
72static int nhm_get_count(enum intel_nhm_id id, unsigned long long *val,
73 unsigned int cpu)
74{
75 int msr;
76
77 switch (id) {
78 case C3:
79 msr = MSR_CORE_C3_RESIDENCY;
80 break;
81 case C6:
82 msr = MSR_CORE_C6_RESIDENCY;
83 break;
84 case PC3:
85 msr = MSR_PKG_C3_RESIDENCY;
86 break;
87 case PC6:
88 msr = MSR_PKG_C6_RESIDENCY;
89 break;
90 case TSC:
91 msr = MSR_TSC;
92 break;
93 default:
94 return -1;
95 };
96 if (read_msr(cpu, msr, val))
97 return -1;
98
99 return 0;
100}
101
102static int nhm_get_count_percent(unsigned int id, double *percent,
103 unsigned int cpu)
104{
105 *percent = 0.0;
106
107 if (!is_valid[cpu])
108 return -1;
109
110 *percent = (100.0 *
111 (current_count[id][cpu] - previous_count[id][cpu])) /
112 (tsc_at_measure_end - tsc_at_measure_start);
113
114 dprint("%s: previous: %llu - current: %llu - (%u)\n",
115 nhm_cstates[id].name, previous_count[id][cpu],
116 current_count[id][cpu], cpu);
117
118 dprint("%s: tsc_diff: %llu - count_diff: %llu - percent: %2.f (%u)\n",
119 nhm_cstates[id].name,
120 (unsigned long long) tsc_at_measure_end - tsc_at_measure_start,
121 current_count[id][cpu] - previous_count[id][cpu],
122 *percent, cpu);
123
124 return 0;
125}
126
127static int nhm_start(void)
128{
129 int num, cpu;
130 unsigned long long dbg, val;
131
132 nhm_get_count(TSC, &tsc_at_measure_start, 0);
133
134 for (num = 0; num < NHM_CSTATE_COUNT; num++) {
135 for (cpu = 0; cpu < cpu_count; cpu++) {
136 is_valid[cpu] = !nhm_get_count(num, &val, cpu);
137 previous_count[num][cpu] = val;
138 }
139 }
140 nhm_get_count(TSC, &dbg, 0);
141 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start);
142 return 0;
143}
144
145static int nhm_stop(void)
146{
147 unsigned long long val;
148 unsigned long long dbg;
149 int num, cpu;
150
151 nhm_get_count(TSC, &tsc_at_measure_end, 0);
152
153 for (num = 0; num < NHM_CSTATE_COUNT; num++) {
154 for (cpu = 0; cpu < cpu_count; cpu++) {
155 is_valid[cpu] = !nhm_get_count(num, &val, cpu);
156 current_count[num][cpu] = val;
157 }
158 }
159 nhm_get_count(TSC, &dbg, 0);
160 dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);
161
162 return 0;
163}
164
165struct cpuidle_monitor intel_nhm_monitor;
166
167struct cpuidle_monitor *intel_nhm_register(void)
168{
169 int num;
170
171 if (cpupower_cpu_info.vendor != X86_VENDOR_INTEL)
172 return NULL;
173
174 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_INV_TSC))
175 return NULL;
176
177 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_APERF))
178 return NULL;
179
180 /* Free this at program termination */
181 is_valid = calloc(cpu_count, sizeof(int));
182 for (num = 0; num < NHM_CSTATE_COUNT; num++) {
183 previous_count[num] = calloc(cpu_count,
184 sizeof(unsigned long long));
185 current_count[num] = calloc(cpu_count,
186 sizeof(unsigned long long));
187 }
188
189 intel_nhm_monitor.name_len = strlen(intel_nhm_monitor.name);
190 return &intel_nhm_monitor;
191}
192
193void intel_nhm_unregister(void)
194{
195 int num;
196
197 for (num = 0; num < NHM_CSTATE_COUNT; num++) {
198 free(previous_count[num]);
199 free(current_count[num]);
200 }
201 free(is_valid);
202}
203
204struct cpuidle_monitor intel_nhm_monitor = {
205 .name = "Nehalem",
206 .hw_states_num = NHM_CSTATE_COUNT,
207 .hw_states = nhm_cstates,
208 .start = nhm_start,
209 .stop = nhm_stop,
210 .do_register = intel_nhm_register,
211 .unregister = intel_nhm_unregister,
212 .needs_root = 1,
213 .overflow_s = 922000000 /* 922337203 seconds TSC overflow
214 at 20GHz */
215};
216#endif
diff --git a/tools/power/cpupower/utils/idle_monitor/snb_idle.c b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
new file mode 100644
index 00000000000..a1bc07cd53e
--- /dev/null
+++ b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
@@ -0,0 +1,190 @@
1/*
2 * (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
3 *
4 * Licensed under the terms of the GNU GPL License version 2.
5 *
6 * Based on Len Brown's <lenb@kernel.org> turbostat tool.
7 */
8
9#if defined(__i386__) || defined(__x86_64__)
10
11#include <stdio.h>
12#include <stdint.h>
13#include <stdlib.h>
14#include <string.h>
15
16#include "helpers/helpers.h"
17#include "idle_monitor/cpupower-monitor.h"
18
19#define MSR_PKG_C2_RESIDENCY 0x60D
20#define MSR_PKG_C7_RESIDENCY 0x3FA
21#define MSR_CORE_C7_RESIDENCY 0x3FE
22
23#define MSR_TSC 0x10
24
25enum intel_snb_id { C7 = 0, PC2, PC7, SNB_CSTATE_COUNT, TSC = 0xFFFF };
26
27static int snb_get_count_percent(unsigned int self_id, double *percent,
28 unsigned int cpu);
29
30static cstate_t snb_cstates[SNB_CSTATE_COUNT] = {
31 {
32 .name = "C7",
33 .desc = N_("Processor Core C7"),
34 .id = C7,
35 .range = RANGE_CORE,
36 .get_count_percent = snb_get_count_percent,
37 },
38 {
39 .name = "PC2",
40 .desc = N_("Processor Package C2"),
41 .id = PC2,
42 .range = RANGE_PACKAGE,
43 .get_count_percent = snb_get_count_percent,
44 },
45 {
46 .name = "PC7",
47 .desc = N_("Processor Package C7"),
48 .id = PC7,
49 .range = RANGE_PACKAGE,
50 .get_count_percent = snb_get_count_percent,
51 },
52};
53
54static unsigned long long tsc_at_measure_start;
55static unsigned long long tsc_at_measure_end;
56static unsigned long long *previous_count[SNB_CSTATE_COUNT];
57static unsigned long long *current_count[SNB_CSTATE_COUNT];
58/* valid flag for all CPUs. If a MSR read failed it will be zero */
59static int *is_valid;
60
61static int snb_get_count(enum intel_snb_id id, unsigned long long *val,
62 unsigned int cpu)
63{
64 int msr;
65
66 switch (id) {
67 case C7:
68 msr = MSR_CORE_C7_RESIDENCY;
69 break;
70 case PC2:
71 msr = MSR_PKG_C2_RESIDENCY;
72 break;
73 case PC7:
74 msr = MSR_PKG_C7_RESIDENCY;
75 break;
76 case TSC:
77 msr = MSR_TSC;
78 break;
79 default:
80 return -1;
81 };
82 if (read_msr(cpu, msr, val))
83 return -1;
84 return 0;
85}
86
87static int snb_get_count_percent(unsigned int id, double *percent,
88 unsigned int cpu)
89{
90 *percent = 0.0;
91
92 if (!is_valid[cpu])
93 return -1;
94
95 *percent = (100.0 *
96 (current_count[id][cpu] - previous_count[id][cpu])) /
97 (tsc_at_measure_end - tsc_at_measure_start);
98
99 dprint("%s: previous: %llu - current: %llu - (%u)\n",
100 snb_cstates[id].name, previous_count[id][cpu],
101 current_count[id][cpu], cpu);
102
103 dprint("%s: tsc_diff: %llu - count_diff: %llu - percent: %2.f (%u)\n",
104 snb_cstates[id].name,
105 (unsigned long long) tsc_at_measure_end - tsc_at_measure_start,
106 current_count[id][cpu] - previous_count[id][cpu],
107 *percent, cpu);
108
109 return 0;
110}
111
112static int snb_start(void)
113{
114 int num, cpu;
115 unsigned long long val;
116
117 for (num = 0; num < SNB_CSTATE_COUNT; num++) {
118 for (cpu = 0; cpu < cpu_count; cpu++) {
119 snb_get_count(num, &val, cpu);
120 previous_count[num][cpu] = val;
121 }
122 }
123 snb_get_count(TSC, &tsc_at_measure_start, 0);
124 return 0;
125}
126
127static int snb_stop(void)
128{
129 unsigned long long val;
130 int num, cpu;
131
132 snb_get_count(TSC, &tsc_at_measure_end, 0);
133
134 for (num = 0; num < SNB_CSTATE_COUNT; num++) {
135 for (cpu = 0; cpu < cpu_count; cpu++) {
136 is_valid[cpu] = !snb_get_count(num, &val, cpu);
137 current_count[num][cpu] = val;
138 }
139 }
140 return 0;
141}
142
143struct cpuidle_monitor intel_snb_monitor;
144
145static struct cpuidle_monitor *snb_register(void)
146{
147 int num;
148
149 if (cpupower_cpu_info.vendor != X86_VENDOR_INTEL
150 || cpupower_cpu_info.family != 6)
151 return NULL;
152
153 if (cpupower_cpu_info.model != 0x2A
154 && cpupower_cpu_info.model != 0x2D)
155 return NULL;
156
157 is_valid = calloc(cpu_count, sizeof(int));
158 for (num = 0; num < SNB_CSTATE_COUNT; num++) {
159 previous_count[num] = calloc(cpu_count,
160 sizeof(unsigned long long));
161 current_count[num] = calloc(cpu_count,
162 sizeof(unsigned long long));
163 }
164 intel_snb_monitor.name_len = strlen(intel_snb_monitor.name);
165 return &intel_snb_monitor;
166}
167
168void snb_unregister(void)
169{
170 int num;
171 free(is_valid);
172 for (num = 0; num < SNB_CSTATE_COUNT; num++) {
173 free(previous_count[num]);
174 free(current_count[num]);
175 }
176}
177
178struct cpuidle_monitor intel_snb_monitor = {
179 .name = "SandyBridge",
180 .hw_states = snb_cstates,
181 .hw_states_num = SNB_CSTATE_COUNT,
182 .start = snb_start,
183 .stop = snb_stop,
184 .do_register = snb_register,
185 .unregister = snb_unregister,
186 .needs_root = 1,
187 .overflow_s = 922000000 /* 922337203 seconds TSC overflow
188 at 20GHz */
189};
190#endif /* defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/version-gen.sh b/tools/power/cpupower/utils/version-gen.sh
new file mode 100755
index 00000000000..5ec41c55699
--- /dev/null
+++ b/tools/power/cpupower/utils/version-gen.sh
@@ -0,0 +1,35 @@
1#!/bin/sh
2#
3# Script which prints out the version to use for building cpupowerutils.
4# Must be called from tools/power/cpupower/
5#
6# Heavily based on tools/perf/util/PERF-VERSION-GEN .
7
8LF='
9'
10
11# First check if there is a .git to get the version from git describe
12# otherwise try to get the version from the kernel makefile
13if test -d ../../../.git -o -f ../../../.git &&
14 VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
15 case "$VN" in
16 *$LF*) (exit 1) ;;
17 v[0-9]*)
18 git update-index -q --refresh
19 test -z "$(git diff-index --name-only HEAD --)" ||
20 VN="$VN-dirty" ;;
21 esac
22then
23 VN=$(echo "$VN" | sed -e 's/-/./g');
24else
25 eval $(grep '^VERSION[[:space:]]*=' ../../../Makefile|tr -d ' ')
26 eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../../Makefile|tr -d ' ')
27 eval $(grep '^SUBLEVEL[[:space:]]*=' ../../../Makefile|tr -d ' ')
28 eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../../Makefile|tr -d ' ')
29
30 VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}"
31fi
32
33VN=$(expr "$VN" : v*'\(.*\)')
34
35echo $VN
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 6d8ef4a3a9b..8b2d37b59c9 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -128,34 +128,34 @@ unsigned long long get_msr(int cpu, off_t offset)
128void print_header(void) 128void print_header(void)
129{ 129{
130 if (show_pkg) 130 if (show_pkg)
131 fprintf(stderr, "pkg "); 131 fprintf(stderr, "pk");
132 if (show_core) 132 if (show_core)
133 fprintf(stderr, "core"); 133 fprintf(stderr, " cr");
134 if (show_cpu) 134 if (show_cpu)
135 fprintf(stderr, " CPU"); 135 fprintf(stderr, " CPU");
136 if (do_nhm_cstates) 136 if (do_nhm_cstates)
137 fprintf(stderr, " %%c0 "); 137 fprintf(stderr, " %%c0 ");
138 if (has_aperf) 138 if (has_aperf)
139 fprintf(stderr, " GHz"); 139 fprintf(stderr, " GHz");
140 fprintf(stderr, " TSC"); 140 fprintf(stderr, " TSC");
141 if (do_nhm_cstates) 141 if (do_nhm_cstates)
142 fprintf(stderr, " %%c1 "); 142 fprintf(stderr, " %%c1");
143 if (do_nhm_cstates) 143 if (do_nhm_cstates)
144 fprintf(stderr, " %%c3 "); 144 fprintf(stderr, " %%c3");
145 if (do_nhm_cstates) 145 if (do_nhm_cstates)
146 fprintf(stderr, " %%c6 "); 146 fprintf(stderr, " %%c6");
147 if (do_snb_cstates) 147 if (do_snb_cstates)
148 fprintf(stderr, " %%c7 "); 148 fprintf(stderr, " %%c7");
149 if (do_snb_cstates) 149 if (do_snb_cstates)
150 fprintf(stderr, " %%pc2 "); 150 fprintf(stderr, " %%pc2");
151 if (do_nhm_cstates) 151 if (do_nhm_cstates)
152 fprintf(stderr, " %%pc3 "); 152 fprintf(stderr, " %%pc3");
153 if (do_nhm_cstates) 153 if (do_nhm_cstates)
154 fprintf(stderr, " %%pc6 "); 154 fprintf(stderr, " %%pc6");
155 if (do_snb_cstates) 155 if (do_snb_cstates)
156 fprintf(stderr, " %%pc7 "); 156 fprintf(stderr, " %%pc7");
157 if (extra_msr_offset) 157 if (extra_msr_offset)
158 fprintf(stderr, " MSR 0x%x ", extra_msr_offset); 158 fprintf(stderr, " MSR 0x%x ", extra_msr_offset);
159 159
160 putc('\n', stderr); 160 putc('\n', stderr);
161} 161}
@@ -194,14 +194,14 @@ void print_cnt(struct counters *p)
194 /* topology columns, print blanks on 1st (average) line */ 194 /* topology columns, print blanks on 1st (average) line */
195 if (p == cnt_average) { 195 if (p == cnt_average) {
196 if (show_pkg) 196 if (show_pkg)
197 fprintf(stderr, " "); 197 fprintf(stderr, " ");
198 if (show_core) 198 if (show_core)
199 fprintf(stderr, " "); 199 fprintf(stderr, " ");
200 if (show_cpu) 200 if (show_cpu)
201 fprintf(stderr, " "); 201 fprintf(stderr, " ");
202 } else { 202 } else {
203 if (show_pkg) 203 if (show_pkg)
204 fprintf(stderr, "%4d", p->pkg); 204 fprintf(stderr, "%d", p->pkg);
205 if (show_core) 205 if (show_core)
206 fprintf(stderr, "%4d", p->core); 206 fprintf(stderr, "%4d", p->core);
207 if (show_cpu) 207 if (show_cpu)
@@ -241,22 +241,22 @@ void print_cnt(struct counters *p)
241 if (!skip_c1) 241 if (!skip_c1)
242 fprintf(stderr, "%7.2f", 100.0 * p->c1/p->tsc); 242 fprintf(stderr, "%7.2f", 100.0 * p->c1/p->tsc);
243 else 243 else
244 fprintf(stderr, " ****"); 244 fprintf(stderr, " ****");
245 } 245 }
246 if (do_nhm_cstates) 246 if (do_nhm_cstates)
247 fprintf(stderr, "%7.2f", 100.0 * p->c3/p->tsc); 247 fprintf(stderr, " %6.2f", 100.0 * p->c3/p->tsc);
248 if (do_nhm_cstates) 248 if (do_nhm_cstates)
249 fprintf(stderr, "%7.2f", 100.0 * p->c6/p->tsc); 249 fprintf(stderr, " %6.2f", 100.0 * p->c6/p->tsc);
250 if (do_snb_cstates) 250 if (do_snb_cstates)
251 fprintf(stderr, "%7.2f", 100.0 * p->c7/p->tsc); 251 fprintf(stderr, " %6.2f", 100.0 * p->c7/p->tsc);
252 if (do_snb_cstates) 252 if (do_snb_cstates)
253 fprintf(stderr, "%7.2f", 100.0 * p->pc2/p->tsc); 253 fprintf(stderr, " %5.2f", 100.0 * p->pc2/p->tsc);
254 if (do_nhm_cstates) 254 if (do_nhm_cstates)
255 fprintf(stderr, "%7.2f", 100.0 * p->pc3/p->tsc); 255 fprintf(stderr, " %5.2f", 100.0 * p->pc3/p->tsc);
256 if (do_nhm_cstates) 256 if (do_nhm_cstates)
257 fprintf(stderr, "%7.2f", 100.0 * p->pc6/p->tsc); 257 fprintf(stderr, " %5.2f", 100.0 * p->pc6/p->tsc);
258 if (do_snb_cstates) 258 if (do_snb_cstates)
259 fprintf(stderr, "%7.2f", 100.0 * p->pc7/p->tsc); 259 fprintf(stderr, " %5.2f", 100.0 * p->pc7/p->tsc);
260 if (extra_msr_offset) 260 if (extra_msr_offset)
261 fprintf(stderr, " 0x%016llx", p->extra_msr); 261 fprintf(stderr, " 0x%016llx", p->extra_msr);
262 putc('\n', stderr); 262 putc('\n', stderr);
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
index 2618ef2ba31..33c5c7ee148 100644
--- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
@@ -137,7 +137,6 @@ void cmdline(int argc, char **argv)
137void validate_cpuid(void) 137void validate_cpuid(void)
138{ 138{
139 unsigned int eax, ebx, ecx, edx, max_level; 139 unsigned int eax, ebx, ecx, edx, max_level;
140 char brand[16];
141 unsigned int fms, family, model, stepping; 140 unsigned int fms, family, model, stepping;
142 141
143 eax = ebx = ecx = edx = 0; 142 eax = ebx = ecx = edx = 0;
@@ -160,8 +159,8 @@ void validate_cpuid(void)
160 model += ((fms >> 16) & 0xf) << 4; 159 model += ((fms >> 16) & 0xf) << 4;
161 160
162 if (verbose > 1) 161 if (verbose > 1)
163 printf("CPUID %s %d levels family:model:stepping " 162 printf("CPUID %d levels family:model:stepping "
164 "0x%x:%x:%x (%d:%d:%d)\n", brand, max_level, 163 "0x%x:%x:%x (%d:%d:%d)\n", max_level,
165 family, model, stepping, family, model, stepping); 164 family, model, stepping, family, model, stepping);
166 165
167 if (!(edx & (1 << 5))) { 166 if (!(edx & (1 << 5))) {
diff --git a/tools/slub/slabinfo.c b/tools/slub/slabinfo.c
index 516551c9f17..868cc93f7ac 100644
--- a/tools/slub/slabinfo.c
+++ b/tools/slub/slabinfo.c
@@ -2,8 +2,9 @@
2 * Slabinfo: Tool to get reports about slabs 2 * Slabinfo: Tool to get reports about slabs
3 * 3 *
4 * (C) 2007 sgi, Christoph Lameter 4 * (C) 2007 sgi, Christoph Lameter
5 * (C) 2011 Linux Foundation, Christoph Lameter
5 * 6 *
6 * Compile by: 7 * Compile with:
7 * 8 *
8 * gcc -o slabinfo slabinfo.c 9 * gcc -o slabinfo slabinfo.c
9 */ 10 */
@@ -39,6 +40,8 @@ struct slabinfo {
39 unsigned long cpuslab_flush, deactivate_full, deactivate_empty; 40 unsigned long cpuslab_flush, deactivate_full, deactivate_empty;
40 unsigned long deactivate_to_head, deactivate_to_tail; 41 unsigned long deactivate_to_head, deactivate_to_tail;
41 unsigned long deactivate_remote_frees, order_fallback; 42 unsigned long deactivate_remote_frees, order_fallback;
43 unsigned long cmpxchg_double_cpu_fail, cmpxchg_double_fail;
44 unsigned long alloc_node_mismatch, deactivate_bypass;
42 int numa[MAX_NODES]; 45 int numa[MAX_NODES];
43 int numa_partial[MAX_NODES]; 46 int numa_partial[MAX_NODES];
44} slabinfo[MAX_SLABS]; 47} slabinfo[MAX_SLABS];
@@ -99,7 +102,7 @@ static void fatal(const char *x, ...)
99 102
100static void usage(void) 103static void usage(void)
101{ 104{
102 printf("slabinfo 5/7/2007. (c) 2007 sgi.\n\n" 105 printf("slabinfo 4/15/2011. (c) 2007 sgi/(c) 2011 Linux Foundation.\n\n"
103 "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n" 106 "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n"
104 "-a|--aliases Show aliases\n" 107 "-a|--aliases Show aliases\n"
105 "-A|--activity Most active slabs first\n" 108 "-A|--activity Most active slabs first\n"
@@ -293,7 +296,7 @@ int line = 0;
293static void first_line(void) 296static void first_line(void)
294{ 297{
295 if (show_activity) 298 if (show_activity)
296 printf("Name Objects Alloc Free %%Fast Fallb O\n"); 299 printf("Name Objects Alloc Free %%Fast Fallb O CmpX UL\n");
297 else 300 else
298 printf("Name Objects Objsize Space " 301 printf("Name Objects Objsize Space "
299 "Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n"); 302 "Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n");
@@ -379,14 +382,14 @@ static void show_tracking(struct slabinfo *s)
379 printf("\n%s: Kernel object allocation\n", s->name); 382 printf("\n%s: Kernel object allocation\n", s->name);
380 printf("-----------------------------------------------------------------------\n"); 383 printf("-----------------------------------------------------------------------\n");
381 if (read_slab_obj(s, "alloc_calls")) 384 if (read_slab_obj(s, "alloc_calls"))
382 printf(buffer); 385 printf("%s", buffer);
383 else 386 else
384 printf("No Data\n"); 387 printf("No Data\n");
385 388
386 printf("\n%s: Kernel object freeing\n", s->name); 389 printf("\n%s: Kernel object freeing\n", s->name);
387 printf("------------------------------------------------------------------------\n"); 390 printf("------------------------------------------------------------------------\n");
388 if (read_slab_obj(s, "free_calls")) 391 if (read_slab_obj(s, "free_calls"))
389 printf(buffer); 392 printf("%s", buffer);
390 else 393 else
391 printf("No Data\n"); 394 printf("No Data\n");
392 395
@@ -400,7 +403,7 @@ static void ops(struct slabinfo *s)
400 if (read_slab_obj(s, "ops")) { 403 if (read_slab_obj(s, "ops")) {
401 printf("\n%s: kmem_cache operations\n", s->name); 404 printf("\n%s: kmem_cache operations\n", s->name);
402 printf("--------------------------------------------\n"); 405 printf("--------------------------------------------\n");
403 printf(buffer); 406 printf("%s", buffer);
404 } else 407 } else
405 printf("\n%s has no kmem_cache operations\n", s->name); 408 printf("\n%s has no kmem_cache operations\n", s->name);
406} 409}
@@ -462,19 +465,32 @@ static void slab_stats(struct slabinfo *s)
462 if (s->cpuslab_flush) 465 if (s->cpuslab_flush)
463 printf("Flushes %8lu\n", s->cpuslab_flush); 466 printf("Flushes %8lu\n", s->cpuslab_flush);
464 467
465 if (s->alloc_refill)
466 printf("Refill %8lu\n", s->alloc_refill);
467
468 total = s->deactivate_full + s->deactivate_empty + 468 total = s->deactivate_full + s->deactivate_empty +
469 s->deactivate_to_head + s->deactivate_to_tail; 469 s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass;
470 470
471 if (total) 471 if (total) {
472 printf("Deactivate Full=%lu(%lu%%) Empty=%lu(%lu%%) " 472 printf("\nSlab Deactivation Ocurrences %%\n");
473 "ToHead=%lu(%lu%%) ToTail=%lu(%lu%%)\n", 473 printf("-------------------------------------------------\n");
474 s->deactivate_full, (s->deactivate_full * 100) / total, 474 printf("Slab full %7lu %3lu%%\n",
475 s->deactivate_empty, (s->deactivate_empty * 100) / total, 475 s->deactivate_full, (s->deactivate_full * 100) / total);
476 s->deactivate_to_head, (s->deactivate_to_head * 100) / total, 476 printf("Slab empty %7lu %3lu%%\n",
477 s->deactivate_empty, (s->deactivate_empty * 100) / total);
478 printf("Moved to head of partial list %7lu %3lu%%\n",
479 s->deactivate_to_head, (s->deactivate_to_head * 100) / total);
480 printf("Moved to tail of partial list %7lu %3lu%%\n",
477 s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total); 481 s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total);
482 printf("Deactivation bypass %7lu %3lu%%\n",
483 s->deactivate_bypass, (s->deactivate_bypass * 100) / total);
484 printf("Refilled from foreign frees %7lu %3lu%%\n",
485 s->alloc_refill, (s->alloc_refill * 100) / total);
486 printf("Node mismatch %7lu %3lu%%\n",
487 s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total);
488 }
489
490 if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail)
491 printf("\nCmpxchg_double Looping\n------------------------\n");
492 printf("Locked Cmpxchg Double redos %lu\nUnlocked Cmpxchg Double redos %lu\n",
493 s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail);
478} 494}
479 495
480static void report(struct slabinfo *s) 496static void report(struct slabinfo *s)
@@ -573,12 +589,13 @@ static void slabcache(struct slabinfo *s)
573 total_alloc = s->alloc_fastpath + s->alloc_slowpath; 589 total_alloc = s->alloc_fastpath + s->alloc_slowpath;
574 total_free = s->free_fastpath + s->free_slowpath; 590 total_free = s->free_fastpath + s->free_slowpath;
575 591
576 printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d\n", 592 printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d %4ld %4ld\n",
577 s->name, s->objects, 593 s->name, s->objects,
578 total_alloc, total_free, 594 total_alloc, total_free,
579 total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0, 595 total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0,
580 total_free ? (s->free_fastpath * 100 / total_free) : 0, 596 total_free ? (s->free_fastpath * 100 / total_free) : 0,
581 s->order_fallback, s->order); 597 s->order_fallback, s->order, s->cmpxchg_double_fail,
598 s->cmpxchg_double_cpu_fail);
582 } 599 }
583 else 600 else
584 printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n", 601 printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",
@@ -1190,6 +1207,10 @@ static void read_slab_dir(void)
1190 slab->deactivate_to_tail = get_obj("deactivate_to_tail"); 1207 slab->deactivate_to_tail = get_obj("deactivate_to_tail");
1191 slab->deactivate_remote_frees = get_obj("deactivate_remote_frees"); 1208 slab->deactivate_remote_frees = get_obj("deactivate_remote_frees");
1192 slab->order_fallback = get_obj("order_fallback"); 1209 slab->order_fallback = get_obj("order_fallback");
1210 slab->cmpxchg_double_cpu_fail = get_obj("cmpxchg_double_cpu_fail");
1211 slab->cmpxchg_double_fail = get_obj("cmpxchg_double_fail");
1212 slab->alloc_node_mismatch = get_obj("alloc_node_mismatch");
1213 slab->deactivate_bypass = get_obj("deactivate_bypass");
1193 chdir(".."); 1214 chdir("..");
1194 if (slab->name[0] == ':') 1215 if (slab->name[0] == ':')
1195 alias_targets++; 1216 alias_targets++;
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index cef28e6632b..8d02ccb10c5 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -27,7 +27,7 @@ $default{"TEST_TYPE"} = "test";
27$default{"BUILD_TYPE"} = "randconfig"; 27$default{"BUILD_TYPE"} = "randconfig";
28$default{"MAKE_CMD"} = "make"; 28$default{"MAKE_CMD"} = "make";
29$default{"TIMEOUT"} = 120; 29$default{"TIMEOUT"} = 120;
30$default{"TMP_DIR"} = "/tmp/ktest"; 30$default{"TMP_DIR"} = "/tmp/ktest/\${MACHINE}";
31$default{"SLEEP_TIME"} = 60; # sleep time between tests 31$default{"SLEEP_TIME"} = 60; # sleep time between tests
32$default{"BUILD_NOCLEAN"} = 0; 32$default{"BUILD_NOCLEAN"} = 0;
33$default{"REBOOT_ON_ERROR"} = 0; 33$default{"REBOOT_ON_ERROR"} = 0;
@@ -41,6 +41,7 @@ $default{"CLEAR_LOG"} = 0;
41$default{"BISECT_MANUAL"} = 0; 41$default{"BISECT_MANUAL"} = 0;
42$default{"BISECT_SKIP"} = 1; 42$default{"BISECT_SKIP"} = 1;
43$default{"SUCCESS_LINE"} = "login:"; 43$default{"SUCCESS_LINE"} = "login:";
44$default{"DETECT_TRIPLE_FAULT"} = 1;
44$default{"BOOTED_TIMEOUT"} = 1; 45$default{"BOOTED_TIMEOUT"} = 1;
45$default{"DIE_ON_FAILURE"} = 1; 46$default{"DIE_ON_FAILURE"} = 1;
46$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND"; 47$default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
@@ -62,6 +63,10 @@ my $output_config;
62my $test_type; 63my $test_type;
63my $build_type; 64my $build_type;
64my $build_options; 65my $build_options;
66my $pre_build;
67my $post_build;
68my $pre_build_die;
69my $post_build_die;
65my $reboot_type; 70my $reboot_type;
66my $reboot_script; 71my $reboot_script;
67my $power_cycle; 72my $power_cycle;
@@ -81,12 +86,17 @@ my $make;
81my $post_install; 86my $post_install;
82my $noclean; 87my $noclean;
83my $minconfig; 88my $minconfig;
89my $start_minconfig;
90my $start_minconfig_defined;
91my $output_minconfig;
92my $ignore_config;
84my $addconfig; 93my $addconfig;
85my $in_bisect = 0; 94my $in_bisect = 0;
86my $bisect_bad = ""; 95my $bisect_bad = "";
87my $reverse_bisect; 96my $reverse_bisect;
88my $bisect_manual; 97my $bisect_manual;
89my $bisect_skip; 98my $bisect_skip;
99my $config_bisect_good;
90my $in_patchcheck = 0; 100my $in_patchcheck = 0;
91my $run_test; 101my $run_test;
92my $redirect; 102my $redirect;
@@ -98,9 +108,12 @@ my $monitor_cnt = 0;
98my $sleep_time; 108my $sleep_time;
99my $bisect_sleep_time; 109my $bisect_sleep_time;
100my $patchcheck_sleep_time; 110my $patchcheck_sleep_time;
111my $ignore_warnings;
101my $store_failures; 112my $store_failures;
113my $test_name;
102my $timeout; 114my $timeout;
103my $booted_timeout; 115my $booted_timeout;
116my $detect_triplefault;
104my $console; 117my $console;
105my $success_line; 118my $success_line;
106my $stop_after_success; 119my $stop_after_success;
@@ -115,6 +128,7 @@ my $successes = 0;
115my %entered_configs; 128my %entered_configs;
116my %config_help; 129my %config_help;
117my %variable; 130my %variable;
131my %force_config;
118 132
119$config_help{"MACHINE"} = << "EOF" 133$config_help{"MACHINE"} = << "EOF"
120 The machine hostname that you will test. 134 The machine hostname that you will test.
@@ -204,6 +218,26 @@ $config_help{"REBOOT_SCRIPT"} = << "EOF"
204EOF 218EOF
205 ; 219 ;
206 220
221sub read_yn {
222 my ($prompt) = @_;
223
224 my $ans;
225
226 for (;;) {
227 print "$prompt [Y/n] ";
228 $ans = <STDIN>;
229 chomp $ans;
230 if ($ans =~ /^\s*$/) {
231 $ans = "y";
232 }
233 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
234 print "Please answer either 'y' or 'n'.\n";
235 }
236 if ($ans !~ /^y$/i) {
237 return 0;
238 }
239 return 1;
240}
207 241
208sub get_ktest_config { 242sub get_ktest_config {
209 my ($config) = @_; 243 my ($config) = @_;
@@ -335,6 +369,7 @@ sub read_config {
335 my $num_tests_set = 0; 369 my $num_tests_set = 0;
336 my $skip = 0; 370 my $skip = 0;
337 my $rest; 371 my $rest;
372 my $test_case = 0;
338 373
339 while (<IN>) { 374 while (<IN>) {
340 375
@@ -360,6 +395,7 @@ sub read_config {
360 $rest = $1; 395 $rest = $1;
361 $skip = 1; 396 $skip = 1;
362 } else { 397 } else {
398 $test_case = 1;
363 $skip = 0; 399 $skip = 0;
364 } 400 }
365 401
@@ -464,6 +500,15 @@ sub read_config {
464 # make sure we have all mandatory configs 500 # make sure we have all mandatory configs
465 get_ktest_configs; 501 get_ktest_configs;
466 502
503 # was a test specified?
504 if (!$test_case) {
505 print "No test case specified.\n";
506 print "What test case would you like to run?\n";
507 my $ans = <STDIN>;
508 chomp $ans;
509 $default{"TEST_TYPE"} = $ans;
510 }
511
467 # set any defaults 512 # set any defaults
468 513
469 foreach my $default (keys %default) { 514 foreach my $default (keys %default) {
@@ -473,6 +518,69 @@ sub read_config {
473 } 518 }
474} 519}
475 520
521sub __eval_option {
522 my ($option, $i) = @_;
523
524 # Add space to evaluate the character before $
525 $option = " $option";
526 my $retval = "";
527
528 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
529 my $start = $1;
530 my $var = $2;
531 my $end = $3;
532
533 # Append beginning of line
534 $retval = "$retval$start";
535
536 # If the iteration option OPT[$i] exists, then use that.
537 # otherwise see if the default OPT (without [$i]) exists.
538
539 my $o = "$var\[$i\]";
540
541 if (defined($opt{$o})) {
542 $o = $opt{$o};
543 $retval = "$retval$o";
544 } elsif (defined($opt{$var})) {
545 $o = $opt{$var};
546 $retval = "$retval$o";
547 } else {
548 $retval = "$retval\$\{$var\}";
549 }
550
551 $option = $end;
552 }
553
554 $retval = "$retval$option";
555
556 $retval =~ s/^ //;
557
558 return $retval;
559}
560
561sub eval_option {
562 my ($option, $i) = @_;
563
564 my $prev = "";
565
566 # Since an option can evaluate to another option,
567 # keep iterating until we do not evaluate any more
568 # options.
569 my $r = 0;
570 while ($prev ne $option) {
571 # Check for recursive evaluations.
572 # 100 deep should be more than enough.
573 if ($r++ > 100) {
574 die "Over 100 evaluations accurred with $option\n" .
575 "Check for recursive variables\n";
576 }
577 $prev = $option;
578 $option = __eval_option($option, $i);
579 }
580
581 return $option;
582}
583
476sub _logit { 584sub _logit {
477 if (defined($opt{"LOG_FILE"})) { 585 if (defined($opt{"LOG_FILE"})) {
478 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 586 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
@@ -617,9 +725,15 @@ sub fail {
617 end_monitor; 725 end_monitor;
618 } 726 }
619 727
728 my $name = "";
729
730 if (defined($test_name)) {
731 $name = " ($test_name)";
732 }
733
620 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 734 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
621 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 735 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
622 doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n"; 736 doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
623 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 737 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
624 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; 738 doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
625 739
@@ -836,17 +950,35 @@ sub monitor {
836 my $failure_start; 950 my $failure_start;
837 my $monitor_start = time; 951 my $monitor_start = time;
838 my $done = 0; 952 my $done = 0;
953 my $version_found = 0;
839 954
840 while (!$done) { 955 while (!$done) {
841 956
842 if ($booted) { 957 if ($bug && defined($stop_after_failure) &&
958 $stop_after_failure >= 0) {
959 my $time = $stop_after_failure - (time - $failure_start);
960 $line = wait_for_input($monitor_fp, $time);
961 if (!defined($line)) {
962 doprint "bug timed out after $booted_timeout seconds\n";
963 doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
964 last;
965 }
966 } elsif ($booted) {
843 $line = wait_for_input($monitor_fp, $booted_timeout); 967 $line = wait_for_input($monitor_fp, $booted_timeout);
968 if (!defined($line)) {
969 my $s = $booted_timeout == 1 ? "" : "s";
970 doprint "Successful boot found: break after $booted_timeout second$s\n";
971 last;
972 }
844 } else { 973 } else {
845 $line = wait_for_input($monitor_fp); 974 $line = wait_for_input($monitor_fp);
975 if (!defined($line)) {
976 my $s = $timeout == 1 ? "" : "s";
977 doprint "Timed out after $timeout second$s\n";
978 last;
979 }
846 } 980 }
847 981
848 last if (!defined($line));
849
850 doprint $line; 982 doprint $line;
851 print DMESG $line; 983 print DMESG $line;
852 984
@@ -896,6 +1028,22 @@ sub monitor {
896 $bug = 1; 1028 $bug = 1;
897 } 1029 }
898 1030
1031 # Detect triple faults by testing the banner
1032 if ($full_line =~ /\bLinux version (\S+).*\n/) {
1033 if ($1 eq $version) {
1034 $version_found = 1;
1035 } elsif ($version_found && $detect_triplefault) {
1036 # We already booted into the kernel we are testing,
1037 # but now we booted into another kernel?
1038 # Consider this a triple fault.
1039 doprint "Aleady booted in Linux kernel $version, but now\n";
1040 doprint "we booted into Linux kernel $1.\n";
1041 doprint "Assuming that this is a triple fault.\n";
1042 doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1043 last;
1044 }
1045 }
1046
899 if ($line =~ /\n/) { 1047 if ($line =~ /\n/) {
900 $full_line = ""; 1048 $full_line = "";
901 } 1049 }
@@ -923,6 +1071,16 @@ sub monitor {
923 return 1; 1071 return 1;
924} 1072}
925 1073
1074sub do_post_install {
1075
1076 return if (!defined($post_install));
1077
1078 my $cp_post_install = $post_install;
1079 $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
1080 run_command "$cp_post_install" or
1081 dodie "Failed to run post install";
1082}
1083
926sub install { 1084sub install {
927 1085
928 run_scp "$outputdir/$build_target", "$target_image" or 1086 run_scp "$outputdir/$build_target", "$target_image" or
@@ -942,6 +1100,7 @@ sub install {
942 close(IN); 1100 close(IN);
943 1101
944 if (!$install_mods) { 1102 if (!$install_mods) {
1103 do_post_install;
945 doprint "No modules needed\n"; 1104 doprint "No modules needed\n";
946 return; 1105 return;
947 } 1106 }
@@ -964,17 +1123,29 @@ sub install {
964 1123
965 unlink "$tmpdir/$modtar"; 1124 unlink "$tmpdir/$modtar";
966 1125
967 run_ssh "'(cd / && tar xf /tmp/$modtar)'" or 1126 run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
968 dodie "failed to tar modules"; 1127 dodie "failed to tar modules";
969 1128
970 run_ssh "rm -f /tmp/$modtar"; 1129 run_ssh "rm -f /tmp/$modtar";
971 1130
972 return if (!defined($post_install)); 1131 do_post_install;
1132}
973 1133
974 my $cp_post_install = $post_install; 1134sub get_version {
975 $cp_post_install =~ s/\$KERNEL_VERSION/$version/g; 1135 # get the release name
976 run_command "$cp_post_install" or 1136 doprint "$make kernelrelease ... ";
977 dodie "Failed to run post install"; 1137 $version = `$make kernelrelease | tail -1`;
1138 chomp($version);
1139 doprint "$version\n";
1140}
1141
1142sub start_monitor_and_boot {
1143 get_grub_index;
1144 get_version;
1145 install;
1146
1147 start_monitor;
1148 return monitor;
978} 1149}
979 1150
980sub check_buildlog { 1151sub check_buildlog {
@@ -1009,24 +1180,84 @@ sub check_buildlog {
1009 return 1; 1180 return 1;
1010} 1181}
1011 1182
1183sub apply_min_config {
1184 my $outconfig = "$output_config.new";
1185
1186 # Read the config file and remove anything that
1187 # is in the force_config hash (from minconfig and others)
1188 # then add the force config back.
1189
1190 doprint "Applying minimum configurations into $output_config.new\n";
1191
1192 open (OUT, ">$outconfig") or
1193 dodie "Can't create $outconfig";
1194
1195 if (-f $output_config) {
1196 open (IN, $output_config) or
1197 dodie "Failed to open $output_config";
1198 while (<IN>) {
1199 if (/^(# )?(CONFIG_[^\s=]*)/) {
1200 next if (defined($force_config{$2}));
1201 }
1202 print OUT;
1203 }
1204 close IN;
1205 }
1206 foreach my $config (keys %force_config) {
1207 print OUT "$force_config{$config}\n";
1208 }
1209 close OUT;
1210
1211 run_command "mv $outconfig $output_config";
1212}
1213
1012sub make_oldconfig { 1214sub make_oldconfig {
1013 my ($defconfig) = @_;
1014 1215
1015 if (!run_command "$defconfig $make oldnoconfig") { 1216 my @force_list = keys %force_config;
1217
1218 if ($#force_list >= 0) {
1219 apply_min_config;
1220 }
1221
1222 if (!run_command "$make oldnoconfig") {
1016 # Perhaps oldnoconfig doesn't exist in this version of the kernel 1223 # Perhaps oldnoconfig doesn't exist in this version of the kernel
1017 # try a yes '' | oldconfig 1224 # try a yes '' | oldconfig
1018 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; 1225 doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1019 run_command "yes '' | $defconfig $make oldconfig" or 1226 run_command "yes '' | $make oldconfig" or
1020 dodie "failed make config oldconfig"; 1227 dodie "failed make config oldconfig";
1021 } 1228 }
1022} 1229}
1023 1230
1231# read a config file and use this to force new configs.
1232sub load_force_config {
1233 my ($config) = @_;
1234
1235 open(IN, $config) or
1236 dodie "failed to read $config";
1237 while (<IN>) {
1238 chomp;
1239 if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1240 $force_config{$1} = $_;
1241 } elsif (/^# (CONFIG_\S*) is not set/) {
1242 $force_config{$1} = $_;
1243 }
1244 }
1245 close IN;
1246}
1247
1024sub build { 1248sub build {
1025 my ($type) = @_; 1249 my ($type) = @_;
1026 my $defconfig = "";
1027 1250
1028 unlink $buildlog; 1251 unlink $buildlog;
1029 1252
1253 if (defined($pre_build)) {
1254 my $ret = run_command $pre_build;
1255 if (!$ret && defined($pre_build_die) &&
1256 $pre_build_die) {
1257 dodie "failed to pre_build\n";
1258 }
1259 }
1260
1030 if ($type =~ /^useconfig:(.*)/) { 1261 if ($type =~ /^useconfig:(.*)/) {
1031 run_command "cp $1 $output_config" or 1262 run_command "cp $1 $output_config" or
1032 dodie "could not copy $1 to .config"; 1263 dodie "could not copy $1 to .config";
@@ -1063,24 +1294,33 @@ sub build {
1063 close(OUT); 1294 close(OUT);
1064 1295
1065 if (defined($minconfig)) { 1296 if (defined($minconfig)) {
1066 $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; 1297 load_force_config($minconfig);
1067 } 1298 }
1068 1299
1069 if ($type eq "oldnoconfig") { 1300 if ($type ne "oldnoconfig") {
1070 make_oldconfig $defconfig; 1301 run_command "$make $type" or
1071 } else {
1072 run_command "$defconfig $make $type" or
1073 dodie "failed make config"; 1302 dodie "failed make config";
1074 } 1303 }
1304 # Run old config regardless, to enforce min configurations
1305 make_oldconfig;
1075 1306
1076 $redirect = "$buildlog"; 1307 $redirect = "$buildlog";
1077 if (!run_command "$make $build_options") { 1308 my $build_ret = run_command "$make $build_options";
1078 undef $redirect; 1309 undef $redirect;
1310
1311 if (defined($post_build)) {
1312 my $ret = run_command $post_build;
1313 if (!$ret && defined($post_build_die) &&
1314 $post_build_die) {
1315 dodie "failed to post_build\n";
1316 }
1317 }
1318
1319 if (!$build_ret) {
1079 # bisect may need this to pass 1320 # bisect may need this to pass
1080 return 0 if ($in_bisect); 1321 return 0 if ($in_bisect);
1081 fail "failed build" and return 0; 1322 fail "failed build" and return 0;
1082 } 1323 }
1083 undef $redirect;
1084 1324
1085 return 1; 1325 return 1;
1086} 1326}
@@ -1102,9 +1342,15 @@ sub success {
1102 1342
1103 $successes++; 1343 $successes++;
1104 1344
1345 my $name = "";
1346
1347 if (defined($test_name)) {
1348 $name = " ($test_name)";
1349 }
1350
1105 doprint "\n\n*******************************************\n"; 1351 doprint "\n\n*******************************************\n";
1106 doprint "*******************************************\n"; 1352 doprint "*******************************************\n";
1107 doprint "KTEST RESULT: TEST $i SUCCESS!!!! **\n"; 1353 doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n";
1108 doprint "*******************************************\n"; 1354 doprint "*******************************************\n";
1109 doprint "*******************************************\n"; 1355 doprint "*******************************************\n";
1110 1356
@@ -1117,14 +1363,6 @@ sub success {
1117 } 1363 }
1118} 1364}
1119 1365
1120sub get_version {
1121 # get the release name
1122 doprint "$make kernelrelease ... ";
1123 $version = `$make kernelrelease | tail -1`;
1124 chomp($version);
1125 doprint "$version\n";
1126}
1127
1128sub answer_bisect { 1366sub answer_bisect {
1129 for (;;) { 1367 for (;;) {
1130 doprint "Pass or fail? [p/f]"; 1368 doprint "Pass or fail? [p/f]";
@@ -1289,12 +1527,7 @@ sub run_bisect_test {
1289 dodie "Failed on build" if $failed; 1527 dodie "Failed on build" if $failed;
1290 1528
1291 # Now boot the box 1529 # Now boot the box
1292 get_grub_index; 1530 start_monitor_and_boot or $failed = 1;
1293 get_version;
1294 install;
1295
1296 start_monitor;
1297 monitor or $failed = 1;
1298 1531
1299 if ($type ne "boot") { 1532 if ($type ne "boot") {
1300 if ($failed && $bisect_skip) { 1533 if ($failed && $bisect_skip) {
@@ -1473,21 +1706,27 @@ my %null_config;
1473 1706
1474my %dependency; 1707my %dependency;
1475 1708
1476sub process_config_ignore { 1709sub assign_configs {
1477 my ($config) = @_; 1710 my ($hash, $config) = @_;
1478 1711
1479 open (IN, $config) 1712 open (IN, $config)
1480 or dodie "Failed to read $config"; 1713 or dodie "Failed to read $config";
1481 1714
1482 while (<IN>) { 1715 while (<IN>) {
1483 if (/^((CONFIG\S*)=.*)/) { 1716 if (/^((CONFIG\S*)=.*)/) {
1484 $config_ignore{$2} = $1; 1717 ${$hash}{$2} = $1;
1485 } 1718 }
1486 } 1719 }
1487 1720
1488 close(IN); 1721 close(IN);
1489} 1722}
1490 1723
1724sub process_config_ignore {
1725 my ($config) = @_;
1726
1727 assign_configs \%config_ignore, $config;
1728}
1729
1491sub read_current_config { 1730sub read_current_config {
1492 my ($config_ref) = @_; 1731 my ($config_ref) = @_;
1493 1732
@@ -1546,7 +1785,7 @@ sub create_config {
1546 close(OUT); 1785 close(OUT);
1547 1786
1548# exit; 1787# exit;
1549 make_oldconfig ""; 1788 make_oldconfig;
1550} 1789}
1551 1790
1552sub compare_configs { 1791sub compare_configs {
@@ -1718,6 +1957,10 @@ sub config_bisect {
1718 1957
1719 my $tmpconfig = "$tmpdir/use_config"; 1958 my $tmpconfig = "$tmpdir/use_config";
1720 1959
1960 if (defined($config_bisect_good)) {
1961 process_config_ignore $config_bisect_good;
1962 }
1963
1721 # Make the file with the bad config and the min config 1964 # Make the file with the bad config and the min config
1722 if (defined($minconfig)) { 1965 if (defined($minconfig)) {
1723 # read the min config for things to ignore 1966 # read the min config for things to ignore
@@ -1727,15 +1970,8 @@ sub config_bisect {
1727 unlink $tmpconfig; 1970 unlink $tmpconfig;
1728 } 1971 }
1729 1972
1730 # Add other configs
1731 if (defined($addconfig)) {
1732 run_command "cat $addconfig >> $tmpconfig" or
1733 dodie "failed to append $addconfig";
1734 }
1735
1736 my $defconfig = "";
1737 if (-f $tmpconfig) { 1973 if (-f $tmpconfig) {
1738 $defconfig = "KCONFIG_ALLCONFIG=$tmpconfig"; 1974 load_force_config($tmpconfig);
1739 process_config_ignore $tmpconfig; 1975 process_config_ignore $tmpconfig;
1740 } 1976 }
1741 1977
@@ -1755,8 +1991,8 @@ sub config_bisect {
1755 } 1991 }
1756 close(IN); 1992 close(IN);
1757 1993
1758 # Now run oldconfig with the minconfig (and addconfigs) 1994 # Now run oldconfig with the minconfig
1759 make_oldconfig $defconfig; 1995 make_oldconfig;
1760 1996
1761 # check to see what we lost (or gained) 1997 # check to see what we lost (or gained)
1762 open (IN, $output_config) 1998 open (IN, $output_config)
@@ -1882,6 +2118,13 @@ sub patchcheck {
1882 @list = reverse @list; 2118 @list = reverse @list;
1883 2119
1884 my $save_clean = $noclean; 2120 my $save_clean = $noclean;
2121 my %ignored_warnings;
2122
2123 if (defined($ignore_warnings)) {
2124 foreach my $sha1 (split /\s+/, $ignore_warnings) {
2125 $ignored_warnings{$sha1} = 1;
2126 }
2127 }
1885 2128
1886 $in_patchcheck = 1; 2129 $in_patchcheck = 1;
1887 foreach my $item (@list) { 2130 foreach my $item (@list) {
@@ -1908,18 +2151,16 @@ sub patchcheck {
1908 build "oldconfig" or return 0; 2151 build "oldconfig" or return 0;
1909 } 2152 }
1910 2153
1911 check_buildlog $sha1 or return 0;
1912 2154
1913 next if ($type eq "build"); 2155 if (!defined($ignored_warnings{$sha1})) {
2156 check_buildlog $sha1 or return 0;
2157 }
1914 2158
1915 get_grub_index; 2159 next if ($type eq "build");
1916 get_version;
1917 install;
1918 2160
1919 my $failed = 0; 2161 my $failed = 0;
1920 2162
1921 start_monitor; 2163 start_monitor_and_boot or $failed = 1;
1922 monitor or $failed = 1;
1923 2164
1924 if (!$failed && $type ne "boot"){ 2165 if (!$failed && $type ne "boot"){
1925 do_run_test or $failed = 1; 2166 do_run_test or $failed = 1;
@@ -1936,24 +2177,505 @@ sub patchcheck {
1936 return 1; 2177 return 1;
1937} 2178}
1938 2179
2180my %depends;
2181my $iflevel = 0;
2182my @ifdeps;
2183
2184# prevent recursion
2185my %read_kconfigs;
2186
2187# taken from streamline_config.pl
2188sub read_kconfig {
2189 my ($kconfig) = @_;
2190
2191 my $state = "NONE";
2192 my $config;
2193 my @kconfigs;
2194
2195 my $cont = 0;
2196 my $line;
2197
2198
2199 if (! -f $kconfig) {
2200 doprint "file $kconfig does not exist, skipping\n";
2201 return;
2202 }
2203
2204 open(KIN, "$kconfig")
2205 or die "Can't open $kconfig";
2206 while (<KIN>) {
2207 chomp;
2208
2209 # Make sure that lines ending with \ continue
2210 if ($cont) {
2211 $_ = $line . " " . $_;
2212 }
2213
2214 if (s/\\$//) {
2215 $cont = 1;
2216 $line = $_;
2217 next;
2218 }
2219
2220 $cont = 0;
2221
2222 # collect any Kconfig sources
2223 if (/^source\s*"(.*)"/) {
2224 $kconfigs[$#kconfigs+1] = $1;
2225 }
2226
2227 # configs found
2228 if (/^\s*(menu)?config\s+(\S+)\s*$/) {
2229 $state = "NEW";
2230 $config = $2;
2231
2232 for (my $i = 0; $i < $iflevel; $i++) {
2233 if ($i) {
2234 $depends{$config} .= " " . $ifdeps[$i];
2235 } else {
2236 $depends{$config} = $ifdeps[$i];
2237 }
2238 $state = "DEP";
2239 }
2240
2241 # collect the depends for the config
2242 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
2243
2244 if (defined($depends{$1})) {
2245 $depends{$config} .= " " . $1;
2246 } else {
2247 $depends{$config} = $1;
2248 }
2249
2250 # Get the configs that select this config
2251 } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
2252 if (defined($depends{$1})) {
2253 $depends{$1} .= " " . $config;
2254 } else {
2255 $depends{$1} = $config;
2256 }
2257
2258 # Check for if statements
2259 } elsif (/^if\s+(.*\S)\s*$/) {
2260 my $deps = $1;
2261 # remove beginning and ending non text
2262 $deps =~ s/^[^a-zA-Z0-9_]*//;
2263 $deps =~ s/[^a-zA-Z0-9_]*$//;
2264
2265 my @deps = split /[^a-zA-Z0-9_]+/, $deps;
2266
2267 $ifdeps[$iflevel++] = join ':', @deps;
2268
2269 } elsif (/^endif/) {
2270
2271 $iflevel-- if ($iflevel);
2272
2273 # stop on "help"
2274 } elsif (/^\s*help\s*$/) {
2275 $state = "NONE";
2276 }
2277 }
2278 close(KIN);
2279
2280 # read in any configs that were found.
2281 foreach $kconfig (@kconfigs) {
2282 if (!defined($read_kconfigs{$kconfig})) {
2283 $read_kconfigs{$kconfig} = 1;
2284 read_kconfig("$builddir/$kconfig");
2285 }
2286 }
2287}
2288
2289sub read_depends {
2290 # find out which arch this is by the kconfig file
2291 open (IN, $output_config)
2292 or dodie "Failed to read $output_config";
2293 my $arch;
2294 while (<IN>) {
2295 if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
2296 $arch = $1;
2297 last;
2298 }
2299 }
2300 close IN;
2301
2302 if (!defined($arch)) {
2303 doprint "Could not find arch from config file\n";
2304 doprint "no dependencies used\n";
2305 return;
2306 }
2307
2308 # arch is really the subarch, we need to know
2309 # what directory to look at.
2310 if ($arch eq "i386" || $arch eq "x86_64") {
2311 $arch = "x86";
2312 } elsif ($arch =~ /^tile/) {
2313 $arch = "tile";
2314 }
2315
2316 my $kconfig = "$builddir/arch/$arch/Kconfig";
2317
2318 if (! -f $kconfig && $arch =~ /\d$/) {
2319 my $orig = $arch;
2320 # some subarchs have numbers, truncate them
2321 $arch =~ s/\d*$//;
2322 $kconfig = "$builddir/arch/$arch/Kconfig";
2323 if (! -f $kconfig) {
2324 doprint "No idea what arch dir $orig is for\n";
2325 doprint "no dependencies used\n";
2326 return;
2327 }
2328 }
2329
2330 read_kconfig($kconfig);
2331}
2332
2333sub read_config_list {
2334 my ($config) = @_;
2335
2336 open (IN, $config)
2337 or dodie "Failed to read $config";
2338
2339 while (<IN>) {
2340 if (/^((CONFIG\S*)=.*)/) {
2341 if (!defined($config_ignore{$2})) {
2342 $config_list{$2} = $1;
2343 }
2344 }
2345 }
2346
2347 close(IN);
2348}
2349
2350sub read_output_config {
2351 my ($config) = @_;
2352
2353 assign_configs \%config_ignore, $config;
2354}
2355
2356sub make_new_config {
2357 my @configs = @_;
2358
2359 open (OUT, ">$output_config")
2360 or dodie "Failed to write $output_config";
2361
2362 foreach my $config (@configs) {
2363 print OUT "$config\n";
2364 }
2365 close OUT;
2366}
2367
2368sub get_depends {
2369 my ($dep) = @_;
2370
2371 my $kconfig = $dep;
2372 $kconfig =~ s/CONFIG_//;
2373
2374 $dep = $depends{"$kconfig"};
2375
2376 # the dep string we have saves the dependencies as they
2377 # were found, including expressions like ! && ||. We
2378 # want to split this out into just an array of configs.
2379
2380 my $valid = "A-Za-z_0-9";
2381
2382 my @configs;
2383
2384 while ($dep =~ /[$valid]/) {
2385
2386 if ($dep =~ /^[^$valid]*([$valid]+)/) {
2387 my $conf = "CONFIG_" . $1;
2388
2389 $configs[$#configs + 1] = $conf;
2390
2391 $dep =~ s/^[^$valid]*[$valid]+//;
2392 } else {
2393 die "this should never happen";
2394 }
2395 }
2396
2397 return @configs;
2398}
2399
2400my %min_configs;
2401my %keep_configs;
2402my %save_configs;
2403my %processed_configs;
2404my %nochange_config;
2405
2406sub test_this_config {
2407 my ($config) = @_;
2408
2409 my $found;
2410
2411 # if we already processed this config, skip it
2412 if (defined($processed_configs{$config})) {
2413 return undef;
2414 }
2415 $processed_configs{$config} = 1;
2416
2417 # if this config failed during this round, skip it
2418 if (defined($nochange_config{$config})) {
2419 return undef;
2420 }
2421
2422 my $kconfig = $config;
2423 $kconfig =~ s/CONFIG_//;
2424
2425 # Test dependencies first
2426 if (defined($depends{"$kconfig"})) {
2427 my @parents = get_depends $config;
2428 foreach my $parent (@parents) {
2429 # if the parent is in the min config, check it first
2430 next if (!defined($min_configs{$parent}));
2431 $found = test_this_config($parent);
2432 if (defined($found)) {
2433 return $found;
2434 }
2435 }
2436 }
2437
2438 # Remove this config from the list of configs
2439 # do a make oldnoconfig and then read the resulting
2440 # .config to make sure it is missing the config that
2441 # we had before
2442 my %configs = %min_configs;
2443 delete $configs{$config};
2444 make_new_config ((values %configs), (values %keep_configs));
2445 make_oldconfig;
2446 undef %configs;
2447 assign_configs \%configs, $output_config;
2448
2449 return $config if (!defined($configs{$config}));
2450
2451 doprint "disabling config $config did not change .config\n";
2452
2453 $nochange_config{$config} = 1;
2454
2455 return undef;
2456}
2457
2458sub make_min_config {
2459 my ($i) = @_;
2460
2461 if (!defined($output_minconfig)) {
2462 fail "OUTPUT_MIN_CONFIG not defined" and return;
2463 }
2464
2465 # If output_minconfig exists, and the start_minconfig
2466 # came from min_config, than ask if we should use
2467 # that instead.
2468 if (-f $output_minconfig && !$start_minconfig_defined) {
2469 print "$output_minconfig exists\n";
2470 if (read_yn " Use it as minconfig?") {
2471 $start_minconfig = $output_minconfig;
2472 }
2473 }
2474
2475 if (!defined($start_minconfig)) {
2476 fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
2477 }
2478
2479 my $temp_config = "$tmpdir/temp_config";
2480
2481 # First things first. We build an allnoconfig to find
2482 # out what the defaults are that we can't touch.
2483 # Some are selections, but we really can't handle selections.
2484
2485 my $save_minconfig = $minconfig;
2486 undef $minconfig;
2487
2488 run_command "$make allnoconfig" or return 0;
2489
2490 read_depends;
2491
2492 process_config_ignore $output_config;
2493
2494 undef %save_configs;
2495 undef %min_configs;
2496
2497 if (defined($ignore_config)) {
2498 # make sure the file exists
2499 `touch $ignore_config`;
2500 assign_configs \%save_configs, $ignore_config;
2501 }
2502
2503 %keep_configs = %save_configs;
2504
2505 doprint "Load initial configs from $start_minconfig\n";
2506
2507 # Look at the current min configs, and save off all the
2508 # ones that were set via the allnoconfig
2509 assign_configs \%min_configs, $start_minconfig;
2510
2511 my @config_keys = keys %min_configs;
2512
2513 # Remove anything that was set by the make allnoconfig
2514 # we shouldn't need them as they get set for us anyway.
2515 foreach my $config (@config_keys) {
2516 # Remove anything in the ignore_config
2517 if (defined($keep_configs{$config})) {
2518 my $file = $ignore_config;
2519 $file =~ s,.*/(.*?)$,$1,;
2520 doprint "$config set by $file ... ignored\n";
2521 delete $min_configs{$config};
2522 next;
2523 }
2524 # But make sure the settings are the same. If a min config
2525 # sets a selection, we do not want to get rid of it if
2526 # it is not the same as what we have. Just move it into
2527 # the keep configs.
2528 if (defined($config_ignore{$config})) {
2529 if ($config_ignore{$config} ne $min_configs{$config}) {
2530 doprint "$config is in allnoconfig as '$config_ignore{$config}'";
2531 doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
2532 $keep_configs{$config} = $min_configs{$config};
2533 } else {
2534 doprint "$config set by allnoconfig ... ignored\n";
2535 }
2536 delete $min_configs{$config};
2537 }
2538 }
2539
2540 my $done = 0;
2541 my $take_two = 0;
2542
2543 while (!$done) {
2544
2545 my $config;
2546 my $found;
2547
2548 # Now disable each config one by one and do a make oldconfig
2549 # till we find a config that changes our list.
2550
2551 # Put configs that did not modify the config at the end.
2552 my @test_configs = keys %min_configs;
2553 my $reset = 1;
2554 for (my $i = 0; $i < $#test_configs; $i++) {
2555 if (!defined($nochange_config{$test_configs[0]})) {
2556 $reset = 0;
2557 last;
2558 }
2559 # This config didn't change the .config last time.
2560 # Place it at the end
2561 my $config = shift @test_configs;
2562 push @test_configs, $config;
2563 }
2564
2565 # if every test config has failed to modify the .config file
2566 # in the past, then reset and start over.
2567 if ($reset) {
2568 undef %nochange_config;
2569 }
2570
2571 undef %processed_configs;
2572
2573 foreach my $config (@test_configs) {
2574
2575 $found = test_this_config $config;
2576
2577 last if (defined($found));
2578
2579 # oh well, try another config
2580 }
2581
2582 if (!defined($found)) {
2583 # we could have failed due to the nochange_config hash
2584 # reset and try again
2585 if (!$take_two) {
2586 undef %nochange_config;
2587 $take_two = 1;
2588 next;
2589 }
2590 doprint "No more configs found that we can disable\n";
2591 $done = 1;
2592 last;
2593 }
2594 $take_two = 0;
2595
2596 $config = $found;
2597
2598 doprint "Test with $config disabled\n";
2599
2600 # set in_bisect to keep build and monitor from dieing
2601 $in_bisect = 1;
2602
2603 my $failed = 0;
2604 build "oldconfig";
2605 start_monitor_and_boot or $failed = 1;
2606 end_monitor;
2607
2608 $in_bisect = 0;
2609
2610 if ($failed) {
2611 doprint "$min_configs{$config} is needed to boot the box... keeping\n";
2612 # this config is needed, add it to the ignore list.
2613 $keep_configs{$config} = $min_configs{$config};
2614 $save_configs{$config} = $min_configs{$config};
2615 delete $min_configs{$config};
2616
2617 # update new ignore configs
2618 if (defined($ignore_config)) {
2619 open (OUT, ">$temp_config")
2620 or die "Can't write to $temp_config";
2621 foreach my $config (keys %save_configs) {
2622 print OUT "$save_configs{$config}\n";
2623 }
2624 close OUT;
2625 run_command "mv $temp_config $ignore_config" or
2626 dodie "failed to copy update to $ignore_config";
2627 }
2628
2629 } else {
2630 # We booted without this config, remove it from the minconfigs.
2631 doprint "$config is not needed, disabling\n";
2632
2633 delete $min_configs{$config};
2634
2635 # Also disable anything that is not enabled in this config
2636 my %configs;
2637 assign_configs \%configs, $output_config;
2638 my @config_keys = keys %min_configs;
2639 foreach my $config (@config_keys) {
2640 if (!defined($configs{$config})) {
2641 doprint "$config is not set, disabling\n";
2642 delete $min_configs{$config};
2643 }
2644 }
2645
2646 # Save off all the current mandidory configs
2647 open (OUT, ">$temp_config")
2648 or die "Can't write to $temp_config";
2649 foreach my $config (keys %keep_configs) {
2650 print OUT "$keep_configs{$config}\n";
2651 }
2652 foreach my $config (keys %min_configs) {
2653 print OUT "$min_configs{$config}\n";
2654 }
2655 close OUT;
2656
2657 run_command "mv $temp_config $output_minconfig" or
2658 dodie "failed to copy update to $output_minconfig";
2659 }
2660
2661 doprint "Reboot and wait $sleep_time seconds\n";
2662 reboot;
2663 start_monitor;
2664 wait_for_monitor $sleep_time;
2665 end_monitor;
2666 }
2667
2668 success $i;
2669 return 1;
2670}
2671
1939$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; 2672$#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n";
1940 2673
1941if ($#ARGV == 0) { 2674if ($#ARGV == 0) {
1942 $ktest_config = $ARGV[0]; 2675 $ktest_config = $ARGV[0];
1943 if (! -f $ktest_config) { 2676 if (! -f $ktest_config) {
1944 print "$ktest_config does not exist.\n"; 2677 print "$ktest_config does not exist.\n";
1945 my $ans; 2678 if (!read_yn "Create it?") {
1946 for (;;) {
1947 print "Create it? [Y/n] ";
1948 $ans = <STDIN>;
1949 chomp $ans;
1950 if ($ans =~ /^\s*$/) {
1951 $ans = "y";
1952 }
1953 last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
1954 print "Please answer either 'y' or 'n'.\n";
1955 }
1956 if ($ans !~ /^y$/i) {
1957 exit 0; 2679 exit 0;
1958 } 2680 }
1959 } 2681 }
@@ -1977,6 +2699,10 @@ EOF
1977} 2699}
1978read_config $ktest_config; 2700read_config $ktest_config;
1979 2701
2702if (defined($opt{"LOG_FILE"})) {
2703 $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
2704}
2705
1980# Append any configs entered in manually to the config file. 2706# Append any configs entered in manually to the config file.
1981my @new_configs = keys %entered_configs; 2707my @new_configs = keys %entered_configs;
1982if ($#new_configs >= 0) { 2708if ($#new_configs >= 0) {
@@ -2045,70 +2771,13 @@ sub __set_test_option {
2045 return undef; 2771 return undef;
2046} 2772}
2047 2773
2048sub eval_option {
2049 my ($option, $i) = @_;
2050
2051 # Add space to evaluate the character before $
2052 $option = " $option";
2053 my $retval = "";
2054
2055 while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
2056 my $start = $1;
2057 my $var = $2;
2058 my $end = $3;
2059
2060 # Append beginning of line
2061 $retval = "$retval$start";
2062
2063 # If the iteration option OPT[$i] exists, then use that.
2064 # otherwise see if the default OPT (without [$i]) exists.
2065
2066 my $o = "$var\[$i\]";
2067
2068 if (defined($opt{$o})) {
2069 $o = $opt{$o};
2070 $retval = "$retval$o";
2071 } elsif (defined($opt{$var})) {
2072 $o = $opt{$var};
2073 $retval = "$retval$o";
2074 } else {
2075 $retval = "$retval\$\{$var\}";
2076 }
2077
2078 $option = $end;
2079 }
2080
2081 $retval = "$retval$option";
2082
2083 $retval =~ s/^ //;
2084
2085 return $retval;
2086}
2087
2088sub set_test_option { 2774sub set_test_option {
2089 my ($name, $i) = @_; 2775 my ($name, $i) = @_;
2090 2776
2091 my $option = __set_test_option($name, $i); 2777 my $option = __set_test_option($name, $i);
2092 return $option if (!defined($option)); 2778 return $option if (!defined($option));
2093 2779
2094 my $prev = ""; 2780 return eval_option($option, $i);
2095
2096 # Since an option can evaluate to another option,
2097 # keep iterating until we do not evaluate any more
2098 # options.
2099 my $r = 0;
2100 while ($prev ne $option) {
2101 # Check for recursive evaluations.
2102 # 100 deep should be more than enough.
2103 if ($r++ > 100) {
2104 die "Over 100 evaluations accurred with $name\n" .
2105 "Check for recursive variables\n";
2106 }
2107 $prev = $option;
2108 $option = eval_option($option, $i);
2109 }
2110
2111 return $option;
2112} 2781}
2113 2782
2114# First we need to do is the builds 2783# First we need to do is the builds
@@ -2126,10 +2795,17 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2126 $test_type = set_test_option("TEST_TYPE", $i); 2795 $test_type = set_test_option("TEST_TYPE", $i);
2127 $build_type = set_test_option("BUILD_TYPE", $i); 2796 $build_type = set_test_option("BUILD_TYPE", $i);
2128 $build_options = set_test_option("BUILD_OPTIONS", $i); 2797 $build_options = set_test_option("BUILD_OPTIONS", $i);
2798 $pre_build = set_test_option("PRE_BUILD", $i);
2799 $post_build = set_test_option("POST_BUILD", $i);
2800 $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
2801 $post_build_die = set_test_option("POST_BUILD_DIE", $i);
2129 $power_cycle = set_test_option("POWER_CYCLE", $i); 2802 $power_cycle = set_test_option("POWER_CYCLE", $i);
2130 $reboot = set_test_option("REBOOT", $i); 2803 $reboot = set_test_option("REBOOT", $i);
2131 $noclean = set_test_option("BUILD_NOCLEAN", $i); 2804 $noclean = set_test_option("BUILD_NOCLEAN", $i);
2132 $minconfig = set_test_option("MIN_CONFIG", $i); 2805 $minconfig = set_test_option("MIN_CONFIG", $i);
2806 $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i);
2807 $start_minconfig = set_test_option("START_MIN_CONFIG", $i);
2808 $ignore_config = set_test_option("IGNORE_CONFIG", $i);
2133 $run_test = set_test_option("TEST", $i); 2809 $run_test = set_test_option("TEST", $i);
2134 $addconfig = set_test_option("ADD_CONFIG", $i); 2810 $addconfig = set_test_option("ADD_CONFIG", $i);
2135 $reboot_type = set_test_option("REBOOT_TYPE", $i); 2811 $reboot_type = set_test_option("REBOOT_TYPE", $i);
@@ -2145,12 +2821,16 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2145 $sleep_time = set_test_option("SLEEP_TIME", $i); 2821 $sleep_time = set_test_option("SLEEP_TIME", $i);
2146 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); 2822 $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
2147 $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i); 2823 $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
2824 $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
2148 $bisect_manual = set_test_option("BISECT_MANUAL", $i); 2825 $bisect_manual = set_test_option("BISECT_MANUAL", $i);
2149 $bisect_skip = set_test_option("BISECT_SKIP", $i); 2826 $bisect_skip = set_test_option("BISECT_SKIP", $i);
2827 $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
2150 $store_failures = set_test_option("STORE_FAILURES", $i); 2828 $store_failures = set_test_option("STORE_FAILURES", $i);
2829 $test_name = set_test_option("TEST_NAME", $i);
2151 $timeout = set_test_option("TIMEOUT", $i); 2830 $timeout = set_test_option("TIMEOUT", $i);
2152 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); 2831 $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
2153 $console = set_test_option("CONSOLE", $i); 2832 $console = set_test_option("CONSOLE", $i);
2833 $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
2154 $success_line = set_test_option("SUCCESS_LINE", $i); 2834 $success_line = set_test_option("SUCCESS_LINE", $i);
2155 $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); 2835 $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
2156 $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); 2836 $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
@@ -2161,6 +2841,13 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2161 $target_image = set_test_option("TARGET_IMAGE", $i); 2841 $target_image = set_test_option("TARGET_IMAGE", $i);
2162 $localversion = set_test_option("LOCALVERSION", $i); 2842 $localversion = set_test_option("LOCALVERSION", $i);
2163 2843
2844 $start_minconfig_defined = 1;
2845
2846 if (!defined($start_minconfig)) {
2847 $start_minconfig_defined = 0;
2848 $start_minconfig = $minconfig;
2849 }
2850
2164 chdir $builddir || die "can't change directory to $builddir"; 2851 chdir $builddir || die "can't change directory to $builddir";
2165 2852
2166 if (!-d $tmpdir) { 2853 if (!-d $tmpdir) {
@@ -2193,6 +2880,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2193 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; 2880 $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
2194 } 2881 }
2195 2882
2883 if ($test_type eq "make_min_config") {
2884 $run_type = "";
2885 }
2886
2196 # mistake in config file? 2887 # mistake in config file?
2197 if (!defined($run_type)) { 2888 if (!defined($run_type)) {
2198 $run_type = "ERROR"; 2889 $run_type = "ERROR";
@@ -2204,11 +2895,12 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2204 unlink $dmesg; 2895 unlink $dmesg;
2205 unlink $buildlog; 2896 unlink $buildlog;
2206 2897
2207 if (!defined($minconfig)) { 2898 if (defined($addconfig)) {
2208 $minconfig = $addconfig; 2899 my $min = $minconfig;
2209 2900 if (!defined($minconfig)) {
2210 } elsif (defined($addconfig)) { 2901 $min = "";
2211 run_command "cat $addconfig $minconfig > $tmpdir/add_config" or 2902 }
2903 run_command "cat $addconfig $min > $tmpdir/add_config" or
2212 dodie "Failed to create temp config"; 2904 dodie "Failed to create temp config";
2213 $minconfig = "$tmpdir/add_config"; 2905 $minconfig = "$tmpdir/add_config";
2214 } 2906 }
@@ -2228,6 +2920,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2228 } elsif ($test_type eq "patchcheck") { 2920 } elsif ($test_type eq "patchcheck") {
2229 patchcheck $i; 2921 patchcheck $i;
2230 next; 2922 next;
2923 } elsif ($test_type eq "make_min_config") {
2924 make_min_config $i;
2925 next;
2231 } 2926 }
2232 2927
2233 if ($build_type ne "nobuild") { 2928 if ($build_type ne "nobuild") {
@@ -2235,13 +2930,8 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
2235 } 2930 }
2236 2931
2237 if ($test_type ne "build") { 2932 if ($test_type ne "build") {
2238 get_grub_index;
2239 get_version;
2240 install;
2241
2242 my $failed = 0; 2933 my $failed = 0;
2243 start_monitor; 2934 start_monitor_and_boot or $failed = 1;
2244 monitor or $failed = 1;;
2245 2935
2246 if (!$failed && $test_type ne "boot" && defined($run_test)) { 2936 if (!$failed && $test_type ne "boot" && defined($run_test)) {
2247 do_run_test or $failed = 1; 2937 do_run_test or $failed = 1;
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf
index 48cbcc80602..b8bcd14b5a4 100644
--- a/tools/testing/ktest/sample.conf
+++ b/tools/testing/ktest/sample.conf
@@ -293,6 +293,38 @@
293# or on some systems: 293# or on some systems:
294#POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION 294#POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION
295 295
296# If there is a script that you require to run before the build is done
297# you can specify it with PRE_BUILD.
298#
299# One example may be if you must add a temporary patch to the build to
300# fix a unrelated bug to perform a patchcheck test. This will apply the
301# patch before each build that is made. Use the POST_BUILD to do a git reset --hard
302# to remove the patch.
303#
304# (default undef)
305#PRE_BUILD = cd ${BUILD_DIR} && patch -p1 < /tmp/temp.patch
306
307# To specify if the test should fail if the PRE_BUILD fails,
308# PRE_BUILD_DIE needs to be set to 1. Otherwise the PRE_BUILD
309# result is ignored.
310# (default 0)
311# PRE_BUILD_DIE = 1
312
313# If there is a script that should run after the build is done
314# you can specify it with POST_BUILD.
315#
316# As the example in PRE_BUILD, POST_BUILD can be used to reset modifications
317# made by the PRE_BUILD.
318#
319# (default undef)
320#POST_BUILD = cd ${BUILD_DIR} && git reset --hard
321
322# To specify if the test should fail if the POST_BUILD fails,
323# POST_BUILD_DIE needs to be set to 1. Otherwise the POST_BUILD
324# result is ignored.
325# (default 0)
326#POST_BUILD_DIE = 1
327
296# Way to reboot the box to the test kernel. 328# Way to reboot the box to the test kernel.
297# Only valid options so far are "grub" and "script" 329# Only valid options so far are "grub" and "script"
298# (default grub) 330# (default grub)
@@ -360,8 +392,8 @@
360#ADD_CONFIG = /home/test/config-broken 392#ADD_CONFIG = /home/test/config-broken
361 393
362# The location on the host where to write temp files 394# The location on the host where to write temp files
363# (default /tmp/ktest) 395# (default /tmp/ktest/${MACHINE})
364#TMP_DIR = /tmp/ktest 396#TMP_DIR = /tmp/ktest/${MACHINE}
365 397
366# Optional log file to write the status (recommended) 398# Optional log file to write the status (recommended)
367# Note, this is a DEFAULT section only option. 399# Note, this is a DEFAULT section only option.
@@ -518,6 +550,16 @@
518# The variables SSH_USER and MACHINE are defined. 550# The variables SSH_USER and MACHINE are defined.
519#REBOOT = ssh $SSH_USER@$MACHINE reboot 551#REBOOT = ssh $SSH_USER@$MACHINE reboot
520 552
553# The way triple faults are detected is by testing the kernel
554# banner. If the kernel banner for the kernel we are testing is
555# found, and then later a kernel banner for another kernel version
556# is found, it is considered that we encountered a triple fault,
557# and there is no panic or callback, but simply a reboot.
558# To disable this (because it did a false positive) set the following
559# to 0.
560# (default 1)
561#DETECT_TRIPLE_FAULT = 0
562
521#### Per test run options #### 563#### Per test run options ####
522# The following options are only allowed in TEST_START sections. 564# The following options are only allowed in TEST_START sections.
523# They are ignored in the DEFAULTS sections. 565# They are ignored in the DEFAULTS sections.
@@ -535,6 +577,12 @@
535# all preceding tests until a new CHECKOUT is set. 577# all preceding tests until a new CHECKOUT is set.
536# 578#
537# 579#
580# TEST_NAME = name
581#
582# If you want the test to have a name that is displayed in
583# the test result banner at the end of the test, then use this
584# option. This is useful to search for the RESULT keyword and
585# not have to translate a test number to a test in the config.
538# 586#
539# For TEST_TYPE = patchcheck 587# For TEST_TYPE = patchcheck
540# 588#
@@ -556,7 +604,12 @@
556# build, boot, test. 604# build, boot, test.
557# 605#
558# Note, the build test will look for warnings, if a warning occurred 606# Note, the build test will look for warnings, if a warning occurred
559# in a file that a commit touches, the build will fail. 607# in a file that a commit touches, the build will fail, unless
608# IGNORE_WARNINGS is set for the given commit's sha1
609#
610# IGNORE_WARNINGS can be used to disable the failure of patchcheck
611# on a particuler commit (SHA1). You can add more than one commit
612# by adding a list of SHA1s that are space delimited.
560# 613#
561# If BUILD_NOCLEAN is set, then make mrproper will not be run on 614# If BUILD_NOCLEAN is set, then make mrproper will not be run on
562# any of the builds, just like all other TEST_TYPE tests. But 615# any of the builds, just like all other TEST_TYPE tests. But
@@ -571,6 +624,7 @@
571# PATCHCHECK_TYPE = boot 624# PATCHCHECK_TYPE = boot
572# PATCHCHECK_START = 747e94ae3d1b4c9bf5380e569f614eb9040b79e7 625# PATCHCHECK_START = 747e94ae3d1b4c9bf5380e569f614eb9040b79e7
573# PATCHCHECK_END = HEAD~2 626# PATCHCHECK_END = HEAD~2
627# IGNORE_WARNINGS = 42f9c6b69b54946ffc0515f57d01dc7f5c0e4712 0c17ca2c7187f431d8ffc79e81addc730f33d128
574# 628#
575# 629#
576# 630#
@@ -739,13 +793,18 @@
739# boot - bad builds but fails to boot 793# boot - bad builds but fails to boot
740# test - bad boots but fails a test 794# test - bad boots but fails a test
741# 795#
742# CONFIG_BISECT is the config that failed to boot 796# CONFIG_BISECT is the config that failed to boot
743# 797#
744# If BISECT_MANUAL is set, it will pause between iterations. 798# If BISECT_MANUAL is set, it will pause between iterations.
745# This is useful to use just ktest.pl just for the config bisect. 799# This is useful to use just ktest.pl just for the config bisect.
746# If you set it to build, it will run the bisect and you can 800# If you set it to build, it will run the bisect and you can
747# control what happens in between iterations. It will ask you if 801# control what happens in between iterations. It will ask you if
748# the test succeeded or not and continue the config bisect. 802# the test succeeded or not and continue the config bisect.
803#
804# CONFIG_BISECT_GOOD (optional)
805# If you have a good config to start with, then you
806# can specify it with CONFIG_BISECT_GOOD. Otherwise
807# the MIN_CONFIG is the base.
749# 808#
750# Example: 809# Example:
751# TEST_START 810# TEST_START
@@ -755,3 +814,68 @@
755# MIN_CONFIG = /home/test/config-min 814# MIN_CONFIG = /home/test/config-min
756# BISECT_MANUAL = 1 815# BISECT_MANUAL = 1
757# 816#
817#
818#
819# For TEST_TYPE = make_min_config
820#
821# After doing a make localyesconfig, your kernel configuration may
822# not be the most useful minimum configuration. Having a true minimum
823# config that you can use against other configs is very useful if
824# someone else has a config that breaks on your code. By only forcing
825# those configurations that are truly required to boot your machine
826# will give you less of a chance that one of your set configurations
827# will make the bug go away. This will give you a better chance to
828# be able to reproduce the reported bug matching the broken config.
829#
830# Note, this does take some time, and may require you to run the
831# test over night, or perhaps over the weekend. But it also allows
832# you to interrupt it, and gives you the current minimum config
833# that was found till that time.
834#
835# Note, this test automatically assumes a BUILD_TYPE of oldconfig
836# and its test type acts like boot.
837# TODO: add a test version that makes the config do more than just
838# boot, like having network access.
839#
840# To save time, the test does not just grab any option and test
841# it. The Kconfig files are examined to determine the dependencies
842# of the configs. If a config is chosen that depends on another
843# config, that config will be checked first. By checking the
844# parents first, we can eliminate whole groups of configs that
845# may have been enabled.
846#
847# For example, if a USB device config is chosen and depends on CONFIG_USB,
848# the CONFIG_USB will be tested before the device. If CONFIG_USB is
849# found not to be needed, it, as well as all configs that depend on
850# it, will be disabled and removed from the current min_config.
851#
852# OUTPUT_MIN_CONFIG is the path and filename of the file that will
853# be created from the MIN_CONFIG. If you interrupt the test, set
854# this file as your new min config, and use it to continue the test.
855# This file does not need to exist on start of test.
856# This file is not created until a config is found that can be removed.
857# If this file exists, you will be prompted if you want to use it
858# as the min_config (overriding MIN_CONFIG) if START_MIN_CONFIG
859# is not defined.
860# (required field)
861#
862# START_MIN_CONFIG is the config to use to start the test with.
863# you can set this as the same OUTPUT_MIN_CONFIG, but if you do
864# the OUTPUT_MIN_CONFIG file must exist.
865# (default MIN_CONFIG)
866#
867# IGNORE_CONFIG is used to specify a config file that has configs that
868# you already know must be set. Configs are written here that have
869# been tested and proved to be required. It is best to define this
870# file if you intend on interrupting the test and running it where
871# it left off. New configs that it finds will be written to this file
872# and will not be tested again in later runs.
873# (optional)
874#
875# Example:
876#
877# TEST_TYPE = make_min_config
878# OUTPUT_MIN_CONFIG = /path/to/config-new-min
879# START_MIN_CONFIG = /path/to/config-min
880# IGNORE_CONFIG = /path/to/config-tested
881#
diff --git a/tools/testing/selftests/mqueue/.gitignore b/tools/testing/selftests/mqueue/.gitignore
new file mode 100644
index 00000000000..d8d42377205
--- /dev/null
+++ b/tools/testing/selftests/mqueue/.gitignore
@@ -0,0 +1,2 @@
1mq_open_tests
2mq_perf_tests
diff --git a/tools/virtio/linux/hrtimer.h b/tools/virtio/linux/hrtimer.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tools/virtio/linux/hrtimer.h
diff --git a/tools/virtio/linux/module.h b/tools/virtio/linux/module.h
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tools/virtio/linux/module.h