diff options
Diffstat (limited to 'tools')
117 files changed, 17364 insertions, 1413 deletions
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index 6f5a498608b2..85c5f026930d 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 | |||
| 69 | SEE ALSO | 75 | SEE ALSO |
| 70 | -------- | 76 | -------- |
| 71 | linkperf:perf-record[1], linkperf:perf-report[1] | 77 | linkperf:perf-record[1], linkperf:perf-report[1] |
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 02bafce4b341..2780d9ce48bf 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 8ba03d6e5398..04253c07d19a 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 | |||
| 122 | SEE ALSO | 137 | SEE ALSO |
| 123 | -------- | 138 | -------- |
| 124 | linkperf:perf-stat[1] | 139 | linkperf:perf-stat[1] |
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 86c87e214b11..db017867d9e8 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 | |||
| 185 | SEE ALSO | 191 | SEE ALSO |
| 186 | -------- | 192 | -------- |
| 187 | linkperf:perf-record[1], linkperf:perf-script-perl[1], | 193 | linkperf:perf-record[1], linkperf:perf-script-perl[1], |
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 940257b5774e..3b8f7b80376b 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
| @@ -52,7 +52,10 @@ ifeq ($(ARCH),i386) | |||
| 52 | endif | 52 | endif |
| 53 | ifeq ($(ARCH),x86_64) | 53 | ifeq ($(ARCH),x86_64) |
| 54 | ARCH := x86 | 54 | ARCH := x86 |
| 55 | IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) | 55 | IS_X86_64 := 0 |
| 56 | ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) | ||
| 57 | IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) | ||
| 58 | endif | ||
| 56 | ifeq (${IS_X86_64}, 1) | 59 | ifeq (${IS_X86_64}, 1) |
| 57 | RAW_ARCH := x86_64 | 60 | RAW_ARCH := x86_64 |
| 58 | ARCH_CFLAGS := -DARCH_X86_64 | 61 | ARCH_CFLAGS := -DARCH_X86_64 |
| @@ -178,9 +181,9 @@ strip-libs = $(filter-out -l%,$(1)) | |||
| 178 | 181 | ||
| 179 | $(OUTPUT)python/perf.so: $(PYRF_OBJS) | 182 | $(OUTPUT)python/perf.so: $(PYRF_OBJS) |
| 180 | $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ | 183 | $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ |
| 181 | --quiet build_ext \ | 184 | --quiet build_ext; \ |
| 182 | --build-lib='$(OUTPUT)python' \ | 185 | mkdir -p $(OUTPUT)python && \ |
| 183 | --build-temp='$(OUTPUT)python/temp' | 186 | cp $(PYTHON_EXTBUILD_LIB)perf.so $(OUTPUT)python/ |
| 184 | # | 187 | # |
| 185 | # No Perl scripts right now: | 188 | # No Perl scripts right now: |
| 186 | # | 189 | # |
| @@ -279,6 +282,7 @@ LIB_H += util/thread.h | |||
| 279 | LIB_H += util/thread_map.h | 282 | LIB_H += util/thread_map.h |
| 280 | LIB_H += util/trace-event.h | 283 | LIB_H += util/trace-event.h |
| 281 | LIB_H += util/probe-finder.h | 284 | LIB_H += util/probe-finder.h |
| 285 | LIB_H += util/dwarf-aux.h | ||
| 282 | LIB_H += util/probe-event.h | 286 | LIB_H += util/probe-event.h |
| 283 | LIB_H += util/pstack.h | 287 | LIB_H += util/pstack.h |
| 284 | LIB_H += util/cpumap.h | 288 | LIB_H += util/cpumap.h |
| @@ -435,6 +439,7 @@ else | |||
| 435 | BASIC_CFLAGS += -DDWARF_SUPPORT | 439 | BASIC_CFLAGS += -DDWARF_SUPPORT |
| 436 | EXTLIBS += -lelf -ldw | 440 | EXTLIBS += -lelf -ldw |
| 437 | LIB_OBJS += $(OUTPUT)util/probe-finder.o | 441 | LIB_OBJS += $(OUTPUT)util/probe-finder.o |
| 442 | LIB_OBJS += $(OUTPUT)util/dwarf-aux.o | ||
| 438 | endif # PERF_HAVE_DWARF_REGS | 443 | endif # PERF_HAVE_DWARF_REGS |
| 439 | endif # NO_DWARF | 444 | endif # NO_DWARF |
| 440 | 445 | ||
| @@ -504,9 +509,13 @@ else | |||
| 504 | 509 | ||
| 505 | PYTHON_WORD := $(call shell-wordify,$(PYTHON)) | 510 | PYTHON_WORD := $(call shell-wordify,$(PYTHON)) |
| 506 | 511 | ||
| 507 | python-clean := $(PYTHON_WORD) util/setup.py clean \ | 512 | # python extension build directories |
| 508 | --build-lib='$(OUTPUT)python' \ | 513 | PYTHON_EXTBUILD := $(OUTPUT)python_ext_build/ |
| 509 | --build-temp='$(OUTPUT)python/temp' | 514 | PYTHON_EXTBUILD_LIB := $(PYTHON_EXTBUILD)lib/ |
| 515 | PYTHON_EXTBUILD_TMP := $(PYTHON_EXTBUILD)tmp/ | ||
| 516 | export PYTHON_EXTBUILD_LIB PYTHON_EXTBUILD_TMP | ||
| 517 | |||
| 518 | python-clean := rm -rf $(PYTHON_EXTBUILD) $(OUTPUT)python/perf.so | ||
| 510 | 519 | ||
| 511 | ifdef NO_LIBPYTHON | 520 | ifdef NO_LIBPYTHON |
| 512 | $(call disable-python) | 521 | $(call disable-python) |
| @@ -863,6 +872,9 @@ install: all | |||
| 863 | $(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python' | 872 | $(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' | 873 | $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' |
| 865 | 874 | ||
| 875 | install-python_ext: | ||
| 876 | $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' | ||
| 877 | |||
| 866 | install-doc: | 878 | install-doc: |
| 867 | $(MAKE) -C Documentation install | 879 | $(MAKE) -C Documentation install |
| 868 | 880 | ||
| @@ -890,7 +902,7 @@ quick-install-html: | |||
| 890 | ### Cleaning rules | 902 | ### Cleaning rules |
| 891 | 903 | ||
| 892 | clean: | 904 | clean: |
| 893 | $(RM) $(OUTPUT){*.o,*/*.o,*/*/*.o,*/*/*/*.o,$(LIB_FILE),perf-archive} | 905 | $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) |
| 894 | $(RM) $(ALL_PROGRAMS) perf | 906 | $(RM) $(ALL_PROGRAMS) perf |
| 895 | $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* | 907 | $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* |
| 896 | $(MAKE) -C Documentation/ clean | 908 | $(MAKE) -C Documentation/ clean |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 7b139e1e7e86..555aefd7fe01 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 | |||
| 31 | static char const *input_name = "perf.data"; | 33 | static char const *input_name = "perf.data"; |
| 32 | 34 | ||
| 33 | static bool force, use_tui, use_stdio; | 35 | static bool force, use_tui, use_stdio; |
| @@ -38,6 +40,9 @@ static bool print_line; | |||
| 38 | 40 | ||
| 39 | static const char *sym_hist_filter; | 41 | static const char *sym_hist_filter; |
| 40 | 42 | ||
| 43 | static const char *cpu_list; | ||
| 44 | static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | ||
| 45 | |||
| 41 | static int perf_evlist__add_sample(struct perf_evlist *evlist, | 46 | static 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 9ac05aafd9b2..899080ace267 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 | ||
| 951 | static int __cmd_record(int argc, const char **argv) | 951 | static int __cmd_record(int argc, const char **argv) |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 2c0e64d0b4aa..710ae3d0a489 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, ¶ms.line_range); | 138 | return 0; |
| 139 | INIT_LIST_HEAD(¶ms.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, ¶ms.line_range); | ||
| 148 | INIT_LIST_HEAD(¶ms.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", ¶ms.target_module, | 252 | OPT_STRING('m', "module", ¶ms.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", ¶ms.max_probe_points, | 257 | OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8e2c85798185..6b0519f885e4 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 | |||
| 35 | enum write_mode_t { | 33 | enum write_mode_t { |
| 36 | WRITE_FORCE, | 34 | WRITE_FORCE, |
| 37 | WRITE_APPEND | 35 | WRITE_APPEND |
| @@ -47,7 +45,7 @@ static int freq = 1000; | |||
| 47 | static int output; | 45 | static int output; |
| 48 | static int pipe_output = 0; | 46 | static int pipe_output = 0; |
| 49 | static const char *output_name = NULL; | 47 | static const char *output_name = NULL; |
| 50 | static int group = 0; | 48 | static bool group = false; |
| 51 | static int realtime_prio = 0; | 49 | static int realtime_prio = 0; |
| 52 | static bool nodelay = false; | 50 | static bool nodelay = false; |
| 53 | static bool raw_samples = false; | 51 | static bool raw_samples = false; |
| @@ -438,7 +436,6 @@ static void mmap_read_all(void) | |||
| 438 | 436 | ||
| 439 | static int __cmd_record(int argc, const char **argv) | 437 | static int __cmd_record(int argc, const char **argv) |
| 440 | { | 438 | { |
| 441 | int i; | ||
| 442 | struct stat st; | 439 | struct stat st; |
| 443 | int flags; | 440 | int flags; |
| 444 | int err; | 441 | int err; |
| @@ -682,7 +679,6 @@ static int __cmd_record(int argc, const char **argv) | |||
| 682 | 679 | ||
| 683 | for (;;) { | 680 | for (;;) { |
| 684 | int hits = samples; | 681 | int hits = samples; |
| 685 | int thread; | ||
| 686 | 682 | ||
| 687 | mmap_read_all(); | 683 | mmap_read_all(); |
| 688 | 684 | ||
| @@ -693,19 +689,8 @@ static int __cmd_record(int argc, const char **argv) | |||
| 693 | waking++; | 689 | waking++; |
| 694 | } | 690 | } |
| 695 | 691 | ||
| 696 | if (done) { | 692 | if (done) |
| 697 | for (i = 0; i < evsel_list->cpus->nr; i++) { | 693 | 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 | } | 694 | } |
| 710 | 695 | ||
| 711 | if (quiet || signr == SIGUSR1) | 696 | if (quiet || signr == SIGUSR1) |
| @@ -740,7 +725,7 @@ static bool force, append_file; | |||
| 740 | const struct option record_options[] = { | 725 | const struct option record_options[] = { |
| 741 | OPT_CALLBACK('e', "event", &evsel_list, "event", | 726 | OPT_CALLBACK('e', "event", &evsel_list, "event", |
| 742 | "event selector. use 'perf list' to list available events", | 727 | "event selector. use 'perf list' to list available events", |
| 743 | parse_events), | 728 | parse_events_option), |
| 744 | OPT_CALLBACK(0, "filter", &evsel_list, "filter", | 729 | OPT_CALLBACK(0, "filter", &evsel_list, "filter", |
| 745 | "event filter", parse_filter), | 730 | "event filter", parse_filter), |
| 746 | OPT_INTEGER('p', "pid", &target_pid, | 731 | OPT_INTEGER('p', "pid", &target_pid, |
| @@ -768,6 +753,8 @@ const struct option record_options[] = { | |||
| 768 | "child tasks do not inherit counters"), | 753 | "child tasks do not inherit counters"), |
| 769 | OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), | 754 | OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), |
| 770 | OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), | 755 | OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), |
| 756 | OPT_BOOLEAN(0, "group", &group, | ||
| 757 | "put the counters into a counter group"), | ||
| 771 | OPT_BOOLEAN('g', "call-graph", &call_graph, | 758 | OPT_BOOLEAN('g', "call-graph", &call_graph, |
| 772 | "do call-graph (stack chain/backtrace) recording"), | 759 | "do call-graph (stack chain/backtrace) recording"), |
| 773 | OPT_INCR('v', "verbose", &verbose, | 760 | OPT_INCR('v', "verbose", &verbose, |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 287a173523a7..d7ff277bdb78 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 | |||
| 36 | static char const *input_name = "perf.data"; | 38 | static char const *input_name = "perf.data"; |
| 37 | 39 | ||
| 38 | static bool force, use_tui, use_stdio; | 40 | static bool force, use_tui, use_stdio; |
| @@ -45,9 +47,13 @@ static struct perf_read_values show_threads_values; | |||
| 45 | static const char default_pretty_printing_style[] = "normal"; | 47 | static const char default_pretty_printing_style[] = "normal"; |
| 46 | static const char *pretty_printing_style = default_pretty_printing_style; | 48 | static const char *pretty_printing_style = default_pretty_printing_style; |
| 47 | 49 | ||
| 48 | static char callchain_default_opt[] = "fractal,0.5"; | 50 | static char callchain_default_opt[] = "fractal,0.5,callee"; |
| 51 | static bool inverted_callchain; | ||
| 49 | static symbol_filter_t annotate_init; | 52 | static symbol_filter_t annotate_init; |
| 50 | 53 | ||
| 54 | static const char *cpu_list; | ||
| 55 | static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | ||
| 56 | |||
| 51 | static int perf_session__add_hist_entry(struct perf_session *session, | 57 | static 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; | ||
| 396 | setup: | 426 | setup: |
| 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 dcfe8873c9a1..5177964943e7 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 | ||
| 1640 | static int read_events(void) | 1640 | static 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 | ||
| 1659 | static void print_bad_events(void) | 1665 | static void print_bad_events(void) |
| @@ -1689,9 +1695,10 @@ static void print_bad_events(void) | |||
| 1689 | static void __cmd_lat(void) | 1695 | static 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 | ||
| 1722 | static struct trace_sched_handler map_ops = { | 1730 | static 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 | ||
| 1771 | static const char * const sched_usage[] = { | 1779 | static 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 22747de7234b..09024ec2ab2e 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 | ||
| 17 | static char const *script_name; | 18 | static char const *script_name; |
| 18 | static char const *generate_script_lang; | 19 | static char const *generate_script_lang; |
| @@ -21,6 +22,8 @@ static u64 last_timestamp; | |||
| 21 | static u64 nr_unordered; | 22 | static u64 nr_unordered; |
| 22 | extern const struct option record_options[]; | 23 | extern const struct option record_options[]; |
| 23 | static bool no_callchain; | 24 | static bool no_callchain; |
| 25 | static const char *cpu_list; | ||
| 26 | static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); | ||
| 24 | 27 | ||
| 25 | enum perf_output_field { | 28 | enum 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 | ||
| 36 | struct output_option { | 42 | struct 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 | ||
| 304 | static 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 | |||
| 315 | static 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 | |||
| 274 | static void process_event(union perf_event *event __unused, | 361 | static 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 a9f06715e44d..5deb17d9e795 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 | ||
| 65 | static struct perf_event_attr default_attrs[] = { | 67 | static struct perf_event_attr default_attrs[] = { |
| 66 | 68 | ||
| @@ -191,6 +193,7 @@ static int big_num_opt = -1; | |||
| 191 | static const char *cpu_list; | 193 | static const char *cpu_list; |
| 192 | static const char *csv_sep = NULL; | 194 | static const char *csv_sep = NULL; |
| 193 | static bool csv_output = false; | 195 | static bool csv_output = false; |
| 196 | static bool group = false; | ||
| 194 | 197 | ||
| 195 | static volatile int done = 0; | 198 | static 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 | ||
| 519 | static void print_noise(struct perf_evsel *evsel, double avg) | 527 | static 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, | |||
| 1024 | static const struct option options[] = { | 1033 | static 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 2da9162262b0..55f4c76f2821 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 | ||
| 16 | static long page_size; | 17 | static 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); |
| @@ -600,6 +601,246 @@ out_free_threads: | |||
| 600 | #undef nsyscalls | 601 | #undef nsyscalls |
| 601 | } | 602 | } |
| 602 | 603 | ||
| 604 | #define TEST_ASSERT_VAL(text, cond) \ | ||
| 605 | do { \ | ||
| 606 | if (!cond) { \ | ||
| 607 | pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ | ||
| 608 | return -1; \ | ||
| 609 | } \ | ||
| 610 | } while (0) | ||
| 611 | |||
| 612 | static 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 | |||
| 626 | static 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 | |||
| 644 | static 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 | |||
| 655 | static 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 | |||
| 666 | static 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 | |||
| 678 | static 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 | |||
| 690 | static 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 | |||
| 701 | static 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 | |||
| 716 | static 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 | |||
| 730 | static 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 | |||
| 746 | static 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 | |||
| 762 | static 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 | |||
| 815 | static 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 | } | ||
| 603 | static struct test { | 844 | static 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 f2f3f4937aa2..a43433f08300 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
| @@ -990,7 +990,7 @@ static const char * const top_usage[] = { | |||
| 990 | static const struct option options[] = { | 990 | static const struct option options[] = { |
| 991 | OPT_CALLBACK('e', "event", &top.evlist, "event", | 991 | OPT_CALLBACK('e', "event", &top.evlist, "event", |
| 992 | "event selector. use 'perf list' to list available events", | 992 | "event selector. use 'perf list' to list available events", |
| 993 | parse_events), | 993 | parse_events_option), |
| 994 | OPT_INTEGER('c', "count", &default_interval, | 994 | OPT_INTEGER('c', "count", &default_interval, |
| 995 | "event period to sample"), | 995 | "event period to sample"), |
| 996 | OPT_INTEGER('p', "pid", &top.target_pid, | 996 | OPT_INTEGER('p', "pid", &top.target_pid, |
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 1a79df9f739f..9b4ff16cac96 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 | ||
| 17 | enum chain_order { | ||
| 18 | ORDER_CALLER, | ||
| 19 | ORDER_CALLEE | ||
| 20 | }; | ||
| 21 | |||
| 17 | struct callchain_node { | 22 | struct 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 | ||
| 46 | struct callchain_list { | 52 | struct callchain_list { |
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index e02d78cae70f..fe02903f7d0f 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c | |||
| @@ -399,7 +399,6 @@ static int perf_config_global(void) | |||
| 399 | int perf_config(config_fn_t fn, void *data) | 399 | int 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; |
| 438 | out_free: | ||
| 439 | free(user_config); | ||
| 428 | } | 440 | } |
| 429 | free(repo_config); | 441 | out: |
| 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 000000000000..ee51e9b4dc09 --- /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 | */ | ||
| 32 | const 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 | */ | ||
| 64 | const 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 | */ | ||
| 81 | int 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 | |||
| 99 | static 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 | */ | ||
| 111 | int 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 | */ | ||
| 139 | bool 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 | */ | ||
| 153 | int 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 | */ | ||
| 173 | Dwarf_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 */ | ||
| 185 | static 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 | */ | ||
| 212 | Dwarf_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 */ | ||
| 222 | static 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 */ | ||
| 235 | static 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 | */ | ||
| 254 | bool 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 | */ | ||
| 273 | int 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 */ | ||
| 300 | static 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 */ | ||
| 311 | static 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 | */ | ||
| 328 | const 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 | */ | ||
| 358 | Dwarf_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 | |||
| 385 | struct __addr_die_search_param { | ||
| 386 | Dwarf_Addr addr; | ||
| 387 | Dwarf_Die *die_mem; | ||
| 388 | }; | ||
| 389 | |||
| 390 | /* die_find callback for non-inlined function search */ | ||
| 391 | static 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 | */ | ||
| 412 | Dwarf_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 */ | ||
| 426 | static 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 | */ | ||
| 448 | Dwarf_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 | |||
| 467 | struct __instance_walk_param { | ||
| 468 | void *addr; | ||
| 469 | int (*callback)(Dwarf_Die *, void *); | ||
| 470 | void *data; | ||
| 471 | int retval; | ||
| 472 | }; | ||
| 473 | |||
| 474 | static 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 | */ | ||
| 516 | int 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 */ | ||
| 537 | struct __line_walk_param { | ||
| 538 | bool recursive; | ||
| 539 | line_walk_callback_t callback; | ||
| 540 | void *data; | ||
| 541 | int retval; | ||
| 542 | }; | ||
| 543 | |||
| 544 | static 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 */ | ||
| 578 | static 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); | ||
| 601 | done: | ||
| 602 | return lw.retval; | ||
| 603 | } | ||
| 604 | |||
| 605 | static 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 | */ | ||
| 628 | int 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, ¶m, 0); | ||
| 700 | ret = param.retval; | ||
| 701 | } | ||
| 702 | |||
| 703 | return ret; | ||
| 704 | } | ||
| 705 | |||
| 706 | struct __find_variable_param { | ||
| 707 | const char *name; | ||
| 708 | Dwarf_Addr addr; | ||
| 709 | }; | ||
| 710 | |||
| 711 | static 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 | */ | ||
| 737 | Dwarf_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 | |||
| 746 | static 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 | */ | ||
| 765 | Dwarf_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 | */ | ||
| 784 | int 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 | */ | ||
| 827 | int 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 000000000000..6ce1717784b7 --- /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 */ | ||
| 28 | extern 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) */ | ||
| 31 | extern const char *cu_get_comp_dir(Dwarf_Die *cu_die); | ||
| 32 | |||
| 33 | /* Get a line number and file name for given address */ | ||
| 34 | extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr, | ||
| 35 | const char **fname, int *lineno); | ||
| 36 | |||
| 37 | /* Walk on funcitons at given address */ | ||
| 38 | extern 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 */ | ||
| 42 | extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname); | ||
| 43 | |||
| 44 | /* Get callsite line number of inline-function instance */ | ||
| 45 | extern int die_get_call_lineno(Dwarf_Die *in_die); | ||
| 46 | |||
| 47 | /* Get callsite file name of inlined function instance */ | ||
| 48 | extern const char *die_get_call_file(Dwarf_Die *in_die); | ||
| 49 | |||
| 50 | /* Get type die */ | ||
| 51 | extern Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem); | ||
| 52 | |||
| 53 | /* Get a type die, but skip qualifiers and typedef */ | ||
| 54 | extern Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem); | ||
| 55 | |||
| 56 | /* Check whether the DIE is signed or not */ | ||
| 57 | extern bool die_is_signed_type(Dwarf_Die *tp_die); | ||
| 58 | |||
| 59 | /* Get data_member_location offset */ | ||
| 60 | extern int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs); | ||
| 61 | |||
| 62 | /* Return values for die_find_child() callbacks */ | ||
| 63 | enum { | ||
| 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 */ | ||
| 71 | extern 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 */ | ||
| 76 | extern 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 */ | ||
| 80 | extern 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 */ | ||
| 84 | extern 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) */ | ||
| 88 | typedef 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 | */ | ||
| 95 | extern 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 */ | ||
| 99 | extern 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' */ | ||
| 103 | extern 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 */ | ||
| 107 | extern 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" */ | ||
| 110 | extern int die_get_varname(Dwarf_Die *vr_die, char *buf, int len); | ||
| 111 | #endif | ||
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index b021ea9265c3..c12bd476c6f7 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
| @@ -85,10 +85,32 @@ 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; |
| 97 | error_free: | ||
| 98 | perf_evsel__delete(evsel); | ||
| 99 | error: | ||
| 100 | return -ENOMEM; | ||
| 101 | } | ||
| 102 | |||
| 103 | void 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 | } | ||
| 92 | } | 114 | } |
| 93 | 115 | ||
| 94 | int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) | 116 | int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) |
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index b2b862374f37..ce85ae9ae57a 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
| @@ -53,6 +53,8 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist); | |||
| 53 | int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite); | 53 | int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite); |
| 54 | void perf_evlist__munmap(struct perf_evlist *evlist); | 54 | void perf_evlist__munmap(struct perf_evlist *evlist); |
| 55 | 55 | ||
| 56 | void perf_evlist__disable(struct perf_evlist *evlist); | ||
| 57 | |||
| 56 | static inline void perf_evlist__set_maps(struct perf_evlist *evlist, | 58 | static inline void perf_evlist__set_maps(struct perf_evlist *evlist, |
| 57 | struct cpu_map *cpus, | 59 | struct cpu_map *cpus, |
| 58 | struct thread_map *threads) | 60 | struct thread_map *threads) |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 0239eb87b232..a03a36b7908a 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -377,6 +377,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, | |||
| 377 | array++; | 377 | array++; |
| 378 | } | 378 | } |
| 379 | 379 | ||
| 380 | data->addr = 0; | ||
| 380 | if (type & PERF_SAMPLE_ADDR) { | 381 | if (type & PERF_SAMPLE_ADDR) { |
| 381 | data->addr = *array; | 382 | data->addr = *array; |
| 382 | array++; | 383 | array++; |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 7e9366e4490b..e9a31554e265 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 | ||
| 66 | struct cpu_map; | 67 | struct cpu_map; |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index afb0849fe530..b6c1ad123ca9 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, | |||
| 254 | int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir) | 254 | int 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 627a02e03c57..677e1da6bb3e 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
| @@ -14,7 +14,8 @@ enum hist_filter { | |||
| 14 | 14 | ||
| 15 | struct callchain_param callchain_param = { | 15 | struct 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 | ||
| 20 | u16 hists__col_len(struct hists *self, enum hist_column col) | 21 | u16 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 791f9dd27ebf..547628e97f3d 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 41982c373faf..928918b796b2 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 | ||
| 89 | static const char *hw_cache[][MAX_ALIASES] = { | 89 | static 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 | ||
| 98 | static const char *hw_cache_op[][MAX_ALIASES] = { | 99 | static 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 | ||
| 104 | static const char *hw_cache_result[][MAX_ALIASES] = { | 105 | static 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) |
| 477 | static enum event_result | 480 | static enum event_result |
| 478 | parse_multiple_tracepoint_event(const struct option *opt, char *sys_name, | 481 | parse_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 | ||
| 519 | static enum event_result | 522 | static enum event_result |
| 520 | parse_tracepoint_event(const struct option *opt, const char **strp, | 523 | parse_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 | */ |
| 780 | static enum event_result | 787 | static enum event_result |
| 781 | parse_event_symbols(const struct option *opt, const char **str, | 788 | parse_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 | ||
| 825 | int parse_events(const struct option *opt, const char *str, int unset __used) | 832 | int 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 | ||
| 872 | int 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 | |||
| 866 | int parse_filter(const struct option *opt, const char *str, | 879 | int 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 746d3fcbfc2a..2f8e375e038d 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | struct list_head; | 9 | struct list_head; |
| 10 | struct perf_evsel; | 10 | struct perf_evsel; |
| 11 | struct perf_evlist; | ||
| 11 | 12 | ||
| 12 | struct option; | 13 | struct option; |
| 13 | 14 | ||
| @@ -24,7 +25,10 @@ const char *event_type(int type); | |||
| 24 | const char *event_name(struct perf_evsel *event); | 25 | const char *event_name(struct perf_evsel *event); |
| 25 | extern const char *__event_name(int type, u64 config); | 26 | extern const char *__event_name(int type, u64 config); |
| 26 | 27 | ||
| 27 | extern int parse_events(const struct option *opt, const char *str, int unset); | 28 | extern int parse_events_option(const struct option *opt, const char *str, |
| 29 | int unset); | ||
| 30 | extern int parse_events(struct perf_evlist *evlist, const char *str, | ||
| 31 | int unset); | ||
| 28 | extern int parse_filter(const struct option *opt, const char *str, int unset); | 32 | extern 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 f0223166e761..1c7bfa5fe0a8 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 |
| 173 | static int open_vmlinux(const char *module) | 177 | /* Open new debuginfo of given module */ |
| 178 | static 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 | ||
| 240 | static 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 */ |
| 218 | static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | 276 | static 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 | ||
| 451 | static int show_available_vars_at(int fd, struct perf_probe_event *pev, | 516 | static 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 */ |
| 992 | static int parse_probe_trace_command(const char *cmd, | 1061 | static 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; |
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 3434fc9d79d5..a7dee835f49c 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 */ |
| 11 | struct probe_trace_point { | 11 | struct 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 3b9d0b800d5c..555fc3864b90 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 | */ | ||
| 50 | static 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 */ |
| 134 | static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias) | 119 | static 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; | ||
| 152 | error: | 142 | error: |
| 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 */ |
| 192 | static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp, | 185 | static 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... */ |
| 220 | static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp, | 210 | static 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 */ | 225 | struct debuginfo *debuginfo__new(const char *path) |
| 241 | |||
| 242 | /* Find the realpath of the target file. */ | ||
| 243 | static 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; |
| 268 | static 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 */ | 239 | struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) |
| 277 | static 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 */ | ||
| 296 | static 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 */ | ||
| 304 | static 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 */ | ||
| 317 | static 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 */ | ||
| 329 | static 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 */ | ||
| 347 | static 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 | |||
| 356 | static 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 | ||
| 368 | static 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 | |||
| 379 | static 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 | |||
| 389 | static 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 | |||
| 399 | static 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 */ | ||
| 410 | static 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 */ | ||
| 437 | enum { | ||
| 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 */ | ||
| 445 | static 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 | |||
| 472 | struct __addr_die_search_param { | ||
| 473 | Dwarf_Addr addr; | ||
| 474 | Dwarf_Die *die_mem; | ||
| 475 | }; | ||
| 476 | |||
| 477 | static 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; |
| 490 | static 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 */ | 253 | void debuginfo__delete(struct debuginfo *self) |
| 504 | static 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. */ | ||
| 516 | static 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) */ | ||
| 536 | typedef int (* line_walk_handler_t) (const char *fname, int lineno, | ||
| 537 | Dwarf_Addr addr, void *data); | ||
| 538 | |||
| 539 | struct __line_walk_param { | ||
| 540 | const char *fname; | ||
| 541 | line_walk_handler_t handler; | ||
| 542 | void *data; | ||
| 543 | int retval; | ||
| 544 | }; | ||
| 545 | |||
| 546 | static 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 */ | ||
| 565 | static 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); | ||
| 586 | done: | ||
| 587 | return lw.retval; | ||
| 588 | } | ||
| 589 | |||
| 590 | static 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 | */ | ||
| 605 | static 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, ¶m, 0); | ||
| 674 | ret = param.retval; | ||
| 675 | } | ||
| 676 | |||
| 677 | return ret; | ||
| 678 | } | ||
| 679 | |||
| 680 | struct __find_variable_param { | ||
| 681 | const char *name; | ||
| 682 | Dwarf_Addr addr; | ||
| 683 | }; | ||
| 684 | |||
| 685 | static 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 */ | ||
| 703 | static 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 | |||
| 712 | static 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' */ | ||
| 724 | static 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 */ | ||
| 732 | static 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" */ | ||
| 768 | static 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 */ |
| 1133 | static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) | 616 | static 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 | } |
| 1195 | found: | 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 */ |
| 1239 | static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf) | 708 | static 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 | ||
| 756 | struct 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 | |||
| 765 | static 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 */ | ||
| 798 | static 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 | |||
| 1284 | static int probe_point_line_walker(const char *fname, int lineno, | 814 | static 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 */ | ||
| 1383 | struct dwarf_callback_param { | ||
| 1384 | void *data; | ||
| 1385 | int retval; | ||
| 1386 | }; | ||
| 1387 | |||
| 1388 | static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) | 927 | static 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 */ | ||
| 955 | struct dwarf_callback_param { | ||
| 956 | void *data; | ||
| 957 | int retval; | ||
| 958 | }; | ||
| 959 | |||
| 1418 | /* Search function from function name */ | 960 | /* Search function from function name */ |
| 1419 | static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) | 961 | static 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 */ |
| 1507 | static int find_probes(int fd, struct probe_finder *pf) | 1045 | static 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 | ||
| 1583 | found: | 1112 | found: |
| 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 */ |
| 1592 | static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf) | 1119 | static 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 */ |
| 1632 | int find_probe_trace_events(int fd, struct perf_probe_event *pev, | 1161 | int 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 */ |
| 1690 | static int add_available_vars(Dwarf_Die *sp_die, struct probe_finder *pf) | 1220 | static 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 | ||
| 1732 | out: | 1258 | out: |
| 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 */ |
| 1742 | int find_available_vars_at(int fd, struct perf_probe_event *pev, | 1268 | int 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 */ |
| 1777 | int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt) | 1304 | int 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 | } |
| 1873 | end: | 1391 | end: |
| 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 | ||
| 1930 | static int line_range_inline_cb(Dwarf_Die *in_die, void *data) | 1446 | static 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 | ||
| 1985 | int find_line_range(int fd, struct line_range *lr) | 1500 | int 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 605730a366db..1132c8f0ce89 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 */ | ||
| 25 | struct debuginfo { | ||
| 26 | Dwarf *dbg; | ||
| 27 | Dwfl *dwfl; | ||
| 28 | Dwarf_Addr bias; | ||
| 29 | }; | ||
| 30 | |||
| 31 | extern struct debuginfo *debuginfo__new(const char *path); | ||
| 32 | extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr); | ||
| 33 | extern 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 */ |
| 20 | extern int find_probe_trace_events(int fd, struct perf_probe_event *pev, | 36 | extern 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 */ |
| 25 | extern int find_perf_probe_point(unsigned long addr, | 42 | extern 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 */ |
| 29 | extern int find_line_range(int fd, struct line_range *lr); | 47 | extern int debuginfo__find_line_range(struct debuginfo *self, |
| 48 | struct line_range *lr); | ||
| 30 | 49 | ||
| 31 | /* Find available variables */ | 50 | /* Find available variables */ |
| 32 | extern int find_available_vars_at(int fd, struct perf_probe_event *pev, | 51 | extern 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 | ||
| 41 | struct probe_finder { | 56 | struct 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 a9ac0504aabd..cbc8f215d4b7 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 | ||
| 190 | static char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object."); | ||
| 191 | |||
| 192 | static 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 | |||
| 199 | static 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 | |||
| 215 | static 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 | |||
| 225 | static char pyrf_read_event__doc[] = PyDoc_STR("perf read event object."); | ||
| 226 | |||
| 227 | static 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 | |||
| 234 | static 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 | |||
| 245 | static 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 | |||
| 255 | static char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object."); | ||
| 256 | |||
| 257 | static PyMemberDef pyrf_sample_event__members[] = { | ||
| 258 | sample_members | ||
| 259 | member_def(perf_event_header, type, T_UINT, "event type"), | ||
| 260 | { .name = NULL, }, | ||
| 261 | }; | ||
| 262 | |||
| 263 | static 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 | |||
| 277 | static 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 | |||
| 190 | static int pyrf_event__setup_types(void) | 287 | static 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; | ||
| 209 | out: | 318 | out: |
| 210 | return err; | 319 | return err; |
| 211 | } | 320 | } |
| 212 | 321 | ||
| 213 | static PyTypeObject *pyrf_event__type[] = { | 322 | static 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 | ||
| 225 | static PyObject *pyrf_event__new(union perf_event *event) | 334 | static PyObject *pyrf_event__new(union perf_event *event) |
| @@ -247,7 +356,7 @@ struct pyrf_cpu_map { | |||
| 247 | static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, | 356 | static 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 { | |||
| 316 | static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, | 425 | static 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, |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index f5a8fbdd3f76..72458d9da5b1 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 | ||
| 16 | static int perf_session__open(struct perf_session *self, bool force) | 17 | static 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 | ||
| 410 | static void perf_event__attr_swap(union perf_event *event) | 416 | /* exported for swapping attributes in file header */ |
| 417 | void 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 | |||
| 431 | static 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 | ||
| 1205 | void perf_session__print_symbols(union perf_event *event, | 1217 | void 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); | 1293 | int 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 66d4e1490879..170601e67d6b 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 | ||
| 114 | void mem_bswap_64(void *src, int byte_size); | 114 | void mem_bswap_64(void *src, int byte_size); |
| 115 | void perf_event__attr_swap(struct perf_event_attr *attr); | ||
| 115 | 116 | ||
| 116 | int perf_session__create_kernel_maps(struct perf_session *self); | 117 | int perf_session__create_kernel_maps(struct perf_session *self); |
| 117 | 118 | ||
| @@ -167,8 +168,12 @@ static inline int perf_session__parse_sample(struct perf_session *session, | |||
| 167 | struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, | 168 | struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, |
| 168 | unsigned int type); | 169 | unsigned int type); |
| 169 | 170 | ||
| 170 | void perf_session__print_symbols(union perf_event *event, | 171 | void perf_session__print_ip(union perf_event *event, |
| 171 | struct perf_sample *sample, | 172 | struct perf_sample *sample, |
| 172 | struct perf_session *session); | 173 | struct perf_session *session, |
| 174 | int print_sym, int print_dso); | ||
| 175 | |||
| 176 | int perf_session__cpu_bitmap(struct perf_session *session, | ||
| 177 | const char *cpu_list, unsigned long *cpu_bitmap); | ||
| 173 | 178 | ||
| 174 | #endif /* __PERF_SESSION_H */ | 179 | #endif /* __PERF_SESSION_H */ |
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index bbc982f5dd8b..95d370074928 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py | |||
| @@ -3,9 +3,27 @@ | |||
| 3 | from distutils.core import setup, Extension | 3 | from distutils.core import setup, Extension |
| 4 | from os import getenv | 4 | from os import getenv |
| 5 | 5 | ||
| 6 | from distutils.command.build_ext import build_ext as _build_ext | ||
| 7 | from distutils.command.install_lib import install_lib as _install_lib | ||
| 8 | |||
| 9 | class 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 | |||
| 15 | class install_lib(_install_lib): | ||
| 16 | def finalize_options(self): | ||
| 17 | _install_lib.finalize_options(self) | ||
| 18 | self.build_dir = build_lib | ||
| 19 | |||
| 20 | |||
| 6 | cflags = ['-fno-strict-aliasing', '-Wno-write-strings'] | 21 | cflags = ['-fno-strict-aliasing', '-Wno-write-strings'] |
| 7 | cflags += getenv('CFLAGS', '').split() | 22 | cflags += getenv('CFLAGS', '').split() |
| 8 | 23 | ||
| 24 | build_lib = getenv('PYTHON_EXTBUILD_LIB') | ||
| 25 | build_tmp = getenv('PYTHON_EXTBUILD_TMP') | ||
| 26 | |||
| 9 | perf = Extension('perf', | 27 | perf = 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 f44fa541d56e..401e220566fd 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
| @@ -15,95 +15,6 @@ char * field_sep; | |||
| 15 | 15 | ||
| 16 | LIST_HEAD(hist_entry__sort_list); | 16 | LIST_HEAD(hist_entry__sort_list); |
| 17 | 17 | ||
| 18 | static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, | ||
| 19 | size_t size, unsigned int width); | ||
| 20 | static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf, | ||
| 21 | size_t size, unsigned int width); | ||
| 22 | static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, | ||
| 23 | size_t size, unsigned int width); | ||
| 24 | static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, | ||
| 25 | size_t size, unsigned int width); | ||
| 26 | static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, | ||
| 27 | size_t size, unsigned int width); | ||
| 28 | static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf, | ||
| 29 | size_t size, unsigned int width); | ||
| 30 | |||
| 31 | struct 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 | |||
| 38 | struct 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 | |||
| 46 | struct 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 | |||
| 53 | struct 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 | |||
| 60 | struct 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 | |||
| 67 | struct 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 | |||
| 74 | struct sort_dimension { | ||
| 75 | const char *name; | ||
| 76 | struct sort_entry *entry; | ||
| 77 | int taken; | ||
| 78 | }; | ||
| 79 | |||
| 80 | static 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 | |||
| 89 | int64_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 | |||
| 101 | int64_t | ||
| 102 | sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) | ||
| 103 | { | ||
| 104 | return right->thread->pid - left->thread->pid; | ||
| 105 | } | ||
| 106 | |||
| 107 | static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) | 18 | static 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 | ||
| 39 | static 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 | |||
| 51 | static int64_t | ||
| 52 | sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) | ||
| 53 | { | ||
| 54 | return right->thread->pid - left->thread->pid; | ||
| 55 | } | ||
| 56 | |||
| 128 | static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, | 57 | static 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 | ||
| 64 | struct 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 | |||
| 73 | static int64_t | ||
| 74 | sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) | ||
| 75 | { | ||
| 76 | return right->thread->pid - left->thread->pid; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int64_t | ||
| 80 | sort__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 | |||
| 135 | static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf, | 91 | static 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 | ||
| 97 | struct 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 | ||
| 143 | int64_t | 107 | static int64_t |
| 144 | sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) | 108 | sort__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,9 +137,16 @@ 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 | ||
| 140 | struct 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 | ||
| 178 | int64_t | 149 | static int64_t |
| 179 | sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) | 150 | sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) |
| 180 | { | 151 | { |
| 181 | u64 ip_l, ip_r; | 152 | u64 ip_l, ip_r; |
| @@ -211,29 +182,16 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, | |||
| 211 | return ret; | 182 | return ret; |
| 212 | } | 183 | } |
| 213 | 184 | ||
| 214 | /* --sort comm */ | 185 | struct sort_entry sort_sym = { |
| 215 | 186 | .se_header = "Symbol", | |
| 216 | int64_t | 187 | .se_cmp = sort__sym_cmp, |
| 217 | sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) | 188 | .se_snprintf = hist_entry__sym_snprintf, |
| 218 | { | 189 | .se_width_idx = HISTC_SYMBOL, |
| 219 | return right->thread->pid - left->thread->pid; | 190 | }; |
| 220 | } | ||
| 221 | |||
| 222 | int64_t | ||
| 223 | sort__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 | 191 | ||
| 234 | /* --sort parent */ | 192 | /* --sort parent */ |
| 235 | 193 | ||
| 236 | int64_t | 194 | static int64_t |
| 237 | sort__parent_cmp(struct hist_entry *left, struct hist_entry *right) | 195 | sort__parent_cmp(struct hist_entry *left, struct hist_entry *right) |
| 238 | { | 196 | { |
| 239 | struct symbol *sym_l = left->parent; | 197 | struct symbol *sym_l = left->parent; |
| @@ -252,9 +210,16 @@ static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, | |||
| 252 | self->parent ? self->parent->name : "[other]"); | 210 | self->parent ? self->parent->name : "[other]"); |
| 253 | } | 211 | } |
| 254 | 212 | ||
| 213 | struct sort_entry sort_parent = { | ||
| 214 | .se_header = "Parent symbol", | ||
| 215 | .se_cmp = sort__parent_cmp, | ||
| 216 | .se_snprintf = hist_entry__parent_snprintf, | ||
| 217 | .se_width_idx = HISTC_PARENT, | ||
| 218 | }; | ||
| 219 | |||
| 255 | /* --sort cpu */ | 220 | /* --sort cpu */ |
| 256 | 221 | ||
| 257 | int64_t | 222 | static int64_t |
| 258 | sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right) | 223 | sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right) |
| 259 | { | 224 | { |
| 260 | return right->cpu - left->cpu; | 225 | return right->cpu - left->cpu; |
| @@ -266,6 +231,28 @@ static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf, | |||
| 266 | return repsep_snprintf(bf, size, "%-*d", width, self->cpu); | 231 | return repsep_snprintf(bf, size, "%-*d", width, self->cpu); |
| 267 | } | 232 | } |
| 268 | 233 | ||
| 234 | struct sort_entry sort_cpu = { | ||
| 235 | .se_header = "CPU", | ||
| 236 | .se_cmp = sort__cpu_cmp, | ||
| 237 | .se_snprintf = hist_entry__cpu_snprintf, | ||
| 238 | .se_width_idx = HISTC_CPU, | ||
| 239 | }; | ||
| 240 | |||
| 241 | struct sort_dimension { | ||
| 242 | const char *name; | ||
| 243 | struct sort_entry *entry; | ||
| 244 | int taken; | ||
| 245 | }; | ||
| 246 | |||
| 247 | static struct sort_dimension sort_dimensions[] = { | ||
| 248 | { .name = "pid", .entry = &sort_thread, }, | ||
| 249 | { .name = "comm", .entry = &sort_comm, }, | ||
| 250 | { .name = "dso", .entry = &sort_dso, }, | ||
| 251 | { .name = "symbol", .entry = &sort_sym, }, | ||
| 252 | { .name = "parent", .entry = &sort_parent, }, | ||
| 253 | { .name = "cpu", .entry = &sort_cpu, }, | ||
| 254 | }; | ||
| 255 | |||
| 269 | int sort_dimension__add(const char *tok) | 256 | int sort_dimension__add(const char *tok) |
| 270 | { | 257 | { |
| 271 | unsigned int i; | 258 | unsigned int i; |
| @@ -273,15 +260,9 @@ int sort_dimension__add(const char *tok) | |||
| 273 | for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { | 260 | for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { |
| 274 | struct sort_dimension *sd = &sort_dimensions[i]; | 261 | struct sort_dimension *sd = &sort_dimensions[i]; |
| 275 | 262 | ||
| 276 | if (sd->taken) | ||
| 277 | continue; | ||
| 278 | |||
| 279 | if (strncasecmp(tok, sd->name, strlen(tok))) | 263 | if (strncasecmp(tok, sd->name, strlen(tok))) |
| 280 | continue; | 264 | continue; |
| 281 | 265 | ||
| 282 | if (sd->entry->se_collapse) | ||
| 283 | sort__need_collapse = 1; | ||
| 284 | |||
| 285 | if (sd->entry == &sort_parent) { | 266 | if (sd->entry == &sort_parent) { |
| 286 | int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED); | 267 | int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED); |
| 287 | if (ret) { | 268 | if (ret) { |
| @@ -294,6 +275,12 @@ int sort_dimension__add(const char *tok) | |||
| 294 | sort__has_parent = 1; | 275 | sort__has_parent = 1; |
| 295 | } | 276 | } |
| 296 | 277 | ||
| 278 | if (sd->taken) | ||
| 279 | return 0; | ||
| 280 | |||
| 281 | if (sd->entry->se_collapse) | ||
| 282 | sort__need_collapse = 1; | ||
| 283 | |||
| 297 | if (list_empty(&hist_entry__sort_list)) { | 284 | if (list_empty(&hist_entry__sort_list)) { |
| 298 | if (!strcmp(sd->name, "pid")) | 285 | if (!strcmp(sd->name, "pid")) |
| 299 | sort__first_dimension = SORT_PID; | 286 | sort__first_dimension = SORT_PID; |
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 0b91053a7d11..77d0388ad415 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
| @@ -103,20 +103,6 @@ extern struct sort_entry sort_thread; | |||
| 103 | extern struct list_head hist_entry__sort_list; | 103 | extern struct list_head hist_entry__sort_list; |
| 104 | 104 | ||
| 105 | void setup_sorting(const char * const usagestr[], const struct option *opts); | 105 | void setup_sorting(const char * const usagestr[], const struct option *opts); |
| 106 | |||
| 107 | extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int); | ||
| 108 | extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int); | ||
| 109 | extern size_t sort__dso_print(FILE *, struct hist_entry *, unsigned int); | ||
| 110 | extern size_t sort__sym_print(FILE *, struct hist_entry *, unsigned int __used); | ||
| 111 | extern int64_t cmp_null(void *, void *); | ||
| 112 | extern int64_t sort__thread_cmp(struct hist_entry *, struct hist_entry *); | ||
| 113 | extern int64_t sort__comm_cmp(struct hist_entry *, struct hist_entry *); | ||
| 114 | extern int64_t sort__comm_collapse(struct hist_entry *, struct hist_entry *); | ||
| 115 | extern int64_t sort__dso_cmp(struct hist_entry *, struct hist_entry *); | ||
| 116 | extern int64_t sort__sym_cmp(struct hist_entry *, struct hist_entry *); | ||
| 117 | extern int64_t sort__parent_cmp(struct hist_entry *, struct hist_entry *); | ||
| 118 | int64_t sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right); | ||
| 119 | extern size_t sort__parent_print(FILE *, struct hist_entry *, unsigned int); | ||
| 120 | extern int sort_dimension__add(const char *); | 106 | extern int sort_dimension__add(const char *); |
| 121 | void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, | 107 | void 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 b9a985dadd08..d5836382ff2c 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 | */ | ||
| 305 | int 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 eec196329fd9..469c0264ed29 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -1504,6 +1504,17 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
| 1504 | dso->adjust_symbols = 0; | 1504 | dso->adjust_symbols = 0; |
| 1505 | 1505 | ||
| 1506 | if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { | 1506 | if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { |
| 1507 | struct stat st; | ||
| 1508 | |||
| 1509 | if (lstat(dso->name, &st) < 0) | ||
| 1510 | return -1; | ||
| 1511 | |||
| 1512 | if (st.st_uid && (st.st_uid != geteuid())) { | ||
| 1513 | pr_warning("File %s not owned by current user or root, " | ||
| 1514 | "ignoring it.\n", dso->name); | ||
| 1515 | return -1; | ||
| 1516 | } | ||
| 1517 | |||
| 1507 | ret = dso__load_perf_map(dso, map, filter); | 1518 | ret = dso__load_perf_map(dso, map, filter); |
| 1508 | dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : | 1519 | dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : |
| 1509 | SYMTAB__NOT_FOUND; | 1520 | SYMTAB__NOT_FOUND; |
| @@ -2170,27 +2181,22 @@ size_t machines__fprintf_dsos_buildid(struct rb_root *machines, | |||
| 2170 | return ret; | 2181 | return ret; |
| 2171 | } | 2182 | } |
| 2172 | 2183 | ||
| 2173 | struct dso *dso__new_kernel(const char *name) | 2184 | static struct dso* |
| 2185 | dso__kernel_findnew(struct machine *machine, const char *name, | ||
| 2186 | const char *short_name, int dso_type) | ||
| 2174 | { | 2187 | { |
| 2175 | struct dso *dso = dso__new(name ?: "[kernel.kallsyms]"); | 2188 | /* |
| 2176 | 2189 | * The kernel dso could be created by build_id processing. | |
| 2177 | if (dso != NULL) { | 2190 | */ |
| 2178 | dso__set_short_name(dso, "[kernel]"); | 2191 | struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name); |
| 2179 | dso->kernel = DSO_TYPE_KERNEL; | ||
| 2180 | } | ||
| 2181 | |||
| 2182 | return dso; | ||
| 2183 | } | ||
| 2184 | 2192 | ||
| 2185 | static struct dso *dso__new_guest_kernel(struct machine *machine, | 2193 | /* |
| 2186 | const char *name) | 2194 | * We need to run this in all cases, since during the build_id |
| 2187 | { | 2195 | * processing we had no idea this was the kernel dso. |
| 2188 | char bf[PATH_MAX]; | 2196 | */ |
| 2189 | struct dso *dso = dso__new(name ?: machine__mmap_name(machine, bf, | ||
| 2190 | sizeof(bf))); | ||
| 2191 | if (dso != NULL) { | 2197 | if (dso != NULL) { |
| 2192 | dso__set_short_name(dso, "[guest.kernel]"); | 2198 | dso__set_short_name(dso, short_name); |
| 2193 | dso->kernel = DSO_TYPE_GUEST_KERNEL; | 2199 | dso->kernel = dso_type; |
| 2194 | } | 2200 | } |
| 2195 | 2201 | ||
| 2196 | return dso; | 2202 | return dso; |
| @@ -2208,24 +2214,36 @@ void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine) | |||
| 2208 | dso->has_build_id = true; | 2214 | dso->has_build_id = true; |
| 2209 | } | 2215 | } |
| 2210 | 2216 | ||
| 2211 | static struct dso *machine__create_kernel(struct machine *machine) | 2217 | static struct dso *machine__get_kernel(struct machine *machine) |
| 2212 | { | 2218 | { |
| 2213 | const char *vmlinux_name = NULL; | 2219 | const char *vmlinux_name = NULL; |
| 2214 | struct dso *kernel; | 2220 | struct dso *kernel; |
| 2215 | 2221 | ||
| 2216 | if (machine__is_host(machine)) { | 2222 | if (machine__is_host(machine)) { |
| 2217 | vmlinux_name = symbol_conf.vmlinux_name; | 2223 | vmlinux_name = symbol_conf.vmlinux_name; |
| 2218 | kernel = dso__new_kernel(vmlinux_name); | 2224 | if (!vmlinux_name) |
| 2225 | vmlinux_name = "[kernel.kallsyms]"; | ||
| 2226 | |||
| 2227 | kernel = dso__kernel_findnew(machine, vmlinux_name, | ||
| 2228 | "[kernel]", | ||
| 2229 | DSO_TYPE_KERNEL); | ||
| 2219 | } else { | 2230 | } else { |
| 2231 | char bf[PATH_MAX]; | ||
| 2232 | |||
| 2220 | if (machine__is_default_guest(machine)) | 2233 | if (machine__is_default_guest(machine)) |
| 2221 | vmlinux_name = symbol_conf.default_guest_vmlinux_name; | 2234 | vmlinux_name = symbol_conf.default_guest_vmlinux_name; |
| 2222 | kernel = dso__new_guest_kernel(machine, vmlinux_name); | 2235 | if (!vmlinux_name) |
| 2236 | vmlinux_name = machine__mmap_name(machine, bf, | ||
| 2237 | sizeof(bf)); | ||
| 2238 | |||
| 2239 | kernel = dso__kernel_findnew(machine, vmlinux_name, | ||
| 2240 | "[guest.kernel]", | ||
| 2241 | DSO_TYPE_GUEST_KERNEL); | ||
| 2223 | } | 2242 | } |
| 2224 | 2243 | ||
| 2225 | if (kernel != NULL) { | 2244 | if (kernel != NULL && (!kernel->has_build_id)) |
| 2226 | dso__read_running_kernel_build_id(kernel, machine); | 2245 | dso__read_running_kernel_build_id(kernel, machine); |
| 2227 | dsos__add(&machine->kernel_dsos, kernel); | 2246 | |
| 2228 | } | ||
| 2229 | return kernel; | 2247 | return kernel; |
| 2230 | } | 2248 | } |
| 2231 | 2249 | ||
| @@ -2329,7 +2347,7 @@ void machine__destroy_kernel_maps(struct machine *machine) | |||
| 2329 | 2347 | ||
| 2330 | int machine__create_kernel_maps(struct machine *machine) | 2348 | int machine__create_kernel_maps(struct machine *machine) |
| 2331 | { | 2349 | { |
| 2332 | struct dso *kernel = machine__create_kernel(machine); | 2350 | struct dso *kernel = machine__get_kernel(machine); |
| 2333 | 2351 | ||
| 2334 | if (kernel == NULL || | 2352 | if (kernel == NULL || |
| 2335 | __machine__create_kernel_maps(machine, kernel) < 0) | 2353 | __machine__create_kernel_maps(machine, kernel) < 0) |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 325ee36a9d29..4f377d92e75a 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
| @@ -155,7 +155,6 @@ struct dso { | |||
| 155 | }; | 155 | }; |
| 156 | 156 | ||
| 157 | struct dso *dso__new(const char *name); | 157 | struct dso *dso__new(const char *name); |
| 158 | struct dso *dso__new_kernel(const char *name); | ||
| 159 | void dso__delete(struct dso *dso); | 158 | void dso__delete(struct dso *dso); |
| 160 | 159 | ||
| 161 | int dso__name_len(const struct dso *dso); | 160 | int 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 35729f4c40cb..3403f814ad72 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 | ||
| 186 | static unsigned long long copy_file_fd(int fd) | 186 | /* unfortunately, you can not stat debugfs or proc files for size */ |
| 187 | static 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 | |||
| 203 | static 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 | |||
| 217 | static 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 | |||
| 234 | static 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 | ||
| 248 | static void read_header_files(void) | 219 | static 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 | ||
| 288 | static bool name_in_tp_list(char *sys, struct tracepoint_path *tps) | 241 | static 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 | ||
| 299 | static void copy_event_system(const char *sys, struct tracepoint_path *tps) | 252 | static 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 | ||
| 427 | static void read_proc_kallsyms(void) | 373 | static 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 | ||
| 449 | static void read_ftrace_printk(void) | 390 | static 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); | ||
| 469 | out: | 407 | out: |
| 470 | put_tracing_file(path); | 408 | put_tracing_file(path); |
| 471 | } | 409 | } |
diff --git a/tools/perf/util/ui/browsers/top.c b/tools/perf/util/ui/browsers/top.c index 5a06538532af..88403cf8396a 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 fc784284ac8b..0128906bac88 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); | |||
| 238 | void argv_free(char **argv); | 238 | void argv_free(char **argv); |
| 239 | bool strglobmatch(const char *str, const char *pat); | 239 | bool strglobmatch(const char *str, const char *pat); |
| 240 | bool strlazymatch(const char *str, const char *pat); | 240 | bool strlazymatch(const char *str, const char *pat); |
| 241 | int strtailcmp(const char *s1, const char *s2); | ||
| 241 | unsigned long convert_unit(unsigned long value, char *unit); | 242 | unsigned long convert_unit(unsigned long value, char *unit); |
| 242 | int readn(int fd, void *buf, size_t size); | 243 | int 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 000000000000..8a83dd2ffc11 --- /dev/null +++ b/tools/power/cpupower/.gitignore | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | .libs | ||
| 2 | libcpupower.so | ||
| 3 | libcpupower.so.0 | ||
| 4 | libcpupower.so.0.0.0 | ||
| 5 | build/ccdv | ||
| 6 | cpufreq-info | ||
| 7 | cpufreq-set | ||
| 8 | cpufreq-aperf | ||
| 9 | lib/.libs | ||
| 10 | lib/cpufreq.lo | ||
| 11 | lib/cpufreq.o | ||
| 12 | lib/proc.lo | ||
| 13 | lib/proc.o | ||
| 14 | lib/sysfs.lo | ||
| 15 | lib/sysfs.o | ||
| 16 | po/cpupowerutils.pot | ||
| 17 | po/*.gmo | ||
| 18 | utils/cpufreq-info.o | ||
| 19 | utils/cpufreq-set.o | ||
| 20 | utils/cpufreq-aperf.o | ||
| 21 | cpupower | ||
| 22 | bench/cpufreq-bench | ||
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile new file mode 100644 index 000000000000..e8a03aceceb1 --- /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. | ||
| 27 | DEBUG ?= true | ||
| 28 | |||
| 29 | # make the build silent. Set this to something else to make it noisy again. | ||
| 30 | V ?= false | ||
| 31 | |||
| 32 | # Internationalization support (output in different languages). | ||
| 33 | # Requires gettext. | ||
| 34 | NLS ?= true | ||
| 35 | |||
| 36 | # Set the following to 'true' to build/install the | ||
| 37 | # cpufreq-bench benchmarking tool | ||
| 38 | CPUFREQ_BENCH ?= true | ||
| 39 | |||
| 40 | # Prefix to the directories we're installing to | ||
| 41 | DESTDIR ?= | ||
| 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 | |||
| 50 | VERSION= $(shell ./utils/version-gen.sh) | ||
| 51 | LIB_MAJ= 0.0.0 | ||
| 52 | LIB_MIN= 0 | ||
| 53 | |||
| 54 | PACKAGE = cpupower | ||
| 55 | PACKAGE_BUGREPORT = cpufreq@vger.kernel.org | ||
| 56 | LANGUAGES = 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 | |||
| 63 | bindir ?= /usr/bin | ||
| 64 | sbindir ?= /usr/sbin | ||
| 65 | mandir ?= /usr/man | ||
| 66 | includedir ?= /usr/include | ||
| 67 | libdir ?= /usr/lib | ||
| 68 | localedir ?= /usr/share/locale | ||
| 69 | docdir ?= /usr/share/doc/packages/cpupower | ||
| 70 | confdir ?= /etc/ | ||
| 71 | |||
| 72 | # Toolchain: what tools do we use, and what options do they need: | ||
| 73 | |||
| 74 | CP = cp -fpR | ||
| 75 | INSTALL = /usr/bin/install -c | ||
| 76 | INSTALL_PROGRAM = ${INSTALL} | ||
| 77 | INSTALL_DATA = ${INSTALL} -m 644 | ||
| 78 | INSTALL_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. | ||
| 83 | CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc- | ||
| 84 | CC = $(CROSS)gcc | ||
| 85 | LD = $(CROSS)gcc | ||
| 86 | AR = $(CROSS)ar | ||
| 87 | STRIP = $(CROSS)strip | ||
| 88 | RANLIB = $(CROSS)ranlib | ||
| 89 | HOSTCC = 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. | ||
| 96 | PWD = $(shell pwd) | ||
| 97 | |||
| 98 | GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo po/$$HLANG.gmo; done;} | ||
| 99 | |||
| 100 | export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS | ||
| 101 | |||
| 102 | # check if compiler option is supported | ||
| 103 | cc-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 | ||
| 106 | OPTIMIZATION := $(call cc-supports,-Os,-O2) | ||
| 107 | |||
| 108 | WARNINGS := -Wall -Wchar-subscripts -Wpointer-arith -Wsign-compare | ||
| 109 | WARNINGS += $(call cc-supports,-Wno-pointer-sign) | ||
| 110 | WARNINGS += $(call cc-supports,-Wdeclaration-after-statement) | ||
| 111 | WARNINGS += -Wshadow | ||
| 112 | |||
| 113 | CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \ | ||
| 114 | -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE | ||
| 115 | |||
| 116 | UTIL_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 | |||
| 125 | UTIL_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 | |||
| 129 | UTIL_SRC := $(UTIL_OBJS:.o=.c) | ||
| 130 | |||
| 131 | LIB_HEADERS = lib/cpufreq.h lib/sysfs.h | ||
| 132 | LIB_SRC = lib/cpufreq.c lib/sysfs.c | ||
| 133 | LIB_OBJS = lib/cpufreq.o lib/sysfs.o | ||
| 134 | |||
| 135 | CFLAGS += -pipe | ||
| 136 | |||
| 137 | ifeq ($(strip $(NLS)),true) | ||
| 138 | INSTALL_NLS += install-gmo | ||
| 139 | COMPILE_NLS += create-gmo | ||
| 140 | CFLAGS += -DNLS | ||
| 141 | endif | ||
| 142 | |||
| 143 | ifeq ($(strip $(CPUFREQ_BENCH)),true) | ||
| 144 | INSTALL_BENCH += install-bench | ||
| 145 | COMPILE_BENCH += compile-bench | ||
| 146 | endif | ||
| 147 | |||
| 148 | CFLAGS += $(WARNINGS) | ||
| 149 | |||
| 150 | ifeq ($(strip $(V)),false) | ||
| 151 | QUIET=@ | ||
| 152 | ECHO=@echo | ||
| 153 | else | ||
| 154 | QUIET= | ||
| 155 | ECHO=@\# | ||
| 156 | endif | ||
| 157 | export QUIET ECHO | ||
| 158 | |||
| 159 | # if DEBUG is enabled, then we do not strip or optimize | ||
| 160 | ifeq ($(strip $(DEBUG)),true) | ||
| 161 | CFLAGS += -O1 -g -DDEBUG | ||
| 162 | STRIPCMD = /bin/true -Since_we_are_debugging | ||
| 163 | else | ||
| 164 | CFLAGS += $(OPTIMIZATION) -fomit-frame-pointer | ||
| 165 | STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment | ||
| 166 | endif | ||
| 167 | |||
| 168 | |||
| 169 | # the actual make rules | ||
| 170 | |||
| 171 | all: libcpupower cpupower $(COMPILE_NLS) $(COMPILE_BENCH) | ||
| 172 | |||
| 173 | lib/%.o: $(LIB_SRC) $(LIB_HEADERS) | ||
| 174 | $(ECHO) " CC " $@ | ||
| 175 | $(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c | ||
| 176 | |||
| 177 | libcpupower.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 | |||
| 184 | libcpupower: 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 | |||
| 194 | cpupower: $(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 | |||
| 199 | po/$(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 | |||
| 206 | po/%.gmo: po/%.po | ||
| 207 | $(ECHO) " MSGFMT " $@ | ||
| 208 | $(QUIET) msgfmt -o $@ po/$*.po | ||
| 209 | |||
| 210 | create-gmo: ${GMO_FILES} | ||
| 211 | |||
| 212 | update-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 | |||
| 225 | compile-bench: libcpupower.so.$(LIB_MAJ) | ||
| 226 | @V=$(V) confdir=$(confdir) $(MAKE) -C bench | ||
| 227 | |||
| 228 | clean: | ||
| 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 | |||
| 239 | install-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 | |||
| 245 | install-tools: | ||
| 246 | $(INSTALL) -d $(DESTDIR)${bindir} | ||
| 247 | $(INSTALL_PROGRAM) cpupower $(DESTDIR)${bindir} | ||
| 248 | |||
| 249 | install-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 | |||
| 257 | install-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 | |||
| 264 | install-bench: | ||
| 265 | @#DESTDIR must be set from outside to survive | ||
| 266 | @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench install | ||
| 267 | |||
| 268 | install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH) | ||
| 269 | |||
| 270 | uninstall: | ||
| 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 000000000000..fd9d4c0d6688 --- /dev/null +++ b/tools/power/cpupower/README | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | The cpufrequtils package (homepage: | ||
| 2 | http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufrequtils.html ) | ||
| 3 | consists of the following elements: | ||
| 4 | |||
| 5 | requirements | ||
| 6 | ------------ | ||
| 7 | |||
| 8 | On x86 pciutils is needed at runtime (-lpci). | ||
| 9 | For compilation pciutils-devel (pci/pci.h) and a gcc version | ||
| 10 | providing cpuid.h is needed. | ||
| 11 | For both it's not explicitly checked for (yet). | ||
| 12 | |||
| 13 | |||
| 14 | libcpufreq | ||
| 15 | ---------- | ||
| 16 | |||
| 17 | "libcpufreq" is a library which offers a unified access method for userspace | ||
| 18 | tools and programs to the cpufreq core and drivers in the Linux kernel. This | ||
| 19 | allows for code reduction in userspace tools, a clean implementation of | ||
| 20 | the interaction to the cpufreq core, and support for both the sysfs and proc | ||
| 21 | interfaces [depending on configuration, see below]. | ||
| 22 | |||
| 23 | |||
| 24 | compilation and installation | ||
| 25 | ---------------------------- | ||
| 26 | |||
| 27 | make | ||
| 28 | su | ||
| 29 | make install | ||
| 30 | |||
| 31 | should suffice on most systems. It builds default libcpufreq, | ||
| 32 | cpufreq-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 | ||
| 34 | want 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 | ||
| 36 | CONFIGURATION. | ||
| 37 | |||
| 38 | |||
| 39 | THANKS | ||
| 40 | ------ | ||
| 41 | Many thanks to Mattia Dongili who wrote the autotoolization and | ||
| 42 | libtoolization, the manpages and the italian language file for cpufrequtils; | ||
| 43 | to Dave Jones for his feedback and his dump_psb tool; to Bruno Ducrot for his | ||
| 44 | powernow-k8-decode and intel_gsic tools as well as the french language file; | ||
| 45 | and to various others commenting on the previous (pre-)releases of | ||
| 46 | cpufrequtils. | ||
| 47 | |||
| 48 | |||
| 49 | Dominik Brodowski | ||
diff --git a/tools/power/cpupower/ToDo b/tools/power/cpupower/ToDo new file mode 100644 index 000000000000..874b78b586ee --- /dev/null +++ b/tools/power/cpupower/ToDo | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | ToDos 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 000000000000..2b67606fc3e3 --- /dev/null +++ b/tools/power/cpupower/bench/Makefile | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | LIBS = -L../ -lm -lcpupower | ||
| 2 | |||
| 3 | OBJS = main.o parse.o system.o benchmark.o | ||
| 4 | CFLAGS += -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 | |||
| 10 | cpufreq-bench: $(OBJS) | ||
| 11 | $(ECHO) " CC " $@ | ||
| 12 | $(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS) | ||
| 13 | |||
| 14 | all: cpufreq-bench | ||
| 15 | |||
| 16 | install: | ||
| 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 | |||
| 27 | clean: | ||
| 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 000000000000..8093ec738170 --- /dev/null +++ b/tools/power/cpupower/bench/README-BENCH | |||
| @@ -0,0 +1,124 @@ | |||
| 1 | This is cpufreq-bench, a microbenchmark for the cpufreq framework. | ||
| 2 | |||
| 3 | Purpose | ||
| 4 | ======= | ||
| 5 | |||
| 6 | What 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 | |||
| 17 | What 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 | |||
| 24 | Description | ||
| 25 | =========== | ||
| 26 | |||
| 27 | cpufreq-bench helps to test the condition of a given cpufreq governor. | ||
| 28 | For that purpose, it compares the performance governor to a configured | ||
| 29 | powersave module. | ||
| 30 | |||
| 31 | |||
| 32 | How it works | ||
| 33 | ============ | ||
| 34 | You can specify load (100% CPU load) and sleep (0% CPU load) times in us which | ||
| 35 | will be run X time in a row (cycles): | ||
| 36 | |||
| 37 | sleep=25000 | ||
| 38 | load=25000 | ||
| 39 | cycles=20 | ||
| 40 | |||
| 41 | This part of the configuration file will create 25ms load/sleep turns, | ||
| 42 | repeated 20 times. | ||
| 43 | |||
| 44 | Adding this: | ||
| 45 | sleep_step=25000 | ||
| 46 | load_step=25000 | ||
| 47 | rounds=5 | ||
| 48 | Will increase load and sleep time by 25ms 5 times. | ||
| 49 | Together you get following test: | ||
| 50 | 25ms load/sleep time repeated 20 times (cycles). | ||
| 51 | 50ms load/sleep time repeated 20 times (cycles). | ||
| 52 | .. | ||
| 53 | 100ms load/sleep time repeated 20 times (cycles). | ||
| 54 | |||
| 55 | First it is calibrated how long a specific CPU intensive calculation | ||
| 56 | takes on this machine and needs to be run in a loop using the performance | ||
| 57 | governor. | ||
| 58 | Then the above test runs are processed using the performance governor | ||
| 59 | and the governor to test. The time the calculation really needed | ||
| 60 | with the dynamic freq scaling governor is compared with the time needed | ||
| 61 | on full performance and you get the overall performance loss. | ||
| 62 | |||
| 63 | |||
| 64 | Example of expected results with ondemand governor: | ||
| 65 | |||
| 66 | This shows expected results of the first two test run rounds from | ||
| 67 | above config, you there have: | ||
| 68 | |||
| 69 | 100% CPU load (load) | 0 % CPU load (sleep) | round | ||
| 70 | 25 ms | 25 ms | 1 | ||
| 71 | 50 ms | 50 ms | 2 | ||
| 72 | |||
| 73 | For example if ondemand governor is configured to have a 50ms | ||
| 74 | sampling rate you get: | ||
| 75 | |||
| 76 | In round 1, ondemand should have rather static 50% load and probably | ||
| 77 | won't ever switch up (as long as up_threshold is above). | ||
| 78 | |||
| 79 | In round 2, if the ondemand sampling times exactly match the load/sleep | ||
| 80 | trigger of the cpufreq-bench, you will see no performance loss (compare with | ||
| 81 | below possible ondemand sample kick ins (1)): | ||
| 82 | |||
| 83 | But if ondemand always kicks in in the middle of the load sleep cycles, it | ||
| 84 | will always see 50% loads and you get worst performance impact never | ||
| 85 | switching up (compare with below possible ondemand sample kick ins (2)):: | ||
| 86 | |||
| 87 | 50 50 50 50ms ->time | ||
| 88 | load -----| |-----| |-----| |-----| | ||
| 89 | | | | | | | | | ||
| 90 | sleep |-----| |-----| |-----| |---- | ||
| 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 | |||
| 96 | You can easily test all kind of load/sleep times and check whether your | ||
| 97 | governor in average behaves as expected. | ||
| 98 | |||
| 99 | |||
| 100 | ToDo | ||
| 101 | ==== | ||
| 102 | |||
| 103 | Provide a gnuplot utility script for easy generation of plots to present | ||
| 104 | the outcome nicely. | ||
| 105 | |||
| 106 | |||
| 107 | cpufreq-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 | |||
| 122 | Due to the high priority, the application may not be responsible for some time. | ||
| 123 | After 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 000000000000..81b1c48607d9 --- /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) \ | ||
| 30 | if (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 | |||
| 45 | unsigned 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 | |||
| 91 | void 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 000000000000..51d7f50ac2bb --- /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 | |||
| 29 | void 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 000000000000..ee6f258e5336 --- /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 000000000000..410021a12f40 --- /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 | |||
| 22 | dir=`mktemp -d` | ||
| 23 | output_file="cpufreq-bench.png" | ||
| 24 | global_title="cpufreq-bench plot" | ||
| 25 | picture_type="jpeg" | ||
| 26 | file[0]="" | ||
| 27 | |||
| 28 | function 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 | |||
| 39 | if [ $# -eq 0 ];then | ||
| 40 | echo "No benchmark results file provided" | ||
| 41 | echo | ||
| 42 | usage | ||
| 43 | fi | ||
| 44 | |||
| 45 | while 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 | ||
| 60 | done | ||
| 61 | shift $(($OPTIND -1)) | ||
| 62 | |||
| 63 | plots=0 | ||
| 64 | while [ "$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)) | ||
| 74 | done | ||
| 75 | |||
| 76 | echo "set terminal $picture_type" >> $dir/plot_script.gpl | ||
| 77 | echo "set output \"$output_file\"" >> $dir/plot_script.gpl | ||
| 78 | echo "set title \"$global_title\"" >> $dir/plot_script.gpl | ||
| 79 | echo "set xlabel \"sleep/load time\"" >> $dir/plot_script.gpl | ||
| 80 | echo "set ylabel \"Performance (%)\"" >> $dir/plot_script.gpl | ||
| 81 | |||
| 82 | for((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 | ||
| 100 | done | ||
| 101 | echo >> $dir/plot_script.gpl | ||
| 102 | |||
| 103 | gnuplot $dir/plot_script.gpl | ||
| 104 | rm -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 000000000000..de20d2a06879 --- /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 | ||
| 28 | UP_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 | ||
| 33 | SAMPLING_RATE="20000 80000" | ||
| 34 | |||
| 35 | function 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 | |||
| 66 | function 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 | |||
| 100 | measure | ||
| 101 | create_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 000000000000..f91f64360688 --- /dev/null +++ b/tools/power/cpupower/bench/example.cfg | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | sleep = 50000 | ||
| 2 | load = 50000 | ||
| 3 | cpu = 0 | ||
| 4 | priority = LOW | ||
| 5 | output = /var/log/cpufreq-bench | ||
| 6 | sleep_step = 50000 | ||
| 7 | load_step = 50000 | ||
| 8 | cycles = 20 | ||
| 9 | rounds = 40 | ||
| 10 | verbose = 0 | ||
| 11 | governor = ondemand | ||
diff --git a/tools/power/cpupower/bench/main.c b/tools/power/cpupower/bench/main.c new file mode 100644 index 000000000000..24910313a521 --- /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 | |||
| 31 | static 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 | |||
| 52 | void 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 | |||
| 76 | int 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 000000000000..543bba14ae2c --- /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 | |||
| 43 | enum 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 | |||
| 64 | FILE *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 | |||
| 123 | struct 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 | |||
| 158 | int 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 000000000000..a8dc632d9eee --- /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 */ | ||
| 21 | struct 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 | |||
| 47 | enum sched_prio string_to_prio(const char *str); | ||
| 48 | |||
| 49 | FILE *prepare_output(const char *dir); | ||
| 50 | |||
| 51 | int prepare_config(const char *path, struct config *config); | ||
| 52 | struct 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 000000000000..f01e3f4be84c --- /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 | |||
| 39 | long 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 | |||
| 58 | int 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 | |||
| 87 | int 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 | |||
| 114 | int 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, ¶m) < 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 | |||
| 138 | void 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 | |||
| 164 | void 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 000000000000..3a8c858b78f0 --- /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 | |||
| 22 | long long get_time(); | ||
| 23 | |||
| 24 | int set_cpufreq_governor(char *governor, unsigned int cpu); | ||
| 25 | int set_cpu_affinity(unsigned int cpu); | ||
| 26 | int set_process_priority(int priority); | ||
| 27 | |||
| 28 | void prepare_user(const struct config *config); | ||
| 29 | void 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 000000000000..d08cc1ead9bc --- /dev/null +++ b/tools/power/cpupower/debug/i386/Makefile | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | default: all | ||
| 2 | |||
| 3 | centrino-decode: centrino-decode.c | ||
| 4 | $(CC) $(CFLAGS) -o centrino-decode centrino-decode.c | ||
| 5 | |||
| 6 | dump_psb: dump_psb.c | ||
| 7 | $(CC) $(CFLAGS) -o dump_psb dump_psb.c | ||
| 8 | |||
| 9 | intel_gsic: intel_gsic.c | ||
| 10 | $(CC) $(CFLAGS) -o intel_gsic -llrmi intel_gsic.c | ||
| 11 | |||
| 12 | powernow-k8-decode: powernow-k8-decode.c | ||
| 13 | $(CC) $(CFLAGS) -o powernow-k8-decode powernow-k8-decode.c | ||
| 14 | |||
| 15 | all: centrino-decode dump_psb intel_gsic powernow-k8-decode | ||
| 16 | |||
| 17 | clean: | ||
| 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 000000000000..7ef24cce4926 --- /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 | |||
| 29 | static 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; | ||
| 58 | err2: | ||
| 59 | close(fd); | ||
| 60 | err1: | ||
| 61 | return retval; | ||
| 62 | } | ||
| 63 | |||
| 64 | static 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 | |||
| 76 | static 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 | |||
| 95 | int 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 000000000000..8d6a47514253 --- /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 | |||
| 24 | static long relevant; | ||
| 25 | |||
| 26 | static 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 | |||
| 33 | static 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 | |||
| 40 | struct 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 | |||
| 49 | struct 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 | |||
| 57 | static u_int fsb; | ||
| 58 | static u_int sgtc; | ||
| 59 | |||
| 60 | static int | ||
| 61 | decode_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 | |||
| 81 | static | ||
| 82 | void 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 | |||
| 130 | next_one: | ||
| 131 | p += sizeof(struct pst_header) + 2*pst->numpstates; | ||
| 132 | } | ||
| 133 | |||
| 134 | } | ||
| 135 | |||
| 136 | static struct option info_opts[] = { | ||
| 137 | {.name = "numpst", .has_arg=no_argument, .flag=NULL, .val='n'}, | ||
| 138 | }; | ||
| 139 | |||
| 140 | void 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 | |||
| 148 | int | ||
| 149 | main(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 000000000000..53f5293c9c9a --- /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 | |||
| 16 | int 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 000000000000..638a6b3bfd97 --- /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 | |||
| 28 | static 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; | ||
| 50 | err1: | ||
| 51 | close(fd); | ||
| 52 | out: | ||
| 53 | return err; | ||
| 54 | } | ||
| 55 | |||
| 56 | |||
| 57 | /* Return a frequency in MHz, given an input fid */ | ||
| 58 | static 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 */ | ||
| 64 | static uint32_t find_millivolts_from_vid(uint32_t vid) | ||
| 65 | { | ||
| 66 | return 1550-vid*25; | ||
| 67 | } | ||
| 68 | |||
| 69 | int 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 000000000000..96b146fe6f8d --- /dev/null +++ b/tools/power/cpupower/debug/kernel/Makefile | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | obj-m := | ||
| 2 | |||
| 3 | KDIR := /lib/modules/$(shell uname -r)/build | ||
| 4 | PWD := $(shell pwd) | ||
| 5 | KMISC := /lib/modules/$(shell uname -r)/cpufrequtils/ | ||
| 6 | |||
| 7 | ifeq ("$(CONFIG_X86_TSC)", "y") | ||
| 8 | obj-m += cpufreq-test_tsc.o | ||
| 9 | endif | ||
| 10 | |||
| 11 | default: | ||
| 12 | $(MAKE) -C $(KDIR) M=$(PWD) | ||
| 13 | |||
| 14 | clean: | ||
| 15 | - rm -rf *.o *.ko .tmp-versions .*.cmd .*.mod.* *.mod.c | ||
| 16 | - rm -rf .tmp_versions* Module.symvers modules.order | ||
| 17 | |||
| 18 | install: default | ||
| 19 | install -d $(KMISC) | ||
| 20 | install -m 644 -c *.ko $(KMISC) | ||
| 21 | /sbin/depmod -a | ||
| 22 | |||
| 23 | all: 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 000000000000..66cace601e57 --- /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 | |||
| 34 | static int pm_tmr_ioport = 0; | ||
| 35 | |||
| 36 | /*helper function to safely read acpi pm timesource*/ | ||
| 37 | static 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 | |||
| 56 | static 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 | |||
| 102 | static void __exit cpufreq_none(void) | ||
| 103 | { | ||
| 104 | return; | ||
| 105 | } | ||
| 106 | |||
| 107 | module_init(cpufreq_test_tsc) | ||
| 108 | module_exit(cpufreq_none) | ||
| 109 | |||
| 110 | |||
| 111 | MODULE_AUTHOR("Dominik Brodowski"); | ||
| 112 | MODULE_DESCRIPTION("Verify the TSC cpufreq notifier working correctly -- needs ACPI-enabled system"); | ||
| 113 | MODULE_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 000000000000..3326217dd311 --- /dev/null +++ b/tools/power/cpupower/debug/x86_64/Makefile | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | default: all | ||
| 2 | |||
| 3 | centrino-decode: ../i386/centrino-decode.c | ||
| 4 | $(CC) $(CFLAGS) -o $@ $< | ||
| 5 | |||
| 6 | powernow-k8-decode: ../i386/powernow-k8-decode.c | ||
| 7 | $(CC) $(CFLAGS) -o $@ $< | ||
| 8 | |||
| 9 | all: centrino-decode powernow-k8-decode | ||
| 10 | |||
| 11 | clean: | ||
| 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 000000000000..d961101d1cea --- /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 | |||
| 16 | int cpufreq_cpu_exists(unsigned int cpu) | ||
| 17 | { | ||
| 18 | return sysfs_cpu_exists(cpu); | ||
| 19 | } | ||
| 20 | |||
| 21 | unsigned long cpufreq_get_freq_kernel(unsigned int cpu) | ||
| 22 | { | ||
| 23 | return sysfs_get_freq_kernel(cpu); | ||
| 24 | } | ||
| 25 | |||
| 26 | unsigned long cpufreq_get_freq_hardware(unsigned int cpu) | ||
| 27 | { | ||
| 28 | return sysfs_get_freq_hardware(cpu); | ||
| 29 | } | ||
| 30 | |||
| 31 | unsigned long cpufreq_get_transition_latency(unsigned int cpu) | ||
| 32 | { | ||
| 33 | return sysfs_get_freq_transition_latency(cpu); | ||
| 34 | } | ||
| 35 | |||
| 36 | int 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 | |||
| 45 | char *cpufreq_get_driver(unsigned int cpu) | ||
| 46 | { | ||
| 47 | return sysfs_get_freq_driver(cpu); | ||
| 48 | } | ||
| 49 | |||
| 50 | void cpufreq_put_driver(char *ptr) | ||
| 51 | { | ||
| 52 | if (!ptr) | ||
| 53 | return; | ||
| 54 | free(ptr); | ||
| 55 | } | ||
| 56 | |||
| 57 | struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu) | ||
| 58 | { | ||
| 59 | return sysfs_get_freq_policy(cpu); | ||
| 60 | } | ||
| 61 | |||
| 62 | void 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 | |||
| 72 | struct cpufreq_available_governors *cpufreq_get_available_governors(unsigned | ||
| 73 | int cpu) | ||
| 74 | { | ||
| 75 | return sysfs_get_freq_available_governors(cpu); | ||
| 76 | } | ||
| 77 | |||
| 78 | void 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 | |||
| 96 | struct cpufreq_available_frequencies | ||
| 97 | *cpufreq_get_available_frequencies(unsigned int cpu) | ||
| 98 | { | ||
| 99 | return sysfs_get_available_frequencies(cpu); | ||
| 100 | } | ||
| 101 | |||
| 102 | void 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 | |||
| 118 | struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned int cpu) | ||
| 119 | { | ||
| 120 | return sysfs_get_freq_affected_cpus(cpu); | ||
| 121 | } | ||
| 122 | |||
| 123 | void 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 | |||
| 139 | struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned int cpu) | ||
| 140 | { | ||
| 141 | return sysfs_get_freq_related_cpus(cpu); | ||
| 142 | } | ||
| 143 | |||
| 144 | void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any) | ||
| 145 | { | ||
| 146 | cpufreq_put_affected_cpus(any); | ||
| 147 | } | ||
| 148 | |||
| 149 | |||
| 150 | int 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 | |||
| 159 | int 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 | |||
| 165 | int 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 | |||
| 171 | int 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 | |||
| 179 | int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency) | ||
| 180 | { | ||
| 181 | return sysfs_set_frequency(cpu, target_frequency); | ||
| 182 | } | ||
| 183 | |||
| 184 | struct 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 | |||
| 190 | void 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 | |||
| 205 | unsigned 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 000000000000..3aae8e7a0839 --- /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 | |||
| 23 | struct cpufreq_policy { | ||
| 24 | unsigned long min; | ||
| 25 | unsigned long max; | ||
| 26 | char *governor; | ||
| 27 | }; | ||
| 28 | |||
| 29 | struct cpufreq_available_governors { | ||
| 30 | char *governor; | ||
| 31 | struct cpufreq_available_governors *next; | ||
| 32 | struct cpufreq_available_governors *first; | ||
| 33 | }; | ||
| 34 | |||
| 35 | struct cpufreq_available_frequencies { | ||
| 36 | unsigned long frequency; | ||
| 37 | struct cpufreq_available_frequencies *next; | ||
| 38 | struct cpufreq_available_frequencies *first; | ||
| 39 | }; | ||
| 40 | |||
| 41 | |||
| 42 | struct cpufreq_affected_cpus { | ||
| 43 | unsigned int cpu; | ||
| 44 | struct cpufreq_affected_cpus *next; | ||
| 45 | struct cpufreq_affected_cpus *first; | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct 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 | ||
| 58 | extern "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 | |||
| 66 | extern 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 | |||
| 76 | extern unsigned long cpufreq_get_freq_kernel(unsigned int cpu); | ||
| 77 | |||
| 78 | extern 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 | */ | ||
| 87 | extern 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 | |||
| 96 | extern 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 | |||
| 107 | extern char *cpufreq_get_driver(unsigned int cpu); | ||
| 108 | |||
| 109 | extern 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 | |||
| 119 | extern struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu); | ||
| 120 | |||
| 121 | extern 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 | |||
| 132 | extern struct cpufreq_available_governors | ||
| 133 | *cpufreq_get_available_governors(unsigned int cpu); | ||
| 134 | |||
| 135 | extern 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 | |||
| 146 | extern struct cpufreq_available_frequencies | ||
| 147 | *cpufreq_get_available_frequencies(unsigned int cpu); | ||
| 148 | |||
| 149 | extern 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 | |||
| 159 | extern struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned | ||
| 160 | int cpu); | ||
| 161 | |||
| 162 | extern 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 | |||
| 171 | extern struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned | ||
| 172 | int cpu); | ||
| 173 | |||
| 174 | extern 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 | |||
| 182 | extern struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu, | ||
| 183 | unsigned long long *total_time); | ||
| 184 | |||
| 185 | extern void cpufreq_put_stats(struct cpufreq_stats *stats); | ||
| 186 | |||
| 187 | extern 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 | |||
| 196 | extern 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 | |||
| 204 | extern int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq); | ||
| 205 | extern int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq); | ||
| 206 | extern 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 | |||
| 216 | extern 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 000000000000..870713a75a81 --- /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 | |||
| 24 | static 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 */ | ||
| 50 | static 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 */ | ||
| 62 | static 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 | |||
| 90 | enum 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 | |||
| 102 | static 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 | |||
| 114 | static 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 | |||
| 141 | enum cpufreq_string { | ||
| 142 | SCALING_DRIVER, | ||
| 143 | SCALING_GOVERNOR, | ||
| 144 | MAX_CPUFREQ_STRING_FILES | ||
| 145 | }; | ||
| 146 | |||
| 147 | static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = { | ||
| 148 | [SCALING_DRIVER] = "scaling_driver", | ||
| 149 | [SCALING_GOVERNOR] = "scaling_governor", | ||
| 150 | }; | ||
| 151 | |||
| 152 | |||
| 153 | static 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 | |||
| 180 | enum 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 | |||
| 188 | static 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 | |||
| 195 | static 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 | |||
| 209 | unsigned long sysfs_get_freq_kernel(unsigned int cpu) | ||
| 210 | { | ||
| 211 | return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ); | ||
| 212 | } | ||
| 213 | |||
| 214 | unsigned long sysfs_get_freq_hardware(unsigned int cpu) | ||
| 215 | { | ||
| 216 | return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ); | ||
| 217 | } | ||
| 218 | |||
| 219 | unsigned long sysfs_get_freq_transition_latency(unsigned int cpu) | ||
| 220 | { | ||
| 221 | return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY); | ||
| 222 | } | ||
| 223 | |||
| 224 | int 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 | |||
| 242 | char *sysfs_get_freq_driver(unsigned int cpu) | ||
| 243 | { | ||
| 244 | return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER); | ||
| 245 | } | ||
| 246 | |||
| 247 | struct 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 | |||
| 271 | struct cpufreq_available_governors * | ||
| 272 | sysfs_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 | |||
| 327 | struct cpufreq_available_frequencies * | ||
| 328 | sysfs_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", ¤t->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 | |||
| 382 | static 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", ¤t->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 | |||
| 438 | struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(unsigned int cpu) | ||
| 439 | { | ||
| 440 | return sysfs_get_cpu_list(cpu, "affected_cpus"); | ||
| 441 | } | ||
| 442 | |||
| 443 | struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(unsigned int cpu) | ||
| 444 | { | ||
| 445 | return sysfs_get_cpu_list(cpu, "related_cpus"); | ||
| 446 | } | ||
| 447 | |||
| 448 | struct 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 | ¤t->frequency, | ||
| 488 | ¤t->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 | |||
| 507 | unsigned long sysfs_get_freq_transitions(unsigned int cpu) | ||
| 508 | { | ||
| 509 | return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS); | ||
| 510 | } | ||
| 511 | |||
| 512 | static 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 | |||
| 547 | int 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 | |||
| 561 | int 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 | |||
| 572 | int 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 | |||
| 583 | int 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 | |||
| 630 | int 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 **************************************************/ | ||
| 659 | int 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 000000000000..c76a5e0af501 --- /dev/null +++ b/tools/power/cpupower/lib/sysfs.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | /* General */ | ||
| 2 | extern unsigned int sysfs_cpu_exists(unsigned int cpu); | ||
| 3 | |||
| 4 | /* CPUfreq */ | ||
| 5 | extern unsigned long sysfs_get_freq_kernel(unsigned int cpu); | ||
| 6 | extern unsigned long sysfs_get_freq_hardware(unsigned int cpu); | ||
| 7 | extern unsigned long sysfs_get_freq_transition_latency(unsigned int cpu); | ||
| 8 | extern int sysfs_get_freq_hardware_limits(unsigned int cpu, | ||
| 9 | unsigned long *min, unsigned long *max); | ||
| 10 | extern char *sysfs_get_freq_driver(unsigned int cpu); | ||
| 11 | extern struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu); | ||
| 12 | extern struct cpufreq_available_governors *sysfs_get_freq_available_governors( | ||
| 13 | unsigned int cpu); | ||
| 14 | extern struct cpufreq_available_frequencies *sysfs_get_available_frequencies( | ||
| 15 | unsigned int cpu); | ||
| 16 | extern struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus( | ||
| 17 | unsigned int cpu); | ||
| 18 | extern struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus( | ||
| 19 | unsigned int cpu); | ||
| 20 | extern struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu, | ||
| 21 | unsigned long long *total_time); | ||
| 22 | extern unsigned long sysfs_get_freq_transitions(unsigned int cpu); | ||
| 23 | extern int sysfs_set_freq_policy(unsigned int cpu, | ||
| 24 | struct cpufreq_policy *policy); | ||
| 25 | extern int sysfs_modify_freq_policy_min(unsigned int cpu, | ||
| 26 | unsigned long min_freq); | ||
| 27 | extern int sysfs_modify_freq_policy_max(unsigned int cpu, | ||
| 28 | unsigned long max_freq); | ||
| 29 | extern int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor); | ||
| 30 | extern 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 000000000000..bb60a8d1e45a --- /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 | ||
| 4 | cpupower frequency\-info \- Utility to retrieve cpufreq kernel information | ||
| 5 | .SH "SYNTAX" | ||
| 6 | .LP | ||
| 7 | cpupower [ \-c cpulist ] frequency\-info [\fIoptions\fP] | ||
| 8 | .SH "DESCRIPTION" | ||
| 9 | .LP | ||
| 10 | A 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 | ||
| 15 | Prints out debug information. | ||
| 16 | .TP | ||
| 17 | \fB\-f\fR \fB\-\-freq\fR | ||
| 18 | Get frequency the CPU currently runs at, according to the cpufreq core. | ||
| 19 | .TP | ||
| 20 | \fB\-w\fR \fB\-\-hwfreq\fR | ||
| 21 | Get frequency the CPU currently runs at, by reading it from hardware (only available to root). | ||
| 22 | .TP | ||
| 23 | \fB\-l\fR \fB\-\-hwlimits\fR | ||
| 24 | Determine the minimum and maximum CPU frequency allowed. | ||
| 25 | .TP | ||
| 26 | \fB\-d\fR \fB\-\-driver\fR | ||
| 27 | Determines the used cpufreq kernel driver. | ||
| 28 | .TP | ||
| 29 | \fB\-p\fR \fB\-\-policy\fR | ||
| 30 | Gets the currently used cpufreq policy. | ||
| 31 | .TP | ||
| 32 | \fB\-g\fR \fB\-\-governors\fR | ||
| 33 | Determines available cpufreq governors. | ||
| 34 | .TP | ||
| 35 | \fB\-a\fR \fB\-\-related\-cpus\fR | ||
| 36 | Determines which CPUs run at the same hardware frequency. | ||
| 37 | .TP | ||
| 38 | \fB\-a\fR \fB\-\-affected\-cpus\fR | ||
| 39 | Determines which CPUs need to have their frequency coordinated by software. | ||
| 40 | .TP | ||
| 41 | \fB\-s\fR \fB\-\-stats\fR | ||
| 42 | Shows cpufreq statistics if available. | ||
| 43 | .TP | ||
| 44 | \fB\-y\fR \fB\-\-latency\fR | ||
| 45 | Determines the maximum latency on CPU frequency changes. | ||
| 46 | .TP | ||
| 47 | \fB\-o\fR \fB\-\-proc\fR | ||
| 48 | Prints 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 | ||
| 51 | human\-readable output for the \-f, \-w, \-s and \-y parameters. | ||
| 52 | .TP | ||
| 53 | \fB\-h\fR \fB\-\-help\fR | ||
| 54 | Prints out the help screen. | ||
| 55 | .SH "REMARKS" | ||
| 56 | .LP | ||
| 57 | By default only values of core zero are displayed. How to display settings of | ||
| 58 | other cores is described in the cpupower(1) manpage in the \-\-cpu option section. | ||
| 59 | .LP | ||
| 60 | You can't specify more than one of the output specific options \-o \-e \-a \-g \-p \-d \-l \-w \-f \-y. | ||
| 61 | .LP | ||
| 62 | You 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 | ||
| 71 | Dominik Brodowski <linux@brodo.de> \- author | ||
| 72 | Mattia Dongili<malattia@gmail.com> \- first autolibtoolization | ||
| 73 | .fi | ||
| 74 | .SH "SEE ALSO" | ||
| 75 | .LP | ||
| 76 | cpupower\-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 000000000000..685f469093ad --- /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 | ||
| 4 | cpupower frequency\-set \- A small tool which allows to modify cpufreq settings. | ||
| 5 | .SH "SYNTAX" | ||
| 6 | .LP | ||
| 7 | cpupower [ \-c cpu ] frequency\-set [\fIoptions\fP] | ||
| 8 | .SH "DESCRIPTION" | ||
| 9 | .LP | ||
| 10 | cpupower 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> | ||
| 15 | new minimum CPU frequency the governor may select. | ||
| 16 | .TP | ||
| 17 | \fB\-u\fR \fB\-\-max\fR <FREQ> | ||
| 18 | new maximum CPU frequency the governor may select. | ||
| 19 | .TP | ||
| 20 | \fB\-g\fR \fB\-\-governor\fR <GOV> | ||
| 21 | new cpufreq governor. | ||
| 22 | .TP | ||
| 23 | \fB\-f\fR \fB\-\-freq\fR <FREQ> | ||
| 24 | specific frequency to be set. Requires userspace governor to be available and loaded. | ||
| 25 | .TP | ||
| 26 | \fB\-r\fR \fB\-\-related\fR | ||
| 27 | modify all hardware-related CPUs at the same time | ||
| 28 | .TP | ||
| 29 | \fB\-h\fR \fB\-\-help\fR | ||
| 30 | Prints out the help screen. | ||
| 31 | .SH "REMARKS" | ||
| 32 | .LP | ||
| 33 | By default values are applied on all cores. How to modify single core | ||
| 34 | configurations is described in the cpupower(1) manpage in the \-\-cpu option section. | ||
| 35 | .LP | ||
| 36 | The \-f FREQ, \-\-freq FREQ parameter cannot be combined with any other parameter. | ||
| 37 | .LP | ||
| 38 | FREQuencies 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 | ||
| 40 | On 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 | ||
| 49 | Dominik Brodowski <linux@brodo.de> \- author | ||
| 50 | Mattia Dongili<malattia@gmail.com> \- first autolibtoolization | ||
| 51 | .fi | ||
| 52 | .SH "SEE ALSO" | ||
| 53 | .LP | ||
| 54 | cpupower\-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 000000000000..58e21196f17f --- /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 | ||
| 3 | cpupower\-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 | ||
| 10 | registers affecting processor power saving policies. | ||
| 11 | |||
| 12 | Some options are platform wide, some affect single cores. By default values | ||
| 13 | of core zero are displayed only. cpupower --cpu all cpuinfo will show the | ||
| 14 | settings of all cores, see cpupower(1) how to choose specific cores. | ||
| 15 | |||
| 16 | .SH "SEE ALSO" | ||
| 17 | Options are described in detail in: | ||
| 18 | |||
| 19 | cpupower(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 000000000000..d5cfa265c3d3 --- /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 | ||
| 3 | cpupower\-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 | ||
| 19 | state statistics. Either \fBcommand\fP is forked and | ||
| 20 | statistics are printed upon its completion, or statistics are printed periodically. | ||
| 21 | |||
| 22 | \fBcpupower-monitor \fP implements independent processor sleep state and | ||
| 23 | frequency counters. Some are retrieved from kernel statistics, some are | ||
| 24 | directly reading out hardware registers. Use \-l to get an overview which are | ||
| 25 | supported on your system. | ||
| 26 | |||
| 27 | .SH Options | ||
| 28 | .PP | ||
| 29 | \-l | ||
| 30 | .RS 4 | ||
| 31 | List available monitors on your system. Additional details about each monitor | ||
| 32 | are shown: | ||
| 33 | .RS 2 | ||
| 34 | .IP \(bu | ||
| 35 | The name in quotation marks which can be passed to the \-m parameter. | ||
| 36 | .IP \(bu | ||
| 37 | The number of different counters the monitor supports in brackets. | ||
| 38 | .IP \(bu | ||
| 39 | The amount of time in seconds the counters might overflow, due to | ||
| 40 | implementation constraints. | ||
| 41 | .IP \(bu | ||
| 42 | The name and a description of each counter and its processor hierarchy level | ||
| 43 | coverage 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 | ||
| 59 | Only display specific monitors. Use the monitor string(s) provided by \-l option. | ||
| 60 | .RE | ||
| 61 | .PP | ||
| 62 | \-i seconds | ||
| 63 | .RS 4 | ||
| 64 | Measure intervall. | ||
| 65 | .RE | ||
| 66 | .PP | ||
| 67 | command | ||
| 68 | .RS 4 | ||
| 69 | Measure idle and frequency characteristics of an arbitrary command/workload. | ||
| 70 | The executable \fBcommand\fP is forked and upon its exit, statistics gathered since it was | ||
| 71 | forked are displayed. | ||
| 72 | .RE | ||
| 73 | .PP | ||
| 74 | \-v | ||
| 75 | .RS 4 | ||
| 76 | Increase verbosity if the binary was compiled with the DEBUG option set. | ||
| 77 | .RE | ||
| 78 | |||
| 79 | .SH MONITOR DESCRIPTIONS | ||
| 80 | .SS "Idle_Stats" | ||
| 81 | Shows statistics of the cpuidle kernel subsystem. Values are retrieved from | ||
| 82 | /sys/devices/system/cpu/cpu*/cpuidle/state*/. | ||
| 83 | The kernel updates these values every time an idle state is entered or | ||
| 84 | left. Therefore there can be some inaccuracy when cores are in an idle | ||
| 85 | state for some time when the measure starts or ends. In worst case it can happen | ||
| 86 | that one core stayed in an idle state for the whole measure time and the idle | ||
| 87 | state usage time as exported by the kernel did not get updated. In this case | ||
| 88 | a state residency of 0 percent is shown while it was 100. | ||
| 89 | |||
| 90 | .SS "Mperf" | ||
| 91 | The name comes from the aperf/mperf (average and maximum) MSR registers used | ||
| 92 | which are available on recent X86 processors. It shows the average frequency | ||
| 93 | (including boost frequencies). | ||
| 94 | The fact that on all recent hardware the mperf timer stops ticking in any idle | ||
| 95 | state it is also used to show C0 (processor is active) and Cx (processor is in | ||
| 96 | any sleep state) times. These counters do not have the inaccuracy restrictions | ||
| 97 | the "Idle_Stats" counters may show. | ||
| 98 | May work poorly on Linux-2.6.20 through 2.6.29, as the \fBacpi-cpufreq \fP | ||
| 99 | kernel frequency driver periodically cleared aperf/mperf registers in those | ||
| 100 | kernels. | ||
| 101 | |||
| 102 | .SS "Nehalem" "SandyBridge" | ||
| 103 | Intel Core and Package sleep state counters. | ||
| 104 | Threads (hyperthreaded cores) may not be able to enter deeper core states if | ||
| 105 | its sibling is utilized. | ||
| 106 | Deepest package sleep states may in reality show up as machine/platform wide | ||
| 107 | sleep states and can only be entered if all cores are idle. Look up Intel | ||
| 108 | manuals (some are provided in the References section) for further details. | ||
| 109 | |||
| 110 | .SS "Ontario" "Liano" | ||
| 111 | AMD laptop and desktop processor (family 12h and 14h) sleep state counters. | ||
| 112 | The registers are accessed via PCI and therefore can still be read out while | ||
| 113 | cores have been offlined. | ||
| 114 | |||
| 115 | There is one special counter: NBP1 (North Bridge P1). | ||
| 116 | This one always returns 0 or 1, depending on whether the North Bridge P1 | ||
| 117 | power state got entered at least once during measure time. | ||
| 118 | Being able to enter NBP1 state also depends on graphics power management. | ||
| 119 | Therefore this counter can be used to verify whether the graphics' driver | ||
| 120 | power management is working as expected. | ||
| 121 | |||
| 122 | .SH EXAMPLES | ||
| 123 | |||
| 124 | cpupower monitor -l" may show: | ||
| 125 | .RS 4 | ||
| 126 | Monitor "Mperf" (3 states) \- Might overflow after 922000000 s | ||
| 127 | |||
| 128 | ... | ||
| 129 | |||
| 130 | Monitor "Idle_Stats" (3 states) \- Might overflow after 4294967295 s | ||
| 131 | |||
| 132 | ... | ||
| 133 | |||
| 134 | .RE | ||
| 135 | cpupower monitor \-m "Idle_Stats,Mperf" scp /tmp/test /nfs/tmp | ||
| 136 | |||
| 137 | Monitor the scp command, show both Mperf and Idle_Stats states counter | ||
| 138 | statistics, but in exchanged order. | ||
| 139 | |||
| 140 | |||
| 141 | |||
| 142 | .RE | ||
| 143 | Be careful that the typical command to fully utilize one CPU by doing: | ||
| 144 | |||
| 145 | cpupower monitor cat /dev/zero >/dev/null | ||
| 146 | |||
| 147 | Does 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 | ||
| 149 | shell script. Hit CTRL\-c to terminate the command and get the measure output | ||
| 150 | displayed. | ||
| 151 | |||
| 152 | .SH REFERENCES | ||
| 153 | "BIOS and Kernel Developer’s Guide (BKDG) for AMD Family 14h Processors" | ||
| 154 | http://support.amd.com/us/Processor_TechDocs/43170.pdf | ||
| 155 | |||
| 156 | "Intel® Turbo Boost Technology | ||
| 157 | in Intel® Core™ Microarchitecture (Nehalem) Based Processors" | ||
| 158 | http://download.intel.com/design/processor/applnots/320354.pdf | ||
| 159 | |||
| 160 | "Intel® 64 and IA-32 Architectures Software Developer's Manual | ||
| 161 | Volume 3B: System Programming Guide" | ||
| 162 | http://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" | ||
| 172 | powertop(8), msr(4), vmstat(8) | ||
| 173 | .PP | ||
| 174 | .SH AUTHORS | ||
| 175 | .nf | ||
| 176 | Written by Thomas Renninger <trenn@suse.de> | ||
| 177 | |||
| 178 | Nehalem, SandyBridge monitors and command passing | ||
| 179 | based 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 000000000000..c4954a9fe4e7 --- /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 | ||
| 3 | cpupower\-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 | ||
| 11 | registers affecting processor power saving policies. | ||
| 12 | |||
| 13 | Some options are platform wide, some affect single cores. By default values | ||
| 14 | are applied on all cores. How to modify single core configurations is | ||
| 15 | described in the cpupower(1) manpage in the \-\-cpu option section. Whether an | ||
| 16 | option affects the whole system or can be applied to individual cores is | ||
| 17 | described in the Options sections. | ||
| 18 | |||
| 19 | Use \fBcpupower info \fP to read out current settings and whether they are | ||
| 20 | supported on the system at all. | ||
| 21 | |||
| 22 | .SH Options | ||
| 23 | .PP | ||
| 24 | \-\-perf-bias, \-b | ||
| 25 | .RS 4 | ||
| 26 | Sets a register on supported Intel processore which allows software to convey | ||
| 27 | its policy for the relative importance of performance versus energy savings to | ||
| 28 | the processor. | ||
| 29 | |||
| 30 | The range of valid numbers is 0-15, where 0 is maximum | ||
| 31 | performance and 15 is maximum energy efficiency. | ||
| 32 | |||
| 33 | The processor uses this information in model-specific ways | ||
| 34 | when it must select trade-offs between performance and | ||
| 35 | energy efficiency. | ||
| 36 | |||
| 37 | This policy hint does not supersede Processor Performance states | ||
| 38 | (P-states) or CPU Idle power states (C-states), but allows | ||
| 39 | software to have influence where it would otherwise be unable | ||
| 40 | to express a preference. | ||
| 41 | |||
| 42 | For example, this setting may tell the hardware how | ||
| 43 | aggressively or conservatively to control frequency | ||
| 44 | in the "turbo range" above the explicitly OS-controlled | ||
| 45 | P-state frequency range. It may also tell the hardware | ||
| 46 | how aggressively it should enter the OS requested C-states. | ||
| 47 | |||
| 48 | This option can be applied to individual cores only via the \-\-cpu option, | ||
| 49 | cpupower(1). | ||
| 50 | |||
| 51 | Setting the performance bias value on one CPU can modify the setting on | ||
| 52 | related CPUs as well (for example all CPUs on one socket), because of | ||
| 53 | hardware restrictions. | ||
| 54 | Use \fBcpupower -c all info -b\fP to verify. | ||
| 55 | |||
| 56 | This 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 | ||
| 64 | processes are scheduled to other processor packages/sockets. | ||
| 65 | |||
| 66 | \-\-sched\-smt utilizes thread siblings of one processor core first before | ||
| 67 | processes are scheduled to other cores. | ||
| 68 | |||
| 69 | The impact on power consumption and performance (positiv or negativ) heavily | ||
| 70 | depends on processor support for deep sleep states, frequency scaling and | ||
| 71 | frequency boost modes and their dependencies between other thread siblings | ||
| 72 | and processor cores. | ||
| 73 | |||
| 74 | Taken over from kernel documentation: | ||
| 75 | |||
| 76 | Adjust the kernel's multi-core scheduler support. | ||
| 77 | |||
| 78 | Possible values are: | ||
| 79 | .RS 2 | ||
| 80 | 0 - No power saving load balance (default value) | ||
| 81 | |||
| 82 | 1 - Fill one thread/core/package first for long running threads | ||
| 83 | |||
| 84 | 2 - Also bias task wakeups to semi-idle cpu package for power | ||
| 85 | savings | ||
| 86 | .RE | ||
| 87 | |||
| 88 | sched_mc_power_savings is dependent upon SCHED_MC, which is | ||
| 89 | itself architecture dependent. | ||
| 90 | |||
| 91 | sched_smt_power_savings is dependent upon SCHED_SMT, which | ||
| 92 | is itself architecture dependent. | ||
| 93 | |||
| 94 | The two files are independent of each other. It is possible | ||
| 95 | that one file may be present without the other. | ||
| 96 | |||
| 97 | .SH "SEE ALSO" | ||
| 98 | cpupower-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> | ||
| 103 | Thomas 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 000000000000..baf741d06e82 --- /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 | ||
| 3 | cpupower \- 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 | ||
| 14 | related features of your processor. | ||
| 15 | |||
| 16 | The manpages of the commands (cpupower\-<command>(1)) provide detailed | ||
| 17 | descriptions of supported features. Run \fBcpupower help\fP to get an overview | ||
| 18 | of supported commands. | ||
| 19 | |||
| 20 | .SH Options | ||
| 21 | .PP | ||
| 22 | \-\-help, \-h | ||
| 23 | .RS 4 | ||
| 24 | Shows supported commands and general usage. | ||
| 25 | .RE | ||
| 26 | .PP | ||
| 27 | \-\-cpu cpulist, \-c cpulist | ||
| 28 | .RS 4 | ||
| 29 | Only show or set values for specific cores. | ||
| 30 | This option is not supported by all commands, details can be found in the | ||
| 31 | manpages of the commands. | ||
| 32 | |||
| 33 | Some commands access all cores (typically the *\-set commands), some only | ||
| 34 | the first core (typically the *\-info commands) by default. | ||
| 35 | |||
| 36 | The syntax for <cpulist> is based on how the kernel exports CPU bitmasks via | ||
| 37 | sysfs files. Some examples: | ||
| 38 | .RS 4 | ||
| 39 | .TP 16 | ||
| 40 | Input | ||
| 41 | Equivalent to | ||
| 42 | .TP | ||
| 43 | all | ||
| 44 | all cores | ||
| 45 | .TP | ||
| 46 | 0\-3 | ||
| 47 | 0,1,2,3 | ||
| 48 | .TP | ||
| 49 | 0\-7:2 | ||
| 50 | 0,2,4,6 | ||
| 51 | .TP | ||
| 52 | 1,3,5-7 | ||
| 53 | 1,3,5,6,7 | ||
| 54 | .TP | ||
| 55 | 0\-3:2,8\-15:4 | ||
| 56 | 0,2,8,12 | ||
| 57 | .RE | ||
| 58 | .RE | ||
| 59 | .PP | ||
| 60 | \-\-version, \-v | ||
| 61 | .RS 4 | ||
| 62 | Print the package name and version number. | ||
| 63 | |||
| 64 | .SH "SEE ALSO" | ||
| 65 | cpupower-set(1), cpupower-info(1), cpupower-idle(1), | ||
| 66 | cpupower-frequency-set(1), cpupower-frequency-info(1), cpupower-monitor(1), | ||
| 67 | powertop(1) | ||
| 68 | .PP | ||
| 69 | .SH AUTHORS | ||
| 70 | .nf | ||
| 71 | \-\-perf\-bias parts written by Len Brown <len.brown@intel.com> | ||
| 72 | Thomas 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 000000000000..cb22c45c5069 --- /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. | ||
| 8 | msgid "" | ||
| 9 | msgstr "" | ||
| 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 | ||
| 24 | msgid "Processor Core C3" | ||
| 25 | msgstr "" | ||
| 26 | |||
| 27 | #: utils/idle_monitor/nhm_idle.c:43 | ||
| 28 | msgid "Processor Core C6" | ||
| 29 | msgstr "" | ||
| 30 | |||
| 31 | #: utils/idle_monitor/nhm_idle.c:51 | ||
| 32 | msgid "Processor Package C3" | ||
| 33 | msgstr "" | ||
| 34 | |||
| 35 | #: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70 | ||
| 36 | msgid "Processor Package C6" | ||
| 37 | msgstr "" | ||
| 38 | |||
| 39 | #: utils/idle_monitor/snb_idle.c:33 | ||
| 40 | msgid "Processor Core C7" | ||
| 41 | msgstr "" | ||
| 42 | |||
| 43 | #: utils/idle_monitor/snb_idle.c:40 | ||
| 44 | msgid "Processor Package C2" | ||
| 45 | msgstr "" | ||
| 46 | |||
| 47 | #: utils/idle_monitor/snb_idle.c:47 | ||
| 48 | msgid "Processor Package C7" | ||
| 49 | msgstr "" | ||
| 50 | |||
| 51 | #: utils/idle_monitor/amd_fam14h_idle.c:56 | ||
| 52 | msgid "Package in sleep state (PC1 or deeper)" | ||
| 53 | msgstr "" | ||
| 54 | |||
| 55 | #: utils/idle_monitor/amd_fam14h_idle.c:63 | ||
| 56 | msgid "Processor Package C1" | ||
| 57 | msgstr "" | ||
| 58 | |||
| 59 | #: utils/idle_monitor/amd_fam14h_idle.c:77 | ||
| 60 | msgid "North Bridge P1 boolean counter (returns 0 or 1)" | ||
| 61 | msgstr "" | ||
| 62 | |||
| 63 | #: utils/idle_monitor/mperf_monitor.c:35 | ||
| 64 | msgid "Processor Core not idle" | ||
| 65 | msgstr "" | ||
| 66 | |||
| 67 | #: utils/idle_monitor/mperf_monitor.c:42 | ||
| 68 | msgid "Processor Core in an idle state" | ||
| 69 | msgstr "" | ||
| 70 | |||
| 71 | #: utils/idle_monitor/mperf_monitor.c:50 | ||
| 72 | msgid "Average Frequency (including boost) in MHz" | ||
| 73 | msgstr "" | ||
| 74 | |||
| 75 | #: utils/idle_monitor/cpupower-monitor.c:66 | ||
| 76 | #, c-format | ||
| 77 | msgid "" | ||
| 78 | "cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " | ||
| 79 | "interval_sec | -c command ...]\n" | ||
| 80 | msgstr "" | ||
| 81 | |||
| 82 | #: utils/idle_monitor/cpupower-monitor.c:69 | ||
| 83 | #, c-format | ||
| 84 | msgid "" | ||
| 85 | "cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " | ||
| 86 | "interval_sec | -c command ...]\n" | ||
| 87 | msgstr "" | ||
| 88 | |||
| 89 | #: utils/idle_monitor/cpupower-monitor.c:71 | ||
| 90 | #, c-format | ||
| 91 | msgid "\t -v: be more verbose\n" | ||
| 92 | msgstr "" | ||
| 93 | |||
| 94 | #: utils/idle_monitor/cpupower-monitor.c:73 | ||
| 95 | #, c-format | ||
| 96 | msgid "\t -h: print this help\n" | ||
| 97 | msgstr "" | ||
| 98 | |||
| 99 | #: utils/idle_monitor/cpupower-monitor.c:74 | ||
| 100 | #, c-format | ||
| 101 | msgid "\t -i: time intervall to measure for in seconds (default 1)\n" | ||
| 102 | msgstr "" | ||
| 103 | |||
| 104 | #: utils/idle_monitor/cpupower-monitor.c:75 | ||
| 105 | #, c-format | ||
| 106 | msgid "\t -t: show CPU topology/hierarchy\n" | ||
| 107 | msgstr "" | ||
| 108 | |||
| 109 | #: utils/idle_monitor/cpupower-monitor.c:76 | ||
| 110 | #, c-format | ||
| 111 | msgid "\t -l: list available CPU sleep monitors (for use with -m)\n" | ||
| 112 | msgstr "" | ||
| 113 | |||
| 114 | #: utils/idle_monitor/cpupower-monitor.c:77 | ||
| 115 | #, c-format | ||
| 116 | msgid "\t -m: show specific CPU sleep monitors only (in same order)\n" | ||
| 117 | msgstr "" | ||
| 118 | |||
| 119 | #: utils/idle_monitor/cpupower-monitor.c:79 | ||
| 120 | #, c-format | ||
| 121 | msgid "" | ||
| 122 | "only one of: -t, -l, -m are allowed\n" | ||
| 123 | "If none of them is passed," | ||
| 124 | msgstr "" | ||
| 125 | |||
| 126 | #: utils/idle_monitor/cpupower-monitor.c:80 | ||
| 127 | #, c-format | ||
| 128 | msgid " all supported monitors are shown\n" | ||
| 129 | msgstr "" | ||
| 130 | |||
| 131 | #: utils/idle_monitor/cpupower-monitor.c:197 | ||
| 132 | #, c-format | ||
| 133 | msgid "Monitor %s, Counter %s has no count function. Implementation error\n" | ||
| 134 | msgstr "" | ||
| 135 | |||
| 136 | #: utils/idle_monitor/cpupower-monitor.c:207 | ||
| 137 | #, c-format | ||
| 138 | msgid " *is offline\n" | ||
| 139 | msgstr "" | ||
| 140 | |||
| 141 | #: utils/idle_monitor/cpupower-monitor.c:236 | ||
| 142 | #, c-format | ||
| 143 | msgid "%s: max monitor name length (%d) exceeded\n" | ||
| 144 | msgstr "" | ||
| 145 | |||
| 146 | #: utils/idle_monitor/cpupower-monitor.c:250 | ||
| 147 | #, c-format | ||
| 148 | msgid "No matching monitor found in %s, try -l option\n" | ||
| 149 | msgstr "" | ||
| 150 | |||
| 151 | #: utils/idle_monitor/cpupower-monitor.c:266 | ||
| 152 | #, c-format | ||
| 153 | msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n" | ||
| 154 | msgstr "" | ||
| 155 | |||
| 156 | #: utils/idle_monitor/cpupower-monitor.c:319 | ||
| 157 | #, c-format | ||
| 158 | msgid "%s took %.5f seconds and exited with status %d\n" | ||
| 159 | msgstr "" | ||
| 160 | |||
| 161 | #: utils/idle_monitor/cpupower-monitor.c:406 | ||
| 162 | #, c-format | ||
| 163 | msgid "Cannot read number of available processors\n" | ||
| 164 | msgstr "" | ||
| 165 | |||
| 166 | #: utils/idle_monitor/cpupower-monitor.c:417 | ||
| 167 | #, c-format | ||
| 168 | msgid "Available monitor %s needs root access\n" | ||
| 169 | msgstr "" | ||
| 170 | |||
| 171 | #: utils/idle_monitor/cpupower-monitor.c:428 | ||
| 172 | #, c-format | ||
| 173 | msgid "No HW Cstate monitors found\n" | ||
| 174 | msgstr "" | ||
| 175 | |||
| 176 | #: utils/cpupower.c:78 | ||
| 177 | #, c-format | ||
| 178 | msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n" | ||
| 179 | msgstr "" | ||
| 180 | |||
| 181 | #: utils/cpupower.c:79 | ||
| 182 | #, c-format | ||
| 183 | msgid "cpupower --version\n" | ||
| 184 | msgstr "" | ||
| 185 | |||
| 186 | #: utils/cpupower.c:80 | ||
| 187 | #, c-format | ||
| 188 | msgid "Supported subcommands are:\n" | ||
| 189 | msgstr "" | ||
| 190 | |||
| 191 | #: utils/cpupower.c:83 | ||
| 192 | #, c-format | ||
| 193 | msgid "" | ||
| 194 | "\n" | ||
| 195 | "Some subcommands can make use of the -c cpulist option.\n" | ||
| 196 | msgstr "" | ||
| 197 | |||
| 198 | #: utils/cpupower.c:84 | ||
| 199 | #, c-format | ||
| 200 | msgid "Look at the general cpupower manpage how to use it\n" | ||
| 201 | msgstr "" | ||
| 202 | |||
| 203 | #: utils/cpupower.c:85 | ||
| 204 | #, c-format | ||
| 205 | msgid "and read up the subcommand's manpage whether it is supported.\n" | ||
| 206 | msgstr "" | ||
| 207 | |||
| 208 | #: utils/cpupower.c:86 | ||
| 209 | #, c-format | ||
| 210 | msgid "" | ||
| 211 | "\n" | ||
| 212 | "Use cpupower help subcommand for getting help for above subcommands.\n" | ||
| 213 | msgstr "" | ||
| 214 | |||
| 215 | #: utils/cpupower.c:91 | ||
| 216 | #, c-format | ||
| 217 | msgid "Report errors and bugs to %s, please.\n" | ||
| 218 | msgstr "" | ||
| 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 | ||
| 224 | msgid "Error parsing cpu list\n" | ||
| 225 | msgstr "" | ||
| 226 | |||
| 227 | #: utils/cpupower.c:172 | ||
| 228 | #, c-format | ||
| 229 | msgid "Subcommand %s needs root privileges\n" | ||
| 230 | msgstr "" | ||
| 231 | |||
| 232 | #: utils/cpufreq-info.c:31 | ||
| 233 | #, c-format | ||
| 234 | msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n" | ||
| 235 | msgstr "Nelze zjistit poÄet CPU (%s: %s), pÅ™edpokládá se 1.\n" | ||
| 236 | |||
| 237 | #: utils/cpufreq-info.c:63 | ||
| 238 | #, c-format | ||
| 239 | msgid "" | ||
| 240 | " minimum CPU frequency - maximum CPU frequency - governor\n" | ||
| 241 | msgstr "" | ||
| 242 | " minimálnà frekvence CPU - maximálnà frekvence CPU - regulátor\n" | ||
| 243 | |||
| 244 | #: utils/cpufreq-info.c:151 | ||
| 245 | #, c-format | ||
| 246 | msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n" | ||
| 247 | msgstr "" | ||
| 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 | ||
| 256 | msgid " boost state support: \n" | ||
| 257 | msgstr "" | ||
| 258 | |||
| 259 | #: utils/cpufreq-info.c:163 | ||
| 260 | #, c-format | ||
| 261 | msgid " Supported: %s\n" | ||
| 262 | msgstr "" | ||
| 263 | |||
| 264 | #: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 | ||
| 265 | msgid "yes" | ||
| 266 | msgstr "" | ||
| 267 | |||
| 268 | #: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 | ||
| 269 | msgid "no" | ||
| 270 | msgstr "" | ||
| 271 | |||
| 272 | #: utils/cpufreq-info.c:164 | ||
| 273 | #, fuzzy, c-format | ||
| 274 | msgid " Active: %s\n" | ||
| 275 | msgstr " ovladaÄ: %s\n" | ||
| 276 | |||
| 277 | #: utils/cpufreq-info.c:177 | ||
| 278 | #, c-format | ||
| 279 | msgid " Boost States: %d\n" | ||
| 280 | msgstr "" | ||
| 281 | |||
| 282 | #: utils/cpufreq-info.c:178 | ||
| 283 | #, c-format | ||
| 284 | msgid " Total States: %d\n" | ||
| 285 | msgstr "" | ||
| 286 | |||
| 287 | #: utils/cpufreq-info.c:181 | ||
| 288 | #, c-format | ||
| 289 | msgid " Pstate-Pb%d: %luMHz (boost state)\n" | ||
| 290 | msgstr "" | ||
| 291 | |||
| 292 | #: utils/cpufreq-info.c:184 | ||
| 293 | #, c-format | ||
| 294 | msgid " Pstate-P%d: %luMHz\n" | ||
| 295 | msgstr "" | ||
| 296 | |||
| 297 | #: utils/cpufreq-info.c:211 | ||
| 298 | #, c-format | ||
| 299 | msgid " no or unknown cpufreq driver is active on this CPU\n" | ||
| 300 | msgstr " pro tento CPU nenà aktivnà žádný známý ovladaÄ cpufreq\n" | ||
| 301 | |||
| 302 | #: utils/cpufreq-info.c:213 | ||
| 303 | #, c-format | ||
| 304 | msgid " driver: %s\n" | ||
| 305 | msgstr " ovladaÄ: %s\n" | ||
| 306 | |||
| 307 | #: utils/cpufreq-info.c:219 | ||
| 308 | #, fuzzy, c-format | ||
| 309 | msgid " CPUs which run at the same hardware frequency: " | ||
| 310 | msgstr " CPU, které musà měnit frekvenci zároveň: " | ||
| 311 | |||
| 312 | #: utils/cpufreq-info.c:230 | ||
| 313 | #, fuzzy, c-format | ||
| 314 | msgid " CPUs which need to have their frequency coordinated by software: " | ||
| 315 | msgstr " CPU, které musà měnit frekvenci zároveň: " | ||
| 316 | |||
| 317 | #: utils/cpufreq-info.c:241 | ||
| 318 | #, c-format | ||
| 319 | msgid " maximum transition latency: " | ||
| 320 | msgstr "" | ||
| 321 | |||
| 322 | #: utils/cpufreq-info.c:247 | ||
| 323 | #, c-format | ||
| 324 | msgid " hardware limits: " | ||
| 325 | msgstr " hardwarové meze: " | ||
| 326 | |||
| 327 | #: utils/cpufreq-info.c:256 | ||
| 328 | #, c-format | ||
| 329 | msgid " available frequency steps: " | ||
| 330 | msgstr " dostupné frekvence: " | ||
| 331 | |||
| 332 | #: utils/cpufreq-info.c:269 | ||
| 333 | #, c-format | ||
| 334 | msgid " available cpufreq governors: " | ||
| 335 | msgstr " dostupné regulátory: " | ||
| 336 | |||
| 337 | #: utils/cpufreq-info.c:280 | ||
| 338 | #, c-format | ||
| 339 | msgid " current policy: frequency should be within " | ||
| 340 | msgstr " souÄasná taktika: frekvence by mÄ›la být mezi " | ||
| 341 | |||
| 342 | #: utils/cpufreq-info.c:282 | ||
| 343 | #, c-format | ||
| 344 | msgid " and " | ||
| 345 | msgstr " a " | ||
| 346 | |||
| 347 | #: utils/cpufreq-info.c:286 | ||
| 348 | #, c-format | ||
| 349 | msgid "" | ||
| 350 | "The governor \"%s\" may decide which speed to use\n" | ||
| 351 | " within this range.\n" | ||
| 352 | msgstr "" | ||
| 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 | ||
| 358 | msgid " current CPU frequency is " | ||
| 359 | msgstr " souÄasná frekvence CPU je " | ||
| 360 | |||
| 361 | #: utils/cpufreq-info.c:296 | ||
| 362 | #, c-format | ||
| 363 | msgid " (asserted by call to hardware)" | ||
| 364 | msgstr " (zjiÅ¡tÄ›no hardwarovým volánÃm)" | ||
| 365 | |||
| 366 | #: utils/cpufreq-info.c:304 | ||
| 367 | #, c-format | ||
| 368 | msgid " cpufreq stats: " | ||
| 369 | msgstr " statistika cpufreq: " | ||
| 370 | |||
| 371 | #: utils/cpufreq-info.c:472 | ||
| 372 | #, fuzzy, c-format | ||
| 373 | msgid "Usage: cpupower freqinfo [options]\n" | ||
| 374 | msgstr "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 | ||
| 379 | msgid "Options:\n" | ||
| 380 | msgstr "PÅ™epÃnaÄe:\n" | ||
| 381 | |||
| 382 | #: utils/cpufreq-info.c:474 | ||
| 383 | #, fuzzy, c-format | ||
| 384 | msgid " -e, --debug Prints out debug information [default]\n" | ||
| 385 | msgstr " -e, --debug VypÃÅ¡e ladicà informace\n" | ||
| 386 | |||
| 387 | #: utils/cpufreq-info.c:475 | ||
| 388 | #, c-format | ||
| 389 | msgid "" | ||
| 390 | " -f, --freq Get frequency the CPU currently runs at, according\n" | ||
| 391 | " to the cpufreq core *\n" | ||
| 392 | msgstr "" | ||
| 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 | ||
| 398 | msgid "" | ||
| 399 | " -w, --hwfreq Get frequency the CPU currently runs at, by reading\n" | ||
| 400 | " it from hardware (only available to root) *\n" | ||
| 401 | msgstr "" | ||
| 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 | ||
| 407 | msgid "" | ||
| 408 | " -l, --hwlimits Determine the minimum and maximum CPU frequency " | ||
| 409 | "allowed *\n" | ||
| 410 | msgstr "" | ||
| 411 | " -l, --hwlimits Zjistà minimálnà a maximálnà dostupnou frekvenci CPU " | ||
| 412 | "*\n" | ||
| 413 | |||
| 414 | #: utils/cpufreq-info.c:480 | ||
| 415 | #, c-format | ||
| 416 | msgid " -d, --driver Determines the used cpufreq kernel driver *\n" | ||
| 417 | msgstr " -d, --driver Zjistà aktivnà ovladaÄ cpufreq *\n" | ||
| 418 | |||
| 419 | #: utils/cpufreq-info.c:481 | ||
| 420 | #, c-format | ||
| 421 | msgid " -p, --policy Gets the currently used cpufreq policy *\n" | ||
| 422 | msgstr " -p, --policy Zjistà aktuálnà taktiku cpufreq *\n" | ||
| 423 | |||
| 424 | #: utils/cpufreq-info.c:482 | ||
| 425 | #, c-format | ||
| 426 | msgid " -g, --governors Determines available cpufreq governors *\n" | ||
| 427 | msgstr " -g, --governors Zjistà dostupné regulátory cpufreq *\n" | ||
| 428 | |||
| 429 | #: utils/cpufreq-info.c:483 | ||
| 430 | #, fuzzy, c-format | ||
| 431 | msgid "" | ||
| 432 | " -r, --related-cpus Determines which CPUs run at the same hardware " | ||
| 433 | "frequency *\n" | ||
| 434 | msgstr "" | ||
| 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 | ||
| 439 | msgid "" | ||
| 440 | " -a, --affected-cpus Determines which CPUs need to have their frequency\n" | ||
| 441 | " coordinated by software *\n" | ||
| 442 | msgstr "" | ||
| 443 | " -a, --affected-cpus ZjistÃ, které CPU musà mÄ›nit frekvenci zároveň *\n" | ||
| 444 | |||
| 445 | #: utils/cpufreq-info.c:486 | ||
| 446 | #, c-format | ||
| 447 | msgid " -s, --stats Shows cpufreq statistics if available\n" | ||
| 448 | msgstr " -s, --stats Zobrazà statistiku cpufreq, je-li dostupná\n" | ||
| 449 | |||
| 450 | #: utils/cpufreq-info.c:487 | ||
| 451 | #, fuzzy, c-format | ||
| 452 | msgid "" | ||
| 453 | " -y, --latency Determines the maximum latency on CPU frequency " | ||
| 454 | "changes *\n" | ||
| 455 | msgstr "" | ||
| 456 | " -l, --hwlimits Zjistà minimálnà a maximálnà dostupnou frekvenci CPU " | ||
| 457 | "*\n" | ||
| 458 | |||
| 459 | #: utils/cpufreq-info.c:488 | ||
| 460 | #, c-format | ||
| 461 | msgid " -b, --boost Checks for turbo or boost modes *\n" | ||
| 462 | msgstr "" | ||
| 463 | |||
| 464 | #: utils/cpufreq-info.c:489 | ||
| 465 | #, c-format | ||
| 466 | msgid "" | ||
| 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" | ||
| 470 | msgstr "" | ||
| 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 | ||
| 476 | msgid "" | ||
| 477 | " -m, --human human-readable output for the -f, -w, -s and -y " | ||
| 478 | "parameters\n" | ||
| 479 | msgstr "" | ||
| 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 | ||
| 485 | msgid " -h, --help Prints out this screen\n" | ||
| 486 | msgstr " -h, --help VypÃÅ¡e tuto nápovÄ›du\n" | ||
| 487 | |||
| 488 | #: utils/cpufreq-info.c:495 | ||
| 489 | #, c-format | ||
| 490 | msgid "" | ||
| 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" | ||
| 493 | msgstr "" | ||
| 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 | ||
| 500 | msgid "" | ||
| 501 | "For the arguments marked with *, omitting the -c or --cpu argument is\n" | ||
| 502 | "equivalent to setting it to zero\n" | ||
| 503 | msgstr "" | ||
| 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 | ||
| 509 | msgid "" | ||
| 510 | "The argument passed to this tool can't be combined with passing a --cpu " | ||
| 511 | "argument\n" | ||
| 512 | msgstr "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 | ||
| 516 | msgid "" | ||
| 517 | "You can't specify more than one --cpu parameter and/or\n" | ||
| 518 | "more than one output-specific argument\n" | ||
| 519 | msgstr "" | ||
| 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 | ||
| 526 | msgid "invalid or unknown argument\n" | ||
| 527 | msgstr "neplatný nebo neznámý parametr\n" | ||
| 528 | |||
| 529 | #: utils/cpufreq-info.c:617 | ||
| 530 | #, c-format | ||
| 531 | msgid "couldn't analyze CPU %d as it doesn't seem to be present\n" | ||
| 532 | msgstr "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 | ||
| 536 | msgid "analyzing CPU %d:\n" | ||
| 537 | msgstr "analyzuji CPU %d:\n" | ||
| 538 | |||
| 539 | #: utils/cpufreq-set.c:25 | ||
| 540 | #, fuzzy, c-format | ||
| 541 | msgid "Usage: cpupower frequency-set [options]\n" | ||
| 542 | msgstr "UžitÃ: cpufreq-set [pÅ™epÃnaÄe]\n" | ||
| 543 | |||
| 544 | #: utils/cpufreq-set.c:27 | ||
| 545 | #, c-format | ||
| 546 | msgid "" | ||
| 547 | " -d FREQ, --min FREQ new minimum CPU frequency the governor may " | ||
| 548 | "select\n" | ||
| 549 | msgstr "" | ||
| 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 | ||
| 555 | msgid "" | ||
| 556 | " -u FREQ, --max FREQ new maximum CPU frequency the governor may " | ||
| 557 | "select\n" | ||
| 558 | msgstr "" | ||
| 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 | ||
| 564 | msgid " -g GOV, --governor GOV new cpufreq governor\n" | ||
| 565 | msgstr " -g GOV, --governors GOV Nový regulátor cpufreq\n" | ||
| 566 | |||
| 567 | #: utils/cpufreq-set.c:30 | ||
| 568 | #, c-format | ||
| 569 | msgid "" | ||
| 570 | " -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n" | ||
| 571 | " governor to be available and loaded\n" | ||
| 572 | msgstr "" | ||
| 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 | ||
| 579 | msgid " -r, --related Switches all hardware-related CPUs\n" | ||
| 580 | msgstr "" | ||
| 581 | |||
| 582 | #: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27 | ||
| 583 | #, fuzzy, c-format | ||
| 584 | msgid " -h, --help Prints out this screen\n" | ||
| 585 | msgstr " -h, --help VypÃÅ¡e tuto nápovÄ›du\n" | ||
| 586 | |||
| 587 | #: utils/cpufreq-set.c:35 | ||
| 588 | #, fuzzy, c-format | ||
| 589 | msgid "" | ||
| 590 | "Notes:\n" | ||
| 591 | "1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n" | ||
| 592 | msgstr "" | ||
| 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 | ||
| 598 | msgid "" | ||
| 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" | ||
| 605 | msgstr "" | ||
| 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 | ||
| 617 | msgid "" | ||
| 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" | ||
| 627 | msgstr "" | ||
| 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 | ||
| 638 | msgid "wrong, unknown or unhandled CPU?\n" | ||
| 639 | msgstr "neznámý nebo nepodporovaný CPU?\n" | ||
| 640 | |||
| 641 | #: utils/cpufreq-set.c:302 | ||
| 642 | #, c-format | ||
| 643 | msgid "" | ||
| 644 | "the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n" | ||
| 645 | "-g/--governor parameters\n" | ||
| 646 | msgstr "" | ||
| 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 | ||
| 652 | msgid "" | ||
| 653 | "At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n" | ||
| 654 | "-g/--governor must be passed\n" | ||
| 655 | msgstr "" | ||
| 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 | ||
| 661 | msgid "Setting cpu: %d\n" | ||
| 662 | msgstr "" | ||
| 663 | |||
| 664 | #: utils/cpupower-set.c:22 | ||
| 665 | #, c-format | ||
| 666 | msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n" | ||
| 667 | msgstr "" | ||
| 668 | |||
| 669 | #: utils/cpupower-set.c:24 | ||
| 670 | #, c-format | ||
| 671 | msgid "" | ||
| 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" | ||
| 674 | msgstr "" | ||
| 675 | |||
| 676 | #: utils/cpupower-set.c:26 | ||
| 677 | #, c-format | ||
| 678 | msgid "" | ||
| 679 | " -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n" | ||
| 680 | msgstr "" | ||
| 681 | |||
| 682 | #: utils/cpupower-set.c:27 | ||
| 683 | #, c-format | ||
| 684 | msgid "" | ||
| 685 | " -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler " | ||
| 686 | "policy.\n" | ||
| 687 | msgstr "" | ||
| 688 | |||
| 689 | #: utils/cpupower-set.c:80 | ||
| 690 | #, c-format | ||
| 691 | msgid "--perf-bias param out of range [0-%d]\n" | ||
| 692 | msgstr "" | ||
| 693 | |||
| 694 | #: utils/cpupower-set.c:91 | ||
| 695 | #, c-format | ||
| 696 | msgid "--sched-mc param out of range [0-%d]\n" | ||
| 697 | msgstr "" | ||
| 698 | |||
| 699 | #: utils/cpupower-set.c:102 | ||
| 700 | #, c-format | ||
| 701 | msgid "--sched-smt param out of range [0-%d]\n" | ||
| 702 | msgstr "" | ||
| 703 | |||
| 704 | #: utils/cpupower-set.c:121 | ||
| 705 | #, c-format | ||
| 706 | msgid "Error setting sched-mc %s\n" | ||
| 707 | msgstr "" | ||
| 708 | |||
| 709 | #: utils/cpupower-set.c:127 | ||
| 710 | #, c-format | ||
| 711 | msgid "Error setting sched-smt %s\n" | ||
| 712 | msgstr "" | ||
| 713 | |||
| 714 | #: utils/cpupower-set.c:146 | ||
| 715 | #, c-format | ||
| 716 | msgid "Error setting perf-bias value on CPU %d\n" | ||
| 717 | msgstr "" | ||
| 718 | |||
| 719 | #: utils/cpupower-info.c:21 | ||
| 720 | #, c-format | ||
| 721 | msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n" | ||
| 722 | msgstr "" | ||
| 723 | |||
| 724 | #: utils/cpupower-info.c:23 | ||
| 725 | #, c-format | ||
| 726 | msgid "" | ||
| 727 | " -b, --perf-bias Gets CPU's power vs performance policy on some\n" | ||
| 728 | " Intel models [0-15], see manpage for details\n" | ||
| 729 | msgstr "" | ||
| 730 | |||
| 731 | #: utils/cpupower-info.c:25 | ||
| 732 | #, fuzzy, c-format | ||
| 733 | msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n" | ||
| 734 | msgstr " -p, --policy Zjistà aktuálnà taktiku cpufreq *\n" | ||
| 735 | |||
| 736 | #: utils/cpupower-info.c:26 | ||
| 737 | #, c-format | ||
| 738 | msgid "" | ||
| 739 | " -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n" | ||
| 740 | msgstr "" | ||
| 741 | |||
| 742 | #: utils/cpupower-info.c:28 | ||
| 743 | #, c-format | ||
| 744 | msgid "" | ||
| 745 | "\n" | ||
| 746 | "Passing no option will show all info, by default only on core 0\n" | ||
| 747 | msgstr "" | ||
| 748 | |||
| 749 | #: utils/cpupower-info.c:102 | ||
| 750 | #, c-format | ||
| 751 | msgid "System's multi core scheduler setting: " | ||
| 752 | msgstr "" | ||
| 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 | ||
| 757 | msgid "not supported\n" | ||
| 758 | msgstr "" | ||
| 759 | |||
| 760 | #: utils/cpupower-info.c:111 | ||
| 761 | #, c-format | ||
| 762 | msgid "System's thread sibling scheduler setting: " | ||
| 763 | msgstr "" | ||
| 764 | |||
| 765 | #: utils/cpupower-info.c:126 | ||
| 766 | #, c-format | ||
| 767 | msgid "Intel's performance bias setting needs root privileges\n" | ||
| 768 | msgstr "" | ||
| 769 | |||
| 770 | #: utils/cpupower-info.c:128 | ||
| 771 | #, c-format | ||
| 772 | msgid "System does not support Intel's performance bias setting\n" | ||
| 773 | msgstr "" | ||
| 774 | |||
| 775 | #: utils/cpupower-info.c:147 | ||
| 776 | #, c-format | ||
| 777 | msgid "Could not read perf-bias value\n" | ||
| 778 | msgstr "" | ||
| 779 | |||
| 780 | #: utils/cpupower-info.c:150 | ||
| 781 | #, c-format | ||
| 782 | msgid "perf-bias: %d\n" | ||
| 783 | msgstr "" | ||
| 784 | |||
| 785 | #: utils/cpuidle-info.c:28 | ||
| 786 | #, fuzzy, c-format | ||
| 787 | msgid "Analyzing CPU %d:\n" | ||
| 788 | msgstr "analyzuji CPU %d:\n" | ||
| 789 | |||
| 790 | #: utils/cpuidle-info.c:32 | ||
| 791 | #, c-format | ||
| 792 | msgid "CPU %u: No idle states\n" | ||
| 793 | msgstr "" | ||
| 794 | |||
| 795 | #: utils/cpuidle-info.c:36 | ||
| 796 | #, c-format | ||
| 797 | msgid "CPU %u: Can't read idle state info\n" | ||
| 798 | msgstr "" | ||
| 799 | |||
| 800 | #: utils/cpuidle-info.c:41 | ||
| 801 | #, c-format | ||
| 802 | msgid "Could not determine max idle state %u\n" | ||
| 803 | msgstr "" | ||
| 804 | |||
| 805 | #: utils/cpuidle-info.c:46 | ||
| 806 | #, c-format | ||
| 807 | msgid "Number of idle states: %d\n" | ||
| 808 | msgstr "" | ||
| 809 | |||
| 810 | #: utils/cpuidle-info.c:48 | ||
| 811 | #, fuzzy, c-format | ||
| 812 | msgid "Available idle states:" | ||
| 813 | msgstr " dostupné frekvence: " | ||
| 814 | |||
| 815 | #: utils/cpuidle-info.c:71 | ||
| 816 | #, c-format | ||
| 817 | msgid "Flags/Description: %s\n" | ||
| 818 | msgstr "" | ||
| 819 | |||
| 820 | #: utils/cpuidle-info.c:74 | ||
| 821 | #, c-format | ||
| 822 | msgid "Latency: %lu\n" | ||
| 823 | msgstr "" | ||
| 824 | |||
| 825 | #: utils/cpuidle-info.c:76 | ||
| 826 | #, c-format | ||
| 827 | msgid "Usage: %lu\n" | ||
| 828 | msgstr "" | ||
| 829 | |||
| 830 | #: utils/cpuidle-info.c:78 | ||
| 831 | #, c-format | ||
| 832 | msgid "Duration: %llu\n" | ||
| 833 | msgstr "" | ||
| 834 | |||
| 835 | #: utils/cpuidle-info.c:90 | ||
| 836 | #, c-format | ||
| 837 | msgid "Could not determine cpuidle driver\n" | ||
| 838 | msgstr "" | ||
| 839 | |||
| 840 | #: utils/cpuidle-info.c:94 | ||
| 841 | #, fuzzy, c-format | ||
| 842 | msgid "CPUidle driver: %s\n" | ||
| 843 | msgstr " ovladaÄ: %s\n" | ||
| 844 | |||
| 845 | #: utils/cpuidle-info.c:99 | ||
| 846 | #, c-format | ||
| 847 | msgid "Could not determine cpuidle governor\n" | ||
| 848 | msgstr "" | ||
| 849 | |||
| 850 | #: utils/cpuidle-info.c:103 | ||
| 851 | #, c-format | ||
| 852 | msgid "CPUidle governor: %s\n" | ||
| 853 | msgstr "" | ||
| 854 | |||
| 855 | #: utils/cpuidle-info.c:122 | ||
| 856 | #, c-format | ||
| 857 | msgid "CPU %u: Can't read C-state info\n" | ||
| 858 | msgstr "" | ||
| 859 | |||
| 860 | #. printf("Cstates: %d\n", cstates); | ||
| 861 | #: utils/cpuidle-info.c:127 | ||
| 862 | #, c-format | ||
| 863 | msgid "active state: C0\n" | ||
| 864 | msgstr "" | ||
| 865 | |||
| 866 | #: utils/cpuidle-info.c:128 | ||
| 867 | #, c-format | ||
| 868 | msgid "max_cstate: C%u\n" | ||
| 869 | msgstr "" | ||
| 870 | |||
| 871 | #: utils/cpuidle-info.c:129 | ||
| 872 | #, c-format | ||
| 873 | msgid "maximum allowed latency: %lu usec\n" | ||
| 874 | msgstr "" | ||
| 875 | |||
| 876 | #: utils/cpuidle-info.c:130 | ||
| 877 | #, c-format | ||
| 878 | msgid "states:\t\n" | ||
| 879 | msgstr "" | ||
| 880 | |||
| 881 | #: utils/cpuidle-info.c:132 | ||
| 882 | #, c-format | ||
| 883 | msgid " C%d: type[C%d] " | ||
| 884 | msgstr "" | ||
| 885 | |||
| 886 | #: utils/cpuidle-info.c:134 | ||
| 887 | #, c-format | ||
| 888 | msgid "promotion[--] demotion[--] " | ||
| 889 | msgstr "" | ||
| 890 | |||
| 891 | #: utils/cpuidle-info.c:135 | ||
| 892 | #, c-format | ||
| 893 | msgid "latency[%03lu] " | ||
| 894 | msgstr "" | ||
| 895 | |||
| 896 | #: utils/cpuidle-info.c:137 | ||
| 897 | #, c-format | ||
| 898 | msgid "usage[%08lu] " | ||
| 899 | msgstr "" | ||
| 900 | |||
| 901 | #: utils/cpuidle-info.c:139 | ||
| 902 | #, c-format | ||
| 903 | msgid "duration[%020Lu] \n" | ||
| 904 | msgstr "" | ||
| 905 | |||
| 906 | #: utils/cpuidle-info.c:147 | ||
| 907 | #, fuzzy, c-format | ||
| 908 | msgid "Usage: cpupower idleinfo [options]\n" | ||
| 909 | msgstr "UžitÃ: cpufreq-info [pÅ™epÃnaÄe]\n" | ||
| 910 | |||
| 911 | #: utils/cpuidle-info.c:149 | ||
| 912 | #, fuzzy, c-format | ||
| 913 | msgid " -s, --silent Only show general C-state information\n" | ||
| 914 | msgstr " -e, --debug VypÃÅ¡e ladicà informace\n" | ||
| 915 | |||
| 916 | #: utils/cpuidle-info.c:150 | ||
| 917 | #, fuzzy, c-format | ||
| 918 | msgid "" | ||
| 919 | " -o, --proc Prints out information like provided by the /proc/" | ||
| 920 | "acpi/processor/*/power\n" | ||
| 921 | " interface in older kernels\n" | ||
| 922 | msgstr "" | ||
| 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 | ||
| 928 | msgid "You can't specify more than one output-specific argument\n" | ||
| 929 | msgstr "" | ||
| 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 000000000000..78c09e51663a --- /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 | # | ||
| 6 | msgid "" | ||
| 7 | msgstr "" | ||
| 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 | ||
| 21 | msgid "Processor Core C3" | ||
| 22 | msgstr "" | ||
| 23 | |||
| 24 | #: utils/idle_monitor/nhm_idle.c:43 | ||
| 25 | msgid "Processor Core C6" | ||
| 26 | msgstr "" | ||
| 27 | |||
| 28 | #: utils/idle_monitor/nhm_idle.c:51 | ||
| 29 | msgid "Processor Package C3" | ||
| 30 | msgstr "" | ||
| 31 | |||
| 32 | #: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70 | ||
| 33 | msgid "Processor Package C6" | ||
| 34 | msgstr "" | ||
| 35 | |||
| 36 | #: utils/idle_monitor/snb_idle.c:33 | ||
| 37 | msgid "Processor Core C7" | ||
| 38 | msgstr "" | ||
| 39 | |||
| 40 | #: utils/idle_monitor/snb_idle.c:40 | ||
| 41 | msgid "Processor Package C2" | ||
| 42 | msgstr "" | ||
| 43 | |||
| 44 | #: utils/idle_monitor/snb_idle.c:47 | ||
| 45 | msgid "Processor Package C7" | ||
| 46 | msgstr "" | ||
| 47 | |||
| 48 | #: utils/idle_monitor/amd_fam14h_idle.c:56 | ||
| 49 | msgid "Package in sleep state (PC1 or deeper)" | ||
| 50 | msgstr "" | ||
| 51 | |||
| 52 | #: utils/idle_monitor/amd_fam14h_idle.c:63 | ||
| 53 | msgid "Processor Package C1" | ||
| 54 | msgstr "" | ||
| 55 | |||
| 56 | #: utils/idle_monitor/amd_fam14h_idle.c:77 | ||
| 57 | msgid "North Bridge P1 boolean counter (returns 0 or 1)" | ||
| 58 | msgstr "" | ||
| 59 | |||
| 60 | #: utils/idle_monitor/mperf_monitor.c:35 | ||
| 61 | msgid "Processor Core not idle" | ||
| 62 | msgstr "" | ||
| 63 | |||
| 64 | #: utils/idle_monitor/mperf_monitor.c:42 | ||
| 65 | msgid "Processor Core in an idle state" | ||
| 66 | msgstr "" | ||
| 67 | |||
| 68 | #: utils/idle_monitor/mperf_monitor.c:50 | ||
| 69 | msgid "Average Frequency (including boost) in MHz" | ||
| 70 | msgstr "" | ||
| 71 | |||
| 72 | #: utils/idle_monitor/cpupower-monitor.c:66 | ||
| 73 | #, c-format | ||
| 74 | msgid "" | ||
| 75 | "cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " | ||
| 76 | "interval_sec | -c command ...]\n" | ||
| 77 | msgstr "" | ||
| 78 | |||
| 79 | #: utils/idle_monitor/cpupower-monitor.c:69 | ||
| 80 | #, c-format | ||
| 81 | msgid "" | ||
| 82 | "cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " | ||
| 83 | "interval_sec | -c command ...]\n" | ||
| 84 | msgstr "" | ||
| 85 | |||
| 86 | #: utils/idle_monitor/cpupower-monitor.c:71 | ||
| 87 | #, c-format | ||
| 88 | msgid "\t -v: be more verbose\n" | ||
| 89 | msgstr "" | ||
| 90 | |||
| 91 | #: utils/idle_monitor/cpupower-monitor.c:73 | ||
| 92 | #, c-format | ||
| 93 | msgid "\t -h: print this help\n" | ||
| 94 | msgstr "" | ||
| 95 | |||
| 96 | #: utils/idle_monitor/cpupower-monitor.c:74 | ||
| 97 | #, c-format | ||
| 98 | msgid "\t -i: time intervall to measure for in seconds (default 1)\n" | ||
| 99 | msgstr "" | ||
| 100 | |||
| 101 | #: utils/idle_monitor/cpupower-monitor.c:75 | ||
| 102 | #, c-format | ||
| 103 | msgid "\t -t: show CPU topology/hierarchy\n" | ||
| 104 | msgstr "" | ||
| 105 | |||
| 106 | #: utils/idle_monitor/cpupower-monitor.c:76 | ||
| 107 | #, c-format | ||
| 108 | msgid "\t -l: list available CPU sleep monitors (for use with -m)\n" | ||
| 109 | msgstr "" | ||
| 110 | |||
| 111 | #: utils/idle_monitor/cpupower-monitor.c:77 | ||
| 112 | #, c-format | ||
| 113 | msgid "\t -m: show specific CPU sleep monitors only (in same order)\n" | ||
| 114 | msgstr "" | ||
| 115 | |||
| 116 | #: utils/idle_monitor/cpupower-monitor.c:79 | ||
| 117 | #, c-format | ||
| 118 | msgid "" | ||
| 119 | "only one of: -t, -l, -m are allowed\n" | ||
| 120 | "If none of them is passed," | ||
| 121 | msgstr "" | ||
| 122 | |||
| 123 | #: utils/idle_monitor/cpupower-monitor.c:80 | ||
| 124 | #, c-format | ||
| 125 | msgid " all supported monitors are shown\n" | ||
| 126 | msgstr "" | ||
| 127 | |||
| 128 | #: utils/idle_monitor/cpupower-monitor.c:197 | ||
| 129 | #, c-format | ||
| 130 | msgid "Monitor %s, Counter %s has no count function. Implementation error\n" | ||
| 131 | msgstr "" | ||
| 132 | |||
| 133 | #: utils/idle_monitor/cpupower-monitor.c:207 | ||
| 134 | #, c-format | ||
| 135 | msgid " *is offline\n" | ||
| 136 | msgstr "" | ||
| 137 | |||
| 138 | #: utils/idle_monitor/cpupower-monitor.c:236 | ||
| 139 | #, c-format | ||
| 140 | msgid "%s: max monitor name length (%d) exceeded\n" | ||
| 141 | msgstr "" | ||
| 142 | |||
| 143 | #: utils/idle_monitor/cpupower-monitor.c:250 | ||
| 144 | #, c-format | ||
| 145 | msgid "No matching monitor found in %s, try -l option\n" | ||
| 146 | msgstr "" | ||
| 147 | |||
| 148 | #: utils/idle_monitor/cpupower-monitor.c:266 | ||
| 149 | #, c-format | ||
| 150 | msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n" | ||
| 151 | msgstr "" | ||
| 152 | |||
| 153 | #: utils/idle_monitor/cpupower-monitor.c:319 | ||
| 154 | #, c-format | ||
| 155 | msgid "%s took %.5f seconds and exited with status %d\n" | ||
| 156 | msgstr "" | ||
| 157 | |||
| 158 | #: utils/idle_monitor/cpupower-monitor.c:406 | ||
| 159 | #, c-format | ||
| 160 | msgid "Cannot read number of available processors\n" | ||
| 161 | msgstr "" | ||
| 162 | |||
| 163 | #: utils/idle_monitor/cpupower-monitor.c:417 | ||
| 164 | #, c-format | ||
| 165 | msgid "Available monitor %s needs root access\n" | ||
| 166 | msgstr "" | ||
| 167 | |||
| 168 | #: utils/idle_monitor/cpupower-monitor.c:428 | ||
| 169 | #, c-format | ||
| 170 | msgid "No HW Cstate monitors found\n" | ||
| 171 | msgstr "" | ||
| 172 | |||
| 173 | #: utils/cpupower.c:78 | ||
| 174 | #, c-format | ||
| 175 | msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n" | ||
| 176 | msgstr "" | ||
| 177 | |||
| 178 | #: utils/cpupower.c:79 | ||
| 179 | #, c-format | ||
| 180 | msgid "cpupower --version\n" | ||
| 181 | msgstr "" | ||
| 182 | |||
| 183 | #: utils/cpupower.c:80 | ||
| 184 | #, c-format | ||
| 185 | msgid "Supported subcommands are:\n" | ||
| 186 | msgstr "" | ||
| 187 | |||
| 188 | #: utils/cpupower.c:83 | ||
| 189 | #, c-format | ||
| 190 | msgid "" | ||
| 191 | "\n" | ||
| 192 | "Some subcommands can make use of the -c cpulist option.\n" | ||
| 193 | msgstr "" | ||
| 194 | |||
| 195 | #: utils/cpupower.c:84 | ||
| 196 | #, c-format | ||
| 197 | msgid "Look at the general cpupower manpage how to use it\n" | ||
| 198 | msgstr "" | ||
| 199 | |||
| 200 | #: utils/cpupower.c:85 | ||
| 201 | #, c-format | ||
| 202 | msgid "and read up the subcommand's manpage whether it is supported.\n" | ||
| 203 | msgstr "" | ||
| 204 | |||
| 205 | #: utils/cpupower.c:86 | ||
| 206 | #, c-format | ||
| 207 | msgid "" | ||
| 208 | "\n" | ||
| 209 | "Use cpupower help subcommand for getting help for above subcommands.\n" | ||
| 210 | msgstr "" | ||
| 211 | |||
| 212 | #: utils/cpupower.c:91 | ||
| 213 | #, c-format | ||
| 214 | msgid "Report errors and bugs to %s, please.\n" | ||
| 215 | msgstr "Bitte melden Sie Fehler an %s.\n" | ||
| 216 | |||
| 217 | #: utils/cpupower.c:114 | ||
| 218 | #, c-format | ||
| 219 | msgid "Error parsing cpu list\n" | ||
| 220 | msgstr "" | ||
| 221 | |||
| 222 | #: utils/cpupower.c:172 | ||
| 223 | #, c-format | ||
| 224 | msgid "Subcommand %s needs root privileges\n" | ||
| 225 | msgstr "" | ||
| 226 | |||
| 227 | #: utils/cpufreq-info.c:31 | ||
| 228 | #, c-format | ||
| 229 | msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n" | ||
| 230 | msgstr "" | ||
| 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 | ||
| 235 | msgid "" | ||
| 236 | " minimum CPU frequency - maximum CPU frequency - governor\n" | ||
| 237 | msgstr "" | ||
| 238 | " minimale CPU-Taktfreq. - maximale CPU-Taktfreq. - Regler \n" | ||
| 239 | |||
| 240 | #: utils/cpufreq-info.c:151 | ||
| 241 | #, c-format | ||
| 242 | msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n" | ||
| 243 | msgstr "" | ||
| 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 | ||
| 252 | msgid " boost state support: \n" | ||
| 253 | msgstr "" | ||
| 254 | |||
| 255 | #: utils/cpufreq-info.c:163 | ||
| 256 | #, c-format | ||
| 257 | msgid " Supported: %s\n" | ||
| 258 | msgstr "" | ||
| 259 | |||
| 260 | #: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 | ||
| 261 | msgid "yes" | ||
| 262 | msgstr "" | ||
| 263 | |||
| 264 | #: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 | ||
| 265 | msgid "no" | ||
| 266 | msgstr "" | ||
| 267 | |||
| 268 | #: utils/cpufreq-info.c:164 | ||
| 269 | #, fuzzy, c-format | ||
| 270 | msgid " Active: %s\n" | ||
| 271 | msgstr " Treiber: %s\n" | ||
| 272 | |||
| 273 | #: utils/cpufreq-info.c:177 | ||
| 274 | #, c-format | ||
| 275 | msgid " Boost States: %d\n" | ||
| 276 | msgstr "" | ||
| 277 | |||
| 278 | #: utils/cpufreq-info.c:178 | ||
| 279 | #, c-format | ||
| 280 | msgid " Total States: %d\n" | ||
| 281 | msgstr "" | ||
| 282 | |||
| 283 | #: utils/cpufreq-info.c:181 | ||
| 284 | #, c-format | ||
| 285 | msgid " Pstate-Pb%d: %luMHz (boost state)\n" | ||
| 286 | msgstr "" | ||
| 287 | |||
| 288 | #: utils/cpufreq-info.c:184 | ||
| 289 | #, c-format | ||
| 290 | msgid " Pstate-P%d: %luMHz\n" | ||
| 291 | msgstr "" | ||
| 292 | |||
| 293 | #: utils/cpufreq-info.c:211 | ||
| 294 | #, c-format | ||
| 295 | msgid " no or unknown cpufreq driver is active on this CPU\n" | ||
| 296 | msgstr " kein oder nicht bestimmbarer cpufreq-Treiber aktiv\n" | ||
| 297 | |||
| 298 | #: utils/cpufreq-info.c:213 | ||
| 299 | #, c-format | ||
| 300 | msgid " driver: %s\n" | ||
| 301 | msgstr " Treiber: %s\n" | ||
| 302 | |||
| 303 | #: utils/cpufreq-info.c:219 | ||
| 304 | #, c-format | ||
| 305 | msgid " CPUs which run at the same hardware frequency: " | ||
| 306 | msgstr " Folgende CPUs laufen mit der gleichen Hardware-Taktfrequenz: " | ||
| 307 | |||
| 308 | #: utils/cpufreq-info.c:230 | ||
| 309 | #, c-format | ||
| 310 | msgid " CPUs which need to have their frequency coordinated by software: " | ||
| 311 | msgstr " Die Taktfrequenz folgender CPUs werden per Software koordiniert: " | ||
| 312 | |||
| 313 | #: utils/cpufreq-info.c:241 | ||
| 314 | #, c-format | ||
| 315 | msgid " maximum transition latency: " | ||
| 316 | msgstr " Maximale Dauer eines Taktfrequenzwechsels: " | ||
| 317 | |||
| 318 | #: utils/cpufreq-info.c:247 | ||
| 319 | #, c-format | ||
| 320 | msgid " hardware limits: " | ||
| 321 | msgstr " Hardwarebedingte Grenzen der Taktfrequenz: " | ||
| 322 | |||
| 323 | #: utils/cpufreq-info.c:256 | ||
| 324 | #, c-format | ||
| 325 | msgid " available frequency steps: " | ||
| 326 | msgstr " mögliche Taktfrequenzen: " | ||
| 327 | |||
| 328 | #: utils/cpufreq-info.c:269 | ||
| 329 | #, c-format | ||
| 330 | msgid " available cpufreq governors: " | ||
| 331 | msgstr " mögliche Regler: " | ||
| 332 | |||
| 333 | #: utils/cpufreq-info.c:280 | ||
| 334 | #, c-format | ||
| 335 | msgid " current policy: frequency should be within " | ||
| 336 | msgstr " momentane Taktik: die Frequenz soll innerhalb " | ||
| 337 | |||
| 338 | #: utils/cpufreq-info.c:282 | ||
| 339 | #, c-format | ||
| 340 | msgid " and " | ||
| 341 | msgstr " und " | ||
| 342 | |||
| 343 | #: utils/cpufreq-info.c:286 | ||
| 344 | #, c-format | ||
| 345 | msgid "" | ||
| 346 | "The governor \"%s\" may decide which speed to use\n" | ||
| 347 | " within this range.\n" | ||
| 348 | msgstr "" | ||
| 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 | ||
| 355 | msgid " current CPU frequency is " | ||
| 356 | msgstr " momentane Taktfrequenz ist " | ||
| 357 | |||
| 358 | #: utils/cpufreq-info.c:296 | ||
| 359 | #, c-format | ||
| 360 | msgid " (asserted by call to hardware)" | ||
| 361 | msgstr " (verifiziert durch Nachfrage bei der Hardware)" | ||
| 362 | |||
| 363 | #: utils/cpufreq-info.c:304 | ||
| 364 | #, c-format | ||
| 365 | msgid " cpufreq stats: " | ||
| 366 | msgstr " Statistik:" | ||
| 367 | |||
| 368 | #: utils/cpufreq-info.c:472 | ||
| 369 | #, fuzzy, c-format | ||
| 370 | msgid "Usage: cpupower freqinfo [options]\n" | ||
| 371 | msgstr "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 | ||
| 376 | msgid "Options:\n" | ||
| 377 | msgstr "Optionen:\n" | ||
| 378 | |||
| 379 | #: utils/cpufreq-info.c:474 | ||
| 380 | #, fuzzy, c-format | ||
| 381 | msgid " -e, --debug Prints out debug information [default]\n" | ||
| 382 | msgstr "" | ||
| 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 | ||
| 388 | msgid "" | ||
| 389 | " -f, --freq Get frequency the CPU currently runs at, according\n" | ||
| 390 | " to the cpufreq core *\n" | ||
| 391 | msgstr "" | ||
| 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 | ||
| 397 | msgid "" | ||
| 398 | " -w, --hwfreq Get frequency the CPU currently runs at, by reading\n" | ||
| 399 | " it from hardware (only available to root) *\n" | ||
| 400 | msgstr "" | ||
| 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 | ||
| 407 | msgid "" | ||
| 408 | " -l, --hwlimits Determine the minimum and maximum CPU frequency " | ||
| 409 | "allowed *\n" | ||
| 410 | msgstr "" | ||
| 411 | " -l, --hwlimits Findet die minimale und maximale Taktfrequenz heraus " | ||
| 412 | "*\n" | ||
| 413 | |||
| 414 | #: utils/cpufreq-info.c:480 | ||
| 415 | #, c-format | ||
| 416 | msgid " -d, --driver Determines the used cpufreq kernel driver *\n" | ||
| 417 | msgstr " -d, --driver Findet den momentanen Treiber heraus *\n" | ||
| 418 | |||
| 419 | #: utils/cpufreq-info.c:481 | ||
| 420 | #, c-format | ||
| 421 | msgid " -p, --policy Gets the currently used cpufreq policy *\n" | ||
| 422 | msgstr " -p, --policy Findet die momentane Taktik heraus *\n" | ||
| 423 | |||
| 424 | #: utils/cpufreq-info.c:482 | ||
| 425 | #, c-format | ||
| 426 | msgid " -g, --governors Determines available cpufreq governors *\n" | ||
| 427 | msgstr " -g, --governors Erzeugt eine Liste mit verfügbaren Reglern *\n" | ||
| 428 | |||
| 429 | #: utils/cpufreq-info.c:483 | ||
| 430 | #, c-format | ||
| 431 | msgid "" | ||
| 432 | " -r, --related-cpus Determines which CPUs run at the same hardware " | ||
| 433 | "frequency *\n" | ||
| 434 | msgstr "" | ||
| 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 | ||
| 441 | msgid "" | ||
| 442 | " -a, --affected-cpus Determines which CPUs need to have their frequency\n" | ||
| 443 | " coordinated by software *\n" | ||
| 444 | msgstr "" | ||
| 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 | ||
| 451 | msgid " -s, --stats Shows cpufreq statistics if available\n" | ||
| 452 | msgstr "" | ||
| 453 | " -s, --stats Zeigt, sofern möglich, Statistiken über cpufreq an.\n" | ||
| 454 | |||
| 455 | #: utils/cpufreq-info.c:487 | ||
| 456 | #, c-format | ||
| 457 | msgid "" | ||
| 458 | " -y, --latency Determines the maximum latency on CPU frequency " | ||
| 459 | "changes *\n" | ||
| 460 | msgstr "" | ||
| 461 | " -y, --latency Findet die maximale Dauer eines Taktfrequenzwechsels " | ||
| 462 | "heraus *\n" | ||
| 463 | |||
| 464 | #: utils/cpufreq-info.c:488 | ||
| 465 | #, c-format | ||
| 466 | msgid " -b, --boost Checks for turbo or boost modes *\n" | ||
| 467 | msgstr "" | ||
| 468 | |||
| 469 | #: utils/cpufreq-info.c:489 | ||
| 470 | #, c-format | ||
| 471 | msgid "" | ||
| 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" | ||
| 475 | msgstr "" | ||
| 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 | ||
| 483 | msgid "" | ||
| 484 | " -m, --human human-readable output for the -f, -w, -s and -y " | ||
| 485 | "parameters\n" | ||
| 486 | msgstr "" | ||
| 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 | ||
| 493 | msgid " -h, --help Prints out this screen\n" | ||
| 494 | msgstr " -h, --help Gibt diese Kurzübersicht aus\n" | ||
| 495 | |||
| 496 | #: utils/cpufreq-info.c:495 | ||
| 497 | #, c-format | ||
| 498 | msgid "" | ||
| 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" | ||
| 501 | msgstr "" | ||
| 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 | ||
| 508 | msgid "" | ||
| 509 | "For the arguments marked with *, omitting the -c or --cpu argument is\n" | ||
| 510 | "equivalent to setting it to zero\n" | ||
| 511 | msgstr "" | ||
| 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 | ||
| 517 | msgid "" | ||
| 518 | "The argument passed to this tool can't be combined with passing a --cpu " | ||
| 519 | "argument\n" | ||
| 520 | msgstr "Diese Option kann nicht mit der --cpu-Option kombiniert werden\n" | ||
| 521 | |||
| 522 | #: utils/cpufreq-info.c:596 | ||
| 523 | #, c-format | ||
| 524 | msgid "" | ||
| 525 | "You can't specify more than one --cpu parameter and/or\n" | ||
| 526 | "more than one output-specific argument\n" | ||
| 527 | msgstr "" | ||
| 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 | ||
| 534 | msgid "invalid or unknown argument\n" | ||
| 535 | msgstr "unbekannter oder falscher Parameter\n" | ||
| 536 | |||
| 537 | #: utils/cpufreq-info.c:617 | ||
| 538 | #, c-format | ||
| 539 | msgid "couldn't analyze CPU %d as it doesn't seem to be present\n" | ||
| 540 | msgstr "" | ||
| 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 | ||
| 545 | msgid "analyzing CPU %d:\n" | ||
| 546 | msgstr "analysiere CPU %d:\n" | ||
| 547 | |||
| 548 | #: utils/cpufreq-set.c:25 | ||
| 549 | #, fuzzy, c-format | ||
| 550 | msgid "Usage: cpupower frequency-set [options]\n" | ||
| 551 | msgstr "Aufruf: cpufreq-set [Optionen]\n" | ||
| 552 | |||
| 553 | #: utils/cpufreq-set.c:27 | ||
| 554 | #, c-format | ||
| 555 | msgid "" | ||
| 556 | " -d FREQ, --min FREQ new minimum CPU frequency the governor may " | ||
| 557 | "select\n" | ||
| 558 | msgstr "" | ||
| 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 | ||
| 564 | msgid "" | ||
| 565 | " -u FREQ, --max FREQ new maximum CPU frequency the governor may " | ||
| 566 | "select\n" | ||
| 567 | msgstr "" | ||
| 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 | ||
| 573 | msgid " -g GOV, --governor GOV new cpufreq governor\n" | ||
| 574 | msgstr " -g GOV, --governors GOV wechsle zu Regler GOV\n" | ||
| 575 | |||
| 576 | #: utils/cpufreq-set.c:30 | ||
| 577 | #, c-format | ||
| 578 | msgid "" | ||
| 579 | " -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n" | ||
| 580 | " governor to be available and loaded\n" | ||
| 581 | msgstr "" | ||
| 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 | ||
| 587 | msgid " -r, --related Switches all hardware-related CPUs\n" | ||
| 588 | msgstr "" | ||
| 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 | ||
| 594 | msgid " -h, --help Prints out this screen\n" | ||
| 595 | msgstr " -h, --help Gibt diese Kurzübersicht aus\n" | ||
| 596 | |||
| 597 | #: utils/cpufreq-set.c:35 | ||
| 598 | #, fuzzy, c-format | ||
| 599 | msgid "" | ||
| 600 | "Notes:\n" | ||
| 601 | "1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n" | ||
| 602 | msgstr "" | ||
| 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 | ||
| 608 | msgid "" | ||
| 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" | ||
| 615 | msgstr "" | ||
| 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 | ||
| 628 | msgid "" | ||
| 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" | ||
| 638 | msgstr "" | ||
| 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 | ||
| 648 | msgid "wrong, unknown or unhandled CPU?\n" | ||
| 649 | msgstr "unbekannte oder nicht regelbare CPU\n" | ||
| 650 | |||
| 651 | #: utils/cpufreq-set.c:302 | ||
| 652 | #, c-format | ||
| 653 | msgid "" | ||
| 654 | "the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n" | ||
| 655 | "-g/--governor parameters\n" | ||
| 656 | msgstr "" | ||
| 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 | ||
| 663 | msgid "" | ||
| 664 | "At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n" | ||
| 665 | "-g/--governor must be passed\n" | ||
| 666 | msgstr "" | ||
| 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 | ||
| 672 | msgid "Setting cpu: %d\n" | ||
| 673 | msgstr "" | ||
| 674 | |||
| 675 | #: utils/cpupower-set.c:22 | ||
| 676 | #, c-format | ||
| 677 | msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n" | ||
| 678 | msgstr "" | ||
| 679 | |||
| 680 | #: utils/cpupower-set.c:24 | ||
| 681 | #, c-format | ||
| 682 | msgid "" | ||
| 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" | ||
| 685 | msgstr "" | ||
| 686 | |||
| 687 | #: utils/cpupower-set.c:26 | ||
| 688 | #, c-format | ||
| 689 | msgid "" | ||
| 690 | " -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n" | ||
| 691 | msgstr "" | ||
| 692 | |||
| 693 | #: utils/cpupower-set.c:27 | ||
| 694 | #, c-format | ||
| 695 | msgid "" | ||
| 696 | " -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler " | ||
| 697 | "policy.\n" | ||
| 698 | msgstr "" | ||
| 699 | |||
| 700 | #: utils/cpupower-set.c:80 | ||
| 701 | #, c-format | ||
| 702 | msgid "--perf-bias param out of range [0-%d]\n" | ||
| 703 | msgstr "" | ||
| 704 | |||
| 705 | #: utils/cpupower-set.c:91 | ||
| 706 | #, c-format | ||
| 707 | msgid "--sched-mc param out of range [0-%d]\n" | ||
| 708 | msgstr "" | ||
| 709 | |||
| 710 | #: utils/cpupower-set.c:102 | ||
| 711 | #, c-format | ||
| 712 | msgid "--sched-smt param out of range [0-%d]\n" | ||
| 713 | msgstr "" | ||
| 714 | |||
| 715 | #: utils/cpupower-set.c:121 | ||
| 716 | #, c-format | ||
| 717 | msgid "Error setting sched-mc %s\n" | ||
| 718 | msgstr "" | ||
| 719 | |||
| 720 | #: utils/cpupower-set.c:127 | ||
| 721 | #, c-format | ||
| 722 | msgid "Error setting sched-smt %s\n" | ||
| 723 | msgstr "" | ||
| 724 | |||
| 725 | #: utils/cpupower-set.c:146 | ||
| 726 | #, c-format | ||
| 727 | msgid "Error setting perf-bias value on CPU %d\n" | ||
| 728 | msgstr "" | ||
| 729 | |||
| 730 | #: utils/cpupower-info.c:21 | ||
| 731 | #, c-format | ||
| 732 | msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n" | ||
| 733 | msgstr "" | ||
| 734 | |||
| 735 | #: utils/cpupower-info.c:23 | ||
| 736 | #, c-format | ||
| 737 | msgid "" | ||
| 738 | " -b, --perf-bias Gets CPU's power vs performance policy on some\n" | ||
| 739 | " Intel models [0-15], see manpage for details\n" | ||
| 740 | msgstr "" | ||
| 741 | |||
| 742 | #: utils/cpupower-info.c:25 | ||
| 743 | #, fuzzy, c-format | ||
| 744 | msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n" | ||
| 745 | msgstr " -p, --policy Findet die momentane Taktik heraus *\n" | ||
| 746 | |||
| 747 | #: utils/cpupower-info.c:26 | ||
| 748 | #, c-format | ||
| 749 | msgid "" | ||
| 750 | " -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n" | ||
| 751 | msgstr "" | ||
| 752 | |||
| 753 | #: utils/cpupower-info.c:28 | ||
| 754 | #, c-format | ||
| 755 | msgid "" | ||
| 756 | "\n" | ||
| 757 | "Passing no option will show all info, by default only on core 0\n" | ||
| 758 | msgstr "" | ||
| 759 | |||
| 760 | #: utils/cpupower-info.c:102 | ||
| 761 | #, c-format | ||
| 762 | msgid "System's multi core scheduler setting: " | ||
| 763 | msgstr "" | ||
| 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 | ||
| 768 | msgid "not supported\n" | ||
| 769 | msgstr "" | ||
| 770 | |||
| 771 | #: utils/cpupower-info.c:111 | ||
| 772 | #, c-format | ||
| 773 | msgid "System's thread sibling scheduler setting: " | ||
| 774 | msgstr "" | ||
| 775 | |||
| 776 | #: utils/cpupower-info.c:126 | ||
| 777 | #, c-format | ||
| 778 | msgid "Intel's performance bias setting needs root privileges\n" | ||
| 779 | msgstr "" | ||
| 780 | |||
| 781 | #: utils/cpupower-info.c:128 | ||
| 782 | #, c-format | ||
| 783 | msgid "System does not support Intel's performance bias setting\n" | ||
| 784 | msgstr "" | ||
| 785 | |||
| 786 | #: utils/cpupower-info.c:147 | ||
| 787 | #, c-format | ||
| 788 | msgid "Could not read perf-bias value\n" | ||
| 789 | msgstr "" | ||
| 790 | |||
| 791 | #: utils/cpupower-info.c:150 | ||
| 792 | #, c-format | ||
| 793 | msgid "perf-bias: %d\n" | ||
| 794 | msgstr "" | ||
| 795 | |||
| 796 | #: utils/cpuidle-info.c:28 | ||
| 797 | #, fuzzy, c-format | ||
| 798 | msgid "Analyzing CPU %d:\n" | ||
| 799 | msgstr "analysiere CPU %d:\n" | ||
| 800 | |||
| 801 | #: utils/cpuidle-info.c:32 | ||
| 802 | #, c-format | ||
| 803 | msgid "CPU %u: No idle states\n" | ||
| 804 | msgstr "" | ||
| 805 | |||
| 806 | #: utils/cpuidle-info.c:36 | ||
| 807 | #, c-format | ||
| 808 | msgid "CPU %u: Can't read idle state info\n" | ||
| 809 | msgstr "" | ||
| 810 | |||
| 811 | #: utils/cpuidle-info.c:41 | ||
| 812 | #, c-format | ||
| 813 | msgid "Could not determine max idle state %u\n" | ||
| 814 | msgstr "" | ||
| 815 | |||
| 816 | #: utils/cpuidle-info.c:46 | ||
| 817 | #, c-format | ||
| 818 | msgid "Number of idle states: %d\n" | ||
| 819 | msgstr "" | ||
| 820 | |||
| 821 | #: utils/cpuidle-info.c:48 | ||
| 822 | #, fuzzy, c-format | ||
| 823 | msgid "Available idle states:" | ||
| 824 | msgstr " mögliche Taktfrequenzen: " | ||
| 825 | |||
| 826 | #: utils/cpuidle-info.c:71 | ||
| 827 | #, c-format | ||
| 828 | msgid "Flags/Description: %s\n" | ||
| 829 | msgstr "" | ||
| 830 | |||
| 831 | #: utils/cpuidle-info.c:74 | ||
| 832 | #, c-format | ||
| 833 | msgid "Latency: %lu\n" | ||
| 834 | msgstr "" | ||
| 835 | |||
| 836 | #: utils/cpuidle-info.c:76 | ||
| 837 | #, c-format | ||
| 838 | msgid "Usage: %lu\n" | ||
| 839 | msgstr "" | ||
| 840 | |||
| 841 | #: utils/cpuidle-info.c:78 | ||
| 842 | #, c-format | ||
| 843 | msgid "Duration: %llu\n" | ||
| 844 | msgstr "" | ||
| 845 | |||
| 846 | #: utils/cpuidle-info.c:90 | ||
| 847 | #, c-format | ||
| 848 | msgid "Could not determine cpuidle driver\n" | ||
| 849 | msgstr "" | ||
| 850 | |||
| 851 | #: utils/cpuidle-info.c:94 | ||
| 852 | #, fuzzy, c-format | ||
| 853 | msgid "CPUidle driver: %s\n" | ||
| 854 | msgstr " Treiber: %s\n" | ||
| 855 | |||
| 856 | #: utils/cpuidle-info.c:99 | ||
| 857 | #, c-format | ||
| 858 | msgid "Could not determine cpuidle governor\n" | ||
| 859 | msgstr "" | ||
| 860 | |||
| 861 | #: utils/cpuidle-info.c:103 | ||
| 862 | #, c-format | ||
| 863 | msgid "CPUidle governor: %s\n" | ||
| 864 | msgstr "" | ||
| 865 | |||
| 866 | #: utils/cpuidle-info.c:122 | ||
| 867 | #, c-format | ||
| 868 | msgid "CPU %u: Can't read C-state info\n" | ||
| 869 | msgstr "" | ||
| 870 | |||
| 871 | #. printf("Cstates: %d\n", cstates); | ||
| 872 | #: utils/cpuidle-info.c:127 | ||
| 873 | #, c-format | ||
| 874 | msgid "active state: C0\n" | ||
| 875 | msgstr "" | ||
| 876 | |||
| 877 | #: utils/cpuidle-info.c:128 | ||
| 878 | #, c-format | ||
| 879 | msgid "max_cstate: C%u\n" | ||
| 880 | msgstr "" | ||
| 881 | |||
| 882 | #: utils/cpuidle-info.c:129 | ||
| 883 | #, fuzzy, c-format | ||
| 884 | msgid "maximum allowed latency: %lu usec\n" | ||
| 885 | msgstr " Maximale Dauer eines Taktfrequenzwechsels: " | ||
| 886 | |||
| 887 | #: utils/cpuidle-info.c:130 | ||
| 888 | #, c-format | ||
| 889 | msgid "states:\t\n" | ||
| 890 | msgstr "" | ||
| 891 | |||
| 892 | #: utils/cpuidle-info.c:132 | ||
| 893 | #, c-format | ||
| 894 | msgid " C%d: type[C%d] " | ||
| 895 | msgstr "" | ||
| 896 | |||
| 897 | #: utils/cpuidle-info.c:134 | ||
| 898 | #, c-format | ||
| 899 | msgid "promotion[--] demotion[--] " | ||
| 900 | msgstr "" | ||
| 901 | |||
| 902 | #: utils/cpuidle-info.c:135 | ||
| 903 | #, c-format | ||
| 904 | msgid "latency[%03lu] " | ||
| 905 | msgstr "" | ||
| 906 | |||
| 907 | #: utils/cpuidle-info.c:137 | ||
| 908 | #, c-format | ||
| 909 | msgid "usage[%08lu] " | ||
| 910 | msgstr "" | ||
| 911 | |||
| 912 | #: utils/cpuidle-info.c:139 | ||
| 913 | #, c-format | ||
| 914 | msgid "duration[%020Lu] \n" | ||
| 915 | msgstr "" | ||
| 916 | |||
| 917 | #: utils/cpuidle-info.c:147 | ||
| 918 | #, fuzzy, c-format | ||
| 919 | msgid "Usage: cpupower idleinfo [options]\n" | ||
| 920 | msgstr "Aufruf: cpufreq-info [Optionen]\n" | ||
| 921 | |||
| 922 | #: utils/cpuidle-info.c:149 | ||
| 923 | #, fuzzy, c-format | ||
| 924 | msgid " -s, --silent Only show general C-state information\n" | ||
| 925 | msgstr "" | ||
| 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 | ||
| 931 | msgid "" | ||
| 932 | " -o, --proc Prints out information like provided by the /proc/" | ||
| 933 | "acpi/processor/*/power\n" | ||
| 934 | " interface in older kernels\n" | ||
| 935 | msgstr "" | ||
| 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 | ||
| 943 | msgid "You can't specify more than one output-specific argument\n" | ||
| 944 | msgstr "" | ||
| 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 000000000000..245ad20a9bf9 --- /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 | ||
| 7 | msgid "" | ||
| 8 | msgstr "" | ||
| 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 | ||
| 21 | msgid "Processor Core C3" | ||
| 22 | msgstr "" | ||
| 23 | |||
| 24 | #: utils/idle_monitor/nhm_idle.c:43 | ||
| 25 | msgid "Processor Core C6" | ||
| 26 | msgstr "" | ||
| 27 | |||
| 28 | #: utils/idle_monitor/nhm_idle.c:51 | ||
| 29 | msgid "Processor Package C3" | ||
| 30 | msgstr "" | ||
| 31 | |||
| 32 | #: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70 | ||
| 33 | msgid "Processor Package C6" | ||
| 34 | msgstr "" | ||
| 35 | |||
| 36 | #: utils/idle_monitor/snb_idle.c:33 | ||
| 37 | msgid "Processor Core C7" | ||
| 38 | msgstr "" | ||
| 39 | |||
| 40 | #: utils/idle_monitor/snb_idle.c:40 | ||
| 41 | msgid "Processor Package C2" | ||
| 42 | msgstr "" | ||
| 43 | |||
| 44 | #: utils/idle_monitor/snb_idle.c:47 | ||
| 45 | msgid "Processor Package C7" | ||
| 46 | msgstr "" | ||
| 47 | |||
| 48 | #: utils/idle_monitor/amd_fam14h_idle.c:56 | ||
| 49 | msgid "Package in sleep state (PC1 or deeper)" | ||
| 50 | msgstr "" | ||
| 51 | |||
| 52 | #: utils/idle_monitor/amd_fam14h_idle.c:63 | ||
| 53 | msgid "Processor Package C1" | ||
| 54 | msgstr "" | ||
| 55 | |||
| 56 | #: utils/idle_monitor/amd_fam14h_idle.c:77 | ||
| 57 | msgid "North Bridge P1 boolean counter (returns 0 or 1)" | ||
| 58 | msgstr "" | ||
| 59 | |||
| 60 | #: utils/idle_monitor/mperf_monitor.c:35 | ||
| 61 | msgid "Processor Core not idle" | ||
| 62 | msgstr "" | ||
| 63 | |||
| 64 | #: utils/idle_monitor/mperf_monitor.c:42 | ||
| 65 | msgid "Processor Core in an idle state" | ||
| 66 | msgstr "" | ||
| 67 | |||
| 68 | #: utils/idle_monitor/mperf_monitor.c:50 | ||
| 69 | msgid "Average Frequency (including boost) in MHz" | ||
| 70 | msgstr "" | ||
| 71 | |||
| 72 | #: utils/idle_monitor/cpupower-monitor.c:66 | ||
| 73 | #, c-format | ||
| 74 | msgid "" | ||
| 75 | "cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " | ||
| 76 | "interval_sec | -c command ...]\n" | ||
| 77 | msgstr "" | ||
| 78 | |||
| 79 | #: utils/idle_monitor/cpupower-monitor.c:69 | ||
| 80 | #, c-format | ||
| 81 | msgid "" | ||
| 82 | "cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " | ||
| 83 | "interval_sec | -c command ...]\n" | ||
| 84 | msgstr "" | ||
| 85 | |||
| 86 | #: utils/idle_monitor/cpupower-monitor.c:71 | ||
| 87 | #, c-format | ||
| 88 | msgid "\t -v: be more verbose\n" | ||
| 89 | msgstr "" | ||
| 90 | |||
| 91 | #: utils/idle_monitor/cpupower-monitor.c:73 | ||
| 92 | #, c-format | ||
| 93 | msgid "\t -h: print this help\n" | ||
| 94 | msgstr "" | ||
| 95 | |||
| 96 | #: utils/idle_monitor/cpupower-monitor.c:74 | ||
| 97 | #, c-format | ||
| 98 | msgid "\t -i: time intervall to measure for in seconds (default 1)\n" | ||
| 99 | msgstr "" | ||
| 100 | |||
| 101 | #: utils/idle_monitor/cpupower-monitor.c:75 | ||
| 102 | #, c-format | ||
| 103 | msgid "\t -t: show CPU topology/hierarchy\n" | ||
| 104 | msgstr "" | ||
| 105 | |||
| 106 | #: utils/idle_monitor/cpupower-monitor.c:76 | ||
| 107 | #, c-format | ||
| 108 | msgid "\t -l: list available CPU sleep monitors (for use with -m)\n" | ||
| 109 | msgstr "" | ||
| 110 | |||
| 111 | #: utils/idle_monitor/cpupower-monitor.c:77 | ||
| 112 | #, c-format | ||
| 113 | msgid "\t -m: show specific CPU sleep monitors only (in same order)\n" | ||
| 114 | msgstr "" | ||
| 115 | |||
| 116 | #: utils/idle_monitor/cpupower-monitor.c:79 | ||
| 117 | #, c-format | ||
| 118 | msgid "" | ||
| 119 | "only one of: -t, -l, -m are allowed\n" | ||
| 120 | "If none of them is passed," | ||
| 121 | msgstr "" | ||
| 122 | |||
| 123 | #: utils/idle_monitor/cpupower-monitor.c:80 | ||
| 124 | #, c-format | ||
| 125 | msgid " all supported monitors are shown\n" | ||
| 126 | msgstr "" | ||
| 127 | |||
| 128 | #: utils/idle_monitor/cpupower-monitor.c:197 | ||
| 129 | #, c-format | ||
| 130 | msgid "Monitor %s, Counter %s has no count function. Implementation error\n" | ||
| 131 | msgstr "" | ||
| 132 | |||
| 133 | #: utils/idle_monitor/cpupower-monitor.c:207 | ||
| 134 | #, c-format | ||
| 135 | msgid " *is offline\n" | ||
| 136 | msgstr "" | ||
| 137 | |||
| 138 | #: utils/idle_monitor/cpupower-monitor.c:236 | ||
| 139 | #, c-format | ||
| 140 | msgid "%s: max monitor name length (%d) exceeded\n" | ||
| 141 | msgstr "" | ||
| 142 | |||
| 143 | #: utils/idle_monitor/cpupower-monitor.c:250 | ||
| 144 | #, c-format | ||
| 145 | msgid "No matching monitor found in %s, try -l option\n" | ||
| 146 | msgstr "" | ||
| 147 | |||
| 148 | #: utils/idle_monitor/cpupower-monitor.c:266 | ||
| 149 | #, c-format | ||
| 150 | msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n" | ||
| 151 | msgstr "" | ||
| 152 | |||
| 153 | #: utils/idle_monitor/cpupower-monitor.c:319 | ||
| 154 | #, c-format | ||
| 155 | msgid "%s took %.5f seconds and exited with status %d\n" | ||
| 156 | msgstr "" | ||
| 157 | |||
| 158 | #: utils/idle_monitor/cpupower-monitor.c:406 | ||
| 159 | #, c-format | ||
| 160 | msgid "Cannot read number of available processors\n" | ||
| 161 | msgstr "" | ||
| 162 | |||
| 163 | #: utils/idle_monitor/cpupower-monitor.c:417 | ||
| 164 | #, c-format | ||
| 165 | msgid "Available monitor %s needs root access\n" | ||
| 166 | msgstr "" | ||
| 167 | |||
| 168 | #: utils/idle_monitor/cpupower-monitor.c:428 | ||
| 169 | #, c-format | ||
| 170 | msgid "No HW Cstate monitors found\n" | ||
| 171 | msgstr "" | ||
| 172 | |||
| 173 | #: utils/cpupower.c:78 | ||
| 174 | #, c-format | ||
| 175 | msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n" | ||
| 176 | msgstr "" | ||
| 177 | |||
| 178 | #: utils/cpupower.c:79 | ||
| 179 | #, c-format | ||
| 180 | msgid "cpupower --version\n" | ||
| 181 | msgstr "" | ||
| 182 | |||
| 183 | #: utils/cpupower.c:80 | ||
| 184 | #, c-format | ||
| 185 | msgid "Supported subcommands are:\n" | ||
| 186 | msgstr "" | ||
| 187 | |||
| 188 | #: utils/cpupower.c:83 | ||
| 189 | #, c-format | ||
| 190 | msgid "" | ||
| 191 | "\n" | ||
| 192 | "Some subcommands can make use of the -c cpulist option.\n" | ||
| 193 | msgstr "" | ||
| 194 | |||
| 195 | #: utils/cpupower.c:84 | ||
| 196 | #, c-format | ||
| 197 | msgid "Look at the general cpupower manpage how to use it\n" | ||
| 198 | msgstr "" | ||
| 199 | |||
| 200 | #: utils/cpupower.c:85 | ||
| 201 | #, c-format | ||
| 202 | msgid "and read up the subcommand's manpage whether it is supported.\n" | ||
| 203 | msgstr "" | ||
| 204 | |||
| 205 | #: utils/cpupower.c:86 | ||
| 206 | #, c-format | ||
| 207 | msgid "" | ||
| 208 | "\n" | ||
| 209 | "Use cpupower help subcommand for getting help for above subcommands.\n" | ||
| 210 | msgstr "" | ||
| 211 | |||
| 212 | #: utils/cpupower.c:91 | ||
| 213 | #, c-format | ||
| 214 | msgid "Report errors and bugs to %s, please.\n" | ||
| 215 | msgstr "Veuillez rapportez les erreurs et les bogues à %s, s'il vous plait.\n" | ||
| 216 | |||
| 217 | #: utils/cpupower.c:114 | ||
| 218 | #, c-format | ||
| 219 | msgid "Error parsing cpu list\n" | ||
| 220 | msgstr "" | ||
| 221 | |||
| 222 | #: utils/cpupower.c:172 | ||
| 223 | #, c-format | ||
| 224 | msgid "Subcommand %s needs root privileges\n" | ||
| 225 | msgstr "" | ||
| 226 | |||
| 227 | #: utils/cpufreq-info.c:31 | ||
| 228 | #, c-format | ||
| 229 | msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n" | ||
| 230 | msgstr "Détermination du nombre de CPUs (%s : %s) impossible. Assume 1\n" | ||
| 231 | |||
| 232 | #: utils/cpufreq-info.c:63 | ||
| 233 | #, c-format | ||
| 234 | msgid "" | ||
| 235 | " minimum CPU frequency - maximum CPU frequency - governor\n" | ||
| 236 | msgstr "" | ||
| 237 | " Fréquence CPU minimale - Fréquence CPU maximale - régulateur\n" | ||
| 238 | |||
| 239 | #: utils/cpufreq-info.c:151 | ||
| 240 | #, c-format | ||
| 241 | msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n" | ||
| 242 | msgstr "" | ||
| 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 | ||
| 251 | msgid " boost state support: \n" | ||
| 252 | msgstr "" | ||
| 253 | |||
| 254 | #: utils/cpufreq-info.c:163 | ||
| 255 | #, c-format | ||
| 256 | msgid " Supported: %s\n" | ||
| 257 | msgstr "" | ||
| 258 | |||
| 259 | #: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 | ||
| 260 | msgid "yes" | ||
| 261 | msgstr "" | ||
| 262 | |||
| 263 | #: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 | ||
| 264 | msgid "no" | ||
| 265 | msgstr "" | ||
| 266 | |||
| 267 | #: utils/cpufreq-info.c:164 | ||
| 268 | #, fuzzy, c-format | ||
| 269 | msgid " Active: %s\n" | ||
| 270 | msgstr " pilote : %s\n" | ||
| 271 | |||
| 272 | #: utils/cpufreq-info.c:177 | ||
| 273 | #, c-format | ||
| 274 | msgid " Boost States: %d\n" | ||
| 275 | msgstr "" | ||
| 276 | |||
| 277 | #: utils/cpufreq-info.c:178 | ||
| 278 | #, c-format | ||
| 279 | msgid " Total States: %d\n" | ||
| 280 | msgstr "" | ||
| 281 | |||
| 282 | #: utils/cpufreq-info.c:181 | ||
| 283 | #, c-format | ||
| 284 | msgid " Pstate-Pb%d: %luMHz (boost state)\n" | ||
| 285 | msgstr "" | ||
| 286 | |||
| 287 | #: utils/cpufreq-info.c:184 | ||
| 288 | #, c-format | ||
| 289 | msgid " Pstate-P%d: %luMHz\n" | ||
| 290 | msgstr "" | ||
| 291 | |||
| 292 | #: utils/cpufreq-info.c:211 | ||
| 293 | #, c-format | ||
| 294 | msgid " no or unknown cpufreq driver is active on this CPU\n" | ||
| 295 | msgstr " pas de pilotes cpufreq reconnu pour ce CPU\n" | ||
| 296 | |||
| 297 | #: utils/cpufreq-info.c:213 | ||
| 298 | #, c-format | ||
| 299 | msgid " driver: %s\n" | ||
| 300 | msgstr " pilote : %s\n" | ||
| 301 | |||
| 302 | #: utils/cpufreq-info.c:219 | ||
| 303 | #, fuzzy, c-format | ||
| 304 | msgid " CPUs which run at the same hardware frequency: " | ||
| 305 | msgstr " CPUs qui doivent changer de fréquences en même temps : " | ||
| 306 | |||
| 307 | #: utils/cpufreq-info.c:230 | ||
| 308 | #, fuzzy, c-format | ||
| 309 | msgid " CPUs which need to have their frequency coordinated by software: " | ||
| 310 | msgstr " CPUs qui doivent changer de fréquences en même temps : " | ||
| 311 | |||
| 312 | #: utils/cpufreq-info.c:241 | ||
| 313 | #, c-format | ||
| 314 | msgid " maximum transition latency: " | ||
| 315 | msgstr "" | ||
| 316 | |||
| 317 | #: utils/cpufreq-info.c:247 | ||
| 318 | #, c-format | ||
| 319 | msgid " hardware limits: " | ||
| 320 | msgstr " limitation matérielle : " | ||
| 321 | |||
| 322 | #: utils/cpufreq-info.c:256 | ||
| 323 | #, c-format | ||
| 324 | msgid " available frequency steps: " | ||
| 325 | msgstr " plage de fréquence : " | ||
| 326 | |||
| 327 | #: utils/cpufreq-info.c:269 | ||
| 328 | #, c-format | ||
| 329 | msgid " available cpufreq governors: " | ||
| 330 | msgstr " régulateurs disponibles : " | ||
| 331 | |||
| 332 | #: utils/cpufreq-info.c:280 | ||
| 333 | #, c-format | ||
| 334 | msgid " current policy: frequency should be within " | ||
| 335 | msgstr " tactique actuelle : la fréquence doit être comprise entre " | ||
| 336 | |||
| 337 | #: utils/cpufreq-info.c:282 | ||
| 338 | #, c-format | ||
| 339 | msgid " and " | ||
| 340 | msgstr " et " | ||
| 341 | |||
| 342 | #: utils/cpufreq-info.c:286 | ||
| 343 | #, c-format | ||
| 344 | msgid "" | ||
| 345 | "The governor \"%s\" may decide which speed to use\n" | ||
| 346 | " within this range.\n" | ||
| 347 | msgstr "" | ||
| 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 | ||
| 353 | msgid " current CPU frequency is " | ||
| 354 | msgstr " la fréquence actuelle de ce CPU est " | ||
| 355 | |||
| 356 | #: utils/cpufreq-info.c:296 | ||
| 357 | #, c-format | ||
| 358 | msgid " (asserted by call to hardware)" | ||
| 359 | msgstr " (vérifié par un appel direct du matériel)" | ||
| 360 | |||
| 361 | #: utils/cpufreq-info.c:304 | ||
| 362 | #, c-format | ||
| 363 | msgid " cpufreq stats: " | ||
| 364 | msgstr " des statistique concernant cpufreq:" | ||
| 365 | |||
| 366 | #: utils/cpufreq-info.c:472 | ||
| 367 | #, fuzzy, c-format | ||
| 368 | msgid "Usage: cpupower freqinfo [options]\n" | ||
| 369 | msgstr "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 | ||
| 374 | msgid "Options:\n" | ||
| 375 | msgstr "Options :\n" | ||
| 376 | |||
| 377 | #: utils/cpufreq-info.c:474 | ||
| 378 | #, fuzzy, c-format | ||
| 379 | msgid " -e, --debug Prints out debug information [default]\n" | ||
| 380 | msgstr " -e, --debug Afficher les informations de déboguage\n" | ||
| 381 | |||
| 382 | #: utils/cpufreq-info.c:475 | ||
| 383 | #, c-format | ||
| 384 | msgid "" | ||
| 385 | " -f, --freq Get frequency the CPU currently runs at, according\n" | ||
| 386 | " to the cpufreq core *\n" | ||
| 387 | msgstr "" | ||
| 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 | ||
| 393 | msgid "" | ||
| 394 | " -w, --hwfreq Get frequency the CPU currently runs at, by reading\n" | ||
| 395 | " it from hardware (only available to root) *\n" | ||
| 396 | msgstr "" | ||
| 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 | ||
| 402 | msgid "" | ||
| 403 | " -l, --hwlimits Determine the minimum and maximum CPU frequency " | ||
| 404 | "allowed *\n" | ||
| 405 | msgstr "" | ||
| 406 | " -l, --hwlimits Affiche les fréquences minimales et maximales du CPU " | ||
| 407 | "*\n" | ||
| 408 | |||
| 409 | #: utils/cpufreq-info.c:480 | ||
| 410 | #, c-format | ||
| 411 | msgid " -d, --driver Determines the used cpufreq kernel driver *\n" | ||
| 412 | msgstr " -d, --driver Affiche le pilote cpufreq utilisé *\n" | ||
| 413 | |||
| 414 | #: utils/cpufreq-info.c:481 | ||
| 415 | #, c-format | ||
| 416 | msgid " -p, --policy Gets the currently used cpufreq policy *\n" | ||
| 417 | msgstr " -p, --policy Affiche la tactique actuelle de cpufreq *\n" | ||
| 418 | |||
| 419 | #: utils/cpufreq-info.c:482 | ||
| 420 | #, c-format | ||
| 421 | msgid " -g, --governors Determines available cpufreq governors *\n" | ||
| 422 | msgstr "" | ||
| 423 | " -g, --governors Affiche les régulateurs disponibles de cpufreq *\n" | ||
| 424 | |||
| 425 | #: utils/cpufreq-info.c:483 | ||
| 426 | #, fuzzy, c-format | ||
| 427 | msgid "" | ||
| 428 | " -r, --related-cpus Determines which CPUs run at the same hardware " | ||
| 429 | "frequency *\n" | ||
| 430 | msgstr "" | ||
| 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 | ||
| 436 | msgid "" | ||
| 437 | " -a, --affected-cpus Determines which CPUs need to have their frequency\n" | ||
| 438 | " coordinated by software *\n" | ||
| 439 | msgstr "" | ||
| 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 | ||
| 445 | msgid " -s, --stats Shows cpufreq statistics if available\n" | ||
| 446 | msgstr "" | ||
| 447 | " -s, --stats Indique des statistiques concernant cpufreq, si\n" | ||
| 448 | " disponibles\n" | ||
| 449 | |||
| 450 | #: utils/cpufreq-info.c:487 | ||
| 451 | #, fuzzy, c-format | ||
| 452 | msgid "" | ||
| 453 | " -y, --latency Determines the maximum latency on CPU frequency " | ||
| 454 | "changes *\n" | ||
| 455 | msgstr "" | ||
| 456 | " -l, --hwlimits Affiche les fréquences minimales et maximales du CPU " | ||
| 457 | "*\n" | ||
| 458 | |||
| 459 | #: utils/cpufreq-info.c:488 | ||
| 460 | #, c-format | ||
| 461 | msgid " -b, --boost Checks for turbo or boost modes *\n" | ||
| 462 | msgstr "" | ||
| 463 | |||
| 464 | #: utils/cpufreq-info.c:489 | ||
| 465 | #, c-format | ||
| 466 | msgid "" | ||
| 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" | ||
| 470 | msgstr "" | ||
| 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 | ||
| 478 | msgid "" | ||
| 479 | " -m, --human human-readable output for the -f, -w, -s and -y " | ||
| 480 | "parameters\n" | ||
| 481 | msgstr "" | ||
| 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 | ||
| 487 | msgid " -h, --help Prints out this screen\n" | ||
| 488 | msgstr " -h, --help affiche l'aide-mémoire\n" | ||
| 489 | |||
| 490 | #: utils/cpufreq-info.c:495 | ||
| 491 | #, c-format | ||
| 492 | msgid "" | ||
| 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" | ||
| 495 | msgstr "" | ||
| 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 | ||
| 502 | msgid "" | ||
| 503 | "For the arguments marked with *, omitting the -c or --cpu argument is\n" | ||
| 504 | "equivalent to setting it to zero\n" | ||
| 505 | msgstr "Les arguments avec un * utiliseront le CPU 0 si -c (--cpu) est omis\n" | ||
| 506 | |||
| 507 | #: utils/cpufreq-info.c:580 | ||
| 508 | #, c-format | ||
| 509 | msgid "" | ||
| 510 | "The argument passed to this tool can't be combined with passing a --cpu " | ||
| 511 | "argument\n" | ||
| 512 | msgstr "Cette option est incompatible avec --cpu\n" | ||
| 513 | |||
| 514 | #: utils/cpufreq-info.c:596 | ||
| 515 | #, c-format | ||
| 516 | msgid "" | ||
| 517 | "You can't specify more than one --cpu parameter and/or\n" | ||
| 518 | "more than one output-specific argument\n" | ||
| 519 | msgstr "" | ||
| 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 | ||
| 526 | msgid "invalid or unknown argument\n" | ||
| 527 | msgstr "option invalide\n" | ||
| 528 | |||
| 529 | #: utils/cpufreq-info.c:617 | ||
| 530 | #, c-format | ||
| 531 | msgid "couldn't analyze CPU %d as it doesn't seem to be present\n" | ||
| 532 | msgstr "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 | ||
| 536 | msgid "analyzing CPU %d:\n" | ||
| 537 | msgstr "analyse du CPU %d :\n" | ||
| 538 | |||
| 539 | #: utils/cpufreq-set.c:25 | ||
| 540 | #, fuzzy, c-format | ||
| 541 | msgid "Usage: cpupower frequency-set [options]\n" | ||
| 542 | msgstr "Usage : cpufreq-set [options]\n" | ||
| 543 | |||
| 544 | #: utils/cpufreq-set.c:27 | ||
| 545 | #, c-format | ||
| 546 | msgid "" | ||
| 547 | " -d FREQ, --min FREQ new minimum CPU frequency the governor may " | ||
| 548 | "select\n" | ||
| 549 | msgstr "" | ||
| 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 | ||
| 555 | msgid "" | ||
| 556 | " -u FREQ, --max FREQ new maximum CPU frequency the governor may " | ||
| 557 | "select\n" | ||
| 558 | msgstr "" | ||
| 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 | ||
| 564 | msgid " -g GOV, --governor GOV new cpufreq governor\n" | ||
| 565 | msgstr " -g GOV, --governor GOV active le régulateur GOV\n" | ||
| 566 | |||
| 567 | #: utils/cpufreq-set.c:30 | ||
| 568 | #, c-format | ||
| 569 | msgid "" | ||
| 570 | " -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n" | ||
| 571 | " governor to be available and loaded\n" | ||
| 572 | msgstr "" | ||
| 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 | ||
| 579 | msgid " -r, --related Switches all hardware-related CPUs\n" | ||
| 580 | msgstr "" | ||
| 581 | |||
| 582 | #: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27 | ||
| 583 | #, fuzzy, c-format | ||
| 584 | msgid " -h, --help Prints out this screen\n" | ||
| 585 | msgstr " -h, --help affiche l'aide-mémoire\n" | ||
| 586 | |||
| 587 | #: utils/cpufreq-set.c:35 | ||
| 588 | #, fuzzy, c-format | ||
| 589 | msgid "" | ||
| 590 | "Notes:\n" | ||
| 591 | "1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n" | ||
| 592 | msgstr "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 | ||
| 596 | msgid "" | ||
| 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" | ||
| 603 | msgstr "" | ||
| 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 | ||
| 614 | msgid "" | ||
| 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" | ||
| 624 | msgstr "" | ||
| 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 | ||
| 638 | msgid "wrong, unknown or unhandled CPU?\n" | ||
| 639 | msgstr "CPU inconnu ou non supporté ?\n" | ||
| 640 | |||
| 641 | #: utils/cpufreq-set.c:302 | ||
| 642 | #, c-format | ||
| 643 | msgid "" | ||
| 644 | "the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n" | ||
| 645 | "-g/--governor parameters\n" | ||
| 646 | msgstr "" | ||
| 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 | ||
| 652 | msgid "" | ||
| 653 | "At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n" | ||
| 654 | "-g/--governor must be passed\n" | ||
| 655 | msgstr "" | ||
| 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 | ||
| 661 | msgid "Setting cpu: %d\n" | ||
| 662 | msgstr "" | ||
| 663 | |||
| 664 | #: utils/cpupower-set.c:22 | ||
| 665 | #, c-format | ||
| 666 | msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n" | ||
| 667 | msgstr "" | ||
| 668 | |||
| 669 | #: utils/cpupower-set.c:24 | ||
| 670 | #, c-format | ||
| 671 | msgid "" | ||
| 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" | ||
| 674 | msgstr "" | ||
| 675 | |||
| 676 | #: utils/cpupower-set.c:26 | ||
| 677 | #, c-format | ||
| 678 | msgid "" | ||
| 679 | " -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n" | ||
| 680 | msgstr "" | ||
| 681 | |||
| 682 | #: utils/cpupower-set.c:27 | ||
| 683 | #, c-format | ||
| 684 | msgid "" | ||
| 685 | " -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler " | ||
| 686 | "policy.\n" | ||
| 687 | msgstr "" | ||
| 688 | |||
| 689 | #: utils/cpupower-set.c:80 | ||
| 690 | #, c-format | ||
| 691 | msgid "--perf-bias param out of range [0-%d]\n" | ||
| 692 | msgstr "" | ||
| 693 | |||
| 694 | #: utils/cpupower-set.c:91 | ||
| 695 | #, c-format | ||
| 696 | msgid "--sched-mc param out of range [0-%d]\n" | ||
| 697 | msgstr "" | ||
| 698 | |||
| 699 | #: utils/cpupower-set.c:102 | ||
| 700 | #, c-format | ||
| 701 | msgid "--sched-smt param out of range [0-%d]\n" | ||
| 702 | msgstr "" | ||
| 703 | |||
| 704 | #: utils/cpupower-set.c:121 | ||
| 705 | #, c-format | ||
| 706 | msgid "Error setting sched-mc %s\n" | ||
| 707 | msgstr "" | ||
| 708 | |||
| 709 | #: utils/cpupower-set.c:127 | ||
| 710 | #, c-format | ||
| 711 | msgid "Error setting sched-smt %s\n" | ||
| 712 | msgstr "" | ||
| 713 | |||
| 714 | #: utils/cpupower-set.c:146 | ||
| 715 | #, c-format | ||
| 716 | msgid "Error setting perf-bias value on CPU %d\n" | ||
| 717 | msgstr "" | ||
| 718 | |||
| 719 | #: utils/cpupower-info.c:21 | ||
| 720 | #, c-format | ||
| 721 | msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n" | ||
| 722 | msgstr "" | ||
| 723 | |||
| 724 | #: utils/cpupower-info.c:23 | ||
| 725 | #, c-format | ||
| 726 | msgid "" | ||
| 727 | " -b, --perf-bias Gets CPU's power vs performance policy on some\n" | ||
| 728 | " Intel models [0-15], see manpage for details\n" | ||
| 729 | msgstr "" | ||
| 730 | |||
| 731 | #: utils/cpupower-info.c:25 | ||
| 732 | #, fuzzy, c-format | ||
| 733 | msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n" | ||
| 734 | msgstr " -p, --policy Affiche la tactique actuelle de cpufreq *\n" | ||
| 735 | |||
| 736 | #: utils/cpupower-info.c:26 | ||
| 737 | #, c-format | ||
| 738 | msgid "" | ||
| 739 | " -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n" | ||
| 740 | msgstr "" | ||
| 741 | |||
| 742 | #: utils/cpupower-info.c:28 | ||
| 743 | #, c-format | ||
| 744 | msgid "" | ||
| 745 | "\n" | ||
| 746 | "Passing no option will show all info, by default only on core 0\n" | ||
| 747 | msgstr "" | ||
| 748 | |||
| 749 | #: utils/cpupower-info.c:102 | ||
| 750 | #, c-format | ||
| 751 | msgid "System's multi core scheduler setting: " | ||
| 752 | msgstr "" | ||
| 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 | ||
| 757 | msgid "not supported\n" | ||
| 758 | msgstr "" | ||
| 759 | |||
| 760 | #: utils/cpupower-info.c:111 | ||
| 761 | #, c-format | ||
| 762 | msgid "System's thread sibling scheduler setting: " | ||
| 763 | msgstr "" | ||
| 764 | |||
| 765 | #: utils/cpupower-info.c:126 | ||
| 766 | #, c-format | ||
| 767 | msgid "Intel's performance bias setting needs root privileges\n" | ||
| 768 | msgstr "" | ||
| 769 | |||
| 770 | #: utils/cpupower-info.c:128 | ||
| 771 | #, c-format | ||
| 772 | msgid "System does not support Intel's performance bias setting\n" | ||
| 773 | msgstr "" | ||
| 774 | |||
| 775 | #: utils/cpupower-info.c:147 | ||
| 776 | #, c-format | ||
| 777 | msgid "Could not read perf-bias value\n" | ||
| 778 | msgstr "" | ||
| 779 | |||
| 780 | #: utils/cpupower-info.c:150 | ||
| 781 | #, c-format | ||
| 782 | msgid "perf-bias: %d\n" | ||
| 783 | msgstr "" | ||
| 784 | |||
| 785 | #: utils/cpuidle-info.c:28 | ||
| 786 | #, fuzzy, c-format | ||
| 787 | msgid "Analyzing CPU %d:\n" | ||
| 788 | msgstr "analyse du CPU %d :\n" | ||
| 789 | |||
| 790 | #: utils/cpuidle-info.c:32 | ||
| 791 | #, c-format | ||
| 792 | msgid "CPU %u: No idle states\n" | ||
| 793 | msgstr "" | ||
| 794 | |||
| 795 | #: utils/cpuidle-info.c:36 | ||
| 796 | #, c-format | ||
| 797 | msgid "CPU %u: Can't read idle state info\n" | ||
| 798 | msgstr "" | ||
| 799 | |||
| 800 | #: utils/cpuidle-info.c:41 | ||
| 801 | #, c-format | ||
| 802 | msgid "Could not determine max idle state %u\n" | ||
| 803 | msgstr "" | ||
| 804 | |||
| 805 | #: utils/cpuidle-info.c:46 | ||
| 806 | #, c-format | ||
| 807 | msgid "Number of idle states: %d\n" | ||
| 808 | msgstr "" | ||
| 809 | |||
| 810 | #: utils/cpuidle-info.c:48 | ||
| 811 | #, fuzzy, c-format | ||
| 812 | msgid "Available idle states:" | ||
| 813 | msgstr " plage de fréquence : " | ||
| 814 | |||
| 815 | #: utils/cpuidle-info.c:71 | ||
| 816 | #, c-format | ||
| 817 | msgid "Flags/Description: %s\n" | ||
| 818 | msgstr "" | ||
| 819 | |||
| 820 | #: utils/cpuidle-info.c:74 | ||
| 821 | #, c-format | ||
| 822 | msgid "Latency: %lu\n" | ||
| 823 | msgstr "" | ||
| 824 | |||
| 825 | #: utils/cpuidle-info.c:76 | ||
| 826 | #, c-format | ||
| 827 | msgid "Usage: %lu\n" | ||
| 828 | msgstr "" | ||
| 829 | |||
| 830 | #: utils/cpuidle-info.c:78 | ||
| 831 | #, c-format | ||
| 832 | msgid "Duration: %llu\n" | ||
| 833 | msgstr "" | ||
| 834 | |||
| 835 | #: utils/cpuidle-info.c:90 | ||
| 836 | #, c-format | ||
| 837 | msgid "Could not determine cpuidle driver\n" | ||
| 838 | msgstr "" | ||
| 839 | |||
| 840 | #: utils/cpuidle-info.c:94 | ||
| 841 | #, fuzzy, c-format | ||
| 842 | msgid "CPUidle driver: %s\n" | ||
| 843 | msgstr " pilote : %s\n" | ||
| 844 | |||
| 845 | #: utils/cpuidle-info.c:99 | ||
| 846 | #, c-format | ||
| 847 | msgid "Could not determine cpuidle governor\n" | ||
| 848 | msgstr "" | ||
| 849 | |||
| 850 | #: utils/cpuidle-info.c:103 | ||
| 851 | #, c-format | ||
| 852 | msgid "CPUidle governor: %s\n" | ||
| 853 | msgstr "" | ||
| 854 | |||
| 855 | #: utils/cpuidle-info.c:122 | ||
| 856 | #, c-format | ||
| 857 | msgid "CPU %u: Can't read C-state info\n" | ||
| 858 | msgstr "" | ||
| 859 | |||
| 860 | #. printf("Cstates: %d\n", cstates); | ||
| 861 | #: utils/cpuidle-info.c:127 | ||
| 862 | #, c-format | ||
| 863 | msgid "active state: C0\n" | ||
| 864 | msgstr "" | ||
| 865 | |||
| 866 | #: utils/cpuidle-info.c:128 | ||
| 867 | #, c-format | ||
| 868 | msgid "max_cstate: C%u\n" | ||
| 869 | msgstr "" | ||
| 870 | |||
| 871 | #: utils/cpuidle-info.c:129 | ||
| 872 | #, c-format | ||
| 873 | msgid "maximum allowed latency: %lu usec\n" | ||
| 874 | msgstr "" | ||
| 875 | |||
| 876 | #: utils/cpuidle-info.c:130 | ||
| 877 | #, c-format | ||
| 878 | msgid "states:\t\n" | ||
| 879 | msgstr "" | ||
| 880 | |||
| 881 | #: utils/cpuidle-info.c:132 | ||
| 882 | #, c-format | ||
| 883 | msgid " C%d: type[C%d] " | ||
| 884 | msgstr "" | ||
| 885 | |||
| 886 | #: utils/cpuidle-info.c:134 | ||
| 887 | #, c-format | ||
| 888 | msgid "promotion[--] demotion[--] " | ||
| 889 | msgstr "" | ||
| 890 | |||
| 891 | #: utils/cpuidle-info.c:135 | ||
| 892 | #, c-format | ||
| 893 | msgid "latency[%03lu] " | ||
| 894 | msgstr "" | ||
| 895 | |||
| 896 | #: utils/cpuidle-info.c:137 | ||
| 897 | #, c-format | ||
| 898 | msgid "usage[%08lu] " | ||
| 899 | msgstr "" | ||
| 900 | |||
| 901 | #: utils/cpuidle-info.c:139 | ||
| 902 | #, c-format | ||
| 903 | msgid "duration[%020Lu] \n" | ||
| 904 | msgstr "" | ||
| 905 | |||
| 906 | #: utils/cpuidle-info.c:147 | ||
| 907 | #, fuzzy, c-format | ||
| 908 | msgid "Usage: cpupower idleinfo [options]\n" | ||
| 909 | msgstr "Usage : cpufreq-info [options]\n" | ||
| 910 | |||
| 911 | #: utils/cpuidle-info.c:149 | ||
| 912 | #, fuzzy, c-format | ||
| 913 | msgid " -s, --silent Only show general C-state information\n" | ||
| 914 | msgstr " -e, --debug Afficher les informations de déboguage\n" | ||
| 915 | |||
| 916 | #: utils/cpuidle-info.c:150 | ||
| 917 | #, fuzzy, c-format | ||
| 918 | msgid "" | ||
| 919 | " -o, --proc Prints out information like provided by the /proc/" | ||
| 920 | "acpi/processor/*/power\n" | ||
| 921 | " interface in older kernels\n" | ||
| 922 | msgstr "" | ||
| 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 | ||
| 930 | msgid "You can't specify more than one output-specific argument\n" | ||
| 931 | msgstr "" | ||
| 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 000000000000..f80c4ddb9bda --- /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 | # | ||
| 7 | msgid "" | ||
| 8 | msgstr "" | ||
| 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 | ||
| 21 | msgid "Processor Core C3" | ||
| 22 | msgstr "" | ||
| 23 | |||
| 24 | #: utils/idle_monitor/nhm_idle.c:43 | ||
| 25 | msgid "Processor Core C6" | ||
| 26 | msgstr "" | ||
| 27 | |||
| 28 | #: utils/idle_monitor/nhm_idle.c:51 | ||
| 29 | msgid "Processor Package C3" | ||
| 30 | msgstr "" | ||
| 31 | |||
| 32 | #: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70 | ||
| 33 | msgid "Processor Package C6" | ||
| 34 | msgstr "" | ||
| 35 | |||
| 36 | #: utils/idle_monitor/snb_idle.c:33 | ||
| 37 | msgid "Processor Core C7" | ||
| 38 | msgstr "" | ||
| 39 | |||
| 40 | #: utils/idle_monitor/snb_idle.c:40 | ||
| 41 | msgid "Processor Package C2" | ||
| 42 | msgstr "" | ||
| 43 | |||
| 44 | #: utils/idle_monitor/snb_idle.c:47 | ||
| 45 | msgid "Processor Package C7" | ||
| 46 | msgstr "" | ||
| 47 | |||
| 48 | #: utils/idle_monitor/amd_fam14h_idle.c:56 | ||
| 49 | msgid "Package in sleep state (PC1 or deeper)" | ||
| 50 | msgstr "" | ||
| 51 | |||
| 52 | #: utils/idle_monitor/amd_fam14h_idle.c:63 | ||
| 53 | msgid "Processor Package C1" | ||
| 54 | msgstr "" | ||
| 55 | |||
| 56 | #: utils/idle_monitor/amd_fam14h_idle.c:77 | ||
| 57 | msgid "North Bridge P1 boolean counter (returns 0 or 1)" | ||
| 58 | msgstr "" | ||
| 59 | |||
| 60 | #: utils/idle_monitor/mperf_monitor.c:35 | ||
| 61 | msgid "Processor Core not idle" | ||
| 62 | msgstr "" | ||
| 63 | |||
| 64 | #: utils/idle_monitor/mperf_monitor.c:42 | ||
| 65 | msgid "Processor Core in an idle state" | ||
| 66 | msgstr "" | ||
| 67 | |||
| 68 | #: utils/idle_monitor/mperf_monitor.c:50 | ||
| 69 | msgid "Average Frequency (including boost) in MHz" | ||
| 70 | msgstr "" | ||
| 71 | |||
| 72 | #: utils/idle_monitor/cpupower-monitor.c:66 | ||
| 73 | #, c-format | ||
| 74 | msgid "" | ||
| 75 | "cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " | ||
| 76 | "interval_sec | -c command ...]\n" | ||
| 77 | msgstr "" | ||
| 78 | |||
| 79 | #: utils/idle_monitor/cpupower-monitor.c:69 | ||
| 80 | #, c-format | ||
| 81 | msgid "" | ||
| 82 | "cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " | ||
| 83 | "interval_sec | -c command ...]\n" | ||
| 84 | msgstr "" | ||
| 85 | |||
| 86 | #: utils/idle_monitor/cpupower-monitor.c:71 | ||
| 87 | #, c-format | ||
| 88 | msgid "\t -v: be more verbose\n" | ||
| 89 | msgstr "" | ||
| 90 | |||
| 91 | #: utils/idle_monitor/cpupower-monitor.c:73 | ||
| 92 | #, c-format | ||
| 93 | msgid "\t -h: print this help\n" | ||
| 94 | msgstr "" | ||
| 95 | |||
| 96 | #: utils/idle_monitor/cpupower-monitor.c:74 | ||
| 97 | #, c-format | ||
| 98 | msgid "\t -i: time intervall to measure for in seconds (default 1)\n" | ||
| 99 | msgstr "" | ||
| 100 | |||
| 101 | #: utils/idle_monitor/cpupower-monitor.c:75 | ||
| 102 | #, c-format | ||
| 103 | msgid "\t -t: show CPU topology/hierarchy\n" | ||
| 104 | msgstr "" | ||
| 105 | |||
| 106 | #: utils/idle_monitor/cpupower-monitor.c:76 | ||
| 107 | #, c-format | ||
| 108 | msgid "\t -l: list available CPU sleep monitors (for use with -m)\n" | ||
| 109 | msgstr "" | ||
| 110 | |||
| 111 | #: utils/idle_monitor/cpupower-monitor.c:77 | ||
| 112 | #, c-format | ||
| 113 | msgid "\t -m: show specific CPU sleep monitors only (in same order)\n" | ||
| 114 | msgstr "" | ||
| 115 | |||
| 116 | #: utils/idle_monitor/cpupower-monitor.c:79 | ||
| 117 | #, c-format | ||
| 118 | msgid "" | ||
| 119 | "only one of: -t, -l, -m are allowed\n" | ||
| 120 | "If none of them is passed," | ||
| 121 | msgstr "" | ||
| 122 | |||
| 123 | #: utils/idle_monitor/cpupower-monitor.c:80 | ||
| 124 | #, c-format | ||
| 125 | msgid " all supported monitors are shown\n" | ||
| 126 | msgstr "" | ||
| 127 | |||
| 128 | #: utils/idle_monitor/cpupower-monitor.c:197 | ||
| 129 | #, c-format | ||
| 130 | msgid "Monitor %s, Counter %s has no count function. Implementation error\n" | ||
| 131 | msgstr "" | ||
| 132 | |||
| 133 | #: utils/idle_monitor/cpupower-monitor.c:207 | ||
| 134 | #, c-format | ||
| 135 | msgid " *is offline\n" | ||
| 136 | msgstr "" | ||
| 137 | |||
| 138 | #: utils/idle_monitor/cpupower-monitor.c:236 | ||
| 139 | #, c-format | ||
| 140 | msgid "%s: max monitor name length (%d) exceeded\n" | ||
| 141 | msgstr "" | ||
| 142 | |||
| 143 | #: utils/idle_monitor/cpupower-monitor.c:250 | ||
| 144 | #, c-format | ||
| 145 | msgid "No matching monitor found in %s, try -l option\n" | ||
| 146 | msgstr "" | ||
| 147 | |||
| 148 | #: utils/idle_monitor/cpupower-monitor.c:266 | ||
| 149 | #, c-format | ||
| 150 | msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n" | ||
| 151 | msgstr "" | ||
| 152 | |||
| 153 | #: utils/idle_monitor/cpupower-monitor.c:319 | ||
| 154 | #, c-format | ||
| 155 | msgid "%s took %.5f seconds and exited with status %d\n" | ||
| 156 | msgstr "" | ||
| 157 | |||
| 158 | #: utils/idle_monitor/cpupower-monitor.c:406 | ||
| 159 | #, c-format | ||
| 160 | msgid "Cannot read number of available processors\n" | ||
| 161 | msgstr "" | ||
| 162 | |||
| 163 | #: utils/idle_monitor/cpupower-monitor.c:417 | ||
| 164 | #, c-format | ||
| 165 | msgid "Available monitor %s needs root access\n" | ||
| 166 | msgstr "" | ||
| 167 | |||
| 168 | #: utils/idle_monitor/cpupower-monitor.c:428 | ||
| 169 | #, c-format | ||
| 170 | msgid "No HW Cstate monitors found\n" | ||
| 171 | msgstr "" | ||
| 172 | |||
| 173 | #: utils/cpupower.c:78 | ||
| 174 | #, c-format | ||
| 175 | msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n" | ||
| 176 | msgstr "" | ||
| 177 | |||
| 178 | #: utils/cpupower.c:79 | ||
| 179 | #, c-format | ||
| 180 | msgid "cpupower --version\n" | ||
| 181 | msgstr "" | ||
| 182 | |||
| 183 | #: utils/cpupower.c:80 | ||
| 184 | #, c-format | ||
| 185 | msgid "Supported subcommands are:\n" | ||
| 186 | msgstr "" | ||
| 187 | |||
| 188 | #: utils/cpupower.c:83 | ||
| 189 | #, c-format | ||
| 190 | msgid "" | ||
| 191 | "\n" | ||
| 192 | "Some subcommands can make use of the -c cpulist option.\n" | ||
| 193 | msgstr "" | ||
| 194 | |||
| 195 | #: utils/cpupower.c:84 | ||
| 196 | #, c-format | ||
| 197 | msgid "Look at the general cpupower manpage how to use it\n" | ||
| 198 | msgstr "" | ||
| 199 | |||
| 200 | #: utils/cpupower.c:85 | ||
| 201 | #, c-format | ||
| 202 | msgid "and read up the subcommand's manpage whether it is supported.\n" | ||
| 203 | msgstr "" | ||
| 204 | |||
| 205 | #: utils/cpupower.c:86 | ||
| 206 | #, c-format | ||
| 207 | msgid "" | ||
| 208 | "\n" | ||
| 209 | "Use cpupower help subcommand for getting help for above subcommands.\n" | ||
| 210 | msgstr "" | ||
| 211 | |||
| 212 | #: utils/cpupower.c:91 | ||
| 213 | #, c-format | ||
| 214 | msgid "Report errors and bugs to %s, please.\n" | ||
| 215 | msgstr "Per favore, comunicare errori e malfunzionamenti a %s.\n" | ||
| 216 | |||
| 217 | #: utils/cpupower.c:114 | ||
| 218 | #, c-format | ||
| 219 | msgid "Error parsing cpu list\n" | ||
| 220 | msgstr "" | ||
| 221 | |||
| 222 | #: utils/cpupower.c:172 | ||
| 223 | #, c-format | ||
| 224 | msgid "Subcommand %s needs root privileges\n" | ||
| 225 | msgstr "" | ||
| 226 | |||
| 227 | #: utils/cpufreq-info.c:31 | ||
| 228 | #, c-format | ||
| 229 | msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n" | ||
| 230 | msgstr "Impossibile determinare il numero di CPU (%s: %s), assumo sia 1\n" | ||
| 231 | |||
| 232 | #: utils/cpufreq-info.c:63 | ||
| 233 | #, c-format | ||
| 234 | msgid "" | ||
| 235 | " minimum CPU frequency - maximum CPU frequency - governor\n" | ||
| 236 | msgstr "" | ||
| 237 | " frequenza minima CPU - frequenza massima CPU - gestore\n" | ||
| 238 | |||
| 239 | #: utils/cpufreq-info.c:151 | ||
| 240 | #, c-format | ||
| 241 | msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n" | ||
| 242 | msgstr "" | ||
| 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 | ||
| 251 | msgid " boost state support: \n" | ||
| 252 | msgstr "" | ||
| 253 | |||
| 254 | #: utils/cpufreq-info.c:163 | ||
| 255 | #, c-format | ||
| 256 | msgid " Supported: %s\n" | ||
| 257 | msgstr "" | ||
| 258 | |||
| 259 | #: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 | ||
| 260 | msgid "yes" | ||
| 261 | msgstr "" | ||
| 262 | |||
| 263 | #: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 | ||
| 264 | msgid "no" | ||
| 265 | msgstr "" | ||
| 266 | |||
| 267 | #: utils/cpufreq-info.c:164 | ||
| 268 | #, fuzzy, c-format | ||
| 269 | msgid " Active: %s\n" | ||
| 270 | msgstr " modulo %s\n" | ||
| 271 | |||
| 272 | #: utils/cpufreq-info.c:177 | ||
| 273 | #, c-format | ||
| 274 | msgid " Boost States: %d\n" | ||
| 275 | msgstr "" | ||
| 276 | |||
| 277 | #: utils/cpufreq-info.c:178 | ||
| 278 | #, c-format | ||
| 279 | msgid " Total States: %d\n" | ||
| 280 | msgstr "" | ||
| 281 | |||
| 282 | #: utils/cpufreq-info.c:181 | ||
| 283 | #, c-format | ||
| 284 | msgid " Pstate-Pb%d: %luMHz (boost state)\n" | ||
| 285 | msgstr "" | ||
| 286 | |||
| 287 | #: utils/cpufreq-info.c:184 | ||
| 288 | #, c-format | ||
| 289 | msgid " Pstate-P%d: %luMHz\n" | ||
| 290 | msgstr "" | ||
| 291 | |||
| 292 | #: utils/cpufreq-info.c:211 | ||
| 293 | #, c-format | ||
| 294 | msgid " no or unknown cpufreq driver is active on this CPU\n" | ||
| 295 | msgstr " nessun modulo o modulo cpufreq sconosciuto per questa CPU\n" | ||
| 296 | |||
| 297 | #: utils/cpufreq-info.c:213 | ||
| 298 | #, c-format | ||
| 299 | msgid " driver: %s\n" | ||
| 300 | msgstr " modulo %s\n" | ||
| 301 | |||
| 302 | #: utils/cpufreq-info.c:219 | ||
| 303 | #, c-format | ||
| 304 | msgid " CPUs which run at the same hardware frequency: " | ||
| 305 | msgstr " CPU che operano alla stessa frequenza hardware: " | ||
| 306 | |||
| 307 | #: utils/cpufreq-info.c:230 | ||
| 308 | #, c-format | ||
| 309 | msgid " CPUs which need to have their frequency coordinated by software: " | ||
| 310 | msgstr " CPU che è necessario siano coordinate dal software: " | ||
| 311 | |||
| 312 | #: utils/cpufreq-info.c:241 | ||
| 313 | #, c-format | ||
| 314 | msgid " maximum transition latency: " | ||
| 315 | msgstr " latenza massima durante la transizione: " | ||
| 316 | |||
| 317 | #: utils/cpufreq-info.c:247 | ||
| 318 | #, c-format | ||
| 319 | msgid " hardware limits: " | ||
| 320 | msgstr " limiti hardware: " | ||
| 321 | |||
| 322 | #: utils/cpufreq-info.c:256 | ||
| 323 | #, c-format | ||
| 324 | msgid " available frequency steps: " | ||
| 325 | msgstr " frequenze disponibili: " | ||
| 326 | |||
| 327 | #: utils/cpufreq-info.c:269 | ||
| 328 | #, c-format | ||
| 329 | msgid " available cpufreq governors: " | ||
| 330 | msgstr " gestori disponibili: " | ||
| 331 | |||
| 332 | #: utils/cpufreq-info.c:280 | ||
| 333 | #, c-format | ||
| 334 | msgid " current policy: frequency should be within " | ||
| 335 | msgstr " gestore attuale: la frequenza deve mantenersi tra " | ||
| 336 | |||
| 337 | #: utils/cpufreq-info.c:282 | ||
| 338 | #, c-format | ||
| 339 | msgid " and " | ||
| 340 | msgstr " e " | ||
| 341 | |||
| 342 | #: utils/cpufreq-info.c:286 | ||
| 343 | #, c-format | ||
| 344 | msgid "" | ||
| 345 | "The governor \"%s\" may decide which speed to use\n" | ||
| 346 | " within this range.\n" | ||
| 347 | msgstr "" | ||
| 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 | ||
| 353 | msgid " current CPU frequency is " | ||
| 354 | msgstr " la frequenza attuale della CPU è " | ||
| 355 | |||
| 356 | #: utils/cpufreq-info.c:296 | ||
| 357 | #, c-format | ||
| 358 | msgid " (asserted by call to hardware)" | ||
| 359 | msgstr " (ottenuta da una chiamata diretta all'hardware)" | ||
| 360 | |||
| 361 | #: utils/cpufreq-info.c:304 | ||
| 362 | #, c-format | ||
| 363 | msgid " cpufreq stats: " | ||
| 364 | msgstr " statistiche cpufreq:" | ||
| 365 | |||
| 366 | #: utils/cpufreq-info.c:472 | ||
| 367 | #, fuzzy, c-format | ||
| 368 | msgid "Usage: cpupower freqinfo [options]\n" | ||
| 369 | msgstr "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 | ||
| 374 | msgid "Options:\n" | ||
| 375 | msgstr "Opzioni:\n" | ||
| 376 | |||
| 377 | #: utils/cpufreq-info.c:474 | ||
| 378 | #, fuzzy, c-format | ||
| 379 | msgid " -e, --debug Prints out debug information [default]\n" | ||
| 380 | msgstr " -e, --debug Mostra informazioni di debug\n" | ||
| 381 | |||
| 382 | #: utils/cpufreq-info.c:475 | ||
| 383 | #, c-format | ||
| 384 | msgid "" | ||
| 385 | " -f, --freq Get frequency the CPU currently runs at, according\n" | ||
| 386 | " to the cpufreq core *\n" | ||
| 387 | msgstr "" | ||
| 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 | ||
| 393 | msgid "" | ||
| 394 | " -w, --hwfreq Get frequency the CPU currently runs at, by reading\n" | ||
| 395 | " it from hardware (only available to root) *\n" | ||
| 396 | msgstr "" | ||
| 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 | ||
| 402 | msgid "" | ||
| 403 | " -l, --hwlimits Determine the minimum and maximum CPU frequency " | ||
| 404 | "allowed *\n" | ||
| 405 | msgstr "" | ||
| 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 | ||
| 411 | msgid " -d, --driver Determines the used cpufreq kernel driver *\n" | ||
| 412 | msgstr "" | ||
| 413 | " -d, --driver Determina il modulo cpufreq del kernel in uso *\n" | ||
| 414 | |||
| 415 | #: utils/cpufreq-info.c:481 | ||
| 416 | #, c-format | ||
| 417 | msgid " -p, --policy Gets the currently used cpufreq policy *\n" | ||
| 418 | msgstr "" | ||
| 419 | " -p, --policy Mostra il gestore cpufreq attualmente in uso *\n" | ||
| 420 | |||
| 421 | #: utils/cpufreq-info.c:482 | ||
| 422 | #, c-format | ||
| 423 | msgid " -g, --governors Determines available cpufreq governors *\n" | ||
| 424 | msgstr " -g, --governors Determina i gestori cpufreq disponibili *\n" | ||
| 425 | |||
| 426 | #: utils/cpufreq-info.c:483 | ||
| 427 | #, c-format | ||
| 428 | msgid "" | ||
| 429 | " -r, --related-cpus Determines which CPUs run at the same hardware " | ||
| 430 | "frequency *\n" | ||
| 431 | msgstr "" | ||
| 432 | " -r, --related-cpus Determina quali CPU operano alla stessa frequenza *\n" | ||
| 433 | |||
| 434 | #: utils/cpufreq-info.c:484 | ||
| 435 | #, c-format | ||
| 436 | msgid "" | ||
| 437 | " -a, --affected-cpus Determines which CPUs need to have their frequency\n" | ||
| 438 | " coordinated by software *\n" | ||
| 439 | msgstr "" | ||
| 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 | ||
| 445 | msgid " -s, --stats Shows cpufreq statistics if available\n" | ||
| 446 | msgstr " -s, --stats Mostra le statistiche se disponibili\n" | ||
| 447 | |||
| 448 | #: utils/cpufreq-info.c:487 | ||
| 449 | #, c-format | ||
| 450 | msgid "" | ||
| 451 | " -y, --latency Determines the maximum latency on CPU frequency " | ||
| 452 | "changes *\n" | ||
| 453 | msgstr "" | ||
| 454 | " -y, --latency Determina la latenza massima durante i cambi di " | ||
| 455 | "frequenza *\n" | ||
| 456 | |||
| 457 | #: utils/cpufreq-info.c:488 | ||
| 458 | #, c-format | ||
| 459 | msgid " -b, --boost Checks for turbo or boost modes *\n" | ||
| 460 | msgstr "" | ||
| 461 | |||
| 462 | #: utils/cpufreq-info.c:489 | ||
| 463 | #, c-format | ||
| 464 | msgid "" | ||
| 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" | ||
| 468 | msgstr "" | ||
| 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 | ||
| 475 | msgid "" | ||
| 476 | " -m, --human human-readable output for the -f, -w, -s and -y " | ||
| 477 | "parameters\n" | ||
| 478 | msgstr "" | ||
| 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 | ||
| 485 | msgid " -h, --help Prints out this screen\n" | ||
| 486 | msgstr " -h, --help Stampa questa schermata\n" | ||
| 487 | |||
| 488 | #: utils/cpufreq-info.c:495 | ||
| 489 | #, c-format | ||
| 490 | msgid "" | ||
| 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" | ||
| 493 | msgstr "" | ||
| 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 | ||
| 501 | msgid "" | ||
| 502 | "For the arguments marked with *, omitting the -c or --cpu argument is\n" | ||
| 503 | "equivalent to setting it to zero\n" | ||
| 504 | msgstr "" | ||
| 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 | ||
| 511 | msgid "" | ||
| 512 | "The argument passed to this tool can't be combined with passing a --cpu " | ||
| 513 | "argument\n" | ||
| 514 | msgstr "" | ||
| 515 | "L'opzione specificata a questo programma non può essere combinata con --cpu\n" | ||
| 516 | |||
| 517 | #: utils/cpufreq-info.c:596 | ||
| 518 | #, c-format | ||
| 519 | msgid "" | ||
| 520 | "You can't specify more than one --cpu parameter and/or\n" | ||
| 521 | "more than one output-specific argument\n" | ||
| 522 | msgstr "" | ||
| 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 | ||
| 529 | msgid "invalid or unknown argument\n" | ||
| 530 | msgstr "opzione sconosciuta o non valida\n" | ||
| 531 | |||
| 532 | #: utils/cpufreq-info.c:617 | ||
| 533 | #, c-format | ||
| 534 | msgid "couldn't analyze CPU %d as it doesn't seem to be present\n" | ||
| 535 | msgstr "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 | ||
| 539 | msgid "analyzing CPU %d:\n" | ||
| 540 | msgstr "analisi della CPU %d:\n" | ||
| 541 | |||
| 542 | #: utils/cpufreq-set.c:25 | ||
| 543 | #, fuzzy, c-format | ||
| 544 | msgid "Usage: cpupower frequency-set [options]\n" | ||
| 545 | msgstr "Uso: cpufreq-set [opzioni]\n" | ||
| 546 | |||
| 547 | #: utils/cpufreq-set.c:27 | ||
| 548 | #, c-format | ||
| 549 | msgid "" | ||
| 550 | " -d FREQ, --min FREQ new minimum CPU frequency the governor may " | ||
| 551 | "select\n" | ||
| 552 | msgstr "" | ||
| 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 | ||
| 558 | msgid "" | ||
| 559 | " -u FREQ, --max FREQ new maximum CPU frequency the governor may " | ||
| 560 | "select\n" | ||
| 561 | msgstr "" | ||
| 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 | ||
| 567 | msgid " -g GOV, --governor GOV new cpufreq governor\n" | ||
| 568 | msgstr " -g GOV, --governor GOV nuovo gestore cpufreq\n" | ||
| 569 | |||
| 570 | #: utils/cpufreq-set.c:30 | ||
| 571 | #, c-format | ||
| 572 | msgid "" | ||
| 573 | " -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n" | ||
| 574 | " governor to be available and loaded\n" | ||
| 575 | msgstr "" | ||
| 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 | ||
| 582 | msgid " -r, --related Switches all hardware-related CPUs\n" | ||
| 583 | msgstr "" | ||
| 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 | ||
| 588 | msgid " -h, --help Prints out this screen\n" | ||
| 589 | msgstr " -h, --help Stampa questa schermata\n" | ||
| 590 | |||
| 591 | #: utils/cpufreq-set.c:35 | ||
| 592 | #, fuzzy, c-format | ||
| 593 | msgid "" | ||
| 594 | "Notes:\n" | ||
| 595 | "1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n" | ||
| 596 | msgstr "" | ||
| 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 | ||
| 603 | msgid "" | ||
| 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" | ||
| 610 | msgstr "" | ||
| 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 | ||
| 623 | msgid "" | ||
| 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" | ||
| 633 | msgstr "" | ||
| 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 | ||
| 646 | msgid "wrong, unknown or unhandled CPU?\n" | ||
| 647 | msgstr "CPU errata, sconosciuta o non gestita?\n" | ||
| 648 | |||
| 649 | #: utils/cpufreq-set.c:302 | ||
| 650 | #, c-format | ||
| 651 | msgid "" | ||
| 652 | "the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n" | ||
| 653 | "-g/--governor parameters\n" | ||
| 654 | msgstr "" | ||
| 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 | ||
| 660 | msgid "" | ||
| 661 | "At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n" | ||
| 662 | "-g/--governor must be passed\n" | ||
| 663 | msgstr "" | ||
| 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 | ||
| 669 | msgid "Setting cpu: %d\n" | ||
| 670 | msgstr "" | ||
| 671 | |||
| 672 | #: utils/cpupower-set.c:22 | ||
| 673 | #, c-format | ||
| 674 | msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n" | ||
| 675 | msgstr "" | ||
| 676 | |||
| 677 | #: utils/cpupower-set.c:24 | ||
| 678 | #, c-format | ||
| 679 | msgid "" | ||
| 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" | ||
| 682 | msgstr "" | ||
| 683 | |||
| 684 | #: utils/cpupower-set.c:26 | ||
| 685 | #, c-format | ||
| 686 | msgid "" | ||
| 687 | " -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n" | ||
| 688 | msgstr "" | ||
| 689 | |||
| 690 | #: utils/cpupower-set.c:27 | ||
| 691 | #, c-format | ||
| 692 | msgid "" | ||
| 693 | " -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler " | ||
| 694 | "policy.\n" | ||
| 695 | msgstr "" | ||
| 696 | |||
| 697 | #: utils/cpupower-set.c:80 | ||
| 698 | #, c-format | ||
| 699 | msgid "--perf-bias param out of range [0-%d]\n" | ||
| 700 | msgstr "" | ||
| 701 | |||
| 702 | #: utils/cpupower-set.c:91 | ||
| 703 | #, c-format | ||
| 704 | msgid "--sched-mc param out of range [0-%d]\n" | ||
| 705 | msgstr "" | ||
| 706 | |||
| 707 | #: utils/cpupower-set.c:102 | ||
| 708 | #, c-format | ||
| 709 | msgid "--sched-smt param out of range [0-%d]\n" | ||
| 710 | msgstr "" | ||
| 711 | |||
| 712 | #: utils/cpupower-set.c:121 | ||
| 713 | #, c-format | ||
| 714 | msgid "Error setting sched-mc %s\n" | ||
| 715 | msgstr "" | ||
| 716 | |||
| 717 | #: utils/cpupower-set.c:127 | ||
| 718 | #, c-format | ||
| 719 | msgid "Error setting sched-smt %s\n" | ||
| 720 | msgstr "" | ||
| 721 | |||
| 722 | #: utils/cpupower-set.c:146 | ||
| 723 | #, c-format | ||
| 724 | msgid "Error setting perf-bias value on CPU %d\n" | ||
| 725 | msgstr "" | ||
| 726 | |||
| 727 | #: utils/cpupower-info.c:21 | ||
| 728 | #, c-format | ||
| 729 | msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n" | ||
| 730 | msgstr "" | ||
| 731 | |||
| 732 | #: utils/cpupower-info.c:23 | ||
| 733 | #, c-format | ||
| 734 | msgid "" | ||
| 735 | " -b, --perf-bias Gets CPU's power vs performance policy on some\n" | ||
| 736 | " Intel models [0-15], see manpage for details\n" | ||
| 737 | msgstr "" | ||
| 738 | |||
| 739 | #: utils/cpupower-info.c:25 | ||
| 740 | #, fuzzy, c-format | ||
| 741 | msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n" | ||
| 742 | msgstr "" | ||
| 743 | " -p, --policy Mostra il gestore cpufreq attualmente in uso *\n" | ||
| 744 | |||
| 745 | #: utils/cpupower-info.c:26 | ||
| 746 | #, c-format | ||
| 747 | msgid "" | ||
| 748 | " -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n" | ||
| 749 | msgstr "" | ||
| 750 | |||
| 751 | #: utils/cpupower-info.c:28 | ||
| 752 | #, c-format | ||
| 753 | msgid "" | ||
| 754 | "\n" | ||
| 755 | "Passing no option will show all info, by default only on core 0\n" | ||
| 756 | msgstr "" | ||
| 757 | |||
| 758 | #: utils/cpupower-info.c:102 | ||
| 759 | #, c-format | ||
| 760 | msgid "System's multi core scheduler setting: " | ||
| 761 | msgstr "" | ||
| 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 | ||
| 766 | msgid "not supported\n" | ||
| 767 | msgstr "" | ||
| 768 | |||
| 769 | #: utils/cpupower-info.c:111 | ||
| 770 | #, c-format | ||
| 771 | msgid "System's thread sibling scheduler setting: " | ||
| 772 | msgstr "" | ||
| 773 | |||
| 774 | #: utils/cpupower-info.c:126 | ||
| 775 | #, c-format | ||
| 776 | msgid "Intel's performance bias setting needs root privileges\n" | ||
| 777 | msgstr "" | ||
| 778 | |||
| 779 | #: utils/cpupower-info.c:128 | ||
| 780 | #, c-format | ||
| 781 | msgid "System does not support Intel's performance bias setting\n" | ||
| 782 | msgstr "" | ||
| 783 | |||
| 784 | #: utils/cpupower-info.c:147 | ||
| 785 | #, c-format | ||
| 786 | msgid "Could not read perf-bias value\n" | ||
| 787 | msgstr "" | ||
| 788 | |||
| 789 | #: utils/cpupower-info.c:150 | ||
| 790 | #, c-format | ||
| 791 | msgid "perf-bias: %d\n" | ||
| 792 | msgstr "" | ||
| 793 | |||
| 794 | #: utils/cpuidle-info.c:28 | ||
| 795 | #, fuzzy, c-format | ||
| 796 | msgid "Analyzing CPU %d:\n" | ||
| 797 | msgstr "analisi della CPU %d:\n" | ||
| 798 | |||
| 799 | #: utils/cpuidle-info.c:32 | ||
| 800 | #, c-format | ||
| 801 | msgid "CPU %u: No idle states\n" | ||
| 802 | msgstr "" | ||
| 803 | |||
| 804 | #: utils/cpuidle-info.c:36 | ||
| 805 | #, c-format | ||
| 806 | msgid "CPU %u: Can't read idle state info\n" | ||
| 807 | msgstr "" | ||
| 808 | |||
| 809 | #: utils/cpuidle-info.c:41 | ||
| 810 | #, c-format | ||
| 811 | msgid "Could not determine max idle state %u\n" | ||
| 812 | msgstr "" | ||
| 813 | |||
| 814 | #: utils/cpuidle-info.c:46 | ||
| 815 | #, c-format | ||
| 816 | msgid "Number of idle states: %d\n" | ||
| 817 | msgstr "" | ||
| 818 | |||
| 819 | #: utils/cpuidle-info.c:48 | ||
| 820 | #, fuzzy, c-format | ||
| 821 | msgid "Available idle states:" | ||
| 822 | msgstr " frequenze disponibili: " | ||
| 823 | |||
| 824 | #: utils/cpuidle-info.c:71 | ||
| 825 | #, c-format | ||
| 826 | msgid "Flags/Description: %s\n" | ||
| 827 | msgstr "" | ||
| 828 | |||
| 829 | #: utils/cpuidle-info.c:74 | ||
| 830 | #, c-format | ||
| 831 | msgid "Latency: %lu\n" | ||
| 832 | msgstr "" | ||
| 833 | |||
| 834 | #: utils/cpuidle-info.c:76 | ||
| 835 | #, c-format | ||
| 836 | msgid "Usage: %lu\n" | ||
| 837 | msgstr "" | ||
| 838 | |||
| 839 | #: utils/cpuidle-info.c:78 | ||
| 840 | #, c-format | ||
| 841 | msgid "Duration: %llu\n" | ||
| 842 | msgstr "" | ||
| 843 | |||
| 844 | #: utils/cpuidle-info.c:90 | ||
| 845 | #, c-format | ||
| 846 | msgid "Could not determine cpuidle driver\n" | ||
| 847 | msgstr "" | ||
| 848 | |||
| 849 | #: utils/cpuidle-info.c:94 | ||
| 850 | #, fuzzy, c-format | ||
| 851 | msgid "CPUidle driver: %s\n" | ||
| 852 | msgstr " modulo %s\n" | ||
| 853 | |||
| 854 | #: utils/cpuidle-info.c:99 | ||
| 855 | #, c-format | ||
| 856 | msgid "Could not determine cpuidle governor\n" | ||
| 857 | msgstr "" | ||
| 858 | |||
| 859 | #: utils/cpuidle-info.c:103 | ||
| 860 | #, c-format | ||
| 861 | msgid "CPUidle governor: %s\n" | ||
| 862 | msgstr "" | ||
| 863 | |||
| 864 | #: utils/cpuidle-info.c:122 | ||
| 865 | #, c-format | ||
| 866 | msgid "CPU %u: Can't read C-state info\n" | ||
| 867 | msgstr "" | ||
| 868 | |||
| 869 | #. printf("Cstates: %d\n", cstates); | ||
| 870 | #: utils/cpuidle-info.c:127 | ||
| 871 | #, c-format | ||
| 872 | msgid "active state: C0\n" | ||
| 873 | msgstr "" | ||
| 874 | |||
| 875 | #: utils/cpuidle-info.c:128 | ||
| 876 | #, c-format | ||
| 877 | msgid "max_cstate: C%u\n" | ||
| 878 | msgstr "" | ||
| 879 | |||
| 880 | #: utils/cpuidle-info.c:129 | ||
| 881 | #, fuzzy, c-format | ||
| 882 | msgid "maximum allowed latency: %lu usec\n" | ||
| 883 | msgstr " latenza massima durante la transizione: " | ||
| 884 | |||
| 885 | #: utils/cpuidle-info.c:130 | ||
| 886 | #, c-format | ||
| 887 | msgid "states:\t\n" | ||
| 888 | msgstr "" | ||
| 889 | |||
| 890 | #: utils/cpuidle-info.c:132 | ||
| 891 | #, c-format | ||
| 892 | msgid " C%d: type[C%d] " | ||
| 893 | msgstr "" | ||
| 894 | |||
| 895 | #: utils/cpuidle-info.c:134 | ||
| 896 | #, c-format | ||
| 897 | msgid "promotion[--] demotion[--] " | ||
| 898 | msgstr "" | ||
| 899 | |||
| 900 | #: utils/cpuidle-info.c:135 | ||
| 901 | #, c-format | ||
| 902 | msgid "latency[%03lu] " | ||
| 903 | msgstr "" | ||
| 904 | |||
| 905 | #: utils/cpuidle-info.c:137 | ||
| 906 | #, c-format | ||
| 907 | msgid "usage[%08lu] " | ||
| 908 | msgstr "" | ||
| 909 | |||
| 910 | #: utils/cpuidle-info.c:139 | ||
| 911 | #, c-format | ||
| 912 | msgid "duration[%020Lu] \n" | ||
| 913 | msgstr "" | ||
| 914 | |||
| 915 | #: utils/cpuidle-info.c:147 | ||
| 916 | #, fuzzy, c-format | ||
| 917 | msgid "Usage: cpupower idleinfo [options]\n" | ||
| 918 | msgstr "Uso: cpufreq-info [opzioni]\n" | ||
| 919 | |||
| 920 | #: utils/cpuidle-info.c:149 | ||
| 921 | #, fuzzy, c-format | ||
| 922 | msgid " -s, --silent Only show general C-state information\n" | ||
| 923 | msgstr " -e, --debug Mostra informazioni di debug\n" | ||
| 924 | |||
| 925 | #: utils/cpuidle-info.c:150 | ||
| 926 | #, fuzzy, c-format | ||
| 927 | msgid "" | ||
| 928 | " -o, --proc Prints out information like provided by the /proc/" | ||
| 929 | "acpi/processor/*/power\n" | ||
| 930 | " interface in older kernels\n" | ||
| 931 | msgstr "" | ||
| 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 | ||
| 938 | msgid "You can't specify more than one output-specific argument\n" | ||
| 939 | msgstr "" | ||
| 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 000000000000..990f5267ffe8 --- /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 | # | ||
| 7 | msgid "" | ||
| 8 | msgstr "" | ||
| 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 | ||
| 19 | msgid "Processor Core C3" | ||
| 20 | msgstr "" | ||
| 21 | |||
| 22 | #: utils/idle_monitor/nhm_idle.c:43 | ||
| 23 | msgid "Processor Core C6" | ||
| 24 | msgstr "" | ||
| 25 | |||
| 26 | #: utils/idle_monitor/nhm_idle.c:51 | ||
| 27 | msgid "Processor Package C3" | ||
| 28 | msgstr "" | ||
| 29 | |||
| 30 | #: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70 | ||
| 31 | msgid "Processor Package C6" | ||
| 32 | msgstr "" | ||
| 33 | |||
| 34 | #: utils/idle_monitor/snb_idle.c:33 | ||
| 35 | msgid "Processor Core C7" | ||
| 36 | msgstr "" | ||
| 37 | |||
| 38 | #: utils/idle_monitor/snb_idle.c:40 | ||
| 39 | msgid "Processor Package C2" | ||
| 40 | msgstr "" | ||
| 41 | |||
| 42 | #: utils/idle_monitor/snb_idle.c:47 | ||
| 43 | msgid "Processor Package C7" | ||
| 44 | msgstr "" | ||
| 45 | |||
| 46 | #: utils/idle_monitor/amd_fam14h_idle.c:56 | ||
| 47 | msgid "Package in sleep state (PC1 or deeper)" | ||
| 48 | msgstr "" | ||
| 49 | |||
| 50 | #: utils/idle_monitor/amd_fam14h_idle.c:63 | ||
| 51 | msgid "Processor Package C1" | ||
| 52 | msgstr "" | ||
| 53 | |||
| 54 | #: utils/idle_monitor/amd_fam14h_idle.c:77 | ||
| 55 | msgid "North Bridge P1 boolean counter (returns 0 or 1)" | ||
| 56 | msgstr "" | ||
| 57 | |||
| 58 | #: utils/idle_monitor/mperf_monitor.c:35 | ||
| 59 | msgid "Processor Core not idle" | ||
| 60 | msgstr "" | ||
| 61 | |||
| 62 | #: utils/idle_monitor/mperf_monitor.c:42 | ||
| 63 | msgid "Processor Core in an idle state" | ||
| 64 | msgstr "" | ||
| 65 | |||
| 66 | #: utils/idle_monitor/mperf_monitor.c:50 | ||
| 67 | msgid "Average Frequency (including boost) in MHz" | ||
| 68 | msgstr "" | ||
| 69 | |||
| 70 | #: utils/idle_monitor/cpupower-monitor.c:66 | ||
| 71 | #, c-format | ||
| 72 | msgid "" | ||
| 73 | "cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " | ||
| 74 | "interval_sec | -c command ...]\n" | ||
| 75 | msgstr "" | ||
| 76 | |||
| 77 | #: utils/idle_monitor/cpupower-monitor.c:69 | ||
| 78 | #, c-format | ||
| 79 | msgid "" | ||
| 80 | "cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i " | ||
| 81 | "interval_sec | -c command ...]\n" | ||
| 82 | msgstr "" | ||
| 83 | |||
| 84 | #: utils/idle_monitor/cpupower-monitor.c:71 | ||
| 85 | #, c-format | ||
| 86 | msgid "\t -v: be more verbose\n" | ||
| 87 | msgstr "" | ||
| 88 | |||
| 89 | #: utils/idle_monitor/cpupower-monitor.c:73 | ||
| 90 | #, c-format | ||
| 91 | msgid "\t -h: print this help\n" | ||
| 92 | msgstr "" | ||
| 93 | |||
| 94 | #: utils/idle_monitor/cpupower-monitor.c:74 | ||
| 95 | #, c-format | ||
| 96 | msgid "\t -i: time intervall to measure for in seconds (default 1)\n" | ||
| 97 | msgstr "" | ||
| 98 | |||
| 99 | #: utils/idle_monitor/cpupower-monitor.c:75 | ||
| 100 | #, c-format | ||
| 101 | msgid "\t -t: show CPU topology/hierarchy\n" | ||
| 102 | msgstr "" | ||
| 103 | |||
| 104 | #: utils/idle_monitor/cpupower-monitor.c:76 | ||
| 105 | #, c-format | ||
| 106 | msgid "\t -l: list available CPU sleep monitors (for use with -m)\n" | ||
| 107 | msgstr "" | ||
| 108 | |||
| 109 | #: utils/idle_monitor/cpupower-monitor.c:77 | ||
| 110 | #, c-format | ||
| 111 | msgid "\t -m: show specific CPU sleep monitors only (in same order)\n" | ||
| 112 | msgstr "" | ||
| 113 | |||
| 114 | #: utils/idle_monitor/cpupower-monitor.c:79 | ||
| 115 | #, c-format | ||
| 116 | msgid "" | ||
| 117 | "only one of: -t, -l, -m are allowed\n" | ||
| 118 | "If none of them is passed," | ||
| 119 | msgstr "" | ||
| 120 | |||
| 121 | #: utils/idle_monitor/cpupower-monitor.c:80 | ||
| 122 | #, c-format | ||
| 123 | msgid " all supported monitors are shown\n" | ||
| 124 | msgstr "" | ||
| 125 | |||
| 126 | #: utils/idle_monitor/cpupower-monitor.c:197 | ||
| 127 | #, c-format | ||
| 128 | msgid "Monitor %s, Counter %s has no count function. Implementation error\n" | ||
| 129 | msgstr "" | ||
| 130 | |||
| 131 | #: utils/idle_monitor/cpupower-monitor.c:207 | ||
| 132 | #, c-format | ||
| 133 | msgid " *is offline\n" | ||
| 134 | msgstr "" | ||
| 135 | |||
| 136 | #: utils/idle_monitor/cpupower-monitor.c:236 | ||
| 137 | #, c-format | ||
| 138 | msgid "%s: max monitor name length (%d) exceeded\n" | ||
| 139 | msgstr "" | ||
| 140 | |||
| 141 | #: utils/idle_monitor/cpupower-monitor.c:250 | ||
| 142 | #, c-format | ||
| 143 | msgid "No matching monitor found in %s, try -l option\n" | ||
| 144 | msgstr "" | ||
| 145 | |||
| 146 | #: utils/idle_monitor/cpupower-monitor.c:266 | ||
| 147 | #, c-format | ||
| 148 | msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n" | ||
| 149 | msgstr "" | ||
| 150 | |||
| 151 | #: utils/idle_monitor/cpupower-monitor.c:319 | ||
| 152 | #, c-format | ||
| 153 | msgid "%s took %.5f seconds and exited with status %d\n" | ||
| 154 | msgstr "" | ||
| 155 | |||
| 156 | #: utils/idle_monitor/cpupower-monitor.c:406 | ||
| 157 | #, c-format | ||
| 158 | msgid "Cannot read number of available processors\n" | ||
| 159 | msgstr "" | ||
| 160 | |||
| 161 | #: utils/idle_monitor/cpupower-monitor.c:417 | ||
| 162 | #, c-format | ||
| 163 | msgid "Available monitor %s needs root access\n" | ||
| 164 | msgstr "" | ||
| 165 | |||
| 166 | #: utils/idle_monitor/cpupower-monitor.c:428 | ||
| 167 | #, c-format | ||
| 168 | msgid "No HW Cstate monitors found\n" | ||
| 169 | msgstr "" | ||
| 170 | |||
| 171 | #: utils/cpupower.c:78 | ||
| 172 | #, c-format | ||
| 173 | msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n" | ||
| 174 | msgstr "" | ||
| 175 | |||
| 176 | #: utils/cpupower.c:79 | ||
| 177 | #, c-format | ||
| 178 | msgid "cpupower --version\n" | ||
| 179 | msgstr "" | ||
| 180 | |||
| 181 | #: utils/cpupower.c:80 | ||
| 182 | #, c-format | ||
| 183 | msgid "Supported subcommands are:\n" | ||
| 184 | msgstr "" | ||
| 185 | |||
| 186 | #: utils/cpupower.c:83 | ||
| 187 | #, c-format | ||
| 188 | msgid "" | ||
| 189 | "\n" | ||
| 190 | "Some subcommands can make use of the -c cpulist option.\n" | ||
| 191 | msgstr "" | ||
| 192 | |||
| 193 | #: utils/cpupower.c:84 | ||
| 194 | #, c-format | ||
| 195 | msgid "Look at the general cpupower manpage how to use it\n" | ||
| 196 | msgstr "" | ||
| 197 | |||
| 198 | #: utils/cpupower.c:85 | ||
| 199 | #, c-format | ||
| 200 | msgid "and read up the subcommand's manpage whether it is supported.\n" | ||
| 201 | msgstr "" | ||
| 202 | |||
| 203 | #: utils/cpupower.c:86 | ||
| 204 | #, c-format | ||
| 205 | msgid "" | ||
| 206 | "\n" | ||
| 207 | "Use cpupower help subcommand for getting help for above subcommands.\n" | ||
| 208 | msgstr "" | ||
| 209 | |||
| 210 | #: utils/cpupower.c:91 | ||
| 211 | #, c-format | ||
| 212 | msgid "Report errors and bugs to %s, please.\n" | ||
| 213 | msgstr "Reporte erros e bugs para %s, por favor.\n" | ||
| 214 | |||
| 215 | #: utils/cpupower.c:114 | ||
| 216 | #, c-format | ||
| 217 | msgid "Error parsing cpu list\n" | ||
| 218 | msgstr "" | ||
| 219 | |||
| 220 | #: utils/cpupower.c:172 | ||
| 221 | #, c-format | ||
| 222 | msgid "Subcommand %s needs root privileges\n" | ||
| 223 | msgstr "" | ||
| 224 | |||
| 225 | #: utils/cpufreq-info.c:31 | ||
| 226 | #, c-format | ||
| 227 | msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n" | ||
| 228 | msgstr "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 | ||
| 232 | msgid "" | ||
| 233 | " minimum CPU frequency - maximum CPU frequency - governor\n" | ||
| 234 | msgstr "" | ||
| 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 | ||
| 240 | msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n" | ||
| 241 | msgstr "" | ||
| 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 | ||
| 250 | msgid " boost state support: \n" | ||
| 251 | msgstr "" | ||
| 252 | |||
| 253 | #: utils/cpufreq-info.c:163 | ||
| 254 | #, c-format | ||
| 255 | msgid " Supported: %s\n" | ||
| 256 | msgstr "" | ||
| 257 | |||
| 258 | #: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 | ||
| 259 | msgid "yes" | ||
| 260 | msgstr "" | ||
| 261 | |||
| 262 | #: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 | ||
| 263 | msgid "no" | ||
| 264 | msgstr "" | ||
| 265 | |||
| 266 | #: utils/cpufreq-info.c:164 | ||
| 267 | #, fuzzy, c-format | ||
| 268 | msgid " Active: %s\n" | ||
| 269 | msgstr " driver: %s\n" | ||
| 270 | |||
| 271 | #: utils/cpufreq-info.c:177 | ||
| 272 | #, c-format | ||
| 273 | msgid " Boost States: %d\n" | ||
| 274 | msgstr "" | ||
| 275 | |||
| 276 | #: utils/cpufreq-info.c:178 | ||
| 277 | #, c-format | ||
| 278 | msgid " Total States: %d\n" | ||
| 279 | msgstr "" | ||
| 280 | |||
| 281 | #: utils/cpufreq-info.c:181 | ||
| 282 | #, c-format | ||
| 283 | msgid " Pstate-Pb%d: %luMHz (boost state)\n" | ||
| 284 | msgstr "" | ||
| 285 | |||
| 286 | #: utils/cpufreq-info.c:184 | ||
| 287 | #, c-format | ||
| 288 | msgid " Pstate-P%d: %luMHz\n" | ||
| 289 | msgstr "" | ||
| 290 | |||
| 291 | #: utils/cpufreq-info.c:211 | ||
| 292 | #, c-format | ||
| 293 | msgid " no or unknown cpufreq driver is active on this CPU\n" | ||
| 294 | msgstr " nenhum ou driver do cpufreq deconhecido está ativo nesse CPU\n" | ||
| 295 | |||
| 296 | #: utils/cpufreq-info.c:213 | ||
| 297 | #, c-format | ||
| 298 | msgid " driver: %s\n" | ||
| 299 | msgstr " driver: %s\n" | ||
| 300 | |||
| 301 | #: utils/cpufreq-info.c:219 | ||
| 302 | #, c-format | ||
| 303 | msgid " CPUs which run at the same hardware frequency: " | ||
| 304 | msgstr " CPUs que rodam na mesma frequência de hardware: " | ||
| 305 | |||
| 306 | #: utils/cpufreq-info.c:230 | ||
| 307 | #, c-format | ||
| 308 | msgid " CPUs which need to have their frequency coordinated by software: " | ||
| 309 | msgstr " CPUs que precisam ter suas frequências coordenadas por software: " | ||
| 310 | |||
| 311 | #: utils/cpufreq-info.c:241 | ||
| 312 | #, c-format | ||
| 313 | msgid " maximum transition latency: " | ||
| 314 | msgstr " maior latência de transição: " | ||
| 315 | |||
| 316 | #: utils/cpufreq-info.c:247 | ||
| 317 | #, c-format | ||
| 318 | msgid " hardware limits: " | ||
| 319 | msgstr " limites do hardware: " | ||
| 320 | |||
| 321 | #: utils/cpufreq-info.c:256 | ||
| 322 | #, c-format | ||
| 323 | msgid " available frequency steps: " | ||
| 324 | msgstr " nÃveis de frequência disponÃveis: " | ||
| 325 | |||
| 326 | #: utils/cpufreq-info.c:269 | ||
| 327 | #, c-format | ||
| 328 | msgid " available cpufreq governors: " | ||
| 329 | msgstr " reguladores do cpufreq disponÃveis: " | ||
| 330 | |||
| 331 | #: utils/cpufreq-info.c:280 | ||
| 332 | #, c-format | ||
| 333 | msgid " current policy: frequency should be within " | ||
| 334 | msgstr " polÃtica de frequência atual deve estar entre " | ||
| 335 | |||
| 336 | #: utils/cpufreq-info.c:282 | ||
| 337 | #, c-format | ||
| 338 | msgid " and " | ||
| 339 | msgstr " e " | ||
| 340 | |||
| 341 | #: utils/cpufreq-info.c:286 | ||
| 342 | #, c-format | ||
| 343 | msgid "" | ||
| 344 | "The governor \"%s\" may decide which speed to use\n" | ||
| 345 | " within this range.\n" | ||
| 346 | msgstr "" | ||
| 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 | ||
| 352 | msgid " current CPU frequency is " | ||
| 353 | msgstr " frequência atual do CPU é " | ||
| 354 | |||
| 355 | #: utils/cpufreq-info.c:296 | ||
| 356 | #, c-format | ||
| 357 | msgid " (asserted by call to hardware)" | ||
| 358 | msgstr " (declarado por chamada ao hardware)" | ||
| 359 | |||
| 360 | #: utils/cpufreq-info.c:304 | ||
| 361 | #, c-format | ||
| 362 | msgid " cpufreq stats: " | ||
| 363 | msgstr " status do cpufreq: " | ||
| 364 | |||
| 365 | #: utils/cpufreq-info.c:472 | ||
| 366 | #, fuzzy, c-format | ||
| 367 | msgid "Usage: cpupower freqinfo [options]\n" | ||
| 368 | msgstr "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 | ||
| 373 | msgid "Options:\n" | ||
| 374 | msgstr "Opções:\n" | ||
| 375 | |||
| 376 | #: utils/cpufreq-info.c:474 | ||
| 377 | #, fuzzy, c-format | ||
| 378 | msgid " -e, --debug Prints out debug information [default]\n" | ||
| 379 | msgstr " -e, --debug Mostra informação de debug\n" | ||
| 380 | |||
| 381 | #: utils/cpufreq-info.c:475 | ||
| 382 | #, c-format | ||
| 383 | msgid "" | ||
| 384 | " -f, --freq Get frequency the CPU currently runs at, according\n" | ||
| 385 | " to the cpufreq core *\n" | ||
| 386 | msgstr "" | ||
| 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 | ||
| 393 | msgid "" | ||
| 394 | " -w, --hwfreq Get frequency the CPU currently runs at, by reading\n" | ||
| 395 | " it from hardware (only available to root) *\n" | ||
| 396 | msgstr "" | ||
| 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 | ||
| 404 | msgid "" | ||
| 405 | " -l, --hwlimits Determine the minimum and maximum CPU frequency " | ||
| 406 | "allowed *\n" | ||
| 407 | msgstr "" | ||
| 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 | ||
| 413 | msgid " -d, --driver Determines the used cpufreq kernel driver *\n" | ||
| 414 | msgstr "" | ||
| 415 | " -d, --driver Determina o driver do kernel do cpufreq usado *\n" | ||
| 416 | |||
| 417 | #: utils/cpufreq-info.c:481 | ||
| 418 | #, c-format | ||
| 419 | msgid " -p, --policy Gets the currently used cpufreq policy *\n" | ||
| 420 | msgstr "" | ||
| 421 | "--p, --policy Obtem a polÃtica do cpufreq em uso no momento *\n" | ||
| 422 | |||
| 423 | #: utils/cpufreq-info.c:482 | ||
| 424 | #, c-format | ||
| 425 | msgid " -g, --governors Determines available cpufreq governors *\n" | ||
| 426 | msgstr "" | ||
| 427 | " -g, --governors Determina reguladores do cpufreq disponÃveis *\n" | ||
| 428 | |||
| 429 | #: utils/cpufreq-info.c:483 | ||
| 430 | #, c-format | ||
| 431 | msgid "" | ||
| 432 | " -r, --related-cpus Determines which CPUs run at the same hardware " | ||
| 433 | "frequency *\n" | ||
| 434 | msgstr "" | ||
| 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 | ||
| 440 | msgid "" | ||
| 441 | " -a, --affected-cpus Determines which CPUs need to have their frequency\n" | ||
| 442 | " coordinated by software *\n" | ||
| 443 | msgstr "" | ||
| 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 | ||
| 449 | msgid " -s, --stats Shows cpufreq statistics if available\n" | ||
| 450 | msgstr " -s, --stats Mostra estatÃsticas do cpufreq se disponÃveis\n" | ||
| 451 | |||
| 452 | #: utils/cpufreq-info.c:487 | ||
| 453 | #, c-format | ||
| 454 | msgid "" | ||
| 455 | " -y, --latency Determines the maximum latency on CPU frequency " | ||
| 456 | "changes *\n" | ||
| 457 | msgstr "" | ||
| 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 | ||
| 463 | msgid " -b, --boost Checks for turbo or boost modes *\n" | ||
| 464 | msgstr "" | ||
| 465 | |||
| 466 | #: utils/cpufreq-info.c:489 | ||
| 467 | #, c-format | ||
| 468 | msgid "" | ||
| 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" | ||
| 472 | msgstr "" | ||
| 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 | ||
| 479 | msgid "" | ||
| 480 | " -m, --human human-readable output for the -f, -w, -s and -y " | ||
| 481 | "parameters\n" | ||
| 482 | msgstr "" | ||
| 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 | ||
| 488 | msgid " -h, --help Prints out this screen\n" | ||
| 489 | msgstr " -h, --help Imprime essa tela\n" | ||
| 490 | |||
| 491 | #: utils/cpufreq-info.c:495 | ||
| 492 | #, c-format | ||
| 493 | msgid "" | ||
| 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" | ||
| 496 | msgstr "" | ||
| 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 | ||
| 503 | msgid "" | ||
| 504 | "For the arguments marked with *, omitting the -c or --cpu argument is\n" | ||
| 505 | "equivalent to setting it to zero\n" | ||
| 506 | msgstr "" | ||
| 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 | ||
| 512 | msgid "" | ||
| 513 | "The argument passed to this tool can't be combined with passing a --cpu " | ||
| 514 | "argument\n" | ||
| 515 | msgstr "" | ||
| 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 | ||
| 521 | msgid "" | ||
| 522 | "You can't specify more than one --cpu parameter and/or\n" | ||
| 523 | "more than one output-specific argument\n" | ||
| 524 | msgstr "" | ||
| 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 | ||
| 531 | msgid "invalid or unknown argument\n" | ||
| 532 | msgstr "argumento inválido ou desconhecido\n" | ||
| 533 | |||
| 534 | #: utils/cpufreq-info.c:617 | ||
| 535 | #, c-format | ||
| 536 | msgid "couldn't analyze CPU %d as it doesn't seem to be present\n" | ||
| 537 | msgstr "" | ||
| 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 | ||
| 542 | msgid "analyzing CPU %d:\n" | ||
| 543 | msgstr "analisando o CPU %d:\n" | ||
| 544 | |||
| 545 | #: utils/cpufreq-set.c:25 | ||
| 546 | #, fuzzy, c-format | ||
| 547 | msgid "Usage: cpupower frequency-set [options]\n" | ||
| 548 | msgstr "Uso: cpufreq-set [opções]\n" | ||
| 549 | |||
| 550 | #: utils/cpufreq-set.c:27 | ||
| 551 | #, c-format | ||
| 552 | msgid "" | ||
| 553 | " -d FREQ, --min FREQ new minimum CPU frequency the governor may " | ||
| 554 | "select\n" | ||
| 555 | msgstr "" | ||
| 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 | ||
| 561 | msgid "" | ||
| 562 | " -u FREQ, --max FREQ new maximum CPU frequency the governor may " | ||
| 563 | "select\n" | ||
| 564 | msgstr "" | ||
| 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 | ||
| 570 | msgid " -g GOV, --governor GOV new cpufreq governor\n" | ||
| 571 | msgstr " -g GOV, --governor GOV novo regulador do cpufreq\n" | ||
| 572 | |||
| 573 | #: utils/cpufreq-set.c:30 | ||
| 574 | #, c-format | ||
| 575 | msgid "" | ||
| 576 | " -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n" | ||
| 577 | " governor to be available and loaded\n" | ||
| 578 | msgstr "" | ||
| 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 | ||
| 585 | msgid " -r, --related Switches all hardware-related CPUs\n" | ||
| 586 | msgstr "" | ||
| 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 | ||
| 591 | msgid " -h, --help Prints out this screen\n" | ||
| 592 | msgstr " -h, --help Mostra essa tela\n" | ||
| 593 | |||
| 594 | #: utils/cpufreq-set.c:35 | ||
| 595 | #, fuzzy, c-format | ||
| 596 | msgid "" | ||
| 597 | "Notes:\n" | ||
| 598 | "1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n" | ||
| 599 | msgstr "" | ||
| 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 | ||
| 605 | msgid "" | ||
| 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" | ||
| 612 | msgstr "" | ||
| 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 | ||
| 624 | msgid "" | ||
| 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" | ||
| 634 | msgstr "" | ||
| 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 | ||
| 647 | msgid "wrong, unknown or unhandled CPU?\n" | ||
| 648 | msgstr "CPU errado, desconhecido ou inesperado?\n" | ||
| 649 | |||
| 650 | #: utils/cpufreq-set.c:302 | ||
| 651 | #, c-format | ||
| 652 | msgid "" | ||
| 653 | "the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n" | ||
| 654 | "-g/--governor parameters\n" | ||
| 655 | msgstr "" | ||
| 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 | ||
| 662 | msgid "" | ||
| 663 | "At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n" | ||
| 664 | "-g/--governor must be passed\n" | ||
| 665 | msgstr "" | ||
| 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 | ||
| 671 | msgid "Setting cpu: %d\n" | ||
| 672 | msgstr "" | ||
| 673 | |||
| 674 | #: utils/cpupower-set.c:22 | ||
| 675 | #, c-format | ||
| 676 | msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n" | ||
| 677 | msgstr "" | ||
| 678 | |||
| 679 | #: utils/cpupower-set.c:24 | ||
| 680 | #, c-format | ||
| 681 | msgid "" | ||
| 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" | ||
| 684 | msgstr "" | ||
| 685 | |||
| 686 | #: utils/cpupower-set.c:26 | ||
| 687 | #, c-format | ||
| 688 | msgid "" | ||
| 689 | " -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n" | ||
| 690 | msgstr "" | ||
| 691 | |||
| 692 | #: utils/cpupower-set.c:27 | ||
| 693 | #, c-format | ||
| 694 | msgid "" | ||
| 695 | " -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler " | ||
| 696 | "policy.\n" | ||
| 697 | msgstr "" | ||
| 698 | |||
| 699 | #: utils/cpupower-set.c:80 | ||
| 700 | #, c-format | ||
| 701 | msgid "--perf-bias param out of range [0-%d]\n" | ||
| 702 | msgstr "" | ||
| 703 | |||
| 704 | #: utils/cpupower-set.c:91 | ||
| 705 | #, c-format | ||
| 706 | msgid "--sched-mc param out of range [0-%d]\n" | ||
| 707 | msgstr "" | ||
| 708 | |||
| 709 | #: utils/cpupower-set.c:102 | ||
| 710 | #, c-format | ||
| 711 | msgid "--sched-smt param out of range [0-%d]\n" | ||
| 712 | msgstr "" | ||
| 713 | |||
| 714 | #: utils/cpupower-set.c:121 | ||
| 715 | #, c-format | ||
| 716 | msgid "Error setting sched-mc %s\n" | ||
| 717 | msgstr "" | ||
| 718 | |||
| 719 | #: utils/cpupower-set.c:127 | ||
| 720 | #, c-format | ||
| 721 | msgid "Error setting sched-smt %s\n" | ||
| 722 | msgstr "" | ||
| 723 | |||
| 724 | #: utils/cpupower-set.c:146 | ||
| 725 | #, c-format | ||
| 726 | msgid "Error setting perf-bias value on CPU %d\n" | ||
| 727 | msgstr "" | ||
| 728 | |||
| 729 | #: utils/cpupower-info.c:21 | ||
| 730 | #, c-format | ||
| 731 | msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n" | ||
| 732 | msgstr "" | ||
| 733 | |||
| 734 | #: utils/cpupower-info.c:23 | ||
| 735 | #, c-format | ||
| 736 | msgid "" | ||
| 737 | " -b, --perf-bias Gets CPU's power vs performance policy on some\n" | ||
| 738 | " Intel models [0-15], see manpage for details\n" | ||
| 739 | msgstr "" | ||
| 740 | |||
| 741 | #: utils/cpupower-info.c:25 | ||
| 742 | #, fuzzy, c-format | ||
| 743 | msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n" | ||
| 744 | msgstr "" | ||
| 745 | "--p, --policy Obtem a polÃtica do cpufreq em uso no momento *\n" | ||
| 746 | |||
| 747 | #: utils/cpupower-info.c:26 | ||
| 748 | #, c-format | ||
| 749 | msgid "" | ||
| 750 | " -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n" | ||
| 751 | msgstr "" | ||
| 752 | |||
| 753 | #: utils/cpupower-info.c:28 | ||
| 754 | #, c-format | ||
| 755 | msgid "" | ||
| 756 | "\n" | ||
| 757 | "Passing no option will show all info, by default only on core 0\n" | ||
| 758 | msgstr "" | ||
| 759 | |||
| 760 | #: utils/cpupower-info.c:102 | ||
| 761 | #, c-format | ||
| 762 | msgid "System's multi core scheduler setting: " | ||
| 763 | msgstr "" | ||
| 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 | ||
| 768 | msgid "not supported\n" | ||
| 769 | msgstr "" | ||
| 770 | |||
| 771 | #: utils/cpupower-info.c:111 | ||
| 772 | #, c-format | ||
| 773 | msgid "System's thread sibling scheduler setting: " | ||
| 774 | msgstr "" | ||
| 775 | |||
| 776 | #: utils/cpupower-info.c:126 | ||
| 777 | #, c-format | ||
| 778 | msgid "Intel's performance bias setting needs root privileges\n" | ||
| 779 | msgstr "" | ||
| 780 | |||
| 781 | #: utils/cpupower-info.c:128 | ||
| 782 | #, c-format | ||
| 783 | msgid "System does not support Intel's performance bias setting\n" | ||
| 784 | msgstr "" | ||
| 785 | |||
| 786 | #: utils/cpupower-info.c:147 | ||
| 787 | #, c-format | ||
| 788 | msgid "Could not read perf-bias value\n" | ||
| 789 | msgstr "" | ||
| 790 | |||
| 791 | #: utils/cpupower-info.c:150 | ||
| 792 | #, c-format | ||
| 793 | msgid "perf-bias: %d\n" | ||
| 794 | msgstr "" | ||
| 795 | |||
| 796 | #: utils/cpuidle-info.c:28 | ||
| 797 | #, fuzzy, c-format | ||
| 798 | msgid "Analyzing CPU %d:\n" | ||
| 799 | msgstr "analisando o CPU %d:\n" | ||
| 800 | |||
| 801 | #: utils/cpuidle-info.c:32 | ||
| 802 | #, c-format | ||
| 803 | msgid "CPU %u: No idle states\n" | ||
| 804 | msgstr "" | ||
| 805 | |||
| 806 | #: utils/cpuidle-info.c:36 | ||
| 807 | #, c-format | ||
| 808 | msgid "CPU %u: Can't read idle state info\n" | ||
| 809 | msgstr "" | ||
| 810 | |||
| 811 | #: utils/cpuidle-info.c:41 | ||
| 812 | #, c-format | ||
| 813 | msgid "Could not determine max idle state %u\n" | ||
| 814 | msgstr "" | ||
| 815 | |||
| 816 | #: utils/cpuidle-info.c:46 | ||
| 817 | #, c-format | ||
| 818 | msgid "Number of idle states: %d\n" | ||
| 819 | msgstr "" | ||
| 820 | |||
| 821 | #: utils/cpuidle-info.c:48 | ||
| 822 | #, fuzzy, c-format | ||
| 823 | msgid "Available idle states:" | ||
| 824 | msgstr " nÃveis de frequência disponÃveis: " | ||
| 825 | |||
| 826 | #: utils/cpuidle-info.c:71 | ||
| 827 | #, c-format | ||
| 828 | msgid "Flags/Description: %s\n" | ||
| 829 | msgstr "" | ||
| 830 | |||
| 831 | #: utils/cpuidle-info.c:74 | ||
| 832 | #, c-format | ||
| 833 | msgid "Latency: %lu\n" | ||
| 834 | msgstr "" | ||
| 835 | |||
| 836 | #: utils/cpuidle-info.c:76 | ||
| 837 | #, c-format | ||
| 838 | msgid "Usage: %lu\n" | ||
| 839 | msgstr "" | ||
| 840 | |||
| 841 | #: utils/cpuidle-info.c:78 | ||
| 842 | #, c-format | ||
| 843 | msgid "Duration: %llu\n" | ||
| 844 | msgstr "" | ||
| 845 | |||
| 846 | #: utils/cpuidle-info.c:90 | ||
| 847 | #, c-format | ||
| 848 | msgid "Could not determine cpuidle driver\n" | ||
| 849 | msgstr "" | ||
| 850 | |||
| 851 | #: utils/cpuidle-info.c:94 | ||
| 852 | #, fuzzy, c-format | ||
| 853 | msgid "CPUidle driver: %s\n" | ||
| 854 | msgstr " driver: %s\n" | ||
| 855 | |||
| 856 | #: utils/cpuidle-info.c:99 | ||
| 857 | #, c-format | ||
| 858 | msgid "Could not determine cpuidle governor\n" | ||
| 859 | msgstr "" | ||
| 860 | |||
| 861 | #: utils/cpuidle-info.c:103 | ||
| 862 | #, c-format | ||
| 863 | msgid "CPUidle governor: %s\n" | ||
| 864 | msgstr "" | ||
| 865 | |||
| 866 | #: utils/cpuidle-info.c:122 | ||
| 867 | #, c-format | ||
| 868 | msgid "CPU %u: Can't read C-state info\n" | ||
| 869 | msgstr "" | ||
| 870 | |||
| 871 | #. printf("Cstates: %d\n", cstates); | ||
| 872 | #: utils/cpuidle-info.c:127 | ||
| 873 | #, c-format | ||
| 874 | msgid "active state: C0\n" | ||
| 875 | msgstr "" | ||
| 876 | |||
| 877 | #: utils/cpuidle-info.c:128 | ||
| 878 | #, c-format | ||
| 879 | msgid "max_cstate: C%u\n" | ||
| 880 | msgstr "" | ||
| 881 | |||
| 882 | #: utils/cpuidle-info.c:129 | ||
| 883 | #, fuzzy, c-format | ||
| 884 | msgid "maximum allowed latency: %lu usec\n" | ||
| 885 | msgstr " maior latência de transição: " | ||
| 886 | |||
| 887 | #: utils/cpuidle-info.c:130 | ||
| 888 | #, c-format | ||
| 889 | msgid "states:\t\n" | ||
| 890 | msgstr "" | ||
| 891 | |||
| 892 | #: utils/cpuidle-info.c:132 | ||
| 893 | #, c-format | ||
| 894 | msgid " C%d: type[C%d] " | ||
| 895 | msgstr "" | ||
| 896 | |||
| 897 | #: utils/cpuidle-info.c:134 | ||
| 898 | #, c-format | ||
| 899 | msgid "promotion[--] demotion[--] " | ||
| 900 | msgstr "" | ||
| 901 | |||
| 902 | #: utils/cpuidle-info.c:135 | ||
| 903 | #, c-format | ||
| 904 | msgid "latency[%03lu] " | ||
| 905 | msgstr "" | ||
| 906 | |||
| 907 | #: utils/cpuidle-info.c:137 | ||
| 908 | #, c-format | ||
| 909 | msgid "usage[%08lu] " | ||
| 910 | msgstr "" | ||
| 911 | |||
| 912 | #: utils/cpuidle-info.c:139 | ||
| 913 | #, c-format | ||
| 914 | msgid "duration[%020Lu] \n" | ||
| 915 | msgstr "" | ||
| 916 | |||
| 917 | #: utils/cpuidle-info.c:147 | ||
| 918 | #, fuzzy, c-format | ||
| 919 | msgid "Usage: cpupower idleinfo [options]\n" | ||
| 920 | msgstr "Uso: cpufreq-info [opções]\n" | ||
| 921 | |||
| 922 | #: utils/cpuidle-info.c:149 | ||
| 923 | #, fuzzy, c-format | ||
| 924 | msgid " -s, --silent Only show general C-state information\n" | ||
| 925 | msgstr " -e, --debug Mostra informação de debug\n" | ||
| 926 | |||
| 927 | #: utils/cpuidle-info.c:150 | ||
| 928 | #, fuzzy, c-format | ||
| 929 | msgid "" | ||
| 930 | " -o, --proc Prints out information like provided by the /proc/" | ||
| 931 | "acpi/processor/*/power\n" | ||
| 932 | " interface in older kernels\n" | ||
| 933 | msgstr "" | ||
| 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 | ||
| 940 | msgid "You can't specify more than one output-specific argument\n" | ||
| 941 | msgstr "" | ||
| 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 000000000000..c10496fbe3c6 --- /dev/null +++ b/tools/power/cpupower/utils/builtin.h | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | #ifndef BUILTIN_H | ||
| 2 | #define BUILTIN_H | ||
| 3 | |||
| 4 | extern int cmd_set(int argc, const char **argv); | ||
| 5 | extern int cmd_info(int argc, const char **argv); | ||
| 6 | extern int cmd_freq_set(int argc, const char **argv); | ||
| 7 | extern int cmd_freq_info(int argc, const char **argv); | ||
| 8 | extern int cmd_idle_info(int argc, const char **argv); | ||
| 9 | extern 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 000000000000..28953c9a7bd5 --- /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 | |||
| 22 | static 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 | |||
| 55 | static 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 | |||
| 85 | static 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 | |||
| 112 | static 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 | |||
| 141 | static 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 | |||
| 222 | static 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 | |||
| 355 | static 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 | |||
| 371 | static 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 | |||
| 386 | static 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 | |||
| 397 | static 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 | |||
| 409 | static 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 | |||
| 421 | static 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 | |||
| 440 | static 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 | |||
| 457 | static 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 | |||
| 474 | static 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 | |||
| 499 | static 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 | |||
| 513 | static 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 | |||
| 531 | int 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 000000000000..dd1539eb8c63 --- /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 | |||
| 23 | static 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 | |||
| 32 | static 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 | |||
| 43 | struct freq_units { | ||
| 44 | char *str_unit; | ||
| 45 | int power_of_ten; | ||
| 46 | }; | ||
| 47 | |||
| 48 | const 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 | |||
| 57 | static void print_unknown_arg(void) | ||
| 58 | { | ||
| 59 | printf(_("invalid or unknown argument\n")); | ||
| 60 | } | ||
| 61 | |||
| 62 | static 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 | |||
| 140 | static 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 | |||
| 167 | static 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 | |||
| 192 | int 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 000000000000..b028267c1376 --- /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 | |||
| 23 | static 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 | |||
| 83 | static 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 | |||
| 106 | static 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 | |||
| 142 | static 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 | |||
| 148 | static inline void cpuidle_exit(int fail) | ||
| 149 | { | ||
| 150 | exit(EXIT_FAILURE); | ||
| 151 | } | ||
| 152 | |||
| 153 | int 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 000000000000..3f68632c28c7 --- /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 | |||
| 19 | static 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 | |||
| 26 | static void print_wrong_arg_exit(void) | ||
| 27 | { | ||
| 28 | printf(_("invalid or unknown argument\n")); | ||
| 29 | exit(EXIT_FAILURE); | ||
| 30 | } | ||
| 31 | |||
| 32 | int 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 000000000000..dc4de3762111 --- /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 | |||
| 20 | static 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 | |||
| 27 | static void print_wrong_arg_exit(void) | ||
| 28 | { | ||
| 29 | printf(_("invalid or unknown argument\n")); | ||
| 30 | exit(EXIT_FAILURE); | ||
| 31 | } | ||
| 32 | |||
| 33 | int 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 000000000000..52bee591c1c5 --- /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 | |||
| 20 | struct 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 | |||
| 28 | static 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 | */ | ||
| 35 | struct cpupower_cpu_info cpupower_cpu_info; | ||
| 36 | int run_as_root; | ||
| 37 | /* Affected cpus chosen by -c/--cpu param */ | ||
| 38 | struct bitmask *cpus_chosen; | ||
| 39 | |||
| 40 | #ifdef DEBUG | ||
| 41 | int be_verbose; | ||
| 42 | #endif | ||
| 43 | |||
| 44 | static void print_help(void); | ||
| 45 | |||
| 46 | static 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 | |||
| 57 | static 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 | |||
| 73 | static 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 | |||
| 98 | static 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 | |||
| 109 | static void print_version(void) | ||
| 110 | { | ||
| 111 | printf(PACKAGE " " VERSION "\n"); | ||
| 112 | printf(_("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT); | ||
| 113 | } | ||
| 114 | |||
| 115 | static 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 | |||
| 167 | int 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 000000000000..87d5605bdda8 --- /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 | |||
| 15 | union 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 | |||
| 32 | static 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 | |||
| 44 | static 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 | */ | ||
| 72 | int 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 | |||
| 112 | int 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 000000000000..5c074c60f904 --- /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 */ | ||
| 23 | struct 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` */ | ||
| 40 | void 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 */ | ||
| 61 | static 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) */ | ||
| 70 | static 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 | */ | ||
| 98 | static 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 | |||
| 104 | static 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 */ | ||
| 114 | struct 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 */ | ||
| 121 | struct 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 */ | ||
| 130 | struct 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 */ | ||
| 139 | int 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 */ | ||
| 149 | int bitmask_isbitset(const struct bitmask *bmp, unsigned int i) | ||
| 150 | { | ||
| 151 | return _getbit(bmp, i); | ||
| 152 | } | ||
| 153 | |||
| 154 | /* Number of lowest set bit (min) */ | ||
| 155 | unsigned int bitmask_first(const struct bitmask *bmp) | ||
| 156 | { | ||
| 157 | return bitmask_next(bmp, 0); | ||
| 158 | } | ||
| 159 | |||
| 160 | /* Number of highest set bit (max) */ | ||
| 161 | unsigned 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 */ | ||
| 172 | unsigned 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 | */ | ||
| 191 | int 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; | ||
| 234 | err: | ||
| 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 | |||
| 248 | static 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 | |||
| 274 | int 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 000000000000..eb289df41053 --- /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 | |||
| 10 | struct bitmask { | ||
| 11 | unsigned int size; | ||
| 12 | unsigned long *maskp; | ||
| 13 | }; | ||
| 14 | |||
| 15 | struct bitmask *bitmask_alloc(unsigned int n); | ||
| 16 | void bitmask_free(struct bitmask *bmp); | ||
| 17 | |||
| 18 | struct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i); | ||
| 19 | struct bitmask *bitmask_setall(struct bitmask *bmp); | ||
| 20 | struct bitmask *bitmask_clearall(struct bitmask *bmp); | ||
| 21 | |||
| 22 | unsigned int bitmask_first(const struct bitmask *bmp); | ||
| 23 | unsigned int bitmask_next(const struct bitmask *bmp, unsigned int i); | ||
| 24 | unsigned int bitmask_last(const struct bitmask *bmp); | ||
| 25 | int bitmask_isallclear(const struct bitmask *bmp); | ||
| 26 | int bitmask_isbitset(const struct bitmask *bmp, unsigned int i); | ||
| 27 | |||
| 28 | int bitmask_parselist(const char *buf, struct bitmask *bmp); | ||
| 29 | int 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 000000000000..906895d21cce --- /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 | |||
| 9 | static 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 | } | ||
| 30 | cpuid_func(eax); | ||
| 31 | cpuid_func(ebx); | ||
| 32 | cpuid_func(ecx); | ||
| 33 | cpuid_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 | */ | ||
| 45 | int 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; | ||
| 107 | out: | ||
| 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 000000000000..2747e738efb0 --- /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 | |||
| 35 | extern int run_as_root; | ||
| 36 | extern 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 | ||
| 46 | extern 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 | ||
| 55 | static inline void dprint(const char *fmt, ...) { } | ||
| 56 | #endif | ||
| 57 | extern int be_verbose; | ||
| 58 | /* Global verbose (-v) stuff *********************************/ | ||
| 59 | |||
| 60 | /* cpuid and cpuinfo helpers **************************/ | ||
| 61 | enum 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 | |||
| 74 | struct 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 | */ | ||
| 91 | extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info); | ||
| 92 | extern struct cpupower_cpu_info cpupower_cpu_info; | ||
| 93 | /* cpuid and cpuinfo helpers **************************/ | ||
| 94 | |||
| 95 | |||
| 96 | /* CPU topology/hierarchy parsing ******************/ | ||
| 97 | struct 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 | |||
| 114 | extern int get_cpu_topology(struct cpupower_topology *cpu_top); | ||
| 115 | extern 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 ****************************/ | ||
| 124 | extern int read_msr(int cpu, unsigned int idx, unsigned long long *val); | ||
| 125 | extern int write_msr(int cpu, unsigned int idx, unsigned long long val); | ||
| 126 | |||
| 127 | extern int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val); | ||
| 128 | extern int msr_intel_get_perf_bias(unsigned int cpu); | ||
| 129 | extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu); | ||
| 130 | |||
| 131 | /* Read/Write msr ****************************/ | ||
| 132 | |||
| 133 | /* PCI stuff ****************************/ | ||
| 134 | extern int amd_pci_get_num_boost_states(int *active, int *states); | ||
| 135 | extern 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 | |||
| 142 | extern 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 | |||
| 147 | extern int cpufreq_has_boost_support(unsigned int cpu, int *support, | ||
| 148 | int *active, int * states); | ||
| 149 | /* | ||
| 150 | * CPUID functions returning a single datum | ||
| 151 | */ | ||
| 152 | unsigned int cpuid_eax(unsigned int op); | ||
| 153 | unsigned int cpuid_ebx(unsigned int op); | ||
| 154 | unsigned int cpuid_ecx(unsigned int op); | ||
| 155 | unsigned int cpuid_edx(unsigned int op); | ||
| 156 | |||
| 157 | /* cpuid and cpuinfo helpers **************************/ | ||
| 158 | /* X86 ONLY ********************************************/ | ||
| 159 | #else | ||
| 160 | static 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 | |||
| 165 | static inline int read_msr(int cpu, unsigned int idx, unsigned long long *val) | ||
| 166 | { return -1; }; | ||
| 167 | static inline int write_msr(int cpu, unsigned int idx, unsigned long long val) | ||
| 168 | { return -1; }; | ||
| 169 | static inline int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val) | ||
| 170 | { return -1; }; | ||
| 171 | static inline int msr_intel_get_perf_bias(unsigned int cpu) | ||
| 172 | { return -1; }; | ||
| 173 | static inline unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu) | ||
| 174 | { return 0; }; | ||
| 175 | |||
| 176 | /* Read/Write msr ****************************/ | ||
| 177 | |||
| 178 | static 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 | |||
| 184 | static inline unsigned int cpuid_eax(unsigned int op) { return 0; }; | ||
| 185 | static inline unsigned int cpuid_ebx(unsigned int op) { return 0; }; | ||
| 186 | static inline unsigned int cpuid_ecx(unsigned int op) { return 0; }; | ||
| 187 | static 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 000000000000..1609243f5c64 --- /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 | |||
| 5 | int 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 000000000000..31a4b24a8bc6 --- /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 | |||
| 26 | int 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 | */ | ||
| 55 | int 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 | |||
| 75 | int 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 | |||
| 89 | int 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 | |||
| 102 | unsigned 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 000000000000..cd2eb6fe41c4 --- /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 | */ | ||
| 20 | struct 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 000000000000..c6343024a611 --- /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 | |||
| 19 | unsigned 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 | |||
| 40 | static 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 | */ | ||
| 67 | int 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 | */ | ||
| 117 | unsigned 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 | |||
| 145 | enum idlestate_value { | ||
| 146 | IDLESTATE_USAGE, | ||
| 147 | IDLESTATE_POWER, | ||
| 148 | IDLESTATE_LATENCY, | ||
| 149 | IDLESTATE_TIME, | ||
| 150 | MAX_IDLESTATE_VALUE_FILES | ||
| 151 | }; | ||
| 152 | |||
| 153 | static 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 | |||
| 160 | static 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 | |||
| 188 | enum idlestate_string { | ||
| 189 | IDLESTATE_DESC, | ||
| 190 | IDLESTATE_NAME, | ||
| 191 | MAX_IDLESTATE_STRING_FILES | ||
| 192 | }; | ||
| 193 | |||
| 194 | static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = { | ||
| 195 | [IDLESTATE_DESC] = "desc", | ||
| 196 | [IDLESTATE_NAME] = "name", | ||
| 197 | }; | ||
| 198 | |||
| 199 | |||
| 200 | static 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 | |||
| 227 | unsigned 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 | |||
| 233 | unsigned 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 | |||
| 239 | unsigned 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 | |||
| 245 | char *sysfs_get_idlestate_name(unsigned int cpu, unsigned int idlestate) | ||
| 246 | { | ||
| 247 | return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_NAME); | ||
| 248 | } | ||
| 249 | |||
| 250 | char *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 | */ | ||
| 260 | int 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 | */ | ||
| 290 | static 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 | |||
| 304 | enum cpuidle_string { | ||
| 305 | CPUIDLE_GOVERNOR, | ||
| 306 | CPUIDLE_GOVERNOR_RO, | ||
| 307 | CPUIDLE_DRIVER, | ||
| 308 | MAX_CPUIDLE_STRING_FILES | ||
| 309 | }; | ||
| 310 | |||
| 311 | static 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 | |||
| 318 | static 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 | |||
| 342 | char *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 | |||
| 351 | char *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 | */ | ||
| 363 | int 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 | */ | ||
| 389 | int 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 000000000000..8cb797bbceb0 --- /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 | |||
| 8 | extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen); | ||
| 9 | |||
| 10 | extern int sysfs_is_cpu_online(unsigned int cpu); | ||
| 11 | |||
| 12 | extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu, | ||
| 13 | unsigned int idlestate); | ||
| 14 | extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu, | ||
| 15 | unsigned int idlestate); | ||
| 16 | extern unsigned long long sysfs_get_idlestate_time(unsigned int cpu, | ||
| 17 | unsigned int idlestate); | ||
| 18 | extern char *sysfs_get_idlestate_name(unsigned int cpu, | ||
| 19 | unsigned int idlestate); | ||
| 20 | extern char *sysfs_get_idlestate_desc(unsigned int cpu, | ||
| 21 | unsigned int idlestate); | ||
| 22 | extern int sysfs_get_idlestate_count(unsigned int cpu); | ||
| 23 | |||
| 24 | extern char *sysfs_get_cpuidle_governor(void); | ||
| 25 | extern char *sysfs_get_cpuidle_driver(void); | ||
| 26 | |||
| 27 | extern int sysfs_get_sched(const char *smt_mc); | ||
| 28 | extern 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 000000000000..4eae2c47ba48 --- /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 */ | ||
| 23 | int 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 | |||
| 40 | struct 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 | |||
| 48 | static 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 | */ | ||
| 74 | int 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 | |||
| 108 | void 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 000000000000..202e555988be --- /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 | |||
| 45 | enum amd_fam14h_states {NON_PC0 = 0, PC1, PC6, NBP1, | ||
| 46 | AMD_FAM14H_STATE_NUM}; | ||
| 47 | |||
| 48 | static int fam14h_get_count_percent(unsigned int self_id, double *percent, | ||
| 49 | unsigned int cpu); | ||
| 50 | static int fam14h_nbp1_count(unsigned int id, unsigned long long *count, | ||
| 51 | unsigned int cpu); | ||
| 52 | |||
| 53 | static 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 | |||
| 84 | static struct pci_access *pci_acc; | ||
| 85 | static int pci_vendor_id = 0x1022; | ||
| 86 | static int pci_dev_ids[2] = {0x1716, 0}; | ||
| 87 | static struct pci_dev *amd_fam14h_pci_dev; | ||
| 88 | |||
| 89 | static int nbp1_entered; | ||
| 90 | |||
| 91 | struct timespec start_time; | ||
| 92 | static unsigned long long timediff; | ||
| 93 | |||
| 94 | #ifdef DEBUG | ||
| 95 | struct timespec dbg_time; | ||
| 96 | long dbg_timediff; | ||
| 97 | #endif | ||
| 98 | |||
| 99 | static unsigned long long *previous_count[AMD_FAM14H_STATE_NUM]; | ||
| 100 | static unsigned long long *current_count[AMD_FAM14H_STATE_NUM]; | ||
| 101 | |||
| 102 | static 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 | |||
| 130 | static 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 | |||
| 165 | static 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 | |||
| 201 | static 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 | } | ||
| 213 | static 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 | |||
| 234 | static 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 | |||
| 251 | static 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 | |||
| 275 | static 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 | |||
| 282 | struct 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 | |||
| 317 | static 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 | |||
| 327 | struct 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 000000000000..bcd22a1a3970 --- /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 | ||
| 19 | static cstate_t cpuidle_cstates[CPUIDLE_STATES_MAX]; | ||
| 20 | struct cpuidle_monitor cpuidle_sysfs_monitor; | ||
| 21 | |||
| 22 | static unsigned long long **previous_count; | ||
| 23 | static unsigned long long **current_count; | ||
| 24 | struct timespec start_time; | ||
| 25 | static unsigned long long timediff; | ||
| 26 | |||
| 27 | static 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 | |||
| 46 | static 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 | |||
| 62 | static 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 | |||
| 81 | void 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 | |||
| 129 | static 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 | |||
| 175 | void 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 | |||
| 187 | struct 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 000000000000..0d6571e418db --- /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 , | ||
| 27 | struct cpuidle_monitor *all_monitors[] = { | ||
| 28 | #include "idle_monitors.def" | ||
| 29 | 0 | ||
| 30 | }; | ||
| 31 | |||
| 32 | static struct cpuidle_monitor *monitors[MONITORS_MAX]; | ||
| 33 | static unsigned int avail_monitors; | ||
| 34 | |||
| 35 | static char *progname; | ||
| 36 | |||
| 37 | enum operation_mode_e { list = 1, show, show_all }; | ||
| 38 | static int mode; | ||
| 39 | static int interval = 1; | ||
| 40 | static char *show_monitors_param; | ||
| 41 | static struct cpupower_topology cpu_top; | ||
| 42 | |||
| 43 | /* ToDo: Document this in the manpage */ | ||
| 44 | static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', }; | ||
| 45 | |||
| 46 | static void print_wrong_arg_exit(void) | ||
| 47 | { | ||
| 48 | printf(_("invalid or unknown argument\n")); | ||
| 49 | exit(EXIT_FAILURE); | ||
| 50 | } | ||
| 51 | |||
| 52 | long 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 | |||
| 65 | void 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 */ | ||
| 73 | int 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 | |||
| 84 | void 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 | |||
| 135 | void 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 | |||
| 211 | static 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 | |||
| 248 | void 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 | |||
| 272 | int 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 | |||
| 315 | int 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 | |||
| 331 | static 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 | |||
| 363 | int 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 000000000000..9312ee1f2dbc --- /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 | |||
| 21 | int cpu_count; | ||
| 22 | |||
| 23 | /* Hard to define the right names ...: */ | ||
| 24 | enum 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 | |||
| 32 | typedef 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 | |||
| 45 | struct 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 | |||
| 59 | extern 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 000000000000..e3f8d9b2b18f --- /dev/null +++ b/tools/power/cpupower/utils/idle_monitor/idle_monitors.def | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | #if defined(__i386__) || defined(__x86_64__) | ||
| 2 | DEF(amd_fam14h) | ||
| 3 | DEF(intel_nhm) | ||
| 4 | DEF(intel_snb) | ||
| 5 | DEF(mperf) | ||
| 6 | #endif | ||
| 7 | DEF(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 000000000000..4fcdeb1e07e8 --- /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 | ||
| 16 | extern 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 000000000000..5650ab5a2c20 --- /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 | |||
| 27 | enum mperf_id { C0 = 0, Cx, AVG_FREQ, MPERF_CSTATE_COUNT }; | ||
| 28 | |||
| 29 | static int mperf_get_count_percent(unsigned int self_id, double *percent, | ||
| 30 | unsigned int cpu); | ||
| 31 | static int mperf_get_count_freq(unsigned int id, unsigned long long *count, | ||
| 32 | unsigned int cpu); | ||
| 33 | static struct timespec time_start, time_end; | ||
| 34 | |||
| 35 | static 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 | |||
| 60 | enum MAX_FREQ_MODE { MAX_FREQ_SYSFS, MAX_FREQ_TSC_REF }; | ||
| 61 | static 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 | */ | ||
| 68 | static unsigned long max_frequency; | ||
| 69 | |||
| 70 | static unsigned long long tsc_at_measure_start; | ||
| 71 | static unsigned long long tsc_at_measure_end; | ||
| 72 | static unsigned long long *mperf_previous_count; | ||
| 73 | static unsigned long long *aperf_previous_count; | ||
| 74 | static unsigned long long *mperf_current_count; | ||
| 75 | static unsigned long long *aperf_current_count; | ||
| 76 | |||
| 77 | /* valid flag for all CPUs. If a MSR read failed it will be zero */ | ||
| 78 | static int *is_valid; | ||
| 79 | |||
| 80 | static 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 | |||
| 89 | static 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 | |||
| 103 | static 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 | |||
| 117 | static 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 | |||
| 154 | static 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 | |||
| 186 | static 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 | |||
| 202 | static 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 | */ | ||
| 234 | static 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 | } | ||
| 275 | use_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 | */ | ||
| 297 | struct cpuidle_monitor mperf_monitor; | ||
| 298 | struct 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 | |||
| 317 | void 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 | |||
| 326 | struct 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 000000000000..d2a91dd0d563 --- /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 | |||
| 28 | enum intel_nhm_id { C3 = 0, C6, PC3, PC6, TSC = 0xFFFF }; | ||
| 29 | |||
| 30 | static int nhm_get_count_percent(unsigned int self_id, double *percent, | ||
| 31 | unsigned int cpu); | ||
| 32 | |||
| 33 | static 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 | |||
| 65 | static unsigned long long tsc_at_measure_start; | ||
| 66 | static unsigned long long tsc_at_measure_end; | ||
| 67 | static unsigned long long *previous_count[NHM_CSTATE_COUNT]; | ||
| 68 | static unsigned long long *current_count[NHM_CSTATE_COUNT]; | ||
| 69 | /* valid flag for all CPUs. If a MSR read failed it will be zero */ | ||
| 70 | static int *is_valid; | ||
| 71 | |||
| 72 | static 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 | |||
| 102 | static 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 | |||
| 127 | static 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 | |||
| 145 | static 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 | |||
| 165 | struct cpuidle_monitor intel_nhm_monitor; | ||
| 166 | |||
| 167 | struct 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 | |||
| 193 | void 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 | |||
| 204 | struct 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 000000000000..a1bc07cd53e1 --- /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 | |||
| 25 | enum intel_snb_id { C7 = 0, PC2, PC7, SNB_CSTATE_COUNT, TSC = 0xFFFF }; | ||
| 26 | |||
| 27 | static int snb_get_count_percent(unsigned int self_id, double *percent, | ||
| 28 | unsigned int cpu); | ||
| 29 | |||
| 30 | static 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 | |||
| 54 | static unsigned long long tsc_at_measure_start; | ||
| 55 | static unsigned long long tsc_at_measure_end; | ||
| 56 | static unsigned long long *previous_count[SNB_CSTATE_COUNT]; | ||
| 57 | static unsigned long long *current_count[SNB_CSTATE_COUNT]; | ||
| 58 | /* valid flag for all CPUs. If a MSR read failed it will be zero */ | ||
| 59 | static int *is_valid; | ||
| 60 | |||
| 61 | static 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 | |||
| 87 | static 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 | |||
| 112 | static 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 | |||
| 127 | static 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 | |||
| 143 | struct cpuidle_monitor intel_snb_monitor; | ||
| 144 | |||
| 145 | static 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 | |||
| 168 | void 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 | |||
| 178 | struct 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 000000000000..5ec41c556992 --- /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 | |||
| 8 | LF=' | ||
| 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 | ||
| 13 | if 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 | ||
| 22 | then | ||
| 23 | VN=$(echo "$VN" | sed -e 's/-/./g'); | ||
| 24 | else | ||
| 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}" | ||
| 31 | fi | ||
| 32 | |||
| 33 | VN=$(expr "$VN" : v*'\(.*\)') | ||
| 34 | |||
| 35 | echo $VN | ||
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 6d8ef4a3a9b5..8b2d37b59c9e 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) | |||
| 128 | void print_header(void) | 128 | void 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 2618ef2ba31f..33c5c7ee148f 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) | |||
| 137 | void validate_cpuid(void) | 137 | void 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 516551c9f172..868cc93f7ac2 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 | ||
| 100 | static void usage(void) | 103 | static 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; | |||
| 293 | static void first_line(void) | 296 | static 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 | ||
| 480 | static void report(struct slabinfo *s) | 496 | static 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 cef28e6632b9..8d02ccb10c59 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; | |||
| 62 | my $test_type; | 63 | my $test_type; |
| 63 | my $build_type; | 64 | my $build_type; |
| 64 | my $build_options; | 65 | my $build_options; |
| 66 | my $pre_build; | ||
| 67 | my $post_build; | ||
| 68 | my $pre_build_die; | ||
| 69 | my $post_build_die; | ||
| 65 | my $reboot_type; | 70 | my $reboot_type; |
| 66 | my $reboot_script; | 71 | my $reboot_script; |
| 67 | my $power_cycle; | 72 | my $power_cycle; |
| @@ -81,12 +86,17 @@ my $make; | |||
| 81 | my $post_install; | 86 | my $post_install; |
| 82 | my $noclean; | 87 | my $noclean; |
| 83 | my $minconfig; | 88 | my $minconfig; |
| 89 | my $start_minconfig; | ||
| 90 | my $start_minconfig_defined; | ||
| 91 | my $output_minconfig; | ||
| 92 | my $ignore_config; | ||
| 84 | my $addconfig; | 93 | my $addconfig; |
| 85 | my $in_bisect = 0; | 94 | my $in_bisect = 0; |
| 86 | my $bisect_bad = ""; | 95 | my $bisect_bad = ""; |
| 87 | my $reverse_bisect; | 96 | my $reverse_bisect; |
| 88 | my $bisect_manual; | 97 | my $bisect_manual; |
| 89 | my $bisect_skip; | 98 | my $bisect_skip; |
| 99 | my $config_bisect_good; | ||
| 90 | my $in_patchcheck = 0; | 100 | my $in_patchcheck = 0; |
| 91 | my $run_test; | 101 | my $run_test; |
| 92 | my $redirect; | 102 | my $redirect; |
| @@ -98,9 +108,12 @@ my $monitor_cnt = 0; | |||
| 98 | my $sleep_time; | 108 | my $sleep_time; |
| 99 | my $bisect_sleep_time; | 109 | my $bisect_sleep_time; |
| 100 | my $patchcheck_sleep_time; | 110 | my $patchcheck_sleep_time; |
| 111 | my $ignore_warnings; | ||
| 101 | my $store_failures; | 112 | my $store_failures; |
| 113 | my $test_name; | ||
| 102 | my $timeout; | 114 | my $timeout; |
| 103 | my $booted_timeout; | 115 | my $booted_timeout; |
| 116 | my $detect_triplefault; | ||
| 104 | my $console; | 117 | my $console; |
| 105 | my $success_line; | 118 | my $success_line; |
| 106 | my $stop_after_success; | 119 | my $stop_after_success; |
| @@ -115,6 +128,7 @@ my $successes = 0; | |||
| 115 | my %entered_configs; | 128 | my %entered_configs; |
| 116 | my %config_help; | 129 | my %config_help; |
| 117 | my %variable; | 130 | my %variable; |
| 131 | my %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" | |||
| 204 | EOF | 218 | EOF |
| 205 | ; | 219 | ; |
| 206 | 220 | ||
| 221 | sub 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 | ||
| 208 | sub get_ktest_config { | 242 | sub 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 | ||
| 521 | sub __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 | |||
| 561 | sub 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 | |||
| 476 | sub _logit { | 584 | sub _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 | ||
| 1074 | sub 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 | |||
| 926 | sub install { | 1084 | sub 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; | 1134 | sub 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 | |||
| 1142 | sub start_monitor_and_boot { | ||
| 1143 | get_grub_index; | ||
| 1144 | get_version; | ||
| 1145 | install; | ||
| 1146 | |||
| 1147 | start_monitor; | ||
| 1148 | return monitor; | ||
| 978 | } | 1149 | } |
| 979 | 1150 | ||
| 980 | sub check_buildlog { | 1151 | sub check_buildlog { |
| @@ -1009,24 +1180,84 @@ sub check_buildlog { | |||
| 1009 | return 1; | 1180 | return 1; |
| 1010 | } | 1181 | } |
| 1011 | 1182 | ||
| 1183 | sub 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 | |||
| 1012 | sub make_oldconfig { | 1214 | sub 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. | ||
| 1232 | sub 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 | |||
| 1024 | sub build { | 1248 | sub 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 | ||
| 1120 | sub 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 | |||
| 1128 | sub answer_bisect { | 1366 | sub 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 | ||
| 1474 | my %dependency; | 1707 | my %dependency; |
| 1475 | 1708 | ||
| 1476 | sub process_config_ignore { | 1709 | sub 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 | ||
| 1724 | sub process_config_ignore { | ||
| 1725 | my ($config) = @_; | ||
| 1726 | |||
| 1727 | assign_configs \%config_ignore, $config; | ||
| 1728 | } | ||
| 1729 | |||
| 1491 | sub read_current_config { | 1730 | sub 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 | ||
| 1552 | sub compare_configs { | 1791 | sub 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 | ||
| 2180 | my %depends; | ||
| 2181 | my $iflevel = 0; | ||
| 2182 | my @ifdeps; | ||
| 2183 | |||
| 2184 | # prevent recursion | ||
| 2185 | my %read_kconfigs; | ||
| 2186 | |||
| 2187 | # taken from streamline_config.pl | ||
| 2188 | sub 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 | |||
| 2289 | sub 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 | |||
| 2333 | sub 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 | |||
| 2350 | sub read_output_config { | ||
| 2351 | my ($config) = @_; | ||
| 2352 | |||
| 2353 | assign_configs \%config_ignore, $config; | ||
| 2354 | } | ||
| 2355 | |||
| 2356 | sub 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 | |||
| 2368 | sub 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 | |||
| 2400 | my %min_configs; | ||
| 2401 | my %keep_configs; | ||
| 2402 | my %save_configs; | ||
| 2403 | my %processed_configs; | ||
| 2404 | my %nochange_config; | ||
| 2405 | |||
| 2406 | sub 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 | |||
| 2458 | sub 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 | ||
| 1941 | if ($#ARGV == 0) { | 2674 | if ($#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 | } |
| 1978 | read_config $ktest_config; | 2700 | read_config $ktest_config; |
| 1979 | 2701 | ||
| 2702 | if (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. |
| 1981 | my @new_configs = keys %entered_configs; | 2707 | my @new_configs = keys %entered_configs; |
| 1982 | if ($#new_configs >= 0) { | 2708 | if ($#new_configs >= 0) { |
| @@ -2045,70 +2771,13 @@ sub __set_test_option { | |||
| 2045 | return undef; | 2771 | return undef; |
| 2046 | } | 2772 | } |
| 2047 | 2773 | ||
| 2048 | sub 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 | |||
| 2088 | sub set_test_option { | 2774 | sub 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 48cbcc80602a..b8bcd14b5a4d 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 | # | ||
