From bccdaba044a445eb2c391295587aa47977994777 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 2 Jun 2011 10:39:43 -0300 Subject: perf evlist: Remove dependency on debug routines So far we avoided having to link debug.o in the python binding, keep it that way by not using ui__warning() in evlist.c. Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-4wtew8hd3g7ejnlehtspys2t@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 50aa34879c33..04c8a60075b3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -12,7 +12,6 @@ #include "evlist.h" #include "evsel.h" #include "util.h" -#include "debug.h" #include @@ -257,19 +256,15 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist) return evlist->mmap != NULL ? 0 : -ENOMEM; } -static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel, +static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, int prot, int mask, int fd) { evlist->mmap[idx].prev = 0; evlist->mmap[idx].mask = mask; evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, MAP_SHARED, fd, 0); - if (evlist->mmap[idx].base == MAP_FAILED) { - if (evlist->cpus->map[idx] == -1 && evsel->attr.inherit) - ui__warning("Inherit is not allowed on per-task " - "events using mmap.\n"); + if (evlist->mmap[idx].base == MAP_FAILED) return -1; - } perf_evlist__add_pollfd(evlist, fd); return 0; @@ -289,7 +284,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int m if (output == -1) { output = fd; - if (__perf_evlist__mmap(evlist, evsel, cpu, + if (__perf_evlist__mmap(evlist, cpu, prot, mask, output) < 0) goto out_unmap; } else { @@ -329,7 +324,7 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in if (output == -1) { output = fd; - if (__perf_evlist__mmap(evlist, evsel, thread, + if (__perf_evlist__mmap(evlist, thread, prot, mask, output) < 0) goto out_unmap; } else { -- cgit v1.2.3 From 5c6970af2f4be4e04b06fe78214f6809777a8354 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 2 Jun 2011 10:55:10 -0300 Subject: perf python: Use exception to propagate errors We were using pr_debug to tell the user about not being able to parse a sample where we should really use the python way of reporting errors: exceptions. Fixes this problem: [root@emilia ~]# python >>> import perf Traceback (most recent call last): File "", line 1, in ImportError: /home/acme/git/build/perf/python/perf.so: undefined symbol: eprintf >>> [root@emilia ~] As we want to keep the objects linked in the python binding (and in the future in a shared library) minimal. Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-m9dba9kaluas0kq8r58z191c@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 69436b3200a4..2dd1698e0932 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -694,14 +694,12 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, err = perf_event__parse_sample(event, first->attr.sample_type, perf_sample_size(first->attr.sample_type), sample_id_all, &pevent->sample); - if (err) { - pr_err("Can't parse sample, err = %d\n", err); - goto end; - } - + if (err) + return PyErr_Format(PyExc_OSError, + "perf: can't parse sample, err=%d", err); return pyevent; } -end: + Py_INCREF(Py_None); return Py_None; } -- cgit v1.2.3 From c2a70653af45c9cbb0cab900e8931b062e57b1ae Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 2 Jun 2011 11:04:54 -0300 Subject: perf evlist: Don't die if sample_{id_all|type} is invalid Fixes two more cases where the python binding would not load: . Not finding die(), which it shouldn't anyway, not good to just stop the world because some particular perf.data file is invalid, just propagate the error to the caller. . Not finding perf_sample_size: fix it by moving it from event.c to evsel, where it belongs, as most cases are moving to operate on an evsel object.o One of the fixed problems: [root@emilia ~]# python >>> import perf Traceback (most recent call last): File "", line 1, in ImportError: /home/acme/git/build/perf/python/perf.so: undefined symbol: perf_sample_size >>> [root@emilia ~]# Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-1hkj7b2cvgbfnoizsekjb6c9@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-test.c | 2 +- tools/perf/util/event.c | 16 -------------- tools/perf/util/event.h | 2 -- tools/perf/util/evlist.c | 55 +++++++++++++++++++++++++++++------------------ tools/perf/util/evlist.h | 6 ++++-- tools/perf/util/evsel.c | 16 ++++++++++++++ tools/perf/util/evsel.h | 7 ++++++ tools/perf/util/python.c | 2 +- tools/perf/util/session.c | 12 ++++++++++- 9 files changed, 74 insertions(+), 44 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index b67186228c89..2da9162262b0 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -474,7 +474,7 @@ static int test__basic_mmap(void) unsigned int nr_events[nsyscalls], expected_nr_events[nsyscalls], i, j; struct perf_evsel *evsels[nsyscalls], *evsel; - int sample_size = perf_sample_size(attr.sample_type); + int sample_size = __perf_evsel__sample_size(attr.sample_type); for (i = 0; i < nsyscalls; ++i) { char name[64]; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 0fe9adf76379..3c1b8a632101 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -35,22 +35,6 @@ const char *perf_event__name(unsigned int id) return perf_event__names[id]; } -int perf_sample_size(u64 sample_type) -{ - u64 mask = sample_type & PERF_SAMPLE_MASK; - int size = 0; - int i; - - for (i = 0; i < 64; i++) { - if (mask & (1ULL << i)) - size++; - } - - size *= sizeof(u64); - - return size; -} - static struct perf_sample synth_sample = { .pid = -1, .tid = -1, diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index c08332871408..1d7f66488a88 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -82,8 +82,6 @@ struct perf_sample { struct ip_callchain *callchain; }; -int perf_sample_size(u64 sample_type); - #define BUILD_ID_SIZE 20 struct build_id_event { diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 04c8a60075b3..b021ea9265c3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -455,33 +455,46 @@ int perf_evlist__set_filters(struct perf_evlist *evlist) return 0; } -u64 perf_evlist__sample_type(struct perf_evlist *evlist) +bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist) { - struct perf_evsel *pos; - u64 type = 0; - - list_for_each_entry(pos, &evlist->entries, node) { - if (!type) - type = pos->attr.sample_type; - else if (type != pos->attr.sample_type) - die("non matching sample_type"); + struct perf_evsel *pos, *first; + + pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); + + list_for_each_entry_continue(pos, &evlist->entries, node) { + if (first->attr.sample_type != pos->attr.sample_type) + return false; } - return type; + return true; } -bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) +u64 perf_evlist__sample_type(const struct perf_evlist *evlist) +{ + struct perf_evsel *first; + + first = list_entry(evlist->entries.next, struct perf_evsel, node); + return first->attr.sample_type; +} + +bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist) { - bool value = false, first = true; - struct perf_evsel *pos; - - list_for_each_entry(pos, &evlist->entries, node) { - if (first) { - value = pos->attr.sample_id_all; - first = false; - } else if (value != pos->attr.sample_id_all) - die("non matching sample_id_all"); + struct perf_evsel *pos, *first; + + pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); + + list_for_each_entry_continue(pos, &evlist->entries, node) { + if (first->attr.sample_id_all != pos->attr.sample_id_all) + return false; } - return value; + return true; +} + +bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) +{ + struct perf_evsel *first; + + first = list_entry(evlist->entries.next, struct perf_evsel, node); + return first->attr.sample_id_all; } diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 0a1ef1f051f0..b2b862374f37 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -66,7 +66,9 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, void perf_evlist__delete_maps(struct perf_evlist *evlist); int perf_evlist__set_filters(struct perf_evlist *evlist); -u64 perf_evlist__sample_type(struct perf_evlist *evlist); -bool perf_evlist__sample_id_all(const struct perf_evlist *evlist); +u64 perf_evlist__sample_type(const struct perf_evlist *evlist); +bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); +bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); +bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); #endif /* __PERF_EVLIST_H */ diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index cca29ededb5b..0239eb87b232 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -15,6 +15,22 @@ #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) +int __perf_evsel__sample_size(u64 sample_type) +{ + u64 mask = sample_type & PERF_SAMPLE_MASK; + int size = 0; + int i; + + for (i = 0; i < 64; i++) { + if (mask & (1ULL << i)) + size++; + } + + size *= sizeof(u64); + + return size; +} + void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, int idx) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index f79bb2c09a6c..7e9366e4490b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -149,4 +149,11 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel, return __perf_evsel__read(evsel, ncpus, nthreads, true); } +int __perf_evsel__sample_size(u64 sample_type); + +static inline int perf_evsel__sample_size(struct perf_evsel *evsel) +{ + return __perf_evsel__sample_size(evsel->attr.sample_type); +} + #endif /* __PERF_EVSEL_H */ diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 2dd1698e0932..24063b4d41e0 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -692,7 +692,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, first = list_entry(evlist->entries.next, struct perf_evsel, node); err = perf_event__parse_sample(event, first->attr.sample_type, - perf_sample_size(first->attr.sample_type), + perf_evsel__sample_size(first), sample_id_all, &pevent->sample); if (err) return PyErr_Format(PyExc_OSError, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 64500fc78799..f5a8fbdd3f76 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -58,6 +58,16 @@ static int perf_session__open(struct perf_session *self, bool force) goto out_close; } + if (!perf_evlist__valid_sample_type(self->evlist)) { + pr_err("non matching sample_type"); + goto out_close; + } + + if (!perf_evlist__valid_sample_id_all(self->evlist)) { + pr_err("non matching sample_id_all"); + goto out_close; + } + self->size = input_stat.st_size; return 0; @@ -97,7 +107,7 @@ out: void perf_session__update_sample_type(struct perf_session *self) { self->sample_type = perf_evlist__sample_type(self->evlist); - self->sample_size = perf_sample_size(self->sample_type); + self->sample_size = __perf_evsel__sample_size(self->sample_type); self->sample_id_all = perf_evlist__sample_id_all(self->evlist); perf_session__id_header_size(self); } -- cgit v1.2.3 From e95cc02880947e9f77540b03e166470e8ac14cbc Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 31 Mar 2011 18:27:42 +0200 Subject: perf python: Fix argument name list of read_on_cpu() Mandatory arguments need to be present in the argument name list, as well as optional arguments, otherwise python barfs: # ./python/twatch.py Traceback (most recent call last): File "./python/twatch.py", line 41, in main() File "./python/twatch.py", line 32, in main event = evlist.read_on_cpu(cpu) RuntimeError: more argument specifiers than keyword list entries Hence, add cpu to the name list. Cc: David Ahern Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Tom Zanussi Link: http://lkml.kernel.org/r/1301588863-20210-1-git-send-email-fweisbec@gmail.com Signed-off-by: Frederic Weisbecker Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 24063b4d41e0..a9ac0504aabd 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -674,7 +674,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, struct perf_evlist *evlist = &pevlist->evlist; union perf_event *event; int sample_id_all = 1, cpu; - static char *kwlist[] = {"sample_id_all", NULL, NULL}; + static char *kwlist[] = {"cpu", "sample_id_all", NULL, NULL}; int err; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, -- cgit v1.2.3 From 64348153c63b8c1f99f19f14a9c3cbd5df70c9d3 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 31 Mar 2011 18:27:43 +0200 Subject: perf python: Cleanup useless double NULL termination in method arg names The list of methods argument names only needs to be NULL terminated once. Remove the second ones. Cc: David Ahern Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Tom Zanussi Link: http://lkml.kernel.org/r/1301588863-20210-2-git-send-email-fweisbec@gmail.com Signed-off-by: Frederic Weisbecker Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index a9ac0504aabd..8e0b5a39d8a7 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -247,7 +247,7 @@ struct pyrf_cpu_map { static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, PyObject *args, PyObject *kwargs) { - static char *kwlist[] = { "cpustr", NULL, NULL, }; + static char *kwlist[] = { "cpustr", NULL }; char *cpustr = NULL; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", @@ -316,7 +316,7 @@ struct pyrf_thread_map { static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, PyObject *args, PyObject *kwargs) { - static char *kwlist[] = { "pid", "tid", NULL, NULL, }; + static char *kwlist[] = { "pid", "tid", NULL }; int pid = -1, tid = -1; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", @@ -418,7 +418,9 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel, "wakeup_events", "bp_type", "bp_addr", - "bp_len", NULL, NULL, }; + "bp_len", + NULL + }; u64 sample_period = 0; u32 disabled = 0, inherit = 0, @@ -499,7 +501,7 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, struct thread_map *threads = NULL; PyObject *pcpus = NULL, *pthreads = NULL; int group = 0, inherit = 0; - static char *kwlist[] = {"cpus", "threads", "group", "inherit", NULL, NULL}; + static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, &pcpus, &pthreads, &group, &inherit)) @@ -582,8 +584,7 @@ static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist, PyObject *args, PyObject *kwargs) { struct perf_evlist *evlist = &pevlist->evlist; - static char *kwlist[] = {"pages", "overwrite", - NULL, NULL}; + static char *kwlist[] = { "pages", "overwrite", NULL }; int pages = 128, overwrite = false; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist, @@ -603,7 +604,7 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist, PyObject *args, PyObject *kwargs) { struct perf_evlist *evlist = &pevlist->evlist; - static char *kwlist[] = {"timeout", NULL, NULL}; + static char *kwlist[] = { "timeout", NULL }; int timeout = -1, n; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout)) @@ -674,7 +675,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, struct perf_evlist *evlist = &pevlist->evlist; union perf_event *event; int sample_id_all = 1, cpu; - static char *kwlist[] = {"cpu", "sample_id_all", NULL, NULL}; + static char *kwlist[] = { "cpu", "sample_id_all", NULL }; int err; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, -- cgit v1.2.3 From 2cee77c4505fc581f41b44e18ffc0953b67a414c Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 30 May 2011 08:55:59 -0600 Subject: perf stat: clarify unsupported events from uncounted events perf stat continues running even if the event list contains counters that are not supported. The resulting output then contains for those events which gets confusing as to which events are supported, but not counted and which are not supported. Before: perf stat -ddd -- sleep 1 Performance counter stats for 'sleep 1': 0.571283 task-clock # 0.001 CPUs utilized 1 context-switches # 0.002 M/sec 0 CPU-migrations # 0.000 M/sec 157 page-faults # 0.275 M/sec 1,037,707 cycles # 1.816 GHz stalled-cycles-frontend stalled-cycles-backend 654,499 instructions # 0.63 insns per cycle 136,129 branches # 238.286 M/sec branch-misses L1-dcache-loads L1-dcache-load-misses LLC-loads LLC-load-misses L1-icache-loads L1-icache-load-misses dTLB-loads dTLB-load-misses iTLB-loads iTLB-load-misses L1-dcache-prefetches L1-dcache-prefetch-misses 1.001004836 seconds time elapsed After: perf stat -ddd -- sleep 1 Performance counter stats for 'sleep 1': 1.350326 task-clock # 0.001 CPUs utilized 2 context-switches # 0.001 M/sec 0 CPU-migrations # 0.000 M/sec 157 page-faults # 0.116 M/sec 11,986 cycles # 0.009 GHz stalled-cycles-frontend stalled-cycles-backend 496,986 instructions # 41.46 insns per cycle 138,065 branches # 102.246 M/sec 7,245 branch-misses # 5.25% of all branches L1-dcache-loads L1-dcache-load-misses LLC-loads LLC-load-misses L1-icache-loads L1-icache-load-misses dTLB-loads dTLB-load-misses iTLB-loads iTLB-load-misses L1-dcache-prefetches L1-dcache-prefetch-misses 1.002397333 seconds time elapsed v1->v2: changed supported type from int to bool v2->v3 fixed vertical alignment of new struct element Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1306767359-13221-1-git-send-email-dsahern@gmail.com Signed-off-by: David Ahern Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-stat.c | 9 +++++++-- tools/perf/util/evsel.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index a9f06715e44d..784ed6d6e0d6 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -61,6 +61,8 @@ #include #define DEFAULT_SEPARATOR " " +#define CNTR_NOT_SUPPORTED "" +#define CNTR_NOT_COUNTED "" static struct perf_event_attr default_attrs[] = { @@ -448,6 +450,7 @@ static int run_perf_stat(int argc __used, const char **argv) if (verbose) ui__warning("%s event is not supported by the kernel.\n", event_name(counter)); + counter->supported = false; continue; } @@ -466,6 +469,7 @@ static int run_perf_stat(int argc __used, const char **argv) die("Not all events could be opened.\n"); return -1; } + counter->supported = true; } if (perf_evlist__set_filters(evsel_list)) { @@ -861,7 +865,7 @@ static void print_counter_aggr(struct perf_evsel *counter) if (scaled == -1) { fprintf(stderr, "%*s%s%*s", csv_output ? 0 : 18, - "", + counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, csv_sep, csv_output ? 0 : -24, event_name(counter)); @@ -914,7 +918,8 @@ static void print_counter(struct perf_evsel *counter) csv_output ? 0 : -4, evsel_list->cpus->map[cpu], csv_sep, csv_output ? 0 : 18, - "", csv_sep, + counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, + csv_sep, csv_output ? 0 : -24, event_name(counter)); 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 { off_t id_offset; }; struct cgroup_sel *cgrp; + bool supported; }; struct cpu_map; -- cgit v1.2.3 From 787bef174f055343c69a9639e6e05a564980ed4c Mon Sep 17 00:00:00 2001 From: David Ahern Date: Fri, 27 May 2011 14:28:43 -0600 Subject: perf script: "sym" field really means show IP data Currently the "sym" output field is used to dump instruction pointers and callchain stack. Sample addresses can also be converted to symbols, so the meaning of "sym" needs to be fixed. This patch adds an "ip" option and if it is selected the user can also opt to dump symbols for them. If the user opts to dump IP without syms only the address is shown. Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1306528124-25861-2-git-send-email-dsahern@gmail.com Signed-off-by: David Ahern Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-script.txt | 10 +++---- tools/perf/builtin-script.c | 31 +++++++++++++------- tools/perf/util/session.c | 50 ++++++++++++++++++-------------- tools/perf/util/session.h | 5 ++-- 4 files changed, 58 insertions(+), 38 deletions(-) (limited to 'tools') diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 86c87e214b11..67a4e5cbc880 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -115,10 +115,10 @@ OPTIONS -f:: --fields:: Comma separated list of fields to print. Options are: - comm, tid, pid, time, cpu, event, trace, sym. Field + comm, tid, pid, time, cpu, event, trace, ip, sym. Field list can be prepended with the type, trace, sw or hw, to indicate to which event type the field list applies. - e.g., -f sw:comm,tid,time,sym and -f trace:time,cpu,trace + e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace perf script -f @@ -132,17 +132,17 @@ OPTIONS The arguments are processed in the order received. A later usage can reset a prior request. e.g.: - -f trace: -f comm,tid,time,sym + -f trace: -f comm,tid,time,ip,sym The first -f suppresses trace events (field list is ""), but then the - second invocation sets the fields to comm,tid,time,sym. In this case a + second invocation sets the fields to comm,tid,time,ip,sym. In this case a warning is given to the user: "Overriding previous field request for all events." Alternativey, consider the order: - -f comm,tid,time,sym -f trace: + -f comm,tid,time,ip,sym -f trace: The first -f sets the fields for all events and the second -f suppresses trace events. The user is given a warning message about diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 22747de7234b..0852db2ea155 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -30,7 +30,8 @@ enum perf_output_field { PERF_OUTPUT_CPU = 1U << 4, PERF_OUTPUT_EVNAME = 1U << 5, PERF_OUTPUT_TRACE = 1U << 6, - PERF_OUTPUT_SYM = 1U << 7, + PERF_OUTPUT_IP = 1U << 7, + PERF_OUTPUT_SYM = 1U << 8, }; struct output_option { @@ -44,6 +45,7 @@ struct output_option { {.str = "cpu", .field = PERF_OUTPUT_CPU}, {.str = "event", .field = PERF_OUTPUT_EVNAME}, {.str = "trace", .field = PERF_OUTPUT_TRACE}, + {.str = "ip", .field = PERF_OUTPUT_IP}, {.str = "sym", .field = PERF_OUTPUT_SYM}, }; @@ -60,7 +62,8 @@ static struct { .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | - PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, + PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | + PERF_OUTPUT_SYM, .invalid_fields = PERF_OUTPUT_TRACE, }, @@ -70,7 +73,8 @@ static struct { .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | - PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, + PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | + PERF_OUTPUT_SYM, .invalid_fields = PERF_OUTPUT_TRACE, }, @@ -88,7 +92,8 @@ static struct { .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | - PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, + PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | + PERF_OUTPUT_SYM, .invalid_fields = PERF_OUTPUT_TRACE, }, @@ -157,15 +162,20 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, !perf_session__has_traces(session, "record -R")) return -EINVAL; - if (PRINT_FIELD(SYM)) { + if (PRINT_FIELD(IP)) { if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP", - PERF_OUTPUT_SYM)) + PERF_OUTPUT_IP)) return -EINVAL; if (!no_callchain && !(attr->sample_type & PERF_SAMPLE_CALLCHAIN)) symbol_conf.use_callchain = false; } + if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP)) { + pr_err("Display of symbols requested but IP is not selected.\n" + "No addresses to convert to symbols.\n"); + return -EINVAL; + } if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID", @@ -230,7 +240,7 @@ static void print_sample_start(struct perf_sample *sample, if (PRINT_FIELD(COMM)) { if (latency_format) printf("%8.8s ", thread->comm); - else if (PRINT_FIELD(SYM) && symbol_conf.use_callchain) + else if (PRINT_FIELD(IP) && symbol_conf.use_callchain) printf("%s ", thread->comm); else printf("%16s ", thread->comm); @@ -288,12 +298,13 @@ static void process_event(union perf_event *event __unused, print_trace_event(sample->cpu, sample->raw_data, sample->raw_size); - if (PRINT_FIELD(SYM)) { + if (PRINT_FIELD(IP)) { if (!symbol_conf.use_callchain) printf(" "); else printf("\n"); - perf_session__print_symbols(event, sample, session); + perf_session__print_ip(event, sample, session, + PRINT_FIELD(SYM)); } printf("\n"); @@ -985,7 +996,7 @@ static const struct option options[] = { OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", "Look for files with symbols relative to this directory"), OPT_CALLBACK('f', "fields", NULL, "str", - "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,sym", + "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym", parse_output_fields), OPT_END() diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index f5a8fbdd3f76..ad33650cdd41 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1202,9 +1202,10 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, return NULL; } -void perf_session__print_symbols(union perf_event *event, - struct perf_sample *sample, - struct perf_session *session) +void perf_session__print_ip(union perf_event *event, + struct perf_sample *sample, + struct perf_session *session, + int print_sym) { struct addr_location al; const char *symname, *dsoname; @@ -1233,32 +1234,39 @@ void perf_session__print_symbols(union perf_event *event, if (!node) break; - if (node->sym && node->sym->name) - symname = node->sym->name; - else - symname = ""; + printf("\t%16" PRIx64, node->ip); + if (print_sym) { + if (node->sym && node->sym->name) + symname = node->sym->name; + else + symname = ""; - if (node->map && node->map->dso && node->map->dso->name) - dsoname = node->map->dso->name; - else - dsoname = ""; + if (node->map && node->map->dso && node->map->dso->name) + dsoname = node->map->dso->name; + else + dsoname = ""; - printf("\t%16" PRIx64 " %s (%s)\n", node->ip, symname, dsoname); + printf(" %s (%s)", symname, dsoname); + } + printf("\n"); callchain_cursor_advance(cursor); } } else { - if (al.sym && al.sym->name) - symname = al.sym->name; - else - symname = ""; + printf("%16" PRIx64, al.addr); + if (print_sym) { + if (al.sym && al.sym->name) + symname = al.sym->name; + else + symname = ""; - if (al.map && al.map->dso && al.map->dso->name) - dsoname = al.map->dso->name; - else - dsoname = ""; + if (al.map && al.map->dso && al.map->dso->name) + dsoname = al.map->dso->name; + else + dsoname = ""; - printf("%16" PRIx64 " %s (%s)", al.addr, symname, dsoname); + printf(" %s (%s)", symname, dsoname); + } } } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 66d4e1490879..d76af0f975d3 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -167,8 +167,9 @@ static inline int perf_session__parse_sample(struct perf_session *session, struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, unsigned int type); -void perf_session__print_symbols(union perf_event *event, +void perf_session__print_ip(union perf_event *event, struct perf_sample *sample, - struct perf_session *session); + struct perf_session *session, + int print_sym); #endif /* __PERF_SESSION_H */ -- cgit v1.2.3 From 610723f24eeb842025178a6722fa9108c4e157b6 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Fri, 27 May 2011 14:28:44 -0600 Subject: perf script: Make printing of dso a separate field option The 'sym' option displays both the function name and the DSO it comes from. Split the display of the dso into a separate option. This allows display of the ip address and symbol without the dso, thus shortening line lengths - and decluttering the output a bit. Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1306528124-25861-3-git-send-email-dsahern@gmail.com Signed-off-by: David Ahern Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-script.txt | 2 +- tools/perf/builtin-script.c | 17 ++++++++++++----- tools/perf/util/session.c | 13 ++++++++++--- tools/perf/util/session.h | 2 +- 4 files changed, 24 insertions(+), 10 deletions(-) (limited to 'tools') diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 67a4e5cbc880..1e744c2391dc 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -115,7 +115,7 @@ OPTIONS -f:: --fields:: Comma separated list of fields to print. Options are: - comm, tid, pid, time, cpu, event, trace, ip, sym. Field + comm, tid, pid, time, cpu, event, trace, ip, sym, dso. Field list can be prepended with the type, trace, sw or hw, to indicate to which event type the field list applies. e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 0852db2ea155..a8bd00f2e557 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -32,6 +32,7 @@ enum perf_output_field { PERF_OUTPUT_TRACE = 1U << 6, PERF_OUTPUT_IP = 1U << 7, PERF_OUTPUT_SYM = 1U << 8, + PERF_OUTPUT_DSO = 1U << 9, }; struct output_option { @@ -47,6 +48,7 @@ struct output_option { {.str = "trace", .field = PERF_OUTPUT_TRACE}, {.str = "ip", .field = PERF_OUTPUT_IP}, {.str = "sym", .field = PERF_OUTPUT_SYM}, + {.str = "dso", .field = PERF_OUTPUT_DSO}, }; /* default set to maintain compatibility with current format */ @@ -63,7 +65,7 @@ static struct { .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | - PERF_OUTPUT_SYM, + PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, .invalid_fields = PERF_OUTPUT_TRACE, }, @@ -74,7 +76,7 @@ static struct { .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | - PERF_OUTPUT_SYM, + PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, .invalid_fields = PERF_OUTPUT_TRACE, }, @@ -93,7 +95,7 @@ static struct { .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | - PERF_OUTPUT_SYM, + PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, .invalid_fields = PERF_OUTPUT_TRACE, }, @@ -176,6 +178,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, "No addresses to convert to symbols.\n"); return -EINVAL; } + if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP)) { + pr_err("Display of DSO requested but IP is not selected.\n" + "No addresses to convert to dso.\n"); + return -EINVAL; + } if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID", @@ -304,7 +311,7 @@ static void process_event(union perf_event *event __unused, else printf("\n"); perf_session__print_ip(event, sample, session, - PRINT_FIELD(SYM)); + PRINT_FIELD(SYM), PRINT_FIELD(DSO)); } printf("\n"); @@ -996,7 +1003,7 @@ static const struct option options[] = { OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", "Look for files with symbols relative to this directory"), OPT_CALLBACK('f', "fields", NULL, "str", - "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym", + "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso", parse_output_fields), OPT_END() diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index ad33650cdd41..0dd418299261 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1205,7 +1205,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, void perf_session__print_ip(union perf_event *event, struct perf_sample *sample, struct perf_session *session, - int print_sym) + int print_sym, int print_dso) { struct addr_location al; const char *symname, *dsoname; @@ -1241,12 +1241,15 @@ void perf_session__print_ip(union perf_event *event, else symname = ""; + printf(" %s", symname); + } + if (print_dso) { if (node->map && node->map->dso && node->map->dso->name) dsoname = node->map->dso->name; else dsoname = ""; - printf(" %s (%s)", symname, dsoname); + printf(" (%s)", dsoname); } printf("\n"); @@ -1261,12 +1264,16 @@ void perf_session__print_ip(union perf_event *event, else symname = ""; + printf(" %s", symname); + } + + if (print_dso) { if (al.map && al.map->dso && al.map->dso->name) dsoname = al.map->dso->name; else dsoname = ""; - printf(" %s (%s)", symname, dsoname); + printf(" (%s)", dsoname); } } } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index d76af0f975d3..de4178d7bb7b 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -170,6 +170,6 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, void perf_session__print_ip(union perf_event *event, struct perf_sample *sample, struct perf_session *session, - int print_sym); + int print_sym, int print_dso); #endif /* __PERF_SESSION_H */ -- cgit v1.2.3 From 7cec0922389e080d11ec43dd23aa778e136bd1e1 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 30 May 2011 13:08:23 -0600 Subject: perf script: Add printing of sample address Resolve to a function or variable if possible and if the sym option is enabled. Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1306782503-22002-1-git-send-email-dsahern@gmail.com Signed-off-by: David Ahern Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-script.txt | 4 +- tools/perf/builtin-script.c | 84 +++++++++++++++++++++++++++++--- tools/perf/util/evsel.c | 1 + tools/perf/util/session.c | 4 +- 4 files changed, 82 insertions(+), 11 deletions(-) (limited to 'tools') diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 1e744c2391dc..c6068cb43f57 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -115,8 +115,8 @@ OPTIONS -f:: --fields:: Comma separated list of fields to print. Options are: - comm, tid, pid, time, cpu, event, trace, ip, sym, dso. Field - list can be prepended with the type, trace, sw or hw, + comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr. + Field list can be prepended with the type, trace, sw or hw, to indicate to which event type the field list applies. e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index a8bd00f2e557..3056b45b3dd6 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -33,6 +33,7 @@ enum perf_output_field { PERF_OUTPUT_IP = 1U << 7, PERF_OUTPUT_SYM = 1U << 8, PERF_OUTPUT_DSO = 1U << 9, + PERF_OUTPUT_ADDR = 1U << 10, }; struct output_option { @@ -49,6 +50,7 @@ struct output_option { {.str = "ip", .field = PERF_OUTPUT_IP}, {.str = "sym", .field = PERF_OUTPUT_SYM}, {.str = "dso", .field = PERF_OUTPUT_DSO}, + {.str = "addr", .field = PERF_OUTPUT_ADDR}, }; /* default set to maintain compatibility with current format */ @@ -173,14 +175,22 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, !(attr->sample_type & PERF_SAMPLE_CALLCHAIN)) symbol_conf.use_callchain = false; } - if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP)) { - pr_err("Display of symbols requested but IP is not selected.\n" - "No addresses to convert to symbols.\n"); + + if (PRINT_FIELD(ADDR) && + perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR", + PERF_OUTPUT_ADDR)) + return -EINVAL; + + if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { + pr_err("Display of symbols requested but neither sample IP nor " + "sample address\nis selected. Hence, no addresses to convert " + "to symbols.\n"); return -EINVAL; } - if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP)) { - pr_err("Display of DSO requested but IP is not selected.\n" - "No addresses to convert to dso.\n"); + if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) { + pr_err("Display of DSO requested but neither sample IP nor " + "sample address\nis selected. Hence, no addresses to convert " + "to DSO.\n"); return -EINVAL; } @@ -288,6 +298,63 @@ static void print_sample_start(struct perf_sample *sample, } } +static bool sample_addr_correlates_sym(struct perf_event_attr *attr) +{ + if ((attr->type == PERF_TYPE_SOFTWARE) && + ((attr->config == PERF_COUNT_SW_PAGE_FAULTS) || + (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN) || + (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ))) + return true; + + return false; +} + +static void print_sample_addr(union perf_event *event, + struct perf_sample *sample, + struct perf_session *session, + struct thread *thread, + struct perf_event_attr *attr) +{ + struct addr_location al; + u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + const char *symname, *dsoname; + + printf("%16" PRIx64, sample->addr); + + if (!sample_addr_correlates_sym(attr)) + return; + + thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, + event->ip.pid, sample->addr, &al); + if (!al.map) + thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE, + event->ip.pid, sample->addr, &al); + + al.cpu = sample->cpu; + al.sym = NULL; + + if (al.map) + al.sym = map__find_symbol(al.map, al.addr, NULL); + + if (PRINT_FIELD(SYM)) { + if (al.sym && al.sym->name) + symname = al.sym->name; + else + symname = ""; + + printf(" %16s", symname); + } + + if (PRINT_FIELD(DSO)) { + if (al.map && al.map->dso && al.map->dso->name) + dsoname = al.map->dso->name; + else + dsoname = ""; + + printf(" (%s)", dsoname); + } +} + static void process_event(union perf_event *event __unused, struct perf_sample *sample, struct perf_evsel *evsel, @@ -305,6 +372,9 @@ static void process_event(union perf_event *event __unused, print_trace_event(sample->cpu, sample->raw_data, sample->raw_size); + if (PRINT_FIELD(ADDR)) + print_sample_addr(event, sample, session, thread, attr); + if (PRINT_FIELD(IP)) { if (!symbol_conf.use_callchain) printf(" "); @@ -1003,7 +1073,7 @@ static const struct option options[] = { OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", "Look for files with symbols relative to this directory"), OPT_CALLBACK('f', "fields", NULL, "str", - "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso", + "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", parse_output_fields), OPT_END() 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, array++; } + data->addr = 0; if (type & PERF_SAMPLE_ADDR) { data->addr = *array; array++; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0dd418299261..b723f211881c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -708,9 +708,9 @@ static void dump_sample(struct perf_session *session, union perf_event *event, if (!dump_trace) return; - printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 "\n", + printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n", event->header.misc, sample->pid, sample->tid, sample->ip, - sample->period); + sample->period, sample->addr); if (session->sample_type & PERF_SAMPLE_CALLCHAIN) callchain__printf(sample); -- cgit v1.2.3 From d21cc9f67d689effbfd24bac878bc2c057de8c46 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 2 Jun 2011 10:39:43 -0300 Subject: perf evlist: Remove dependency on debug routines So far we avoided having to link debug.o in the python binding, keep it that way by not using ui__warning() in evlist.c. Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-4wtew8hd3g7ejnlehtspys2t@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 50aa34879c33..04c8a60075b3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -12,7 +12,6 @@ #include "evlist.h" #include "evsel.h" #include "util.h" -#include "debug.h" #include @@ -257,19 +256,15 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist) return evlist->mmap != NULL ? 0 : -ENOMEM; } -static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel, +static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, int prot, int mask, int fd) { evlist->mmap[idx].prev = 0; evlist->mmap[idx].mask = mask; evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot, MAP_SHARED, fd, 0); - if (evlist->mmap[idx].base == MAP_FAILED) { - if (evlist->cpus->map[idx] == -1 && evsel->attr.inherit) - ui__warning("Inherit is not allowed on per-task " - "events using mmap.\n"); + if (evlist->mmap[idx].base == MAP_FAILED) return -1; - } perf_evlist__add_pollfd(evlist, fd); return 0; @@ -289,7 +284,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int m if (output == -1) { output = fd; - if (__perf_evlist__mmap(evlist, evsel, cpu, + if (__perf_evlist__mmap(evlist, cpu, prot, mask, output) < 0) goto out_unmap; } else { @@ -329,7 +324,7 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in if (output == -1) { output = fd; - if (__perf_evlist__mmap(evlist, evsel, thread, + if (__perf_evlist__mmap(evlist, thread, prot, mask, output) < 0) goto out_unmap; } else { -- cgit v1.2.3 From 9c850d6c4b95bb07fb066eb7f43dd4e3b4842b85 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 2 Jun 2011 10:55:10 -0300 Subject: perf python: Use exception to propagate errors We were using pr_debug to tell the user about not being able to parse a sample where we should really use the python way of reporting errors: exceptions. Fixes this problem: [root@emilia ~]# python >>> import perf Traceback (most recent call last): File "", line 1, in ImportError: /home/acme/git/build/perf/python/perf.so: undefined symbol: eprintf >>> [root@emilia ~] As we want to keep the objects linked in the python binding (and in the future in a shared library) minimal. Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-m9dba9kaluas0kq8r58z191c@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 69436b3200a4..2dd1698e0932 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -694,14 +694,12 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, err = perf_event__parse_sample(event, first->attr.sample_type, perf_sample_size(first->attr.sample_type), sample_id_all, &pevent->sample); - if (err) { - pr_err("Can't parse sample, err = %d\n", err); - goto end; - } - + if (err) + return PyErr_Format(PyExc_OSError, + "perf: can't parse sample, err=%d", err); return pyevent; } -end: + Py_INCREF(Py_None); return Py_None; } -- cgit v1.2.3 From 56722381b8506733852c44dacf6d7bc5f90aedaf Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 2 Jun 2011 11:04:54 -0300 Subject: perf evlist: Don't die if sample_{id_all|type} is invalid Fixes two more cases where the python binding would not load: . Not finding die(), which it shouldn't anyway, not good to just stop the world because some particular perf.data file is invalid, just propagate the error to the caller. . Not finding perf_sample_size: fix it by moving it from event.c to evsel, where it belongs, as most cases are moving to operate on an evsel object.o One of the fixed problems: [root@emilia ~]# python >>> import perf Traceback (most recent call last): File "", line 1, in ImportError: /home/acme/git/build/perf/python/perf.so: undefined symbol: perf_sample_size >>> [root@emilia ~]# Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-1hkj7b2cvgbfnoizsekjb6c9@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-test.c | 2 +- tools/perf/util/event.c | 16 -------------- tools/perf/util/event.h | 2 -- tools/perf/util/evlist.c | 55 +++++++++++++++++++++++++++++------------------ tools/perf/util/evlist.h | 6 ++++-- tools/perf/util/evsel.c | 16 ++++++++++++++ tools/perf/util/evsel.h | 7 ++++++ tools/perf/util/python.c | 2 +- tools/perf/util/session.c | 12 ++++++++++- 9 files changed, 74 insertions(+), 44 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index b67186228c89..2da9162262b0 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -474,7 +474,7 @@ static int test__basic_mmap(void) unsigned int nr_events[nsyscalls], expected_nr_events[nsyscalls], i, j; struct perf_evsel *evsels[nsyscalls], *evsel; - int sample_size = perf_sample_size(attr.sample_type); + int sample_size = __perf_evsel__sample_size(attr.sample_type); for (i = 0; i < nsyscalls; ++i) { char name[64]; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 0fe9adf76379..3c1b8a632101 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -35,22 +35,6 @@ const char *perf_event__name(unsigned int id) return perf_event__names[id]; } -int perf_sample_size(u64 sample_type) -{ - u64 mask = sample_type & PERF_SAMPLE_MASK; - int size = 0; - int i; - - for (i = 0; i < 64; i++) { - if (mask & (1ULL << i)) - size++; - } - - size *= sizeof(u64); - - return size; -} - static struct perf_sample synth_sample = { .pid = -1, .tid = -1, diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index c08332871408..1d7f66488a88 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -82,8 +82,6 @@ struct perf_sample { struct ip_callchain *callchain; }; -int perf_sample_size(u64 sample_type); - #define BUILD_ID_SIZE 20 struct build_id_event { diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 04c8a60075b3..b021ea9265c3 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -455,33 +455,46 @@ int perf_evlist__set_filters(struct perf_evlist *evlist) return 0; } -u64 perf_evlist__sample_type(struct perf_evlist *evlist) +bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist) { - struct perf_evsel *pos; - u64 type = 0; - - list_for_each_entry(pos, &evlist->entries, node) { - if (!type) - type = pos->attr.sample_type; - else if (type != pos->attr.sample_type) - die("non matching sample_type"); + struct perf_evsel *pos, *first; + + pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); + + list_for_each_entry_continue(pos, &evlist->entries, node) { + if (first->attr.sample_type != pos->attr.sample_type) + return false; } - return type; + return true; } -bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) +u64 perf_evlist__sample_type(const struct perf_evlist *evlist) +{ + struct perf_evsel *first; + + first = list_entry(evlist->entries.next, struct perf_evsel, node); + return first->attr.sample_type; +} + +bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist) { - bool value = false, first = true; - struct perf_evsel *pos; - - list_for_each_entry(pos, &evlist->entries, node) { - if (first) { - value = pos->attr.sample_id_all; - first = false; - } else if (value != pos->attr.sample_id_all) - die("non matching sample_id_all"); + struct perf_evsel *pos, *first; + + pos = first = list_entry(evlist->entries.next, struct perf_evsel, node); + + list_for_each_entry_continue(pos, &evlist->entries, node) { + if (first->attr.sample_id_all != pos->attr.sample_id_all) + return false; } - return value; + return true; +} + +bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) +{ + struct perf_evsel *first; + + first = list_entry(evlist->entries.next, struct perf_evsel, node); + return first->attr.sample_id_all; } diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 0a1ef1f051f0..b2b862374f37 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -66,7 +66,9 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, void perf_evlist__delete_maps(struct perf_evlist *evlist); int perf_evlist__set_filters(struct perf_evlist *evlist); -u64 perf_evlist__sample_type(struct perf_evlist *evlist); -bool perf_evlist__sample_id_all(const struct perf_evlist *evlist); +u64 perf_evlist__sample_type(const struct perf_evlist *evlist); +bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); +bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); +bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); #endif /* __PERF_EVLIST_H */ diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index cca29ededb5b..0239eb87b232 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -15,6 +15,22 @@ #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) +int __perf_evsel__sample_size(u64 sample_type) +{ + u64 mask = sample_type & PERF_SAMPLE_MASK; + int size = 0; + int i; + + for (i = 0; i < 64; i++) { + if (mask & (1ULL << i)) + size++; + } + + size *= sizeof(u64); + + return size; +} + void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, int idx) { diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index f79bb2c09a6c..7e9366e4490b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -149,4 +149,11 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel, return __perf_evsel__read(evsel, ncpus, nthreads, true); } +int __perf_evsel__sample_size(u64 sample_type); + +static inline int perf_evsel__sample_size(struct perf_evsel *evsel) +{ + return __perf_evsel__sample_size(evsel->attr.sample_type); +} + #endif /* __PERF_EVSEL_H */ diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 2dd1698e0932..24063b4d41e0 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -692,7 +692,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, first = list_entry(evlist->entries.next, struct perf_evsel, node); err = perf_event__parse_sample(event, first->attr.sample_type, - perf_sample_size(first->attr.sample_type), + perf_evsel__sample_size(first), sample_id_all, &pevent->sample); if (err) return PyErr_Format(PyExc_OSError, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 64500fc78799..f5a8fbdd3f76 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -58,6 +58,16 @@ static int perf_session__open(struct perf_session *self, bool force) goto out_close; } + if (!perf_evlist__valid_sample_type(self->evlist)) { + pr_err("non matching sample_type"); + goto out_close; + } + + if (!perf_evlist__valid_sample_id_all(self->evlist)) { + pr_err("non matching sample_id_all"); + goto out_close; + } + self->size = input_stat.st_size; return 0; @@ -97,7 +107,7 @@ out: void perf_session__update_sample_type(struct perf_session *self) { self->sample_type = perf_evlist__sample_type(self->evlist); - self->sample_size = perf_sample_size(self->sample_type); + self->sample_size = __perf_evsel__sample_size(self->sample_type); self->sample_id_all = perf_evlist__sample_id_all(self->evlist); perf_session__id_header_size(self); } -- cgit v1.2.3 From b273fa9716aa1564bee88ceee62f9042981cdc81 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 31 Mar 2011 18:27:42 +0200 Subject: perf python: Fix argument name list of read_on_cpu() Mandatory arguments need to be present in the argument name list, as well as optional arguments, otherwise python barfs: # ./python/twatch.py Traceback (most recent call last): File "./python/twatch.py", line 41, in main() File "./python/twatch.py", line 32, in main event = evlist.read_on_cpu(cpu) RuntimeError: more argument specifiers than keyword list entries Hence, add cpu to the name list. Cc: David Ahern Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Tom Zanussi Link: http://lkml.kernel.org/r/1301588863-20210-1-git-send-email-fweisbec@gmail.com Signed-off-by: Frederic Weisbecker Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 24063b4d41e0..a9ac0504aabd 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -674,7 +674,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, struct perf_evlist *evlist = &pevlist->evlist; union perf_event *event; int sample_id_all = 1, cpu; - static char *kwlist[] = {"sample_id_all", NULL, NULL}; + static char *kwlist[] = {"cpu", "sample_id_all", NULL, NULL}; int err; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, -- cgit v1.2.3 From 5d61b9fd19d9f3cf653dbba615876e7792eea5ea Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Mon, 30 May 2011 14:12:09 +0200 Subject: perf: Use make kernelversion instead of parsing the Makefile Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Signed-off-by: Michal Marek --- tools/perf/util/PERF-VERSION-GEN | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN index 26d4d3fd6deb..9c5fb4d93824 100755 --- a/tools/perf/util/PERF-VERSION-GEN +++ b/tools/perf/util/PERF-VERSION-GEN @@ -23,12 +23,7 @@ if test -d ../../.git -o -f ../../.git && then VN=$(echo "$VN" | sed -e 's/-/./g'); else - eval $(grep '^VERSION[[:space:]]*=' ../../Makefile|tr -d ' ') - eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ') - eval $(grep '^SUBLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ') - eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../Makefile|tr -d ' ') - - VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}" + VN=$(make -sC ../.. kernelversion) fi VN=$(expr "$VN" : v*'\(.*\)') -- cgit v1.2.3 From cd4f1d536c2b2221d5a80399698d39717bf40077 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 13 Jun 2011 10:26:27 -0400 Subject: ktest: Notify reason to break out of monitoring boot Different timeouts can cause the ktest monitor to break out of the loop. It becomes annoying that one does not know the reason why it exited the monitor loop. Display the cause of the reason why the loop was exited. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index cef28e6632b9..b96d3819c42e 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -841,12 +841,20 @@ sub monitor { if ($booted) { $line = wait_for_input($monitor_fp, $booted_timeout); + if (!defined($line)) { + my $s = $booted_timeout == 1 ? "" : "s"; + doprint "Successful boot found: break after $booted_timeout second$s\n"; + last; + } } else { $line = wait_for_input($monitor_fp); + if (!defined($line)) { + my $s = $timeout == 1 ? "" : "s"; + doprint "Timed out after $timeout second$s\n"; + last; + } } - last if (!defined($line)); - doprint $line; print DMESG $line; -- cgit v1.2.3 From f1a5b96219e3483ab519bed9bb04cc8fadf74816 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 13 Jun 2011 10:30:00 -0400 Subject: ktest: Add detection of triple faults When a triple fault happens in a test, no call trace nor panic is displayed. Instead, the system reboots to the good kernel. Since the good kernel may display a boot prompt that matches the success string, ktest may think that the test succeeded, when it did not. Detecting triple faults is tricky because it is hard to generalize what a reboot looks like. The best that we can come up with for now is to examine the Linux banner. If we detect that the Linux banner matches the test we want to test, then look to see if we hit another Linux banner with a different kernel is booted. This can be assumed to be a triple fault. We can't just check for two Linux banners because things like early printk may cause the Linux banner to be displayed twice. Checking for different kernel versions should be the safe bet. If this for some reason detects a false triple boot. A new ktest config option is also created: DETECT_TRIPLE_FAULT This can be set to 0 to disable this checking. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 20 ++++++++++++++++++++ tools/testing/ktest/sample.conf | 10 ++++++++++ 2 files changed, 30 insertions(+) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index b96d3819c42e..a8e1826e0cba 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -41,6 +41,7 @@ $default{"CLEAR_LOG"} = 0; $default{"BISECT_MANUAL"} = 0; $default{"BISECT_SKIP"} = 1; $default{"SUCCESS_LINE"} = "login:"; +$default{"DETECT_TRIPLE_FAULT"} = 1; $default{"BOOTED_TIMEOUT"} = 1; $default{"DIE_ON_FAILURE"} = 1; $default{"SSH_EXEC"} = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND"; @@ -101,6 +102,7 @@ my $patchcheck_sleep_time; my $store_failures; my $timeout; my $booted_timeout; +my $detect_triplefault; my $console; my $success_line; my $stop_after_success; @@ -836,6 +838,7 @@ sub monitor { my $failure_start; my $monitor_start = time; my $done = 0; + my $version_found = 0; while (!$done) { @@ -904,6 +907,22 @@ sub monitor { $bug = 1; } + # Detect triple faults by testing the banner + if ($full_line =~ /\bLinux version (\S+).*\n/) { + if ($1 eq $version) { + $version_found = 1; + } elsif ($version_found && $detect_triplefault) { + # We already booted into the kernel we are testing, + # but now we booted into another kernel? + # Consider this a triple fault. + doprint "Aleady booted in Linux kernel $version, but now\n"; + doprint "we booted into Linux kernel $1.\n"; + doprint "Assuming that this is a triple fault.\n"; + doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n"; + last; + } + } + if ($line =~ /\n/) { $full_line = ""; } @@ -2159,6 +2178,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $timeout = set_test_option("TIMEOUT", $i); $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); $console = set_test_option("CONSOLE", $i); + $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i); $success_line = set_test_option("SUCCESS_LINE", $i); $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i); $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i); diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 48cbcc80602a..c2c072e96032 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -518,6 +518,16 @@ # The variables SSH_USER and MACHINE are defined. #REBOOT = ssh $SSH_USER@$MACHINE reboot +# The way triple faults are detected is by testing the kernel +# banner. If the kernel banner for the kernel we are testing is +# found, and then later a kernel banner for another kernel version +# is found, it is considered that we encountered a triple fault, +# and there is no panic or callback, but simply a reboot. +# To disable this (because it did a false positive) set the following +# to 0. +# (default 1) +#DETECT_TRIPLE_FAULT = 0 + #### Per test run options #### # The following options are only allowed in TEST_START sections. # They are ignored in the DEFAULTS sections. -- cgit v1.2.3 From 30f75da5ff475f1f455c0b009f3c06767963c54f Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 13 Jun 2011 10:35:35 -0400 Subject: ktest: Add CONFIG_BISECT_GOOD option Currently the config_bisect compares the min config with the CONFIG_BISECT config. There may be another config that we know is good that we want to ignore configs on. By passing in this config it will ignore the options that are set in the good config. Note: This only ignores the config, it does not (yet) handle options that are different between the two configs. If the good config has "SLAB" set and the bad config has "SLUB" it will not find the bug if the bug had to do with changing these two options. This is something that I intend to implement in the future. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 6 ++++++ tools/testing/ktest/sample.conf | 19 ++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index a8e1826e0cba..dbc02de93e59 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -88,6 +88,7 @@ my $bisect_bad = ""; my $reverse_bisect; my $bisect_manual; my $bisect_skip; +my $config_bisect_good; my $in_patchcheck = 0; my $run_test; my $redirect; @@ -1745,6 +1746,10 @@ sub config_bisect { my $tmpconfig = "$tmpdir/use_config"; + if (defined($config_bisect_good)) { + process_config_ignore $config_bisect_good; + } + # Make the file with the bad config and the min config if (defined($minconfig)) { # read the min config for things to ignore @@ -2174,6 +2179,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i); $bisect_manual = set_test_option("BISECT_MANUAL", $i); $bisect_skip = set_test_option("BISECT_SKIP", $i); + $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i); $store_failures = set_test_option("STORE_FAILURES", $i); $timeout = set_test_option("TIMEOUT", $i); $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index c2c072e96032..be531c20643d 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -749,13 +749,18 @@ # boot - bad builds but fails to boot # test - bad boots but fails a test # -# CONFIG_BISECT is the config that failed to boot -# -# If BISECT_MANUAL is set, it will pause between iterations. -# This is useful to use just ktest.pl just for the config bisect. -# If you set it to build, it will run the bisect and you can -# control what happens in between iterations. It will ask you if -# the test succeeded or not and continue the config bisect. +# CONFIG_BISECT is the config that failed to boot +# +# If BISECT_MANUAL is set, it will pause between iterations. +# This is useful to use just ktest.pl just for the config bisect. +# If you set it to build, it will run the bisect and you can +# control what happens in between iterations. It will ask you if +# the test succeeded or not and continue the config bisect. +# +# CONFIG_BISECT_GOOD (optional) +# If you have a good config to start with, then you +# can specify it with CONFIG_BISECT_GOOD. Otherwise +# the MIN_CONFIG is the base. # # Example: # TEST_START -- cgit v1.2.3 From 9064af5206c26ce0d47621fef216b0c43d65d693 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 13 Jun 2011 10:38:48 -0400 Subject: ktest: Add TEST_NAME option Searching through several tests, it gets confusing which test result is for which test. By adding the TEST_NAME option, the user can tell which test result belongs to which test. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 18 ++++++++++++++++-- tools/testing/ktest/sample.conf | 6 ++++++ 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index dbc02de93e59..579569f57b06 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -101,6 +101,7 @@ my $sleep_time; my $bisect_sleep_time; my $patchcheck_sleep_time; my $store_failures; +my $test_name; my $timeout; my $booted_timeout; my $detect_triplefault; @@ -620,9 +621,15 @@ sub fail { end_monitor; } + my $name = ""; + + if (defined($test_name)) { + $name = " ($test_name)"; + } + doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; - doprint "KTEST RESULT: TEST $i Failed: ", @_, "\n"; + doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n"; doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"; @@ -1130,9 +1137,15 @@ sub success { $successes++; + my $name = ""; + + if (defined($test_name)) { + $name = " ($test_name)"; + } + doprint "\n\n*******************************************\n"; doprint "*******************************************\n"; - doprint "KTEST RESULT: TEST $i SUCCESS!!!! **\n"; + doprint "KTEST RESULT: TEST $i$name SUCCESS!!!! **\n"; doprint "*******************************************\n"; doprint "*******************************************\n"; @@ -2181,6 +2194,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $bisect_skip = set_test_option("BISECT_SKIP", $i); $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i); $store_failures = set_test_option("STORE_FAILURES", $i); + $test_name = set_test_option("TEST_NAME", $i); $timeout = set_test_option("TIMEOUT", $i); $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i); $console = set_test_option("CONSOLE", $i); diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index be531c20643d..0e5f764ac9ee 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -545,6 +545,12 @@ # all preceding tests until a new CHECKOUT is set. # # +# TEST_NAME = name +# +# If you want the test to have a name that is displayed in +# the test result banner at the end of the test, then use this +# option. This is useful to search for the RESULT keyword and +# not have to translate a test number to a test in the config. # # For TEST_TYPE = patchcheck # -- cgit v1.2.3 From fcb3f16a4f4bf4e667ae4c68b1d5401824058efb Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 13 Jun 2011 10:40:58 -0400 Subject: ktest: Implement our own force min config Using the build KCONFIG_ALLCONFIG environment variable to force the min config may not always work properly. Since ktest is written in perl, it is trivial to read and replace the current config with the configs specified by the min config. Now the min config (and add configs) are read by perl and before a make is done, these configs in the .config file are replaced by the version in the min config. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 74 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 13 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 579569f57b06..aa442a9075db 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -119,6 +119,7 @@ my $successes = 0; my %entered_configs; my %config_help; my %variable; +my %force_config; $config_help{"MACHINE"} = << "EOF" The machine hostname that you will test. @@ -1044,21 +1045,69 @@ sub check_buildlog { return 1; } +sub apply_min_config { + my $outconfig = "$output_config.new"; + + # Read the config file and remove anything that + # is in the force_config hash (from minconfig and others) + # then add the force config back. + + doprint "Applying minimum configurations into $output_config.new\n"; + + open (OUT, ">$outconfig") or + dodie "Can't create $outconfig"; + + if (-f $output_config) { + open (IN, $output_config) or + dodie "Failed to open $output_config"; + while () { + if (/^(# )?(CONFIG_[^\s=]*)/) { + next if (defined($force_config{$2})); + } + print OUT; + } + close IN; + } + foreach my $config (keys %force_config) { + print OUT "$force_config{$config}\n"; + } + close OUT; + + run_command "mv $outconfig $output_config"; +} + sub make_oldconfig { - my ($defconfig) = @_; - if (!run_command "$defconfig $make oldnoconfig") { + apply_min_config; + + if (!run_command "$make oldnoconfig") { # Perhaps oldnoconfig doesn't exist in this version of the kernel # try a yes '' | oldconfig doprint "oldnoconfig failed, trying yes '' | make oldconfig\n"; - run_command "yes '' | $defconfig $make oldconfig" or + run_command "yes '' | $make oldconfig" or dodie "failed make config oldconfig"; } } +# read a config file and use this to force new configs. +sub load_force_config { + my ($config) = @_; + + open(IN, $config) or + dodie "failed to read $config"; + while () { + chomp; + if (/^(CONFIG[^\s=]*)(\s*=.*)/) { + $force_config{$1} = $_; + } elsif (/^# (CONFIG_\S*) is not set/) { + $force_config{$1} = $_; + } + } + close IN; +} + sub build { my ($type) = @_; - my $defconfig = ""; unlink $buildlog; @@ -1098,15 +1147,15 @@ sub build { close(OUT); if (defined($minconfig)) { - $defconfig = "KCONFIG_ALLCONFIG=$minconfig"; + load_force_config($minconfig); } - if ($type eq "oldnoconfig") { - make_oldconfig $defconfig; - } else { - run_command "$defconfig $make $type" or + if ($type ne "oldnoconfig") { + run_command "$make $type" or dodie "failed make config"; } + # Run old config regardless, to enforce min configurations + make_oldconfig; $redirect = "$buildlog"; if (!run_command "$make $build_options") { @@ -1587,7 +1636,7 @@ sub create_config { close(OUT); # exit; - make_oldconfig ""; + make_oldconfig; } sub compare_configs { @@ -1778,9 +1827,8 @@ sub config_bisect { dodie "failed to append $addconfig"; } - my $defconfig = ""; if (-f $tmpconfig) { - $defconfig = "KCONFIG_ALLCONFIG=$tmpconfig"; + load_force_config($tmpconfig); process_config_ignore $tmpconfig; } @@ -1801,7 +1849,7 @@ sub config_bisect { close(IN); # Now run oldconfig with the minconfig (and addconfigs) - make_oldconfig $defconfig; + make_oldconfig; # check to see what we lost (or gained) open (IN, $output_config) -- cgit v1.2.3 From ecaf8e521324d5a7f85976bb8689e248b8d3a2f6 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 13 Jun 2011 10:48:10 -0400 Subject: ktest: Have wait on stdio honor bug timeout After a bug is found, the STOP_AFTER_FAILURE timeout is used to determine how much output should be printed before breaking out of the monitor loop. This is to get things like call traces and enough infromation about the bug to help determine what caused it. The STOP_AFTER_FAILURE is usually much shorter than the TIMEOUT that is used to determine when to quit after no more stdio is given. But since the stdio read uses a wait on I/O, the STOP_AFTER_FAILURE is only checked after we get something from I/O. But if the I/O does not return any more data, we wait the TIMEOUT period instead, even though we already triggered a bug report. The wait on I/O should honor the STOP_AFTER_FAILURE time if a bug has been found. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index aa442a9075db..1e1fe835df48 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -851,7 +851,16 @@ sub monitor { while (!$done) { - if ($booted) { + if ($bug && defined($stop_after_failure) && + $stop_after_failure >= 0) { + my $time = $stop_after_failure - (time - $failure_start); + $line = wait_for_input($monitor_fp, $time); + if (!defined($line)) { + doprint "bug timed out after $booted_timeout seconds\n"; + doprint "Test forced to stop after $stop_after_failure seconds after failure\n"; + last; + } + } elsif ($booted) { $line = wait_for_input($monitor_fp, $booted_timeout); if (!defined($line)) { my $s = $booted_timeout == 1 ? "" : "s"; -- cgit v1.2.3 From 23715c3c9a31dd34c8c2f27086a9562e35da423b Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 13 Jun 2011 11:03:34 -0400 Subject: ktest: Have LOG_FILE evaluate options as well The LOG_FILE variable needs to evaluate the $ options as well. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 126 +++++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 58 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 1e1fe835df48..83dcfaf0cac4 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -478,6 +478,69 @@ sub read_config { } } +sub __eval_option { + my ($option, $i) = @_; + + # Add space to evaluate the character before $ + $option = " $option"; + my $retval = ""; + + while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { + my $start = $1; + my $var = $2; + my $end = $3; + + # Append beginning of line + $retval = "$retval$start"; + + # If the iteration option OPT[$i] exists, then use that. + # otherwise see if the default OPT (without [$i]) exists. + + my $o = "$var\[$i\]"; + + if (defined($opt{$o})) { + $o = $opt{$o}; + $retval = "$retval$o"; + } elsif (defined($opt{$var})) { + $o = $opt{$var}; + $retval = "$retval$o"; + } else { + $retval = "$retval\$\{$var\}"; + } + + $option = $end; + } + + $retval = "$retval$option"; + + $retval =~ s/^ //; + + return $retval; +} + +sub eval_option { + my ($option, $i) = @_; + + my $prev = ""; + + # Since an option can evaluate to another option, + # keep iterating until we do not evaluate any more + # options. + my $r = 0; + while ($prev ne $option) { + # Check for recursive evaluations. + # 100 deep should be more than enough. + if ($r++ > 100) { + die "Over 100 evaluations accurred with $option\n" . + "Check for recursive variables\n"; + } + $prev = $option; + $option = __eval_option($option, $i); + } + + return $option; +} + sub _logit { if (defined($opt{"LOG_FILE"})) { open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; @@ -2079,6 +2142,10 @@ EOF } read_config $ktest_config; +if (defined($opt{"LOG_FILE"})) { + $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1); +} + # Append any configs entered in manually to the config file. my @new_configs = keys %entered_configs; if ($#new_configs >= 0) { @@ -2147,70 +2214,13 @@ sub __set_test_option { return undef; } -sub eval_option { - my ($option, $i) = @_; - - # Add space to evaluate the character before $ - $option = " $option"; - my $retval = ""; - - while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) { - my $start = $1; - my $var = $2; - my $end = $3; - - # Append beginning of line - $retval = "$retval$start"; - - # If the iteration option OPT[$i] exists, then use that. - # otherwise see if the default OPT (without [$i]) exists. - - my $o = "$var\[$i\]"; - - if (defined($opt{$o})) { - $o = $opt{$o}; - $retval = "$retval$o"; - } elsif (defined($opt{$var})) { - $o = $opt{$var}; - $retval = "$retval$o"; - } else { - $retval = "$retval\$\{$var\}"; - } - - $option = $end; - } - - $retval = "$retval$option"; - - $retval =~ s/^ //; - - return $retval; -} - sub set_test_option { my ($name, $i) = @_; my $option = __set_test_option($name, $i); return $option if (!defined($option)); - my $prev = ""; - - # Since an option can evaluate to another option, - # keep iterating until we do not evaluate any more - # options. - my $r = 0; - while ($prev ne $option) { - # Check for recursive evaluations. - # 100 deep should be more than enough. - if ($r++ > 100) { - die "Over 100 evaluations accurred with $name\n" . - "Check for recursive variables\n"; - } - $prev = $option; - $option = eval_option($option, $i); - } - - return $option; + return eval_option($option, $i); } # First we need to do is the builds -- cgit v1.2.3 From db05cfefce6e6120267974345599760b1d653439 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 13 Jun 2011 11:09:22 -0400 Subject: ktest: Allow initrd processing without modules defined When a config is set with CONFIG_MODULES=n, it does not mean that the kernel does not need an initrd to boot. For systems that depend on LVM and such, an initrd must run first. If POST_INSTALL is defined, then run the post install regardless if modules are needed or not. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 83dcfaf0cac4..fb46e12eb1d7 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1031,6 +1031,16 @@ sub monitor { return 1; } +sub do_post_install { + + return if (!defined($post_install)); + + my $cp_post_install = $post_install; + $cp_post_install =~ s/\$KERNEL_VERSION/$version/g; + run_command "$cp_post_install" or + dodie "Failed to run post install"; +} + sub install { run_scp "$outputdir/$build_target", "$target_image" or @@ -1050,6 +1060,7 @@ sub install { close(IN); if (!$install_mods) { + do_post_install; doprint "No modules needed\n"; return; } @@ -1077,12 +1088,7 @@ sub install { run_ssh "rm -f /tmp/$modtar"; - return if (!defined($post_install)); - - my $cp_post_install = $post_install; - $cp_post_install =~ s/\$KERNEL_VERSION/$version/g; - run_command "$cp_post_install" or - dodie "Failed to run post install"; + do_post_install; } sub check_buildlog { -- cgit v1.2.3 From 09223371deac67d08ca0b70bd18787920284c967 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 14 Jun 2011 13:26:25 +0800 Subject: rcu: Use softirq to address performance regression Commit a26ac2455ffcf3(rcu: move TREE_RCU from softirq to kthread) introduced performance regression. In an AIM7 test, this commit degraded performance by about 40%. The commit runs rcu callbacks in a kthread instead of softirq. We observed high rate of context switch which is caused by this. Out test system has 64 CPUs and HZ is 1000, so we saw more than 64k context switch per second which is caused by RCU's per-CPU kthread. A trace showed that most of the time the RCU per-CPU kthread doesn't actually handle any callbacks, but instead just does a very small amount of work handling grace periods. This means that RCU's per-CPU kthreads are making the scheduler do quite a bit of work in order to allow a very small amount of RCU-related processing to be done. Alex Shi's analysis determined that this slowdown is due to lock contention within the scheduler. Unfortunately, as Peter Zijlstra points out, the scheduler's real-time semantics require global action, which means that this contention is inherent in real-time scheduling. (Yes, perhaps someone will come up with a workaround -- otherwise, -rt is not going to do well on large SMP systems -- but this patch will work around this issue in the meantime. And "the meantime" might well be forever.) This patch therefore re-introduces softirq processing to RCU, but only for core RCU work. RCU callbacks are still executed in kthread context, so that only a small amount of RCU work runs in softirq context in the common case. This should minimize ksoftirqd execution, allowing us to skip boosting of ksoftirqd for CONFIG_RCU_BOOST=y kernels. Signed-off-by: Shaohua Li Tested-by: "Alex,Shi" Signed-off-by: Paul E. McKenney --- tools/perf/util/trace-event-parse.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools') diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 1e88485c16a0..0a7ed5b5e281 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -2187,6 +2187,7 @@ static const struct flag flags[] = { { "TASKLET_SOFTIRQ", 6 }, { "SCHED_SOFTIRQ", 7 }, { "HRTIMER_SOFTIRQ", 8 }, + { "RCU_SOFTIRQ", 9 }, { "HRTIMER_NORESTART", 0 }, { "HRTIMER_RESTART", 1 }, -- cgit v1.2.3 From 0bd6c1a38f57127eeb9444ed74cf5b65f36f563c Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 14 Jun 2011 20:39:31 -0400 Subject: ktest: Add POST/PRE_BUILD options There are some cases that a patch may be needed to apply to the kernel in patchcheck or bisect tests. Adding a PRE_BUILD option to apply the patch and POST_BUILD to remove it, allows for this to be done easily. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 31 ++++++++++++++++++++++++++++--- tools/testing/ktest/sample.conf | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index fb46e12eb1d7..d0e1de6e4d1f 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -63,6 +63,10 @@ my $output_config; my $test_type; my $build_type; my $build_options; +my $pre_build; +my $post_build; +my $pre_build_die; +my $post_build_die; my $reboot_type; my $reboot_script; my $power_cycle; @@ -1189,6 +1193,14 @@ sub build { unlink $buildlog; + if (defined($pre_build)) { + my $ret = run_command $pre_build; + if (!$ret && defined($pre_build_die) && + $pre_build_die) { + dodie "failed to pre_build\n"; + } + } + if ($type =~ /^useconfig:(.*)/) { run_command "cp $1 $output_config" or dodie "could not copy $1 to .config"; @@ -1236,13 +1248,22 @@ sub build { make_oldconfig; $redirect = "$buildlog"; - if (!run_command "$make $build_options") { - undef $redirect; + my $build_ret = run_command "$make $build_options"; + undef $redirect; + + if (defined($post_build)) { + my $ret = run_command $post_build; + if (!$ret && defined($post_build_die) && + $post_build_die) { + dodie "failed to post_build\n"; + } + } + + if (!$build_ret) { # bisect may need this to pass return 0 if ($in_bisect); fail "failed build" and return 0; } - undef $redirect; return 1; } @@ -2244,6 +2265,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $test_type = set_test_option("TEST_TYPE", $i); $build_type = set_test_option("BUILD_TYPE", $i); $build_options = set_test_option("BUILD_OPTIONS", $i); + $pre_build = set_test_option("PRE_BUILD", $i); + $post_build = set_test_option("POST_BUILD", $i); + $pre_build_die = set_test_option("PRE_BUILD_DIE", $i); + $post_build_die = set_test_option("POST_BUILD_DIE", $i); $power_cycle = set_test_option("POWER_CYCLE", $i); $reboot = set_test_option("REBOOT", $i); $noclean = set_test_option("BUILD_NOCLEAN", $i); diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 0e5f764ac9ee..1092e4759c1e 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -293,6 +293,38 @@ # or on some systems: #POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION +# If there is a script that you require to run before the build is done +# you can specify it with PRE_BUILD. +# +# One example may be if you must add a temporary patch to the build to +# fix a unrelated bug to perform a patchcheck test. This will apply the +# patch before each build that is made. Use the POST_BUILD to do a git reset --hard +# to remove the patch. +# +# (default undef) +#PRE_BUILD = cd ${BUILD_DIR} && patch -p1 < /tmp/temp.patch + +# To specify if the test should fail if the PRE_BUILD fails, +# PRE_BUILD_DIE needs to be set to 1. Otherwise the PRE_BUILD +# result is ignored. +# (default 0) +# PRE_BUILD_DIE = 1 + +# If there is a script that should run after the build is done +# you can specify it with POST_BUILD. +# +# As the example in PRE_BUILD, POST_BUILD can be used to reset modifications +# made by the PRE_BUILD. +# +# (default undef) +#POST_BUILD = cd ${BUILD_DIR} && git reset --hard + +# To specify if the test should fail if the POST_BUILD fails, +# POST_BUILD_DIE needs to be set to 1. Otherwise the POST_BUILD +# result is ignored. +# (default 0) +#POST_BUILD_DIE = 1 + # Way to reboot the box to the test kernel. # Only valid options so far are "grub" and "script" # (default grub) -- cgit v1.2.3 From 4892063043282229c1296d86a2f86989ef30a97c Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 14 Jun 2011 20:42:19 -0400 Subject: ktest: Have the testing tmp dir include machine name As multiple tests may be executed by the same server, have the test machine name add uniqueness to the value of the temp directory. Otherwise the temp directories may overwrite each other's tests. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 2 +- tools/testing/ktest/sample.conf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index d0e1de6e4d1f..24286cea14af 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -27,7 +27,7 @@ $default{"TEST_TYPE"} = "test"; $default{"BUILD_TYPE"} = "randconfig"; $default{"MAKE_CMD"} = "make"; $default{"TIMEOUT"} = 120; -$default{"TMP_DIR"} = "/tmp/ktest"; +$default{"TMP_DIR"} = "/tmp/ktest/\${MACHINE}"; $default{"SLEEP_TIME"} = 60; # sleep time between tests $default{"BUILD_NOCLEAN"} = 0; $default{"REBOOT_ON_ERROR"} = 0; diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 1092e4759c1e..e2d8d8338e9a 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -392,8 +392,8 @@ #ADD_CONFIG = /home/test/config-broken # The location on the host where to write temp files -# (default /tmp/ktest) -#TMP_DIR = /tmp/ktest +# (default /tmp/ktest/${MACHINE}) +#TMP_DIR = /tmp/ktest/${MACHINE} # Optional log file to write the status (recommended) # Note, this is a DEFAULT section only option. -- cgit v1.2.3 From e7b13441895fd0f95c34a004eed364524cca71cb Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 14 Jun 2011 20:44:36 -0400 Subject: ktest: Fix tar extracting of modules to target The tar command to create the module directory is cjf, but the extraction only had xf. This works on most versions of tar, but some versions of tar require xjf for extraction as well. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 24286cea14af..5b35fa04429b 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1087,7 +1087,7 @@ sub install { unlink "$tmpdir/$modtar"; - run_ssh "'(cd / && tar xf /tmp/$modtar)'" or + run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or dodie "failed to tar modules"; run_ssh "rm -f /tmp/$modtar"; -- cgit v1.2.3 From 1990207d538885e678f374e3e79f454c2e6c7383 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 14 Jun 2011 20:46:25 -0400 Subject: ktest: Add IGNORE_WARNINGS to ignore warnings in some patches Doing a patchcheck test, there may be warnings that gcc produces which may be OK, and the test should not fail on that commit. By adding a IGNORE_WARNINGS option to list a space delimited SHA1s that are ignored lets the user avoid having the test fail on certain commits. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 14 +++++++++++++- tools/testing/ktest/sample.conf | 8 +++++++- 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 5b35fa04429b..5924f14ba418 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -104,6 +104,7 @@ my $monitor_cnt = 0; my $sleep_time; my $bisect_sleep_time; my $patchcheck_sleep_time; +my $ignore_warnings; my $store_failures; my $test_name; my $timeout; @@ -2074,6 +2075,13 @@ sub patchcheck { @list = reverse @list; my $save_clean = $noclean; + my %ignored_warnings; + + if (defined($ignore_warnings)) { + foreach my $sha1 (split /\s+/, $ignore_warnings) { + $ignored_warnings{$sha1} = 1; + } + } $in_patchcheck = 1; foreach my $item (@list) { @@ -2100,7 +2108,10 @@ sub patchcheck { build "oldconfig" or return 0; } - check_buildlog $sha1 or return 0; + + if (!defined($ignored_warnings{$sha1})) { + check_buildlog $sha1 or return 0; + } next if ($type eq "build"); @@ -2288,6 +2299,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $sleep_time = set_test_option("SLEEP_TIME", $i); $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i); $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i); + $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i); $bisect_manual = set_test_option("BISECT_MANUAL", $i); $bisect_skip = set_test_option("BISECT_SKIP", $i); $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i); diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index e2d8d8338e9a..82c966c32d61 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -604,7 +604,12 @@ # build, boot, test. # # Note, the build test will look for warnings, if a warning occurred -# in a file that a commit touches, the build will fail. +# in a file that a commit touches, the build will fail, unless +# IGNORE_WARNINGS is set for the given commit's sha1 +# +# IGNORE_WARNINGS can be used to disable the failure of patchcheck +# on a particuler commit (SHA1). You can add more than one commit +# by adding a list of SHA1s that are space delimited. # # If BUILD_NOCLEAN is set, then make mrproper will not be run on # any of the builds, just like all other TEST_TYPE tests. But @@ -619,6 +624,7 @@ # PATCHCHECK_TYPE = boot # PATCHCHECK_START = 747e94ae3d1b4c9bf5380e569f614eb9040b79e7 # PATCHCHECK_END = HEAD~2 +# IGNORE_WARNINGS = 42f9c6b69b54946ffc0515f57d01dc7f5c0e4712 0c17ca2c7187f431d8ffc79e81addc730f33d128 # # # -- cgit v1.2.3 From ddf607e5f853ae172e81e6051e1e12e24ea8a3c6 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 14 Jun 2011 20:49:13 -0400 Subject: ktest: Add helper function to avoid duplicate code Several places had the following code: get_grub_index; get_version; install; start_monitor; return monitor; Creating a function "start_monitor_and_boot()" replaces these mulitple uses with a single call. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 46 +++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 26 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 5924f14ba418..099ceeed4144 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1096,6 +1096,23 @@ sub install { do_post_install; } +sub get_version { + # get the release name + doprint "$make kernelrelease ... "; + $version = `$make kernelrelease | tail -1`; + chomp($version); + doprint "$version\n"; +} + +sub start_monitor_and_boot { + get_grub_index; + get_version; + install; + + start_monitor; + return monitor; +} + sub check_buildlog { my ($patch) = @_; @@ -1307,14 +1324,6 @@ sub success { } } -sub get_version { - # get the release name - doprint "$make kernelrelease ... "; - $version = `$make kernelrelease | tail -1`; - chomp($version); - doprint "$version\n"; -} - sub answer_bisect { for (;;) { doprint "Pass or fail? [p/f]"; @@ -1479,12 +1488,7 @@ sub run_bisect_test { dodie "Failed on build" if $failed; # Now boot the box - get_grub_index; - get_version; - install; - - start_monitor; - monitor or $failed = 1; + start_monitor_and_boot or $failed = 1; if ($type ne "boot") { if ($failed && $bisect_skip) { @@ -2115,14 +2119,9 @@ sub patchcheck { next if ($type eq "build"); - get_grub_index; - get_version; - install; - my $failed = 0; - start_monitor; - monitor or $failed = 1; + start_monitor_and_boot or $failed = 1; if (!$failed && $type ne "boot"){ do_run_test or $failed = 1; @@ -2393,13 +2392,8 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { } if ($test_type ne "build") { - get_grub_index; - get_version; - install; - my $failed = 0; - start_monitor; - monitor or $failed = 1;; + start_monitor_and_boot or $failed = 1; if (!$failed && $test_type ne "boot" && defined($run_test)) { do_run_test or $failed = 1; -- cgit v1.2.3 From 0df213ca31f43faf0b1d6c7108e190ff198b42d3 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 14 Jun 2011 20:51:37 -0400 Subject: ktest: Require one TEST_START in config file There has been too many times that I put in one too many SKIP TEST_STARTs and start the test with the default randconfig by accident that I added this to have ktest ask the user for which test they want to run if no TEST_START is specified. Now if I accidently start the test with all TEST_STARTs skipped, ktest asks what test do I want to run, and I now have a chance to kill it before it does a make mrproper on my build directory. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 099ceeed4144..6166f3a0f2ea 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -345,6 +345,7 @@ sub read_config { my $num_tests_set = 0; my $skip = 0; my $rest; + my $test_case = 0; while () { @@ -370,6 +371,7 @@ sub read_config { $rest = $1; $skip = 1; } else { + $test_case = 1; $skip = 0; } @@ -474,6 +476,15 @@ sub read_config { # make sure we have all mandatory configs get_ktest_configs; + # was a test specified? + if (!$test_case) { + print "No test case specified.\n"; + print "What test case would you like to run?\n"; + my $ans = ; + chomp $ans; + $default{"TEST_TYPE"} = $ans; + } + # set any defaults foreach my $default (keys %default) { -- cgit v1.2.3 From 37aa9a2eb4d9b1a4aec1fd18bb2bb6bca029de27 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Wed, 15 Jun 2011 14:35:00 +0100 Subject: perf: clear out make flags when calling kernel make kernelver When generating the perf version from the kernel version using 'make kernelver' it is necessary to clear out any MAKEFLAGS otherwise they may trigger additional output which pollute the contents. Signed-off-by: Andy Whitcroft Signed-off-by: Michal Marek --- tools/perf/util/PERF-VERSION-GEN | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN index 9c5fb4d93824..ad73300f7bac 100755 --- a/tools/perf/util/PERF-VERSION-GEN +++ b/tools/perf/util/PERF-VERSION-GEN @@ -23,7 +23,7 @@ if test -d ../../.git -o -f ../../.git && then VN=$(echo "$VN" | sed -e 's/-/./g'); else - VN=$(make -sC ../.. kernelversion) + VN=$(MAKEFLAGS= make -sC ../.. kernelversion) fi VN=$(expr "$VN" : v*'\(.*\)') -- cgit v1.2.3 From 203db2952bc87f5d610c9ad53a7d02b85897721f Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 15 Jun 2011 23:03:38 +0200 Subject: tools/perf: Fix static build of perf tool To build a statically linked version of the perf tool all needed libraries must be added in the correct order to get the symbols resolved. Currently this is broken when, e.g. python or newt support is enabled -- libpython needs libpthread which is an unconditional link dependency of the perf tool; libslang needs libm, another unconditional dependency. To solve the problem in the long run without the need to keep track of transitive library dependencies, simply make the linker look at the EXTLIBS multiple times until it has all symbols resolved. Signed-off-by: Mathias Krause Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/r/1308171818-20370-1-git-send-email-minipli@googlemail.com Signed-off-by: Ingo Molnar --- tools/perf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 032ba6398a5c..940257b5774e 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -633,7 +633,7 @@ prefix_SQ = $(subst ','\'',$(prefix)) SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) -LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive $(EXTLIBS) +LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group ALL_CFLAGS += $(BASIC_CFLAGS) ALL_CFLAGS += $(ARCH_CFLAGS) -- cgit v1.2.3 From d797fdc5c5c245fbb05f553e68cb95d962fbdd01 Mon Sep 17 00:00:00 2001 From: Sam Liao Date: Tue, 7 Jun 2011 23:49:46 +0800 Subject: perf tools: Add inverted call graph report support. Add "caller/callee" option to support inverted butterfly report, in the inverted report (with caller option), the call graph start from the callee's ancestor. Users can use such view to catch system's performance bottleneck from a sysprof like view. Using this option with specified sort order like pid gives us high level view of call graph statistics. Also add "-G" alias for inverted call graph. Signed-off-by: Sam Liao Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: David Ahern Signed-off-by: Frederic Weisbecker --- tools/perf/Documentation/perf-report.txt | 15 ++++++++++++--- tools/perf/builtin-report.c | 33 ++++++++++++++++++++++++++------ tools/perf/util/callchain.h | 6 ++++++ tools/perf/util/hist.c | 3 ++- tools/perf/util/session.c | 7 ++++++- 5 files changed, 53 insertions(+), 11 deletions(-) (limited to 'tools') diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 8ba03d6e5398..cfa8e513d0fb 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -80,15 +80,24 @@ OPTIONS --dump-raw-trace:: Dump raw trace in ASCII. --g [type,min]:: +-g [type,min,order]:: --call-graph:: - Display call chains using type and min percent threshold. + Display call chains using type, min percent threshold and order. type can be either: - flat: single column, linear exposure of call chains. - graph: use a graph tree, displaying absolute overhead rates. - fractal: like graph, but displays relative rates. Each branch of the tree is considered as a new profiled object. + - Default: fractal,0.5. + + order can be either: + - callee: callee based call graph. + - caller: inverted caller based call graph. + + Default: fractal,0.5,callee. + +-G:: +--inverted:: + alias for inverted caller based call graph. --pretty=:: Pretty printing style. key: normal, raw diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 287a173523a7..271e252dc651 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -45,7 +45,8 @@ static struct perf_read_values show_threads_values; static const char default_pretty_printing_style[] = "normal"; static const char *pretty_printing_style = default_pretty_printing_style; -static char callchain_default_opt[] = "fractal,0.5"; +static char callchain_default_opt[] = "fractal,0.5,callee"; +static bool inverted_callchain; static symbol_filter_t annotate_init; static int perf_session__add_hist_entry(struct perf_session *session, @@ -386,13 +387,29 @@ parse_callchain_opt(const struct option *opt __used, const char *arg, if (!tok) goto setup; - tok2 = strtok(NULL, ","); callchain_param.min_percent = strtod(tok, &endptr); if (tok == endptr) return -1; - if (tok2) + /* get the print limit */ + tok2 = strtok(NULL, ","); + if (!tok2) + goto setup; + + if (tok2[0] != 'c') { callchain_param.print_limit = strtod(tok2, &endptr); + tok2 = strtok(NULL, ","); + if (!tok2) + goto setup; + } + + /* get the call chain order */ + if (!strcmp(tok2, "caller")) + callchain_param.order = ORDER_CALLER; + else if (!strcmp(tok2, "callee")) + callchain_param.order = ORDER_CALLEE; + else + return -1; setup: if (callchain_register_param(&callchain_param) < 0) { fprintf(stderr, "Can't register callchain params\n"); @@ -436,9 +453,10 @@ static const struct option options[] = { "regex filter to identify parent, see: '--sort parent'"), OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, "Only display entries with parent-match"), - OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent", - "Display callchains using output_type (graph, flat, fractal, or none) and min percent threshold. " - "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt), + OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent, call_order", + "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. " + "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt), + OPT_BOOLEAN('G', "inverted", &inverted_callchain, "alias for inverted call graph"), OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", "only consider symbols in these dsos"), OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", @@ -467,6 +485,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) else if (use_tui) use_browser = 1; + if (inverted_callchain) + callchain_param.order = ORDER_CALLER; + if (strcmp(input_name, "-") != 0) setup_browser(true); else 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 { CHAIN_GRAPH_REL }; +enum chain_order { + ORDER_CALLER, + ORDER_CALLEE +}; + struct callchain_node { struct callchain_node *parent; struct list_head siblings; @@ -41,6 +46,7 @@ struct callchain_param { u32 print_limit; double min_percent; sort_chain_func_t sort; + enum chain_order order; }; struct callchain_list { diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 627a02e03c57..dae4202fa65a 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -14,7 +14,8 @@ enum hist_filter { struct callchain_param callchain_param = { .mode = CHAIN_GRAPH_REL, - .min_percent = 0.5 + .min_percent = 0.5, + .order = ORDER_CALLEE }; u16 hists__col_len(struct hists *self, enum hist_column col) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index b723f211881c..558bcf996949 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -247,9 +247,14 @@ int perf_session__resolve_callchain(struct perf_session *self, callchain_cursor_reset(&self->callchain_cursor); for (i = 0; i < chain->nr; i++) { - u64 ip = chain->ips[i]; + u64 ip; struct addr_location al; + if (callchain_param.order == ORDER_CALLEE) + ip = chain->ips[i]; + else + ip = chain->ips[chain->nr - i - 1]; + if (ip >= PERF_CONTEXT_MAX) { switch (ip) { case PERF_CONTEXT_HV: -- cgit v1.2.3 From 872a878fb1ee53e21c90040de2c01b3fc53b5942 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 29 Jun 2011 03:14:52 +0200 Subject: perf tools: Make sort operations static These don't need to be globally visible. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: David Ahern Cc: Sam Liao --- tools/perf/util/sort.c | 211 +++++++++++++++++++++++-------------------------- tools/perf/util/sort.h | 8 -- 2 files changed, 99 insertions(+), 120 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index f44fa541d56e..f5dba560d918 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -15,95 +15,6 @@ char * field_sep; LIST_HEAD(hist_entry__sort_list); -static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width); -static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width); -static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width); -static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width); -static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width); -static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf, - size_t size, unsigned int width); - -struct sort_entry sort_thread = { - .se_header = "Command: Pid", - .se_cmp = sort__thread_cmp, - .se_snprintf = hist_entry__thread_snprintf, - .se_width_idx = HISTC_THREAD, -}; - -struct sort_entry sort_comm = { - .se_header = "Command", - .se_cmp = sort__comm_cmp, - .se_collapse = sort__comm_collapse, - .se_snprintf = hist_entry__comm_snprintf, - .se_width_idx = HISTC_COMM, -}; - -struct sort_entry sort_dso = { - .se_header = "Shared Object", - .se_cmp = sort__dso_cmp, - .se_snprintf = hist_entry__dso_snprintf, - .se_width_idx = HISTC_DSO, -}; - -struct sort_entry sort_sym = { - .se_header = "Symbol", - .se_cmp = sort__sym_cmp, - .se_snprintf = hist_entry__sym_snprintf, - .se_width_idx = HISTC_SYMBOL, -}; - -struct sort_entry sort_parent = { - .se_header = "Parent symbol", - .se_cmp = sort__parent_cmp, - .se_snprintf = hist_entry__parent_snprintf, - .se_width_idx = HISTC_PARENT, -}; - -struct sort_entry sort_cpu = { - .se_header = "CPU", - .se_cmp = sort__cpu_cmp, - .se_snprintf = hist_entry__cpu_snprintf, - .se_width_idx = HISTC_CPU, -}; - -struct sort_dimension { - const char *name; - struct sort_entry *entry; - int taken; -}; - -static struct sort_dimension sort_dimensions[] = { - { .name = "pid", .entry = &sort_thread, }, - { .name = "comm", .entry = &sort_comm, }, - { .name = "dso", .entry = &sort_dso, }, - { .name = "symbol", .entry = &sort_sym, }, - { .name = "parent", .entry = &sort_parent, }, - { .name = "cpu", .entry = &sort_cpu, }, -}; - -int64_t cmp_null(void *l, void *r) -{ - if (!l && !r) - return 0; - else if (!l) - return -1; - else - return 1; -} - -/* --sort pid */ - -int64_t -sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) -{ - return right->thread->pid - left->thread->pid; -} - static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) { int n; @@ -125,6 +36,24 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) return n; } +static int64_t cmp_null(void *l, void *r) +{ + if (!l && !r) + return 0; + else if (!l) + return -1; + else + return 1; +} + +/* --sort pid */ + +static int64_t +sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) +{ + return right->thread->pid - left->thread->pid; +} + static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { @@ -132,15 +61,50 @@ static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, self->thread->comm ?: "", self->thread->pid); } +struct sort_entry sort_thread = { + .se_header = "Command: Pid", + .se_cmp = sort__thread_cmp, + .se_snprintf = hist_entry__thread_snprintf, + .se_width_idx = HISTC_THREAD, +}; + +/* --sort comm */ + +static int64_t +sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) +{ + return right->thread->pid - left->thread->pid; +} + +static int64_t +sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) +{ + char *comm_l = left->thread->comm; + char *comm_r = right->thread->comm; + + if (!comm_l || !comm_r) + return cmp_null(comm_l, comm_r); + + return strcmp(comm_l, comm_r); +} + static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { return repsep_snprintf(bf, size, "%*s", width, self->thread->comm); } +struct sort_entry sort_comm = { + .se_header = "Command", + .se_cmp = sort__comm_cmp, + .se_collapse = sort__comm_collapse, + .se_snprintf = hist_entry__comm_snprintf, + .se_width_idx = HISTC_COMM, +}; + /* --sort dso */ -int64_t +static int64_t sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) { 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, return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); } +struct sort_entry sort_dso = { + .se_header = "Shared Object", + .se_cmp = sort__dso_cmp, + .se_snprintf = hist_entry__dso_snprintf, + .se_width_idx = HISTC_DSO, +}; + /* --sort symbol */ -int64_t +static int64_t sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) { u64 ip_l, ip_r; @@ -211,29 +182,16 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, return ret; } -/* --sort comm */ - -int64_t -sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) -{ - return right->thread->pid - left->thread->pid; -} - -int64_t -sort__comm_collapse(struct hist_entry *left, struct hist_entry *right) -{ - char *comm_l = left->thread->comm; - char *comm_r = right->thread->comm; - - if (!comm_l || !comm_r) - return cmp_null(comm_l, comm_r); - - return strcmp(comm_l, comm_r); -} +struct sort_entry sort_sym = { + .se_header = "Symbol", + .se_cmp = sort__sym_cmp, + .se_snprintf = hist_entry__sym_snprintf, + .se_width_idx = HISTC_SYMBOL, +}; /* --sort parent */ -int64_t +static int64_t sort__parent_cmp(struct hist_entry *left, struct hist_entry *right) { struct symbol *sym_l = left->parent; @@ -252,9 +210,16 @@ static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, self->parent ? self->parent->name : "[other]"); } +struct sort_entry sort_parent = { + .se_header = "Parent symbol", + .se_cmp = sort__parent_cmp, + .se_snprintf = hist_entry__parent_snprintf, + .se_width_idx = HISTC_PARENT, +}; + /* --sort cpu */ -int64_t +static int64_t sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right) { return right->cpu - left->cpu; @@ -266,6 +231,28 @@ static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf, return repsep_snprintf(bf, size, "%-*d", width, self->cpu); } +struct sort_entry sort_cpu = { + .se_header = "CPU", + .se_cmp = sort__cpu_cmp, + .se_snprintf = hist_entry__cpu_snprintf, + .se_width_idx = HISTC_CPU, +}; + +struct sort_dimension { + const char *name; + struct sort_entry *entry; + int taken; +}; + +static struct sort_dimension sort_dimensions[] = { + { .name = "pid", .entry = &sort_thread, }, + { .name = "comm", .entry = &sort_comm, }, + { .name = "dso", .entry = &sort_dso, }, + { .name = "symbol", .entry = &sort_sym, }, + { .name = "parent", .entry = &sort_parent, }, + { .name = "cpu", .entry = &sort_cpu, }, +}; + int sort_dimension__add(const char *tok) { unsigned int i; diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 0b91053a7d11..4a6d30908249 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -108,14 +108,6 @@ extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int); extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int); extern size_t sort__dso_print(FILE *, struct hist_entry *, unsigned int); extern size_t sort__sym_print(FILE *, struct hist_entry *, unsigned int __used); -extern int64_t cmp_null(void *, void *); -extern int64_t sort__thread_cmp(struct hist_entry *, struct hist_entry *); -extern int64_t sort__comm_cmp(struct hist_entry *, struct hist_entry *); -extern int64_t sort__comm_collapse(struct hist_entry *, struct hist_entry *); -extern int64_t sort__dso_cmp(struct hist_entry *, struct hist_entry *); -extern int64_t sort__sym_cmp(struct hist_entry *, struct hist_entry *); -extern int64_t sort__parent_cmp(struct hist_entry *, struct hist_entry *); -int64_t sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right); extern size_t sort__parent_print(FILE *, struct hist_entry *, unsigned int); extern int sort_dimension__add(const char *); void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, -- cgit v1.2.3 From 2fd701bc782fad8792059dd586e1f00b64f6a52e Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 29 Jun 2011 03:25:14 +0200 Subject: perf tools: Remove sort print helpers declarations These are probably some old leftovers. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: David Ahern Cc: Sam Liao --- tools/perf/util/sort.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 4a6d30908249..77d0388ad415 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -103,12 +103,6 @@ extern struct sort_entry sort_thread; extern struct list_head hist_entry__sort_list; void setup_sorting(const char * const usagestr[], const struct option *opts); - -extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int); -extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int); -extern size_t sort__dso_print(FILE *, struct hist_entry *, unsigned int); -extern size_t sort__sym_print(FILE *, struct hist_entry *, unsigned int __used); -extern size_t sort__parent_print(FILE *, struct hist_entry *, unsigned int); extern int sort_dimension__add(const char *); void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, const char *list_name, FILE *fp); -- cgit v1.2.3 From e84d21227c6865fe1f3d0c79d1539b6877f54c84 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 29 Jun 2011 22:23:03 +0200 Subject: perf tools: Don't display ignored entries on stdio ui As for newt ui, don't display entries that have been marked as ignored. The practical current effect of this is to make parent filtering really working. Before, entries that were ignored were given a null parent but were still displayed. This resulted in some weird effects: # Overhead Command Shared Object Symbol # ........ ........... ................. ............ # ^A | --- __lock_acquire | |--95.97%-- lock_acquire | | | |--30.75%-- _raw_spin_lock Discard these from the stdio display. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: David Ahern Cc: Sam Liao --- tools/perf/util/hist.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index dae4202fa65a..677e1da6bb3e 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -847,6 +847,9 @@ print_entries: for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + if (h->filtered) + continue; + if (show_displacement) { if (h->pair != NULL) displacement = ((long)h->pair->position - -- cgit v1.2.3 From fd8ea21276adefc7f0133bd42fcf3b2faf0b15f8 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 29 Jun 2011 23:08:14 +0200 Subject: perf tools: Allow sort dimensions to be registered more than once So that the parent sort dimension can be registered twice: once if we add it as an explicit sort dimension (-s parent) and twice if we request a parent filter (-p foo). We'll have only one parent sort dimension in the end but this allows to override the default parent filter with we gave in "-p" option. The goal of this is to prepare to allow the use of "-s parent" and "-p foo" at the same time, ie: sort by filtered parent. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: David Ahern Cc: Sam Liao --- tools/perf/util/sort.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index f5dba560d918..401e220566fd 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -260,15 +260,9 @@ int sort_dimension__add(const char *tok) for (i = 0; i < ARRAY_SIZE(sort_dimensions); i++) { struct sort_dimension *sd = &sort_dimensions[i]; - if (sd->taken) - continue; - if (strncasecmp(tok, sd->name, strlen(tok))) continue; - if (sd->entry->se_collapse) - sort__need_collapse = 1; - if (sd->entry == &sort_parent) { int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED); if (ret) { @@ -281,6 +275,12 @@ int sort_dimension__add(const char *tok) sort__has_parent = 1; } + if (sd->taken) + return 0; + + if (sd->entry->se_collapse) + sort__need_collapse = 1; + if (list_empty(&hist_entry__sort_list)) { if (!strcmp(sd->name, "pid")) sort__first_dimension = SORT_PID; -- cgit v1.2.3 From cb1955b86c86782ff20037da42ef030057501c34 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 29 Jun 2011 23:52:52 +0200 Subject: perf tools: Only display parent field if explictly sorted We don't need to display the parent field if the parent sorting machinery is only used for parent filtering (as in "-p foo"). However if parent filtering is used in combination with explicit parent sorting ( -s parent), we want to display it. Result with: perf report -p kernel_thread -s parent Before: # Overhead Parent symbol # ........ ............. # 0.07% | --- ioread8 ata_sff_check_status ata_sff_tf_load ata_sff_qc_issue ata_bmdma_qc_issue ata_qc_issue ata_scsi_translate ata_scsi_queuecmd scsi_dispatch_cmd scsi_request_fn __blk_run_queue __make_request generic_make_request submit_bio submit_bh journal_submit_commit_record jbd2_journal_commit_transaction kjournald2 kthread kernel_thread_helpe After: # Overhead Parent symbol # ........ ............. # 0.07% kernel_thread_helper | --- ioread8 ata_sff_check_status ata_sff_tf_load ata_sff_qc_issue ata_bmdma_qc_issue ata_qc_issue ata_scsi_translate ata_scsi_queuecmd scsi_dispatch_cmd scsi_request_fn __blk_run_queue __make_request generic_make_request submit_bio submit_bh journal_submit_commit_record jbd2_journal_commit_transaction kjournald2 kthread kernel_thread_helper Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: David Ahern Cc: Sam Liao --- tools/perf/builtin-report.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 271e252dc651..5d43d0181d63 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -525,7 +525,14 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) if (parent_pattern != default_parent_pattern) { if (sort_dimension__add("parent") < 0) return -1; - sort_parent.elide = 1; + + /* + * Only show the parent fields if we explicitly + * sort that way. If we only use parent machinery + * for filtering, we don't want it. + */ + if (!strstr(sort_order, "parent")) + sort_parent.elide = 1; } else symbol_conf.exclude_other = false; -- cgit v1.2.3 From 3ae9a34d747f9abf2bcc85dc0e77b951513ccdf2 Mon Sep 17 00:00:00 2001 From: Zhengyu He Date: Thu, 23 Jun 2011 13:45:42 -0700 Subject: perf stat: Add noise output for csv mode Previously, when you want perf-stat to output the statistics in csv mode, no information of the noise will be printed out. For example right now we output this --repeat information: ./perf stat -r3 -x, sleep 1 1.164789,task-clock 8,context-switches 0,CPU-migrations 219,page-faults 3337800,cycles With this patch, the output will be appended with an additional entry for the noise value: ./perf stat -r3 -x, sleep 1 1.164789,task-clock,3.75% 8,context-switches,75.00% 0,CPU-migrations,100.00% 219,page-faults,0.00% 3337800,cycles,3.36% Signed-off-by: Zhengyu He Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: Venkatesh Pallipadi Cc: Peter Zijlstra Cc: Frederic Weisbecker Link: http://lkml.kernel.org/r/1308861942-4945-1-git-send-email-zhengyuh@google.com Signed-off-by: Ingo Molnar --- tools/perf/builtin-stat.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 784ed6d6e0d6..1d08c8084cc4 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -517,7 +517,10 @@ static void print_noise_pct(double total, double avg) if (avg) pct = 100.0*total/avg; - fprintf(stderr, " ( +-%6.2f%% )", pct); + if (csv_output) + fprintf(stderr, "%s%.2f%%", csv_sep, pct); + else + fprintf(stderr, " ( +-%6.2f%% )", pct); } static void print_noise(struct perf_evsel *evsel, double avg) @@ -882,13 +885,13 @@ static void print_counter_aggr(struct perf_evsel *counter) else abs_printout(-1, counter, avg); + print_noise(counter, avg); + if (csv_output) { fputc('\n', stderr); return; } - print_noise(counter, avg); - if (scaled) { double avg_enabled, avg_running; -- cgit v1.2.3 From 9da4714a2d44ff48618a8d375dd81873e858803d Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 1 Jun 2011 12:26:00 -0500 Subject: slub: slabinfo update for cmpxchg handling Update the statistics handling and the slabinfo tool to include the new statistics in the reports it generates. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- tools/slub/slabinfo.c | 59 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 19 deletions(-) (limited to 'tools') 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 @@ * Slabinfo: Tool to get reports about slabs * * (C) 2007 sgi, Christoph Lameter + * (C) 2011 Linux Foundation, Christoph Lameter * - * Compile by: + * Compile with: * * gcc -o slabinfo slabinfo.c */ @@ -39,6 +40,8 @@ struct slabinfo { unsigned long cpuslab_flush, deactivate_full, deactivate_empty; unsigned long deactivate_to_head, deactivate_to_tail; unsigned long deactivate_remote_frees, order_fallback; + unsigned long cmpxchg_double_cpu_fail, cmpxchg_double_fail; + unsigned long alloc_node_mismatch, deactivate_bypass; int numa[MAX_NODES]; int numa_partial[MAX_NODES]; } slabinfo[MAX_SLABS]; @@ -99,7 +102,7 @@ static void fatal(const char *x, ...) static void usage(void) { - printf("slabinfo 5/7/2007. (c) 2007 sgi.\n\n" + printf("slabinfo 4/15/2011. (c) 2007 sgi/(c) 2011 Linux Foundation.\n\n" "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n" "-a|--aliases Show aliases\n" "-A|--activity Most active slabs first\n" @@ -293,7 +296,7 @@ int line = 0; static void first_line(void) { if (show_activity) - printf("Name Objects Alloc Free %%Fast Fallb O\n"); + printf("Name Objects Alloc Free %%Fast Fallb O CmpX UL\n"); else printf("Name Objects Objsize Space " "Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n"); @@ -379,14 +382,14 @@ static void show_tracking(struct slabinfo *s) printf("\n%s: Kernel object allocation\n", s->name); printf("-----------------------------------------------------------------------\n"); if (read_slab_obj(s, "alloc_calls")) - printf(buffer); + printf("%s", buffer); else printf("No Data\n"); printf("\n%s: Kernel object freeing\n", s->name); printf("------------------------------------------------------------------------\n"); if (read_slab_obj(s, "free_calls")) - printf(buffer); + printf("%s", buffer); else printf("No Data\n"); @@ -400,7 +403,7 @@ static void ops(struct slabinfo *s) if (read_slab_obj(s, "ops")) { printf("\n%s: kmem_cache operations\n", s->name); printf("--------------------------------------------\n"); - printf(buffer); + printf("%s", buffer); } else printf("\n%s has no kmem_cache operations\n", s->name); } @@ -462,19 +465,32 @@ static void slab_stats(struct slabinfo *s) if (s->cpuslab_flush) printf("Flushes %8lu\n", s->cpuslab_flush); - if (s->alloc_refill) - printf("Refill %8lu\n", s->alloc_refill); - total = s->deactivate_full + s->deactivate_empty + - s->deactivate_to_head + s->deactivate_to_tail; - - if (total) - printf("Deactivate Full=%lu(%lu%%) Empty=%lu(%lu%%) " - "ToHead=%lu(%lu%%) ToTail=%lu(%lu%%)\n", - s->deactivate_full, (s->deactivate_full * 100) / total, - s->deactivate_empty, (s->deactivate_empty * 100) / total, - s->deactivate_to_head, (s->deactivate_to_head * 100) / total, + s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass; + + if (total) { + printf("\nSlab Deactivation Ocurrences %%\n"); + printf("-------------------------------------------------\n"); + printf("Slab full %7lu %3lu%%\n", + s->deactivate_full, (s->deactivate_full * 100) / total); + printf("Slab empty %7lu %3lu%%\n", + s->deactivate_empty, (s->deactivate_empty * 100) / total); + printf("Moved to head of partial list %7lu %3lu%%\n", + s->deactivate_to_head, (s->deactivate_to_head * 100) / total); + printf("Moved to tail of partial list %7lu %3lu%%\n", s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total); + printf("Deactivation bypass %7lu %3lu%%\n", + s->deactivate_bypass, (s->deactivate_bypass * 100) / total); + printf("Refilled from foreign frees %7lu %3lu%%\n", + s->alloc_refill, (s->alloc_refill * 100) / total); + printf("Node mismatch %7lu %3lu%%\n", + s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total); + } + + if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail) + printf("\nCmpxchg_double Looping\n------------------------\n"); + printf("Locked Cmpxchg Double redos %lu\nUnlocked Cmpxchg Double redos %lu\n", + s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail); } static void report(struct slabinfo *s) @@ -573,12 +589,13 @@ static void slabcache(struct slabinfo *s) total_alloc = s->alloc_fastpath + s->alloc_slowpath; total_free = s->free_fastpath + s->free_slowpath; - printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d\n", + printf("%-21s %8ld %10ld %10ld %3ld %3ld %5ld %1d %4ld %4ld\n", s->name, s->objects, total_alloc, total_free, total_alloc ? (s->alloc_fastpath * 100 / total_alloc) : 0, total_free ? (s->free_fastpath * 100 / total_free) : 0, - s->order_fallback, s->order); + s->order_fallback, s->order, s->cmpxchg_double_fail, + s->cmpxchg_double_cpu_fail); } else printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n", @@ -1190,6 +1207,10 @@ static void read_slab_dir(void) slab->deactivate_to_tail = get_obj("deactivate_to_tail"); slab->deactivate_remote_frees = get_obj("deactivate_remote_frees"); slab->order_fallback = get_obj("order_fallback"); + slab->cmpxchg_double_cpu_fail = get_obj("cmpxchg_double_cpu_fail"); + slab->cmpxchg_double_fail = get_obj("cmpxchg_double_fail"); + slab->alloc_node_mismatch = get_obj("alloc_node_mismatch"); + slab->deactivate_bypass = get_obj("deactivate_bypass"); chdir(".."); if (slab->name[0] == ':') alias_targets++; -- cgit v1.2.3 From 5d67be97f8903d05ce53597fb5f3bc25a45e8026 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 4 Jul 2011 21:57:50 +1000 Subject: perf report/annotate/script: Add option to specify a CPU range Add an option to perf report/annotate/script to specify which CPUs to operate on. This enables us to take a single system wide profile and analyse each CPU (or group of CPUs) in isolation. This was useful when profiling a multiprocess workload where the bottleneck was on one CPU but this was hidden in the overall profile. Per process and per thread breakdowns didn't help because multiple processes were running on each CPU and no single process consumed an entire CPU. The patch converts the list of CPUs returned by cpu_map__new into a bitmap for fast lookup. I wanted to use -C to be consistent with perf top/record/stat, but unfortunately perf report already uses -C . v2: Incorporate suggestions from David Ahern: - Added -c to perf script - Check that SAMPLE_CPU is set when -c is used - Update documentation v3: Create perf_session__cpu_bitmap() Signed-off-by: Anton Blanchard Acked-by: David Ahern Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Paul Mackerras Link: http://lkml.kernel.org/r/20110704215750.11647eb9@kryten Signed-off-by: Ingo Molnar --- tools/perf/Documentation/perf-annotate.txt | 6 +++++ tools/perf/Documentation/perf-report.txt | 6 +++++ tools/perf/Documentation/perf-script.txt | 6 +++++ tools/perf/builtin-annotate.c | 15 ++++++++++++ tools/perf/builtin-report.c | 15 ++++++++++++ tools/perf/builtin-script.c | 13 ++++++++++ tools/perf/util/session.c | 38 ++++++++++++++++++++++++++++++ tools/perf/util/session.h | 3 +++ 8 files changed, 102 insertions(+) (limited to 'tools') 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 used. This interfaces starts by centering on the line with more samples, TAB/UNTAB cycles through the lines with more samples. +-c:: +--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can + be provided as a comma-separated list with no space: 0,1. Ranges of + CPUs are specified with -: 0-2. Default is to report samples on all + CPUs. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-report[1] diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index cfa8e513d0fb..04253c07d19a 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -128,6 +128,12 @@ OPTIONS --symfs=:: Look for files with symbols relative to this directory. +-c:: +--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can + be provided as a comma-separated list with no space: 0,1. Ranges of + CPUs are specified with -: 0-2. Default is to report samples on all + CPUs. + SEE ALSO -------- linkperf:perf-stat[1] diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index c6068cb43f57..db017867d9e8 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -182,6 +182,12 @@ OPTIONS --hide-call-graph:: When printing symbols do not display call chain. +-c:: +--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can + be provided as a comma-separated list with no space: 0,1. Ranges of + CPUs are specified with -: 0-2. Default is to report samples on all + CPUs. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-script-perl[1], 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 @@ #include "util/hist.h" #include "util/session.h" +#include + static char const *input_name = "perf.data"; static bool force, use_tui, use_stdio; @@ -38,6 +40,9 @@ static bool print_line; static const char *sym_hist_filter; +static const char *cpu_list; +static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); + static int perf_evlist__add_sample(struct perf_evlist *evlist, struct perf_sample *sample, struct perf_evsel *evsel, @@ -90,6 +95,9 @@ static int process_sample_event(union perf_event *event, return -1; } + if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) + return 0; + if (!al.filtered && perf_evlist__add_sample(session->evlist, sample, evsel, &al)) { pr_warning("problem incrementing symbol count, " @@ -177,6 +185,12 @@ static int __cmd_annotate(void) if (session == NULL) return -ENOMEM; + if (cpu_list) { + ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); + if (ret) + goto out_delete; + } + ret = perf_session__process_events(session, &event_ops); if (ret) goto out_delete; @@ -252,6 +266,7 @@ static const struct option options[] = { "print matching source lines (may be slow)"), OPT_BOOLEAN('P', "full-paths", &full_paths, "Don't shorten the displayed pathnames"), + OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), OPT_END() }; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 5d43d0181d63..f854efda7686 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -33,6 +33,8 @@ #include "util/sort.h" #include "util/hist.h" +#include + static char const *input_name = "perf.data"; static bool force, use_tui, use_stdio; @@ -49,6 +51,9 @@ static char callchain_default_opt[] = "fractal,0.5,callee"; static bool inverted_callchain; static symbol_filter_t annotate_init; +static const char *cpu_list; +static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); + static int perf_session__add_hist_entry(struct perf_session *session, struct addr_location *al, struct perf_sample *sample, @@ -117,6 +122,9 @@ static int process_sample_event(union perf_event *event, if (al.filtered || (hide_unresolved && al.sym == NULL)) return 0; + if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) + return 0; + if (al.map != NULL) al.map->dso->hit = 1; @@ -263,6 +271,12 @@ static int __cmd_report(void) if (session == NULL) return -ENOMEM; + if (cpu_list) { + ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); + if (ret) + goto out_delete; + } + if (show_threads) perf_read_values_init(&show_threads_values); @@ -473,6 +487,7 @@ static const struct option options[] = { "Only display entries resolved to a symbol"), OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", "Look for files with symbols relative to this directory"), + OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), OPT_END() }; diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 3056b45b3dd6..09024ec2ab2e 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -13,6 +13,7 @@ #include "util/util.h" #include "util/evlist.h" #include "util/evsel.h" +#include static char const *script_name; static char const *generate_script_lang; @@ -21,6 +22,8 @@ static u64 last_timestamp; static u64 nr_unordered; extern const struct option record_options[]; static bool no_callchain; +static const char *cpu_list; +static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); enum perf_output_field { PERF_OUTPUT_COMM = 1U << 0, @@ -453,6 +456,10 @@ static int process_sample_event(union perf_event *event, last_timestamp = sample->time; return 0; } + + if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) + return 0; + scripting_ops->process_event(event, sample, evsel, session, thread); session->hists.stats.total_period += sample->period; @@ -1075,6 +1082,7 @@ static const struct option options[] = { OPT_CALLBACK('f', "fields", NULL, "str", "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", parse_output_fields), + OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), OPT_END() }; @@ -1255,6 +1263,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) if (session == NULL) return -ENOMEM; + if (cpu_list) { + if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) + return -1; + } + if (!no_callchain) symbol_conf.use_callchain = true; else diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 558bcf996949..080e5336d89f 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -12,6 +12,7 @@ #include "session.h" #include "sort.h" #include "util.h" +#include "cpumap.h" static int perf_session__open(struct perf_session *self, bool force) { @@ -1282,3 +1283,40 @@ void perf_session__print_ip(union perf_event *event, } } } + +int perf_session__cpu_bitmap(struct perf_session *session, + const char *cpu_list, unsigned long *cpu_bitmap) +{ + int i; + struct cpu_map *map; + + for (i = 0; i < PERF_TYPE_MAX; ++i) { + struct perf_evsel *evsel; + + evsel = perf_session__find_first_evtype(session, i); + if (!evsel) + continue; + + if (!(evsel->attr.sample_type & PERF_SAMPLE_CPU)) { + pr_err("File does not contain CPU events. " + "Remove -c option to proceed.\n"); + return -1; + } + } + + map = cpu_map__new(cpu_list); + + for (i = 0; i < map->nr; i++) { + int cpu = map->map[i]; + + if (cpu >= MAX_NR_CPUS) { + pr_err("Requested CPU %d too large. " + "Consider raising MAX_NR_CPUS\n", cpu); + return -1; + } + + set_bit(cpu, cpu_bitmap); + } + + return 0; +} diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index de4178d7bb7b..5de754f4b7f3 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -172,4 +172,7 @@ void perf_session__print_ip(union perf_event *event, struct perf_session *session, int print_sym, int print_dso); +int perf_session__cpu_bitmap(struct perf_session *session, + const char *cpu_list, unsigned long *cpu_bitmap); + #endif /* __PERF_SESSION_H */ -- cgit v1.2.3 From 259032bfe379281bf7cba512b7705bdb4ce41db5 Mon Sep 17 00:00:00 2001 From: Sonny Rao Date: Thu, 14 Jul 2011 13:34:43 +1000 Subject: perf: Robustify proc and debugfs file recording While attempting to create a timechart of boot up I found perf didn't tolerate modules being loaded/unloaded. This patch fixes this by reading the file once and then writing the size read at the correct point in the file. It also simplifies the code somewhat. Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Signed-off-by: Sonny Rao Signed-off-by: Michael Neuling Link: http://lkml.kernel.org/r/10011.1310614483@neuling.org Signed-off-by: Steven Rostedt --- tools/perf/util/trace-event-info.c | 120 +++++++++---------------------------- 1 file changed, 29 insertions(+), 91 deletions(-) (limited to 'tools') 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) return *ptr == 0x01020304; } -static unsigned long long copy_file_fd(int fd) +/* unfortunately, you can not stat debugfs or proc files for size */ +static void record_file(const char *file, size_t hdr_sz) { unsigned long long size = 0; - char buf[BUFSIZ]; - int r; - - do { - r = read(fd, buf, BUFSIZ); - if (r > 0) { - size += r; - write_or_die(buf, r); - } - } while (r > 0); - - return size; -} - -static unsigned long long copy_file(const char *file) -{ - unsigned long long size = 0; - int fd; + char buf[BUFSIZ], *sizep; + off_t hdr_pos = lseek(output_fd, 0, SEEK_CUR); + int r, fd; fd = open(file, O_RDONLY); if (fd < 0) die("Can't read '%s'", file); - size = copy_file_fd(fd); - close(fd); - return size; -} - -static unsigned long get_size_fd(int fd) -{ - unsigned long long size = 0; - char buf[BUFSIZ]; - int r; + /* put in zeros for file size, then fill true size later */ + write_or_die(&size, hdr_sz); do { r = read(fd, buf, BUFSIZ); - if (r > 0) + if (r > 0) { size += r; + write_or_die(buf, r); + } } while (r > 0); - - lseek(fd, 0, SEEK_SET); - - return size; -} - -static unsigned long get_size(const char *file) -{ - unsigned long long size = 0; - int fd; - - fd = open(file, O_RDONLY); - if (fd < 0) - die("Can't read '%s'", file); - size = get_size_fd(fd); close(fd); - return size; + /* ugh, handle big-endian hdr_size == 4 */ + sizep = (char*)&size; + if (bigendian()) + sizep += sizeof(u64) - hdr_sz; + + if (pwrite(output_fd, sizep, hdr_sz, hdr_pos) < 0) + die("writing to %s", output_file); } static void read_header_files(void) { - unsigned long long size, check_size; char *path; - int fd; + struct stat st; path = get_tracing_file("events/header_page"); - fd = open(path, O_RDONLY); - if (fd < 0) + if (stat(path, &st) < 0) die("can't read '%s'", path); - /* unfortunately, you can not stat debugfs files for size */ - size = get_size_fd(fd); - write_or_die("header_page", 12); - write_or_die(&size, 8); - check_size = copy_file_fd(fd); - close(fd); - - if (size != check_size) - die("wrong size for '%s' size=%lld read=%lld", - path, size, check_size); + record_file(path, 8); put_tracing_file(path); path = get_tracing_file("events/header_event"); - fd = open(path, O_RDONLY); - if (fd < 0) + if (stat(path, &st) < 0) die("can't read '%s'", path); - size = get_size_fd(fd); - write_or_die("header_event", 13); - write_or_die(&size, 8); - check_size = copy_file_fd(fd); - if (size != check_size) - die("wrong size for '%s'", path); + record_file(path, 8); put_tracing_file(path); - close(fd); } 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) static void copy_event_system(const char *sys, struct tracepoint_path *tps) { - unsigned long long size, check_size; struct dirent *dent; struct stat st; char *format; @@ -338,14 +290,8 @@ static void copy_event_system(const char *sys, struct tracepoint_path *tps) sprintf(format, "%s/%s/format", sys, dent->d_name); ret = stat(format, &st); - if (ret >= 0) { - /* unfortunately, you can not stat debugfs files for size */ - size = get_size(format); - write_or_die(&size, 8); - check_size = copy_file(format); - if (size != check_size) - die("error in size of file '%s'", format); - } + if (ret >= 0) + record_file(format, 8); free(format); } @@ -426,7 +372,7 @@ static void read_event_files(struct tracepoint_path *tps) static void read_proc_kallsyms(void) { - unsigned int size, check_size; + unsigned int size; const char *path = "/proc/kallsyms"; struct stat st; int ret; @@ -438,17 +384,12 @@ static void read_proc_kallsyms(void) write_or_die(&size, 4); return; } - size = get_size(path); - write_or_die(&size, 4); - check_size = copy_file(path); - if (size != check_size) - die("error in size of file '%s'", path); - + record_file(path, 4); } static void read_ftrace_printk(void) { - unsigned int size, check_size; + unsigned int size; char *path; struct stat st; int ret; @@ -461,11 +402,8 @@ static void read_ftrace_printk(void) write_or_die(&size, 4); goto out; } - size = get_size(path); - write_or_die(&size, 4); - check_size = copy_file(path); - if (size != check_size) - die("error in size of file '%s'", path); + record_file(path, 4); + out: put_tracing_file(path); } -- cgit v1.2.3 From baad2d3e69ba154dae340904a47ae12414f1894f Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 27 Jun 2011 16:27:09 +0900 Subject: perf probe: Rename DIE_FIND_CB_FOUND to DIE_FIND_CB_END Since die_find/walk* callbacks use DIE_FIND_CB_FOUND for both of failed and found cases, it should be "END" instead "FOUND" for avoiding confusion. Signed-off-by: Masami Hiramatsu Reported-by: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Ingo Molnar Link: http://lkml.kernel.org/r/20110627072709.6528.45706.stgit@fedora15 Signed-off-by: Steven Rostedt --- tools/perf/util/probe-finder.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 3b9d0b800d5c..7b78904a4dba 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -435,7 +435,7 @@ static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs) /* Return values for die_find callbacks */ enum { - DIE_FIND_CB_FOUND = 0, /* End of Search */ + DIE_FIND_CB_END = 0, /* End of Search */ DIE_FIND_CB_CHILD = 1, /* Search only children */ DIE_FIND_CB_SIBLING = 2, /* Search only siblings */ DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */ @@ -455,7 +455,7 @@ static Dwarf_Die *die_find_child(Dwarf_Die *rt_die, do { ret = callback(die_mem, data); - if (ret == DIE_FIND_CB_FOUND) + if (ret == DIE_FIND_CB_END) return die_mem; if ((ret & DIE_FIND_CB_CHILD) && @@ -507,7 +507,7 @@ static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data) if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine && dwarf_haspc(die_mem, *addr)) - return DIE_FIND_CB_FOUND; + return DIE_FIND_CB_END; return DIE_FIND_CB_CONTINUE; } @@ -555,7 +555,7 @@ static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data) lw->retval = lw->handler(lw->fname, lineno, addr, lw->data); if (lw->retval != 0) - return DIE_FIND_CB_FOUND; + return DIE_FIND_CB_END; } } return DIE_FIND_CB_SIBLING; @@ -691,7 +691,7 @@ static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) if ((tag == DW_TAG_formal_parameter || tag == DW_TAG_variable) && die_compare_name(die_mem, fvp->name)) - return DIE_FIND_CB_FOUND; + return DIE_FIND_CB_END; if (dwarf_haspc(die_mem, fvp->addr)) return DIE_FIND_CB_CONTINUE; @@ -715,7 +715,7 @@ static int __die_find_member_cb(Dwarf_Die *die_mem, void *data) if ((dwarf_tag(die_mem) == DW_TAG_member) && die_compare_name(die_mem, name)) - return DIE_FIND_CB_FOUND; + return DIE_FIND_CB_END; return DIE_FIND_CB_SIBLING; } -- cgit v1.2.3 From bad03ae476214d9d66bb96be02b630385936f788 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 27 Jun 2011 16:27:15 +0900 Subject: perf probe: Move strtailcmp to string.c Since strtailcmp() is enough generic, it should be defined in string.c. Signed-off-by: Masami Hiramatsu Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/r/20110627072715.6528.10677.stgit@fedora15 Signed-off-by: Steven Rostedt --- tools/perf/util/probe-finder.c | 15 --------------- tools/perf/util/string.c | 19 +++++++++++++++++++ tools/perf/util/util.h | 1 + 3 files changed, 20 insertions(+), 15 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 7b78904a4dba..459ebe8b04f3 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -43,21 +43,6 @@ /* Kprobe tracer basic type is up to u64 */ #define MAX_BASIC_TYPE_BITS 64 -/* - * Compare the tail of two strings. - * Return 0 if whole of either string is same as another's tail part. - */ -static int strtailcmp(const char *s1, const char *s2) -{ - int i1 = strlen(s1); - int i2 = strlen(s2); - while (--i1 >= 0 && --i2 >= 0) { - if (s1[i1] != s2[i2]) - return s1[i1] - s2[i2]; - } - return 0; -} - /* Line number list operations */ /* Add a line to line number list */ 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) { return __match_glob(str, pat, true); } + +/** + * strtailcmp - Compare the tail of two strings + * @s1: 1st string to be compared + * @s2: 2nd string to be compared + * + * Return 0 if whole of either string is same as another's tail part. + */ +int strtailcmp(const char *s1, const char *s2) +{ + int i1 = strlen(s1); + int i2 = strlen(s2); + while (--i1 >= 0 && --i2 >= 0) { + if (s1[i1] != s2[i2]) + return s1[i1] - s2[i2]; + } + return 0; +} + 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); void argv_free(char **argv); bool strglobmatch(const char *str, const char *pat); bool strlazymatch(const char *str, const char *pat); +int strtailcmp(const char *s1, const char *s2); unsigned long convert_unit(unsigned long value, char *unit); int readn(int fd, void *buf, size_t size); -- cgit v1.2.3 From bcfc082150c6b1e9443c1277bca8be80094150b5 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 27 Jun 2011 16:27:21 +0900 Subject: perf probe: Remove redundant dwarf functions Since there are dwarf_bitsize, dwarf_bitoffset and dwarf_bytesize defined in libdw, we don't need die_get_bit_size, die_get_bit_offset and die_get_byte_size anymore. Signed-off-by: Masami Hiramatsu Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/r/20110627072721.6528.2747.stgit@fedora15 Signed-off-by: Steven Rostedt --- tools/perf/util/probe-finder.c | 50 +++++++++++------------------------------- 1 file changed, 13 insertions(+), 37 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 459ebe8b04f3..d443b643957f 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -361,36 +361,6 @@ static bool die_is_signed_type(Dwarf_Die *tp_die) ret == DW_ATE_signed_fixed); } -static int die_get_byte_size(Dwarf_Die *tp_die) -{ - Dwarf_Word ret; - - if (die_get_attr_udata(tp_die, DW_AT_byte_size, &ret)) - return 0; - - return (int)ret; -} - -static int die_get_bit_size(Dwarf_Die *tp_die) -{ - Dwarf_Word ret; - - if (die_get_attr_udata(tp_die, DW_AT_bit_size, &ret)) - return 0; - - return (int)ret; -} - -static int die_get_bit_offset(Dwarf_Die *tp_die) -{ - Dwarf_Word ret; - - if (die_get_attr_udata(tp_die, DW_AT_bit_offset, &ret)) - return 0; - - return (int)ret; -} - /* Get data_member_location offset */ static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs) { @@ -882,6 +852,7 @@ static int convert_variable_type(Dwarf_Die *vr_die, struct probe_trace_arg_ref **ref_ptr = &tvar->ref; Dwarf_Die type; char buf[16]; + int bsize, boffs, total; int ret; /* TODO: check all types */ @@ -891,11 +862,15 @@ static int convert_variable_type(Dwarf_Die *vr_die, return (tvar->type == NULL) ? -ENOMEM : 0; } - if (die_get_bit_size(vr_die) != 0) { + bsize = dwarf_bitsize(vr_die); + if (bsize > 0) { /* This is a bitfield */ - ret = snprintf(buf, 16, "b%d@%d/%zd", die_get_bit_size(vr_die), - die_get_bit_offset(vr_die), - BYTES_TO_BITS(die_get_byte_size(vr_die))); + boffs = dwarf_bitoffset(vr_die); + total = dwarf_bytesize(vr_die); + if (boffs < 0 || total < 0) + return -ENOENT; + ret = snprintf(buf, 16, "b%d@%d/%zd", bsize, boffs, + BYTES_TO_BITS(total)); goto formatted; } @@ -943,10 +918,11 @@ static int convert_variable_type(Dwarf_Die *vr_die, return (tvar->type == NULL) ? -ENOMEM : 0; } - ret = BYTES_TO_BITS(die_get_byte_size(&type)); - if (!ret) + ret = dwarf_bytesize(&type); + if (ret <= 0) /* No size ... try to use default type */ return 0; + ret = BYTES_TO_BITS(ret); /* Check the bitwidth */ if (ret > MAX_BASIC_TYPE_BITS) { @@ -1010,7 +986,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, else *ref_ptr = ref; } - ref->offset += die_get_byte_size(&type) * field->index; + ref->offset += dwarf_bytesize(&type) * field->index; if (!field->next) /* Save vr_die for converting types */ memcpy(die_mem, vr_die, sizeof(*die_mem)); -- cgit v1.2.3 From e0d153c69040bb37cbdf09deb52fee3013c07742 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 27 Jun 2011 16:27:27 +0900 Subject: perf-probe: Move dwarf library routines to dwarf-aux.{c, h} Move dwarf library related routines to dwarf-aux.{c,h}. This includes several minor changes. - Add simple documents for each API. - Rename die_find_real_subprogram() to die_find_realfunc() - Rename line_walk_handler_t to line_walk_callback_t. - Minor cleanups. Signed-off-by: Masami Hiramatsu Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/r/20110627072727.6528.57647.stgit@fedora15 Signed-off-by: Steven Rostedt --- tools/perf/Makefile | 2 + tools/perf/util/dwarf-aux.c | 663 +++++++++++++++++++++++++++++++++++++++++ tools/perf/util/dwarf-aux.h | 100 +++++++ tools/perf/util/probe-finder.c | 520 +------------------------------- tools/perf/util/probe-finder.h | 6 +- 5 files changed, 768 insertions(+), 523 deletions(-) create mode 100644 tools/perf/util/dwarf-aux.c create mode 100644 tools/perf/util/dwarf-aux.h (limited to 'tools') diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 940257b5774e..d0861bbd1d94 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -279,6 +279,7 @@ LIB_H += util/thread.h LIB_H += util/thread_map.h LIB_H += util/trace-event.h LIB_H += util/probe-finder.h +LIB_H += util/dwarf-aux.h LIB_H += util/probe-event.h LIB_H += util/pstack.h LIB_H += util/cpumap.h @@ -435,6 +436,7 @@ else BASIC_CFLAGS += -DDWARF_SUPPORT EXTLIBS += -lelf -ldw LIB_OBJS += $(OUTPUT)util/probe-finder.o + LIB_OBJS += $(OUTPUT)util/dwarf-aux.o endif # PERF_HAVE_DWARF_REGS endif # NO_DWARF diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c new file mode 100644 index 000000000000..fddf40f30d3e --- /dev/null +++ b/tools/perf/util/dwarf-aux.c @@ -0,0 +1,663 @@ +/* + * dwarf-aux.c : libdw auxiliary interfaces + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include "util.h" +#include "debug.h" +#include "dwarf-aux.h" + +/** + * cu_find_realpath - Find the realpath of the target file + * @cu_die: A DIE(dwarf information entry) of CU(compilation Unit) + * @fname: The tail filename of the target file + * + * Find the real(long) path of @fname in @cu_die. + */ +const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname) +{ + Dwarf_Files *files; + size_t nfiles, i; + const char *src = NULL; + int ret; + + if (!fname) + return NULL; + + ret = dwarf_getsrcfiles(cu_die, &files, &nfiles); + if (ret != 0) + return NULL; + + for (i = 0; i < nfiles; i++) { + src = dwarf_filesrc(files, i, NULL, NULL); + if (strtailcmp(src, fname) == 0) + break; + } + if (i == nfiles) + return NULL; + return src; +} + +/** + * cu_get_comp_dir - Get the path of compilation directory + * @cu_die: a CU DIE + * + * Get the path of compilation directory of given @cu_die. + * Since this depends on DW_AT_comp_dir, older gcc will not + * embedded it. In that case, this returns NULL. + */ +const char *cu_get_comp_dir(Dwarf_Die *cu_die) +{ + Dwarf_Attribute attr; + if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL) + return NULL; + return dwarf_formstring(&attr); +} + +/** + * cu_find_lineinfo - Get a line number and file name for given address + * @cu_die: a CU DIE + * @addr: An address + * @fname: a pointer which returns the file name string + * @lineno: a pointer which returns the line number + * + * Find a line number and file name for @addr in @cu_die. + */ +int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr, + const char **fname, int *lineno) +{ + Dwarf_Line *line; + Dwarf_Addr laddr; + + line = dwarf_getsrc_die(cu_die, (Dwarf_Addr)addr); + if (line && dwarf_lineaddr(line, &laddr) == 0 && + addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) { + *fname = dwarf_linesrc(line, NULL, NULL); + if (!*fname) + /* line number is useless without filename */ + *lineno = 0; + } + + return *lineno ?: -ENOENT; +} + +/** + * die_compare_name - Compare diename and tname + * @dw_die: a DIE + * @tname: a string of target name + * + * Compare the name of @dw_die and @tname. Return false if @dw_die has no name. + */ +bool die_compare_name(Dwarf_Die *dw_die, const char *tname) +{ + const char *name; + name = dwarf_diename(dw_die); + return name ? (strcmp(tname, name) == 0) : false; +} + +/** + * die_get_call_lineno - Get callsite line number of inline-function instance + * @in_die: a DIE of an inlined function instance + * + * Get call-site line number of @in_die. This means from where the inline + * function is called. + */ +int die_get_call_lineno(Dwarf_Die *in_die) +{ + Dwarf_Attribute attr; + Dwarf_Word ret; + + if (!dwarf_attr(in_die, DW_AT_call_line, &attr)) + return -ENOENT; + + dwarf_formudata(&attr, &ret); + return (int)ret; +} + +/** + * die_get_type - Get type DIE + * @vr_die: a DIE of a variable + * @die_mem: where to store a type DIE + * + * Get a DIE of the type of given variable (@vr_die), and store + * it to die_mem. Return NULL if fails to get a type DIE. + */ +Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) +{ + Dwarf_Attribute attr; + + if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) && + dwarf_formref_die(&attr, die_mem)) + return die_mem; + else + return NULL; +} + +/* Get a type die, but skip qualifiers */ +static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) +{ + int tag; + + do { + vr_die = die_get_type(vr_die, die_mem); + if (!vr_die) + break; + tag = dwarf_tag(vr_die); + } while (tag == DW_TAG_const_type || + tag == DW_TAG_restrict_type || + tag == DW_TAG_volatile_type || + tag == DW_TAG_shared_type); + + return vr_die; +} + +/** + * die_get_real_type - Get a type die, but skip qualifiers and typedef + * @vr_die: a DIE of a variable + * @die_mem: where to store a type DIE + * + * Get a DIE of the type of given variable (@vr_die), and store + * it to die_mem. Return NULL if fails to get a type DIE. + * If the type is qualifiers (e.g. const) or typedef, this skips it + * and tries to find real type (structure or basic types, e.g. int). + */ +Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) +{ + do { + vr_die = __die_get_real_type(vr_die, die_mem); + } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef); + + return vr_die; +} + +/* Get attribute and translate it as a udata */ +static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name, + Dwarf_Word *result) +{ + Dwarf_Attribute attr; + + if (dwarf_attr(tp_die, attr_name, &attr) == NULL || + dwarf_formudata(&attr, result) != 0) + return -ENOENT; + + return 0; +} + +/** + * die_is_signed_type - Check whether a type DIE is signed or not + * @tp_die: a DIE of a type + * + * Get the encoding of @tp_die and return true if the encoding + * is signed. + */ +bool die_is_signed_type(Dwarf_Die *tp_die) +{ + Dwarf_Word ret; + + if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret)) + return false; + + return (ret == DW_ATE_signed_char || ret == DW_ATE_signed || + ret == DW_ATE_signed_fixed); +} + +/** + * die_get_data_member_location - Get the data-member offset + * @mb_die: a DIE of a member of a data structure + * @offs: The offset of the member in the data structure + * + * Get the offset of @mb_die in the data structure including @mb_die, and + * stores result offset to @offs. If any error occurs this returns errno. + */ +int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs) +{ + Dwarf_Attribute attr; + Dwarf_Op *expr; + size_t nexpr; + int ret; + + if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL) + return -ENOENT; + + if (dwarf_formudata(&attr, offs) != 0) { + /* DW_AT_data_member_location should be DW_OP_plus_uconst */ + ret = dwarf_getlocation(&attr, &expr, &nexpr); + if (ret < 0 || nexpr == 0) + return -ENOENT; + + if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) { + pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n", + expr[0].atom, nexpr); + return -ENOTSUP; + } + *offs = (Dwarf_Word)expr[0].number; + } + return 0; +} + +/** + * die_find_child - Generic DIE search function in DIE tree + * @rt_die: a root DIE + * @callback: a callback function + * @data: a user data passed to the callback function + * @die_mem: a buffer for result DIE + * + * Trace DIE tree from @rt_die and call @callback for each child DIE. + * If @callback returns DIE_FIND_CB_END, this stores the DIE into + * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE, + * this continues to trace the tree. Optionally, @callback can return + * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only + * the children and trace only the siblings respectively. + * Returns NULL if @callback can't find any appropriate DIE. + */ +Dwarf_Die *die_find_child(Dwarf_Die *rt_die, + int (*callback)(Dwarf_Die *, void *), + void *data, Dwarf_Die *die_mem) +{ + Dwarf_Die child_die; + int ret; + + ret = dwarf_child(rt_die, die_mem); + if (ret != 0) + return NULL; + + do { + ret = callback(die_mem, data); + if (ret == DIE_FIND_CB_END) + return die_mem; + + if ((ret & DIE_FIND_CB_CHILD) && + die_find_child(die_mem, callback, data, &child_die)) { + memcpy(die_mem, &child_die, sizeof(Dwarf_Die)); + return die_mem; + } + } while ((ret & DIE_FIND_CB_SIBLING) && + dwarf_siblingof(die_mem, die_mem) == 0); + + return NULL; +} + +struct __addr_die_search_param { + Dwarf_Addr addr; + Dwarf_Die *die_mem; +}; + +/* die_find callback for non-inlined function search */ +static int __die_search_func_cb(Dwarf_Die *fn_die, void *data) +{ + struct __addr_die_search_param *ad = data; + + if (dwarf_tag(fn_die) == DW_TAG_subprogram && + dwarf_haspc(fn_die, ad->addr)) { + memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die)); + return DWARF_CB_ABORT; + } + return DWARF_CB_OK; +} + +/** + * die_find_realfunc - Search a non-inlined function at given address + * @cu_die: a CU DIE which including @addr + * @addr: target address + * @die_mem: a buffer for result DIE + * + * Search a non-inlined function DIE which includes @addr. Stores the + * DIE to @die_mem and returns it if found. Returns NULl if failed. + */ +Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, + Dwarf_Die *die_mem) +{ + struct __addr_die_search_param ad; + ad.addr = addr; + ad.die_mem = die_mem; + /* dwarf_getscopes can't find subprogram. */ + if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0)) + return NULL; + else + return die_mem; +} + +/* die_find callback for inline function search */ +static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data) +{ + Dwarf_Addr *addr = data; + + if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine && + dwarf_haspc(die_mem, *addr)) + return DIE_FIND_CB_END; + + return DIE_FIND_CB_CONTINUE; +} + +/** + * die_find_inlinefunc - Search an inlined function at given address + * @cu_die: a CU DIE which including @addr + * @addr: target address + * @die_mem: a buffer for result DIE + * + * Search an inlined function DIE which includes @addr. Stores the + * DIE to @die_mem and returns it if found. Returns NULl if failed. + * If several inlined functions are expanded recursively, this trace + * it and returns deepest one. + */ +Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, + Dwarf_Die *die_mem) +{ + Dwarf_Die tmp_die; + + sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die); + if (!sp_die) + return NULL; + + /* Inlined function could be recursive. Trace it until fail */ + while (sp_die) { + memcpy(die_mem, sp_die, sizeof(Dwarf_Die)); + sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, + &tmp_die); + } + + return die_mem; +} + +/* Line walker internal parameters */ +struct __line_walk_param { + const char *fname; + line_walk_callback_t callback; + void *data; + int retval; +}; + +static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data) +{ + struct __line_walk_param *lw = data; + Dwarf_Addr addr; + int lineno; + + if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) { + lineno = die_get_call_lineno(in_die); + if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) { + lw->retval = lw->callback(lw->fname, lineno, addr, + lw->data); + if (lw->retval != 0) + return DIE_FIND_CB_END; + } + } + return DIE_FIND_CB_SIBLING; +} + +/* Walk on lines of blocks included in given DIE */ +static int __die_walk_funclines(Dwarf_Die *sp_die, + line_walk_callback_t callback, void *data) +{ + struct __line_walk_param lw = { + .callback = callback, + .data = data, + .retval = 0, + }; + Dwarf_Die die_mem; + Dwarf_Addr addr; + int lineno; + + /* Handle function declaration line */ + lw.fname = dwarf_decl_file(sp_die); + if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 && + dwarf_entrypc(sp_die, &addr) == 0) { + lw.retval = callback(lw.fname, lineno, addr, data); + if (lw.retval != 0) + goto done; + } + die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem); +done: + return lw.retval; +} + +static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data) +{ + struct __line_walk_param *lw = data; + + lw->retval = __die_walk_funclines(sp_die, lw->callback, lw->data); + if (lw->retval != 0) + return DWARF_CB_ABORT; + + return DWARF_CB_OK; +} + +/** + * die_walk_lines - Walk on lines inside given DIE + * @rt_die: a root DIE (CU or subprogram) + * @callback: callback routine + * @data: user data + * + * Walk on all lines inside given @rt_die and call @callback on each line. + * If the @rt_die is a function, walk only on the lines inside the function, + * otherwise @rt_die must be a CU DIE. + * Note that this walks not only dwarf line list, but also function entries + * and inline call-site. + */ +int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data) +{ + Dwarf_Lines *lines; + Dwarf_Line *line; + Dwarf_Addr addr; + const char *fname; + int lineno, ret = 0; + Dwarf_Die die_mem, *cu_die; + size_t nlines, i; + + /* Get the CU die */ + if (dwarf_tag(rt_die) == DW_TAG_subprogram) + cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL); + else + cu_die = rt_die; + if (!cu_die) { + pr_debug2("Failed to get CU from subprogram\n"); + return -EINVAL; + } + + /* Get lines list in the CU */ + if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) { + pr_debug2("Failed to get source lines on this CU.\n"); + return -ENOENT; + } + pr_debug2("Get %zd lines from this CU\n", nlines); + + /* Walk on the lines on lines list */ + for (i = 0; i < nlines; i++) { + line = dwarf_onesrcline(lines, i); + if (line == NULL || + dwarf_lineno(line, &lineno) != 0 || + dwarf_lineaddr(line, &addr) != 0) { + pr_debug2("Failed to get line info. " + "Possible error in debuginfo.\n"); + continue; + } + /* Filter lines based on address */ + if (rt_die != cu_die) + /* + * Address filtering + * The line is included in given function, and + * no inline block includes it. + */ + if (!dwarf_haspc(rt_die, addr) || + die_find_inlinefunc(rt_die, addr, &die_mem)) + continue; + /* Get source line */ + fname = dwarf_linesrc(line, NULL, NULL); + + ret = callback(fname, lineno, addr, data); + if (ret != 0) + return ret; + } + + /* + * Dwarf lines doesn't include function declarations and inlined + * subroutines. We have to check functions list or given function. + */ + if (rt_die != cu_die) + ret = __die_walk_funclines(rt_die, callback, data); + else { + struct __line_walk_param param = { + .callback = callback, + .data = data, + .retval = 0, + }; + dwarf_getfuncs(cu_die, __die_walk_culines_cb, ¶m, 0); + ret = param.retval; + } + + return ret; +} + +struct __find_variable_param { + const char *name; + Dwarf_Addr addr; +}; + +static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) +{ + struct __find_variable_param *fvp = data; + int tag; + + tag = dwarf_tag(die_mem); + if ((tag == DW_TAG_formal_parameter || + tag == DW_TAG_variable) && + die_compare_name(die_mem, fvp->name)) + return DIE_FIND_CB_END; + + if (dwarf_haspc(die_mem, fvp->addr)) + return DIE_FIND_CB_CONTINUE; + else + return DIE_FIND_CB_SIBLING; +} + +/** + * die_find_variable_at - Find a given name variable at given address + * @sp_die: a function DIE + * @name: variable name + * @addr: address + * @die_mem: a buffer for result DIE + * + * Find a variable DIE called @name at @addr in @sp_die. + */ +Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name, + Dwarf_Addr addr, Dwarf_Die *die_mem) +{ + struct __find_variable_param fvp = { .name = name, .addr = addr}; + + return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp, + die_mem); +} + +static int __die_find_member_cb(Dwarf_Die *die_mem, void *data) +{ + const char *name = data; + + if ((dwarf_tag(die_mem) == DW_TAG_member) && + die_compare_name(die_mem, name)) + return DIE_FIND_CB_END; + + return DIE_FIND_CB_SIBLING; +} + +/** + * die_find_member - Find a given name member in a data structure + * @st_die: a data structure type DIE + * @name: member name + * @die_mem: a buffer for result DIE + * + * Find a member DIE called @name in @st_die. + */ +Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name, + Dwarf_Die *die_mem) +{ + return die_find_child(st_die, __die_find_member_cb, (void *)name, + die_mem); +} + +/** + * die_get_typename - Get the name of given variable DIE + * @vr_die: a variable DIE + * @buf: a buffer for result type name + * @len: a max-length of @buf + * + * Get the name of @vr_die and stores it to @buf. Return the actual length + * of type name if succeeded. Return -E2BIG if @len is not enough long, and + * Return -ENOENT if failed to find type name. + * Note that the result will stores typedef name if possible, and stores + * "*(function_type)" if the type is a function pointer. + */ +int die_get_typename(Dwarf_Die *vr_die, char *buf, int len) +{ + Dwarf_Die type; + int tag, ret, ret2; + const char *tmp = ""; + + if (__die_get_real_type(vr_die, &type) == NULL) + return -ENOENT; + + tag = dwarf_tag(&type); + if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type) + tmp = "*"; + else if (tag == DW_TAG_subroutine_type) { + /* Function pointer */ + ret = snprintf(buf, len, "(function_type)"); + return (ret >= len) ? -E2BIG : ret; + } else { + if (!dwarf_diename(&type)) + return -ENOENT; + if (tag == DW_TAG_union_type) + tmp = "union "; + else if (tag == DW_TAG_structure_type) + tmp = "struct "; + /* Write a base name */ + ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type)); + return (ret >= len) ? -E2BIG : ret; + } + ret = die_get_typename(&type, buf, len); + if (ret > 0) { + ret2 = snprintf(buf + ret, len - ret, "%s", tmp); + ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret; + } + return ret; +} + +/** + * die_get_varname - Get the name and type of given variable DIE + * @vr_die: a variable DIE + * @buf: a buffer for type and variable name + * @len: the max-length of @buf + * + * Get the name and type of @vr_die and stores it in @buf as "type\tname". + */ +int die_get_varname(Dwarf_Die *vr_die, char *buf, int len) +{ + int ret, ret2; + + ret = die_get_typename(vr_die, buf, len); + if (ret < 0) { + pr_debug("Failed to get type, make it unknown.\n"); + ret = snprintf(buf, len, "(unknown_type)"); + } + if (ret > 0) { + ret2 = snprintf(buf + ret, len - ret, "\t%s", + dwarf_diename(vr_die)); + ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret; + } + return ret; +} + diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h new file mode 100644 index 000000000000..bc3b21167e70 --- /dev/null +++ b/tools/perf/util/dwarf-aux.h @@ -0,0 +1,100 @@ +#ifndef _DWARF_AUX_H +#define _DWARF_AUX_H +/* + * dwarf-aux.h : libdw auxiliary interfaces + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#include +#include + +/* Find the realpath of the target file */ +extern const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname); + +/* Get DW_AT_comp_dir (should be NULL with older gcc) */ +extern const char *cu_get_comp_dir(Dwarf_Die *cu_die); + +/* Get a line number and file name for given address */ +extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr, + const char **fname, int *lineno); + +/* Compare diename and tname */ +extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname); + +/* Get callsite line number of inline-function instance */ +extern int die_get_call_lineno(Dwarf_Die *in_die); + +/* Get type die */ +extern Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem); + +/* Get a type die, but skip qualifiers and typedef */ +extern Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem); + +/* Check whether the DIE is signed or not */ +extern bool die_is_signed_type(Dwarf_Die *tp_die); + +/* Get data_member_location offset */ +extern int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs); + +/* Return values for die_find_child() callbacks */ +enum { + DIE_FIND_CB_END = 0, /* End of Search */ + DIE_FIND_CB_CHILD = 1, /* Search only children */ + DIE_FIND_CB_SIBLING = 2, /* Search only siblings */ + DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */ +}; + +/* Search child DIEs */ +extern Dwarf_Die *die_find_child(Dwarf_Die *rt_die, + int (*callback)(Dwarf_Die *, void *), + void *data, Dwarf_Die *die_mem); + +/* Search a non-inlined function including given address */ +extern Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, + Dwarf_Die *die_mem); + +/* Search an inlined function including given address */ +extern Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, + Dwarf_Die *die_mem); + +/* Walker on lines (Note: line number will not be sorted) */ +typedef int (* line_walk_callback_t) (const char *fname, int lineno, + Dwarf_Addr addr, void *data); + +/* + * Walk on lines inside given DIE. If the DIE is a subprogram, walk only on + * the lines inside the subprogram, otherwise the DIE must be a CU DIE. + */ +extern int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, + void *data); + +/* Find a variable called 'name' at given address */ +extern Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name, + Dwarf_Addr addr, Dwarf_Die *die_mem); + +/* Find a member called 'name' */ +extern Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name, + Dwarf_Die *die_mem); + +/* Get the name of given variable DIE */ +extern int die_get_typename(Dwarf_Die *vr_die, char *buf, int len); + +/* Get the name and type of given variable DIE, stored as "type\tname" */ +extern int die_get_varname(Dwarf_Die *vr_die, char *buf, int len); +#endif diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index d443b643957f..53d219bddb48 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -222,521 +222,6 @@ static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp, } #endif -/* Dwarf wrappers */ - -/* Find the realpath of the target file. */ -static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname) -{ - Dwarf_Files *files; - size_t nfiles, i; - const char *src = NULL; - int ret; - - if (!fname) - return NULL; - - ret = dwarf_getsrcfiles(cu_die, &files, &nfiles); - if (ret != 0) - return NULL; - - for (i = 0; i < nfiles; i++) { - src = dwarf_filesrc(files, i, NULL, NULL); - if (strtailcmp(src, fname) == 0) - break; - } - if (i == nfiles) - return NULL; - return src; -} - -/* Get DW_AT_comp_dir (should be NULL with older gcc) */ -static const char *cu_get_comp_dir(Dwarf_Die *cu_die) -{ - Dwarf_Attribute attr; - if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL) - return NULL; - return dwarf_formstring(&attr); -} - -/* Get a line number and file name for given address */ -static int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr, - const char **fname, int *lineno) -{ - Dwarf_Line *line; - Dwarf_Addr laddr; - - line = dwarf_getsrc_die(cudie, (Dwarf_Addr)addr); - if (line && dwarf_lineaddr(line, &laddr) == 0 && - addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) { - *fname = dwarf_linesrc(line, NULL, NULL); - if (!*fname) - /* line number is useless without filename */ - *lineno = 0; - } - - return *lineno ?: -ENOENT; -} - -/* Compare diename and tname */ -static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) -{ - const char *name; - name = dwarf_diename(dw_die); - return name ? (strcmp(tname, name) == 0) : false; -} - -/* Get callsite line number of inline-function instance */ -static int die_get_call_lineno(Dwarf_Die *in_die) -{ - Dwarf_Attribute attr; - Dwarf_Word ret; - - if (!dwarf_attr(in_die, DW_AT_call_line, &attr)) - return -ENOENT; - - dwarf_formudata(&attr, &ret); - return (int)ret; -} - -/* Get type die */ -static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) -{ - Dwarf_Attribute attr; - - if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) && - dwarf_formref_die(&attr, die_mem)) - return die_mem; - else - return NULL; -} - -/* Get a type die, but skip qualifiers */ -static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) -{ - int tag; - - do { - vr_die = die_get_type(vr_die, die_mem); - if (!vr_die) - break; - tag = dwarf_tag(vr_die); - } while (tag == DW_TAG_const_type || - tag == DW_TAG_restrict_type || - tag == DW_TAG_volatile_type || - tag == DW_TAG_shared_type); - - return vr_die; -} - -/* Get a type die, but skip qualifiers and typedef */ -static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) -{ - do { - vr_die = __die_get_real_type(vr_die, die_mem); - } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef); - - return vr_die; -} - -static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name, - Dwarf_Word *result) -{ - Dwarf_Attribute attr; - - if (dwarf_attr(tp_die, attr_name, &attr) == NULL || - dwarf_formudata(&attr, result) != 0) - return -ENOENT; - - return 0; -} - -static bool die_is_signed_type(Dwarf_Die *tp_die) -{ - Dwarf_Word ret; - - if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret)) - return false; - - return (ret == DW_ATE_signed_char || ret == DW_ATE_signed || - ret == DW_ATE_signed_fixed); -} - -/* Get data_member_location offset */ -static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs) -{ - Dwarf_Attribute attr; - Dwarf_Op *expr; - size_t nexpr; - int ret; - - if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL) - return -ENOENT; - - if (dwarf_formudata(&attr, offs) != 0) { - /* DW_AT_data_member_location should be DW_OP_plus_uconst */ - ret = dwarf_getlocation(&attr, &expr, &nexpr); - if (ret < 0 || nexpr == 0) - return -ENOENT; - - if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) { - pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n", - expr[0].atom, nexpr); - return -ENOTSUP; - } - *offs = (Dwarf_Word)expr[0].number; - } - return 0; -} - -/* Return values for die_find callbacks */ -enum { - DIE_FIND_CB_END = 0, /* End of Search */ - DIE_FIND_CB_CHILD = 1, /* Search only children */ - DIE_FIND_CB_SIBLING = 2, /* Search only siblings */ - DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */ -}; - -/* Search a child die */ -static Dwarf_Die *die_find_child(Dwarf_Die *rt_die, - int (*callback)(Dwarf_Die *, void *), - void *data, Dwarf_Die *die_mem) -{ - Dwarf_Die child_die; - int ret; - - ret = dwarf_child(rt_die, die_mem); - if (ret != 0) - return NULL; - - do { - ret = callback(die_mem, data); - if (ret == DIE_FIND_CB_END) - return die_mem; - - if ((ret & DIE_FIND_CB_CHILD) && - die_find_child(die_mem, callback, data, &child_die)) { - memcpy(die_mem, &child_die, sizeof(Dwarf_Die)); - return die_mem; - } - } while ((ret & DIE_FIND_CB_SIBLING) && - dwarf_siblingof(die_mem, die_mem) == 0); - - return NULL; -} - -struct __addr_die_search_param { - Dwarf_Addr addr; - Dwarf_Die *die_mem; -}; - -static int __die_search_func_cb(Dwarf_Die *fn_die, void *data) -{ - struct __addr_die_search_param *ad = data; - - if (dwarf_tag(fn_die) == DW_TAG_subprogram && - dwarf_haspc(fn_die, ad->addr)) { - memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die)); - return DWARF_CB_ABORT; - } - return DWARF_CB_OK; -} - -/* Search a real subprogram including this line, */ -static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr, - Dwarf_Die *die_mem) -{ - struct __addr_die_search_param ad; - ad.addr = addr; - ad.die_mem = die_mem; - /* dwarf_getscopes can't find subprogram. */ - if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0)) - return NULL; - else - return die_mem; -} - -/* die_find callback for inline function search */ -static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data) -{ - Dwarf_Addr *addr = data; - - if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine && - dwarf_haspc(die_mem, *addr)) - return DIE_FIND_CB_END; - - return DIE_FIND_CB_CONTINUE; -} - -/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */ -static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, - Dwarf_Die *die_mem) -{ - Dwarf_Die tmp_die; - - sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die); - if (!sp_die) - return NULL; - - /* Inlined function could be recursive. Trace it until fail */ - while (sp_die) { - memcpy(die_mem, sp_die, sizeof(Dwarf_Die)); - sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, - &tmp_die); - } - - return die_mem; -} - -/* Walker on lines (Note: line number will not be sorted) */ -typedef int (* line_walk_handler_t) (const char *fname, int lineno, - Dwarf_Addr addr, void *data); - -struct __line_walk_param { - const char *fname; - line_walk_handler_t handler; - void *data; - int retval; -}; - -static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data) -{ - struct __line_walk_param *lw = data; - Dwarf_Addr addr; - int lineno; - - if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) { - lineno = die_get_call_lineno(in_die); - if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) { - lw->retval = lw->handler(lw->fname, lineno, addr, - lw->data); - if (lw->retval != 0) - return DIE_FIND_CB_END; - } - } - return DIE_FIND_CB_SIBLING; -} - -/* Walk on lines of blocks included in given DIE */ -static int __die_walk_funclines(Dwarf_Die *sp_die, - line_walk_handler_t handler, void *data) -{ - struct __line_walk_param lw = { - .handler = handler, - .data = data, - .retval = 0, - }; - Dwarf_Die die_mem; - Dwarf_Addr addr; - int lineno; - - /* Handle function declaration line */ - lw.fname = dwarf_decl_file(sp_die); - if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 && - dwarf_entrypc(sp_die, &addr) == 0) { - lw.retval = handler(lw.fname, lineno, addr, data); - if (lw.retval != 0) - goto done; - } - die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem); -done: - return lw.retval; -} - -static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data) -{ - struct __line_walk_param *lw = data; - - lw->retval = __die_walk_funclines(sp_die, lw->handler, lw->data); - if (lw->retval != 0) - return DWARF_CB_ABORT; - - return DWARF_CB_OK; -} - -/* - * Walk on lines inside given PDIE. If the PDIE is subprogram, walk only on - * the lines inside the subprogram, otherwise PDIE must be a CU DIE. - */ -static int die_walk_lines(Dwarf_Die *pdie, line_walk_handler_t handler, - void *data) -{ - Dwarf_Lines *lines; - Dwarf_Line *line; - Dwarf_Addr addr; - const char *fname; - int lineno, ret = 0; - Dwarf_Die die_mem, *cu_die; - size_t nlines, i; - - /* Get the CU die */ - if (dwarf_tag(pdie) == DW_TAG_subprogram) - cu_die = dwarf_diecu(pdie, &die_mem, NULL, NULL); - else - cu_die = pdie; - if (!cu_die) { - pr_debug2("Failed to get CU from subprogram\n"); - return -EINVAL; - } - - /* Get lines list in the CU */ - if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) { - pr_debug2("Failed to get source lines on this CU.\n"); - return -ENOENT; - } - pr_debug2("Get %zd lines from this CU\n", nlines); - - /* Walk on the lines on lines list */ - for (i = 0; i < nlines; i++) { - line = dwarf_onesrcline(lines, i); - if (line == NULL || - dwarf_lineno(line, &lineno) != 0 || - dwarf_lineaddr(line, &addr) != 0) { - pr_debug2("Failed to get line info. " - "Possible error in debuginfo.\n"); - continue; - } - /* Filter lines based on address */ - if (pdie != cu_die) - /* - * Address filtering - * The line is included in given function, and - * no inline block includes it. - */ - if (!dwarf_haspc(pdie, addr) || - die_find_inlinefunc(pdie, addr, &die_mem)) - continue; - /* Get source line */ - fname = dwarf_linesrc(line, NULL, NULL); - - ret = handler(fname, lineno, addr, data); - if (ret != 0) - return ret; - } - - /* - * Dwarf lines doesn't include function declarations and inlined - * subroutines. We have to check functions list or given function. - */ - if (pdie != cu_die) - ret = __die_walk_funclines(pdie, handler, data); - else { - struct __line_walk_param param = { - .handler = handler, - .data = data, - .retval = 0, - }; - dwarf_getfuncs(cu_die, __die_walk_culines_cb, ¶m, 0); - ret = param.retval; - } - - return ret; -} - -struct __find_variable_param { - const char *name; - Dwarf_Addr addr; -}; - -static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) -{ - struct __find_variable_param *fvp = data; - int tag; - - tag = dwarf_tag(die_mem); - if ((tag == DW_TAG_formal_parameter || - tag == DW_TAG_variable) && - die_compare_name(die_mem, fvp->name)) - return DIE_FIND_CB_END; - - if (dwarf_haspc(die_mem, fvp->addr)) - return DIE_FIND_CB_CONTINUE; - else - return DIE_FIND_CB_SIBLING; -} - -/* Find a variable called 'name' at given address */ -static Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name, - Dwarf_Addr addr, Dwarf_Die *die_mem) -{ - struct __find_variable_param fvp = { .name = name, .addr = addr}; - - return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp, - die_mem); -} - -static int __die_find_member_cb(Dwarf_Die *die_mem, void *data) -{ - const char *name = data; - - if ((dwarf_tag(die_mem) == DW_TAG_member) && - die_compare_name(die_mem, name)) - return DIE_FIND_CB_END; - - return DIE_FIND_CB_SIBLING; -} - -/* Find a member called 'name' */ -static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name, - Dwarf_Die *die_mem) -{ - return die_find_child(st_die, __die_find_member_cb, (void *)name, - die_mem); -} - -/* Get the name of given variable DIE */ -static int die_get_typename(Dwarf_Die *vr_die, char *buf, int len) -{ - Dwarf_Die type; - int tag, ret, ret2; - const char *tmp = ""; - - if (__die_get_real_type(vr_die, &type) == NULL) - return -ENOENT; - - tag = dwarf_tag(&type); - if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type) - tmp = "*"; - else if (tag == DW_TAG_subroutine_type) { - /* Function pointer */ - ret = snprintf(buf, len, "(function_type)"); - return (ret >= len) ? -E2BIG : ret; - } else { - if (!dwarf_diename(&type)) - return -ENOENT; - if (tag == DW_TAG_union_type) - tmp = "union "; - else if (tag == DW_TAG_structure_type) - tmp = "struct "; - /* Write a base name */ - ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type)); - return (ret >= len) ? -E2BIG : ret; - } - ret = die_get_typename(&type, buf, len); - if (ret > 0) { - ret2 = snprintf(buf + ret, len - ret, "%s", tmp); - ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret; - } - return ret; -} - -/* Get the name and type of given variable DIE, stored as "type\tname" */ -static int die_get_varname(Dwarf_Die *vr_die, char *buf, int len) -{ - int ret, ret2; - - ret = die_get_typename(vr_die, buf, len); - if (ret < 0) { - pr_debug("Failed to get type, make it unknown.\n"); - ret = snprintf(buf, len, "(unknown_type)"); - } - if (ret > 0) { - ret2 = snprintf(buf + ret, len - ret, "\t%s", - dwarf_diename(vr_die)); - ret = (ret2 >= len - ret) ? -E2BIG : ret2 + ret; - } - return ret; -} - /* * Probe finder related functions */ @@ -1206,8 +691,7 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf) /* If no real subprogram, find a real one */ if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) { - sp_die = die_find_real_subprogram(&pf->cu_die, - pf->addr, &die_mem); + sp_die = die_find_realfunc(&pf->cu_die, pf->addr, &die_mem); if (!sp_die) { pr_warning("Failed to find probe point in any " "functions.\n"); @@ -1768,7 +1252,7 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt) /* Don't care whether it failed or not */ /* Find a corresponding function (name, baseline and baseaddr) */ - if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { + if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) { /* Get function entry information */ tmp = dwarf_diename(&spdie); if (!tmp || diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 605730a366db..0f1ed3d25a20 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -32,11 +32,7 @@ extern int find_line_range(int fd, struct line_range *lr); extern int find_available_vars_at(int fd, struct perf_probe_event *pev, struct variable_list **vls, int max_points, bool externs); - -#include -#include -#include -#include +#include "dwarf-aux.h" struct probe_finder { struct perf_probe_event *pev; /* Target probe event */ -- cgit v1.2.3 From ff741783506c340035659a71be68ddb4068760d1 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 27 Jun 2011 16:27:39 +0900 Subject: perf probe: Introduce debuginfo to encapsulate dwarf information Introduce debuginfo to encapsulate dwarf information. This new object allows us to reuse and expand debuginfo easily. Signed-off-by: Masami Hiramatsu Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/r/20110627072739.6528.12438.stgit@fedora15 Signed-off-by: Steven Rostedt --- tools/perf/util/probe-event.c | 78 ++++++++++------ tools/perf/util/probe-finder.c | 201 +++++++++++++++++++++-------------------- tools/perf/util/probe-finder.h | 39 ++++++-- 3 files changed, 182 insertions(+), 136 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index f0223166e761..920c1957d6d3 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -170,16 +170,17 @@ const char *kernel_get_module_path(const char *module) } #ifdef DWARF_SUPPORT -static int open_vmlinux(const char *module) +/* Open new debuginfo of given module */ +static struct debuginfo *open_debuginfo(const char *module) { const char *path = kernel_get_module_path(module); + if (!path) { pr_err("Failed to find path of %s module.\n", module ?: "kernel"); - return -ENOENT; + return NULL; } - pr_debug("Try to open %s\n", path); - return open(path, O_RDONLY); + return debuginfo__new(path); } /* @@ -193,13 +194,24 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, struct map *map; u64 addr; int ret = -ENOENT; + struct debuginfo *dinfo; sym = __find_kernel_function_by_name(tp->symbol, &map); if (sym) { addr = map->unmap_ip(map, sym->start + tp->offset); pr_debug("try to find %s+%ld@%" PRIx64 "\n", tp->symbol, tp->offset, addr); - ret = find_perf_probe_point((unsigned long)addr, pp); + + dinfo = debuginfo__new_online_kernel(addr); + if (dinfo) { + ret = debuginfo__find_probe_point(dinfo, + (unsigned long)addr, pp); + debuginfo__delete(dinfo); + } else { + pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n", + addr); + ret = -ENOENT; + } } if (ret <= 0) { pr_debug("Failed to find corresponding probes from " @@ -220,20 +232,22 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, int max_tevs, const char *module) { bool need_dwarf = perf_probe_event_need_dwarf(pev); - int fd, ntevs; + struct debuginfo *dinfo = open_debuginfo(module); + int ntevs; - fd = open_vmlinux(module); - if (fd < 0) { + if (!dinfo) { if (need_dwarf) { pr_warning("Failed to open debuginfo file.\n"); - return fd; + return -ENOENT; } - pr_debug("Could not open vmlinux. Try to use symbols.\n"); + pr_debug("Could not open debuginfo. Try to use symbols.\n"); return 0; } - /* Searching trace events corresponding to probe event */ - ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); + /* Searching trace events corresponding to a probe event */ + ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs); + + debuginfo__delete(dinfo); if (ntevs > 0) { /* Succeeded to find trace events */ pr_debug("find %d probe_trace_events.\n", ntevs); @@ -371,8 +385,9 @@ int show_line_range(struct line_range *lr, const char *module) { int l = 1; struct line_node *ln; + struct debuginfo *dinfo; FILE *fp; - int fd, ret; + int ret; char *tmp; /* Search a line range */ @@ -380,13 +395,14 @@ int show_line_range(struct line_range *lr, const char *module) if (ret < 0) return ret; - fd = open_vmlinux(module); - if (fd < 0) { + dinfo = open_debuginfo(module); + if (!dinfo) { pr_warning("Failed to open debuginfo file.\n"); - return fd; + return -ENOENT; } - ret = find_line_range(fd, lr); + ret = debuginfo__find_line_range(dinfo, lr); + debuginfo__delete(dinfo); if (ret == 0) { pr_warning("Specified source line is not found.\n"); return -ENOENT; @@ -448,7 +464,8 @@ end: return ret; } -static int show_available_vars_at(int fd, struct perf_probe_event *pev, +static int show_available_vars_at(struct debuginfo *dinfo, + struct perf_probe_event *pev, int max_vls, struct strfilter *_filter, bool externs) { @@ -463,7 +480,8 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev, return -EINVAL; pr_debug("Searching variables at %s\n", buf); - ret = find_available_vars_at(fd, pev, &vls, max_vls, externs); + ret = debuginfo__find_available_vars_at(dinfo, pev, &vls, + max_vls, externs); if (ret <= 0) { pr_err("Failed to find variables at %s (%d)\n", buf, ret); goto end; @@ -504,24 +522,26 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, int max_vls, const char *module, struct strfilter *_filter, bool externs) { - int i, fd, ret = 0; + int i, ret = 0; + struct debuginfo *dinfo; ret = init_vmlinux(); if (ret < 0) return ret; + dinfo = open_debuginfo(module); + if (!dinfo) { + pr_warning("Failed to open debuginfo file.\n"); + return -ENOENT; + } + setup_pager(); - for (i = 0; i < npevs && ret >= 0; i++) { - fd = open_vmlinux(module); - if (fd < 0) { - pr_warning("Failed to open debug information file.\n"); - ret = fd; - break; - } - ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter, + for (i = 0; i < npevs && ret >= 0; i++) + ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter, externs); - } + + debuginfo__delete(dinfo); return ret; } diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 53d219bddb48..3e44a3e36519 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -116,29 +116,37 @@ static const Dwfl_Callbacks offline_callbacks = { }; /* Get a Dwarf from offline image */ -static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias) +static int debuginfo__init_offline_dwarf(struct debuginfo *self, + const char *path) { Dwfl_Module *mod; - Dwarf *dbg = NULL; + int fd; - if (!dwflp) - return NULL; + fd = open(path, O_RDONLY); + if (fd < 0) + return fd; - *dwflp = dwfl_begin(&offline_callbacks); - if (!*dwflp) - return NULL; + self->dwfl = dwfl_begin(&offline_callbacks); + if (!self->dwfl) + goto error; - mod = dwfl_report_offline(*dwflp, "", "", fd); + mod = dwfl_report_offline(self->dwfl, "", "", fd); if (!mod) goto error; - dbg = dwfl_module_getdwarf(mod, bias); - if (!dbg) { + self->dbg = dwfl_module_getdwarf(mod, &self->bias); + if (!self->dbg) + goto error; + + return 0; error: - dwfl_end(*dwflp); - *dwflp = NULL; - } - return dbg; + if (self->dwfl) + dwfl_end(self->dwfl); + else + close(fd); + memset(self, 0, sizeof(*self)); + + return -ENOENT; } #if _ELFUTILS_PREREQ(0, 148) @@ -174,53 +182,82 @@ static const Dwfl_Callbacks kernel_callbacks = { }; /* Get a Dwarf from live kernel image */ -static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp, - Dwarf_Addr *bias) +static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, + Dwarf_Addr addr) { - Dwarf *dbg; - - if (!dwflp) - return NULL; - - *dwflp = dwfl_begin(&kernel_callbacks); - if (!*dwflp) - return NULL; + self->dwfl = dwfl_begin(&kernel_callbacks); + if (!self->dwfl) + return -EINVAL; /* Load the kernel dwarves: Don't care the result here */ - dwfl_linux_kernel_report_kernel(*dwflp); - dwfl_linux_kernel_report_modules(*dwflp); + dwfl_linux_kernel_report_kernel(self->dwfl); + dwfl_linux_kernel_report_modules(self->dwfl); - dbg = dwfl_addrdwarf(*dwflp, addr, bias); + self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias); /* Here, check whether we could get a real dwarf */ - if (!dbg) { + if (!self->dbg) { pr_debug("Failed to find kernel dwarf at %lx\n", (unsigned long)addr); - dwfl_end(*dwflp); - *dwflp = NULL; + dwfl_end(self->dwfl); + memset(self, 0, sizeof(*self)); + return -ENOENT; } - return dbg; + + return 0; } #else /* With older elfutils, this just support kernel module... */ -static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp, - Dwarf_Addr *bias) +static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self, + Dwarf_Addr addr __used) { - int fd; const char *path = kernel_get_module_path("kernel"); if (!path) { pr_err("Failed to find vmlinux path\n"); - return NULL; + return -ENOENT; } pr_debug2("Use file %s for debuginfo\n", path); - fd = open(path, O_RDONLY); - if (fd < 0) + return debuginfo__init_offline_dwarf(self, path); +} +#endif + +struct debuginfo *debuginfo__new(const char *path) +{ + struct debuginfo *self = zalloc(sizeof(struct debuginfo)); + if (!self) return NULL; - return dwfl_init_offline_dwarf(fd, dwflp, bias); + if (debuginfo__init_offline_dwarf(self, path) < 0) { + free(self); + self = NULL; + } + + return self; +} + +struct debuginfo *debuginfo__new_online_kernel(unsigned long addr) +{ + struct debuginfo *self = zalloc(sizeof(struct debuginfo)); + if (!self) + return NULL; + + if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) { + free(self); + self = NULL; + } + + return self; +} + +void debuginfo__delete(struct debuginfo *self) +{ + if (self) { + if (self->dwfl) + dwfl_end(self->dwfl); + free(self); + } } -#endif /* * Probe finder related functions @@ -949,28 +986,18 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data) } /* Find probe points from debuginfo */ -static int find_probes(int fd, struct probe_finder *pf) +static int debuginfo__find_probes(struct debuginfo *self, + struct probe_finder *pf) { struct perf_probe_point *pp = &pf->pev->point; Dwarf_Off off, noff; size_t cuhl; Dwarf_Die *diep; - Dwarf *dbg = NULL; - Dwfl *dwfl; - Dwarf_Addr bias; /* Currently ignored */ int ret = 0; - dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); - if (!dbg) { - pr_warning("No debug information found in the vmlinux - " - "please rebuild with CONFIG_DEBUG_INFO=y.\n"); - close(fd); /* Without dwfl_end(), fd isn't closed. */ - return -EBADF; - } - #if _ELFUTILS_PREREQ(0, 142) /* Get the call frame information from this dwarf */ - pf->cfi = dwarf_getcfi(dbg); + pf->cfi = dwarf_getcfi(self->dbg); #endif off = 0; @@ -989,7 +1016,8 @@ static int find_probes(int fd, struct probe_finder *pf) .data = pf, }; - dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); + dwarf_getpubnames(self->dbg, pubname_search_cb, + &pubname_param, 0); if (pubname_param.found) { ret = probe_point_search_cb(&pf->sp_die, &probe_param); if (ret) @@ -998,9 +1026,9 @@ static int find_probes(int fd, struct probe_finder *pf) } /* Loop on CUs (Compilation Unit) */ - while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { + while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { /* Get the DIE(Debugging Information Entry) of this CU */ - diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die); + diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die); if (!diep) continue; @@ -1027,8 +1055,6 @@ static int find_probes(int fd, struct probe_finder *pf) found: line_list__free(&pf->lcache); - if (dwfl) - dwfl_end(dwfl); return ret; } @@ -1074,8 +1100,9 @@ static int add_probe_trace_event(Dwarf_Die *sp_die, struct probe_finder *pf) } /* Find probe_trace_events specified by perf_probe_event from debuginfo */ -int find_probe_trace_events(int fd, struct perf_probe_event *pev, - struct probe_trace_event **tevs, int max_tevs) +int debuginfo__find_trace_events(struct debuginfo *self, + struct perf_probe_event *pev, + struct probe_trace_event **tevs, int max_tevs) { struct trace_event_finder tf = { .pf = {.pev = pev, .callback = add_probe_trace_event}, @@ -1090,7 +1117,7 @@ int find_probe_trace_events(int fd, struct perf_probe_event *pev, tf.tevs = *tevs; tf.ntevs = 0; - ret = find_probes(fd, &tf.pf); + ret = debuginfo__find_probes(self, &tf.pf); if (ret < 0) { free(*tevs); *tevs = NULL; @@ -1184,9 +1211,10 @@ out: } /* Find available variables at given probe point */ -int find_available_vars_at(int fd, struct perf_probe_event *pev, - struct variable_list **vls, int max_vls, - bool externs) +int debuginfo__find_available_vars_at(struct debuginfo *self, + struct perf_probe_event *pev, + struct variable_list **vls, + int max_vls, bool externs) { struct available_var_finder af = { .pf = {.pev = pev, .callback = add_available_vars}, @@ -1201,7 +1229,7 @@ int find_available_vars_at(int fd, struct perf_probe_event *pev, af.vls = *vls; af.nvls = 0; - ret = find_probes(fd, &af.pf); + ret = debuginfo__find_probes(self, &af.pf); if (ret < 0) { /* Free vlist for error */ while (af.nvls--) { @@ -1219,28 +1247,19 @@ int find_available_vars_at(int fd, struct perf_probe_event *pev, } /* Reverse search */ -int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt) +int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr, + struct perf_probe_point *ppt) { Dwarf_Die cudie, spdie, indie; - Dwarf *dbg = NULL; - Dwfl *dwfl = NULL; - Dwarf_Addr _addr, baseaddr, bias = 0; + Dwarf_Addr _addr, baseaddr; const char *fname = NULL, *func = NULL, *tmp; int baseline = 0, lineno = 0, ret = 0; - /* Open the live linux kernel */ - dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); - if (!dbg) { - pr_warning("No debug information found in the vmlinux - " - "please rebuild with CONFIG_DEBUG_INFO=y.\n"); - ret = -EINVAL; - goto end; - } - /* Adjust address with bias */ - addr += bias; + addr += self->bias; + /* Find cu die */ - if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) { + if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) { pr_warning("Failed to find debug information for address %lx\n", addr); ret = -EINVAL; @@ -1316,8 +1335,6 @@ post: } } end: - if (dwfl) - dwfl_end(dwfl); if (ret == 0 && (fname || func)) ret = 1; /* Found a point */ return ret; @@ -1427,26 +1444,15 @@ static int find_line_range_by_func(struct line_finder *lf) return param.retval; } -int find_line_range(int fd, struct line_range *lr) +int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr) { struct line_finder lf = {.lr = lr, .found = 0}; int ret = 0; Dwarf_Off off = 0, noff; size_t cuhl; Dwarf_Die *diep; - Dwarf *dbg = NULL; - Dwfl *dwfl; - Dwarf_Addr bias; /* Currently ignored */ const char *comp_dir; - dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); - if (!dbg) { - pr_warning("No debug information found in the vmlinux - " - "please rebuild with CONFIG_DEBUG_INFO=y.\n"); - close(fd); /* Without dwfl_end(), fd isn't closed. */ - return -EBADF; - } - /* Fastpath: lookup by function name from .debug_pubnames section */ if (lr->function) { struct pubname_callback_param pubname_param = { @@ -1455,7 +1461,8 @@ int find_line_range(int fd, struct line_range *lr) struct dwarf_callback_param line_range_param = { .data = (void *)&lf, .retval = 0}; - dwarf_getpubnames(dbg, pubname_search_cb, &pubname_param, 0); + dwarf_getpubnames(self->dbg, pubname_search_cb, + &pubname_param, 0); if (pubname_param.found) { line_range_search_cb(&lf.sp_die, &line_range_param); if (lf.found) @@ -1465,11 +1472,12 @@ int find_line_range(int fd, struct line_range *lr) /* Loop on CUs (Compilation Unit) */ while (!lf.found && ret >= 0) { - if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) + if (dwarf_nextcu(self->dbg, off, &noff, &cuhl, + NULL, NULL, NULL) != 0) break; /* Get the DIE(Debugging Information Entry) of this CU */ - diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die); + diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die); if (!diep) continue; @@ -1503,7 +1511,6 @@ found: } pr_debug("path: %s\n", lr->path); - dwfl_end(dwfl); return (ret < 0) ? ret : lf.found; } diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 0f1ed3d25a20..c478b42a2473 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -16,23 +16,42 @@ static inline int is_c_varname(const char *name) } #ifdef DWARF_SUPPORT + +#include "dwarf-aux.h" + +/* TODO: export debuginfo data structure even if no dwarf support */ + +/* debug information structure */ +struct debuginfo { + Dwarf *dbg; + Dwfl *dwfl; + Dwarf_Addr bias; +}; + +extern struct debuginfo *debuginfo__new(const char *path); +extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr); +extern void debuginfo__delete(struct debuginfo *self); + /* Find probe_trace_events specified by perf_probe_event from debuginfo */ -extern int find_probe_trace_events(int fd, struct perf_probe_event *pev, - struct probe_trace_event **tevs, - int max_tevs); +extern int debuginfo__find_trace_events(struct debuginfo *self, + struct perf_probe_event *pev, + struct probe_trace_event **tevs, + int max_tevs); /* Find a perf_probe_point from debuginfo */ -extern int find_perf_probe_point(unsigned long addr, - struct perf_probe_point *ppt); +extern int debuginfo__find_probe_point(struct debuginfo *self, + unsigned long addr, + struct perf_probe_point *ppt); /* Find a line range */ -extern int find_line_range(int fd, struct line_range *lr); +extern int debuginfo__find_line_range(struct debuginfo *self, + struct line_range *lr); /* Find available variables */ -extern int find_available_vars_at(int fd, struct perf_probe_event *pev, - struct variable_list **vls, int max_points, - bool externs); -#include "dwarf-aux.h" +extern int debuginfo__find_available_vars_at(struct debuginfo *self, + struct perf_probe_event *pev, + struct variable_list **vls, + int max_points, bool externs); struct probe_finder { struct perf_probe_event *pev; /* Target probe event */ -- cgit v1.2.3 From 190b57fcb9c5fed5414935a174094f534fc510bc Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 27 Jun 2011 16:27:45 +0900 Subject: perf probe: Add probed module in front of function Add probed module name and ":" in front of function name if -m module option is given. In the result, the symbol name passed to kprobe-tracer becomes MODULE:FUNCTION, so that kallsyms can solve it as a symbol in the module correctly. Signed-off-by: Masami Hiramatsu Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/r/20110627072745.6528.26416.stgit@fedora15 Signed-off-by: Steven Rostedt --- tools/perf/util/probe-event.c | 47 ++++++++++++++++++++++++++++++++++--------- tools/perf/util/probe-event.h | 1 + 2 files changed, 39 insertions(+), 9 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 920c1957d6d3..ee3f41eec5c1 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -226,14 +226,26 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, return 0; } +static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, + int ntevs, const char *module) +{ + int i; + for (i = 0; i < ntevs; i++) { + tevs[i].point.module = strdup(module); + if (!tevs[i].point.module) + return -ENOMEM; + } + return 0; +} + /* Try to find perf_probe_event with debuginfo */ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, - struct probe_trace_event **tevs, - int max_tevs, const char *module) + struct probe_trace_event **tevs, + int max_tevs, const char *module) { bool need_dwarf = perf_probe_event_need_dwarf(pev); struct debuginfo *dinfo = open_debuginfo(module); - int ntevs; + int ntevs, ret = 0; if (!dinfo) { if (need_dwarf) { @@ -251,7 +263,10 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, if (ntevs > 0) { /* Succeeded to find trace events */ pr_debug("find %d probe_trace_events.\n", ntevs); - return ntevs; + if (module) + ret = add_module_to_probe_trace_events(*tevs, ntevs, + module); + return ret < 0 ? ret : ntevs; } if (ntevs == 0) { /* No error but failed to find probe point. */ @@ -1010,7 +1025,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) /* Parse probe_events event into struct probe_point */ static int parse_probe_trace_command(const char *cmd, - struct probe_trace_event *tev) + struct probe_trace_event *tev) { struct probe_trace_point *tp = &tev->point; char pr; @@ -1043,8 +1058,14 @@ static int parse_probe_trace_command(const char *cmd, tp->retprobe = (pr == 'r'); - /* Scan function name and offset */ - ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol, + /* Scan module name(if there), function name and offset */ + p = strchr(argv[1], ':'); + if (p) { + tp->module = strndup(argv[1], p - argv[1]); + p++; + } else + p = argv[1]; + ret = sscanf(p, "%a[^+]+%lu", (float *)(void *)&tp->symbol, &tp->offset); if (ret == 1) tp->offset = 0; @@ -1289,9 +1310,10 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev) if (buf == NULL) return NULL; - len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu", + len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s%s%s+%lu", tp->retprobe ? 'r' : 'p', tev->group, tev->event, + tp->module ?: "", tp->module ? ":" : "", tp->symbol, tp->offset); if (len <= 0) goto error; @@ -1398,6 +1420,8 @@ static void clear_probe_trace_event(struct probe_trace_event *tev) free(tev->group); if (tev->point.symbol) free(tev->point.symbol); + if (tev->point.module) + free(tev->point.module); for (i = 0; i < tev->nargs; i++) { if (tev->args[i].name) free(tev->args[i].name); @@ -1749,7 +1773,7 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, /* Convert perf_probe_event with debuginfo */ ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module); if (ret != 0) - return ret; + return ret; /* Found in debuginfo or got an error */ /* Allocate trace event buffer */ tev = *tevs = zalloc(sizeof(struct probe_trace_event)); @@ -1762,6 +1786,11 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, ret = -ENOMEM; goto error; } + tev->point.module = strdup(module); + if (tev->point.module == NULL) { + ret = -ENOMEM; + goto error; + } tev->point.offset = pev->point.offset; tev->point.retprobe = pev->point.retprobe; 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; /* kprobe-tracer tracing point */ struct probe_trace_point { char *symbol; /* Base symbol */ + char *module; /* Module name */ unsigned long offset; /* Offset from symbol */ bool retprobe; /* Return probe flag */ }; -- cgit v1.2.3 From 14a8fd7ceea6915c613746203d6e9a2bf273f16c Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 27 Jun 2011 16:27:51 +0900 Subject: perf probe: Support adding probes on offline kernel modules Support adding probes on offline kernel modules. This enables perf-probe to trace kernel-module init functions via perf-probe. If user gives the path of module with -m option, perf-probe expects the module is offline. This feature works with --add, --funcs, and --vars. E.g) # perf probe -m /lib/modules/`uname -r`/kernel/fs/btrfs/btrfs.ko \ -a "extent_io_init:5 extent_state_cache" Add new events: probe:extent_io_init (on extent_io_init:5 with extent_state_cache) probe:extent_io_init_1 (on extent_io_init:5 with extent_state_cache) You can now use it on all perf tools, such as: perf record -e probe:extent_io_init_1 -aR sleep 1 Signed-off-by: Masami Hiramatsu Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Ingo Molnar Cc: Arnaldo Carvalho de Melo Link: http://lkml.kernel.org/r/20110627072751.6528.10230.stgit@fedora15 Signed-off-by: Steven Rostedt --- tools/perf/Documentation/perf-probe.txt | 6 ++-- tools/perf/builtin-probe.c | 3 +- tools/perf/util/probe-event.c | 52 +++++++++++++++++++++++++++------ 3 files changed, 49 insertions(+), 12 deletions(-) (limited to 'tools') 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 Specify vmlinux path which has debuginfo (Dwarf binary). -m:: ---module=MODNAME:: +--module=MODNAME|PATH:: Specify module name in which perf-probe searches probe points - or lines. + or lines. If a path of module file is passed, perf-probe + treat it as an offline module (this means you can add a probe on + a module which has not been loaded yet). -s:: --source=PATH:: diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 2c0e64d0b4aa..5f2a5c7046df 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -242,7 +242,8 @@ static const struct option options[] = { OPT_STRING('s', "source", &symbol_conf.source_prefix, "directory", "path to kernel source"), OPT_STRING('m', "module", ¶ms.target_module, - "modname", "target module name"), + "modname|path", + "target module name (for online) or path (for offline)"), #endif OPT__DRY_RUN(&probe_event_dry_run), OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index ee3f41eec5c1..b82d54fa2c56 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) struct rb_node *nd; struct map_groups *grp = &machine.kmaps; + /* A file path -- this is an offline module */ + if (module && strchr(module, '/')) + return machine__new_module(&machine, 0, module); + if (!module) module = "kernel"; @@ -173,12 +177,19 @@ const char *kernel_get_module_path(const char *module) /* Open new debuginfo of given module */ static struct debuginfo *open_debuginfo(const char *module) { - const char *path = kernel_get_module_path(module); + const char *path; - if (!path) { - pr_err("Failed to find path of %s module.\n", - module ?: "kernel"); - return NULL; + /* A file path -- this is an offline module */ + if (module && strchr(module, '/')) + path = module; + else { + path = kernel_get_module_path(module); + + if (!path) { + pr_err("Failed to find path of %s module.\n", + module ?: "kernel"); + return NULL; + } } return debuginfo__new(path); } @@ -229,13 +240,36 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, int ntevs, const char *module) { - int i; + int i, ret = 0; + char *tmp; + + if (!module) + return 0; + + tmp = strrchr(module, '/'); + if (tmp) { + /* This is a module path -- get the module name */ + module = strdup(tmp + 1); + if (!module) + return -ENOMEM; + tmp = strchr(module, '.'); + if (tmp) + *tmp = '\0'; + tmp = (char *)module; /* For free() */ + } + for (i = 0; i < ntevs; i++) { tevs[i].point.module = strdup(module); - if (!tevs[i].point.module) - return -ENOMEM; + if (!tevs[i].point.module) { + ret = -ENOMEM; + break; + } } - return 0; + + if (tmp) + free(tmp); + + return ret; } /* Try to find perf_probe_event with debuginfo */ -- cgit v1.2.3 From 4c4ab1204fe4e201ece94c3062aa6b5eed670457 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 15 Jul 2011 21:16:17 -0400 Subject: ktest: Add test type make_min_config After doing a make localyesconfig, your kernel configuration may not be the most useful minimum configuration. Having a true minimum config that you can use against other configs is very useful if someone else has a config that breaks on your code. By only forcing those configurations that are truly required to boot your machine will give you less of a chance that one of your set configurations will make the bug go away. This will give you a better chance to be able to reproduce the reported bug matching the broken config. Note, this does take some time, and may require you to run the test over night, or perhaps over the weekend. But it also allows you to interrupt it, and gives you the current minimum config that was found till that time. Note, this test automatically assumes a BUILD_TYPE of oldconfig and its test type acts like boot. TODO: add a test version that makes the config do more than just boot, like having network access. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 255 +++++++++++++++++++++++++++++++++++++++- tools/testing/ktest/sample.conf | 50 ++++++++ 2 files changed, 301 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 6166f3a0f2ea..5323c6f9bf9b 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -86,6 +86,9 @@ my $make; my $post_install; my $noclean; my $minconfig; +my $start_minconfig; +my $output_minconfig; +my $ignore_config; my $addconfig; my $in_bisect = 0; my $bisect_bad = ""; @@ -1189,7 +1192,11 @@ sub apply_min_config { sub make_oldconfig { - apply_min_config; + my @force_list = keys %force_config; + + if ($#force_list >= 0) { + apply_min_config; + } if (!run_command "$make oldnoconfig") { # Perhaps oldnoconfig doesn't exist in this version of the kernel @@ -1678,21 +1685,27 @@ my %null_config; my %dependency; -sub process_config_ignore { - my ($config) = @_; +sub assign_configs { + my ($hash, $config) = @_; open (IN, $config) or dodie "Failed to read $config"; while () { if (/^((CONFIG\S*)=.*)/) { - $config_ignore{$2} = $1; + ${$hash}{$2} = $1; } } close(IN); } +sub process_config_ignore { + my ($config) = @_; + + assign_configs \%config_ignore, $config; +} + sub read_current_config { my ($config_ref) = @_; @@ -2149,6 +2162,226 @@ sub patchcheck { return 1; } +sub read_config_list { + my ($config) = @_; + + open (IN, $config) + or dodie "Failed to read $config"; + + while () { + if (/^((CONFIG\S*)=.*)/) { + if (!defined($config_ignore{$2})) { + $config_list{$2} = $1; + } + } + } + + close(IN); +} + +sub read_output_config { + my ($config) = @_; + + assign_configs \%config_ignore, $config; +} + +sub make_new_config { + my @configs = @_; + + open (OUT, ">$output_config") + or dodie "Failed to write $output_config"; + + foreach my $config (@configs) { + print OUT "$config\n"; + } + close OUT; +} + +sub make_min_config { + my ($i) = @_; + + if (!defined($output_minconfig)) { + fail "OUTPUT_MIN_CONFIG not defined" and return; + } + if (!defined($start_minconfig)) { + fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; + } + + # First things first. We build an allnoconfig to find + # out what the defaults are that we can't touch. + # Some are selections, but we really can't handle selections. + + my $save_minconfig = $minconfig; + undef $minconfig; + + run_command "$make allnoconfig" or return 0; + + process_config_ignore $output_config; + my %keep_configs; + + if (defined($ignore_config)) { + # make sure the file exists + `touch $ignore_config`; + assign_configs \%keep_configs, $ignore_config; + } + + doprint "Load initial configs from $start_minconfig\n"; + + # Look at the current min configs, and save off all the + # ones that were set via the allnoconfig + my %min_configs; + assign_configs \%min_configs, $start_minconfig; + + my @config_keys = keys %min_configs; + + # Remove anything that was set by the make allnoconfig + # we shouldn't need them as they get set for us anyway. + foreach my $config (@config_keys) { + # Remove anything in the ignore_config + if (defined($keep_configs{$config})) { + my $file = $ignore_config; + $file =~ s,.*/(.*?)$,$1,; + doprint "$config set by $file ... ignored\n"; + delete $min_configs{$config}; + next; + } + # But make sure the settings are the same. If a min config + # sets a selection, we do not want to get rid of it if + # it is not the same as what we have. Just move it into + # the keep configs. + if (defined($config_ignore{$config})) { + if ($config_ignore{$config} ne $min_configs{$config}) { + doprint "$config is in allnoconfig as '$config_ignore{$config}'"; + doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n"; + $keep_configs{$config} = $min_configs{$config}; + } else { + doprint "$config set by allnoconfig ... ignored\n"; + } + delete $min_configs{$config}; + } + } + + my %nochange_config; + + my $done = 0; + + while (!$done) { + + my $config; + my $found; + + # Now disable each config one by one and do a make oldconfig + # till we find a config that changes our list. + + # Put configs that did not modify the config at the end. + my @test_configs = keys %min_configs; + my $reset = 1; + for (my $i = 0; $i < $#test_configs; $i++) { + if (!defined($nochange_config{$test_configs[0]})) { + $reset = 0; + last; + } + # This config didn't change the .config last time. + # Place it at the end + my $config = shift @test_configs; + push @test_configs, $config; + } + + # if every test config has failed to modify the .config file + # in the past, then reset and start over. + if ($reset) { + undef %nochange_config; + } + + foreach my $config (@test_configs) { + + # Remove this config from the list of configs + # do a make oldnoconfig and then read the resulting + # .config to make sure it is missing the config that + # we had before + my %configs = %min_configs; + delete $configs{$config}; + make_new_config ((values %configs), (values %keep_configs)); + make_oldconfig; + undef %configs; + assign_configs \%configs, $output_config; + + if (!defined($configs{$config})) { + $found = $config; + last; + } + + doprint "disabling config $config did not change .config\n"; + + # oh well, try another config + $nochange_config{$config} = 1; + } + + if (!defined($found)) { + doprint "No more configs found that we can disable\n"; + $done = 1; + last; + } + + $config = $found; + + doprint "Test with $config disabled\n"; + + # set in_bisect to keep build and monitor from dieing + $in_bisect = 1; + + my $failed = 0; + build "oldconfig"; + start_monitor_and_boot or $failed = 1; + end_monitor; + + $in_bisect = 0; + + if ($failed) { + doprint "$config is needed to boot the box... keeping\n"; + # this config is needed, add it to the ignore list. + $keep_configs{$config} = $min_configs{$config}; + delete $min_configs{$config}; + } else { + # We booted without this config, remove it from the minconfigs. + doprint "$config is not needed, disabling\n"; + + delete $min_configs{$config}; + + # Also disable anything that is not enabled in this config + my %configs; + assign_configs \%configs, $output_config; + my @config_keys = keys %min_configs; + foreach my $config (@config_keys) { + if (!defined($configs{$config})) { + doprint "$config is not set, disabling\n"; + delete $min_configs{$config}; + } + } + + # Save off all the current mandidory configs + open (OUT, ">$output_minconfig") + or die "Can't write to $output_minconfig"; + foreach my $config (keys %keep_configs) { + print OUT "$keep_configs{$config}\n"; + } + foreach my $config (keys %min_configs) { + print OUT "$min_configs{$config}\n"; + } + close OUT; + } + + doprint "Reboot and wait $sleep_time seconds\n"; + reboot; + start_monitor; + wait_for_monitor $sleep_time; + end_monitor; + } + + success $i; + return 1; +} + $#ARGV < 1 or die "ktest.pl version: $VERSION\n usage: ktest.pl config-file\n"; if ($#ARGV == 0) { @@ -2294,6 +2527,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $reboot = set_test_option("REBOOT", $i); $noclean = set_test_option("BUILD_NOCLEAN", $i); $minconfig = set_test_option("MIN_CONFIG", $i); + $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i); + $start_minconfig = set_test_option("START_MIN_CONFIG", $i); + $ignore_config = set_test_option("IGNORE_CONFIG", $i); $run_test = set_test_option("TEST", $i); $addconfig = set_test_option("ADD_CONFIG", $i); $reboot_type = set_test_option("REBOOT_TYPE", $i); @@ -2329,6 +2565,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $target_image = set_test_option("TARGET_IMAGE", $i); $localversion = set_test_option("LOCALVERSION", $i); + if (!defined($start_minconfig)) { + $start_minconfig = $minconfig; + } + chdir $builddir || die "can't change directory to $builddir"; if (!-d $tmpdir) { @@ -2361,6 +2601,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $run_type = $opt{"CONFIG_BISECT_TYPE[$i]"}; } + if ($test_type eq "make_min_config") { + $run_type = ""; + } + # mistake in config file? if (!defined($run_type)) { $run_type = "ERROR"; @@ -2396,6 +2640,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { } elsif ($test_type eq "patchcheck") { patchcheck $i; next; + } elsif ($test_type eq "make_min_config") { + make_min_config $i; + next; } if ($build_type ne "nobuild") { diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index 82c966c32d61..a83846d829bd 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -814,3 +814,53 @@ # MIN_CONFIG = /home/test/config-min # BISECT_MANUAL = 1 # +# +# +# For TEST_TYPE = make_min_config +# +# After doing a make localyesconfig, your kernel configuration may +# not be the most useful minimum configuration. Having a true minimum +# config that you can use against other configs is very useful if +# someone else has a config that breaks on your code. By only forcing +# those configurations that are truly required to boot your machine +# will give you less of a chance that one of your set configurations +# will make the bug go away. This will give you a better chance to +# be able to reproduce the reported bug matching the broken config. +# +# Note, this does take some time, and may require you to run the +# test over night, or perhaps over the weekend. But it also allows +# you to interrupt it, and gives you the current minimum config +# that was found till that time. +# +# Note, this test automatically assumes a BUILD_TYPE of oldconfig +# and its test type acts like boot. +# TODO: add a test version that makes the config do more than just +# boot, like having network access. +# +# OUTPUT_MIN_CONFIG is the path and filename of the file that will +# be created from the MIN_CONFIG. If you interrupt the test, set +# this file as your new min config, and use it to continue the test. +# This file does not need to exist on start of test. +# This file is not created until a config is found that can be removed. +# (required field) +# +# START_MIN_CONFIG is the config to use to start the test with. +# you can set this as the same OUTPUT_MIN_CONFIG, but if you do +# the OUTPUT_MIN_CONFIG file must exist. +# (default MIN_CONFIG) +# +# IGNORE_CONFIG is used to specify a config file that has configs that +# you already know must be set. Configs are written here that have +# been tested and proved to be required. It is best to define this +# file if you intend on interrupting the test and running it where +# it left off. New configs that it finds will be written to this file +# and will not be tested again in later runs. +# (optional) +# +# Example: +# +# TEST_TYPE = make_min_config +# OUTPUT_MIN_CONFIG = /path/to/config-new-min +# START_MIN_CONFIG = /path/to/config-min +# IGNORE_CONFIG = /path/to/config-tested +# -- cgit v1.2.3 From b9066f6c0e215386d4b888eaedd739397b987421 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 15 Jul 2011 21:25:24 -0400 Subject: ktest: Use Kconfig dependencies to shorten time to make min_config To save time, the test does not just grab any option and test it. The Kconfig files are examined to determine the dependencies of the configs. If a config is chosen that depends on another config, that config will be checked first. By checking the parents first, we can eliminate whole groups of configs that may have been enabled. For example, if a USB device config is chosen and depends on CONFIG_USB, the CONFIG_USB will be tested before the device. If CONFIG_USB is found not to be needed, it, as well as all configs that depend on it, will be disabled and removed from the current min_config. Note, the code from streamline_config (make localmodconfig) was copied and used to find the dependencies in the Kconfig file. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 283 ++++++++++++++++++++++++++++++++++++---- tools/testing/ktest/sample.conf | 12 ++ 2 files changed, 273 insertions(+), 22 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 5323c6f9bf9b..a9f2e10fc16f 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -2162,6 +2162,159 @@ sub patchcheck { return 1; } +my %depends; +my $iflevel = 0; +my @ifdeps; + +# prevent recursion +my %read_kconfigs; + +# taken from streamline_config.pl +sub read_kconfig { + my ($kconfig) = @_; + + my $state = "NONE"; + my $config; + my @kconfigs; + + my $cont = 0; + my $line; + + + if (! -f $kconfig) { + doprint "file $kconfig does not exist, skipping\n"; + return; + } + + open(KIN, "$kconfig") + or die "Can't open $kconfig"; + while () { + chomp; + + # Make sure that lines ending with \ continue + if ($cont) { + $_ = $line . " " . $_; + } + + if (s/\\$//) { + $cont = 1; + $line = $_; + next; + } + + $cont = 0; + + # collect any Kconfig sources + if (/^source\s*"(.*)"/) { + $kconfigs[$#kconfigs+1] = $1; + } + + # configs found + if (/^\s*(menu)?config\s+(\S+)\s*$/) { + $state = "NEW"; + $config = $2; + + for (my $i = 0; $i < $iflevel; $i++) { + if ($i) { + $depends{$config} .= " " . $ifdeps[$i]; + } else { + $depends{$config} = $ifdeps[$i]; + } + $state = "DEP"; + } + + # collect the depends for the config + } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) { + + if (defined($depends{$1})) { + $depends{$config} .= " " . $1; + } else { + $depends{$config} = $1; + } + + # Get the configs that select this config + } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) { + if (defined($depends{$1})) { + $depends{$1} .= " " . $config; + } else { + $depends{$1} = $config; + } + + # Check for if statements + } elsif (/^if\s+(.*\S)\s*$/) { + my $deps = $1; + # remove beginning and ending non text + $deps =~ s/^[^a-zA-Z0-9_]*//; + $deps =~ s/[^a-zA-Z0-9_]*$//; + + my @deps = split /[^a-zA-Z0-9_]+/, $deps; + + $ifdeps[$iflevel++] = join ':', @deps; + + } elsif (/^endif/) { + + $iflevel-- if ($iflevel); + + # stop on "help" + } elsif (/^\s*help\s*$/) { + $state = "NONE"; + } + } + close(KIN); + + # read in any configs that were found. + foreach $kconfig (@kconfigs) { + if (!defined($read_kconfigs{$kconfig})) { + $read_kconfigs{$kconfig} = 1; + read_kconfig("$builddir/$kconfig"); + } + } +} + +sub read_depends { + # find out which arch this is by the kconfig file + open (IN, $output_config) + or dodie "Failed to read $output_config"; + my $arch; + while () { + if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) { + $arch = $1; + last; + } + } + close IN; + + if (!defined($arch)) { + doprint "Could not find arch from config file\n"; + doprint "no dependencies used\n"; + return; + } + + # arch is really the subarch, we need to know + # what directory to look at. + if ($arch eq "i386" || $arch eq "x86_64") { + $arch = "x86"; + } elsif ($arch =~ /^tile/) { + $arch = "tile"; + } + + my $kconfig = "$builddir/arch/$arch/Kconfig"; + + if (! -f $kconfig && $arch =~ /\d$/) { + my $orig = $arch; + # some subarchs have numbers, truncate them + $arch =~ s/\d*$//; + $kconfig = "$builddir/arch/$arch/Kconfig"; + if (! -f $kconfig) { + doprint "No idea what arch dir $orig is for\n"; + doprint "no dependencies used\n"; + return; + } + } + + read_kconfig($kconfig); +} + sub read_config_list { my ($config) = @_; @@ -2197,6 +2350,95 @@ sub make_new_config { close OUT; } +sub get_depends { + my ($dep) = @_; + + my $kconfig = $dep; + $kconfig =~ s/CONFIG_//; + + $dep = $depends{"$kconfig"}; + + # the dep string we have saves the dependencies as they + # were found, including expressions like ! && ||. We + # want to split this out into just an array of configs. + + my $valid = "A-Za-z_0-9"; + + my @configs; + + while ($dep =~ /[$valid]/) { + + if ($dep =~ /^[^$valid]*([$valid]+)/) { + my $conf = "CONFIG_" . $1; + + $configs[$#configs + 1] = $conf; + + $dep =~ s/^[^$valid]*[$valid]+//; + } else { + die "this should never happen"; + } + } + + return @configs; +} + +my %min_configs; +my %keep_configs; +my %processed_configs; +my %nochange_config; + +sub test_this_config { + my ($config) = @_; + + my $found; + + # if we already processed this config, skip it + if (defined($processed_configs{$config})) { + return undef; + } + $processed_configs{$config} = 1; + + # if this config failed during this round, skip it + if (defined($nochange_config{$config})) { + return undef; + } + + my $kconfig = $config; + $kconfig =~ s/CONFIG_//; + + # Test dependencies first + if (defined($depends{"$kconfig"})) { + my @parents = get_depends $config; + foreach my $parent (@parents) { + # if the parent is in the min config, check it first + next if (!defined($min_configs{$parent})); + $found = test_this_config($parent); + if (defined($found)) { + return $found; + } + } + } + + # Remove this config from the list of configs + # do a make oldnoconfig and then read the resulting + # .config to make sure it is missing the config that + # we had before + my %configs = %min_configs; + delete $configs{$config}; + make_new_config ((values %configs), (values %keep_configs)); + make_oldconfig; + undef %configs; + assign_configs \%configs, $output_config; + + return $config if (!defined($configs{$config})); + + doprint "disabling config $config did not change .config\n"; + + $nochange_config{$config} = 1; + + return undef; +} + sub make_min_config { my ($i) = @_; @@ -2216,8 +2458,12 @@ sub make_min_config { run_command "$make allnoconfig" or return 0; + read_depends; + process_config_ignore $output_config; - my %keep_configs; + + undef %keep_configs; + undef %min_configs; if (defined($ignore_config)) { # make sure the file exists @@ -2229,7 +2475,6 @@ sub make_min_config { # Look at the current min configs, and save off all the # ones that were set via the allnoconfig - my %min_configs; assign_configs \%min_configs, $start_minconfig; my @config_keys = keys %min_configs; @@ -2261,9 +2506,8 @@ sub make_min_config { } } - my %nochange_config; - my $done = 0; + my $take_two = 0; while (!$done) { @@ -2293,35 +2537,30 @@ sub make_min_config { undef %nochange_config; } - foreach my $config (@test_configs) { + undef %processed_configs; - # Remove this config from the list of configs - # do a make oldnoconfig and then read the resulting - # .config to make sure it is missing the config that - # we had before - my %configs = %min_configs; - delete $configs{$config}; - make_new_config ((values %configs), (values %keep_configs)); - make_oldconfig; - undef %configs; - assign_configs \%configs, $output_config; + foreach my $config (@test_configs) { - if (!defined($configs{$config})) { - $found = $config; - last; - } + $found = test_this_config $config; - doprint "disabling config $config did not change .config\n"; + last if (defined($found)); # oh well, try another config - $nochange_config{$config} = 1; } if (!defined($found)) { + # we could have failed due to the nochange_config hash + # reset and try again + if (!$take_two) { + undef %nochange_config; + $take_two = 1; + next; + } doprint "No more configs found that we can disable\n"; $done = 1; last; } + $take_two = 0; $config = $found; @@ -2338,7 +2577,7 @@ sub make_min_config { $in_bisect = 0; if ($failed) { - doprint "$config is needed to boot the box... keeping\n"; + doprint "$min_configs{$config} is needed to boot the box... keeping\n"; # this config is needed, add it to the ignore list. $keep_configs{$config} = $min_configs{$config}; delete $min_configs{$config}; diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index a83846d829bd..d096a0c80401 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -837,6 +837,18 @@ # TODO: add a test version that makes the config do more than just # boot, like having network access. # +# To save time, the test does not just grab any option and test +# it. The Kconfig files are examined to determine the dependencies +# of the configs. If a config is chosen that depends on another +# config, that config will be checked first. By checking the +# parents first, we can eliminate whole groups of configs that +# may have been enabled. +# +# For example, if a USB device config is chosen and depends on CONFIG_USB, +# the CONFIG_USB will be tested before the device. If CONFIG_USB is +# found not to be needed, it, as well as all configs that depend on +# it, will be disabled and removed from the current min_config. +# # OUTPUT_MIN_CONFIG is the path and filename of the file that will # be created from the MIN_CONFIG. If you interrupt the test, set # this file as your new min config, and use it to continue the test. -- cgit v1.2.3 From 35ce5952e62bc72520e6a7dbcfa4baf8c9f9eedb Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 15 Jul 2011 21:57:25 -0400 Subject: ktest: Add prompt to use OUTPUT_MIN_CONFIG If the defined OUTPUT_MIN_CONFIG in the make_min_config test exists, then give a prompt to ask the user if they want to use that config instead, as it is very often the case, especially when the test has been interrupted. The OUTPUT_MIN_CONFIG is usually the config that one wants to use to continue the test where they left off. But if START_MIN_CONFIG is defined (thus the MIN_CONFIG is not the default), then do not prompt, as it will be annoying if the user has this as one of many tests, and the test pauses waiting for input, while the user is sleeping. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 70 ++++++++++++++++++++++++++++++++--------- tools/testing/ktest/sample.conf | 3 ++ 2 files changed, 59 insertions(+), 14 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index a9f2e10fc16f..cf45f58f8fdf 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -87,6 +87,7 @@ my $post_install; my $noclean; my $minconfig; my $start_minconfig; +my $start_minconfig_defined; my $output_minconfig; my $ignore_config; my $addconfig; @@ -217,6 +218,26 @@ $config_help{"REBOOT_SCRIPT"} = << "EOF" EOF ; +sub read_yn { + my ($prompt) = @_; + + my $ans; + + for (;;) { + print "$prompt [Y/n] "; + $ans = ; + chomp $ans; + if ($ans =~ /^\s*$/) { + $ans = "y"; + } + last if ($ans =~ /^y$/i || $ans =~ /^n$/i); + print "Please answer either 'y' or 'n'.\n"; + } + if ($ans !~ /^y$/i) { + return 0; + } + return 1; +} sub get_ktest_config { my ($config) = @_; @@ -2445,10 +2466,23 @@ sub make_min_config { if (!defined($output_minconfig)) { fail "OUTPUT_MIN_CONFIG not defined" and return; } + + # If output_minconfig exists, and the start_minconfig + # came from min_config, than ask if we should use + # that instead. + if (-f $output_minconfig && !$start_minconfig_defined) { + print "$output_minconfig exists\n"; + if (read_yn " Use it as minconfig?") { + $start_minconfig = $output_minconfig; + } + } + if (!defined($start_minconfig)) { fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return; } + my $temp_config = "$tmpdir/temp_config"; + # First things first. We build an allnoconfig to find # out what the defaults are that we can't touch. # Some are selections, but we really can't handle selections. @@ -2581,6 +2615,19 @@ sub make_min_config { # this config is needed, add it to the ignore list. $keep_configs{$config} = $min_configs{$config}; delete $min_configs{$config}; + + # update new ignore configs + if (defined($ignore_config)) { + open (OUT, ">$temp_config") + or die "Can't write to $temp_config"; + foreach my $config (keys %keep_configs) { + print OUT "$keep_configs{$config}\n"; + } + close OUT; + run_command "mv $temp_config $ignore_config" or + dodie "failed to copy update to $ignore_config"; + } + } else { # We booted without this config, remove it from the minconfigs. doprint "$config is not needed, disabling\n"; @@ -2599,8 +2646,8 @@ sub make_min_config { } # Save off all the current mandidory configs - open (OUT, ">$output_minconfig") - or die "Can't write to $output_minconfig"; + open (OUT, ">$temp_config") + or die "Can't write to $temp_config"; foreach my $config (keys %keep_configs) { print OUT "$keep_configs{$config}\n"; } @@ -2608,6 +2655,9 @@ sub make_min_config { print OUT "$min_configs{$config}\n"; } close OUT; + + run_command "mv $temp_config $output_minconfig" or + dodie "failed to copy update to $output_minconfig"; } doprint "Reboot and wait $sleep_time seconds\n"; @@ -2627,18 +2677,7 @@ if ($#ARGV == 0) { $ktest_config = $ARGV[0]; if (! -f $ktest_config) { print "$ktest_config does not exist.\n"; - my $ans; - for (;;) { - print "Create it? [Y/n] "; - $ans = ; - chomp $ans; - if ($ans =~ /^\s*$/) { - $ans = "y"; - } - last if ($ans =~ /^y$/i || $ans =~ /^n$/i); - print "Please answer either 'y' or 'n'.\n"; - } - if ($ans !~ /^y$/i) { + if (!read_yn "Create it?") { exit 0; } } @@ -2804,7 +2843,10 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { $target_image = set_test_option("TARGET_IMAGE", $i); $localversion = set_test_option("LOCALVERSION", $i); + $start_minconfig_defined = 1; + if (!defined($start_minconfig)) { + $start_minconfig_defined = 0; $start_minconfig = $minconfig; } diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf index d096a0c80401..b8bcd14b5a4d 100644 --- a/tools/testing/ktest/sample.conf +++ b/tools/testing/ktest/sample.conf @@ -854,6 +854,9 @@ # this file as your new min config, and use it to continue the test. # This file does not need to exist on start of test. # This file is not created until a config is found that can be removed. +# If this file exists, you will be prompted if you want to use it +# as the min_config (overriding MIN_CONFIG) if START_MIN_CONFIG +# is not defined. # (required field) # # START_MIN_CONFIG is the config to use to start the test with. -- cgit v1.2.3 From 43d1b6518e523df1bd15f07be480d10a9eb043bc Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 15 Jul 2011 22:01:56 -0400 Subject: ktest: Keep fonud configs separate from default configs The IGNORE_CONFIG file holds the configs that we don't want to change (with their proper settings). But on start up, the make noconfig is executed, and the configs that are on are also put into the ignore config category. But these are configs that were forced on by the kconfig scripts and not something that we found must be enabled to boot our machine. By keeping the configs that are forced on by default, separate from the configs we found that are required to boot the box, we can get a much more interesting IGNORE_CONFIG. In fact, the IGNORE_CONFIG can usually end up being the must have configs to boot, and only have 6 or 7 configs set. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index cf45f58f8fdf..e826704703f4 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -2405,6 +2405,7 @@ sub get_depends { my %min_configs; my %keep_configs; +my %save_configs; my %processed_configs; my %nochange_config; @@ -2496,15 +2497,17 @@ sub make_min_config { process_config_ignore $output_config; - undef %keep_configs; + undef %save_configs; undef %min_configs; if (defined($ignore_config)) { # make sure the file exists `touch $ignore_config`; - assign_configs \%keep_configs, $ignore_config; + assign_configs \%save_configs, $ignore_config; } + %keep_configs = %save_configs; + doprint "Load initial configs from $start_minconfig\n"; # Look at the current min configs, and save off all the @@ -2614,14 +2617,15 @@ sub make_min_config { doprint "$min_configs{$config} is needed to boot the box... keeping\n"; # this config is needed, add it to the ignore list. $keep_configs{$config} = $min_configs{$config}; + $save_configs{$config} = $min_configs{$config}; delete $min_configs{$config}; # update new ignore configs if (defined($ignore_config)) { open (OUT, ">$temp_config") or die "Can't write to $temp_config"; - foreach my $config (keys %keep_configs) { - print OUT "$keep_configs{$config}\n"; + foreach my $config (keys %save_configs) { + print OUT "$save_configs{$config}\n"; } close OUT; run_command "mv $temp_config $ignore_config" or -- cgit v1.2.3 From 250bae8be0177fcc1435cb46d1aba7e40a0366b2 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 15 Jul 2011 22:05:59 -0400 Subject: ktest: Fix bug when ADD_CONFIG is set but MIN_CONFIG is not The MIN_CONFIG is a single config that is considered to have all the configs that are required to boot the box. ADD_CONFIG is a list of configs that we add that may contain configs known to be broken (set off) or just configs that we want every box to have and this can include shared configs. If a config has no MIN_CONFIG defined, but has multiple files defined for the ADD_CONFIG, the test will die, because the MIN_CONFIG will default to ADD_CONFIG. The problem is the code to open MIN_CONFIG expects a string of one file, not multiple, and the open will fail. Since the real minconfig that is used is a concatination of MIN_CONFIG and ADD_CONFIG files, we change the code to open that instead of whatever MIN_CONFIG defaults to. Signed-off-by: Steven Rostedt --- tools/testing/ktest/ktest.pl | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'tools') diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index e826704703f4..8d02ccb10c59 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -1970,12 +1970,6 @@ sub config_bisect { unlink $tmpconfig; } - # Add other configs - if (defined($addconfig)) { - run_command "cat $addconfig >> $tmpconfig" or - dodie "failed to append $addconfig"; - } - if (-f $tmpconfig) { load_force_config($tmpconfig); process_config_ignore $tmpconfig; @@ -1997,7 +1991,7 @@ sub config_bisect { } close(IN); - # Now run oldconfig with the minconfig (and addconfigs) + # Now run oldconfig with the minconfig make_oldconfig; # check to see what we lost (or gained) @@ -2901,11 +2895,12 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { unlink $dmesg; unlink $buildlog; - if (!defined($minconfig)) { - $minconfig = $addconfig; - - } elsif (defined($addconfig)) { - run_command "cat $addconfig $minconfig > $tmpdir/add_config" or + if (defined($addconfig)) { + my $min = $minconfig; + if (!defined($minconfig)) { + $min = ""; + } + run_command "cat $addconfig $min > $tmpdir/add_config" or dodie "Failed to create temp config"; $minconfig = "$tmpdir/add_config"; } -- cgit v1.2.3 From e4c0d0e22ce5cf84b3993b5af6c2dac08d52f06b Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 15 Jul 2011 23:39:00 -0400 Subject: tools/power x86_energy_perf_policy: fix print of uninitialized string Looks like I was going to stick the brand string in the verbose ouput, but didn't get around to it. Signed-off-by: Len Brown --- tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'tools') 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) void validate_cpuid(void) { unsigned int eax, ebx, ecx, edx, max_level; - char brand[16]; unsigned int fms, family, model, stepping; eax = ebx = ecx = edx = 0; @@ -160,8 +159,8 @@ void validate_cpuid(void) model += ((fms >> 16) & 0xf) << 4; if (verbose > 1) - printf("CPUID %s %d levels family:model:stepping " - "0x%x:%x:%x (%d:%d:%d)\n", brand, max_level, + printf("CPUID %d levels family:model:stepping " + "0x%x:%x:%x (%d:%d:%d)\n", max_level, family, model, stepping, family, model, stepping); if (!(edx & (1 << 5))) { -- cgit v1.2.3 From 0111919da268e1ced315e009ad0d0435a2fb32ac Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 13 Jul 2011 22:58:18 +0200 Subject: perf tools: Add missing 'node' alias to the hw_cache[] array Add "node" as a simple alias for NODE cache events. The addition of NODE cache events broke the parse_alias function, so any mismatched event caused the segfault, like: # ./perf stat -e krava ls The hw_cache/hw_cache_op/hw_cache_result arrays needs to follow PERF_COUNT_HW_CACHE_*MAX enums. Adding those MAXs to be size of those arrays, so possible ommision in future wil not lead to segfault. Adding read/write/prefetch as allowed operations for node cache event. Signed-off-by: Jiri Olsa Acked-by: Peter Zijlstra Cc: acme@redhat.com Link: http://lkml.kernel.org/r/20110713205818.GB7827@jolsa.brq.redhat.com Signed-off-by: Ingo Molnar --- tools/perf/util/parse-events.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 41982c373faf..c0e21aec4896 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] = { #define MAX_ALIASES 8 -static const char *hw_cache[][MAX_ALIASES] = { +static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = { { "L1-dcache", "l1-d", "l1d", "L1-data", }, { "L1-icache", "l1-i", "l1i", "L1-instruction", }, - { "LLC", "L2" }, + { "LLC", "L2", }, { "dTLB", "d-tlb", "Data-TLB", }, { "iTLB", "i-tlb", "Instruction-TLB", }, { "branch", "branches", "bpu", "btb", "bpc", }, + { "node", }, }; -static const char *hw_cache_op[][MAX_ALIASES] = { +static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = { { "load", "loads", "read", }, { "store", "stores", "write", }, { "prefetch", "prefetches", "speculative-read", "speculative-load", }, }; -static const char *hw_cache_result[][MAX_ALIASES] = { +static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] + [MAX_ALIASES] = { { "refs", "Reference", "ops", "access", }, { "misses", "miss", }, }; @@ -124,6 +126,7 @@ static unsigned long hw_cache_stat[C(MAX)] = { [C(DTLB)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), [C(ITLB)] = (CACHE_READ), [C(BPU)] = (CACHE_READ), + [C(NODE)] = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH), }; #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) PERF_COUNT_HW_CACHE_OP_MAX); if (cache_op >= 0) { if (!is_cache_op_valid(cache_type, cache_op)) - return 0; + return EVT_FAILED; continue; } } -- cgit v1.2.3 From eda3913bb70ecebac13adccffe1e7f96e93cee02 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Fri, 15 Jul 2011 12:34:09 -0600 Subject: perf tools: Fix endian conversion reading event attr from file header The perf_event_attr struct has two __u32's at the top and they need to be swapped individually. With this change I was able to analyze a perf.data collected in a 32-bit PPC VM on an x86 system. I tested both 32-bit and 64-bit binaries for the Intel analysis side; both read the PPC perf.data file correctly. -v2: - changed the existing perf_event__attr_swap() to swap only elements of perf_event_attr and exported it for use in swapping the attributes in the file header - updated swap_ops used for processing events Signed-off-by: David Ahern Acked-by: Frederic Weisbecker Cc: acme@ghostprotocols.net Cc: peterz@infradead.org Cc: paulus@samba.org Cc: Link: http://lkml.kernel.org/r/1310754849-12474-1-git-send-email-dsahern@gmail.com Signed-off-by: Ingo Molnar --- tools/perf/util/header.c | 5 ++++- tools/perf/util/session.c | 30 ++++++++++++++++++------------ tools/perf/util/session.h | 1 + 3 files changed, 23 insertions(+), 13 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index afb0849fe530..cb2959a3fb43 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -877,9 +877,12 @@ int perf_session__read_header(struct perf_session *session, int fd) struct perf_evsel *evsel; off_t tmp; - if (perf_header__getbuffer64(header, fd, &f_attr, sizeof(f_attr))) + if (readn(fd, &f_attr, sizeof(f_attr)) <= 0) goto out_errno; + if (header->needs_swap) + perf_event__attr_swap(&f_attr.attr); + tmp = lseek(fd, 0, SEEK_CUR); evsel = perf_evsel__new(&f_attr.attr, i); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 080e5336d89f..a3c13bcd5a8d 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -413,20 +413,26 @@ static void perf_event__read_swap(union perf_event *event) event->read.id = bswap_64(event->read.id); } -static void perf_event__attr_swap(union perf_event *event) +/* exported for swapping attributes in file header */ +void perf_event__attr_swap(struct perf_event_attr *attr) +{ + attr->type = bswap_32(attr->type); + attr->size = bswap_32(attr->size); + attr->config = bswap_64(attr->config); + attr->sample_period = bswap_64(attr->sample_period); + attr->sample_type = bswap_64(attr->sample_type); + attr->read_format = bswap_64(attr->read_format); + attr->wakeup_events = bswap_32(attr->wakeup_events); + attr->bp_type = bswap_32(attr->bp_type); + attr->bp_addr = bswap_64(attr->bp_addr); + attr->bp_len = bswap_64(attr->bp_len); +} + +static void perf_event__hdr_attr_swap(union perf_event *event) { size_t size; - event->attr.attr.type = bswap_32(event->attr.attr.type); - event->attr.attr.size = bswap_32(event->attr.attr.size); - event->attr.attr.config = bswap_64(event->attr.attr.config); - event->attr.attr.sample_period = bswap_64(event->attr.attr.sample_period); - event->attr.attr.sample_type = bswap_64(event->attr.attr.sample_type); - event->attr.attr.read_format = bswap_64(event->attr.attr.read_format); - event->attr.attr.wakeup_events = bswap_32(event->attr.attr.wakeup_events); - event->attr.attr.bp_type = bswap_32(event->attr.attr.bp_type); - event->attr.attr.bp_addr = bswap_64(event->attr.attr.bp_addr); - event->attr.attr.bp_len = bswap_64(event->attr.attr.bp_len); + perf_event__attr_swap(&event->attr.attr); size = event->header.size; size -= (void *)&event->attr.id - (void *)event; @@ -454,7 +460,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_LOST] = perf_event__all64_swap, [PERF_RECORD_READ] = perf_event__read_swap, [PERF_RECORD_SAMPLE] = perf_event__all64_swap, - [PERF_RECORD_HEADER_ATTR] = perf_event__attr_swap, + [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, [PERF_RECORD_HEADER_BUILD_ID] = NULL, diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 5de754f4b7f3..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, u64 addr); void mem_bswap_64(void *src, int byte_size); +void perf_event__attr_swap(struct perf_event_attr *attr); int perf_session__create_kernel_maps(struct perf_session *self); -- cgit v1.2.3 From adc4bf9955856f8aa081ba613dbf56ffd664f0b7 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 30 May 2011 09:16:27 -0600 Subject: perf script: Fix display of IP address for non-callchain path Non-callchain path is using al.addr which prints as: openssl 14564 17672.003587: 7862d _x86_64_AES_encrypt_compact This should be sample->ip to print as: openssl 14564 17672.003587: 3f7867862d _x86_64_AES_encrypt_compact Signed-off-by: David Ahern Acked-by: Frederic Weisbecker Cc: acme@ghostprotocols.net Cc: peterz@infradead.org Cc: paulus@samba.org Link: http://lkml.kernel.org/r/1306768587-15376-1-git-send-email-dsahern@gmail.com Signed-off-by: Ingo Molnar --- tools/perf/util/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index a3c13bcd5a8d..72458d9da5b1 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1269,7 +1269,7 @@ void perf_session__print_ip(union perf_event *event, } } else { - printf("%16" PRIx64, al.addr); + printf("%16" PRIx64, sample->ip); if (print_sym) { if (al.sym && al.sym->name) symname = al.sym->name; -- cgit v1.2.3 From f120f9d51be3a7db8991e7b78dc08bab5f8ab8f3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 14 Jul 2011 11:25:32 +0200 Subject: perf tools: De-opt the parse_events function Moving out the option parameter from parse_events function, and adding new parse_events_option function instead. The option parameter is used only to carry "struct perf_evlist" pointer for chaining new events. Putting it away, enable us to call parse_events from other places without using the option parameter. Signed-off-by: Jiri Olsa Cc: acme@redhat.com Cc: a.p.zijlstra@chello.nl Cc: paulus@samba.org Link: http://lkml.kernel.org/r/1310635534-4013-2-git-send-email-jolsa@redhat.com Signed-off-by: Ingo Molnar --- tools/perf/builtin-record.c | 2 +- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/util/parse-events.c | 26 ++++++++++++++++---------- tools/perf/util/parse-events.h | 6 +++++- 5 files changed, 24 insertions(+), 14 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8e2c85798185..80dc5b790e47 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -740,7 +740,7 @@ static bool force, append_file; const struct option record_options[] = { OPT_CALLBACK('e', "event", &evsel_list, "event", "event selector. use 'perf list' to list available events", - parse_events), + parse_events_option), OPT_CALLBACK(0, "filter", &evsel_list, "filter", "event filter", parse_filter), OPT_INTEGER('p', "pid", &target_pid, diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 1d08c8084cc4..1ad04ce29c34 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -1032,7 +1032,7 @@ static int stat__set_big_num(const struct option *opt __used, static const struct option options[] = { OPT_CALLBACK('e', "event", &evsel_list, "event", "event selector. use 'perf list' to list available events", - parse_events), + parse_events_option), OPT_CALLBACK(0, "filter", &evsel_list, "filter", "event filter", parse_filter), OPT_BOOLEAN('i', "no-inherit", &no_inherit, 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[] = { static const struct option options[] = { OPT_CALLBACK('e', "event", &top.evlist, "event", "event selector. use 'perf list' to list available events", - parse_events), + parse_events_option), OPT_INTEGER('c', "count", &default_interval, "event period to sample"), OPT_INTEGER('p', "pid", &top.target_pid, diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index c0e21aec4896..4ea7e19f5251 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -478,7 +478,7 @@ parse_single_tracepoint_event(char *sys_name, /* sys + ':' + event + ':' + flags*/ #define MAX_EVOPT_LEN (MAX_EVENT_LENGTH * 2 + 2 + 128) static enum event_result -parse_multiple_tracepoint_event(const struct option *opt, char *sys_name, +parse_multiple_tracepoint_event(struct perf_evlist *evlist, char *sys_name, const char *evt_exp, char *flags) { char evt_path[MAXPATHLEN]; @@ -512,7 +512,7 @@ parse_multiple_tracepoint_event(const struct option *opt, char *sys_name, if (len < 0) return EVT_FAILED; - if (parse_events(opt, event_opt, 0)) + if (parse_events(evlist, event_opt, 0)) return EVT_FAILED; } @@ -520,7 +520,7 @@ parse_multiple_tracepoint_event(const struct option *opt, char *sys_name, } static enum event_result -parse_tracepoint_event(const struct option *opt, const char **strp, +parse_tracepoint_event(struct perf_evlist *evlist, const char **strp, struct perf_event_attr *attr) { const char *evt_name; @@ -560,8 +560,8 @@ parse_tracepoint_event(const struct option *opt, const char **strp, return EVT_FAILED; if (strpbrk(evt_name, "*?")) { *strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */ - return parse_multiple_tracepoint_event(opt, sys_name, evt_name, - flags); + return parse_multiple_tracepoint_event(evlist, sys_name, + evt_name, flags); } else { return parse_single_tracepoint_event(sys_name, evt_name, evt_length, attr, strp); @@ -781,12 +781,12 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr) * Symbolic names are (almost) exactly matched. */ static enum event_result -parse_event_symbols(const struct option *opt, const char **str, +parse_event_symbols(struct perf_evlist *evlist, const char **str, struct perf_event_attr *attr) { enum event_result ret; - ret = parse_tracepoint_event(opt, str, attr); + ret = parse_tracepoint_event(evlist, str, attr); if (ret != EVT_FAILED) goto modifier; @@ -825,9 +825,8 @@ modifier: return ret; } -int parse_events(const struct option *opt, const char *str, int unset __used) +int parse_events(struct perf_evlist *evlist , const char *str, int unset __used) { - struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; struct perf_event_attr attr; enum event_result ret; const char *ostr; @@ -835,7 +834,7 @@ int parse_events(const struct option *opt, const char *str, int unset __used) for (;;) { ostr = str; memset(&attr, 0, sizeof(attr)); - ret = parse_event_symbols(opt, &str, &attr); + ret = parse_event_symbols(evlist, &str, &attr); if (ret == EVT_FAILED) return -1; @@ -866,6 +865,13 @@ int parse_events(const struct option *opt, const char *str, int unset __used) return 0; } +int parse_events_option(const struct option *opt, const char *str, + int unset __used) +{ + struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; + return parse_events(evlist, str, unset); +} + int parse_filter(const struct option *opt, const char *str, int unset __used) { 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 @@ struct list_head; struct perf_evsel; +struct perf_evlist; struct option; @@ -24,7 +25,10 @@ const char *event_type(int type); const char *event_name(struct perf_evsel *event); extern const char *__event_name(int type, u64 config); -extern int parse_events(const struct option *opt, const char *str, int unset); +extern int parse_events_option(const struct option *opt, const char *str, + int unset); +extern int parse_events(struct perf_evlist *evlist, const char *str, + int unset); extern int parse_filter(const struct option *opt, const char *str, int unset); #define EVENTS_HELP_MAX (128*1024) -- cgit v1.2.3 From 13b62567e909125145f90e91625b1062196d1258 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 14 Jul 2011 11:25:33 +0200 Subject: perf tools: Add automated tests for events parsing Adding builtin test for parse_events function, which is responsible for parsing/processing "-e" option for stat/top/record commands. This new test will run within the builtin test command suite (perf test). One or several tests were added for each type of event. More tests could be added easily if needed. Signed-off-by: Jiri Olsa Cc: acme@redhat.com Cc: a.p.zijlstra@chello.nl Cc: paulus@samba.org Link: http://lkml.kernel.org/r/1310635534-4013-3-git-send-email-jolsa@redhat.com Signed-off-by: Ingo Molnar --- tools/perf/builtin-test.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) (limited to 'tools') diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 2da9162262b0..b5cd5f5ed195 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -12,6 +12,7 @@ #include "util/parse-events.h" #include "util/symbol.h" #include "util/thread_map.h" +#include "../../include/linux/hw_breakpoint.h" static long page_size; @@ -600,6 +601,246 @@ out_free_threads: #undef nsyscalls } +#define TEST_ASSERT_VAL(text, cond) \ +do { \ + if (!cond) { \ + pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ + return -1; \ + } \ +} while (0) + +static int test__checkevent_tracepoint(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type); + TEST_ASSERT_VAL("wrong sample_type", + (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) == + evsel->attr.sample_type); + TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period); + return 0; +} + +static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel; + + TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); + + list_for_each_entry(evsel, &evlist->entries, node) { + TEST_ASSERT_VAL("wrong type", + PERF_TYPE_TRACEPOINT == evsel->attr.type); + TEST_ASSERT_VAL("wrong sample_type", + (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) + == evsel->attr.sample_type); + TEST_ASSERT_VAL("wrong sample_period", + 1 == evsel->attr.sample_period); + } + return 0; +} + +static int test__checkevent_raw(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type); + TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); + return 0; +} + +static int test__checkevent_numeric(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", 1 == evsel->attr.type); + TEST_ASSERT_VAL("wrong config", 1 == evsel->attr.config); + return 0; +} + +static int test__checkevent_symbolic_name(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong config", + PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config); + return 0; +} + +static int test__checkevent_symbolic_alias(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_SOFTWARE == evsel->attr.type); + TEST_ASSERT_VAL("wrong config", + PERF_COUNT_SW_PAGE_FAULTS == evsel->attr.config); + return 0; +} + +static int test__checkevent_genhw(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_HW_CACHE == evsel->attr.type); + TEST_ASSERT_VAL("wrong config", (1 << 16) == evsel->attr.config); + return 0; +} + +static int test__checkevent_breakpoint(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); + TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); + TEST_ASSERT_VAL("wrong bp_type", (HW_BREAKPOINT_R | HW_BREAKPOINT_W) == + evsel->attr.bp_type); + TEST_ASSERT_VAL("wrong bp_len", HW_BREAKPOINT_LEN_4 == + evsel->attr.bp_len); + return 0; +} + +static int test__checkevent_breakpoint_x(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", PERF_TYPE_BREAKPOINT == evsel->attr.type); + TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); + TEST_ASSERT_VAL("wrong bp_type", + HW_BREAKPOINT_X == evsel->attr.bp_type); + TEST_ASSERT_VAL("wrong bp_len", sizeof(long) == evsel->attr.bp_len); + return 0; +} + +static int test__checkevent_breakpoint_r(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", + PERF_TYPE_BREAKPOINT == evsel->attr.type); + TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); + TEST_ASSERT_VAL("wrong bp_type", + HW_BREAKPOINT_R == evsel->attr.bp_type); + TEST_ASSERT_VAL("wrong bp_len", + HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len); + return 0; +} + +static int test__checkevent_breakpoint_w(struct perf_evlist *evlist) +{ + struct perf_evsel *evsel = list_entry(evlist->entries.next, + struct perf_evsel, node); + + TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries); + TEST_ASSERT_VAL("wrong type", + PERF_TYPE_BREAKPOINT == evsel->attr.type); + TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config); + TEST_ASSERT_VAL("wrong bp_type", + HW_BREAKPOINT_W == evsel->attr.bp_type); + TEST_ASSERT_VAL("wrong bp_len", + HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len); + return 0; +} + +static struct test__event_st { + const char *name; + __u32 type; + int (*check)(struct perf_evlist *evlist); +} test__events[] = { + { + .name = "syscalls:sys_enter_open", + .check = test__checkevent_tracepoint, + }, + { + .name = "syscalls:*", + .check = test__checkevent_tracepoint_multi, + }, + { + .name = "r1", + .check = test__checkevent_raw, + }, + { + .name = "1:1", + .check = test__checkevent_numeric, + }, + { + .name = "instructions", + .check = test__checkevent_symbolic_name, + }, + { + .name = "faults", + .check = test__checkevent_symbolic_alias, + }, + { + .name = "L1-dcache-load-miss", + .check = test__checkevent_genhw, + }, + { + .name = "mem:0", + .check = test__checkevent_breakpoint, + }, + { + .name = "mem:0:x", + .check = test__checkevent_breakpoint_x, + }, + { + .name = "mem:0:r", + .check = test__checkevent_breakpoint_r, + }, + { + .name = "mem:0:w", + .check = test__checkevent_breakpoint_w, + }, +}; + +#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st)) + +static int test__parse_events(void) +{ + struct perf_evlist *evlist; + u_int i; + int ret = 0; + + for (i = 0; i < TEST__EVENTS_CNT; i++) { + struct test__event_st *e = &test__events[i]; + + evlist = perf_evlist__new(NULL, NULL); + if (evlist == NULL) + break; + + ret = parse_events(evlist, e->name, 0); + if (ret) { + pr_debug("failed to parse event '%s', err %d\n", + e->name, ret); + break; + } + + ret = e->check(evlist); + if (ret) + break; + + perf_evlist__delete(evlist); + } + + return ret; +} static struct test { const char *desc; int (*func)(void); @@ -620,6 +861,10 @@ static struct test { .desc = "read samples using the mmap interface", .func = test__basic_mmap, }, + { + .desc = "parse events tests", + .func = test__parse_events, + }, { .func = NULL, }, -- cgit v1.2.3 From baf040a0d1ac6319725c0fe400503683ac016580 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 14 Jul 2011 11:25:34 +0200 Subject: perf tools: Make test use the preset debugfs path Use preset debugfs path instead of hardcoded one. Signed-off-by: Jiri Olsa Cc: acme@redhat.com Cc: a.p.zijlstra@chello.nl Cc: paulus@samba.org Link: http://lkml.kernel.org/r/1310635534-4013-4-git-send-email-jolsa@redhat.com Signed-off-by: Ingo Molnar --- tools/perf/builtin-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index b5cd5f5ed195..55f4c76f2821 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -246,8 +246,8 @@ static int trace_event__id(const char *evname) int err = -1, fd; if (asprintf(&filename, - "/sys/kernel/debug/tracing/events/syscalls/%s/id", - evname) < 0) + "%s/syscalls/%s/id", + debugfs_path, evname) < 0) return -1; fd = open(filename, O_RDONLY); -- cgit v1.2.3 From 08a4a43fc407d780bdde36d98f89c0dbb2a6be6b Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 11 Jul 2011 15:38:24 -0600 Subject: perf tools, x86: Fix 32-bit compile on 64-bit system Builds for 32-bit perf binaries on a 64-bit host currently fail with this error: [...] bench/../../../arch/x86/lib/memcpy_64.S: Assembler messages: bench/../../../arch/x86/lib/memcpy_64.S:29: Error: bad register name `%rdi' bench/../../../arch/x86/lib/memcpy_64.S:34: Error: invalid instruction suffix for `movs' bench/../../../arch/x86/lib/memcpy_64.S:50: Error: bad register name `%rdi' bench/../../../arch/x86/lib/memcpy_64.S:61: Error: bad register name `%rdi' ... The problem is the detection of the host arch without considering passed in flags. This change fixes 32-bit builds via: make EXTRA_CFLAGS=-m32 and 64-bit builds still reference the memcpy_64.S. Signed-off-by: David Ahern Acked-by: Frederic Weisbecker Signed-off-by: Peter Zijlstra Cc: Link: http://lkml.kernel.org/r/1310420304-21452-1-git-send-email-dsahern@gmail.com Signed-off-by: Ingo Molnar --- tools/perf/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 940257b5774e..c16836611d22 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -52,7 +52,10 @@ ifeq ($(ARCH),i386) endif ifeq ($(ARCH),x86_64) ARCH := x86 - IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) + IS_X86_64 := 0 + ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) + IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) + endif ifeq (${IS_X86_64}, 1) RAW_ARCH := x86_64 ARCH_CFLAGS := -DARCH_X86_64 -- cgit v1.2.3 From 7fe2f6399a84760a9af8896ac152728250f82adb Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 30 Mar 2011 16:30:11 +0200 Subject: cpupowerutils - cpufrequtils extended with quite some features CPU power consumption vs performance tuning is no longer limited to CPU frequency switching anymore: deep sleep states, traditional dynamic frequency scaling and hidden turbo/boost frequencies are tied close together and depend on each other. The first two exist on different architectures like PPC, Itanium and ARM, the latter (so far) only on X86. On X86 the APU (CPU+GPU) will only run most efficiently if CPU and GPU has proper power management in place. Users and Developers want to have *one* tool to get an overview what their system supports and to monitor and debug CPU power management in detail. The tool should compile and work on as many architectures as possible. Once this tool stabilizes a bit, it is intended to replace the Intel-specific tools in tools/power/x86 Signed-off-by: Dominik Brodowski --- tools/power/cpupower/.gitignore | 21 + tools/power/cpupower/AUTHORS | 18 + tools/power/cpupower/COPYING | 340 ++++++++ tools/power/cpupower/Makefile | 273 ++++++ tools/power/cpupower/README | 49 ++ tools/power/cpupower/ToDo | 11 + tools/power/cpupower/bench/Makefile | 30 + tools/power/cpupower/bench/README-BENCH | 124 +++ tools/power/cpupower/bench/benchmark.c | 184 ++++ tools/power/cpupower/bench/benchmark.h | 27 + tools/power/cpupower/bench/config.h | 36 + tools/power/cpupower/bench/cpufreq-bench_plot.sh | 104 +++ tools/power/cpupower/bench/cpufreq-bench_script.sh | 101 +++ tools/power/cpupower/bench/example.cfg | 11 + tools/power/cpupower/bench/main.c | 203 +++++ tools/power/cpupower/bench/parse.c | 224 +++++ tools/power/cpupower/bench/parse.h | 50 ++ tools/power/cpupower/bench/system.c | 188 ++++ tools/power/cpupower/bench/system.h | 29 + tools/power/cpupower/build/ccdv.c | 387 +++++++++ tools/power/cpupower/debug/i386/Makefile | 20 + tools/power/cpupower/debug/i386/centrino-decode.c | 113 +++ tools/power/cpupower/debug/i386/dump_psb.c | 196 +++++ tools/power/cpupower/debug/i386/intel_gsic.c | 78 ++ .../power/cpupower/debug/i386/powernow-k8-decode.c | 96 ++ tools/power/cpupower/debug/kernel/Makefile | 23 + .../power/cpupower/debug/kernel/cpufreq-test_tsc.c | 113 +++ tools/power/cpupower/debug/x86_64/Makefile | 14 + .../power/cpupower/debug/x86_64/centrino-decode.c | 1 + .../cpupower/debug/x86_64/powernow-k8-decode.c | 1 + tools/power/cpupower/lib/cpufreq.c | 190 ++++ tools/power/cpupower/lib/cpufreq.h | 215 +++++ tools/power/cpupower/lib/sysfs.c | 671 ++++++++++++++ tools/power/cpupower/lib/sysfs.h | 21 + tools/power/cpupower/man/cpupower-frequency-info.1 | 76 ++ tools/power/cpupower/man/cpupower-frequency-set.1 | 54 ++ tools/power/cpupower/man/cpupower-info.1 | 19 + tools/power/cpupower/man/cpupower-monitor.1 | 179 ++++ tools/power/cpupower/man/cpupower-set.1 | 103 +++ tools/power/cpupower/man/cpupower.1 | 72 ++ tools/power/cpupower/po/cs.po | 944 ++++++++++++++++++++ tools/power/cpupower/po/de.po | 961 +++++++++++++++++++++ tools/power/cpupower/po/fr.po | 947 ++++++++++++++++++++ tools/power/cpupower/po/it.po | 961 +++++++++++++++++++++ tools/power/cpupower/po/pt.po | 957 ++++++++++++++++++++ tools/power/cpupower/utils/builtin.h | 18 + tools/power/cpupower/utils/cpufreq-info.c | 665 ++++++++++++++ tools/power/cpupower/utils/cpufreq-set.c | 357 ++++++++ tools/power/cpupower/utils/cpuidle-info.c | 245 ++++++ tools/power/cpupower/utils/cpupower-info.c | 154 ++++ tools/power/cpupower/utils/cpupower-set.c | 153 ++++ tools/power/cpupower/utils/cpupower.c | 201 +++++ tools/power/cpupower/utils/helpers/amd.c | 137 +++ tools/power/cpupower/utils/helpers/bitmask.c | 290 +++++++ tools/power/cpupower/utils/helpers/bitmask.h | 33 + tools/power/cpupower/utils/helpers/cpuid.c | 145 ++++ tools/power/cpupower/utils/helpers/helpers.h | 180 ++++ tools/power/cpupower/utils/helpers/misc.c | 34 + tools/power/cpupower/utils/helpers/msr.c | 122 +++ tools/power/cpupower/utils/helpers/pci.c | 44 + tools/power/cpupower/utils/helpers/sysfs.c | 350 ++++++++ tools/power/cpupower/utils/helpers/sysfs.h | 23 + tools/power/cpupower/utils/helpers/topology.c | 108 +++ .../cpupower/utils/idle_monitor/amd_fam14h_idle.c | 340 ++++++++ .../cpupower/utils/idle_monitor/cpuidle_sysfs.c | 185 ++++ .../cpupower/utils/idle_monitor/cpupower-monitor.c | 446 ++++++++++ .../cpupower/utils/idle_monitor/cpupower-monitor.h | 68 ++ .../cpupower/utils/idle_monitor/idle_monitors.def | 7 + .../cpupower/utils/idle_monitor/idle_monitors.h | 18 + .../cpupower/utils/idle_monitor/mperf_monitor.c | 258 ++++++ tools/power/cpupower/utils/idle_monitor/nhm_idle.c | 212 +++++ tools/power/cpupower/utils/idle_monitor/snb_idle.c | 189 ++++ 72 files changed, 14417 insertions(+) create mode 100644 tools/power/cpupower/.gitignore create mode 100644 tools/power/cpupower/AUTHORS create mode 100644 tools/power/cpupower/COPYING create mode 100644 tools/power/cpupower/Makefile create mode 100644 tools/power/cpupower/README create mode 100644 tools/power/cpupower/ToDo create mode 100644 tools/power/cpupower/bench/Makefile create mode 100644 tools/power/cpupower/bench/README-BENCH create mode 100644 tools/power/cpupower/bench/benchmark.c create mode 100644 tools/power/cpupower/bench/benchmark.h create mode 100644 tools/power/cpupower/bench/config.h create mode 100644 tools/power/cpupower/bench/cpufreq-bench_plot.sh create mode 100644 tools/power/cpupower/bench/cpufreq-bench_script.sh create mode 100644 tools/power/cpupower/bench/example.cfg create mode 100644 tools/power/cpupower/bench/main.c create mode 100644 tools/power/cpupower/bench/parse.c create mode 100644 tools/power/cpupower/bench/parse.h create mode 100644 tools/power/cpupower/bench/system.c create mode 100644 tools/power/cpupower/bench/system.h create mode 100644 tools/power/cpupower/build/ccdv.c create mode 100644 tools/power/cpupower/debug/i386/Makefile create mode 100644 tools/power/cpupower/debug/i386/centrino-decode.c create mode 100644 tools/power/cpupower/debug/i386/dump_psb.c create mode 100644 tools/power/cpupower/debug/i386/intel_gsic.c create mode 100644 tools/power/cpupower/debug/i386/powernow-k8-decode.c create mode 100644 tools/power/cpupower/debug/kernel/Makefile create mode 100644 tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c create mode 100644 tools/power/cpupower/debug/x86_64/Makefile create mode 120000 tools/power/cpupower/debug/x86_64/centrino-decode.c create mode 120000 tools/power/cpupower/debug/x86_64/powernow-k8-decode.c create mode 100644 tools/power/cpupower/lib/cpufreq.c create mode 100644 tools/power/cpupower/lib/cpufreq.h create mode 100644 tools/power/cpupower/lib/sysfs.c create mode 100644 tools/power/cpupower/lib/sysfs.h create mode 100644 tools/power/cpupower/man/cpupower-frequency-info.1 create mode 100644 tools/power/cpupower/man/cpupower-frequency-set.1 create mode 100644 tools/power/cpupower/man/cpupower-info.1 create mode 100644 tools/power/cpupower/man/cpupower-monitor.1 create mode 100644 tools/power/cpupower/man/cpupower-set.1 create mode 100644 tools/power/cpupower/man/cpupower.1 create mode 100644 tools/power/cpupower/po/cs.po create mode 100644 tools/power/cpupower/po/de.po create mode 100644 tools/power/cpupower/po/fr.po create mode 100644 tools/power/cpupower/po/it.po create mode 100644 tools/power/cpupower/po/pt.po create mode 100644 tools/power/cpupower/utils/builtin.h create mode 100644 tools/power/cpupower/utils/cpufreq-info.c create mode 100644 tools/power/cpupower/utils/cpufreq-set.c create mode 100644 tools/power/cpupower/utils/cpuidle-info.c create mode 100644 tools/power/cpupower/utils/cpupower-info.c create mode 100644 tools/power/cpupower/utils/cpupower-set.c create mode 100644 tools/power/cpupower/utils/cpupower.c create mode 100644 tools/power/cpupower/utils/helpers/amd.c create mode 100644 tools/power/cpupower/utils/helpers/bitmask.c create mode 100644 tools/power/cpupower/utils/helpers/bitmask.h create mode 100644 tools/power/cpupower/utils/helpers/cpuid.c create mode 100644 tools/power/cpupower/utils/helpers/helpers.h create mode 100644 tools/power/cpupower/utils/helpers/misc.c create mode 100644 tools/power/cpupower/utils/helpers/msr.c create mode 100644 tools/power/cpupower/utils/helpers/pci.c create mode 100644 tools/power/cpupower/utils/helpers/sysfs.c create mode 100644 tools/power/cpupower/utils/helpers/sysfs.h create mode 100644 tools/power/cpupower/utils/helpers/topology.c create mode 100644 tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c create mode 100644 tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c create mode 100644 tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c create mode 100644 tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h create mode 100644 tools/power/cpupower/utils/idle_monitor/idle_monitors.def create mode 100644 tools/power/cpupower/utils/idle_monitor/idle_monitors.h create mode 100644 tools/power/cpupower/utils/idle_monitor/mperf_monitor.c create mode 100644 tools/power/cpupower/utils/idle_monitor/nhm_idle.c create mode 100644 tools/power/cpupower/utils/idle_monitor/snb_idle.c (limited to 'tools') diff --git a/tools/power/cpupower/.gitignore b/tools/power/cpupower/.gitignore new file mode 100644 index 000000000000..f8d7b5ac2719 --- /dev/null +++ b/tools/power/cpupower/.gitignore @@ -0,0 +1,21 @@ +.libs +libcpufreq.so +libcpufreq.so.0 +libcpufreq.so.0.0.0 +build/ccdv +cpufreq-info +cpufreq-set +cpufreq-aperf +lib/.libs +lib/cpufreq.lo +lib/cpufreq.o +lib/proc.lo +lib/proc.o +lib/sysfs.lo +lib/sysfs.o +libcpufreq.la +po/cpufrequtils.pot +po/*.gmo +utils/cpufreq-info.o +utils/cpufreq-set.o +utils/cpufreq-aperf.o \ No newline at end of file diff --git a/tools/power/cpupower/AUTHORS b/tools/power/cpupower/AUTHORS new file mode 100644 index 000000000000..090af2cb81b1 --- /dev/null +++ b/tools/power/cpupower/AUTHORS @@ -0,0 +1,18 @@ +Dominik Brodowski + + +Mattia Dongili +via Latisana, 8 +00177 Rome +Italy + + +Goran Koruga +Slovenia + + +Thomas Renninger +SUSE Linux GmbH +Germany + + diff --git a/tools/power/cpupower/COPYING b/tools/power/cpupower/COPYING new file mode 100644 index 000000000000..d60c31a97a54 --- /dev/null +++ b/tools/power/cpupower/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile new file mode 100644 index 000000000000..aef1e3b41792 --- /dev/null +++ b/tools/power/cpupower/Makefile @@ -0,0 +1,273 @@ +# Makefile for cpupowerutils +# +# Copyright (C) 2005,2006 Dominik Brodowski +# +# Based largely on the Makefile for udev by: +# +# Copyright (C) 2003,2004 Greg Kroah-Hartman +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +# --- CONFIGURATION BEGIN --- + +# Set the following to `true' to make a unstripped, unoptimized +# binary. Leave this set to `false' for production use. +DEBUG ?= true + +# make the build silent. Set this to something else to make it noisy again. +V ?= false + +# Internationalization support (output in different languages). +# Requires gettext. +NLS ?= true + +# Set the following to 'true' to build/install the +# cpufreq-bench benchmarking tool +CPUFRQ_BENCH ?= true + +# Prefix to the directories we're installing to +DESTDIR ?= + +# --- CONFIGURATION END --- + + + +# Package-related definitions. Distributions can modify the version +# and _should_ modify the PACKAGE_BUGREPORT definition + +VERSION = 009p1 +LIB_MAJ= 0.0.0 +LIB_MIN= 0 + +PACKAGE = cpupowerutils +PACKAGE_BUGREPORT = cpufreq@vger.kernel.org +LANGUAGES = de fr it cs pt + + +# Directory definitions. These are default and most probably +# do not need to be changed. Please note that DESTDIR is +# added in front of any of them + +bindir ?= /usr/bin +sbindir ?= /usr/sbin +mandir ?= /usr/man +includedir ?= /usr/include +libdir ?= /usr/lib +localedir ?= /usr/share/locale +docdir ?= /usr/share/doc/packages/cpupowerutils +confdir ?= /etc/ + +# Toolchain: what tools do we use, and what options do they need: + +CP = cp -fpR +INSTALL = /usr/bin/install -c +INSTALL_PROGRAM = ${INSTALL} +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_SCRIPT = ${INSTALL_PROGRAM} + +# If you are running a cross compiler, you may want to set this +# to something more interesting, like "arm-linux-". If you want +# to compile vs uClibc, that can be done here as well. +CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc- +CC = $(CROSS)gcc +LD = $(CROSS)gcc +AR = $(CROSS)ar +STRIP = $(CROSS)strip +RANLIB = $(CROSS)ranlib +HOSTCC = gcc + + +# Now we set up the build system +# + +# set up PWD so that older versions of make will work with our build. +PWD = $(shell pwd) + +export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS + +# check if compiler option is supported +cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;} + +# use '-Os' optimization if available, else use -O2 +OPTIMIZATION := $(call cc-supports,-Os,-O2) + +WARNINGS := -Wall -Wchar-subscripts -Wpointer-arith -Wsign-compare +WARNINGS += $(call cc-supports,-Wno-pointer-sign) +WARNINGS += $(call cc-supports,-Wdeclaration-after-statement) +WARNINGS += -Wshadow + +CPPFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \ + -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE + +UTIL_OBJS = utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \ + utils/helpers/sysfs.o utils/helpers/misc.o utils/helpers/cpuid.o \ + utils/helpers/pci.o utils/helpers/bitmask.o \ + utils/idle_monitor/nhm_idle.o utils/idle_monitor/snb_idle.o \ + utils/idle_monitor/amd_fam14h_idle.o utils/idle_monitor/cpuidle_sysfs.o \ + utils/idle_monitor/mperf_monitor.o utils/idle_monitor/cpupower-monitor.o \ + utils/cpupower.o utils/cpufreq-info.o utils/cpufreq-set.o \ + utils/cpupower-set.o utils/cpupower-info.o utils/cpuidle-info.o + +UTIL_HEADERS = utils/helpers/helpers.h utils/idle_monitor/cpupower-monitor.h \ + utils/helpers/bitmask.h \ + utils/idle_monitor/idle_monitors.h utils/idle_monitor/idle_monitors.def + +UTIL_SRC := $(UTIL_OBJS:.o=.c) + +LIB_HEADERS = lib/cpufreq.h lib/sysfs.h +LIB_SRC = lib/cpufreq.c lib/sysfs.c +LIB_OBJS = lib/cpufreq.o lib/sysfs.o + +CFLAGS += -pipe + +ifeq ($(strip $(NLS)),true) + INSTALL_NLS += install-gmo + COMPILE_NLS += update-gmo +endif + +ifeq ($(strip $(CPUFRQ_BENCH)),true) + INSTALL_BENCH += install-bench + COMPILE_BENCH += compile-bench +endif + +CFLAGS += $(WARNINGS) + +ifeq ($(strip $(V)),false) + QUIET=@$(PWD)/build/ccdv + HOST_PROGS=build/ccdv +else + QUIET= + HOST_PROGS= +endif + +# if DEBUG is enabled, then we do not strip or optimize +ifeq ($(strip $(DEBUG)),true) + CFLAGS += -O1 -g + CPPFLAGS += -DDEBUG + STRIPCMD = /bin/true -Since_we_are_debugging +else + CFLAGS += $(OPTIMIZATION) -fomit-frame-pointer + STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment +endif + + +# the actual make rules + +all: ccdv libcpufreq cpupower $(COMPILE_NLS) $(COMPILE_BENCH) + +ccdv: build/ccdv +build/ccdv: build/ccdv.c + @echo "Building ccdv" + @$(HOSTCC) -O1 $< -o $@ + +lib/%.o: $(LIB_SRC) $(LIB_HEADERS) build/ccdv + $(QUIET) $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -o $@ -c lib/$*.c + +libcpufreq.so.$(LIB_MAJ): $(LIB_OBJS) + $(QUIET) $(CC) -shared $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \ + -Wl,-soname,libcpufreq.so.$(LIB_MIN) $(LIB_OBJS) + @ln -sf $@ libcpufreq.so + @ln -sf $@ libcpufreq.so.$(LIB_MIN) + +libcpufreq: libcpufreq.so.$(LIB_MAJ) + +# Let all .o files depend on its .c file and all headers +# Might be worth to put this into utils/Makefile at some point of time +$(UTIL_OBJS): $(UTIL_HEADERS) + +.c.o: + $(QUIET) $(CC) $(CFLAGS) $(CPPFLAGS) -I./lib -I ./utils -o $@ -c $*.c + +cpupower: $(UTIL_OBJS) libcpufreq + $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -lcpufreq -lrt -lpci -L. -o $@ $(UTIL_OBJS) + $(STRIPCMD) $@ + +po/$(PACKAGE).pot: $(UTIL_SRC) + @xgettext --default-domain=$(PACKAGE) --add-comments \ + --keyword=_ --keyword=N_ $(UTIL_SRC) && \ + test -f $(PACKAGE).po && \ + mv -f $(PACKAGE).po po/$(PACKAGE).pot + +update-gmo: po/$(PACKAGE).pot + @for HLANG in $(LANGUAGES); do \ + echo -n "Translating $$HLANG "; \ + if msgmerge po/$$HLANG.po po/$(PACKAGE).pot -o \ + po/$$HLANG.new.po; then \ + mv -f po/$$HLANG.new.po po/$$HLANG.po; \ + else \ + echo "msgmerge for $$HLANG failed!"; \ + rm -f po/$$HLANG.new.po; \ + fi; \ + msgfmt --statistics -o po/$$HLANG.gmo po/$$HLANG.po; \ + done; + +compile-bench: libcpufreq.so.$(LIB_MAJ) + @V=$(V) confdir=$(confdir) $(MAKE) -C bench + +clean: + -find . \( -not -type d \) -and \( -name '*~' -o -name '*.[oas]' \) -type f -print \ + | xargs rm -f + -rm -f $(UTIL_BINS) + -rm -f $(IDLE_OBJS) + -rm -f cpupower + -rm -f libcpufreq.so* + -rm -f build/ccdv + -rm -rf po/*.gmo po/*.pot + $(MAKE) -C bench clean + + +install-lib: + $(INSTALL) -d $(DESTDIR)${libdir} + $(CP) libcpufreq.so* $(DESTDIR)${libdir}/ + $(INSTALL) -d $(DESTDIR)${includedir} + $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h + +install-tools: + $(INSTALL) -d $(DESTDIR)${bindir} + $(INSTALL_PROGRAM) cpupower $(DESTDIR)${bindir} + +install-man: + $(INSTALL_DATA) -D man/cpupower.1 $(DESTDIR)${mandir}/man1/cpupower.1 + $(INSTALL_DATA) -D man/cpupower-frequency-set.1 $(DESTDIR)${mandir}/man1/cpupower-frequency-set.1 + $(INSTALL_DATA) -D man/cpupower-frequency-info.1 $(DESTDIR)${mandir}/man1/cpupower-frequency-info.1 + $(INSTALL_DATA) -D man/cpupower-set.1 $(DESTDIR)${mandir}/man1/cpupower-set.1 + $(INSTALL_DATA) -D man/cpupower-info.1 $(DESTDIR)${mandir}/man1/cpupower-info.1 + $(INSTALL_DATA) -D man/cpupower-monitor.1 $(DESTDIR)${mandir}/man1/cpupower-monitor.1 + +install-gmo: + $(INSTALL) -d $(DESTDIR)${localedir} + for HLANG in $(LANGUAGES); do \ + echo '$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo'; \ + $(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo; \ + done; + +install-bench: + @#DESTDIR must be set from outside to survive + @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench install + +install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH) + +uninstall: + - rm -f $(DESTDIR)${libdir}/libcpufreq.* + - rm -f $(DESTDIR)${includedir}/cpufreq.h + - rm -f $(DESTDIR)${bindir}/utils/cpupower + - rm -f $(DESTDIR)${mandir}/man1/cpufreq-set.1 + - rm -f $(DESTDIR)${mandir}/man1/cpufreq-info.1 + - for HLANG in $(LANGUAGES); do \ + rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo; \ + done; + +.PHONY: all utils libcpufreq ccdv update-po update-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 @@ +The cpufrequtils package (homepage: +http://www.kernel.org/pub/linux/utils/kernel/cpufreq/cpufrequtils.html ) +consists of the following elements: + +requirements +------------ + +On x86 pciutils is needed at runtime (-lpci). +For compilation pciutils-devel (pci/pci.h) and a gcc version +providing cpuid.h is needed. +For both it's not explicitly checked for (yet). + + +libcpufreq +---------- + +"libcpufreq" is a library which offers a unified access method for userspace +tools and programs to the cpufreq core and drivers in the Linux kernel. This +allows for code reduction in userspace tools, a clean implementation of +the interaction to the cpufreq core, and support for both the sysfs and proc +interfaces [depending on configuration, see below]. + + +compilation and installation +---------------------------- + +make +su +make install + +should suffice on most systems. It builds default libcpufreq, +cpufreq-set and cpufreq-info files and installs them in /usr/lib and +/usr/bin, respectively. If you want to set up the paths differently and/or +want to configure the package to your specific needs, you need to open +"Makefile" with an editor of your choice and edit the block marked +CONFIGURATION. + + +THANKS +------ +Many thanks to Mattia Dongili who wrote the autotoolization and +libtoolization, the manpages and the italian language file for cpufrequtils; +to Dave Jones for his feedback and his dump_psb tool; to Bruno Ducrot for his +powernow-k8-decode and intel_gsic tools as well as the french language file; +and to various others commenting on the previous (pre-)releases of +cpufrequtils. + + + 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 @@ +ToDos sorted by priority: + +- Use bitmask functions to parse CPU topology more robust + (current implementation has issues on AMD) +- Try to read out boost states and frequencies on Intel +- Adjust README +- Somewhere saw the ability to read power consumption of + RAM from HW on Intel SandyBridge -> another monitor? +- Add another c1e debug idle monitor + -> Is by design racy with BIOS, but could be added + 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..3d8fa21855f6 --- /dev/null +++ b/tools/power/cpupower/bench/Makefile @@ -0,0 +1,30 @@ +LIBS = -L../ -lm -lcpufreq + +OBJS = main.o parse.o system.o benchmark.o +CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\" + +ifeq ($(strip $(V)),false) + CC=@../build/ccdv gcc +else + CC=gcc +endif + +cpufreq-bench: $(OBJS) + $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS) + +all: cpufreq-bench + +install: + mkdir -p $(DESTDIR)/$(sbindir) + mkdir -p $(DESTDIR)/$(bindir) + mkdir -p $(DESTDIR)/$(docdir) + mkdir -p $(DESTDIR)/$(confdir) + install -m 755 cpufreq-bench $(DESTDIR)/$(sbindir)/cpufreq-bench + install -m 755 cpufreq-bench_plot.sh $(DESTDIR)/$(bindir)/cpufreq-bench_plot.sh + install -m 644 README-BENCH $(DESTDIR)/$(docdir)/README-BENCH + install -m 755 cpufreq-bench_script.sh $(DESTDIR)/$(docdir)/cpufreq-bench_script.sh + install -m 644 example.cfg $(DESTDIR)/$(confdir)/cpufreq-bench.conf + +clean: + rm -f *.o + 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 @@ +This is cpufreq-bench, a microbenchmark for the cpufreq framework. + +Purpose +======= + +What is this benchmark for: + - Identify worst case performance loss when doing dynamic frequency + scaling using Linux kernel governors + - Identify average reaction time of a governor to CPU load changes + - (Stress) Testing whether a cpufreq low level driver or governor works + as expected + - Identify cpufreq related performance regressions between kernels + - Possibly Real time priority testing? -> what happens if there are + processes with a higher prio than the governor's kernel thread + - ... + +What this benchmark does *not* cover: + - Power saving related regressions (In fact as better the performance + throughput is, the worse the power savings will be, but the first should + mostly count more...) + - Real world (workloads) + + +Description +=========== + +cpufreq-bench helps to test the condition of a given cpufreq governor. +For that purpose, it compares the performance governor to a configured +powersave module. + + +How it works +============ +You can specify load (100% CPU load) and sleep (0% CPU load) times in us which +will be run X time in a row (cycles): + + sleep=25000 + load=25000 + cycles=20 + +This part of the configuration file will create 25ms load/sleep turns, +repeated 20 times. + +Adding this: + sleep_step=25000 + load_step=25000 + rounds=5 +Will increase load and sleep time by 25ms 5 times. +Together you get following test: +25ms load/sleep time repeated 20 times (cycles). +50ms load/sleep time repeated 20 times (cycles). +.. +100ms load/sleep time repeated 20 times (cycles). + +First it is calibrated how long a specific CPU intensive calculation +takes on this machine and needs to be run in a loop using the performance +governor. +Then the above test runs are processed using the performance governor +and the governor to test. The time the calculation really needed +with the dynamic freq scaling governor is compared with the time needed +on full performance and you get the overall performance loss. + + +Example of expected results with ondemand governor: + +This shows expected results of the first two test run rounds from +above config, you there have: + +100% CPU load (load) | 0 % CPU load (sleep) | round + 25 ms | 25 ms | 1 + 50 ms | 50 ms | 2 + +For example if ondemand governor is configured to have a 50ms +sampling rate you get: + +In round 1, ondemand should have rather static 50% load and probably +won't ever switch up (as long as up_threshold is above). + +In round 2, if the ondemand sampling times exactly match the load/sleep +trigger of the cpufreq-bench, you will see no performance loss (compare with +below possible ondemand sample kick ins (1)): + +But if ondemand always kicks in in the middle of the load sleep cycles, it +will always see 50% loads and you get worst performance impact never +switching up (compare with below possible ondemand sample kick ins (2)):: + + 50 50 50 50ms ->time +load -----| |-----| |-----| |-----| + | | | | | | | +sleep |-----| |-----| |-----| |---- + |-----|-----|-----|-----|-----|-----|-----|---- ondemand sampling (1) + 100 0 100 0 100 0 100 load seen by ondemand(%) + |-----|-----|-----|-----|-----|-----|-----|-- ondemand sampling (2) + 50 50 50 50 50 50 50 load seen by ondemand(%) + +You can easily test all kind of load/sleep times and check whether your +governor in average behaves as expected. + + +ToDo +==== + +Provide a gnuplot utility script for easy generation of plots to present +the outcome nicely. + + +cpufreq-bench Command Usage +=========================== +-l, --load= initial load time in us +-s, --sleep= initial sleep time in us +-x, --load-step= time to be added to load time, in us +-y, --sleep-step= time to be added to sleep time, in us +-c, --cpu= CPU Number to use, starting at 0 +-p, --prio= scheduler priority, HIGH, LOW or DEFAULT +-g, --governor= cpufreq governor to test +-n, --cycles= load/sleep cycles to get an avarage value to compare +-r, --rounds load/sleep rounds +-f, --file= config file to use +-o, --output= output dir, must exist +-v, --verbose verbose output on/off + +Due to the high priority, the application may not be responsible for some time. +After the benchmark, the logfile is saved in OUTPUTDIR/benchmark_TIMESTAMP.log + diff --git a/tools/power/cpupower/bench/benchmark.c b/tools/power/cpupower/bench/benchmark.c new file mode 100644 index 000000000000..f538633b8b41 --- /dev/null +++ b/tools/power/cpupower/bench/benchmark.c @@ -0,0 +1,184 @@ +/* cpufreq-bench CPUFreq microbenchmark + * + * Copyright (C) 2008 Christian Kornacker + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include "config.h" +#include "system.h" +#include "benchmark.h" + +/* Print out progress if we log into a file */ +#define show_progress(total_time, progress_time) \ +if (config->output != stdout) { \ + fprintf(stdout, "Progress: %02lu %%\r", \ + (progress_time * 100) / total_time); \ + fflush(stdout); \ +} + +/** + * compute how many rounds of calculation we should do + * to get the given load time + * + * @param load aimed load time in µs + * + * @retval rounds of calculation + **/ + +unsigned int calculate_timespace(long load, struct config *config) +{ + int i; + long long now, then; + unsigned int estimated = GAUGECOUNT; + unsigned int rounds = 0; + unsigned int timed = 0; + + if (config->verbose) + printf("calibrating load of %lius, please wait...\n", load); + + /* get the initial calculation time for a specific number of rounds */ + now = get_time(); + ROUNDS(estimated); + then = get_time(); + + timed = (unsigned int)(then - now); + + /* approximation of the wanted load time by comparing with the + * initial calculation time */ + for (i= 0; i < 4; i++) + { + rounds = (unsigned int)(load * estimated / timed); + dprintf("calibrating with %u rounds\n", rounds); + now = get_time(); + ROUNDS(rounds); + then = get_time(); + + timed = (unsigned int)(then - now); + estimated = rounds; + } + if (config->verbose) + printf("calibration done\n"); + + return estimated; +} + +/** + * benchmark + * generates a specific sleep an load time with the performance + * governor and compares the used time for same calculations done + * with the configured powersave governor + * + * @param config config values for the benchmark + * + **/ + +void start_benchmark(struct config *config) +{ + unsigned int _round, cycle; + long long now, then; + long sleep_time = 0, load_time = 0; + long performance_time = 0, powersave_time = 0; + unsigned int calculations; + unsigned long total_time = 0, progress_time = 0; + + sleep_time = config->sleep; + load_time = config->load; + + /* For the progress bar */ + for (_round=1; _round <= config->rounds; _round++) + total_time += _round * (config->sleep + config->load); + total_time *= 2; /* powersave and performance cycles */ + + for (_round=0; _round < config->rounds; _round++) { + performance_time = 0LL; + powersave_time = 0LL; + + show_progress(total_time, progress_time); + + /* set the cpufreq governor to "performance" which disables + * P-State switching. */ + if (set_cpufreq_governor("performance", config->cpu) != 0) + return; + + /* calibrate the calculation time. the resulting calculation + * _rounds should produce a load which matches the configured + * load time */ + calculations = calculate_timespace(load_time, config); + + if (config->verbose) + printf("_round %i: doing %u cycles with %u calculations" + " for %lius\n", _round + 1, config->cycles, + calculations, load_time); + + fprintf(config->output, "%u %li %li ", + _round, load_time, sleep_time); + + if (config->verbose) { + printf("avarage: %lius, rps:%li\n", load_time / calculations, 1000000 * calculations / load_time); + } + + /* do some sleep/load cycles with the performance governor */ + for (cycle = 0; cycle < config->cycles; cycle++) { + now = get_time(); + usleep(sleep_time); + ROUNDS(calculations); + then = get_time(); + performance_time += then - now - sleep_time; + if (config->verbose) + printf("performance cycle took %lius, sleep: %lius, load: %lius, rounds: %u\n", + (long)(then - now), sleep_time, load_time, calculations); + } + fprintf(config->output, "%li ", performance_time / config->cycles); + + progress_time += sleep_time + load_time; + show_progress(total_time, progress_time); + + /* set the powersave governor which activates P-State switching + * again */ + if (set_cpufreq_governor(config->governor, config->cpu) != 0) + return; + + /* again, do some sleep/load cycles with the powersave governor */ + for (cycle = 0; cycle < config->cycles; cycle++) { + now = get_time(); + usleep(sleep_time); + ROUNDS(calculations); + then = get_time(); + powersave_time += then - now - sleep_time; + if (config->verbose) + printf("powersave cycle took %lius, sleep: %lius, load: %lius, rounds: %u\n", + (long)(then - now), sleep_time, load_time, calculations); + } + + progress_time += sleep_time + load_time; + + /* compare the avarage sleep/load cycles */ + fprintf(config->output, "%li ", powersave_time / config->cycles); + fprintf(config->output, "%.3f\n", performance_time * 100.0 / powersave_time); + fflush(config->output); + + if (config->verbose) + printf("performance is at %.2f%%\n", performance_time * 100.0 / powersave_time); + + sleep_time += config->sleep_step; + load_time += config->load_step; + } +} + diff --git a/tools/power/cpupower/bench/benchmark.h b/tools/power/cpupower/bench/benchmark.h new file mode 100644 index 000000000000..0691f91b720b --- /dev/null +++ b/tools/power/cpupower/bench/benchmark.h @@ -0,0 +1,27 @@ +/* cpufreq-bench CPUFreq microbenchmark + * + * Copyright (C) 2008 Christian Kornacker + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* load loop, this schould take about 1 to 2ms to complete */ +#define ROUNDS(x) {unsigned int rcnt; \ + for (rcnt = 0; rcnt< x*1000; rcnt++) { \ + (void)(((int)(pow(rcnt, rcnt) * sqrt(rcnt*7230970)) ^ 7230716) ^ (int)atan2(rcnt, rcnt)); \ + }} \ + + +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..9690f1be32fd --- /dev/null +++ b/tools/power/cpupower/bench/config.h @@ -0,0 +1,36 @@ +/* cpufreq-bench CPUFreq microbenchmark + * + * Copyright (C) 2008 Christian Kornacker + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* initial loop count for the load calibration */ +#define GAUGECOUNT 1500 + +/* default scheduling policy SCHED_OTHER */ +#define SCHEDULER SCHED_OTHER + +#define PRIORITY_DEFAULT 0 +#define PRIORITY_HIGH sched_get_priority_max(SCHEDULER) +#define PRIORITY_LOW sched_get_priority_min(SCHEDULER) + +/* enable further debug messages */ +#ifdef DEBUG +#define dprintf printf +#else +#define dprintf( ... ) while(0) { } +#endif + 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 @@ +#!/bin/bash + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# Author/Copyright(c): 2009, Thomas Renninger , Novell Inc. + +# Helper script to easily create nice plots of your cpufreq-bench results + +dir=`mktemp -d` +output_file="cpufreq-bench.png" +global_title="cpufreq-bench plot" +picture_type="jpeg" +file[0]="" + +function usage() +{ + echo "cpufreq-bench_plot.sh [OPTIONS] logfile [measure_title] [logfile [measure_title]] ...]" + echo + echo "Options" + echo " -o output_file" + echo " -t global_title" + echo " -p picture_type [jpeg|gif|png|postscript|...]" + exit 1 +} + +if [ $# -eq 0 ];then + echo "No benchmark results file provided" + echo + usage +fi + +while getopts o:t:p: name ; do + case $name in + o) + output_file="$OPTARG".$picture_type + ;; + t) + global_title="$OPTARG" + ;; + p) + picture_type="$OPTARG" + ;; + ?) + usage + ;; + esac +done +shift $(($OPTIND -1)) + +plots=0 +while [ "$1" ];do + if [ ! -f "$1" ];then + echo "File $1 does not exist" + usage + fi + file[$plots]="$1" + title[$plots]="$2" + # echo "File: ${file[$plots]} - ${title[plots]}" + shift;shift + plots=$((plots + 1)) +done + +echo "set terminal $picture_type" >> $dir/plot_script.gpl +echo "set output \"$output_file\"" >> $dir/plot_script.gpl +echo "set title \"$global_title\"" >> $dir/plot_script.gpl +echo "set xlabel \"sleep/load time\"" >> $dir/plot_script.gpl +echo "set ylabel \"Performance (%)\"" >> $dir/plot_script.gpl + +for((plot=0;plot<$plots;plot++));do + + # Sanity check + ###### I am to dump to get this redirected to stderr/stdout in one awk call... ##### + 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}' + ###### I am to dump to get this redirected in one awk call... ##### + + # Parse out load time (which must be equal to sleep time for a plot), divide it by 1000 + # to get ms and parse out the performance in percentage and write it to a temp file for plotting + cat ${file[$plot]} |grep -v "^#" |awk '{printf "%lu %.1f\n",$2/1000, $6}' >$dir/data_$plot + + if [ $plot -eq 0 ];then + echo -n "plot " >> $dir/plot_script.gpl + fi + echo -n "\"$dir/data_$plot\" title \"${title[$plot]}\" with lines" >> $dir/plot_script.gpl + if [ $(($plot + 1)) -ne $plots ];then + echo -n ", " >> $dir/plot_script.gpl + fi +done +echo >> $dir/plot_script.gpl + +gnuplot $dir/plot_script.gpl +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 @@ +#!/bin/bash + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# Author/Copyright(c): 2009, Thomas Renninger , Novell Inc. + +# Ondemand up_threshold and sampling rate test script for cpufreq-bench +# mircobenchmark. +# Modify the general variables at the top or extend or copy out parts +# if you want to test other things +# + +# Default with latest kernels is 95, before micro account patches +# it was 80, cmp. with git commit 808009131046b62ac434dbc796 +UP_THRESHOLD="60 80 95" +# Depending on the kernel and the HW sampling rate could be restricted +# and cannot be set that low... +# E.g. before git commit cef9615a853ebc4972084f7 one could only set +# min sampling rate of 80000 if CONFIG_HZ=250 +SAMPLING_RATE="20000 80000" + +function measure() +{ + local -i up_threshold_set + local -i sampling_rate_set + + for up_threshold in $UP_THRESHOLD;do + for sampling_rate in $SAMPLING_RATE;do + # Set values in sysfs + echo $up_threshold >/sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold + echo $sampling_rate >/sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate + up_threshold_set=$(cat /sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold) + sampling_rate_set=$(cat /sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate) + + # Verify set values in sysfs + if [ ${up_threshold_set} -eq ${up_threshold} ];then + echo "up_threshold: $up_threshold, set in sysfs: ${up_threshold_set}" + else + echo "WARNING: Tried to set up_threshold: $up_threshold, set in sysfs: ${up_threshold_set}" + fi + if [ ${sampling_rate_set} -eq ${sampling_rate} ];then + echo "sampling_rate: $sampling_rate, set in sysfs: ${sampling_rate_set}" + else + echo "WARNING: Tried to set sampling_rate: $sampling_rate, set in sysfs: ${sampling_rate_set}" + fi + + # Benchmark + cpufreq-bench -o /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate} + done + done +} + +function create_plots() +{ + local command + + for up_threshold in $UP_THRESHOLD;do + 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 %\"" + for sampling_rate in $SAMPLING_RATE;do + command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"sampling_rate = $sampling_rate\"" + done + echo $command + eval "$command" + echo + done + + for sampling_rate in $SAMPLING_RATE;do + 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\"" + for up_threshold in $UP_THRESHOLD;do + command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"up_threshold = $up_threshold\"" + done + echo $command + eval "$command" + echo + done + + 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\"" + for sampling_rate in $SAMPLING_RATE;do + for up_threshold in $UP_THRESHOLD;do + command="${command} /var/log/cpufreq-bench/up_threshold_${up_threshold}_sampling_rate_${sampling_rate}/* \"up_threshold = $up_threshold - sampling_rate = $sampling_rate\"" + done + done + echo "$command" + eval "$command" +} + +measure +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 @@ +sleep = 50000 +load = 50000 +cpu = 0 +priority = LOW +output = /var/log/cpufreq-bench +sleep_step = 50000 +load_step = 50000 +cycles = 20 +rounds = 40 +verbose = 0 +governor = ondemand diff --git a/tools/power/cpupower/bench/main.c b/tools/power/cpupower/bench/main.c new file mode 100644 index 000000000000..60953fc93431 --- /dev/null +++ b/tools/power/cpupower/bench/main.c @@ -0,0 +1,203 @@ +/* cpufreq-bench CPUFreq microbenchmark + * + * Copyright (C) 2008 Christian Kornacker + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "system.h" +#include "benchmark.h" + +static struct option long_options[] = +{ + {"output", 1, 0, 'o'}, + {"sleep", 1, 0, 's'}, + {"load", 1, 0, 'l'}, + {"verbose", 0, 0, 'v'}, + {"cpu", 1, 0, 'c'}, + {"governor", 1, 0, 'g'}, + {"prio", 1, 0, 'p'}, + {"file", 1, 0, 'f'}, + {"cycles", 1, 0, 'n'}, + {"rounds", 1, 0, 'r'}, + {"load-step", 1, 0, 'x'}, + {"sleep-step", 1, 0, 'y'}, + {"help", 0, 0, 'h'}, + {0, 0, 0, 0} +}; + +/******************************************************************* + usage +*******************************************************************/ + +void usage() +{ + printf("usage: ./bench\n"); + printf("Options:\n"); + printf(" -l, --load=\t\tinitial load time in us\n"); + printf(" -s, --sleep=\t\tinitial sleep time in us\n"); + printf(" -x, --load-step=\ttime to be added to load time, in us\n"); + printf(" -y, --sleep-step=\ttime to be added to sleep time, in us\n"); + printf(" -c, --cpu=\t\t\tCPU Nr. to use, starting at 0\n"); + printf(" -p, --prio=\t\t\tscheduler priority, HIGH, LOW or DEFAULT\n"); + printf(" -g, --governor=\t\tcpufreq governor to test\n"); + printf(" -n, --cycles=\t\t\tload/sleep cycles\n"); + printf(" -r, --rounds\t\t\tload/sleep rounds\n"); + printf(" -f, --file=\t\tconfig file to use\n"); + printf(" -o, --output=\t\t\toutput path. Filename will be OUTPUTPATH/benchmark_TIMESTAMP.log\n"); + printf(" -v, --verbose\t\t\t\tverbose output on/off\n"); + printf(" -h, --help\t\t\t\tPrint this help screen\n"); + exit (1); +} + +/******************************************************************* + main +*******************************************************************/ + +int main(int argc, char **argv) +{ + int c; + int option_index = 0; + struct config *config = NULL; + + config = prepare_default_config(); + + if (config == NULL) + return EXIT_FAILURE; + + while (1) { + c = getopt_long (argc, argv, "hg:o:s:l:vc:p:f:n:r:x:y:", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 'o': + if (config->output != NULL) + fclose(config->output); + + config->output = prepare_output(optarg); + + if (config->output == NULL) + return EXIT_FAILURE; + + dprintf("user output path -> %s\n", optarg); + break; + case 's': + sscanf(optarg, "%li", &config->sleep); + dprintf("user sleep time -> %s\n", optarg); + break; + case 'l': + sscanf(optarg, "%li", &config->load); + dprintf("user load time -> %s\n", optarg); + break; + case 'c': + sscanf(optarg, "%u", &config->cpu); + dprintf("user cpu -> %s\n", optarg); + break; + case 'g': + strncpy(config->governor, optarg, 14); + dprintf("user governor -> %s\n", optarg); + break; + case 'p': + if (string_to_prio(optarg) != SCHED_ERR) { + config->prio = string_to_prio(optarg); + dprintf("user prio -> %s\n", optarg); + } else { + if (config != NULL) { + if (config->output != NULL) + fclose(config->output); + free(config); + } + usage(); + } + break; + case 'n': + sscanf(optarg, "%u", &config->cycles); + dprintf("user cycles -> %s\n", optarg); + break; + case 'r': + sscanf(optarg, "%u", &config->rounds); + dprintf("user rounds -> %s\n", optarg); + break; + case 'x': + sscanf(optarg, "%li", &config->load_step); + dprintf("user load_step -> %s\n", optarg); + break; + case 'y': + sscanf(optarg, "%li", &config->sleep_step); + dprintf("user sleep_step -> %s\n", optarg); + break; + case 'f': + if (prepare_config(optarg, config)) + return EXIT_FAILURE; + break; + case 'v': + config->verbose = 1; + dprintf("verbose output enabled\n"); + break; + case 'h': + case '?': + default: + if (config != NULL) { + if (config->output != NULL) + fclose(config->output); + free(config); + } + usage(); + } + } + + if (config->verbose) { + printf("starting benchmark with parameters:\n"); + printf("config:\n\t" + "sleep=%li\n\t" + "load=%li\n\t" + "sleep_step=%li\n\t" + "load_step=%li\n\t" + "cpu=%u\n\t" + "cycles=%u\n\t" + "rounds=%u\n\t" + "governor=%s\n\n", + config->sleep, + config->load, + config->sleep_step, + config->load_step, + config->cpu, + config->cycles, + config->rounds, + config->governor); + } + + prepare_user(config); + prepare_system(config); + start_benchmark(config); + + if (config->output != stdout) + fclose(config->output); + + free(config); + + return EXIT_SUCCESS; +} + diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c new file mode 100644 index 000000000000..3b270ac92c46 --- /dev/null +++ b/tools/power/cpupower/bench/parse.c @@ -0,0 +1,224 @@ +/* cpufreq-bench CPUFreq microbenchmark + * + * Copyright (C) 2008 Christian Kornacker + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "parse.h" +#include "config.h" + +/** + * converts priority string to priority + * + * @param str string that represents a scheduler priority + * + * @retval priority + * @retval SCHED_ERR when the priority doesn't exit + **/ + +enum sched_prio string_to_prio(const char *str) +{ + if (strncasecmp("high", str, strlen(str)) == 0) + return SCHED_HIGH; + else if (strncasecmp("default", str, strlen(str)) == 0) + return SCHED_DEFAULT; + else if (strncasecmp("low", str, strlen(str)) == 0) + return SCHED_LOW; + else + return SCHED_ERR; +} + +/** + * create and open logfile + * + * @param dir directory in which the logfile should be created + * + * @retval logfile on success + * @retval NULL when the file can't be created + **/ + +FILE *prepare_output(const char *dirname) +{ + FILE *output = NULL; + int len; + char *filename; + struct utsname sysdata; + DIR *dir; + + dir = opendir(dirname); + if (dir == NULL) { + if (mkdir(dirname, 0755)) { + perror("mkdir"); + fprintf(stderr, "error: Cannot create dir %s\n", + dirname); + return NULL; + } + } + + len = strlen(dirname) + 30; + filename = malloc(sizeof(char) * len); + + if (uname(&sysdata) == 0) { + len += strlen(sysdata.nodename) + strlen(sysdata.release); + filename = realloc(filename, sizeof(char) * len); + + if(filename == NULL) { + perror("realloc"); + return NULL; + } + + snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log", + dirname, sysdata.nodename, sysdata.release, time(NULL)); + } else { + snprintf(filename, len -1, "%s/benchmark_%li.log", dirname, time(NULL)); + } + + dprintf("logilename: %s\n", filename); + + if ((output = fopen(filename, "w+")) == NULL) { + perror("fopen"); + fprintf(stderr, "error: unable to open logfile\n"); + } + + fprintf(stdout, "Logfile: %s\n", filename); + + free(filename); + fprintf(output, "#round load sleep performance powersave percentage\n"); + return output; +} + +/** + * returns the default config + * + * @retval default config on success + * @retval NULL when the output file can't be created + **/ + +struct config *prepare_default_config() +{ + struct config *config = malloc(sizeof(struct config)); + + dprintf("loading defaults\n"); + + config->sleep = 500000; + config->load = 500000; + config->sleep_step = 500000; + config->load_step = 500000; + config->cycles = 5; + config->rounds = 50; + config->cpu = 0; + config->prio = SCHED_HIGH; + config->verbose = 0; + strncpy(config->governor, "ondemand", 8); + + config->output = stdout; + +#ifdef DEFAULT_CONFIG_FILE + if (prepare_config(DEFAULT_CONFIG_FILE, config)) + return NULL; +#endif + return config; +} + +/** + * parses config file and returns the config to the caller + * + * @param path config file name + * + * @retval 1 on error + * @retval 0 on success + **/ + +int prepare_config(const char *path, struct config *config) +{ + size_t len = 0; + char *opt, *val, *line = NULL; + FILE *configfile = fopen(path, "r"); + + if (config == NULL) { + fprintf(stderr, "error: config is NULL\n"); + return 1; + } + + if (configfile == NULL) { + perror("fopen"); + fprintf(stderr, "error: unable to read configfile\n"); + free(config); + return 1; + } + + while (getline(&line, &len, configfile) != -1) + { + if (line[0] == '#' || line[0] == ' ') + continue; + + sscanf(line, "%as = %as", &opt, &val); + + dprintf("parsing: %s -> %s\n", opt, val); + + if (strncmp("sleep", opt, strlen(opt)) == 0) + sscanf(val, "%li", &config->sleep); + + else if (strncmp("load", opt, strlen(opt)) == 0) + sscanf(val, "%li", &config->load); + + else if (strncmp("load_step", opt, strlen(opt)) == 0) + sscanf(val, "%li", &config->load_step); + + else if (strncmp("sleep_step", opt, strlen(opt)) == 0) + sscanf(val, "%li", &config->sleep_step); + + else if (strncmp("cycles", opt, strlen(opt)) == 0) + sscanf(val, "%u", &config->cycles); + + else if (strncmp("rounds", opt, strlen(opt)) == 0) + sscanf(val, "%u", &config->rounds); + + else if (strncmp("verbose", opt, strlen(opt)) == 0) + sscanf(val, "%u", &config->verbose); + + else if (strncmp("output", opt, strlen(opt)) == 0) + config->output = prepare_output(val); + + else if (strncmp("cpu", opt, strlen(opt)) == 0) + sscanf(val, "%u", &config->cpu); + + else if (strncmp("governor", opt, 14) == 0) + strncpy(config->governor, val, 14); + + else if (strncmp("priority", opt, strlen(opt)) == 0) { + if (string_to_prio(val) != SCHED_ERR) + config->prio = string_to_prio(val); + } + } + + free(line); + free(opt); + free(val); + + return 0; +} diff --git a/tools/power/cpupower/bench/parse.h b/tools/power/cpupower/bench/parse.h new file mode 100644 index 000000000000..9fcdfa23dd9c --- /dev/null +++ b/tools/power/cpupower/bench/parse.h @@ -0,0 +1,50 @@ +/* cpufreq-bench CPUFreq microbenchmark + * + * Copyright (C) 2008 Christian Kornacker + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* struct that holds the required config parameters */ +struct config +{ + long sleep; /* sleep time in µs */ + long load; /* load time in µs */ + long sleep_step; /* time value which changes the + * sleep time after every round in µs */ + long load_step; /* time value which changes the + * load time after every round in µs */ + unsigned int cycles; /* calculation cycles with the same sleep/load time */ + unsigned int rounds; /* calculation rounds with iterated sleep/load time */ + unsigned int cpu; /* cpu for which the affinity is set */ + char governor[15]; /* cpufreq governor */ + enum sched_prio /* possible scheduler priorities */ + { + SCHED_ERR=-1,SCHED_HIGH, SCHED_DEFAULT, SCHED_LOW + } prio; + + unsigned int verbose; /* verbose output */ + FILE *output; /* logfile */ + char *output_filename; /* logfile name, must be freed at the end + if output != NULL and output != stdout*/ +}; + +enum sched_prio string_to_prio(const char *str); + +FILE *prepare_output(const char *dir); + +int prepare_config(const char *path, struct config *config); +struct config *prepare_default_config(); + diff --git a/tools/power/cpupower/bench/system.c b/tools/power/cpupower/bench/system.c new file mode 100644 index 000000000000..3e3a82e8bdd9 --- /dev/null +++ b/tools/power/cpupower/bench/system.c @@ -0,0 +1,188 @@ +/* cpufreq-bench CPUFreq microbenchmark + * + * Copyright (C) 2008 Christian Kornacker + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#include + +#include + +#include "config.h" +#include "system.h" + +/** + * returns time since epoch in µs + * + * @retval time + **/ + +long long int get_time() +{ + struct timeval now; + + gettimeofday(&now, NULL); + + return (long long int)(now.tv_sec * 1000000LL + now.tv_usec); +} + +/** + * sets the cpufreq governor + * + * @param governor cpufreq governor name + * @param cpu cpu for which the governor should be set + * + * @retval 0 on success + * @retval -1 when failed + **/ + +int set_cpufreq_governor(char *governor, unsigned int cpu) +{ + + dprintf("set %s as cpufreq governor\n", governor); + + if (cpufreq_cpu_exists(cpu) != 0) { + perror("cpufreq_cpu_exists"); + fprintf(stderr, "error: cpu %u does not exist\n", cpu); + return -1; + } + + if (cpufreq_modify_policy_governor(cpu, governor) != 0) { + perror("cpufreq_modify_policy_governor"); + fprintf(stderr, "error: unable to set %s governor\n", governor); + return -1; + } + + return 0; +} + +/** + * sets cpu affinity for the process + * + * @param cpu cpu# to which the affinity should be set + * + * @retval 0 on success + * @retval -1 when setting the affinity failed + **/ + +int set_cpu_affinity(unsigned int cpu) +{ + cpu_set_t cpuset; + + CPU_ZERO(&cpuset); + CPU_SET(cpu, &cpuset); + + dprintf("set affinity to cpu #%u\n", cpu); + + if (sched_setaffinity(getpid(), sizeof(cpu_set_t), &cpuset) < 0) { + perror("sched_setaffinity"); + fprintf(stderr, "warning: unable to set cpu affinity\n"); + return -1; + } + + return 0; +} + +/** + * sets the process priority parameter + * + * @param priority priority value + * + * @retval 0 on success + * @retval -1 when setting the priority failed + **/ + +int set_process_priority(int priority) +{ + struct sched_param param; + + dprintf("set scheduler priority to %i\n", priority); + + param.sched_priority = priority; + + if (sched_setscheduler(0, SCHEDULER, ¶m) < 0) { + perror("sched_setscheduler"); + fprintf(stderr, "warning: unable to set scheduler priority\n"); + return -1; + } + + return 0; +} + +/** + * notifys the user that the benchmark may run some time + * + * @param config benchmark config values + * + **/ + +void prepare_user(const struct config *config) +{ + unsigned long sleep_time = 0; + unsigned long load_time = 0; + unsigned int round; + + for (round = 0; round < config->rounds; round++) { + sleep_time += 2 * config->cycles * (config->sleep + config->sleep_step * round); + load_time += 2 * config->cycles * (config->load + config->load_step * round) + (config->load + config->load_step * round * 4); + } + + if (config->verbose || config->output != stdout) + printf("approx. test duration: %im\n", + (int)((sleep_time + load_time) / 60000000)); +} + +/** + * sets up the cpu affinity and scheduler priority + * + * @param config benchmark config values + * + **/ + +void prepare_system(const struct config *config) +{ + if (config->verbose) + printf("set cpu affinity to cpu #%u\n", config->cpu); + + set_cpu_affinity(config->cpu); + + switch (config->prio) { + case SCHED_HIGH: + if (config->verbose) + printf("high priority condition requested\n"); + + set_process_priority(PRIORITY_HIGH); + break; + case SCHED_LOW: + if (config->verbose) + printf("low priority condition requested\n"); + + set_process_priority(PRIORITY_LOW); + break; + default: + if (config->verbose) + printf("default priority condition requested\n"); + + set_process_priority(PRIORITY_DEFAULT); + } +} + 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 @@ +/* cpufreq-bench CPUFreq microbenchmark + * + * Copyright (C) 2008 Christian Kornacker + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "parse.h" + +long long get_time(); + +int set_cpufreq_governor(char *governor, unsigned int cpu); +int set_cpu_affinity(unsigned int cpu); +int set_process_priority(int priority); + +void prepare_user(const struct config *config); +void prepare_system(const struct config *config); diff --git a/tools/power/cpupower/build/ccdv.c b/tools/power/cpupower/build/ccdv.c new file mode 100644 index 000000000000..e3ae9da91a53 --- /dev/null +++ b/tools/power/cpupower/build/ccdv.c @@ -0,0 +1,387 @@ +/* ccdv.c + * + * Copyright (C) 2002-2003, by Mike Gleason, NcFTP Software. + * All Rights Reserved. + * + * Licensed under the GNU Public License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SETCOLOR_SUCCESS (gANSIEscapes ? "\033\1331;32m" : "") +#define SETCOLOR_FAILURE (gANSIEscapes ? "\033\1331;31m" : "") +#define SETCOLOR_WARNING (gANSIEscapes ? "\033\1331;33m" : "") +#define SETCOLOR_NORMAL (gANSIEscapes ? "\033\1330;39m" : "") + +#define TEXT_BLOCK_SIZE 8192 +#define INDENT 2 + +#define TERMS "vt100:vt102:vt220:vt320:xterm:xterm-color:ansi:linux:scoterm:scoansi:dtterm:cons25:cygwin" + +size_t gNBufUsed = 0, gNBufAllocated = 0; +char *gBuf = NULL; +int gCCPID; +char gAction[200] = ""; +char gTarget[200] = ""; +char gAr[32] = ""; +char gArLibraryTarget[64] = ""; +int gDumpCmdArgs = 0; +char gArgsStr[1000]; +int gColumns = 80; +int gANSIEscapes = 0; +int gExitStatus = 95; + +static void DumpFormattedOutput(void) +{ + char *cp; + char spaces[8 + 1] = " "; + char *saved; + int curcol; + int i; + + curcol = 0; + saved = NULL; + for (cp = gBuf + ((gDumpCmdArgs == 0) ? strlen(gArgsStr) : 0); ; cp++) { + if (*cp == '\0') { + if (saved != NULL) { + cp = saved; + saved = NULL; + } else break; + } + if (*cp == '\r') + continue; + if (*cp == '\t') { + saved = cp + 1; + cp = spaces + 8 - (8 - ((curcol - INDENT - 1) % 8)); + } + if (curcol == 0) { + for (i = INDENT; --i >= 0; ) + putchar(' '); + curcol = INDENT; + } + putchar(*cp); + if (++curcol == (gColumns - 1)) { + putchar('\n'); + curcol = 0; + } else if (*cp == '\n') + curcol = 0; + } + free(gBuf); +} /* DumpFormattedOutput */ + + + +/* Difftime(), only for timeval structures. */ +static void TimeValSubtract(struct timeval *tdiff, struct timeval *t1, struct timeval *t0) +{ + tdiff->tv_sec = t1->tv_sec - t0->tv_sec; + tdiff->tv_usec = t1->tv_usec - t0->tv_usec; + if (tdiff->tv_usec < 0) { + tdiff->tv_sec--; + tdiff->tv_usec += 1000000; + } +} /* TimeValSubtract */ + + + +static void Wait(void) +{ + int pid2, status; + + do { + status = 0; + pid2 = (int) waitpid(gCCPID, &status, 0); + } while (((pid2 >= 0) && (! WIFEXITED(status))) || ((pid2 < 0) && (errno == EINTR))); + if (WIFEXITED(status)) + gExitStatus = WEXITSTATUS(status); +} /* Wait */ + + + +static int SlurpProgress(int fd) +{ + char s1[71]; + char *newbuf; + int nready; + size_t ntoread; + ssize_t nread; + struct timeval now, tnext, tleft; + fd_set ss; + fd_set ss2; + const char *trail = "/-\\|", *trailcp; + + trailcp = trail; + snprintf(s1, sizeof(s1), "%s%s%s... ", gAction, gTarget[0] ? " " : "", gTarget); + printf("\r%-70s%-9s", s1, ""); + fflush(stdout); + + gettimeofday(&now, NULL); + tnext = now; + tnext.tv_sec++; + tleft.tv_sec = 1; + tleft.tv_usec = 0; + FD_ZERO(&ss2); + FD_SET(fd, &ss2); + for(;;) { + if (gNBufUsed == (gNBufAllocated - 1)) { + if ((newbuf = (char *) realloc(gBuf, gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) { + perror("ccdv: realloc"); + return (-1); + } + gNBufAllocated += TEXT_BLOCK_SIZE; + gBuf = newbuf; + } + for (;;) { + ss = ss2; + nready = select(fd + 1, &ss, NULL, NULL, &tleft); + if (nready == 1) + break; + if (nready < 0) { + if (errno != EINTR) { + perror("ccdv: select"); + return (-1); + } + continue; + } + gettimeofday(&now, NULL); + if ((now.tv_sec > tnext.tv_sec) || ((now.tv_sec == tnext.tv_sec) && (now.tv_usec >= tnext.tv_usec))) { + tnext = now; + tnext.tv_sec++; + tleft.tv_sec = 1; + tleft.tv_usec = 0; + printf("\r%-71s%c%-7s", s1, *trailcp, ""); + fflush(stdout); + if (*++trailcp == '\0') + trailcp = trail; + } else { + TimeValSubtract(&tleft, &tnext, &now); + } + } + ntoread = (gNBufAllocated - gNBufUsed - 1); + nread = read(fd, gBuf + gNBufUsed, ntoread); + if (nread < 0) { + if (errno == EINTR) + continue; + perror("ccdv: read"); + return (-1); + } else if (nread == 0) { + break; + } + gNBufUsed += nread; + gBuf[gNBufUsed] = '\0'; + } + snprintf(s1, sizeof(s1), "%s%s%s: ", gAction, gTarget[0] ? " " : "", gTarget); + Wait(); + if (gExitStatus == 0) { + printf("\r%-70s", s1); + printf("[%s%s%s]", ((gNBufUsed - strlen(gArgsStr)) < 4) ? SETCOLOR_SUCCESS : SETCOLOR_WARNING, "OK", SETCOLOR_NORMAL); + printf("%-5s\n", " "); + } else { + printf("\r%-70s", s1); + printf("[%s%s%s]", SETCOLOR_FAILURE, "ERROR", SETCOLOR_NORMAL); + printf("%-2s\n", " "); + gDumpCmdArgs = 1; /* print cmd when there are errors */ + } + fflush(stdout); + return (0); +} /* SlurpProgress */ + + + +static int SlurpAll(int fd) +{ + char *newbuf; + size_t ntoread; + ssize_t nread; + + printf("%s%s%s.\n", gAction, gTarget[0] ? " " : "", gTarget); + fflush(stdout); + + for(;;) { + if (gNBufUsed == (gNBufAllocated - 1)) { + if ((newbuf = (char *) realloc(gBuf, gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) { + perror("ccdv: realloc"); + return (-1); + } + gNBufAllocated += TEXT_BLOCK_SIZE; + gBuf = newbuf; + } + ntoread = (gNBufAllocated - gNBufUsed - 1); + nread = read(fd, gBuf + gNBufUsed, ntoread); + if (nread < 0) { + if (errno == EINTR) + continue; + perror("ccdv: read"); + return (-1); + } else if (nread == 0) { + break; + } + gNBufUsed += nread; + gBuf[gNBufUsed] = '\0'; + } + Wait(); + gDumpCmdArgs = (gExitStatus != 0); /* print cmd when there are errors */ + return (0); +} /* SlurpAll */ + + + +static const char *Basename(const char *path) +{ + const char *cp; + cp = strrchr(path, '/'); + if (cp == NULL) + return (path); + return (cp + 1); +} /* Basename */ + + + +static const char * Extension(const char *path) +{ + const char *cp = path; + cp = strrchr(path, '.'); + if (cp == NULL) + return (""); + // printf("Extension='%s'\n", cp); + return (cp); +} /* Extension */ + + + +static void Usage(void) +{ + fprintf(stderr, "Usage: ccdv /path/to/cc CFLAGS...\n\n"); + fprintf(stderr, "I wrote this to reduce the deluge Make output to make finding actual problems\n"); + fprintf(stderr, "easier. It is intended to be invoked from Makefiles, like this. Instead of:\n\n"); + fprintf(stderr, "\t.c.o:\n"); + fprintf(stderr, "\t\t$(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n"); + fprintf(stderr, "\nRewrite your rule so it looks like:\n\n"); + fprintf(stderr, "\t.c.o:\n"); + fprintf(stderr, "\t\t@ccdv $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\n"); + fprintf(stderr, "ccdv 1.1.0 is Free under the GNU Public License. Enjoy!\n"); + fprintf(stderr, " -- Mike Gleason, NcFTP Software \n"); + exit(96); +} /* Usage */ + + + +int main(int argc, char **argv) +{ + int pipe1[2]; + int devnull; + char emerg[256]; + int fd; + int nread; + int i; + int cc = 0, pch = 0; + const char *quote; + + if (argc < 2) + Usage(); + + snprintf(gAction, sizeof(gAction), "Running %s", Basename(argv[1])); + memset(gArgsStr, 0, sizeof(gArgsStr)); + for (i = 1; i < argc; i++) { + // printf("argv[%d]='%s'\n", i, argv[i]); + quote = (strchr(argv[i], ' ') != NULL) ? "\"" : ""; + snprintf(gArgsStr + strlen(gArgsStr), sizeof(gArgsStr) - strlen(gArgsStr), "%s%s%s%s%s", (i == 1) ? "" : " ", quote, argv[i], quote, (i == (argc - 1)) ? "\n" : ""); + if ((strcmp(argv[i], "-o") == 0) && ((i + 1) < argc)) { + if (strcasecmp(Extension(argv[i + 1]), ".o") != 0) { + strcpy(gAction, "Linking"); + snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i + 1])); + } + } else if (strchr("-+", (int) argv[i][0]) != NULL) { + continue; + } else if (strncasecmp(Extension(argv[i]), ".c", 2) == 0) { + cc++; + snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i])); + // printf("gTarget='%s'\n", gTarget); + } else if ((strncasecmp(Extension(argv[i]), ".h", 2) == 0) && (cc == 0)) { + pch++; + snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i])); + } else if ((i == 1) && (strcmp(Basename(argv[i]), "ar") == 0)) { + snprintf(gAr, sizeof(gAr), "%s", Basename(argv[i])); + } else if ((gArLibraryTarget[0] == '\0') && (strcasecmp(Extension(argv[i]), ".a") == 0)) { + snprintf(gArLibraryTarget, sizeof(gArLibraryTarget), "%s", Basename(argv[i])); + } + } + if ((gAr[0] != '\0') && (gArLibraryTarget[0] != '\0')) { + strcpy(gAction, "Creating library"); + snprintf(gTarget, sizeof(gTarget), "%s", gArLibraryTarget); + } else if (pch > 0) { + strcpy(gAction, "Precompiling"); + } else if (cc > 0) { + strcpy(gAction, "Compiling"); + } + + if (pipe(pipe1) < 0) { + perror("ccdv: pipe"); + exit(97); + } + + (void) close(0); + devnull = open("/dev/null", O_RDWR, 00666); + if ((devnull != 0) && (dup2(devnull, 0) == 0)) + close(devnull); + + gCCPID = (int) fork(); + if (gCCPID < 0) { + (void) close(pipe1[0]); + (void) close(pipe1[1]); + perror("ccdv: fork"); + exit(98); + } else if (gCCPID == 0) { + /* Child */ + (void) close(pipe1[0]); /* close read end */ + if (pipe1[1] != 1) { /* use write end on stdout */ + (void) dup2(pipe1[1], 1); + (void) close(pipe1[1]); + } + (void) dup2(1, 2); /* use write end on stderr */ + execvp(argv[1], argv + 1); + perror(argv[1]); + exit(99); + } + + /* parent */ + (void) close(pipe1[1]); /* close write end */ + fd = pipe1[0]; /* use read end */ + + gColumns = (getenv("COLUMNS") != NULL) ? atoi(getenv("COLUMNS")) : 80; + gANSIEscapes = (getenv("TERM") != NULL) && (strstr(TERMS, getenv("TERM")) != NULL); + gBuf = (char *) malloc(TEXT_BLOCK_SIZE); + if (gBuf == NULL) + goto panic; + gNBufUsed = 0; + gNBufAllocated = TEXT_BLOCK_SIZE; + if (strlen(gArgsStr) < (gNBufAllocated - 1)) { + strcpy(gBuf, gArgsStr); + gNBufUsed = strlen(gArgsStr); + } + + if (isatty(1)) { + if (SlurpProgress(fd) < 0) + goto panic; + } else { + if (SlurpAll(fd) < 0) + goto panic; + } + DumpFormattedOutput(); + exit(gExitStatus); + +panic: + gDumpCmdArgs = 1; /* print cmd when there are errors */ + DumpFormattedOutput(); + while ((nread = read(fd, emerg, (size_t) sizeof(emerg))) > 0) + (void) write(2, emerg, (size_t) nread); + Wait(); + exit(gExitStatus); +} /* main */ 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 @@ +default: all + +centrino-decode: centrino-decode.c + $(CC) $(CFLAGS) -o centrino-decode centrino-decode.c + +dump_psb: dump_psb.c + $(CC) $(CFLAGS) -o dump_psb dump_psb.c + +intel_gsic: intel_gsic.c + $(CC) $(CFLAGS) -o intel_gsic -llrmi intel_gsic.c + +powernow-k8-decode: powernow-k8-decode.c + $(CC) $(CFLAGS) -o powernow-k8-decode powernow-k8-decode.c + +all: centrino-decode dump_psb intel_gsic powernow-k8-decode + +clean: + rm -rf centrino-decode dump_psb intel_gsic powernow-k8-decode + +.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 @@ +/* + * (C) 2003 - 2004 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Based on code found in + * linux/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c + * and originally developed by Jeremy Fitzhardinge. + * + * USAGE: simply run it to decode the current settings on CPU 0, + * or pass the CPU number as argument, or pass the MSR content + * as argument. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MCPU 32 + +#define MSR_IA32_PERF_STATUS 0x198 + +static int rdmsr(unsigned int cpu, unsigned int msr, + unsigned int *lo, unsigned int *hi) +{ + int fd; + char file[20]; + unsigned long long val; + int retval = -1; + + *lo = *hi = 0; + + if (cpu > MCPU) + goto err1; + + sprintf(file, "/dev/cpu/%d/msr", cpu); + fd = open(file, O_RDONLY); + + if (fd < 0) + goto err1; + + if (lseek(fd, msr, SEEK_CUR) == -1) + goto err2; + + if (read(fd, &val, 8) != 8) + goto err2; + + *lo = (uint32_t )(val & 0xffffffffull); + *hi = (uint32_t )(val>>32 & 0xffffffffull); + + retval = 0; +err2: + close(fd); +err1: + return retval; +} + +static void decode (unsigned int msr) +{ + unsigned int multiplier; + unsigned int mv; + + multiplier = ((msr >> 8) & 0xFF); + + mv = (((msr & 0xFF) * 16) + 700); + + printf("0x%x means multiplier %d @ %d mV\n", msr, multiplier, mv); +} + +static int decode_live(unsigned int cpu) +{ + unsigned int lo, hi; + int err; + + err = rdmsr(cpu, MSR_IA32_PERF_STATUS, &lo, &hi); + + if (err) { + printf("can't get MSR_IA32_PERF_STATUS for cpu %d\n", cpu); + printf("Possible trouble: you don't run an Enhanced SpeedStep capable cpu\n"); + printf("or you are not root, or the msr driver is not present\n"); + return 1; + } + + decode(lo); + + return 0; +} + +int main (int argc, char **argv) +{ + unsigned int cpu, mode = 0; + + if (argc < 2) + cpu = 0; + else { + cpu = strtoul(argv[1], NULL, 0); + if (cpu >= MCPU) + mode = 1; + } + + if (mode) + decode(cpu); + else + decode_live(cpu); + + return 0; +} 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 @@ +/* + * dump_psb. (c) 2004, Dave Jones, Red Hat Inc. + * Licensed under the GPL v2. + */ + +#include +#include +#include +#include +#include + +#define _GNU_SOURCE +#include + +#include + +#define LEN (0x100000 - 0xc0000) +#define OFFSET (0xc0000) + +#ifndef __packed +#define __packed __attribute((packed)) +#endif + +static long relevant; + +static const int fid_to_mult[32] = { + 110, 115, 120, 125, 50, 55, 60, 65, + 70, 75, 80, 85, 90, 95, 100, 105, + 30, 190, 40, 200, 130, 135, 140, 210, + 150, 225, 160, 165, 170, 180, -1, -1, +}; + +static const int vid_to_voltage[32] = { + 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650, + 1600, 1550, 1500, 1450, 1400, 1350, 1300, 0, + 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100, + 1075, 1050, 1024, 1000, 975, 950, 925, 0, +}; + +struct psb_header { + char signature[10]; + u_char version; + u_char flags; + u_short settlingtime; + u_char res1; + u_char numpst; +} __packed; + +struct pst_header { + u_int32_t cpuid; + u_char fsb; + u_char maxfid; + u_char startvid; + u_char numpstates; +} __packed; + +static u_int fsb; +static u_int sgtc; + +static int +decode_pst(char *p, int npstates) +{ + int i; + int freq, fid, vid; + + for (i = 0; i < npstates; ++i) { + fid = *p++; + vid = *p++; + freq = 100 * fid_to_mult[fid] * fsb; + + printf(" %2d %8dkHz FID %02x (%2d.%01d) VID %02x (%4dmV)\n", + i, + freq, + fid, fid_to_mult[fid]/10, fid_to_mult[fid]%10, + vid, vid_to_voltage[vid]); + } + + return 0; +} + +static +void decode_psb(char *p, int numpst) +{ + int i; + struct psb_header *psb; + struct pst_header *pst; + + psb = (struct psb_header*) p; + + if (psb->version != 0x12) + return; + + printf("PSB version: %hhx flags: %hhx settling time %hhuus res1 %hhx num pst %hhu\n", + psb->version, + psb->flags, + psb->settlingtime, + psb->res1, + psb->numpst); + sgtc = psb->settlingtime * 100; + + if (sgtc < 10000) + sgtc = 10000; + + p = ((char *) psb) + sizeof(struct psb_header); + + if (numpst < 0) + numpst = psb->numpst; + else + printf("Overriding number of pst :%d\n", numpst); + + for (i = 0; i < numpst; i++) { + pst = (struct pst_header*) p; + + if (relevant != 0) { + if (relevant!= pst->cpuid) + goto next_one; + } + + printf(" PST %d cpuid %.3x fsb %hhu mfid %hhx svid %hhx numberstates %hhu\n", + i+1, + pst->cpuid, + pst->fsb, + pst->maxfid, + pst->startvid, + pst->numpstates); + + fsb = pst->fsb; + decode_pst(p + sizeof(struct pst_header), pst->numpstates); + +next_one: + p += sizeof(struct pst_header) + 2*pst->numpstates; + } + +} + +static struct option info_opts[] = { + {.name = "numpst", .has_arg=no_argument, .flag=NULL, .val='n'}, +}; + +void print_help(void) +{ + printf ("Usage: dump_psb [options]\n"); + printf ("Options:\n"); + printf (" -n, --numpst Set number of PST tables to scan\n"); + printf (" -r, --relevant Only display PSTs relevant to cpuid N\n"); +} + +int +main(int argc, char *argv[]) +{ + int fd; + int numpst=-1; + int ret=0, cont=1; + char *mem = NULL; + char *p; + + do { + ret = getopt_long(argc, argv, "hr:n:", info_opts, NULL); + switch (ret){ + case '?': + case 'h': + print_help(); + cont = 0; + break; + case 'r': + relevant = strtol(optarg, NULL, 16); + break; + case 'n': + numpst = strtol(optarg, NULL, 10); + break; + case -1: + cont = 0; + break; + } + + } while(cont); + + fd = open("/dev/mem", O_RDONLY); + if (fd < 0) { + printf ("Couldn't open /dev/mem. Are you root?\n"); + exit(1); + } + + mem = mmap(mem, 0x100000 - 0xc0000, PROT_READ, MAP_SHARED, fd, 0xc0000); + close(fd); + + for (p = mem; p - mem < LEN; p+=16) { + if (memcmp(p, "AMDK7PNOW!", 10) == 0) { + decode_psb(p, numpst); + break; + } + } + + munmap(mem, LEN); + return 0; +} 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 @@ +/* + * (C) 2003 Bruno Ducrot + * (C) 2004 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Based on code found in + * linux/include/asm-i386/ist.h and linux/arch/i386/kernel/setup.c + * and originally developed by Andy Grover + */ + +#include +#include +#include + +int main (void) +{ + struct LRMI_regs r; + int retval; + + if (!LRMI_init()) + return 0; + + memset(&r, 0, sizeof(r)); + + r.eax = 0x0000E980; + r.edx = 0x47534943; + + retval = LRMI_int(0x15, &r); + + if (!retval) { + printf("Failed!\n"); + return 0; + } + if (r.eax == 0x47534943) { + printf("BIOS supports GSIC call:\n"); + printf("\tsignature: %c%c%c%c\n", + (r.eax >> 24) & 0xff, + (r.eax >> 16) & 0xff, + (r.eax >> 8) & 0xff, + (r.eax) & 0xff); + printf("\tcommand port = 0x%.4x\n", + r.ebx & 0xffff); + printf("\tcommand = 0x%.4x\n", + (r.ebx >> 16) & 0xffff); + printf("\tevent port = 0x%.8x\n", r.ecx); + printf("\tflags = 0x%.8x\n", r.edx); + if (((r.ebx >> 16) & 0xffff) != 0x82) { + printf("non-default command value. If speedstep-smi " + "doesn't work out of the box,\nyou may want to " + "try out the default value by passing " + "smi_cmd=0x82 to the module\n ON YOUR OWN " + "RISK.\n"); + } + if ((r.ebx & 0xffff) != 0xb2) { + printf("non-default command port. If speedstep-smi " + "doesn't work out of the box,\nyou may want to " + "try out the default value by passing " + "smi_port=0x82 to the module\n ON YOUR OWN " + "RISK.\n"); + } + } else { + printf("BIOS DOES NOT support GSIC call. Dumping registers anyway:\n"); + printf("eax = 0x%.8x\n", r.eax); + printf("ebx = 0x%.8x\n", r.ebx); + printf("ecx = 0x%.8x\n", r.ecx); + printf("edx = 0x%.8x\n", r.edx); + printf("Note also that some BIOS do not support the initial " + "GSIC call, but the newer\nspeeedstep-smi driver may " + "work.\nFor this, you need to pass some arguments to " + "the speedstep-smi driver:\n"); + printf("\tsmi_cmd=0x?? smi_port=0x?? smi_sig=1\n"); + printf("\nUnfortunately, you have to know what exactly are " + "smi_cmd and smi_port, and this\nis system " + "dependant.\n"); + } + return 1; +} 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 @@ +/* + * (C) 2004 Bruno Ducrot + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Based on code found in + * linux/arch/i386/kernel/cpu/cpufreq/powernow-k8.c + * and originally developed by Paul Devriendt + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MCPU 32 + +#define MSR_FIDVID_STATUS 0xc0010042 + +#define MSR_S_HI_CURRENT_VID 0x0000001f +#define MSR_S_LO_CURRENT_FID 0x0000003f + +static int get_fidvid(uint32_t cpu, uint32_t *fid, uint32_t *vid) +{ + int err = 1; + uint64_t msr = 0; + int fd; + char file[20]; + + if (cpu > MCPU) + goto out; + + sprintf(file, "/dev/cpu/%d/msr", cpu); + + fd = open(file, O_RDONLY); + if (fd < 0) + goto out; + lseek(fd, MSR_FIDVID_STATUS, SEEK_CUR); + if (read(fd, &msr, 8) != 8) + goto err1; + + *fid = ((uint32_t )(msr & 0xffffffffull)) & MSR_S_LO_CURRENT_FID; + *vid = ((uint32_t )(msr>>32 & 0xffffffffull)) & MSR_S_HI_CURRENT_VID; + err = 0; +err1: + close(fd); +out: + return err; +} + + +/* Return a frequency in MHz, given an input fid */ +static uint32_t find_freq_from_fid(uint32_t fid) +{ + return 800 + (fid * 100); +} + +/* Return a voltage in miliVolts, given an input vid */ +static uint32_t find_millivolts_from_vid(uint32_t vid) +{ + return 1550-vid*25; +} + +int main (int argc, char *argv[]) +{ + int err; + int cpu; + uint32_t fid, vid; + + if (argc < 2) + cpu = 0; + else + cpu = strtoul(argv[1], NULL, 0); + + err = get_fidvid(cpu, &fid, &vid); + + if (err) { + printf("can't get fid, vid from MSR\n"); + printf("Possible trouble: you don't run a powernow-k8 capable cpu\n"); + printf("or you are not root, or the msr driver is not present\n"); + exit(1); + } + + + printf("cpu %d currently at %d MHz and %d mV\n", + cpu, + find_freq_from_fid(fid), + find_millivolts_from_vid(vid)); + + return 0; +} 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 @@ +obj-m := + +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) +KMISC := /lib/modules/$(shell uname -r)/cpufrequtils/ + +ifeq ("$(CONFIG_X86_TSC)", "y") + obj-m += cpufreq-test_tsc.o +endif + +default: + $(MAKE) -C $(KDIR) M=$(PWD) + +clean: + - rm -rf *.o *.ko .tmp-versions .*.cmd .*.mod.* *.mod.c + - rm -rf .tmp_versions* Module.symvers modules.order + +install: default + install -d $(KMISC) + install -m 644 -c *.ko $(KMISC) + /sbin/depmod -a + +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 @@ +/* + * test module to check whether the TSC-based delay routine continues + * to work properly after cpufreq transitions. Needs ACPI to work + * properly. + * + * Based partly on the Power Management Timer (PMTMR) code to be found + * in arch/i386/kernel/timers/timer_pm.c on recent 2.6. kernels, especially + * code written by John Stultz. The read_pmtmr function was copied verbatim + * from that file. + * + * (C) 2004 Dominik Brodowski + * + * To use: + * 1.) pass clock=tsc to the kernel on your bootloader + * 2.) modprobe this module (it'll fail) + * 3.) change CPU frequency + * 4.) modprobe this module again + * 5.) if the third value, "diff_pmtmr", changes between 2. and 4., the + * TSC-based delay routine on the Linux kernel does not correctly + * handle the cpufreq transition. Please report this to + * cpufreq@vger.kernel.org + */ + +#include +#include +#include +#include + +#include + +#include +#include + +static int pm_tmr_ioport = 0; + +/*helper function to safely read acpi pm timesource*/ +static u32 read_pmtmr(void) +{ + u32 v1=0,v2=0,v3=0; + /* It has been reported that because of various broken + * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time + * source is not latched, so you must read it multiple + * times to insure a safe value is read. + */ + do { + v1 = inl(pm_tmr_ioport); + v2 = inl(pm_tmr_ioport); + v3 = inl(pm_tmr_ioport); + } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) + || (v3 > v1 && v3 < v2)); + + /* mask the output to 24 bits */ + return (v2 & 0xFFFFFF); +} + +static int __init cpufreq_test_tsc(void) +{ + u32 now, then, diff; + u64 now_tsc, then_tsc, diff_tsc; + int i; + + /* the following code snipped is copied from arch/x86/kernel/acpi/boot.c + of Linux v2.6.25. */ + + /* detect the location of the ACPI PM Timer */ + if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) { + /* FADT rev. 2 */ + if (acpi_gbl_FADT.xpm_timer_block.space_id != + ACPI_ADR_SPACE_SYSTEM_IO) + return 0; + + pm_tmr_ioport = acpi_gbl_FADT.xpm_timer_block.address; + /* + * "X" fields are optional extensions to the original V1.0 + * fields, so we must selectively expand V1.0 fields if the + * corresponding X field is zero. + */ + if (!pm_tmr_ioport) + pm_tmr_ioport = acpi_gbl_FADT.pm_timer_block; + } else { + /* FADT rev. 1 */ + pm_tmr_ioport = acpi_gbl_FADT.pm_timer_block; + } + + printk(KERN_DEBUG "start--> \n"); + then = read_pmtmr(); + rdtscll(then_tsc); + for (i=0;i<20;i++) { + mdelay(100); + now = read_pmtmr(); + rdtscll(now_tsc); + diff = (now - then) & 0xFFFFFF; + diff_tsc = now_tsc - then_tsc; + printk(KERN_DEBUG "t1: %08u t2: %08u diff_pmtmr: %08u diff_tsc: %016llu\n", then, now, diff, diff_tsc); + then = now; + then_tsc = now_tsc; + } + printk(KERN_DEBUG "<-- end \n"); + return -ENODEV; +} + +static void __exit cpufreq_none(void) +{ + return; +} + +module_init(cpufreq_test_tsc) +module_exit(cpufreq_none) + + +MODULE_AUTHOR("Dominik Brodowski"); +MODULE_DESCRIPTION("Verify the TSC cpufreq notifier working correctly -- needs ACPI-enabled system"); +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..dbf13998462a --- /dev/null +++ b/tools/power/cpupower/debug/x86_64/Makefile @@ -0,0 +1,14 @@ +default: all + +centrino-decode: centrino-decode.c + $(CC) $(CFLAGS) -o centrino-decode centrino-decode.c + +powernow-k8-decode: powernow-k8-decode.c + $(CC) $(CFLAGS) -o powernow-k8-decode powernow-k8-decode.c + +all: centrino-decode powernow-k8-decode + +clean: + rm -rf centrino-decode powernow-k8-decode + +.PHONY: all default clean diff --git a/tools/power/cpupower/debug/x86_64/centrino-decode.c b/tools/power/cpupower/debug/x86_64/centrino-decode.c new file mode 120000 index 000000000000..26fb3f1d8fc7 --- /dev/null +++ b/tools/power/cpupower/debug/x86_64/centrino-decode.c @@ -0,0 +1 @@ +../i386/centrino-decode.c \ No newline at end of file diff --git a/tools/power/cpupower/debug/x86_64/powernow-k8-decode.c b/tools/power/cpupower/debug/x86_64/powernow-k8-decode.c new file mode 120000 index 000000000000..eb30c79cf9df --- /dev/null +++ b/tools/power/cpupower/debug/x86_64/powernow-k8-decode.c @@ -0,0 +1 @@ +../i386/powernow-k8-decode.c \ No newline at end of file diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c new file mode 100644 index 000000000000..ae7d8c57b447 --- /dev/null +++ b/tools/power/cpupower/lib/cpufreq.c @@ -0,0 +1,190 @@ +/* + * (C) 2004-2009 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + */ + + +#include +#include +#include +#include + +#include "cpufreq.h" +#include "sysfs.h" + +int cpufreq_cpu_exists(unsigned int cpu) +{ + return sysfs_cpu_exists(cpu); +} + +unsigned long cpufreq_get_freq_kernel(unsigned int cpu) +{ + return sysfs_get_freq_kernel(cpu); +} + +unsigned long cpufreq_get_freq_hardware(unsigned int cpu) +{ + return sysfs_get_freq_hardware(cpu); +} + +unsigned long cpufreq_get_transition_latency(unsigned int cpu) +{ + return sysfs_get_freq_transition_latency(cpu); +} + +int cpufreq_get_hardware_limits(unsigned int cpu, + unsigned long *min, + unsigned long *max) +{ + if ((!min) || (!max)) + return -EINVAL; + return sysfs_get_freq_hardware_limits(cpu, min, max); +} + +char * cpufreq_get_driver(unsigned int cpu) { + return sysfs_get_freq_driver(cpu); +} + +void cpufreq_put_driver(char * ptr) { + if (!ptr) + return; + free(ptr); +} + +struct cpufreq_policy * cpufreq_get_policy(unsigned int cpu) { + return sysfs_get_freq_policy(cpu); +} + +void cpufreq_put_policy(struct cpufreq_policy *policy) { + if ((!policy) || (!policy->governor)) + return; + + free(policy->governor); + policy->governor = NULL; + free(policy); +} + +struct cpufreq_available_governors * cpufreq_get_available_governors(unsigned int cpu) { + return sysfs_get_freq_available_governors(cpu); +} + +void cpufreq_put_available_governors(struct cpufreq_available_governors *any) { + struct cpufreq_available_governors *tmp, *next; + + if (!any) + return; + + tmp = any->first; + while (tmp) { + next = tmp->next; + if (tmp->governor) + free(tmp->governor); + free(tmp); + tmp = next; + } +} + + +struct cpufreq_available_frequencies * cpufreq_get_available_frequencies(unsigned int cpu) { + return sysfs_get_available_frequencies(cpu); +} + +void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies *any) { + struct cpufreq_available_frequencies *tmp, *next; + + if (!any) + return; + + tmp = any->first; + while (tmp) { + next = tmp->next; + free(tmp); + tmp = next; + } +} + + +struct cpufreq_affected_cpus * cpufreq_get_affected_cpus(unsigned int cpu) { + return sysfs_get_freq_affected_cpus(cpu); +} + +void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any) { + struct cpufreq_affected_cpus *tmp, *next; + + if (!any) + return; + + tmp = any->first; + while (tmp) { + next = tmp->next; + free(tmp); + tmp = next; + } +} + + +struct cpufreq_affected_cpus * cpufreq_get_related_cpus(unsigned int cpu) { + return sysfs_get_freq_related_cpus(cpu); +} + +void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any) { + cpufreq_put_affected_cpus(any); +} + + +int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy) { + if (!policy || !(policy->governor)) + return -EINVAL; + + return sysfs_set_freq_policy(cpu, policy); +} + + +int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq) { + return sysfs_modify_freq_policy_min(cpu, min_freq); +} + + +int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq) { + return sysfs_modify_freq_policy_max(cpu, max_freq); +} + + +int cpufreq_modify_policy_governor(unsigned int cpu, char *governor) { + if ((!governor) || (strlen(governor) > 19)) + return -EINVAL; + + return sysfs_modify_freq_policy_governor(cpu, governor); +} + +int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency) { + return sysfs_set_frequency(cpu, target_frequency); +} + +struct cpufreq_stats * cpufreq_get_stats(unsigned int cpu, unsigned long long *total_time) { + struct cpufreq_stats *ret; + + ret = sysfs_get_freq_stats(cpu, total_time); + return (ret); +} + +void cpufreq_put_stats(struct cpufreq_stats *any) { + struct cpufreq_stats *tmp, *next; + + if (!any) + return; + + tmp = any->first; + while (tmp) { + next = tmp->next; + free(tmp); + tmp = next; + } +} + +unsigned long cpufreq_get_transitions(unsigned int cpu) { + unsigned long ret = sysfs_get_freq_transitions(cpu); + + return (ret); +} diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h new file mode 100644 index 000000000000..03be906581b5 --- /dev/null +++ b/tools/power/cpupower/lib/cpufreq.h @@ -0,0 +1,215 @@ +/* + * cpufreq.h - definitions for libcpufreq + * + * Copyright (C) 2004-2009 Dominik Brodowski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _CPUFREQ_H +#define _CPUFREQ_H 1 + +struct cpufreq_policy { + unsigned long min; + unsigned long max; + char *governor; +}; + +struct cpufreq_available_governors { + char *governor; + struct cpufreq_available_governors *next; + struct cpufreq_available_governors *first; +}; + +struct cpufreq_available_frequencies { + unsigned long frequency; + struct cpufreq_available_frequencies *next; + struct cpufreq_available_frequencies *first; +}; + + +struct cpufreq_affected_cpus { + unsigned int cpu; + struct cpufreq_affected_cpus *next; + struct cpufreq_affected_cpus *first; +}; + +struct cpufreq_stats { + unsigned long frequency; + unsigned long long time_in_state; + struct cpufreq_stats *next; + struct cpufreq_stats *first; +}; + + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * returns 0 if the specified CPU is present (it doesn't say + * whether it is online!), and an error value if not. + */ + +extern int cpufreq_cpu_exists(unsigned int cpu); + +/* determine current CPU frequency + * - _kernel variant means kernel's opinion of CPU frequency + * - _hardware variant means actual hardware CPU frequency, + * which is only available to root. + * + * returns 0 on failure, else frequency in kHz. + */ + +extern unsigned long cpufreq_get_freq_kernel(unsigned int cpu); + +extern unsigned long cpufreq_get_freq_hardware(unsigned int cpu); + +#define cpufreq_get(cpu) cpufreq_get_freq_kernel(cpu); + + +/* determine CPU transition latency + * + * returns 0 on failure, else transition latency in 10^(-9) s = nanoseconds + */ +extern unsigned long cpufreq_get_transition_latency(unsigned int cpu); + + +/* determine hardware CPU frequency limits + * + * These may be limited further by thermal, energy or other + * considerations by cpufreq policy notifiers in the kernel. + */ + +extern int cpufreq_get_hardware_limits(unsigned int cpu, + unsigned long *min, + unsigned long *max); + + +/* determine CPUfreq driver used + * + * Remember to call cpufreq_put_driver when no longer needed + * to avoid memory leakage, please. + */ + +extern char * cpufreq_get_driver(unsigned int cpu); + +extern void cpufreq_put_driver(char * ptr); + + +/* determine CPUfreq policy currently used + * + * Remember to call cpufreq_put_policy when no longer needed + * to avoid memory leakage, please. + */ + + +extern struct cpufreq_policy * cpufreq_get_policy(unsigned int cpu); + +extern void cpufreq_put_policy(struct cpufreq_policy *policy); + + +/* determine CPUfreq governors currently available + * + * may be modified by modprobe'ing or rmmod'ing other governors. Please + * free allocated memory by calling cpufreq_put_available_governors + * after use. + */ + + +extern struct cpufreq_available_governors * cpufreq_get_available_governors(unsigned int cpu); + +extern void cpufreq_put_available_governors(struct cpufreq_available_governors *first); + + +/* determine CPU frequency states available + * + * only present on _some_ ->target() cpufreq drivers. For information purposes + * only. Please free allocated memory by calling cpufreq_put_available_frequencies + * after use. + */ + +extern struct cpufreq_available_frequencies * cpufreq_get_available_frequencies(unsigned int cpu); + +extern void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies *first); + + +/* determine affected CPUs + * + * Remember to call cpufreq_put_affected_cpus when no longer needed + * to avoid memory leakage, please. + */ + +extern struct cpufreq_affected_cpus * cpufreq_get_affected_cpus(unsigned int cpu); + +extern void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first); + + +/* determine related CPUs + * + * Remember to call cpufreq_put_related_cpus when no longer needed + * to avoid memory leakage, please. + */ + +extern struct cpufreq_affected_cpus * cpufreq_get_related_cpus(unsigned int cpu); + +extern void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first); + + +/* determine stats for cpufreq subsystem + * + * This is not available in all kernel versions or configurations. + */ + +extern struct cpufreq_stats * cpufreq_get_stats(unsigned int cpu, unsigned long long *total_time); + +extern void cpufreq_put_stats(struct cpufreq_stats *stats); + +extern unsigned long cpufreq_get_transitions(unsigned int cpu); + + +/* set new cpufreq policy + * + * Tries to set the passed policy as new policy as close as possible, + * but results may differ depending e.g. on governors being available. + */ + +extern int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy); + + +/* modify a policy by only changing min/max freq or governor + * + * Does not check whether result is what was intended. + */ + +extern int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq); +extern int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq); +extern int cpufreq_modify_policy_governor(unsigned int cpu, char *governor); + + +/* set a specific frequency + * + * Does only work if userspace governor can be used and no external + * interference (other calls to this function or to set/modify_policy) + * occurs. Also does not work on ->range() cpufreq drivers. + */ + +extern int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency); + +#ifdef __cplusplus +} +#endif + +#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..c9b061fe87b1 --- /dev/null +++ b/tools/power/cpupower/lib/sysfs.c @@ -0,0 +1,671 @@ +/* + * (C) 2004-2009 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cpufreq.h" + +#define PATH_TO_CPU "/sys/devices/system/cpu/" +#define MAX_LINE_LEN 255 +#define SYSFS_PATH_MAX 255 + + +static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen) +{ + int fd; + size_t numread; + + if ( ( fd = open(path, O_RDONLY) ) == -1 ) + return 0; + + numread = read(fd, buf, buflen - 1); + if ( numread < 1 ) + { + close(fd); + return 0; + } + + buf[numread] = '\0'; + close(fd); + + return numread; +} + + +/* CPUFREQ sysfs access **************************************************/ + +/* helper function to read file from /sys into given buffer */ +/* fname is a relative path under "cpuX/cpufreq" dir */ +static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname, + char *buf, size_t buflen) +{ + char path[SYSFS_PATH_MAX]; + + snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s", + cpu, fname); + return sysfs_read_file(path, buf, buflen); +} + +/* helper function to write a new value to a /sys file */ +/* fname is a relative path under "cpuX/cpufreq" dir */ +static unsigned int sysfs_cpufreq_write_file(unsigned int cpu, + const char *fname, + const char *value, size_t len) +{ + char path[SYSFS_PATH_MAX]; + int fd; + size_t numwrite; + + snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s", + cpu, fname); + + if ( ( fd = open(path, O_WRONLY) ) == -1 ) + return 0; + + numwrite = write(fd, value, len); + if ( numwrite < 1 ) + { + close(fd); + return 0; + } + + close(fd); + + return numwrite; +} + +/* read access to files which contain one numeric value */ + +enum cpufreq_value { + CPUINFO_CUR_FREQ, + CPUINFO_MIN_FREQ, + CPUINFO_MAX_FREQ, + CPUINFO_LATENCY, + SCALING_CUR_FREQ, + SCALING_MIN_FREQ, + SCALING_MAX_FREQ, + STATS_NUM_TRANSITIONS, + MAX_CPUFREQ_VALUE_READ_FILES +}; + +static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = { + [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq", + [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq", + [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq", + [CPUINFO_LATENCY] = "cpuinfo_transition_latency", + [SCALING_CUR_FREQ] = "scaling_cur_freq", + [SCALING_MIN_FREQ] = "scaling_min_freq", + [SCALING_MAX_FREQ] = "scaling_max_freq", + [STATS_NUM_TRANSITIONS] = "stats/total_trans" +}; + + +static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu, + enum cpufreq_value which) +{ + unsigned long value; + unsigned int len; + char linebuf[MAX_LINE_LEN]; + char *endp; + + if ( which >= MAX_CPUFREQ_VALUE_READ_FILES ) + return 0; + + if ( ( len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which], + linebuf, sizeof(linebuf))) == 0 ) + return 0; + + value = strtoul(linebuf, &endp, 0); + + if ( endp == linebuf || errno == ERANGE ) + return 0; + + return value; +} + +/* read access to files which contain one string */ + +enum cpufreq_string { + SCALING_DRIVER, + SCALING_GOVERNOR, + MAX_CPUFREQ_STRING_FILES +}; + +static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = { + [SCALING_DRIVER] = "scaling_driver", + [SCALING_GOVERNOR] = "scaling_governor", +}; + + +static char * sysfs_cpufreq_get_one_string(unsigned int cpu, + enum cpufreq_string which) +{ + char linebuf[MAX_LINE_LEN]; + char *result; + unsigned int len; + + if (which >= MAX_CPUFREQ_STRING_FILES) + return NULL; + + if ( ( len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which], + linebuf, sizeof(linebuf))) == 0 ) + return NULL; + + if ( ( result = strdup(linebuf) ) == NULL ) + return NULL; + + if (result[strlen(result) - 1] == '\n') + result[strlen(result) - 1] = '\0'; + + return result; +} + +/* write access */ + +enum cpufreq_write { + WRITE_SCALING_MIN_FREQ, + WRITE_SCALING_MAX_FREQ, + WRITE_SCALING_GOVERNOR, + WRITE_SCALING_SET_SPEED, + MAX_CPUFREQ_WRITE_FILES +}; + +static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = { + [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq", + [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq", + [WRITE_SCALING_GOVERNOR] = "scaling_governor", + [WRITE_SCALING_SET_SPEED] = "scaling_setspeed", +}; + +static int sysfs_cpufreq_write_one_value(unsigned int cpu, + enum cpufreq_write which, + const char *new_value, size_t len) +{ + if (which >= MAX_CPUFREQ_WRITE_FILES) + return 0; + + if ( sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which], + new_value, len) != len ) + return -ENODEV; + + return 0; +}; + +unsigned long sysfs_get_freq_kernel(unsigned int cpu) +{ + return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ); +} + +unsigned long sysfs_get_freq_hardware(unsigned int cpu) +{ + return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ); +} + +unsigned long sysfs_get_freq_transition_latency(unsigned int cpu) +{ + return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY); +} + +int sysfs_get_freq_hardware_limits(unsigned int cpu, + unsigned long *min, + unsigned long *max) +{ + if ((!min) || (!max)) + return -EINVAL; + + *min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ); + if (!*min) + return -ENODEV; + + *max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ); + if (!*max) + return -ENODEV; + + return 0; +} + +char * sysfs_get_freq_driver(unsigned int cpu) { + return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER); +} + +struct cpufreq_policy * sysfs_get_freq_policy(unsigned int cpu) { + struct cpufreq_policy *policy; + + policy = malloc(sizeof(struct cpufreq_policy)); + if (!policy) + return NULL; + + policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR); + if (!policy->governor) { + free(policy); + return NULL; + } + policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ); + policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ); + if ((!policy->min) || (!policy->max)) { + free(policy->governor); + free(policy); + return NULL; + } + + return policy; +} + +struct cpufreq_available_governors * +sysfs_get_freq_available_governors(unsigned int cpu) { + struct cpufreq_available_governors *first = NULL; + struct cpufreq_available_governors *current = NULL; + char linebuf[MAX_LINE_LEN]; + unsigned int pos, i; + unsigned int len; + + if ( ( len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors", + linebuf, sizeof(linebuf))) == 0 ) + { + return NULL; + } + + pos = 0; + for ( i = 0; i < len; i++ ) + { + if ( linebuf[i] == ' ' || linebuf[i] == '\n' ) + { + if ( i - pos < 2 ) + continue; + if ( current ) { + current->next = malloc(sizeof *current ); + if ( ! current->next ) + goto error_out; + current = current->next; + } else { + first = malloc( sizeof *first ); + if ( ! first ) + goto error_out; + current = first; + } + current->first = first; + current->next = NULL; + + current->governor = malloc(i - pos + 1); + if ( ! current->governor ) + goto error_out; + + memcpy( current->governor, linebuf + pos, i - pos); + current->governor[i - pos] = '\0'; + pos = i + 1; + } + } + + return first; + + error_out: + while ( first ) { + current = first->next; + if ( first->governor ) + free( first->governor ); + free( first ); + first = current; + } + return NULL; +} + + +struct cpufreq_available_frequencies * +sysfs_get_available_frequencies(unsigned int cpu) { + struct cpufreq_available_frequencies *first = NULL; + struct cpufreq_available_frequencies *current = NULL; + char one_value[SYSFS_PATH_MAX]; + char linebuf[MAX_LINE_LEN]; + unsigned int pos, i; + unsigned int len; + + if ( ( len = sysfs_cpufreq_read_file(cpu, + "scaling_available_frequencies", + linebuf, sizeof(linebuf))) == 0 ) + { + return NULL; + } + + pos = 0; + for ( i = 0; i < len; i++ ) + { + if ( linebuf[i] == ' ' || linebuf[i] == '\n' ) + { + if ( i - pos < 2 ) + continue; + if ( i - pos >= SYSFS_PATH_MAX ) + goto error_out; + if ( current ) { + current->next = malloc(sizeof *current ); + if ( ! current->next ) + goto error_out; + current = current->next; + } else { + first = malloc(sizeof *first ); + if ( ! first ) + goto error_out; + current = first; + } + current->first = first; + current->next = NULL; + + memcpy(one_value, linebuf + pos, i - pos); + one_value[i - pos] = '\0'; + if ( sscanf(one_value, "%lu", ¤t->frequency) != 1 ) + goto error_out; + + pos = i + 1; + } + } + + return first; + + error_out: + while ( first ) { + current = first->next; + free(first); + first = current; + } + return NULL; +} + +static struct cpufreq_affected_cpus * sysfs_get_cpu_list(unsigned int cpu, + const char *file) { + struct cpufreq_affected_cpus *first = NULL; + struct cpufreq_affected_cpus *current = NULL; + char one_value[SYSFS_PATH_MAX]; + char linebuf[MAX_LINE_LEN]; + unsigned int pos, i; + unsigned int len; + + if ( ( len = sysfs_cpufreq_read_file(cpu, file, linebuf, + sizeof(linebuf))) == 0 ) + { + return NULL; + } + + pos = 0; + for ( i = 0; i < len; i++ ) + { + if ( i == len || linebuf[i] == ' ' || linebuf[i] == '\n' ) + { + if ( i - pos < 1 ) + continue; + if ( i - pos >= SYSFS_PATH_MAX ) + goto error_out; + if ( current ) { + current->next = malloc(sizeof *current); + if ( ! current->next ) + goto error_out; + current = current->next; + } else { + first = malloc(sizeof *first); + if ( ! first ) + goto error_out; + current = first; + } + current->first = first; + current->next = NULL; + + memcpy(one_value, linebuf + pos, i - pos); + one_value[i - pos] = '\0'; + + if ( sscanf(one_value, "%u", ¤t->cpu) != 1 ) + goto error_out; + + pos = i + 1; + } + } + + return first; + + error_out: + while (first) { + current = first->next; + free(first); + first = current; + } + return NULL; +} + +struct cpufreq_affected_cpus * sysfs_get_freq_affected_cpus(unsigned int cpu) { + return sysfs_get_cpu_list(cpu, "affected_cpus"); +} + +struct cpufreq_affected_cpus * sysfs_get_freq_related_cpus(unsigned int cpu) { + return sysfs_get_cpu_list(cpu, "related_cpus"); +} + +struct cpufreq_stats * sysfs_get_freq_stats(unsigned int cpu, unsigned long long *total_time) { + struct cpufreq_stats *first = NULL; + struct cpufreq_stats *current = NULL; + char one_value[SYSFS_PATH_MAX]; + char linebuf[MAX_LINE_LEN]; + unsigned int pos, i; + unsigned int len; + + if ( ( len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state", + linebuf, sizeof(linebuf))) == 0 ) + return NULL; + + *total_time = 0; + pos = 0; + for ( i = 0; i < len; i++ ) + { + if ( i == strlen(linebuf) || linebuf[i] == '\n' ) + { + if ( i - pos < 2 ) + continue; + if ( (i - pos) >= SYSFS_PATH_MAX ) + goto error_out; + if ( current ) { + current->next = malloc(sizeof *current ); + if ( ! current->next ) + goto error_out; + current = current->next; + } else { + first = malloc(sizeof *first ); + if ( ! first ) + goto error_out; + current = first; + } + current->first = first; + current->next = NULL; + + memcpy(one_value, linebuf + pos, i - pos); + one_value[i - pos] = '\0'; + if ( sscanf(one_value, "%lu %llu", ¤t->frequency, ¤t->time_in_state) != 2 ) + goto error_out; + + *total_time = *total_time + current->time_in_state; + pos = i + 1; + } + } + + return first; + + error_out: + while ( first ) { + current = first->next; + free(first); + first = current; + } + return NULL; +} + +unsigned long sysfs_get_freq_transitions(unsigned int cpu) +{ + return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS); +} + +static int verify_gov(char *new_gov, char *passed_gov) +{ + unsigned int i, j=0; + + if (!passed_gov || (strlen(passed_gov) > 19)) + return -EINVAL; + + strncpy(new_gov, passed_gov, 20); + for (i=0;i<20;i++) { + if (j) { + new_gov[i] = '\0'; + continue; + } + if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z')) { + continue; + } + if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z')) { + continue; + } + if (new_gov[i] == '-') { + continue; + } + if (new_gov[i] == '_') { + continue; + } + if (new_gov[i] == '\0') { + j = 1; + continue; + } + return -EINVAL; + } + new_gov[19] = '\0'; + return 0; +} + +int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor) +{ + char new_gov[SYSFS_PATH_MAX]; + + if (!governor) + return -EINVAL; + + if (verify_gov(new_gov, governor)) + return -EINVAL; + + return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR, + new_gov, strlen(new_gov)); +}; + +int sysfs_modify_freq_policy_max(unsigned int cpu, unsigned long max_freq) +{ + char value[SYSFS_PATH_MAX]; + + snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq); + + return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ, + value, strlen(value)); +}; + + +int sysfs_modify_freq_policy_min(unsigned int cpu, unsigned long min_freq) +{ + char value[SYSFS_PATH_MAX]; + + snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq); + + return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, + value, strlen(value)); +}; + + +int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy) +{ + char min[SYSFS_PATH_MAX]; + char max[SYSFS_PATH_MAX]; + char gov[SYSFS_PATH_MAX]; + int ret; + unsigned long old_min; + int write_max_first; + + if (!policy || !(policy->governor)) + return -EINVAL; + + if (policy->max < policy->min) + return -EINVAL; + + if (verify_gov(gov, policy->governor)) + return -EINVAL; + + snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min); + snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max); + + old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ); + write_max_first = (old_min && (policy->max < old_min) ? 0 : 1); + + if (write_max_first) { + ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ, + max, strlen(max)); + if (ret) + return ret; + } + + ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min, + strlen(min)); + if (ret) + return ret; + + if (!write_max_first) { + ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ, + max, strlen(max)); + if (ret) + return ret; + } + + return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR, + gov, strlen(gov)); +} + +int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency) { + struct cpufreq_policy *pol = sysfs_get_freq_policy(cpu); + char userspace_gov[] = "userspace"; + char freq[SYSFS_PATH_MAX]; + int ret; + + if (!pol) + return -ENODEV; + + if (strncmp(pol->governor, userspace_gov, 9) != 0) { + ret = sysfs_modify_freq_policy_governor(cpu, userspace_gov); + if (ret) { + cpufreq_put_policy(pol); + return (ret); + } + } + + cpufreq_put_policy(pol); + + snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency); + + return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED, + freq, strlen(freq)); +} + +/* CPUFREQ sysfs access **************************************************/ + +/* General sysfs access **************************************************/ +int sysfs_cpu_exists(unsigned int cpu) +{ + char file[SYSFS_PATH_MAX]; + struct stat statbuf; + + snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/", cpu); + + if ( stat(file, &statbuf) != 0 ) + return -ENOSYS; + + return S_ISDIR(statbuf.st_mode) ? 0 : -ENOSYS; +} + +/* 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..c29e5575be8a --- /dev/null +++ b/tools/power/cpupower/lib/sysfs.h @@ -0,0 +1,21 @@ +/* General */ +extern unsigned int sysfs_cpu_exists(unsigned int cpu); + +/* CPUfreq */ +extern unsigned long sysfs_get_freq_kernel(unsigned int cpu); +extern unsigned long sysfs_get_freq_hardware(unsigned int cpu); +extern unsigned long sysfs_get_freq_transition_latency(unsigned int cpu); +extern int sysfs_get_freq_hardware_limits(unsigned int cpu, unsigned long *min, unsigned long *max); +extern char * sysfs_get_freq_driver(unsigned int cpu); +extern struct cpufreq_policy * sysfs_get_freq_policy(unsigned int cpu); +extern struct cpufreq_available_governors * sysfs_get_freq_available_governors(unsigned int cpu); +extern struct cpufreq_available_frequencies * sysfs_get_available_frequencies(unsigned int cpu); +extern struct cpufreq_affected_cpus * sysfs_get_freq_affected_cpus(unsigned int cpu); +extern struct cpufreq_affected_cpus * sysfs_get_freq_related_cpus(unsigned int cpu); +extern struct cpufreq_stats * sysfs_get_freq_stats(unsigned int cpu, unsigned long long *total_time); +extern unsigned long sysfs_get_freq_transitions(unsigned int cpu); +extern int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy); +extern int sysfs_modify_freq_policy_min(unsigned int cpu, unsigned long min_freq); +extern int sysfs_modify_freq_policy_max(unsigned int cpu, unsigned long max_freq); +extern int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor); +extern int sysfs_set_frequency(unsigned int cpu, 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..3194811d58f5 --- /dev/null +++ b/tools/power/cpupower/man/cpupower-frequency-info.1 @@ -0,0 +1,76 @@ +.TH "cpufreq-info" "1" "0.1" "Mattia Dongili" "" +.SH "NAME" +.LP +cpufreq\-info \- Utility to retrieve cpufreq kernel information +.SH "SYNTAX" +.LP +cpufreq\-info [\fIoptions\fP] +.SH "DESCRIPTION" +.LP +A small tool which prints out cpufreq information helpful to developers and interested users. +.SH "OPTIONS" +.LP +.TP +\fB\-e\fR \fB\-\-debug\fR +Prints out debug information. +.TP +\fB\-f\fR \fB\-\-freq\fR +Get frequency the CPU currently runs at, according to the cpufreq core. +.TP +\fB\-w\fR \fB\-\-hwfreq\fR +Get frequency the CPU currently runs at, by reading it from hardware (only available to root). +.TP +\fB\-l\fR \fB\-\-hwlimits\fR +Determine the minimum and maximum CPU frequency allowed. +.TP +\fB\-d\fR \fB\-\-driver\fR +Determines the used cpufreq kernel driver. +.TP +\fB\-p\fR \fB\-\-policy\fR +Gets the currently used cpufreq policy. +.TP +\fB\-g\fR \fB\-\-governors\fR +Determines available cpufreq governors. +.TP +\fB\-a\fR \fB\-\-related\-cpus\fR +Determines which CPUs run at the same hardware frequency. +.TP +\fB\-a\fR \fB\-\-affected\-cpus\fR +Determines which CPUs need to have their frequency coordinated by software. +.TP +\fB\-s\fR \fB\-\-stats\fR +Shows cpufreq statistics if available. +.TP +\fB\-y\fR \fB\-\-latency\fR +Determines the maximum latency on CPU frequency changes. +.TP +\fB\-o\fR \fB\-\-proc\fR +Prints out information like provided by the /proc/cpufreq interface in 2.4. and early 2.6. kernels. +.TP +\fB\-m\fR \fB\-\-human\fR +human\-readable output for the \-f, \-w, \-s and \-y parameters. +.TP +\fB\-h\fR \fB\-\-help\fR +Prints out the help screen. +.SH "REMARKS" +.LP +By default only values of core zero are displayed. How to display settings of +other cores is described in the cpupower(1) manpage in the \-\-cpu option section. +.LP +You can't specify more than one of the output specific options \-o \-e \-a \-g \-p \-d \-l \-w \-f \-y. +.LP +You also can't specify the \-o option combined with the \-c option. +.SH "FILES" +.nf +\fI/sys/devices/system/cpu/cpu*/cpufreq/\fP +\fI/proc/cpufreq\fP (deprecated) +\fI/proc/sys/cpu/\fP (deprecated) +.fi +.SH "AUTHORS" +.nf +Dominik Brodowski \- author +Mattia Dongili \- first autolibtoolization +.fi +.SH "SEE ALSO" +.LP +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..26e3e13eee3b --- /dev/null +++ b/tools/power/cpupower/man/cpupower-frequency-set.1 @@ -0,0 +1,54 @@ +.TH "cpufreq-set" "1" "0.1" "Mattia Dongili" "" +.SH "NAME" +.LP +cpufreq\-set \- A small tool which allows to modify cpufreq settings. +.SH "SYNTAX" +.LP +cpufreq\-set [\fIoptions\fP] +.SH "DESCRIPTION" +.LP +cpufreq\-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. +.SH "OPTIONS" +.LP +.TP +\fB\-d\fR \fB\-\-min\fR +new minimum CPU frequency the governor may select. +.TP +\fB\-u\fR \fB\-\-max\fR +new maximum CPU frequency the governor may select. +.TP +\fB\-g\fR \fB\-\-governor\fR +new cpufreq governor. +.TP +\fB\-f\fR \fB\-\-freq\fR +specific frequency to be set. Requires userspace governor to be available and loaded. +.TP +\fB\-r\fR \fB\-\-related\fR +modify all hardware-related CPUs at the same time +.TP +\fB\-h\fR \fB\-\-help\fR +Prints out the help screen. +.SH "REMARKS" +.LP +By default values are applied on all cores. How to modify single core +configurations is described in the cpupower(1) manpage in the \-\-cpu option section. +.LP +The \-f FREQ, \-\-freq FREQ parameter cannot be combined with any other parameter. +.LP +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). +.LP +On Linux kernels up to 2.6.29, the \-r or \-\-related parameter is ignored. +.SH "FILES" +.nf +\fI/sys/devices/system/cpu/cpu*/cpufreq/\fP +\fI/proc/cpufreq\fP (deprecated) +\fI/proc/sys/cpu/\fP (deprecated) +.fi +.SH "AUTHORS" +.nf +Dominik Brodowski \- author +Mattia Dongili \- first autolibtoolization +.fi +.SH "SEE ALSO" +.LP +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 @@ +.TH CPUPOWER\-INFO "1" "22/02/2011" "" "cpupower Manual" +.SH NAME +cpupower\-info \- Shows processor power related kernel or hardware configurations +.SH SYNOPSIS +.ft B +.B cpupower info [ \-b ] [ \-s ] [ \-m ] + +.SH DESCRIPTION +\fBcpupower info \fP shows kernel configurations or processor hardware +registers affecting processor power saving policies. + +Some options are platform wide, some affect single cores. By default values +of core zero are displayed only. cpupower --cpu all cpuinfo will show the +settings of all cores, see cpupower(1) how to choose specific cores. + +.SH "SEE ALSO" +Options are described in detail in: + +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 @@ +.TH CPUPOWER\-MONITOR "1" "22/02/2011" "" "cpupower Manual" +.SH NAME +cpupower\-monitor \- Report processor frequency and idle statistics +.SH SYNOPSIS +.ft B +.B cpupower monitor +.RB "\-l" + +.B cpupower monitor +.RB [ "\-m ," [ ",..." ] ] +.RB [ "\-i seconds" ] +.br +.B cpupower monitor +.RB [ "\-m ," [ ",..." ] ] +.RB command +.br +.SH DESCRIPTION +\fBcpupower-monitor \fP reports processor topology, frequency and idle power +state statistics. Either \fBcommand\fP is forked and +statistics are printed upon its completion, or statistics are printed periodically. + +\fBcpupower-monitor \fP implements independent processor sleep state and +frequency counters. Some are retrieved from kernel statistics, some are +directly reading out hardware registers. Use \-l to get an overview which are +supported on your system. + +.SH Options +.PP +\-l +.RS 4 +List available monitors on your system. Additional details about each monitor +are shown: +.RS 2 +.IP \(bu +The name in quotation marks which can be passed to the \-m parameter. +.IP \(bu +The number of different counters the monitor supports in brackets. +.IP \(bu +The amount of time in seconds the counters might overflow, due to +implementation constraints. +.IP \(bu +The name and a description of each counter and its processor hierarchy level +coverage in square brackets: +.RS 4 +.IP \(bu +[T] \-> Thread +.IP \(bu +[C] \-> Core +.IP \(bu +[P] \-> Processor Package (Socket) +.IP \(bu +[M] \-> Machine/Platform wide counter +.RE +.RE +.RE +.PP +\-m ,,... +.RS 4 +Only display specific monitors. Use the monitor string(s) provided by \-l option. +.RE +.PP +\-i seconds +.RS 4 +Measure intervall. +.RE +.PP +command +.RS 4 +Measure idle and frequency characteristics of an arbitrary command/workload. +The executable \fBcommand\fP is forked and upon its exit, statistics gathered since it was +forked are displayed. +.RE +.PP +\-v +.RS 4 +Increase verbosity if the binary was compiled with the DEBUG option set. +.RE + +.SH MONITOR DESCRIPTIONS +.SS "Idle_Stats" +Shows statistics of the cpuidle kernel subsystem. Values are retrieved from +/sys/devices/system/cpu/cpu*/cpuidle/state*/. +The kernel updates these values every time an idle state is entered or +left. Therefore there can be some inaccuracy when cores are in an idle +state for some time when the measure starts or ends. In worst case it can happen +that one core stayed in an idle state for the whole measure time and the idle +state usage time as exported by the kernel did not get updated. In this case +a state residency of 0 percent is shown while it was 100. + +.SS "Mperf" +The name comes from the aperf/mperf (average and maximum) MSR registers used +which are available on recent X86 processors. It shows the average frequency +(including boost frequencies). +The fact that on all recent hardware the mperf timer stops ticking in any idle +state it is also used to show C0 (processor is active) and Cx (processor is in +any sleep state) times. These counters do not have the inaccuracy restrictions +the "Idle_Stats" counters may show. +May work poorly on Linux-2.6.20 through 2.6.29, as the \fBacpi-cpufreq \fP +kernel frequency driver periodically cleared aperf/mperf registers in those +kernels. + +.SS "Nehalem" "SandyBridge" +Intel Core and Package sleep state counters. +Threads (hyperthreaded cores) may not be able to enter deeper core states if +its sibling is utilized. +Deepest package sleep states may in reality show up as machine/platform wide +sleep states and can only be entered if all cores are idle. Look up Intel +manuals (some are provided in the References section) for further details. + +.SS "Ontario" "Liano" +AMD laptop and desktop processor (family 12h and 14h) sleep state counters. +The registers are accessed via PCI and therefore can still be read out while +cores have been offlined. + +There is one special counter: NBP1 (North Bridge P1). +This one always returns 0 or 1, depending on whether the North Bridge P1 +power state got entered at least once during measure time. +Being able to enter NBP1 state also depends on graphics power management. +Therefore this counter can be used to verify whether the graphics' driver +power management is working as expected. + +.SH EXAMPLES + +cpupower monitor -l" may show: +.RS 4 +Monitor "Mperf" (3 states) \- Might overflow after 922000000 s + + ... + +Monitor "Idle_Stats" (3 states) \- Might overflow after 4294967295 s + + ... + +.RE +cpupower monitor \-m "Idle_Stats,Mperf" scp /tmp/test /nfs/tmp + +Monitor the scp command, show both Mperf and Idle_Stats states counter +statistics, but in exchanged order. + + + +.RE +Be careful that the typical command to fully utilize one CPU by doing: + +cpupower monitor cat /dev/zero >/dev/null + +Does not work as expected, because the measured output is redirected to +/dev/null. This could get workarounded by putting the line into an own, tiny +shell script. Hit CTRL\-c to terminate the command and get the measure output +displayed. + +.SH REFERENCES +"BIOS and Kernel Developer’s Guide (BKDG) for AMD Family 14h Processors" +http://support.amd.com/us/Processor_TechDocs/43170.pdf + +"Intel® Turbo Boost Technology +in Intel® Coreâ„¢ Microarchitecture (Nehalem) Based Processors" +http://download.intel.com/design/processor/applnots/320354.pdf + +"Intel® 64 and IA-32 Architectures Software Developer's Manual +Volume 3B: System Programming Guide" +http://www.intel.com/products/processor/manuals + +.SH FILES +.ta +.nf +/dev/cpu/*/msr +/sys/devices/system/cpu/cpu*/cpuidle/state*/. +.fi + +.SH "SEE ALSO" +powertop(8), msr(4), vmstat(8) +.PP +.SH AUTHORS +.nf +Written by Thomas Renninger + +Nehalem, SandyBridge monitors and command passing +based on turbostat.8 from Len Brown 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 @@ +.TH CPUPOWER\-SET "1" "22/02/2011" "" "cpupower Manual" +.SH NAME +cpupower\-set \- Set processor power related kernel or hardware configurations +.SH SYNOPSIS +.ft B +.B cpupower set [ \-b VAL ] [ \-s VAL ] [ \-m VAL ] + + +.SH DESCRIPTION +\fBcpupower set \fP sets kernel configurations or directly accesses hardware +registers affecting processor power saving policies. + +Some options are platform wide, some affect single cores. By default values +are applied on all cores. How to modify single core configurations is +described in the cpupower(1) manpage in the \-\-cpu option section. Whether an +option affects the whole system or can be applied to individual cores is +described in the Options sections. + +Use \fBcpupower info \fP to read out current settings and whether they are +supported on the system at all. + +.SH Options +.PP +\-\-perf-bias, \-b +.RS 4 +Sets a register on supported Intel processore which allows software to convey +its policy for the relative importance of performance versus energy savings to +the processor. + +The range of valid numbers is 0-15, where 0 is maximum +performance and 15 is maximum energy efficiency. + +The processor uses this information in model-specific ways +when it must select trade-offs between performance and +energy efficiency. + +This policy hint does not supersede Processor Performance states +(P-states) or CPU Idle power states (C-states), but allows +software to have influence where it would otherwise be unable +to express a preference. + +For example, this setting may tell the hardware how +aggressively or conservatively to control frequency +in the "turbo range" above the explicitly OS-controlled +P-state frequency range. It may also tell the hardware +how aggressively it should enter the OS requested C-states. + +This option can be applied to individual cores only via the \-\-cpu option, +cpupower(1). + +Setting the performance bias value on one CPU can modify the setting on +related CPUs as well (for example all CPUs on one socket), because of +hardware restrictions. +Use \fBcpupower -c all info -b\fP to verify. + +This options needs the msr kernel driver (CONFIG_X86_MSR) loaded. +.RE +.PP +\-\-sched\-mc, \-m [ VAL ] +.RE +\-\-sched\-smt, \-s [ VAL ] +.RS 4 +\-\-sched\-mc utilizes cores in one processor package/socket first before +processes are scheduled to other processor packages/sockets. + +\-\-sched\-smt utilizes thread siblings of one processor core first before +processes are scheduled to other cores. + +The impact on power consumption and performance (positiv or negativ) heavily +depends on processor support for deep sleep states, frequency scaling and +frequency boost modes and their dependencies between other thread siblings +and processor cores. + +Taken over from kernel documentation: + +Adjust the kernel's multi-core scheduler support. + +Possible values are: +.RS 2 +0 - No power saving load balance (default value) + +1 - Fill one thread/core/package first for long running threads + +2 - Also bias task wakeups to semi-idle cpu package for power +savings +.RE + +sched_mc_power_savings is dependent upon SCHED_MC, which is +itself architecture dependent. + +sched_smt_power_savings is dependent upon SCHED_SMT, which +is itself architecture dependent. + +The two files are independent of each other. It is possible +that one file may be present without the other. + +.SH "SEE ALSO" +cpupower-info(1), cpupower-monitor(1), powertop(1) +.PP +.SH AUTHORS +.nf +\-\-perf\-bias parts written by Len Brown +Thomas Renninger diff --git a/tools/power/cpupower/man/cpupower.1 b/tools/power/cpupower/man/cpupower.1 new file mode 100644 index 000000000000..78c20feab85c --- /dev/null +++ b/tools/power/cpupower/man/cpupower.1 @@ -0,0 +1,72 @@ +.TH CPUPOWER "1" "07/03/2011" "" "cpupower Manual" +.SH NAME +cpupower \- Shows and sets processor power related values +.SH SYNOPSIS +.ft B +.B cpupower [ \-c cpulist ] subcommand [ARGS] + +.B cpupower \-v|\-\-version + +.B cpupower \-h|\-\-help + +.SH DESCRIPTION +\fBcpupower \fP is a collection of tools to examine and tune power saving +related features of your processor. + +The manpages of the subcommands (cpupower\-(1)) provide detailed +descriptions of supported features. Run \fBcpupower help\fP to get an overview +of supported subcommands. + +.SH Options +.PP +\-\-help, \-h +.RS 4 +Shows supported subcommands and general usage. +.RE +.PP +\-\-cpu cpulist, \-c cpulist +.RS 4 +Only show or set values for specific cores. +This option is not supported by all subcommands, details can be found in the +manpages of the subcommands. + +Some subcommands access all cores (typically the *\-set commands), some only +the first core (typically the *\-info commands) by default. + +The syntax for is based on how the kernel exports CPU bitmasks via +sysfs files. Some examples: +.RS 4 +.TP 16 +Input +Equivalent to +.TP +all +all cores +.TP +0\-3 +0,1,2,3 +.TP +0\-7:2 +0,2,4,6 +.TP +1,3,5-7 +1,3,5,6,7 +.TP +0\-3:2,8\-15:4 +0,2,8,12 +.RE +.RE +.PP +\-\-version, \-v +.RS 4 +Print the package name and version number. + +.SH "SEE ALSO" +cpupower-set(1), cpupower-info(1), cpupower-idle(1), +cpupower-frequency-set(1), cpupower-frequency-info(1), cpupower-monitor(1), +powertop(1) +.PP +.SH AUTHORS +.nf +\-\-perf\-bias parts written by Len Brown +Thomas Renninger 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 @@ +# translation of cs.po to Czech +# Czech translation for cpufrequtils package +# Czech messages for cpufrequtils. +# Copyright (C) 2007 kavol +# This file is distributed under the same license as the cpufrequtils package. +# +# Karel Volný , 2007, 2008. +msgid "" +msgstr "" +"Project-Id-Version: cs\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-03-08 17:03+0100\n" +"PO-Revision-Date: 2008-06-11 16:26+0200\n" +"Last-Translator: Karel Volný \n" +"Language-Team: Czech \n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: KBabel 1.11.4\n" + +#: utils/idle_monitor/nhm_idle.c:36 +msgid "Processor Core C3" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:43 +msgid "Processor Core C6" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:51 +msgid "Processor Package C3" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70 +msgid "Processor Package C6" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:33 +msgid "Processor Core C7" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:40 +msgid "Processor Package C2" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:47 +msgid "Processor Package C7" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:56 +msgid "Package in sleep state (PC1 or deeper)" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:63 +msgid "Processor Package C1" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:77 +msgid "North Bridge P1 boolean counter (returns 0 or 1)" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:35 +msgid "Processor Core not idle" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:42 +msgid "Processor Core in an idle state" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:50 +msgid "Average Frequency (including boost) in MHz" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:66 +#, c-format +msgid "" +"cpupower monitor: [-h] [ [-t] | [-l] | [-m ,[] ] ] [-i " +"interval_sec | -c command ...]\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:69 +#, c-format +msgid "" +"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m ,[] ] ] [-i " +"interval_sec | -c command ...]\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:71 +#, c-format +msgid "\t -v: be more verbose\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:73 +#, c-format +msgid "\t -h: print this help\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:74 +#, c-format +msgid "\t -i: time intervall to measure for in seconds (default 1)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:75 +#, c-format +msgid "\t -t: show CPU topology/hierarchy\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:76 +#, c-format +msgid "\t -l: list available CPU sleep monitors (for use with -m)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:77 +#, c-format +msgid "\t -m: show specific CPU sleep monitors only (in same order)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:79 +#, c-format +msgid "" +"only one of: -t, -l, -m are allowed\n" +"If none of them is passed," +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:80 +#, c-format +msgid " all supported monitors are shown\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:197 +#, c-format +msgid "Monitor %s, Counter %s has no count function. Implementation error\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:207 +#, c-format +msgid " *is offline\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:236 +#, c-format +msgid "%s: max monitor name length (%d) exceeded\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:250 +#, c-format +msgid "No matching monitor found in %s, try -l option\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:266 +#, c-format +msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:319 +#, c-format +msgid "%s took %.5f seconds and exited with status %d\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:406 +#, c-format +msgid "Cannot read number of available processors\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:417 +#, c-format +msgid "Available monitor %s needs root access\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:428 +#, c-format +msgid "No HW Cstate monitors found\n" +msgstr "" + +#: utils/cpupower.c:78 +#, c-format +msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n" +msgstr "" + +#: utils/cpupower.c:79 +#, c-format +msgid "cpupower --version\n" +msgstr "" + +#: utils/cpupower.c:80 +#, c-format +msgid "Supported subcommands are:\n" +msgstr "" + +#: utils/cpupower.c:83 +#, c-format +msgid "" +"\n" +"Some subcommands can make use of the -c cpulist option.\n" +msgstr "" + +#: utils/cpupower.c:84 +#, c-format +msgid "Look at the general cpupower manpage how to use it\n" +msgstr "" + +#: utils/cpupower.c:85 +#, c-format +msgid "and read up the subcommand's manpage whether it is supported.\n" +msgstr "" + +#: utils/cpupower.c:86 +#, c-format +msgid "" +"\n" +"Use cpupower help subcommand for getting help for above subcommands.\n" +msgstr "" + +#: utils/cpupower.c:91 +#, c-format +msgid "Report errors and bugs to %s, please.\n" +msgstr "" +"Chyby v programu prosím hlaste na %s (anglicky).\n" +"Chyby v pÅ™ekladu prosím hlaste na kavol@seznam.cz (Äesky ;-)\n" + +#: utils/cpupower.c:114 +#, c-format +msgid "Error parsing cpu list\n" +msgstr "" + +#: utils/cpupower.c:172 +#, c-format +msgid "Subcommand %s needs root privileges\n" +msgstr "" + +#: utils/cpufreq-info.c:31 +#, c-format +msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n" +msgstr "Nelze zjistit poÄet CPU (%s: %s), pÅ™edpokládá se 1.\n" + +#: utils/cpufreq-info.c:63 +#, c-format +msgid "" +" minimum CPU frequency - maximum CPU frequency - governor\n" +msgstr "" +" minimální frekvence CPU - maximální frekvence CPU - regulátor\n" + +#: utils/cpufreq-info.c:151 +#, c-format +msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n" +msgstr "" + +#. P state changes via MSR are identified via cpuid 80000007 +#. on Intel and AMD, but we assume boost capable machines can do that +#. if (cpuid_eax(0x80000000) >= 0x80000007 +#. && (cpuid_edx(0x80000007) & (1 << 7))) +#. +#: utils/cpufreq-info.c:161 +#, c-format +msgid " boost state support: \n" +msgstr "" + +#: utils/cpufreq-info.c:163 +#, c-format +msgid " Supported: %s\n" +msgstr "" + +#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 +msgid "yes" +msgstr "" + +#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 +msgid "no" +msgstr "" + +#: utils/cpufreq-info.c:164 +#, fuzzy, c-format +msgid " Active: %s\n" +msgstr " ovladaÄ: %s\n" + +#: utils/cpufreq-info.c:177 +#, c-format +msgid " Boost States: %d\n" +msgstr "" + +#: utils/cpufreq-info.c:178 +#, c-format +msgid " Total States: %d\n" +msgstr "" + +#: utils/cpufreq-info.c:181 +#, c-format +msgid " Pstate-Pb%d: %luMHz (boost state)\n" +msgstr "" + +#: utils/cpufreq-info.c:184 +#, c-format +msgid " Pstate-P%d: %luMHz\n" +msgstr "" + +#: utils/cpufreq-info.c:211 +#, c-format +msgid " no or unknown cpufreq driver is active on this CPU\n" +msgstr " pro tento CPU není aktivní žádný známý ovladaÄ cpufreq\n" + +#: utils/cpufreq-info.c:213 +#, c-format +msgid " driver: %s\n" +msgstr " ovladaÄ: %s\n" + +#: utils/cpufreq-info.c:219 +#, fuzzy, c-format +msgid " CPUs which run at the same hardware frequency: " +msgstr " CPU, které musí mÄ›nit frekvenci zároveň: " + +#: utils/cpufreq-info.c:230 +#, fuzzy, c-format +msgid " CPUs which need to have their frequency coordinated by software: " +msgstr " CPU, které musí mÄ›nit frekvenci zároveň: " + +#: utils/cpufreq-info.c:241 +#, c-format +msgid " maximum transition latency: " +msgstr "" + +#: utils/cpufreq-info.c:247 +#, c-format +msgid " hardware limits: " +msgstr " hardwarové meze: " + +#: utils/cpufreq-info.c:256 +#, c-format +msgid " available frequency steps: " +msgstr " dostupné frekvence: " + +#: utils/cpufreq-info.c:269 +#, c-format +msgid " available cpufreq governors: " +msgstr " dostupné regulátory: " + +#: utils/cpufreq-info.c:280 +#, c-format +msgid " current policy: frequency should be within " +msgstr " souÄasná taktika: frekvence by mÄ›la být mezi " + +#: utils/cpufreq-info.c:282 +#, c-format +msgid " and " +msgstr " a " + +#: utils/cpufreq-info.c:286 +#, c-format +msgid "" +"The governor \"%s\" may decide which speed to use\n" +" within this range.\n" +msgstr "" +" Regulátor \"%s\" může rozhodnout jakou frekvenci použít\n" +" v tÄ›chto mezích.\n" + +#: utils/cpufreq-info.c:293 +#, c-format +msgid " current CPU frequency is " +msgstr " souÄasná frekvence CPU je " + +#: utils/cpufreq-info.c:296 +#, c-format +msgid " (asserted by call to hardware)" +msgstr " (zjiÅ¡tÄ›no hardwarovým voláním)" + +#: utils/cpufreq-info.c:304 +#, c-format +msgid " cpufreq stats: " +msgstr " statistika cpufreq: " + +#: utils/cpufreq-info.c:472 +#, fuzzy, c-format +msgid "Usage: cpupower freqinfo [options]\n" +msgstr "Užití: cpufreq-info [pÅ™epínaÄe]\n" + +#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23 +#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148 +#, c-format +msgid "Options:\n" +msgstr "PÅ™epínaÄe:\n" + +#: utils/cpufreq-info.c:474 +#, fuzzy, c-format +msgid " -e, --debug Prints out debug information [default]\n" +msgstr " -e, --debug Vypíše ladicí informace\n" + +#: utils/cpufreq-info.c:475 +#, c-format +msgid "" +" -f, --freq Get frequency the CPU currently runs at, according\n" +" to the cpufreq core *\n" +msgstr "" +" -f, --freq Zjistí aktuální frekvenci, na které CPU běží\n" +" podle cpufreq *\n" + +#: utils/cpufreq-info.c:477 +#, c-format +msgid "" +" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n" +" it from hardware (only available to root) *\n" +msgstr "" +" -w, --hwfreq Zjistí aktuální frekvenci, na které CPU běží\n" +" z hardware (dostupné jen uživateli root) *\n" + +#: utils/cpufreq-info.c:479 +#, c-format +msgid "" +" -l, --hwlimits Determine the minimum and maximum CPU frequency " +"allowed *\n" +msgstr "" +" -l, --hwlimits Zjistí minimální a maximální dostupnou frekvenci CPU " +"*\n" + +#: utils/cpufreq-info.c:480 +#, c-format +msgid " -d, --driver Determines the used cpufreq kernel driver *\n" +msgstr " -d, --driver Zjistí aktivní ovladaÄ cpufreq *\n" + +#: utils/cpufreq-info.c:481 +#, c-format +msgid " -p, --policy Gets the currently used cpufreq policy *\n" +msgstr " -p, --policy Zjistí aktuální taktiku cpufreq *\n" + +#: utils/cpufreq-info.c:482 +#, c-format +msgid " -g, --governors Determines available cpufreq governors *\n" +msgstr " -g, --governors Zjistí dostupné regulátory cpufreq *\n" + +#: utils/cpufreq-info.c:483 +#, fuzzy, c-format +msgid "" +" -r, --related-cpus Determines which CPUs run at the same hardware " +"frequency *\n" +msgstr "" +" -a, --affected-cpus Zjistí, které CPU musí mÄ›nit frekvenci zároveň *\n" + +#: utils/cpufreq-info.c:484 +#, fuzzy, c-format +msgid "" +" -a, --affected-cpus Determines which CPUs need to have their frequency\n" +" coordinated by software *\n" +msgstr "" +" -a, --affected-cpus Zjistí, které CPU musí mÄ›nit frekvenci zároveň *\n" + +#: utils/cpufreq-info.c:486 +#, c-format +msgid " -s, --stats Shows cpufreq statistics if available\n" +msgstr " -s, --stats Zobrazí statistiku cpufreq, je-li dostupná\n" + +#: utils/cpufreq-info.c:487 +#, fuzzy, c-format +msgid "" +" -y, --latency Determines the maximum latency on CPU frequency " +"changes *\n" +msgstr "" +" -l, --hwlimits Zjistí minimální a maximální dostupnou frekvenci CPU " +"*\n" + +#: utils/cpufreq-info.c:488 +#, c-format +msgid " -b, --boost Checks for turbo or boost modes *\n" +msgstr "" + +#: utils/cpufreq-info.c:489 +#, c-format +msgid "" +" -o, --proc Prints out information like provided by the /proc/" +"cpufreq\n" +" interface in 2.4. and early 2.6. kernels\n" +msgstr "" +" -o, --proc Vypíše informace ve formátu, jaký používalo rozhraní\n" +" /proc/cpufreq v kernelech Å™ady 2.4 a Äasné 2.6\n" + +#: utils/cpufreq-info.c:491 +#, fuzzy, c-format +msgid "" +" -m, --human human-readable output for the -f, -w, -s and -y " +"parameters\n" +msgstr "" +" -m, --human Výstup parametrů -f, -w a -s v „lidmi Äitelném“ " +"formátu\n" + +#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152 +#, c-format +msgid " -h, --help Prints out this screen\n" +msgstr " -h, --help Vypíše tuto nápovÄ›du\n" + +#: utils/cpufreq-info.c:495 +#, c-format +msgid "" +"If no argument or only the -c, --cpu parameter is given, debug output about\n" +"cpufreq is printed which is useful e.g. for reporting bugs.\n" +msgstr "" +"Není-li zadán žádný parametr nebo je-li zadán pouze pÅ™epínaÄ -c, --cpu, " +"jsou\n" +"vypsány ladicí informace, což může být užiteÄné například pÅ™i hlášení chyb.\n" + +#: utils/cpufreq-info.c:497 +#, c-format +msgid "" +"For the arguments marked with *, omitting the -c or --cpu argument is\n" +"equivalent to setting it to zero\n" +msgstr "" +"Není-li pÅ™i použití pÅ™epínaÄů oznaÄených * zadán parametr -c nebo --cpu,\n" +"pÅ™edpokládá se jeho hodnota 0.\n" + +#: utils/cpufreq-info.c:580 +#, c-format +msgid "" +"The argument passed to this tool can't be combined with passing a --cpu " +"argument\n" +msgstr "Zadaný parametr nemůže být použit zároveň s pÅ™epínaÄem -c nebo --cpu\n" + +#: utils/cpufreq-info.c:596 +#, c-format +msgid "" +"You can't specify more than one --cpu parameter and/or\n" +"more than one output-specific argument\n" +msgstr "" +"Nelze zadat více než jeden parametr -c nebo --cpu\n" +"anebo více než jeden parametr urÄující výstup\n" + +#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42 +#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213 +#, c-format +msgid "invalid or unknown argument\n" +msgstr "neplatný nebo neznámý parametr\n" + +#: utils/cpufreq-info.c:617 +#, c-format +msgid "couldn't analyze CPU %d as it doesn't seem to be present\n" +msgstr "nelze analyzovat CPU %d, vypadá to, že není přítomen\n" + +#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142 +#, c-format +msgid "analyzing CPU %d:\n" +msgstr "analyzuji CPU %d:\n" + +#: utils/cpufreq-set.c:25 +#, fuzzy, c-format +msgid "Usage: cpupower frequency-set [options]\n" +msgstr "Užití: cpufreq-set [pÅ™epínaÄe]\n" + +#: utils/cpufreq-set.c:27 +#, c-format +msgid "" +" -d FREQ, --min FREQ new minimum CPU frequency the governor may " +"select\n" +msgstr "" +" -d FREQ, --min FREQ Nová nejnižší frekvence, kterou může regulátor " +"vybrat\n" + +#: utils/cpufreq-set.c:28 +#, c-format +msgid "" +" -u FREQ, --max FREQ new maximum CPU frequency the governor may " +"select\n" +msgstr "" +" -u FREQ, --max FREQ Nová nejvyšší frekvence, kterou může regulátor " +"zvolit\n" + +#: utils/cpufreq-set.c:29 +#, c-format +msgid " -g GOV, --governor GOV new cpufreq governor\n" +msgstr " -g GOV, --governors GOV Nový regulátor cpufreq\n" + +#: utils/cpufreq-set.c:30 +#, c-format +msgid "" +" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n" +" governor to be available and loaded\n" +msgstr "" +" -f FREQ, --freq FREQ Frekvence, která má být nastavena. Vyžaduje, aby " +"byl\n" +" v jádÅ™e nahrán regulátor ‚userspace‘.\n" + +#: utils/cpufreq-set.c:32 +#, c-format +msgid " -r, --related Switches all hardware-related CPUs\n" +msgstr "" + +#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27 +#, fuzzy, c-format +msgid " -h, --help Prints out this screen\n" +msgstr " -h, --help Vypíše tuto nápovÄ›du\n" + +#: utils/cpufreq-set.c:35 +#, fuzzy, c-format +msgid "" +"Notes:\n" +"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n" +msgstr "" +"Není-li pÅ™i použití pÅ™epínaÄů oznaÄených * zadán parametr -c nebo --cpu,\n" +"pÅ™edpokládá se jeho hodnota 0.\n" + +#: utils/cpufreq-set.c:37 +#, fuzzy, c-format +msgid "" +"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other " +"parameter\n" +" except the -c CPU, --cpu CPU parameter\n" +"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n" +" by postfixing the value with the wanted unit name, without any space\n" +" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n" +msgstr "" +"Poznámky:\n" +"1. Vynechání parametru -c nebo --cpu je ekvivalentní jeho nastavení na 0\n" +"2. PÅ™epínaÄ -f nebo --freq nemůže být použit zároveň s žádným jiným vyjma -" +"c\n" +" nebo --cpu\n" +"3. Frekvence (FREQ) mohou být zadány v Hz, kHz (výchozí), MHz, GHz nebo THz\n" +" pÅ™ipojením názvu jednotky bez mezery mezi Äíslem a jednotkou\n" +" (FREQ v kHz =^ Hz * 0,001 = ^ MHz * 1000 =^ GHz * 1000000)\n" + +#: utils/cpufreq-set.c:57 +#, c-format +msgid "" +"Error setting new values. Common errors:\n" +"- Do you have proper administration rights? (super-user?)\n" +"- Is the governor you requested available and modprobed?\n" +"- Trying to set an invalid policy?\n" +"- Trying to set a specific frequency, but userspace governor is not " +"available,\n" +" for example because of hardware which cannot be set to a specific " +"frequency\n" +" or because the userspace governor isn't loaded?\n" +msgstr "" +"Chyba pÅ™i nastavování nových hodnot. Obvyklé problémy:\n" +"- Máte patÅ™iÄná administrátorská práva? (root?)\n" +"- Je požadovaný regulátor dostupný v jádÅ™e? (modprobe?)\n" +"- Snažíte se nastavit neplatnou taktiku?\n" +"- Snažíte se nastavit urÄitou frekvenci, ale není dostupný\n" +" regulátor ‚userspace‘, například protože není nahrán v jádÅ™e,\n" +" nebo nelze na tomto hardware nastavit urÄitou frekvenci?\n" + +#: utils/cpufreq-set.c:170 +#, c-format +msgid "wrong, unknown or unhandled CPU?\n" +msgstr "neznámý nebo nepodporovaný CPU?\n" + +#: utils/cpufreq-set.c:302 +#, c-format +msgid "" +"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n" +"-g/--governor parameters\n" +msgstr "" +"pÅ™epínaÄ -f/--freq nemůže být použit zároveň\n" +"s pÅ™epínaÄem -d/--min, -u/--max nebo -g/--governor\n" + +#: utils/cpufreq-set.c:308 +#, c-format +msgid "" +"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n" +"-g/--governor must be passed\n" +msgstr "" +"Musí být zadán alespoň jeden pÅ™epínaÄ\n" +"-f/--freq, -d/--min, -u/--max nebo -g/--governor\n" + +#: utils/cpufreq-set.c:347 +#, c-format +msgid "Setting cpu: %d\n" +msgstr "" + +#: utils/cpupower-set.c:22 +#, c-format +msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n" +msgstr "" + +#: utils/cpupower-set.c:24 +#, c-format +msgid "" +" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n" +" Intel models [0-15], see manpage for details\n" +msgstr "" + +#: utils/cpupower-set.c:26 +#, c-format +msgid "" +" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n" +msgstr "" + +#: utils/cpupower-set.c:27 +#, c-format +msgid "" +" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler " +"policy.\n" +msgstr "" + +#: utils/cpupower-set.c:80 +#, c-format +msgid "--perf-bias param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:91 +#, c-format +msgid "--sched-mc param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:102 +#, c-format +msgid "--sched-smt param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:121 +#, c-format +msgid "Error setting sched-mc %s\n" +msgstr "" + +#: utils/cpupower-set.c:127 +#, c-format +msgid "Error setting sched-smt %s\n" +msgstr "" + +#: utils/cpupower-set.c:146 +#, c-format +msgid "Error setting perf-bias value on CPU %d\n" +msgstr "" + +#: utils/cpupower-info.c:21 +#, c-format +msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n" +msgstr "" + +#: utils/cpupower-info.c:23 +#, c-format +msgid "" +" -b, --perf-bias Gets CPU's power vs performance policy on some\n" +" Intel models [0-15], see manpage for details\n" +msgstr "" + +#: utils/cpupower-info.c:25 +#, fuzzy, c-format +msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n" +msgstr " -p, --policy Zjistí aktuální taktiku cpufreq *\n" + +#: utils/cpupower-info.c:26 +#, c-format +msgid "" +" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n" +msgstr "" + +#: utils/cpupower-info.c:28 +#, c-format +msgid "" +"\n" +"Passing no option will show all info, by default only on core 0\n" +msgstr "" + +#: utils/cpupower-info.c:102 +#, c-format +msgid "System's multi core scheduler setting: " +msgstr "" + +#. if sysfs file is missing it's: errno == ENOENT +#: utils/cpupower-info.c:105 utils/cpupower-info.c:114 +#, c-format +msgid "not supported\n" +msgstr "" + +#: utils/cpupower-info.c:111 +#, c-format +msgid "System's thread sibling scheduler setting: " +msgstr "" + +#: utils/cpupower-info.c:126 +#, c-format +msgid "Intel's performance bias setting needs root privileges\n" +msgstr "" + +#: utils/cpupower-info.c:128 +#, c-format +msgid "System does not support Intel's performance bias setting\n" +msgstr "" + +#: utils/cpupower-info.c:147 +#, c-format +msgid "Could not read perf-bias value\n" +msgstr "" + +#: utils/cpupower-info.c:150 +#, c-format +msgid "perf-bias: %d\n" +msgstr "" + +#: utils/cpuidle-info.c:28 +#, fuzzy, c-format +msgid "Analyzing CPU %d:\n" +msgstr "analyzuji CPU %d:\n" + +#: utils/cpuidle-info.c:32 +#, c-format +msgid "CPU %u: No idle states\n" +msgstr "" + +#: utils/cpuidle-info.c:36 +#, c-format +msgid "CPU %u: Can't read idle state info\n" +msgstr "" + +#: utils/cpuidle-info.c:41 +#, c-format +msgid "Could not determine max idle state %u\n" +msgstr "" + +#: utils/cpuidle-info.c:46 +#, c-format +msgid "Number of idle states: %d\n" +msgstr "" + +#: utils/cpuidle-info.c:48 +#, fuzzy, c-format +msgid "Available idle states:" +msgstr " dostupné frekvence: " + +#: utils/cpuidle-info.c:71 +#, c-format +msgid "Flags/Description: %s\n" +msgstr "" + +#: utils/cpuidle-info.c:74 +#, c-format +msgid "Latency: %lu\n" +msgstr "" + +#: utils/cpuidle-info.c:76 +#, c-format +msgid "Usage: %lu\n" +msgstr "" + +#: utils/cpuidle-info.c:78 +#, c-format +msgid "Duration: %llu\n" +msgstr "" + +#: utils/cpuidle-info.c:90 +#, c-format +msgid "Could not determine cpuidle driver\n" +msgstr "" + +#: utils/cpuidle-info.c:94 +#, fuzzy, c-format +msgid "CPUidle driver: %s\n" +msgstr " ovladaÄ: %s\n" + +#: utils/cpuidle-info.c:99 +#, c-format +msgid "Could not determine cpuidle governor\n" +msgstr "" + +#: utils/cpuidle-info.c:103 +#, c-format +msgid "CPUidle governor: %s\n" +msgstr "" + +#: utils/cpuidle-info.c:122 +#, c-format +msgid "CPU %u: Can't read C-state info\n" +msgstr "" + +#. printf("Cstates: %d\n", cstates); +#: utils/cpuidle-info.c:127 +#, c-format +msgid "active state: C0\n" +msgstr "" + +#: utils/cpuidle-info.c:128 +#, c-format +msgid "max_cstate: C%u\n" +msgstr "" + +#: utils/cpuidle-info.c:129 +#, c-format +msgid "maximum allowed latency: %lu usec\n" +msgstr "" + +#: utils/cpuidle-info.c:130 +#, c-format +msgid "states:\t\n" +msgstr "" + +#: utils/cpuidle-info.c:132 +#, c-format +msgid " C%d: type[C%d] " +msgstr "" + +#: utils/cpuidle-info.c:134 +#, c-format +msgid "promotion[--] demotion[--] " +msgstr "" + +#: utils/cpuidle-info.c:135 +#, c-format +msgid "latency[%03lu] " +msgstr "" + +#: utils/cpuidle-info.c:137 +#, c-format +msgid "usage[%08lu] " +msgstr "" + +#: utils/cpuidle-info.c:139 +#, c-format +msgid "duration[%020Lu] \n" +msgstr "" + +#: utils/cpuidle-info.c:147 +#, fuzzy, c-format +msgid "Usage: cpupower idleinfo [options]\n" +msgstr "Užití: cpufreq-info [pÅ™epínaÄe]\n" + +#: utils/cpuidle-info.c:149 +#, fuzzy, c-format +msgid " -s, --silent Only show general C-state information\n" +msgstr " -e, --debug Vypíše ladicí informace\n" + +#: utils/cpuidle-info.c:150 +#, fuzzy, c-format +msgid "" +" -o, --proc Prints out information like provided by the /proc/" +"acpi/processor/*/power\n" +" interface in older kernels\n" +msgstr "" +" -o, --proc Vypíše informace ve formátu, jaký používalo rozhraní\n" +" /proc/cpufreq v kernelech Å™ady 2.4 a Äasné 2.6\n" + +#: utils/cpuidle-info.c:209 +#, fuzzy, c-format +msgid "You can't specify more than one output-specific argument\n" +msgstr "" +"Nelze zadat více než jeden parametr -c nebo --cpu\n" +"anebo více než jeden parametr urÄující výstup\n" + +#~ msgid "" +#~ " -c CPU, --cpu CPU CPU number which information shall be determined " +#~ "about\n" +#~ msgstr "" +#~ " -c CPU, --cpu CPU Číslo CPU, o kterém se mají zjistit informace\n" + +#~ msgid "" +#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be " +#~ "modified\n" +#~ msgstr "" +#~ " -c CPU, --cpu CPU Číslo CPU pro který se má provést nastavení " +#~ "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 @@ +# German translations for cpufrequtils package +# German messages for cpufrequtils. +# Copyright (C) 2004-2009 Dominik Brodowski +# This file is distributed under the same license as the cpufrequtils package. +# +msgid "" +msgstr "" +"Project-Id-Version: cpufrequtils 006\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-03-08 17:03+0100\n" +"PO-Revision-Date: 2009-08-08 17:18+0100\n" +"Last-Translator: \n" +"Language-Team: NONE\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: utils/idle_monitor/nhm_idle.c:36 +msgid "Processor Core C3" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:43 +msgid "Processor Core C6" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:51 +msgid "Processor Package C3" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70 +msgid "Processor Package C6" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:33 +msgid "Processor Core C7" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:40 +msgid "Processor Package C2" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:47 +msgid "Processor Package C7" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:56 +msgid "Package in sleep state (PC1 or deeper)" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:63 +msgid "Processor Package C1" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:77 +msgid "North Bridge P1 boolean counter (returns 0 or 1)" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:35 +msgid "Processor Core not idle" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:42 +msgid "Processor Core in an idle state" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:50 +msgid "Average Frequency (including boost) in MHz" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:66 +#, c-format +msgid "" +"cpupower monitor: [-h] [ [-t] | [-l] | [-m ,[] ] ] [-i " +"interval_sec | -c command ...]\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:69 +#, c-format +msgid "" +"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m ,[] ] ] [-i " +"interval_sec | -c command ...]\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:71 +#, c-format +msgid "\t -v: be more verbose\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:73 +#, c-format +msgid "\t -h: print this help\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:74 +#, c-format +msgid "\t -i: time intervall to measure for in seconds (default 1)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:75 +#, c-format +msgid "\t -t: show CPU topology/hierarchy\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:76 +#, c-format +msgid "\t -l: list available CPU sleep monitors (for use with -m)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:77 +#, c-format +msgid "\t -m: show specific CPU sleep monitors only (in same order)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:79 +#, c-format +msgid "" +"only one of: -t, -l, -m are allowed\n" +"If none of them is passed," +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:80 +#, c-format +msgid " all supported monitors are shown\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:197 +#, c-format +msgid "Monitor %s, Counter %s has no count function. Implementation error\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:207 +#, c-format +msgid " *is offline\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:236 +#, c-format +msgid "%s: max monitor name length (%d) exceeded\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:250 +#, c-format +msgid "No matching monitor found in %s, try -l option\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:266 +#, c-format +msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:319 +#, c-format +msgid "%s took %.5f seconds and exited with status %d\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:406 +#, c-format +msgid "Cannot read number of available processors\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:417 +#, c-format +msgid "Available monitor %s needs root access\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:428 +#, c-format +msgid "No HW Cstate monitors found\n" +msgstr "" + +#: utils/cpupower.c:78 +#, c-format +msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n" +msgstr "" + +#: utils/cpupower.c:79 +#, c-format +msgid "cpupower --version\n" +msgstr "" + +#: utils/cpupower.c:80 +#, c-format +msgid "Supported subcommands are:\n" +msgstr "" + +#: utils/cpupower.c:83 +#, c-format +msgid "" +"\n" +"Some subcommands can make use of the -c cpulist option.\n" +msgstr "" + +#: utils/cpupower.c:84 +#, c-format +msgid "Look at the general cpupower manpage how to use it\n" +msgstr "" + +#: utils/cpupower.c:85 +#, c-format +msgid "and read up the subcommand's manpage whether it is supported.\n" +msgstr "" + +#: utils/cpupower.c:86 +#, c-format +msgid "" +"\n" +"Use cpupower help subcommand for getting help for above subcommands.\n" +msgstr "" + +#: utils/cpupower.c:91 +#, c-format +msgid "Report errors and bugs to %s, please.\n" +msgstr "Bitte melden Sie Fehler an %s.\n" + +#: utils/cpupower.c:114 +#, c-format +msgid "Error parsing cpu list\n" +msgstr "" + +#: utils/cpupower.c:172 +#, c-format +msgid "Subcommand %s needs root privileges\n" +msgstr "" + +#: utils/cpufreq-info.c:31 +#, c-format +msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n" +msgstr "" +"Konnte nicht die Anzahl der CPUs herausfinden (%s : %s), nehme daher 1 an.\n" + +#: utils/cpufreq-info.c:63 +#, c-format +msgid "" +" minimum CPU frequency - maximum CPU frequency - governor\n" +msgstr "" +" minimale CPU-Taktfreq. - maximale CPU-Taktfreq. - Regler \n" + +#: utils/cpufreq-info.c:151 +#, c-format +msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n" +msgstr "" + +#. P state changes via MSR are identified via cpuid 80000007 +#. on Intel and AMD, but we assume boost capable machines can do that +#. if (cpuid_eax(0x80000000) >= 0x80000007 +#. && (cpuid_edx(0x80000007) & (1 << 7))) +#. +#: utils/cpufreq-info.c:161 +#, c-format +msgid " boost state support: \n" +msgstr "" + +#: utils/cpufreq-info.c:163 +#, c-format +msgid " Supported: %s\n" +msgstr "" + +#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 +msgid "yes" +msgstr "" + +#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 +msgid "no" +msgstr "" + +#: utils/cpufreq-info.c:164 +#, fuzzy, c-format +msgid " Active: %s\n" +msgstr " Treiber: %s\n" + +#: utils/cpufreq-info.c:177 +#, c-format +msgid " Boost States: %d\n" +msgstr "" + +#: utils/cpufreq-info.c:178 +#, c-format +msgid " Total States: %d\n" +msgstr "" + +#: utils/cpufreq-info.c:181 +#, c-format +msgid " Pstate-Pb%d: %luMHz (boost state)\n" +msgstr "" + +#: utils/cpufreq-info.c:184 +#, c-format +msgid " Pstate-P%d: %luMHz\n" +msgstr "" + +#: utils/cpufreq-info.c:211 +#, c-format +msgid " no or unknown cpufreq driver is active on this CPU\n" +msgstr " kein oder nicht bestimmbarer cpufreq-Treiber aktiv\n" + +#: utils/cpufreq-info.c:213 +#, c-format +msgid " driver: %s\n" +msgstr " Treiber: %s\n" + +#: utils/cpufreq-info.c:219 +#, c-format +msgid " CPUs which run at the same hardware frequency: " +msgstr " Folgende CPUs laufen mit der gleichen Hardware-Taktfrequenz: " + +#: utils/cpufreq-info.c:230 +#, c-format +msgid " CPUs which need to have their frequency coordinated by software: " +msgstr " Die Taktfrequenz folgender CPUs werden per Software koordiniert: " + +#: utils/cpufreq-info.c:241 +#, c-format +msgid " maximum transition latency: " +msgstr " Maximale Dauer eines Taktfrequenzwechsels: " + +#: utils/cpufreq-info.c:247 +#, c-format +msgid " hardware limits: " +msgstr " Hardwarebedingte Grenzen der Taktfrequenz: " + +#: utils/cpufreq-info.c:256 +#, c-format +msgid " available frequency steps: " +msgstr " mögliche Taktfrequenzen: " + +#: utils/cpufreq-info.c:269 +#, c-format +msgid " available cpufreq governors: " +msgstr " mögliche Regler: " + +#: utils/cpufreq-info.c:280 +#, c-format +msgid " current policy: frequency should be within " +msgstr " momentane Taktik: die Frequenz soll innerhalb " + +#: utils/cpufreq-info.c:282 +#, c-format +msgid " and " +msgstr " und " + +#: utils/cpufreq-info.c:286 +#, c-format +msgid "" +"The governor \"%s\" may decide which speed to use\n" +" within this range.\n" +msgstr "" +" liegen. Der Regler \"%s\" kann frei entscheiden,\n" +" welche Taktfrequenz innerhalb dieser Grenze verwendet " +"wird.\n" + +#: utils/cpufreq-info.c:293 +#, c-format +msgid " current CPU frequency is " +msgstr " momentane Taktfrequenz ist " + +#: utils/cpufreq-info.c:296 +#, c-format +msgid " (asserted by call to hardware)" +msgstr " (verifiziert durch Nachfrage bei der Hardware)" + +#: utils/cpufreq-info.c:304 +#, c-format +msgid " cpufreq stats: " +msgstr " Statistik:" + +#: utils/cpufreq-info.c:472 +#, fuzzy, c-format +msgid "Usage: cpupower freqinfo [options]\n" +msgstr "Aufruf: cpufreq-info [Optionen]\n" + +#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23 +#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148 +#, c-format +msgid "Options:\n" +msgstr "Optionen:\n" + +#: utils/cpufreq-info.c:474 +#, fuzzy, c-format +msgid " -e, --debug Prints out debug information [default]\n" +msgstr "" +" -e, --debug Erzeugt detaillierte Informationen, hilfreich\n" +" zum Aufspüren von Fehlern\n" + +#: utils/cpufreq-info.c:475 +#, c-format +msgid "" +" -f, --freq Get frequency the CPU currently runs at, according\n" +" to the cpufreq core *\n" +msgstr "" +" -f, --freq Findet die momentane CPU-Taktfrquenz heraus (nach\n" +" Meinung des Betriebssystems) *\n" + +#: utils/cpufreq-info.c:477 +#, c-format +msgid "" +" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n" +" it from hardware (only available to root) *\n" +msgstr "" +" -w, --hwfreq Findet die momentane CPU-Taktfrequenz heraus\n" +" (verifiziert durch Nachfrage bei der Hardware)\n" +" [nur der Administrator kann dies tun] *\n" + +#: utils/cpufreq-info.c:479 +#, c-format +msgid "" +" -l, --hwlimits Determine the minimum and maximum CPU frequency " +"allowed *\n" +msgstr "" +" -l, --hwlimits Findet die minimale und maximale Taktfrequenz heraus " +"*\n" + +#: utils/cpufreq-info.c:480 +#, c-format +msgid " -d, --driver Determines the used cpufreq kernel driver *\n" +msgstr " -d, --driver Findet den momentanen Treiber heraus *\n" + +#: utils/cpufreq-info.c:481 +#, c-format +msgid " -p, --policy Gets the currently used cpufreq policy *\n" +msgstr " -p, --policy Findet die momentane Taktik heraus *\n" + +#: utils/cpufreq-info.c:482 +#, c-format +msgid " -g, --governors Determines available cpufreq governors *\n" +msgstr " -g, --governors Erzeugt eine Liste mit verfügbaren Reglern *\n" + +#: utils/cpufreq-info.c:483 +#, c-format +msgid "" +" -r, --related-cpus Determines which CPUs run at the same hardware " +"frequency *\n" +msgstr "" +" -r, --related-cpus Findet heraus, welche CPUs mit derselben " +"physikalischen\n" +" Taktfrequenz laufen *\n" + +#: utils/cpufreq-info.c:484 +#, c-format +msgid "" +" -a, --affected-cpus Determines which CPUs need to have their frequency\n" +" coordinated by software *\n" +msgstr "" +" -a, --affected-cpus Findet heraus, von welchen CPUs die Taktfrequenz " +"durch\n" +" Software koordiniert werden muss *\n" + +#: utils/cpufreq-info.c:486 +#, c-format +msgid " -s, --stats Shows cpufreq statistics if available\n" +msgstr "" +" -s, --stats Zeigt, sofern möglich, Statistiken über cpufreq an.\n" + +#: utils/cpufreq-info.c:487 +#, c-format +msgid "" +" -y, --latency Determines the maximum latency on CPU frequency " +"changes *\n" +msgstr "" +" -y, --latency Findet die maximale Dauer eines Taktfrequenzwechsels " +"heraus *\n" + +#: utils/cpufreq-info.c:488 +#, c-format +msgid " -b, --boost Checks for turbo or boost modes *\n" +msgstr "" + +#: utils/cpufreq-info.c:489 +#, c-format +msgid "" +" -o, --proc Prints out information like provided by the /proc/" +"cpufreq\n" +" interface in 2.4. and early 2.6. kernels\n" +msgstr "" +" -o, --proc Erzeugt Informationen in einem ähnlichem Format zu " +"dem\n" +" der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n" +" Kernel-Versionen\n" + +#: utils/cpufreq-info.c:491 +#, c-format +msgid "" +" -m, --human human-readable output for the -f, -w, -s and -y " +"parameters\n" +msgstr "" +" -m, --human Formatiert Taktfrequenz- und Zeitdauerangaben in " +"besser\n" +" lesbarer Form (MHz, GHz; us, ms)\n" + +#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152 +#, c-format +msgid " -h, --help Prints out this screen\n" +msgstr " -h, --help Gibt diese Kurzübersicht aus\n" + +#: utils/cpufreq-info.c:495 +#, c-format +msgid "" +"If no argument or only the -c, --cpu parameter is given, debug output about\n" +"cpufreq is printed which is useful e.g. for reporting bugs.\n" +msgstr "" +"Sofern kein anderer Parameter als '-c, --cpu' angegeben wird, liefert " +"dieses\n" +"Programm Informationen, die z.B. zum Berichten von Fehlern nützlich sind.\n" + +#: utils/cpufreq-info.c:497 +#, c-format +msgid "" +"For the arguments marked with *, omitting the -c or --cpu argument is\n" +"equivalent to setting it to zero\n" +msgstr "" +"Bei den mit * markierten Parametern wird '--cpu 0' angenommen, soweit nicht\n" +"mittels -c oder --cpu etwas anderes angegeben wird\n" + +#: utils/cpufreq-info.c:580 +#, c-format +msgid "" +"The argument passed to this tool can't be combined with passing a --cpu " +"argument\n" +msgstr "Diese Option kann nicht mit der --cpu-Option kombiniert werden\n" + +#: utils/cpufreq-info.c:596 +#, c-format +msgid "" +"You can't specify more than one --cpu parameter and/or\n" +"more than one output-specific argument\n" +msgstr "" +"Man kann nicht mehr als einen --cpu-Parameter und/oder mehr als einen\n" +"informationsspezifischen Parameter gleichzeitig angeben\n" + +#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42 +#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213 +#, c-format +msgid "invalid or unknown argument\n" +msgstr "unbekannter oder falscher Parameter\n" + +#: utils/cpufreq-info.c:617 +#, c-format +msgid "couldn't analyze CPU %d as it doesn't seem to be present\n" +msgstr "" +"Konnte nicht die CPU %d analysieren, da sie (scheinbar?) nicht existiert.\n" + +#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142 +#, c-format +msgid "analyzing CPU %d:\n" +msgstr "analysiere CPU %d:\n" + +#: utils/cpufreq-set.c:25 +#, fuzzy, c-format +msgid "Usage: cpupower frequency-set [options]\n" +msgstr "Aufruf: cpufreq-set [Optionen]\n" + +#: utils/cpufreq-set.c:27 +#, c-format +msgid "" +" -d FREQ, --min FREQ new minimum CPU frequency the governor may " +"select\n" +msgstr "" +" -d FREQ, --min FREQ neue minimale Taktfrequenz, die der Regler\n" +" auswählen darf\n" + +#: utils/cpufreq-set.c:28 +#, c-format +msgid "" +" -u FREQ, --max FREQ new maximum CPU frequency the governor may " +"select\n" +msgstr "" +" -u FREQ, --max FREQ neue maximale Taktfrequenz, die der Regler\n" +" auswählen darf\n" + +#: utils/cpufreq-set.c:29 +#, c-format +msgid " -g GOV, --governor GOV new cpufreq governor\n" +msgstr " -g GOV, --governors GOV wechsle zu Regler GOV\n" + +#: utils/cpufreq-set.c:30 +#, c-format +msgid "" +" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n" +" governor to be available and loaded\n" +msgstr "" +" -f FREQ, --freq FREQ setze exakte Taktfrequenz. Benötigt den Regler\n" +" 'userspace'.\n" + +#: utils/cpufreq-set.c:32 +#, c-format +msgid " -r, --related Switches all hardware-related CPUs\n" +msgstr "" +" -r, --related Setze Werte für alle CPUs, deren Taktfrequenz\n" +" hardwarebedingt identisch ist.\n" + +#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27 +#, c-format +msgid " -h, --help Prints out this screen\n" +msgstr " -h, --help Gibt diese Kurzübersicht aus\n" + +#: utils/cpufreq-set.c:35 +#, fuzzy, c-format +msgid "" +"Notes:\n" +"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n" +msgstr "" +"Bei den mit * markierten Parametern wird '--cpu 0' angenommen, soweit nicht\n" +"mittels -c oder --cpu etwas anderes angegeben wird\n" + +#: utils/cpufreq-set.c:37 +#, fuzzy, c-format +msgid "" +"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other " +"parameter\n" +" except the -c CPU, --cpu CPU parameter\n" +"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n" +" by postfixing the value with the wanted unit name, without any space\n" +" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n" +msgstr "" +"Hinweise:\n" +"1. Sofern kein -c oder --cpu-Parameter angegeben ist, wird '--cpu 0'\n" +" angenommen\n" +"2. Der Parameter -f bzw. --freq kann mit keinem anderen als dem Parameter\n" +" -c bzw. --cpu kombiniert werden\n" +"3. FREQuenzen können in Hz, kHz (Standard), MHz, GHz oder THz eingegeben\n" +" werden, indem der Wert und unmittelbar anschließend (ohne Leerzeichen!)\n" +" die Einheit angegeben werden. (Bsp: 1GHz )\n" +" (FREQuenz in kHz =^ MHz * 1000 =^ GHz * 1000000).\n" + +#: utils/cpufreq-set.c:57 +#, c-format +msgid "" +"Error setting new values. Common errors:\n" +"- Do you have proper administration rights? (super-user?)\n" +"- Is the governor you requested available and modprobed?\n" +"- Trying to set an invalid policy?\n" +"- Trying to set a specific frequency, but userspace governor is not " +"available,\n" +" for example because of hardware which cannot be set to a specific " +"frequency\n" +" or because the userspace governor isn't loaded?\n" +msgstr "" +"Beim Einstellen ist ein Fehler aufgetreten. Typische Fehlerquellen sind:\n" +"- nicht ausreichende Rechte (Administrator)\n" +"- der Regler ist nicht verfügbar bzw. nicht geladen\n" +"- die angegebene Taktik ist inkorrekt\n" +"- eine spezifische Frequenz wurde angegeben, aber der Regler 'userspace'\n" +" kann entweder hardwarebedingt nicht genutzt werden oder ist nicht geladen\n" + +#: utils/cpufreq-set.c:170 +#, c-format +msgid "wrong, unknown or unhandled CPU?\n" +msgstr "unbekannte oder nicht regelbare CPU\n" + +#: utils/cpufreq-set.c:302 +#, c-format +msgid "" +"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n" +"-g/--governor parameters\n" +msgstr "" +"Der -f bzw. --freq-Parameter kann nicht mit den Parametern -d/--min, -u/--" +"max\n" +"oder -g/--governor kombiniert werden\n" + +#: utils/cpufreq-set.c:308 +#, c-format +msgid "" +"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n" +"-g/--governor must be passed\n" +msgstr "" +"Es muss mindestens ein Parameter aus -f/--freq, -d/--min, -u/--max oder\n" +"-g/--governor angegeben werden.\n" + +#: utils/cpufreq-set.c:347 +#, c-format +msgid "Setting cpu: %d\n" +msgstr "" + +#: utils/cpupower-set.c:22 +#, c-format +msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n" +msgstr "" + +#: utils/cpupower-set.c:24 +#, c-format +msgid "" +" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n" +" Intel models [0-15], see manpage for details\n" +msgstr "" + +#: utils/cpupower-set.c:26 +#, c-format +msgid "" +" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n" +msgstr "" + +#: utils/cpupower-set.c:27 +#, c-format +msgid "" +" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler " +"policy.\n" +msgstr "" + +#: utils/cpupower-set.c:80 +#, c-format +msgid "--perf-bias param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:91 +#, c-format +msgid "--sched-mc param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:102 +#, c-format +msgid "--sched-smt param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:121 +#, c-format +msgid "Error setting sched-mc %s\n" +msgstr "" + +#: utils/cpupower-set.c:127 +#, c-format +msgid "Error setting sched-smt %s\n" +msgstr "" + +#: utils/cpupower-set.c:146 +#, c-format +msgid "Error setting perf-bias value on CPU %d\n" +msgstr "" + +#: utils/cpupower-info.c:21 +#, c-format +msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n" +msgstr "" + +#: utils/cpupower-info.c:23 +#, c-format +msgid "" +" -b, --perf-bias Gets CPU's power vs performance policy on some\n" +" Intel models [0-15], see manpage for details\n" +msgstr "" + +#: utils/cpupower-info.c:25 +#, fuzzy, c-format +msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n" +msgstr " -p, --policy Findet die momentane Taktik heraus *\n" + +#: utils/cpupower-info.c:26 +#, c-format +msgid "" +" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n" +msgstr "" + +#: utils/cpupower-info.c:28 +#, c-format +msgid "" +"\n" +"Passing no option will show all info, by default only on core 0\n" +msgstr "" + +#: utils/cpupower-info.c:102 +#, c-format +msgid "System's multi core scheduler setting: " +msgstr "" + +#. if sysfs file is missing it's: errno == ENOENT +#: utils/cpupower-info.c:105 utils/cpupower-info.c:114 +#, c-format +msgid "not supported\n" +msgstr "" + +#: utils/cpupower-info.c:111 +#, c-format +msgid "System's thread sibling scheduler setting: " +msgstr "" + +#: utils/cpupower-info.c:126 +#, c-format +msgid "Intel's performance bias setting needs root privileges\n" +msgstr "" + +#: utils/cpupower-info.c:128 +#, c-format +msgid "System does not support Intel's performance bias setting\n" +msgstr "" + +#: utils/cpupower-info.c:147 +#, c-format +msgid "Could not read perf-bias value\n" +msgstr "" + +#: utils/cpupower-info.c:150 +#, c-format +msgid "perf-bias: %d\n" +msgstr "" + +#: utils/cpuidle-info.c:28 +#, fuzzy, c-format +msgid "Analyzing CPU %d:\n" +msgstr "analysiere CPU %d:\n" + +#: utils/cpuidle-info.c:32 +#, c-format +msgid "CPU %u: No idle states\n" +msgstr "" + +#: utils/cpuidle-info.c:36 +#, c-format +msgid "CPU %u: Can't read idle state info\n" +msgstr "" + +#: utils/cpuidle-info.c:41 +#, c-format +msgid "Could not determine max idle state %u\n" +msgstr "" + +#: utils/cpuidle-info.c:46 +#, c-format +msgid "Number of idle states: %d\n" +msgstr "" + +#: utils/cpuidle-info.c:48 +#, fuzzy, c-format +msgid "Available idle states:" +msgstr " mögliche Taktfrequenzen: " + +#: utils/cpuidle-info.c:71 +#, c-format +msgid "Flags/Description: %s\n" +msgstr "" + +#: utils/cpuidle-info.c:74 +#, c-format +msgid "Latency: %lu\n" +msgstr "" + +#: utils/cpuidle-info.c:76 +#, c-format +msgid "Usage: %lu\n" +msgstr "" + +#: utils/cpuidle-info.c:78 +#, c-format +msgid "Duration: %llu\n" +msgstr "" + +#: utils/cpuidle-info.c:90 +#, c-format +msgid "Could not determine cpuidle driver\n" +msgstr "" + +#: utils/cpuidle-info.c:94 +#, fuzzy, c-format +msgid "CPUidle driver: %s\n" +msgstr " Treiber: %s\n" + +#: utils/cpuidle-info.c:99 +#, c-format +msgid "Could not determine cpuidle governor\n" +msgstr "" + +#: utils/cpuidle-info.c:103 +#, c-format +msgid "CPUidle governor: %s\n" +msgstr "" + +#: utils/cpuidle-info.c:122 +#, c-format +msgid "CPU %u: Can't read C-state info\n" +msgstr "" + +#. printf("Cstates: %d\n", cstates); +#: utils/cpuidle-info.c:127 +#, c-format +msgid "active state: C0\n" +msgstr "" + +#: utils/cpuidle-info.c:128 +#, c-format +msgid "max_cstate: C%u\n" +msgstr "" + +#: utils/cpuidle-info.c:129 +#, fuzzy, c-format +msgid "maximum allowed latency: %lu usec\n" +msgstr " Maximale Dauer eines Taktfrequenzwechsels: " + +#: utils/cpuidle-info.c:130 +#, c-format +msgid "states:\t\n" +msgstr "" + +#: utils/cpuidle-info.c:132 +#, c-format +msgid " C%d: type[C%d] " +msgstr "" + +#: utils/cpuidle-info.c:134 +#, c-format +msgid "promotion[--] demotion[--] " +msgstr "" + +#: utils/cpuidle-info.c:135 +#, c-format +msgid "latency[%03lu] " +msgstr "" + +#: utils/cpuidle-info.c:137 +#, c-format +msgid "usage[%08lu] " +msgstr "" + +#: utils/cpuidle-info.c:139 +#, c-format +msgid "duration[%020Lu] \n" +msgstr "" + +#: utils/cpuidle-info.c:147 +#, fuzzy, c-format +msgid "Usage: cpupower idleinfo [options]\n" +msgstr "Aufruf: cpufreq-info [Optionen]\n" + +#: utils/cpuidle-info.c:149 +#, fuzzy, c-format +msgid " -s, --silent Only show general C-state information\n" +msgstr "" +" -e, --debug Erzeugt detaillierte Informationen, hilfreich\n" +" zum Aufspüren von Fehlern\n" + +#: utils/cpuidle-info.c:150 +#, fuzzy, c-format +msgid "" +" -o, --proc Prints out information like provided by the /proc/" +"acpi/processor/*/power\n" +" interface in older kernels\n" +msgstr "" +" -o, --proc Erzeugt Informationen in einem ähnlichem Format zu " +"dem\n" +" der /proc/cpufreq-Datei in 2.4. und frühen 2.6.\n" +" Kernel-Versionen\n" + +#: utils/cpuidle-info.c:209 +#, fuzzy, c-format +msgid "You can't specify more than one output-specific argument\n" +msgstr "" +"Man kann nicht mehr als einen --cpu-Parameter und/oder mehr als einen\n" +"informationsspezifischen Parameter gleichzeitig angeben\n" + +#~ msgid "" +#~ " -c CPU, --cpu CPU CPU number which information shall be determined " +#~ "about\n" +#~ msgstr "" +#~ " -c CPU, --cpu CPU Nummer der CPU, über die Informationen " +#~ "herausgefunden werden sollen\n" + +#~ msgid "" +#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be " +#~ "modified\n" +#~ msgstr "" +#~ " -c CPU, --cpu CPU Nummer der CPU, deren Taktfrequenz-" +#~ "Einstellung\n" +#~ " 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 @@ +# French translations for cpufrequtils package +# Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the cpufrequtils package. +# Ducrot Bruno , 2004. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: cpufrequtils 0.1-pre2\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-03-08 17:03+0100\n" +"PO-Revision-Date: 2004-11-17 15:53+1000\n" +"Last-Translator: Bruno Ducrot \n" +"Language-Team: NONE\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: utils/idle_monitor/nhm_idle.c:36 +msgid "Processor Core C3" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:43 +msgid "Processor Core C6" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:51 +msgid "Processor Package C3" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70 +msgid "Processor Package C6" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:33 +msgid "Processor Core C7" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:40 +msgid "Processor Package C2" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:47 +msgid "Processor Package C7" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:56 +msgid "Package in sleep state (PC1 or deeper)" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:63 +msgid "Processor Package C1" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:77 +msgid "North Bridge P1 boolean counter (returns 0 or 1)" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:35 +msgid "Processor Core not idle" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:42 +msgid "Processor Core in an idle state" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:50 +msgid "Average Frequency (including boost) in MHz" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:66 +#, c-format +msgid "" +"cpupower monitor: [-h] [ [-t] | [-l] | [-m ,[] ] ] [-i " +"interval_sec | -c command ...]\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:69 +#, c-format +msgid "" +"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m ,[] ] ] [-i " +"interval_sec | -c command ...]\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:71 +#, c-format +msgid "\t -v: be more verbose\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:73 +#, c-format +msgid "\t -h: print this help\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:74 +#, c-format +msgid "\t -i: time intervall to measure for in seconds (default 1)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:75 +#, c-format +msgid "\t -t: show CPU topology/hierarchy\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:76 +#, c-format +msgid "\t -l: list available CPU sleep monitors (for use with -m)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:77 +#, c-format +msgid "\t -m: show specific CPU sleep monitors only (in same order)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:79 +#, c-format +msgid "" +"only one of: -t, -l, -m are allowed\n" +"If none of them is passed," +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:80 +#, c-format +msgid " all supported monitors are shown\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:197 +#, c-format +msgid "Monitor %s, Counter %s has no count function. Implementation error\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:207 +#, c-format +msgid " *is offline\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:236 +#, c-format +msgid "%s: max monitor name length (%d) exceeded\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:250 +#, c-format +msgid "No matching monitor found in %s, try -l option\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:266 +#, c-format +msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:319 +#, c-format +msgid "%s took %.5f seconds and exited with status %d\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:406 +#, c-format +msgid "Cannot read number of available processors\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:417 +#, c-format +msgid "Available monitor %s needs root access\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:428 +#, c-format +msgid "No HW Cstate monitors found\n" +msgstr "" + +#: utils/cpupower.c:78 +#, c-format +msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n" +msgstr "" + +#: utils/cpupower.c:79 +#, c-format +msgid "cpupower --version\n" +msgstr "" + +#: utils/cpupower.c:80 +#, c-format +msgid "Supported subcommands are:\n" +msgstr "" + +#: utils/cpupower.c:83 +#, c-format +msgid "" +"\n" +"Some subcommands can make use of the -c cpulist option.\n" +msgstr "" + +#: utils/cpupower.c:84 +#, c-format +msgid "Look at the general cpupower manpage how to use it\n" +msgstr "" + +#: utils/cpupower.c:85 +#, c-format +msgid "and read up the subcommand's manpage whether it is supported.\n" +msgstr "" + +#: utils/cpupower.c:86 +#, c-format +msgid "" +"\n" +"Use cpupower help subcommand for getting help for above subcommands.\n" +msgstr "" + +#: utils/cpupower.c:91 +#, c-format +msgid "Report errors and bugs to %s, please.\n" +msgstr "Veuillez rapportez les erreurs et les bogues à %s, s'il vous plait.\n" + +#: utils/cpupower.c:114 +#, c-format +msgid "Error parsing cpu list\n" +msgstr "" + +#: utils/cpupower.c:172 +#, c-format +msgid "Subcommand %s needs root privileges\n" +msgstr "" + +#: utils/cpufreq-info.c:31 +#, c-format +msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n" +msgstr "Détermination du nombre de CPUs (%s : %s) impossible. Assume 1\n" + +#: utils/cpufreq-info.c:63 +#, c-format +msgid "" +" minimum CPU frequency - maximum CPU frequency - governor\n" +msgstr "" +" Fréquence CPU minimale - Fréquence CPU maximale - régulateur\n" + +#: utils/cpufreq-info.c:151 +#, c-format +msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n" +msgstr "" + +#. P state changes via MSR are identified via cpuid 80000007 +#. on Intel and AMD, but we assume boost capable machines can do that +#. if (cpuid_eax(0x80000000) >= 0x80000007 +#. && (cpuid_edx(0x80000007) & (1 << 7))) +#. +#: utils/cpufreq-info.c:161 +#, c-format +msgid " boost state support: \n" +msgstr "" + +#: utils/cpufreq-info.c:163 +#, c-format +msgid " Supported: %s\n" +msgstr "" + +#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 +msgid "yes" +msgstr "" + +#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 +msgid "no" +msgstr "" + +#: utils/cpufreq-info.c:164 +#, fuzzy, c-format +msgid " Active: %s\n" +msgstr " pilote : %s\n" + +#: utils/cpufreq-info.c:177 +#, c-format +msgid " Boost States: %d\n" +msgstr "" + +#: utils/cpufreq-info.c:178 +#, c-format +msgid " Total States: %d\n" +msgstr "" + +#: utils/cpufreq-info.c:181 +#, c-format +msgid " Pstate-Pb%d: %luMHz (boost state)\n" +msgstr "" + +#: utils/cpufreq-info.c:184 +#, c-format +msgid " Pstate-P%d: %luMHz\n" +msgstr "" + +#: utils/cpufreq-info.c:211 +#, c-format +msgid " no or unknown cpufreq driver is active on this CPU\n" +msgstr " pas de pilotes cpufreq reconnu pour ce CPU\n" + +#: utils/cpufreq-info.c:213 +#, c-format +msgid " driver: %s\n" +msgstr " pilote : %s\n" + +#: utils/cpufreq-info.c:219 +#, fuzzy, c-format +msgid " CPUs which run at the same hardware frequency: " +msgstr " CPUs qui doivent changer de fréquences en même temps : " + +#: utils/cpufreq-info.c:230 +#, fuzzy, c-format +msgid " CPUs which need to have their frequency coordinated by software: " +msgstr " CPUs qui doivent changer de fréquences en même temps : " + +#: utils/cpufreq-info.c:241 +#, c-format +msgid " maximum transition latency: " +msgstr "" + +#: utils/cpufreq-info.c:247 +#, c-format +msgid " hardware limits: " +msgstr " limitation matérielle : " + +#: utils/cpufreq-info.c:256 +#, c-format +msgid " available frequency steps: " +msgstr " plage de fréquence : " + +#: utils/cpufreq-info.c:269 +#, c-format +msgid " available cpufreq governors: " +msgstr " régulateurs disponibles : " + +#: utils/cpufreq-info.c:280 +#, c-format +msgid " current policy: frequency should be within " +msgstr " tactique actuelle : la fréquence doit être comprise entre " + +#: utils/cpufreq-info.c:282 +#, c-format +msgid " and " +msgstr " et " + +#: utils/cpufreq-info.c:286 +#, c-format +msgid "" +"The governor \"%s\" may decide which speed to use\n" +" within this range.\n" +msgstr "" +"Le régulateur \"%s\" est libre de choisir la vitesse\n" +" dans cette plage de fréquences.\n" + +#: utils/cpufreq-info.c:293 +#, c-format +msgid " current CPU frequency is " +msgstr " la fréquence actuelle de ce CPU est " + +#: utils/cpufreq-info.c:296 +#, c-format +msgid " (asserted by call to hardware)" +msgstr " (vérifié par un appel direct du matériel)" + +#: utils/cpufreq-info.c:304 +#, c-format +msgid " cpufreq stats: " +msgstr " des statistique concernant cpufreq:" + +#: utils/cpufreq-info.c:472 +#, fuzzy, c-format +msgid "Usage: cpupower freqinfo [options]\n" +msgstr "Usage : cpufreq-info [options]\n" + +#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23 +#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148 +#, c-format +msgid "Options:\n" +msgstr "Options :\n" + +#: utils/cpufreq-info.c:474 +#, fuzzy, c-format +msgid " -e, --debug Prints out debug information [default]\n" +msgstr " -e, --debug Afficher les informations de déboguage\n" + +#: utils/cpufreq-info.c:475 +#, c-format +msgid "" +" -f, --freq Get frequency the CPU currently runs at, according\n" +" to the cpufreq core *\n" +msgstr "" +" -f, --freq Obtenir la fréquence actuelle du CPU selon le point\n" +" de vue du coeur du système de cpufreq *\n" + +#: utils/cpufreq-info.c:477 +#, c-format +msgid "" +" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n" +" it from hardware (only available to root) *\n" +msgstr "" +" -w, --hwfreq Obtenir la fréquence actuelle du CPU directement par\n" +" le matériel (doit être root) *\n" + +#: utils/cpufreq-info.c:479 +#, c-format +msgid "" +" -l, --hwlimits Determine the minimum and maximum CPU frequency " +"allowed *\n" +msgstr "" +" -l, --hwlimits Affiche les fréquences minimales et maximales du CPU " +"*\n" + +#: utils/cpufreq-info.c:480 +#, c-format +msgid " -d, --driver Determines the used cpufreq kernel driver *\n" +msgstr " -d, --driver Affiche le pilote cpufreq utilisé *\n" + +#: utils/cpufreq-info.c:481 +#, c-format +msgid " -p, --policy Gets the currently used cpufreq policy *\n" +msgstr " -p, --policy Affiche la tactique actuelle de cpufreq *\n" + +#: utils/cpufreq-info.c:482 +#, c-format +msgid " -g, --governors Determines available cpufreq governors *\n" +msgstr "" +" -g, --governors Affiche les régulateurs disponibles de cpufreq *\n" + +#: utils/cpufreq-info.c:483 +#, fuzzy, c-format +msgid "" +" -r, --related-cpus Determines which CPUs run at the same hardware " +"frequency *\n" +msgstr "" +" -a, --affected-cpus Affiche quels sont les CPUs qui doivent changer de\n" +" fréquences en même temps *\n" + +#: utils/cpufreq-info.c:484 +#, fuzzy, c-format +msgid "" +" -a, --affected-cpus Determines which CPUs need to have their frequency\n" +" coordinated by software *\n" +msgstr "" +" -a, --affected-cpus Affiche quels sont les CPUs qui doivent changer de\n" +" fréquences en même temps *\n" + +#: utils/cpufreq-info.c:486 +#, c-format +msgid " -s, --stats Shows cpufreq statistics if available\n" +msgstr "" +" -s, --stats Indique des statistiques concernant cpufreq, si\n" +" disponibles\n" + +#: utils/cpufreq-info.c:487 +#, fuzzy, c-format +msgid "" +" -y, --latency Determines the maximum latency on CPU frequency " +"changes *\n" +msgstr "" +" -l, --hwlimits Affiche les fréquences minimales et maximales du CPU " +"*\n" + +#: utils/cpufreq-info.c:488 +#, c-format +msgid " -b, --boost Checks for turbo or boost modes *\n" +msgstr "" + +#: utils/cpufreq-info.c:489 +#, c-format +msgid "" +" -o, --proc Prints out information like provided by the /proc/" +"cpufreq\n" +" interface in 2.4. and early 2.6. kernels\n" +msgstr "" +" -o, --proc Affiche les informations en utilisant l'interface\n" +" fournie par /proc/cpufreq, présente dans les " +"versions\n" +" 2.4 et les anciennes versions 2.6 du noyau\n" + +#: utils/cpufreq-info.c:491 +#, fuzzy, c-format +msgid "" +" -m, --human human-readable output for the -f, -w, -s and -y " +"parameters\n" +msgstr "" +" -m, --human affiche dans un format lisible pour un humain\n" +" pour les options -f, -w et -s (MHz, GHz)\n" + +#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152 +#, c-format +msgid " -h, --help Prints out this screen\n" +msgstr " -h, --help affiche l'aide-mémoire\n" + +#: utils/cpufreq-info.c:495 +#, c-format +msgid "" +"If no argument or only the -c, --cpu parameter is given, debug output about\n" +"cpufreq is printed which is useful e.g. for reporting bugs.\n" +msgstr "" +"Par défaut, les informations de déboguage seront affichées si aucun\n" +"argument, ou bien si seulement l'argument -c (--cpu) est donné, afin de\n" +"faciliter les rapports de bogues par exemple\n" + +#: utils/cpufreq-info.c:497 +#, c-format +msgid "" +"For the arguments marked with *, omitting the -c or --cpu argument is\n" +"equivalent to setting it to zero\n" +msgstr "Les arguments avec un * utiliseront le CPU 0 si -c (--cpu) est omis\n" + +#: utils/cpufreq-info.c:580 +#, c-format +msgid "" +"The argument passed to this tool can't be combined with passing a --cpu " +"argument\n" +msgstr "Cette option est incompatible avec --cpu\n" + +#: utils/cpufreq-info.c:596 +#, c-format +msgid "" +"You can't specify more than one --cpu parameter and/or\n" +"more than one output-specific argument\n" +msgstr "" +"On ne peut indiquer plus d'un paramètre --cpu, tout comme l'on ne peut\n" +"spécifier plus d'un argument de formatage\n" + +#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42 +#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213 +#, c-format +msgid "invalid or unknown argument\n" +msgstr "option invalide\n" + +#: utils/cpufreq-info.c:617 +#, c-format +msgid "couldn't analyze CPU %d as it doesn't seem to be present\n" +msgstr "analyse du CPU %d impossible puisqu'il ne semble pas être présent\n" + +#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142 +#, c-format +msgid "analyzing CPU %d:\n" +msgstr "analyse du CPU %d :\n" + +#: utils/cpufreq-set.c:25 +#, fuzzy, c-format +msgid "Usage: cpupower frequency-set [options]\n" +msgstr "Usage : cpufreq-set [options]\n" + +#: utils/cpufreq-set.c:27 +#, c-format +msgid "" +" -d FREQ, --min FREQ new minimum CPU frequency the governor may " +"select\n" +msgstr "" +" -d FREQ, --min FREQ nouvelle fréquence minimale du CPU à utiliser\n" +" par le régulateur\n" + +#: utils/cpufreq-set.c:28 +#, c-format +msgid "" +" -u FREQ, --max FREQ new maximum CPU frequency the governor may " +"select\n" +msgstr "" +" -u FREQ, --max FREQ nouvelle fréquence maximale du CPU à utiliser\n" +" par le régulateur\n" + +#: utils/cpufreq-set.c:29 +#, c-format +msgid " -g GOV, --governor GOV new cpufreq governor\n" +msgstr " -g GOV, --governor GOV active le régulateur GOV\n" + +#: utils/cpufreq-set.c:30 +#, c-format +msgid "" +" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n" +" governor to be available and loaded\n" +msgstr "" +" -f FREQ, --freq FREQ fixe la fréquence du processeur à FREQ. Il faut\n" +" que le régulateur « userspace » soit disponible \n" +" et activé.\n" + +#: utils/cpufreq-set.c:32 +#, c-format +msgid " -r, --related Switches all hardware-related CPUs\n" +msgstr "" + +#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27 +#, fuzzy, c-format +msgid " -h, --help Prints out this screen\n" +msgstr " -h, --help affiche l'aide-mémoire\n" + +#: utils/cpufreq-set.c:35 +#, fuzzy, c-format +msgid "" +"Notes:\n" +"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n" +msgstr "Les arguments avec un * utiliseront le CPU 0 si -c (--cpu) est omis\n" + +#: utils/cpufreq-set.c:37 +#, fuzzy, c-format +msgid "" +"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other " +"parameter\n" +" except the -c CPU, --cpu CPU parameter\n" +"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n" +" by postfixing the value with the wanted unit name, without any space\n" +" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n" +msgstr "" +"Remarque :\n" +"1. Le CPU numéro 0 sera utilisé par défaut si -c (ou --cpu) est omis ;\n" +"2. l'argument -f FREQ (ou --freq FREQ) ne peut être utilisé qu'avec --cpu ;\n" +"3. on pourra préciser l'unité des fréquences en postfixant sans aucune " +"espace\n" +" les valeurs par hz, kHz (par défaut), MHz, GHz ou THz\n" +" (kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n" + +#: utils/cpufreq-set.c:57 +#, c-format +msgid "" +"Error setting new values. Common errors:\n" +"- Do you have proper administration rights? (super-user?)\n" +"- Is the governor you requested available and modprobed?\n" +"- Trying to set an invalid policy?\n" +"- Trying to set a specific frequency, but userspace governor is not " +"available,\n" +" for example because of hardware which cannot be set to a specific " +"frequency\n" +" or because the userspace governor isn't loaded?\n" +msgstr "" +"En ajustant les nouveaux paramètres, une erreur est apparue. Les sources\n" +"d'erreur typique sont :\n" +"- droit d'administration insuffisant (êtes-vous root ?) ;\n" +"- le régulateur choisi n'est pas disponible, ou bien n'est pas disponible " +"en\n" +" tant que module noyau ;\n" +"- la tactique n'est pas disponible ;\n" +"- vous voulez utiliser l'option -f/--freq, mais le régulateur « userspace »\n" +" n'est pas disponible, par exemple parce que le matériel ne le supporte\n" +" pas, ou bien n'est tout simplement pas chargé.\n" + +#: utils/cpufreq-set.c:170 +#, c-format +msgid "wrong, unknown or unhandled CPU?\n" +msgstr "CPU inconnu ou non supporté ?\n" + +#: utils/cpufreq-set.c:302 +#, c-format +msgid "" +"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n" +"-g/--governor parameters\n" +msgstr "" +"l'option -f/--freq est incompatible avec les options -d/--min, -u/--max et\n" +"-g/--governor\n" + +#: utils/cpufreq-set.c:308 +#, c-format +msgid "" +"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n" +"-g/--governor must be passed\n" +msgstr "" +"L'un de ces paramètres est obligatoire : -f/--freq, -d/--min, -u/--max et\n" +"-g/--governor\n" + +#: utils/cpufreq-set.c:347 +#, c-format +msgid "Setting cpu: %d\n" +msgstr "" + +#: utils/cpupower-set.c:22 +#, c-format +msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n" +msgstr "" + +#: utils/cpupower-set.c:24 +#, c-format +msgid "" +" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n" +" Intel models [0-15], see manpage for details\n" +msgstr "" + +#: utils/cpupower-set.c:26 +#, c-format +msgid "" +" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n" +msgstr "" + +#: utils/cpupower-set.c:27 +#, c-format +msgid "" +" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler " +"policy.\n" +msgstr "" + +#: utils/cpupower-set.c:80 +#, c-format +msgid "--perf-bias param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:91 +#, c-format +msgid "--sched-mc param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:102 +#, c-format +msgid "--sched-smt param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:121 +#, c-format +msgid "Error setting sched-mc %s\n" +msgstr "" + +#: utils/cpupower-set.c:127 +#, c-format +msgid "Error setting sched-smt %s\n" +msgstr "" + +#: utils/cpupower-set.c:146 +#, c-format +msgid "Error setting perf-bias value on CPU %d\n" +msgstr "" + +#: utils/cpupower-info.c:21 +#, c-format +msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n" +msgstr "" + +#: utils/cpupower-info.c:23 +#, c-format +msgid "" +" -b, --perf-bias Gets CPU's power vs performance policy on some\n" +" Intel models [0-15], see manpage for details\n" +msgstr "" + +#: utils/cpupower-info.c:25 +#, fuzzy, c-format +msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n" +msgstr " -p, --policy Affiche la tactique actuelle de cpufreq *\n" + +#: utils/cpupower-info.c:26 +#, c-format +msgid "" +" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n" +msgstr "" + +#: utils/cpupower-info.c:28 +#, c-format +msgid "" +"\n" +"Passing no option will show all info, by default only on core 0\n" +msgstr "" + +#: utils/cpupower-info.c:102 +#, c-format +msgid "System's multi core scheduler setting: " +msgstr "" + +#. if sysfs file is missing it's: errno == ENOENT +#: utils/cpupower-info.c:105 utils/cpupower-info.c:114 +#, c-format +msgid "not supported\n" +msgstr "" + +#: utils/cpupower-info.c:111 +#, c-format +msgid "System's thread sibling scheduler setting: " +msgstr "" + +#: utils/cpupower-info.c:126 +#, c-format +msgid "Intel's performance bias setting needs root privileges\n" +msgstr "" + +#: utils/cpupower-info.c:128 +#, c-format +msgid "System does not support Intel's performance bias setting\n" +msgstr "" + +#: utils/cpupower-info.c:147 +#, c-format +msgid "Could not read perf-bias value\n" +msgstr "" + +#: utils/cpupower-info.c:150 +#, c-format +msgid "perf-bias: %d\n" +msgstr "" + +#: utils/cpuidle-info.c:28 +#, fuzzy, c-format +msgid "Analyzing CPU %d:\n" +msgstr "analyse du CPU %d :\n" + +#: utils/cpuidle-info.c:32 +#, c-format +msgid "CPU %u: No idle states\n" +msgstr "" + +#: utils/cpuidle-info.c:36 +#, c-format +msgid "CPU %u: Can't read idle state info\n" +msgstr "" + +#: utils/cpuidle-info.c:41 +#, c-format +msgid "Could not determine max idle state %u\n" +msgstr "" + +#: utils/cpuidle-info.c:46 +#, c-format +msgid "Number of idle states: %d\n" +msgstr "" + +#: utils/cpuidle-info.c:48 +#, fuzzy, c-format +msgid "Available idle states:" +msgstr " plage de fréquence : " + +#: utils/cpuidle-info.c:71 +#, c-format +msgid "Flags/Description: %s\n" +msgstr "" + +#: utils/cpuidle-info.c:74 +#, c-format +msgid "Latency: %lu\n" +msgstr "" + +#: utils/cpuidle-info.c:76 +#, c-format +msgid "Usage: %lu\n" +msgstr "" + +#: utils/cpuidle-info.c:78 +#, c-format +msgid "Duration: %llu\n" +msgstr "" + +#: utils/cpuidle-info.c:90 +#, c-format +msgid "Could not determine cpuidle driver\n" +msgstr "" + +#: utils/cpuidle-info.c:94 +#, fuzzy, c-format +msgid "CPUidle driver: %s\n" +msgstr " pilote : %s\n" + +#: utils/cpuidle-info.c:99 +#, c-format +msgid "Could not determine cpuidle governor\n" +msgstr "" + +#: utils/cpuidle-info.c:103 +#, c-format +msgid "CPUidle governor: %s\n" +msgstr "" + +#: utils/cpuidle-info.c:122 +#, c-format +msgid "CPU %u: Can't read C-state info\n" +msgstr "" + +#. printf("Cstates: %d\n", cstates); +#: utils/cpuidle-info.c:127 +#, c-format +msgid "active state: C0\n" +msgstr "" + +#: utils/cpuidle-info.c:128 +#, c-format +msgid "max_cstate: C%u\n" +msgstr "" + +#: utils/cpuidle-info.c:129 +#, c-format +msgid "maximum allowed latency: %lu usec\n" +msgstr "" + +#: utils/cpuidle-info.c:130 +#, c-format +msgid "states:\t\n" +msgstr "" + +#: utils/cpuidle-info.c:132 +#, c-format +msgid " C%d: type[C%d] " +msgstr "" + +#: utils/cpuidle-info.c:134 +#, c-format +msgid "promotion[--] demotion[--] " +msgstr "" + +#: utils/cpuidle-info.c:135 +#, c-format +msgid "latency[%03lu] " +msgstr "" + +#: utils/cpuidle-info.c:137 +#, c-format +msgid "usage[%08lu] " +msgstr "" + +#: utils/cpuidle-info.c:139 +#, c-format +msgid "duration[%020Lu] \n" +msgstr "" + +#: utils/cpuidle-info.c:147 +#, fuzzy, c-format +msgid "Usage: cpupower idleinfo [options]\n" +msgstr "Usage : cpufreq-info [options]\n" + +#: utils/cpuidle-info.c:149 +#, fuzzy, c-format +msgid " -s, --silent Only show general C-state information\n" +msgstr " -e, --debug Afficher les informations de déboguage\n" + +#: utils/cpuidle-info.c:150 +#, fuzzy, c-format +msgid "" +" -o, --proc Prints out information like provided by the /proc/" +"acpi/processor/*/power\n" +" interface in older kernels\n" +msgstr "" +" -o, --proc Affiche les informations en utilisant l'interface\n" +" fournie par /proc/cpufreq, présente dans les " +"versions\n" +" 2.4 et les anciennes versions 2.6 du noyau\n" + +#: utils/cpuidle-info.c:209 +#, fuzzy, c-format +msgid "You can't specify more than one output-specific argument\n" +msgstr "" +"On ne peut indiquer plus d'un paramètre --cpu, tout comme l'on ne peut\n" +"spécifier plus d'un argument de formatage\n" + +#~ msgid "" +#~ " -c CPU, --cpu CPU CPU number which information shall be determined " +#~ "about\n" +#~ msgstr "" +#~ " -c CPU, --cpu CPU Numéro du CPU pour lequel l'information sera " +#~ "affichée\n" + +#~ msgid "" +#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be " +#~ "modified\n" +#~ msgstr "" +#~ " -c CPU, --cpu CPU numéro du CPU à prendre en compte pour les\n" +#~ " 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 @@ +# Italian translations for cpufrequtils package +# Copyright (C) 2004-2009 +# This file is distributed under the same license as the cpufrequtils package. +# Mattia Dongili . +# +# +msgid "" +msgstr "" +"Project-Id-Version: cpufrequtils 0.3\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-03-08 17:03+0100\n" +"PO-Revision-Date: 2009-08-15 12:00+0900\n" +"Last-Translator: Mattia Dongili \n" +"Language-Team: NONE\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: utils/idle_monitor/nhm_idle.c:36 +msgid "Processor Core C3" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:43 +msgid "Processor Core C6" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:51 +msgid "Processor Package C3" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70 +msgid "Processor Package C6" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:33 +msgid "Processor Core C7" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:40 +msgid "Processor Package C2" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:47 +msgid "Processor Package C7" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:56 +msgid "Package in sleep state (PC1 or deeper)" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:63 +msgid "Processor Package C1" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:77 +msgid "North Bridge P1 boolean counter (returns 0 or 1)" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:35 +msgid "Processor Core not idle" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:42 +msgid "Processor Core in an idle state" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:50 +msgid "Average Frequency (including boost) in MHz" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:66 +#, c-format +msgid "" +"cpupower monitor: [-h] [ [-t] | [-l] | [-m ,[] ] ] [-i " +"interval_sec | -c command ...]\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:69 +#, c-format +msgid "" +"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m ,[] ] ] [-i " +"interval_sec | -c command ...]\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:71 +#, c-format +msgid "\t -v: be more verbose\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:73 +#, c-format +msgid "\t -h: print this help\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:74 +#, c-format +msgid "\t -i: time intervall to measure for in seconds (default 1)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:75 +#, c-format +msgid "\t -t: show CPU topology/hierarchy\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:76 +#, c-format +msgid "\t -l: list available CPU sleep monitors (for use with -m)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:77 +#, c-format +msgid "\t -m: show specific CPU sleep monitors only (in same order)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:79 +#, c-format +msgid "" +"only one of: -t, -l, -m are allowed\n" +"If none of them is passed," +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:80 +#, c-format +msgid " all supported monitors are shown\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:197 +#, c-format +msgid "Monitor %s, Counter %s has no count function. Implementation error\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:207 +#, c-format +msgid " *is offline\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:236 +#, c-format +msgid "%s: max monitor name length (%d) exceeded\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:250 +#, c-format +msgid "No matching monitor found in %s, try -l option\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:266 +#, c-format +msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:319 +#, c-format +msgid "%s took %.5f seconds and exited with status %d\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:406 +#, c-format +msgid "Cannot read number of available processors\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:417 +#, c-format +msgid "Available monitor %s needs root access\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:428 +#, c-format +msgid "No HW Cstate monitors found\n" +msgstr "" + +#: utils/cpupower.c:78 +#, c-format +msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n" +msgstr "" + +#: utils/cpupower.c:79 +#, c-format +msgid "cpupower --version\n" +msgstr "" + +#: utils/cpupower.c:80 +#, c-format +msgid "Supported subcommands are:\n" +msgstr "" + +#: utils/cpupower.c:83 +#, c-format +msgid "" +"\n" +"Some subcommands can make use of the -c cpulist option.\n" +msgstr "" + +#: utils/cpupower.c:84 +#, c-format +msgid "Look at the general cpupower manpage how to use it\n" +msgstr "" + +#: utils/cpupower.c:85 +#, c-format +msgid "and read up the subcommand's manpage whether it is supported.\n" +msgstr "" + +#: utils/cpupower.c:86 +#, c-format +msgid "" +"\n" +"Use cpupower help subcommand for getting help for above subcommands.\n" +msgstr "" + +#: utils/cpupower.c:91 +#, c-format +msgid "Report errors and bugs to %s, please.\n" +msgstr "Per favore, comunicare errori e malfunzionamenti a %s.\n" + +#: utils/cpupower.c:114 +#, c-format +msgid "Error parsing cpu list\n" +msgstr "" + +#: utils/cpupower.c:172 +#, c-format +msgid "Subcommand %s needs root privileges\n" +msgstr "" + +#: utils/cpufreq-info.c:31 +#, c-format +msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n" +msgstr "Impossibile determinare il numero di CPU (%s: %s), assumo sia 1\n" + +#: utils/cpufreq-info.c:63 +#, c-format +msgid "" +" minimum CPU frequency - maximum CPU frequency - governor\n" +msgstr "" +" frequenza minima CPU - frequenza massima CPU - gestore\n" + +#: utils/cpufreq-info.c:151 +#, c-format +msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n" +msgstr "" + +#. P state changes via MSR are identified via cpuid 80000007 +#. on Intel and AMD, but we assume boost capable machines can do that +#. if (cpuid_eax(0x80000000) >= 0x80000007 +#. && (cpuid_edx(0x80000007) & (1 << 7))) +#. +#: utils/cpufreq-info.c:161 +#, c-format +msgid " boost state support: \n" +msgstr "" + +#: utils/cpufreq-info.c:163 +#, c-format +msgid " Supported: %s\n" +msgstr "" + +#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 +msgid "yes" +msgstr "" + +#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 +msgid "no" +msgstr "" + +#: utils/cpufreq-info.c:164 +#, fuzzy, c-format +msgid " Active: %s\n" +msgstr " modulo %s\n" + +#: utils/cpufreq-info.c:177 +#, c-format +msgid " Boost States: %d\n" +msgstr "" + +#: utils/cpufreq-info.c:178 +#, c-format +msgid " Total States: %d\n" +msgstr "" + +#: utils/cpufreq-info.c:181 +#, c-format +msgid " Pstate-Pb%d: %luMHz (boost state)\n" +msgstr "" + +#: utils/cpufreq-info.c:184 +#, c-format +msgid " Pstate-P%d: %luMHz\n" +msgstr "" + +#: utils/cpufreq-info.c:211 +#, c-format +msgid " no or unknown cpufreq driver is active on this CPU\n" +msgstr " nessun modulo o modulo cpufreq sconosciuto per questa CPU\n" + +#: utils/cpufreq-info.c:213 +#, c-format +msgid " driver: %s\n" +msgstr " modulo %s\n" + +#: utils/cpufreq-info.c:219 +#, c-format +msgid " CPUs which run at the same hardware frequency: " +msgstr " CPU che operano alla stessa frequenza hardware: " + +#: utils/cpufreq-info.c:230 +#, c-format +msgid " CPUs which need to have their frequency coordinated by software: " +msgstr " CPU che è necessario siano coordinate dal software: " + +#: utils/cpufreq-info.c:241 +#, c-format +msgid " maximum transition latency: " +msgstr " latenza massima durante la transizione: " + +#: utils/cpufreq-info.c:247 +#, c-format +msgid " hardware limits: " +msgstr " limiti hardware: " + +#: utils/cpufreq-info.c:256 +#, c-format +msgid " available frequency steps: " +msgstr " frequenze disponibili: " + +#: utils/cpufreq-info.c:269 +#, c-format +msgid " available cpufreq governors: " +msgstr " gestori disponibili: " + +#: utils/cpufreq-info.c:280 +#, c-format +msgid " current policy: frequency should be within " +msgstr " gestore attuale: la frequenza deve mantenersi tra " + +#: utils/cpufreq-info.c:282 +#, c-format +msgid " and " +msgstr " e " + +#: utils/cpufreq-info.c:286 +#, c-format +msgid "" +"The governor \"%s\" may decide which speed to use\n" +" within this range.\n" +msgstr "" +" Il gestore \"%s\" può decidere quale velocità usare\n" +" in questo intervallo.\n" + +#: utils/cpufreq-info.c:293 +#, c-format +msgid " current CPU frequency is " +msgstr " la frequenza attuale della CPU è " + +#: utils/cpufreq-info.c:296 +#, c-format +msgid " (asserted by call to hardware)" +msgstr " (ottenuta da una chiamata diretta all'hardware)" + +#: utils/cpufreq-info.c:304 +#, c-format +msgid " cpufreq stats: " +msgstr " statistiche cpufreq:" + +#: utils/cpufreq-info.c:472 +#, fuzzy, c-format +msgid "Usage: cpupower freqinfo [options]\n" +msgstr "Uso: cpufreq-info [opzioni]\n" + +#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23 +#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148 +#, c-format +msgid "Options:\n" +msgstr "Opzioni:\n" + +#: utils/cpufreq-info.c:474 +#, fuzzy, c-format +msgid " -e, --debug Prints out debug information [default]\n" +msgstr " -e, --debug Mostra informazioni di debug\n" + +#: utils/cpufreq-info.c:475 +#, c-format +msgid "" +" -f, --freq Get frequency the CPU currently runs at, according\n" +" to the cpufreq core *\n" +msgstr "" +" -f, --freq Mostra la frequenza attuale della CPU secondo\n" +" il modulo cpufreq *\n" + +#: utils/cpufreq-info.c:477 +#, c-format +msgid "" +" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n" +" it from hardware (only available to root) *\n" +msgstr "" +" -w, --hwfreq Mostra la frequenza attuale della CPU leggendola\n" +" dall'hardware (disponibile solo per l'utente root) *\n" + +#: utils/cpufreq-info.c:479 +#, c-format +msgid "" +" -l, --hwlimits Determine the minimum and maximum CPU frequency " +"allowed *\n" +msgstr "" +" -l, --hwlimits Determina le frequenze minima e massima possibili per " +"la CPU *\n" + +#: utils/cpufreq-info.c:480 +#, c-format +msgid " -d, --driver Determines the used cpufreq kernel driver *\n" +msgstr "" +" -d, --driver Determina il modulo cpufreq del kernel in uso *\n" + +#: utils/cpufreq-info.c:481 +#, c-format +msgid " -p, --policy Gets the currently used cpufreq policy *\n" +msgstr "" +" -p, --policy Mostra il gestore cpufreq attualmente in uso *\n" + +#: utils/cpufreq-info.c:482 +#, c-format +msgid " -g, --governors Determines available cpufreq governors *\n" +msgstr " -g, --governors Determina i gestori cpufreq disponibili *\n" + +#: utils/cpufreq-info.c:483 +#, c-format +msgid "" +" -r, --related-cpus Determines which CPUs run at the same hardware " +"frequency *\n" +msgstr "" +" -r, --related-cpus Determina quali CPU operano alla stessa frequenza *\n" + +#: utils/cpufreq-info.c:484 +#, c-format +msgid "" +" -a, --affected-cpus Determines which CPUs need to have their frequency\n" +" coordinated by software *\n" +msgstr "" +" -a, --affected-cpus Determina quali CPU devono avere la frequenza\n" +" coordinata dal software *\n" + +#: utils/cpufreq-info.c:486 +#, c-format +msgid " -s, --stats Shows cpufreq statistics if available\n" +msgstr " -s, --stats Mostra le statistiche se disponibili\n" + +#: utils/cpufreq-info.c:487 +#, c-format +msgid "" +" -y, --latency Determines the maximum latency on CPU frequency " +"changes *\n" +msgstr "" +" -y, --latency Determina la latenza massima durante i cambi di " +"frequenza *\n" + +#: utils/cpufreq-info.c:488 +#, c-format +msgid " -b, --boost Checks for turbo or boost modes *\n" +msgstr "" + +#: utils/cpufreq-info.c:489 +#, c-format +msgid "" +" -o, --proc Prints out information like provided by the /proc/" +"cpufreq\n" +" interface in 2.4. and early 2.6. kernels\n" +msgstr "" +" -o, --proc Stampa le informazioni come se provenissero dalla\n" +" interfaccia cpufreq /proc/ presente nei kernel\n" +" 2.4 ed i primi 2.6\n" + +#: utils/cpufreq-info.c:491 +#, c-format +msgid "" +" -m, --human human-readable output for the -f, -w, -s and -y " +"parameters\n" +msgstr "" +" -m, --human formatta l'output delle opzioni -f, -w, -s e -y in " +"maniera\n" +" leggibile da un essere umano\n" + +#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152 +#, c-format +msgid " -h, --help Prints out this screen\n" +msgstr " -h, --help Stampa questa schermata\n" + +#: utils/cpufreq-info.c:495 +#, c-format +msgid "" +"If no argument or only the -c, --cpu parameter is given, debug output about\n" +"cpufreq is printed which is useful e.g. for reporting bugs.\n" +msgstr "" +"Se non viene specificata nessuna opzione o viene specificata solo l'opzione -" +"c, --cpu,\n" +"le informazioni di debug per cpufreq saranno utili ad esempio a riportare i " +"bug.\n" + +#: utils/cpufreq-info.c:497 +#, c-format +msgid "" +"For the arguments marked with *, omitting the -c or --cpu argument is\n" +"equivalent to setting it to zero\n" +msgstr "" +"Per le opzioni segnalate con *, omettere l'opzione -c o --cpu è come " +"specificarla\n" +"con il valore 0\n" + +#: utils/cpufreq-info.c:580 +#, c-format +msgid "" +"The argument passed to this tool can't be combined with passing a --cpu " +"argument\n" +msgstr "" +"L'opzione specificata a questo programma non può essere combinata con --cpu\n" + +#: utils/cpufreq-info.c:596 +#, c-format +msgid "" +"You can't specify more than one --cpu parameter and/or\n" +"more than one output-specific argument\n" +msgstr "" +"Non è possibile specificare più di una volta l'opzione --cpu e/o\n" +"specificare più di un parametro di output specifico\n" + +#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42 +#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213 +#, c-format +msgid "invalid or unknown argument\n" +msgstr "opzione sconosciuta o non valida\n" + +#: utils/cpufreq-info.c:617 +#, c-format +msgid "couldn't analyze CPU %d as it doesn't seem to be present\n" +msgstr "impossibile analizzare la CPU %d poiché non sembra essere presente\n" + +#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142 +#, c-format +msgid "analyzing CPU %d:\n" +msgstr "analisi della CPU %d:\n" + +#: utils/cpufreq-set.c:25 +#, fuzzy, c-format +msgid "Usage: cpupower frequency-set [options]\n" +msgstr "Uso: cpufreq-set [opzioni]\n" + +#: utils/cpufreq-set.c:27 +#, c-format +msgid "" +" -d FREQ, --min FREQ new minimum CPU frequency the governor may " +"select\n" +msgstr "" +" -d FREQ, --min FREQ la nuova frequenza minima che il gestore cpufreq " +"può scegliere\n" + +#: utils/cpufreq-set.c:28 +#, c-format +msgid "" +" -u FREQ, --max FREQ new maximum CPU frequency the governor may " +"select\n" +msgstr "" +" -u FREQ, --max FREQ la nuova frequenza massima che il gestore cpufreq " +"può scegliere\n" + +#: utils/cpufreq-set.c:29 +#, c-format +msgid " -g GOV, --governor GOV new cpufreq governor\n" +msgstr " -g GOV, --governor GOV nuovo gestore cpufreq\n" + +#: utils/cpufreq-set.c:30 +#, c-format +msgid "" +" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n" +" governor to be available and loaded\n" +msgstr "" +" -f FREQ, --freq FREQ specifica la frequenza a cui impostare la CPU.\n" +" È necessario che il gestore userspace sia " +"disponibile e caricato\n" + +#: utils/cpufreq-set.c:32 +#, c-format +msgid " -r, --related Switches all hardware-related CPUs\n" +msgstr "" +" -r, --related Modifica tutte le CPU coordinate dall'hardware\n" + +#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27 +#, c-format +msgid " -h, --help Prints out this screen\n" +msgstr " -h, --help Stampa questa schermata\n" + +#: utils/cpufreq-set.c:35 +#, fuzzy, c-format +msgid "" +"Notes:\n" +"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n" +msgstr "" +"Per le opzioni segnalate con *, omettere l'opzione -c o --cpu è come " +"specificarla\n" +"con il valore 0\n" + +#: utils/cpufreq-set.c:37 +#, fuzzy, c-format +msgid "" +"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other " +"parameter\n" +" except the -c CPU, --cpu CPU parameter\n" +"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n" +" by postfixing the value with the wanted unit name, without any space\n" +" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n" +msgstr "" +"Note:\n" +"1. Omettere l'opzione -c o --cpu è equivalente a impostarlo a 0\n" +"2. l'opzione -f FREQ, --freq FREQ non può essere specificata con altre " +"opzioni\n" +" ad eccezione dell'opzione -c CPU o --cpu CPU\n" +"3. le FREQuenze possono essere specuficate in Hz, kHz (default), MHz, GHz, " +"or THz\n" +" postponendo l'unità di misura al valore senza nessuno spazio fra loro\n" +" (FREQuenza in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n" + +#: utils/cpufreq-set.c:57 +#, c-format +msgid "" +"Error setting new values. Common errors:\n" +"- Do you have proper administration rights? (super-user?)\n" +"- Is the governor you requested available and modprobed?\n" +"- Trying to set an invalid policy?\n" +"- Trying to set a specific frequency, but userspace governor is not " +"available,\n" +" for example because of hardware which cannot be set to a specific " +"frequency\n" +" or because the userspace governor isn't loaded?\n" +msgstr "" +"Si sono verificati degli errori impostando i nuovi valori.\n" +"Alcuni errori comuni possono essere:\n" +"- Hai i necessari diritti di amministrazione? (super-user?)\n" +"- Il gestore che hai richiesto è disponibile e caricato?\n" +"- Stai provando ad impostare una politica di gestione non valida?\n" +"- Stai provando a impostare una specifica frequenza ma il gestore\n" +" userspace non è disponibile, per esempio a causa dell'hardware\n" +" che non supporta frequenze fisse o a causa del fatto che\n" +" il gestore userspace non è caricato?\n" + +#: utils/cpufreq-set.c:170 +#, c-format +msgid "wrong, unknown or unhandled CPU?\n" +msgstr "CPU errata, sconosciuta o non gestita?\n" + +#: utils/cpufreq-set.c:302 +#, c-format +msgid "" +"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n" +"-g/--governor parameters\n" +msgstr "" +"l'opzione -f/--freq non può venire combinata con i parametri\n" +" -d/--min, -u/--max o -g/--governor\n" + +#: utils/cpufreq-set.c:308 +#, c-format +msgid "" +"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n" +"-g/--governor must be passed\n" +msgstr "" +"Almeno una delle opzioni -f/--freq, -d/--min, -u/--max, e -g/--governor\n" +"deve essere specificata\n" + +#: utils/cpufreq-set.c:347 +#, c-format +msgid "Setting cpu: %d\n" +msgstr "" + +#: utils/cpupower-set.c:22 +#, c-format +msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n" +msgstr "" + +#: utils/cpupower-set.c:24 +#, c-format +msgid "" +" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n" +" Intel models [0-15], see manpage for details\n" +msgstr "" + +#: utils/cpupower-set.c:26 +#, c-format +msgid "" +" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n" +msgstr "" + +#: utils/cpupower-set.c:27 +#, c-format +msgid "" +" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler " +"policy.\n" +msgstr "" + +#: utils/cpupower-set.c:80 +#, c-format +msgid "--perf-bias param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:91 +#, c-format +msgid "--sched-mc param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:102 +#, c-format +msgid "--sched-smt param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:121 +#, c-format +msgid "Error setting sched-mc %s\n" +msgstr "" + +#: utils/cpupower-set.c:127 +#, c-format +msgid "Error setting sched-smt %s\n" +msgstr "" + +#: utils/cpupower-set.c:146 +#, c-format +msgid "Error setting perf-bias value on CPU %d\n" +msgstr "" + +#: utils/cpupower-info.c:21 +#, c-format +msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n" +msgstr "" + +#: utils/cpupower-info.c:23 +#, c-format +msgid "" +" -b, --perf-bias Gets CPU's power vs performance policy on some\n" +" Intel models [0-15], see manpage for details\n" +msgstr "" + +#: utils/cpupower-info.c:25 +#, fuzzy, c-format +msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n" +msgstr "" +" -p, --policy Mostra il gestore cpufreq attualmente in uso *\n" + +#: utils/cpupower-info.c:26 +#, c-format +msgid "" +" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n" +msgstr "" + +#: utils/cpupower-info.c:28 +#, c-format +msgid "" +"\n" +"Passing no option will show all info, by default only on core 0\n" +msgstr "" + +#: utils/cpupower-info.c:102 +#, c-format +msgid "System's multi core scheduler setting: " +msgstr "" + +#. if sysfs file is missing it's: errno == ENOENT +#: utils/cpupower-info.c:105 utils/cpupower-info.c:114 +#, c-format +msgid "not supported\n" +msgstr "" + +#: utils/cpupower-info.c:111 +#, c-format +msgid "System's thread sibling scheduler setting: " +msgstr "" + +#: utils/cpupower-info.c:126 +#, c-format +msgid "Intel's performance bias setting needs root privileges\n" +msgstr "" + +#: utils/cpupower-info.c:128 +#, c-format +msgid "System does not support Intel's performance bias setting\n" +msgstr "" + +#: utils/cpupower-info.c:147 +#, c-format +msgid "Could not read perf-bias value\n" +msgstr "" + +#: utils/cpupower-info.c:150 +#, c-format +msgid "perf-bias: %d\n" +msgstr "" + +#: utils/cpuidle-info.c:28 +#, fuzzy, c-format +msgid "Analyzing CPU %d:\n" +msgstr "analisi della CPU %d:\n" + +#: utils/cpuidle-info.c:32 +#, c-format +msgid "CPU %u: No idle states\n" +msgstr "" + +#: utils/cpuidle-info.c:36 +#, c-format +msgid "CPU %u: Can't read idle state info\n" +msgstr "" + +#: utils/cpuidle-info.c:41 +#, c-format +msgid "Could not determine max idle state %u\n" +msgstr "" + +#: utils/cpuidle-info.c:46 +#, c-format +msgid "Number of idle states: %d\n" +msgstr "" + +#: utils/cpuidle-info.c:48 +#, fuzzy, c-format +msgid "Available idle states:" +msgstr " frequenze disponibili: " + +#: utils/cpuidle-info.c:71 +#, c-format +msgid "Flags/Description: %s\n" +msgstr "" + +#: utils/cpuidle-info.c:74 +#, c-format +msgid "Latency: %lu\n" +msgstr "" + +#: utils/cpuidle-info.c:76 +#, c-format +msgid "Usage: %lu\n" +msgstr "" + +#: utils/cpuidle-info.c:78 +#, c-format +msgid "Duration: %llu\n" +msgstr "" + +#: utils/cpuidle-info.c:90 +#, c-format +msgid "Could not determine cpuidle driver\n" +msgstr "" + +#: utils/cpuidle-info.c:94 +#, fuzzy, c-format +msgid "CPUidle driver: %s\n" +msgstr " modulo %s\n" + +#: utils/cpuidle-info.c:99 +#, c-format +msgid "Could not determine cpuidle governor\n" +msgstr "" + +#: utils/cpuidle-info.c:103 +#, c-format +msgid "CPUidle governor: %s\n" +msgstr "" + +#: utils/cpuidle-info.c:122 +#, c-format +msgid "CPU %u: Can't read C-state info\n" +msgstr "" + +#. printf("Cstates: %d\n", cstates); +#: utils/cpuidle-info.c:127 +#, c-format +msgid "active state: C0\n" +msgstr "" + +#: utils/cpuidle-info.c:128 +#, c-format +msgid "max_cstate: C%u\n" +msgstr "" + +#: utils/cpuidle-info.c:129 +#, fuzzy, c-format +msgid "maximum allowed latency: %lu usec\n" +msgstr " latenza massima durante la transizione: " + +#: utils/cpuidle-info.c:130 +#, c-format +msgid "states:\t\n" +msgstr "" + +#: utils/cpuidle-info.c:132 +#, c-format +msgid " C%d: type[C%d] " +msgstr "" + +#: utils/cpuidle-info.c:134 +#, c-format +msgid "promotion[--] demotion[--] " +msgstr "" + +#: utils/cpuidle-info.c:135 +#, c-format +msgid "latency[%03lu] " +msgstr "" + +#: utils/cpuidle-info.c:137 +#, c-format +msgid "usage[%08lu] " +msgstr "" + +#: utils/cpuidle-info.c:139 +#, c-format +msgid "duration[%020Lu] \n" +msgstr "" + +#: utils/cpuidle-info.c:147 +#, fuzzy, c-format +msgid "Usage: cpupower idleinfo [options]\n" +msgstr "Uso: cpufreq-info [opzioni]\n" + +#: utils/cpuidle-info.c:149 +#, fuzzy, c-format +msgid " -s, --silent Only show general C-state information\n" +msgstr " -e, --debug Mostra informazioni di debug\n" + +#: utils/cpuidle-info.c:150 +#, fuzzy, c-format +msgid "" +" -o, --proc Prints out information like provided by the /proc/" +"acpi/processor/*/power\n" +" interface in older kernels\n" +msgstr "" +" -o, --proc Stampa le informazioni come se provenissero dalla\n" +" interfaccia cpufreq /proc/ presente nei kernel\n" +" 2.4 ed i primi 2.6\n" + +#: utils/cpuidle-info.c:209 +#, fuzzy, c-format +msgid "You can't specify more than one output-specific argument\n" +msgstr "" +"Non è possibile specificare più di una volta l'opzione --cpu e/o\n" +"specificare più di un parametro di output specifico\n" + +#~ msgid "" +#~ " -c CPU, --cpu CPU CPU number which information shall be determined " +#~ "about\n" +#~ msgstr "" +#~ " -c CPU, --cpu CPU Numero di CPU per la quale ottenere le " +#~ "informazioni\n" + +#~ msgid "" +#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be " +#~ "modified\n" +#~ msgstr "" +#~ " -c CPU, --cpu CPU numero di CPU per la quale modificare le " +#~ "impostazioni\n" + +#, fuzzy +#~ msgid " CPUs which coordinate software frequency requirements: " +#~ msgstr "" +#~ " CPU per le quali e` necessario cambiare la frequenza " +#~ "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 @@ +# Brazilian Portuguese translations for cpufrequtils package +# Copyright (C) 2008 THE cpufrequtils'S COPYRIGHT HOLDER +# This file is distributed under the same license as the cpufrequtils package. +# Claudio Eduardo , 2009. +# +# +msgid "" +msgstr "" +"Project-Id-Version: cpufrequtils 004\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-03-08 17:03+0100\n" +"PO-Revision-Date: 2008-06-14 22:16-0400\n" +"Last-Translator: Claudio Eduardo \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: utils/idle_monitor/nhm_idle.c:36 +msgid "Processor Core C3" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:43 +msgid "Processor Core C6" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:51 +msgid "Processor Package C3" +msgstr "" + +#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70 +msgid "Processor Package C6" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:33 +msgid "Processor Core C7" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:40 +msgid "Processor Package C2" +msgstr "" + +#: utils/idle_monitor/snb_idle.c:47 +msgid "Processor Package C7" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:56 +msgid "Package in sleep state (PC1 or deeper)" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:63 +msgid "Processor Package C1" +msgstr "" + +#: utils/idle_monitor/amd_fam14h_idle.c:77 +msgid "North Bridge P1 boolean counter (returns 0 or 1)" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:35 +msgid "Processor Core not idle" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:42 +msgid "Processor Core in an idle state" +msgstr "" + +#: utils/idle_monitor/mperf_monitor.c:50 +msgid "Average Frequency (including boost) in MHz" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:66 +#, c-format +msgid "" +"cpupower monitor: [-h] [ [-t] | [-l] | [-m ,[] ] ] [-i " +"interval_sec | -c command ...]\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:69 +#, c-format +msgid "" +"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m ,[] ] ] [-i " +"interval_sec | -c command ...]\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:71 +#, c-format +msgid "\t -v: be more verbose\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:73 +#, c-format +msgid "\t -h: print this help\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:74 +#, c-format +msgid "\t -i: time intervall to measure for in seconds (default 1)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:75 +#, c-format +msgid "\t -t: show CPU topology/hierarchy\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:76 +#, c-format +msgid "\t -l: list available CPU sleep monitors (for use with -m)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:77 +#, c-format +msgid "\t -m: show specific CPU sleep monitors only (in same order)\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:79 +#, c-format +msgid "" +"only one of: -t, -l, -m are allowed\n" +"If none of them is passed," +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:80 +#, c-format +msgid " all supported monitors are shown\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:197 +#, c-format +msgid "Monitor %s, Counter %s has no count function. Implementation error\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:207 +#, c-format +msgid " *is offline\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:236 +#, c-format +msgid "%s: max monitor name length (%d) exceeded\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:250 +#, c-format +msgid "No matching monitor found in %s, try -l option\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:266 +#, c-format +msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:319 +#, c-format +msgid "%s took %.5f seconds and exited with status %d\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:406 +#, c-format +msgid "Cannot read number of available processors\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:417 +#, c-format +msgid "Available monitor %s needs root access\n" +msgstr "" + +#: utils/idle_monitor/cpupower-monitor.c:428 +#, c-format +msgid "No HW Cstate monitors found\n" +msgstr "" + +#: utils/cpupower.c:78 +#, c-format +msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n" +msgstr "" + +#: utils/cpupower.c:79 +#, c-format +msgid "cpupower --version\n" +msgstr "" + +#: utils/cpupower.c:80 +#, c-format +msgid "Supported subcommands are:\n" +msgstr "" + +#: utils/cpupower.c:83 +#, c-format +msgid "" +"\n" +"Some subcommands can make use of the -c cpulist option.\n" +msgstr "" + +#: utils/cpupower.c:84 +#, c-format +msgid "Look at the general cpupower manpage how to use it\n" +msgstr "" + +#: utils/cpupower.c:85 +#, c-format +msgid "and read up the subcommand's manpage whether it is supported.\n" +msgstr "" + +#: utils/cpupower.c:86 +#, c-format +msgid "" +"\n" +"Use cpupower help subcommand for getting help for above subcommands.\n" +msgstr "" + +#: utils/cpupower.c:91 +#, c-format +msgid "Report errors and bugs to %s, please.\n" +msgstr "Reporte erros e bugs para %s, por favor.\n" + +#: utils/cpupower.c:114 +#, c-format +msgid "Error parsing cpu list\n" +msgstr "" + +#: utils/cpupower.c:172 +#, c-format +msgid "Subcommand %s needs root privileges\n" +msgstr "" + +#: utils/cpufreq-info.c:31 +#, c-format +msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n" +msgstr "Não foi possível contar o número de CPUs (%s: %s), assumindo 1\n" + +#: utils/cpufreq-info.c:63 +#, c-format +msgid "" +" minimum CPU frequency - maximum CPU frequency - governor\n" +msgstr "" +" frequência mínina do CPU - frequência máxima do CPU - " +"regulador\n" + +#: utils/cpufreq-info.c:151 +#, c-format +msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n" +msgstr "" + +#. P state changes via MSR are identified via cpuid 80000007 +#. on Intel and AMD, but we assume boost capable machines can do that +#. if (cpuid_eax(0x80000000) >= 0x80000007 +#. && (cpuid_edx(0x80000007) & (1 << 7))) +#. +#: utils/cpufreq-info.c:161 +#, c-format +msgid " boost state support: \n" +msgstr "" + +#: utils/cpufreq-info.c:163 +#, c-format +msgid " Supported: %s\n" +msgstr "" + +#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 +msgid "yes" +msgstr "" + +#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164 +msgid "no" +msgstr "" + +#: utils/cpufreq-info.c:164 +#, fuzzy, c-format +msgid " Active: %s\n" +msgstr " driver: %s\n" + +#: utils/cpufreq-info.c:177 +#, c-format +msgid " Boost States: %d\n" +msgstr "" + +#: utils/cpufreq-info.c:178 +#, c-format +msgid " Total States: %d\n" +msgstr "" + +#: utils/cpufreq-info.c:181 +#, c-format +msgid " Pstate-Pb%d: %luMHz (boost state)\n" +msgstr "" + +#: utils/cpufreq-info.c:184 +#, c-format +msgid " Pstate-P%d: %luMHz\n" +msgstr "" + +#: utils/cpufreq-info.c:211 +#, c-format +msgid " no or unknown cpufreq driver is active on this CPU\n" +msgstr " nenhum ou driver do cpufreq deconhecido está ativo nesse CPU\n" + +#: utils/cpufreq-info.c:213 +#, c-format +msgid " driver: %s\n" +msgstr " driver: %s\n" + +#: utils/cpufreq-info.c:219 +#, c-format +msgid " CPUs which run at the same hardware frequency: " +msgstr " CPUs que rodam na mesma frequência de hardware: " + +#: utils/cpufreq-info.c:230 +#, c-format +msgid " CPUs which need to have their frequency coordinated by software: " +msgstr " CPUs que precisam ter suas frequências coordenadas por software: " + +#: utils/cpufreq-info.c:241 +#, c-format +msgid " maximum transition latency: " +msgstr " maior latência de transição: " + +#: utils/cpufreq-info.c:247 +#, c-format +msgid " hardware limits: " +msgstr " limites do hardware: " + +#: utils/cpufreq-info.c:256 +#, c-format +msgid " available frequency steps: " +msgstr " níveis de frequência disponíveis: " + +#: utils/cpufreq-info.c:269 +#, c-format +msgid " available cpufreq governors: " +msgstr " reguladores do cpufreq disponíveis: " + +#: utils/cpufreq-info.c:280 +#, c-format +msgid " current policy: frequency should be within " +msgstr " política de frequência atual deve estar entre " + +#: utils/cpufreq-info.c:282 +#, c-format +msgid " and " +msgstr " e " + +#: utils/cpufreq-info.c:286 +#, c-format +msgid "" +"The governor \"%s\" may decide which speed to use\n" +" within this range.\n" +msgstr "" +"O regulador \"%s\" deve decidir qual velocidade usar\n" +" dentro desse limite.\n" + +#: utils/cpufreq-info.c:293 +#, c-format +msgid " current CPU frequency is " +msgstr " frequência atual do CPU é " + +#: utils/cpufreq-info.c:296 +#, c-format +msgid " (asserted by call to hardware)" +msgstr " (declarado por chamada ao hardware)" + +#: utils/cpufreq-info.c:304 +#, c-format +msgid " cpufreq stats: " +msgstr " status do cpufreq: " + +#: utils/cpufreq-info.c:472 +#, fuzzy, c-format +msgid "Usage: cpupower freqinfo [options]\n" +msgstr "Uso: cpufreq-info [opções]\n" + +#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23 +#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148 +#, c-format +msgid "Options:\n" +msgstr "Opções:\n" + +#: utils/cpufreq-info.c:474 +#, fuzzy, c-format +msgid " -e, --debug Prints out debug information [default]\n" +msgstr " -e, --debug Mostra informação de debug\n" + +#: utils/cpufreq-info.c:475 +#, c-format +msgid "" +" -f, --freq Get frequency the CPU currently runs at, according\n" +" to the cpufreq core *\n" +msgstr "" +" -f, --freq Obtem a frequência na qual o CPU roda no momento, de " +"acordo\n" +" com o núcleo do cpufreq *\n" + +#: utils/cpufreq-info.c:477 +#, c-format +msgid "" +" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n" +" it from hardware (only available to root) *\n" +msgstr "" +" -w, --hwfreq Obtem a frequência na qual o CPU está operando no " +"momento,\n" +" através de leitura no hardware (disponível somente " +"para root) *\n" + +#: utils/cpufreq-info.c:479 +#, c-format +msgid "" +" -l, --hwlimits Determine the minimum and maximum CPU frequency " +"allowed *\n" +msgstr "" +" -l, --hwlimits Determina a frequência mínima e máxima do CPU " +"permitida *\n" + +#: utils/cpufreq-info.c:480 +#, c-format +msgid " -d, --driver Determines the used cpufreq kernel driver *\n" +msgstr "" +" -d, --driver Determina o driver do kernel do cpufreq usado *\n" + +#: utils/cpufreq-info.c:481 +#, c-format +msgid " -p, --policy Gets the currently used cpufreq policy *\n" +msgstr "" +"--p, --policy Obtem a política do cpufreq em uso no momento *\n" + +#: utils/cpufreq-info.c:482 +#, c-format +msgid " -g, --governors Determines available cpufreq governors *\n" +msgstr "" +" -g, --governors Determina reguladores do cpufreq disponíveis *\n" + +#: utils/cpufreq-info.c:483 +#, c-format +msgid "" +" -r, --related-cpus Determines which CPUs run at the same hardware " +"frequency *\n" +msgstr "" +" -r, --related-cpus Determina quais CPUs rodam na mesma frequência de " +"hardware *\n" + +#: utils/cpufreq-info.c:484 +#, c-format +msgid "" +" -a, --affected-cpus Determines which CPUs need to have their frequency\n" +" coordinated by software *\n" +msgstr "" +" -a, --affected-cpus Determina quais CPUs precisam ter suas frequências\n" +" coordenadas por software *\n" + +#: utils/cpufreq-info.c:486 +#, c-format +msgid " -s, --stats Shows cpufreq statistics if available\n" +msgstr " -s, --stats Mostra estatísticas do cpufreq se disponíveis\n" + +#: utils/cpufreq-info.c:487 +#, c-format +msgid "" +" -y, --latency Determines the maximum latency on CPU frequency " +"changes *\n" +msgstr "" +" -y, --latency Determina a latência máxima nas trocas de frequência " +"do CPU *\n" + +#: utils/cpufreq-info.c:488 +#, c-format +msgid " -b, --boost Checks for turbo or boost modes *\n" +msgstr "" + +#: utils/cpufreq-info.c:489 +#, c-format +msgid "" +" -o, --proc Prints out information like provided by the /proc/" +"cpufreq\n" +" interface in 2.4. and early 2.6. kernels\n" +msgstr "" +" -o, --proc Mostra informação do tipo provida pela interface /" +"proc/cpufreq\n" +" em kernels 2.4. e mais recentes 2.6\n" + +#: utils/cpufreq-info.c:491 +#, c-format +msgid "" +" -m, --human human-readable output for the -f, -w, -s and -y " +"parameters\n" +msgstr "" +" -m, --human saída legível para humanos para os parâmetros -f, -w, " +"-s e -y\n" + +#: utils/cpufreq-info.c:492 utils/cpuidle-info.c:152 +#, c-format +msgid " -h, --help Prints out this screen\n" +msgstr " -h, --help Imprime essa tela\n" + +#: utils/cpufreq-info.c:495 +#, c-format +msgid "" +"If no argument or only the -c, --cpu parameter is given, debug output about\n" +"cpufreq is printed which is useful e.g. for reporting bugs.\n" +msgstr "" +"Se nenhum argumento ou somente o parâmetro -c, --cpu é dado, informação de " +"debug sobre\n" +"o cpufreq é mostrada, o que é útil por exemplo para reportar bugs.\n" + +#: utils/cpufreq-info.c:497 +#, c-format +msgid "" +"For the arguments marked with *, omitting the -c or --cpu argument is\n" +"equivalent to setting it to zero\n" +msgstr "" +"Para os argumentos marcados com *, omitir o argumento -c ou --cpu é\n" +"equivalente a setá-lo como zero\n" + +#: utils/cpufreq-info.c:580 +#, c-format +msgid "" +"The argument passed to this tool can't be combined with passing a --cpu " +"argument\n" +msgstr "" +"O argumento usado pra essa ferramenta não pode ser combinado com um " +"argumento --cpu\n" + +#: utils/cpufreq-info.c:596 +#, c-format +msgid "" +"You can't specify more than one --cpu parameter and/or\n" +"more than one output-specific argument\n" +msgstr "" +"Você não pode especificar mais do que um parâmetro --cpu e/ou\n" +"mais do que um argumento de saída específico\n" + +#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42 +#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213 +#, c-format +msgid "invalid or unknown argument\n" +msgstr "argumento inválido ou desconhecido\n" + +#: utils/cpufreq-info.c:617 +#, c-format +msgid "couldn't analyze CPU %d as it doesn't seem to be present\n" +msgstr "" +"não foi possível analisar o CPU % já que o mesmo parece não estar presente\n" + +#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142 +#, c-format +msgid "analyzing CPU %d:\n" +msgstr "analisando o CPU %d:\n" + +#: utils/cpufreq-set.c:25 +#, fuzzy, c-format +msgid "Usage: cpupower frequency-set [options]\n" +msgstr "Uso: cpufreq-set [opções]\n" + +#: utils/cpufreq-set.c:27 +#, c-format +msgid "" +" -d FREQ, --min FREQ new minimum CPU frequency the governor may " +"select\n" +msgstr "" +" -d FREQ, --min FREQ nova frequência mínima do CPU que o regulador " +"deve selecionar\n" + +#: utils/cpufreq-set.c:28 +#, c-format +msgid "" +" -u FREQ, --max FREQ new maximum CPU frequency the governor may " +"select\n" +msgstr "" +" -u FREQ, --max FREQ nova frequência máxima do CPU que o regulador " +"deve escolher\n" + +#: utils/cpufreq-set.c:29 +#, c-format +msgid " -g GOV, --governor GOV new cpufreq governor\n" +msgstr " -g GOV, --governor GOV novo regulador do cpufreq\n" + +#: utils/cpufreq-set.c:30 +#, c-format +msgid "" +" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n" +" governor to be available and loaded\n" +msgstr "" +" -f FREQ, --freq FREQ frequência específica para ser setada. Necessita " +"que o regulador em\n" +" nível de usuário esteja disponível e carregado\n" + +#: utils/cpufreq-set.c:32 +#, c-format +msgid " -r, --related Switches all hardware-related CPUs\n" +msgstr "" +" -r, --related Modifica todos os CPUs relacionados ao hardware\n" + +#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27 +#, c-format +msgid " -h, --help Prints out this screen\n" +msgstr " -h, --help Mostra essa tela\n" + +#: utils/cpufreq-set.c:35 +#, fuzzy, c-format +msgid "" +"Notes:\n" +"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n" +msgstr "" +"Para os argumentos marcados com *, omitir o argumento -c ou --cpu é\n" +"equivalente a setá-lo como zero\n" + +#: utils/cpufreq-set.c:37 +#, fuzzy, c-format +msgid "" +"2. The -f FREQ, --freq FREQ parameter cannot be combined with any other " +"parameter\n" +" except the -c CPU, --cpu CPU parameter\n" +"3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n" +" by postfixing the value with the wanted unit name, without any space\n" +" (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n" +msgstr "" +"Notas:\n" +"1. Omitir o argumento -c or --cpu é equivalente a setá-lo como zero\n" +"2. O parâmetro -f FREQ, --freq FREQ não pode ser combinado com qualquer " +"outro parâmetro\n" +" exceto com o parâmetro -c CPU, --cpu CPU\n" +"3. FREQuências podem ser usadas em Hz, kHz (padrão), MHz, GHz, o THz\n" +" colocando o nome desejado da unidade após o valor, sem qualquer espaço\n" +" (FREQuência em kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n" + +#: utils/cpufreq-set.c:57 +#, c-format +msgid "" +"Error setting new values. Common errors:\n" +"- Do you have proper administration rights? (super-user?)\n" +"- Is the governor you requested available and modprobed?\n" +"- Trying to set an invalid policy?\n" +"- Trying to set a specific frequency, but userspace governor is not " +"available,\n" +" for example because of hardware which cannot be set to a specific " +"frequency\n" +" or because the userspace governor isn't loaded?\n" +msgstr "" +"Erro ao setar novos valores. Erros comuns:\n" +"- Você tem direitos administrativos necessários? (super-usuário?)\n" +"- O regulador que você requesitou está disponível e foi \"modprobed\"?\n" +"- Tentando setar uma política inválida?\n" +"- Tentando setar uma frequência específica, mas o regulador em nível de " +"usuário não está disponível,\n" +" por exemplo devido ao hardware que não pode ser setado pra uma frequência " +"específica\n" +" ou porque o regulador em nível de usuário não foi carregado?\n" + +#: utils/cpufreq-set.c:170 +#, c-format +msgid "wrong, unknown or unhandled CPU?\n" +msgstr "CPU errado, desconhecido ou inesperado?\n" + +#: utils/cpufreq-set.c:302 +#, c-format +msgid "" +"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n" +"-g/--governor parameters\n" +msgstr "" +"o parâmetro -f/--freq não pode ser combinado com os parâmetros -d/--min, -" +"u/--max ou\n" +"-g/--governor\n" + +#: utils/cpufreq-set.c:308 +#, c-format +msgid "" +"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n" +"-g/--governor must be passed\n" +msgstr "" +"Pelo menos um parâmetro entre -f/--freq, -d/--min, -u/--max, e\n" +"-g/--governor deve ser usado\n" + +#: utils/cpufreq-set.c:347 +#, c-format +msgid "Setting cpu: %d\n" +msgstr "" + +#: utils/cpupower-set.c:22 +#, c-format +msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n" +msgstr "" + +#: utils/cpupower-set.c:24 +#, c-format +msgid "" +" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n" +" Intel models [0-15], see manpage for details\n" +msgstr "" + +#: utils/cpupower-set.c:26 +#, c-format +msgid "" +" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n" +msgstr "" + +#: utils/cpupower-set.c:27 +#, c-format +msgid "" +" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler " +"policy.\n" +msgstr "" + +#: utils/cpupower-set.c:80 +#, c-format +msgid "--perf-bias param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:91 +#, c-format +msgid "--sched-mc param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:102 +#, c-format +msgid "--sched-smt param out of range [0-%d]\n" +msgstr "" + +#: utils/cpupower-set.c:121 +#, c-format +msgid "Error setting sched-mc %s\n" +msgstr "" + +#: utils/cpupower-set.c:127 +#, c-format +msgid "Error setting sched-smt %s\n" +msgstr "" + +#: utils/cpupower-set.c:146 +#, c-format +msgid "Error setting perf-bias value on CPU %d\n" +msgstr "" + +#: utils/cpupower-info.c:21 +#, c-format +msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n" +msgstr "" + +#: utils/cpupower-info.c:23 +#, c-format +msgid "" +" -b, --perf-bias Gets CPU's power vs performance policy on some\n" +" Intel models [0-15], see manpage for details\n" +msgstr "" + +#: utils/cpupower-info.c:25 +#, fuzzy, c-format +msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n" +msgstr "" +"--p, --policy Obtem a política do cpufreq em uso no momento *\n" + +#: utils/cpupower-info.c:26 +#, c-format +msgid "" +" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n" +msgstr "" + +#: utils/cpupower-info.c:28 +#, c-format +msgid "" +"\n" +"Passing no option will show all info, by default only on core 0\n" +msgstr "" + +#: utils/cpupower-info.c:102 +#, c-format +msgid "System's multi core scheduler setting: " +msgstr "" + +#. if sysfs file is missing it's: errno == ENOENT +#: utils/cpupower-info.c:105 utils/cpupower-info.c:114 +#, c-format +msgid "not supported\n" +msgstr "" + +#: utils/cpupower-info.c:111 +#, c-format +msgid "System's thread sibling scheduler setting: " +msgstr "" + +#: utils/cpupower-info.c:126 +#, c-format +msgid "Intel's performance bias setting needs root privileges\n" +msgstr "" + +#: utils/cpupower-info.c:128 +#, c-format +msgid "System does not support Intel's performance bias setting\n" +msgstr "" + +#: utils/cpupower-info.c:147 +#, c-format +msgid "Could not read perf-bias value\n" +msgstr "" + +#: utils/cpupower-info.c:150 +#, c-format +msgid "perf-bias: %d\n" +msgstr "" + +#: utils/cpuidle-info.c:28 +#, fuzzy, c-format +msgid "Analyzing CPU %d:\n" +msgstr "analisando o CPU %d:\n" + +#: utils/cpuidle-info.c:32 +#, c-format +msgid "CPU %u: No idle states\n" +msgstr "" + +#: utils/cpuidle-info.c:36 +#, c-format +msgid "CPU %u: Can't read idle state info\n" +msgstr "" + +#: utils/cpuidle-info.c:41 +#, c-format +msgid "Could not determine max idle state %u\n" +msgstr "" + +#: utils/cpuidle-info.c:46 +#, c-format +msgid "Number of idle states: %d\n" +msgstr "" + +#: utils/cpuidle-info.c:48 +#, fuzzy, c-format +msgid "Available idle states:" +msgstr " níveis de frequência disponíveis: " + +#: utils/cpuidle-info.c:71 +#, c-format +msgid "Flags/Description: %s\n" +msgstr "" + +#: utils/cpuidle-info.c:74 +#, c-format +msgid "Latency: %lu\n" +msgstr "" + +#: utils/cpuidle-info.c:76 +#, c-format +msgid "Usage: %lu\n" +msgstr "" + +#: utils/cpuidle-info.c:78 +#, c-format +msgid "Duration: %llu\n" +msgstr "" + +#: utils/cpuidle-info.c:90 +#, c-format +msgid "Could not determine cpuidle driver\n" +msgstr "" + +#: utils/cpuidle-info.c:94 +#, fuzzy, c-format +msgid "CPUidle driver: %s\n" +msgstr " driver: %s\n" + +#: utils/cpuidle-info.c:99 +#, c-format +msgid "Could not determine cpuidle governor\n" +msgstr "" + +#: utils/cpuidle-info.c:103 +#, c-format +msgid "CPUidle governor: %s\n" +msgstr "" + +#: utils/cpuidle-info.c:122 +#, c-format +msgid "CPU %u: Can't read C-state info\n" +msgstr "" + +#. printf("Cstates: %d\n", cstates); +#: utils/cpuidle-info.c:127 +#, c-format +msgid "active state: C0\n" +msgstr "" + +#: utils/cpuidle-info.c:128 +#, c-format +msgid "max_cstate: C%u\n" +msgstr "" + +#: utils/cpuidle-info.c:129 +#, fuzzy, c-format +msgid "maximum allowed latency: %lu usec\n" +msgstr " maior latência de transição: " + +#: utils/cpuidle-info.c:130 +#, c-format +msgid "states:\t\n" +msgstr "" + +#: utils/cpuidle-info.c:132 +#, c-format +msgid " C%d: type[C%d] " +msgstr "" + +#: utils/cpuidle-info.c:134 +#, c-format +msgid "promotion[--] demotion[--] " +msgstr "" + +#: utils/cpuidle-info.c:135 +#, c-format +msgid "latency[%03lu] " +msgstr "" + +#: utils/cpuidle-info.c:137 +#, c-format +msgid "usage[%08lu] " +msgstr "" + +#: utils/cpuidle-info.c:139 +#, c-format +msgid "duration[%020Lu] \n" +msgstr "" + +#: utils/cpuidle-info.c:147 +#, fuzzy, c-format +msgid "Usage: cpupower idleinfo [options]\n" +msgstr "Uso: cpufreq-info [opções]\n" + +#: utils/cpuidle-info.c:149 +#, fuzzy, c-format +msgid " -s, --silent Only show general C-state information\n" +msgstr " -e, --debug Mostra informação de debug\n" + +#: utils/cpuidle-info.c:150 +#, fuzzy, c-format +msgid "" +" -o, --proc Prints out information like provided by the /proc/" +"acpi/processor/*/power\n" +" interface in older kernels\n" +msgstr "" +" -o, --proc Mostra informação do tipo provida pela interface /" +"proc/cpufreq\n" +" em kernels 2.4. e mais recentes 2.6\n" + +#: utils/cpuidle-info.c:209 +#, fuzzy, c-format +msgid "You can't specify more than one output-specific argument\n" +msgstr "" +"Você não pode especificar mais do que um parâmetro --cpu e/ou\n" +"mais do que um argumento de saída específico\n" + +#~ msgid "" +#~ " -c CPU, --cpu CPU CPU number which information shall be determined " +#~ "about\n" +#~ msgstr "" +#~ " -c CPU, --cpu CPU número do CPU sobre o qual as inforções devem ser " +#~ "determinadas\n" + +#~ msgid "" +#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be " +#~ "modified\n" +#~ msgstr "" +#~ " -c CPU, --cpu CPU número do CPU onde as configurações do cpufreq " +#~ "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..c870ffba5219 --- /dev/null +++ b/tools/power/cpupower/utils/builtin.h @@ -0,0 +1,18 @@ +#ifndef BUILTIN_H +#define BUILTIN_H + +extern int cmd_set(int argc, const char **argv); +extern int cmd_info(int argc, const char **argv); +extern int cmd_freq_set(int argc, const char **argv); +extern int cmd_freq_info(int argc, const char **argv); +extern int cmd_idle_info(int argc, const char **argv); +extern int cmd_monitor(int argc, const char **argv); + +extern void set_help(void); +extern void info_help(void); +extern void freq_set_help(void); +extern void freq_info_help(void); +extern void idle_info_help(void); +extern void monitor_help(void); + +#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..eaa8be06edfa --- /dev/null +++ b/tools/power/cpupower/utils/cpufreq-info.c @@ -0,0 +1,665 @@ +/* + * (C) 2004-2009 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + */ + + +#include +#include +#include +#include +#include + +#include + +#include "cpufreq.h" +#include "helpers/helpers.h" +#include "helpers/bitmask.h" + +#define LINE_LEN 10 + +static unsigned int count_cpus(void) +{ + FILE *fp; + char value[LINE_LEN]; + unsigned int ret = 0; + unsigned int cpunr = 0; + + fp = fopen("/proc/stat", "r"); + if(!fp) { + printf(_("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno)); + return 1; + } + + while (!feof(fp)) { + if (!fgets(value, LINE_LEN, fp)) + continue; + value[LINE_LEN - 1] = '\0'; + if (strlen(value) < (LINE_LEN - 2)) + continue; + if (strstr(value, "cpu ")) + continue; + if (sscanf(value, "cpu%d ", &cpunr) != 1) + continue; + if (cpunr > ret) + ret = cpunr; + } + fclose(fp); + + /* cpu count starts from 0, on error return 1 (UP) */ + return (ret+1); +} + + +static void proc_cpufreq_output(void) +{ + unsigned int cpu, nr_cpus; + struct cpufreq_policy *policy; + unsigned int min_pctg = 0; + unsigned int max_pctg = 0; + unsigned long min, max; + + printf(_(" minimum CPU frequency - maximum CPU frequency - governor\n")); + + nr_cpus = count_cpus(); + for (cpu=0; cpu < nr_cpus; cpu++) { + policy = cpufreq_get_policy(cpu); + if (!policy) + continue; + + if (cpufreq_get_hardware_limits(cpu, &min, &max)) { + max = 0; + } else { + min_pctg = (policy->min * 100) / max; + max_pctg = (policy->max * 100) / max; + } + printf("CPU%3d %9lu kHz (%3d %%) - %9lu kHz (%3d %%) - %s\n", + cpu , policy->min, max ? min_pctg : 0, policy->max, max ? max_pctg : 0, policy->governor); + + cpufreq_put_policy(policy); + } +} + +static void print_speed(unsigned long speed) +{ + unsigned long tmp; + + if (speed > 1000000) { + tmp = speed % 10000; + if (tmp >= 5000) + speed += 10000; + printf ("%u.%02u GHz", ((unsigned int) speed/1000000), + ((unsigned int) (speed%1000000)/10000)); + } else if (speed > 100000) { + tmp = speed % 1000; + if (tmp >= 500) + speed += 1000; + printf ("%u MHz", ((unsigned int) speed / 1000)); + } else if (speed > 1000) { + tmp = speed % 100; + if (tmp >= 50) + speed += 100; + printf ("%u.%01u MHz", ((unsigned int) speed/1000), + ((unsigned int) (speed%1000)/100)); + } else + printf ("%lu kHz", speed); + + return; +} + +static void print_duration(unsigned long duration) +{ + unsigned long tmp; + + if (duration > 1000000) { + tmp = duration % 10000; + if (tmp >= 5000) + duration += 10000; + printf ("%u.%02u ms", ((unsigned int) duration/1000000), + ((unsigned int) (duration%1000000)/10000)); + } else if (duration > 100000) { + tmp = duration % 1000; + if (tmp >= 500) + duration += 1000; + printf ("%u us", ((unsigned int) duration / 1000)); + } else if (duration > 1000) { + tmp = duration % 100; + if (tmp >= 50) + duration += 100; + printf ("%u.%01u us", ((unsigned int) duration/1000), + ((unsigned int) (duration%1000)/100)); + } else + printf ("%lu ns", duration); + + return; +} + +/* --boost / -b */ + +static int get_boost_mode(unsigned int cpu) { + int support, active, b_states = 0, ret, pstate_no, i; + /* ToDo: Make this more global */ + unsigned long pstates[MAX_HW_PSTATES] = {0,}; + + if (cpupower_cpu_info.vendor != X86_VENDOR_AMD && + cpupower_cpu_info.vendor != X86_VENDOR_INTEL) + return 0; + + ret = cpufreq_has_boost_support(cpu, &support, &active, &b_states); + if (ret) { + printf(_("Error while evaluating Boost Capabilities" + " on CPU %d -- are you root?\n"), cpu); + return ret; + } + /* P state changes via MSR are identified via cpuid 80000007 + on Intel and AMD, but we assume boost capable machines can do that + if (cpuid_eax(0x80000000) >= 0x80000007 + && (cpuid_edx(0x80000007) & (1 << 7))) + */ + + printf(_(" boost state support: \n")); + + printf(_(" Supported: %s\n"), support ? _("yes") : _("no")); + printf(_(" Active: %s\n"), active ? _("yes") : _("no")); + + /* ToDo: Only works for AMD for now... */ + + if (cpupower_cpu_info.vendor == X86_VENDOR_AMD && + cpupower_cpu_info.family >= 0x10) { + ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states, + pstates, &pstate_no); + if (ret) + return ret; + } else + return 0; + + printf(_(" Boost States: %d\n"), b_states); + printf(_(" Total States: %d\n"), pstate_no); + for (i = 0; i < pstate_no; i++) { + if (i < b_states) + printf(_(" Pstate-Pb%d: %luMHz (boost state)\n"), + i, pstates[i]); + else + printf(_(" Pstate-P%d: %luMHz\n"), + i - b_states, pstates[i]); + } + return 0; +} + +static void debug_output_one(unsigned int cpu) +{ + char *driver; + struct cpufreq_affected_cpus *cpus; + struct cpufreq_available_frequencies *freqs; + unsigned long min, max, freq_kernel, freq_hardware; + unsigned long total_trans, latency; + unsigned long long total_time; + struct cpufreq_policy *policy; + struct cpufreq_available_governors * governors; + struct cpufreq_stats *stats; + + if (cpufreq_cpu_exists(cpu)) { + return; + } + + freq_kernel = cpufreq_get_freq_kernel(cpu); + freq_hardware = cpufreq_get_freq_hardware(cpu); + + driver = cpufreq_get_driver(cpu); + if (!driver) { + printf(_(" no or unknown cpufreq driver is active on this CPU\n")); + } else { + printf(_(" driver: %s\n"), driver); + cpufreq_put_driver(driver); + } + + cpus = cpufreq_get_related_cpus(cpu); + if (cpus) { + printf(_(" CPUs which run at the same hardware frequency: ")); + while (cpus->next) { + printf("%d ", cpus->cpu); + cpus = cpus->next; + } + printf("%d\n", cpus->cpu); + cpufreq_put_related_cpus(cpus); + } + + cpus = cpufreq_get_affected_cpus(cpu); + if (cpus) { + printf(_(" CPUs which need to have their frequency coordinated by software: ")); + while (cpus->next) { + printf("%d ", cpus->cpu); + cpus = cpus->next; + } + printf("%d\n", cpus->cpu); + cpufreq_put_affected_cpus(cpus); + } + + latency = cpufreq_get_transition_latency(cpu); + if (latency) { + printf(_(" maximum transition latency: ")); + print_duration(latency); + printf(".\n"); + } + + if (!(cpufreq_get_hardware_limits(cpu, &min, &max))) { + printf(_(" hardware limits: ")); + print_speed(min); + printf(" - "); + print_speed(max); + printf("\n"); + } + + freqs = cpufreq_get_available_frequencies(cpu); + if (freqs) { + printf(_(" available frequency steps: ")); + while (freqs->next) { + print_speed(freqs->frequency); + printf(", "); + freqs = freqs->next; + } + print_speed(freqs->frequency); + printf("\n"); + cpufreq_put_available_frequencies(freqs); + } + + governors = cpufreq_get_available_governors(cpu); + if (governors) { + printf(_(" available cpufreq governors: ")); + while (governors->next) { + printf("%s, ", governors->governor); + governors = governors->next; + } + printf("%s\n", governors->governor); + cpufreq_put_available_governors(governors); + } + + policy = cpufreq_get_policy(cpu); + if (policy) { + printf(_(" current policy: frequency should be within ")); + print_speed(policy->min); + printf(_(" and ")); + print_speed(policy->max); + + printf(".\n "); + printf(_("The governor \"%s\" may" + " decide which speed to use\n within this range.\n"), + policy->governor); + cpufreq_put_policy(policy); + } + + if (freq_kernel || freq_hardware) { + printf(_(" current CPU frequency is ")); + if (freq_hardware) { + print_speed(freq_hardware); + printf(_(" (asserted by call to hardware)")); + } + else + print_speed(freq_kernel); + printf(".\n"); + } + stats = cpufreq_get_stats(cpu, &total_time); + if (stats) { + printf(_(" cpufreq stats: ")); + while (stats) { + print_speed(stats->frequency); + printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time); + stats = stats->next; + if (stats) + printf(", "); + } + cpufreq_put_stats(stats); + total_trans = cpufreq_get_transitions(cpu); + if (total_trans) + printf(" (%lu)\n", total_trans); + else + printf("\n"); + } + get_boost_mode(cpu); + +} + +/* --freq / -f */ + +static int get_freq_kernel(unsigned int cpu, unsigned int human) { + unsigned long freq = cpufreq_get_freq_kernel(cpu); + if (!freq) + return -EINVAL; + if (human) { + print_speed(freq); + printf("\n"); + } else + printf("%lu\n", freq); + return 0; +} + + +/* --hwfreq / -w */ + +static int get_freq_hardware(unsigned int cpu, unsigned int human) { + unsigned long freq = cpufreq_get_freq_hardware(cpu); + if (!freq) + return -EINVAL; + if (human) { + print_speed(freq); + printf("\n"); + } else + printf("%lu\n", freq); + return 0; +} + +/* --hwlimits / -l */ + +static int get_hardware_limits(unsigned int cpu) { + unsigned long min, max; + if (cpufreq_get_hardware_limits(cpu, &min, &max)) + return -EINVAL; + printf("%lu %lu\n", min, max); + return 0; +} + +/* --driver / -d */ + +static int get_driver(unsigned int cpu) { + char *driver = cpufreq_get_driver(cpu); + if (!driver) + return -EINVAL; + printf("%s\n", driver); + cpufreq_put_driver(driver); + return 0; +} + +/* --policy / -p */ + +static int get_policy(unsigned int cpu) { + struct cpufreq_policy *policy = cpufreq_get_policy(cpu); + if (!policy) + return -EINVAL; + printf("%lu %lu %s\n", policy->min, policy->max, policy->governor); + cpufreq_put_policy(policy); + return 0; +} + +/* --governors / -g */ + +static int get_available_governors(unsigned int cpu) { + struct cpufreq_available_governors *governors = cpufreq_get_available_governors(cpu); + if (!governors) + return -EINVAL; + + while (governors->next) { + printf("%s ", governors->governor); + governors = governors->next; + } + printf("%s\n", governors->governor); + cpufreq_put_available_governors(governors); + return 0; +} + + +/* --affected-cpus / -a */ + +static int get_affected_cpus(unsigned int cpu) { + struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu); + if (!cpus) + return -EINVAL; + + while (cpus->next) { + printf("%d ", cpus->cpu); + cpus = cpus->next; + } + printf("%d\n", cpus->cpu); + cpufreq_put_affected_cpus(cpus); + return 0; +} + +/* --related-cpus / -r */ + +static int get_related_cpus(unsigned int cpu) { + struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu); + if (!cpus) + return -EINVAL; + + while (cpus->next) { + printf("%d ", cpus->cpu); + cpus = cpus->next; + } + printf("%d\n", cpus->cpu); + cpufreq_put_related_cpus(cpus); + return 0; +} + +/* --stats / -s */ + +static int get_freq_stats(unsigned int cpu, unsigned int human) { + unsigned long total_trans = cpufreq_get_transitions(cpu); + unsigned long long total_time; + struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time); + while (stats) { + if (human) { + print_speed(stats->frequency); + printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time); + } + else + printf("%lu:%llu", stats->frequency, stats->time_in_state); + stats = stats->next; + if (stats) + printf(", "); + } + cpufreq_put_stats(stats); + if (total_trans) + printf(" (%lu)\n", total_trans); + return 0; +} + +/* --latency / -y */ + +static int get_latency(unsigned int cpu, unsigned int human) { + unsigned long latency = cpufreq_get_transition_latency(cpu); + if (!latency) + return -EINVAL; + + if (human) { + print_duration(latency); + printf("\n"); + } else + printf("%lu\n", latency); + return 0; +} + +void freq_info_help(void) { + printf(_("Usage: cpupower freqinfo [options]\n")); + printf(_("Options:\n")); + printf(_(" -e, --debug Prints out debug information [default]\n")); + printf(_(" -f, --freq Get frequency the CPU currently runs at, according\n" + " to the cpufreq core *\n")); + printf(_(" -w, --hwfreq Get frequency the CPU currently runs at, by reading\n" + " it from hardware (only available to root) *\n")); + printf(_(" -l, --hwlimits Determine the minimum and maximum CPU frequency allowed *\n")); + printf(_(" -d, --driver Determines the used cpufreq kernel driver *\n")); + printf(_(" -p, --policy Gets the currently used cpufreq policy *\n")); + printf(_(" -g, --governors Determines available cpufreq governors *\n")); + printf(_(" -r, --related-cpus Determines which CPUs run at the same hardware frequency *\n")); + printf(_(" -a, --affected-cpus Determines which CPUs need to have their frequency\n" + " coordinated by software *\n")); + printf(_(" -s, --stats Shows cpufreq statistics if available\n")); + printf(_(" -y, --latency Determines the maximum latency on CPU frequency changes *\n")); + printf(_(" -b, --boost Checks for turbo or boost modes *\n")); + printf(_(" -o, --proc Prints out information like provided by the /proc/cpufreq\n" + " interface in 2.4. and early 2.6. kernels\n")); + printf(_(" -m, --human human-readable output for the -f, -w, -s and -y parameters\n")); + printf(_(" -h, --help Prints out this screen\n")); + + printf("\n"); + printf(_("If no argument is given, full output about\n" + "cpufreq is printed which is useful e.g. for reporting bugs.\n\n")); + printf(_("By default info of CPU 0 is shown which can be overridden \n" + "with the cpupower --cpu main command option.\n")); +} + +static struct option info_opts[] = { + { .name="debug", .has_arg=no_argument, .flag=NULL, .val='e'}, + { .name="boost", .has_arg=no_argument, .flag=NULL, .val='b'}, + { .name="freq", .has_arg=no_argument, .flag=NULL, .val='f'}, + { .name="hwfreq", .has_arg=no_argument, .flag=NULL, .val='w'}, + { .name="hwlimits", .has_arg=no_argument, .flag=NULL, .val='l'}, + { .name="driver", .has_arg=no_argument, .flag=NULL, .val='d'}, + { .name="policy", .has_arg=no_argument, .flag=NULL, .val='p'}, + { .name="governors", .has_arg=no_argument, .flag=NULL, .val='g'}, + { .name="related-cpus", .has_arg=no_argument, .flag=NULL, .val='r'}, + { .name="affected-cpus",.has_arg=no_argument, .flag=NULL, .val='a'}, + { .name="stats", .has_arg=no_argument, .flag=NULL, .val='s'}, + { .name="latency", .has_arg=no_argument, .flag=NULL, .val='y'}, + { .name="proc", .has_arg=no_argument, .flag=NULL, .val='o'}, + { .name="human", .has_arg=no_argument, .flag=NULL, .val='m'}, + { .name="help", .has_arg=no_argument, .flag=NULL, .val='h'}, + { }, +}; + +int cmd_freq_info(int argc, char **argv) +{ + extern char *optarg; + extern int optind, opterr, optopt; + int ret = 0, cont = 1; + unsigned int cpu = 0; + unsigned int human = 0; + int output_param = 0; + + do { + ret = getopt_long(argc, argv, "hoefwldpgrasmyb", info_opts, NULL); + switch (ret) { + case '?': + output_param = '?'; + cont = 0; + break; + case 'h': + output_param = 'h'; + cont = 0; + break; + case -1: + cont = 0; + break; + case 'b': + case 'o': + case 'a': + case 'r': + case 'g': + case 'p': + case 'd': + case 'l': + case 'w': + case 'f': + case 'e': + case 's': + case 'y': + if (output_param) { + output_param = -1; + cont = 0; + break; + } + output_param = ret; + break; + case 'm': + if (human) { + output_param = -1; + cont = 0; + break; + } + human = 1; + break; + default: + fprintf(stderr, "invalid or unknown argument\n"); + return EXIT_FAILURE; + } + } while(cont); + + switch (output_param) { + case 'o': + if (!bitmask_isallclear(cpus_chosen)) { + printf(_("The argument passed to this tool can't be " + "combined with passing a --cpu argument\n")); + return -EINVAL; + } + break; + case 0: + output_param = 'e'; + } + + ret = 0; + + /* Default is: show output of CPU 0 only */ + if (bitmask_isallclear(cpus_chosen)) + bitmask_setbit(cpus_chosen, 0); + + switch (output_param) { + case -1: + printf(_("You can't specify more than one --cpu parameter and/or\n" + "more than one output-specific argument\n")); + return -EINVAL; + case '?': + printf(_("invalid or unknown argument\n")); + freq_info_help(); + return -EINVAL; + case 'h': + freq_info_help(); + return EXIT_SUCCESS; + case 'o': + proc_cpufreq_output(); + return EXIT_SUCCESS; + } + + for (cpu = bitmask_first(cpus_chosen); + cpu <= bitmask_last(cpus_chosen); cpu++) { + + if (!bitmask_isbitset(cpus_chosen, cpu)) + continue; + if (cpufreq_cpu_exists(cpu)) { + printf(_("couldn't analyze CPU %d as it doesn't seem to be present\n"), cpu); + continue; + } + printf(_("analyzing CPU %d:\n"), cpu); + + switch (output_param) { + case 'b': + get_boost_mode(cpu); + break; + case 'e': + debug_output_one(cpu); + break; + case 'a': + ret = get_affected_cpus(cpu); + break; + case 'r': + ret = get_related_cpus(cpu); + break; + case 'g': + ret = get_available_governors(cpu); + break; + case 'p': + ret = get_policy(cpu); + break; + case 'd': + ret = get_driver(cpu); + break; + case 'l': + ret = get_hardware_limits(cpu); + break; + case 'w': + ret = get_freq_hardware(cpu, human); + break; + case 'f': + ret = get_freq_kernel(cpu, human); + break; + case 's': + ret = get_freq_stats(cpu, human); + break; + case 'y': + ret = get_latency(cpu, human); + break; + } + if (ret) + return (ret); + } + return ret; +} diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c new file mode 100644 index 000000000000..d415b6b52a09 --- /dev/null +++ b/tools/power/cpupower/utils/cpufreq-set.c @@ -0,0 +1,357 @@ +/* + * (C) 2004-2009 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "cpufreq.h" +#include "helpers/helpers.h" + +#define NORM_FREQ_LEN 32 + +void freq_set_help(void) +{ + printf(_("Usage: cpupower frequency-set [options]\n")); + printf(_("Options:\n")); + printf(_(" -d FREQ, --min FREQ new minimum CPU frequency the governor may select\n")); + printf(_(" -u FREQ, --max FREQ new maximum CPU frequency the governor may select\n")); + printf(_(" -g GOV, --governor GOV new cpufreq governor\n")); + printf(_(" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n" + " governor to be available and loaded\n")); + printf(_(" -r, --related Switches all hardware-related CPUs\n")); + printf(_(" -h, --help Prints out this screen\n")); + printf("\n"); + printf(_("Notes:\n" + "1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n")); + printf(_("2. The -f FREQ, --freq FREQ parameter cannot be combined with any other parameter\n" + " except the -c CPU, --cpu CPU parameter\n" + "3. FREQuencies can be passed in Hz, kHz (default), MHz, GHz, or THz\n" + " by postfixing the value with the wanted unit name, without any space\n" + " (FREQuency in kHz =^ Hz * 0.001 =^ MHz * 1000 =^ GHz * 1000000).\n")); + +} + +static struct option set_opts[] = { + { .name="min", .has_arg=required_argument, .flag=NULL, .val='d'}, + { .name="max", .has_arg=required_argument, .flag=NULL, .val='u'}, + { .name="governor", .has_arg=required_argument, .flag=NULL, .val='g'}, + { .name="freq", .has_arg=required_argument, .flag=NULL, .val='f'}, + { .name="help", .has_arg=no_argument, .flag=NULL, .val='h'}, + { .name="related", .has_arg=no_argument, .flag=NULL, .val='r'}, + { }, +}; + +static void print_error(void) +{ + printf(_("Error setting new values. Common errors:\n" + "- Do you have proper administration rights? (super-user?)\n" + "- Is the governor you requested available and modprobed?\n" + "- Trying to set an invalid policy?\n" + "- Trying to set a specific frequency, but userspace governor is not available,\n" + " for example because of hardware which cannot be set to a specific frequency\n" + " or because the userspace governor isn't loaded?\n")); +}; + +struct freq_units { + char* str_unit; + int power_of_ten; +}; + +const struct freq_units def_units[] = { + {"hz", -3}, + {"khz", 0}, /* default */ + {"mhz", 3}, + {"ghz", 6}, + {"thz", 9}, + {NULL, 0} +}; + +static void print_unknown_arg(void) +{ + printf(_("invalid or unknown argument\n")); + freq_set_help(); +} + +static unsigned long string_to_frequency(const char *str) +{ + char normalized[NORM_FREQ_LEN]; + const struct freq_units *unit; + const char *scan; + char *end; + unsigned long freq; + int power = 0, match_count = 0, i, cp, pad; + + while (*str == '0') + str++; + + for (scan = str; isdigit(*scan) || *scan == '.'; scan++) { + if (*scan == '.' && match_count == 0) + match_count = 1; + else if (*scan == '.' && match_count == 1) + return 0; + } + + if (*scan) { + match_count = 0; + for (unit = def_units; unit->str_unit; unit++) { + for (i = 0; + scan[i] && tolower(scan[i]) == unit->str_unit[i]; + ++i) + continue; + if (scan[i]) + continue; + match_count++; + power = unit->power_of_ten; + } + if (match_count != 1) + return 0; + } + + /* count the number of digits to be copied */ + for (cp = 0; isdigit(str[cp]); cp++) + continue; + + if (str[cp] == '.') { + while (power > -1 && isdigit(str[cp+1])) + cp++, power--; + } + if (power >= -1) /* not enough => pad */ + pad = power + 1; + else /* to much => strip */ + pad = 0, cp += power + 1; + /* check bounds */ + if (cp <= 0 || cp + pad > NORM_FREQ_LEN - 1) + return 0; + + /* copy digits */ + for (i = 0; i < cp; i++, str++) { + if (*str == '.') + str++; + normalized[i] = *str; + } + /* and pad */ + for (; i < cp + pad; i++) + normalized[i] = '0'; + + /* round up, down ? */ + match_count = (normalized[i-1] >= '5'); + /* and drop the decimal part */ + normalized[i-1] = 0; /* cp > 0 && pad >= 0 ==> i > 0 */ + + /* final conversion (and applying rounding) */ + errno = 0; + freq = strtoul(normalized, &end, 10); + if (errno) + return 0; + else { + if (match_count && freq != ULONG_MAX) + freq++; + return freq; + } +} + +static int do_new_policy(unsigned int cpu, struct cpufreq_policy *new_pol) +{ + struct cpufreq_policy *cur_pol = cpufreq_get_policy(cpu); + int ret; + + if (!cur_pol) { + printf(_("wrong, unknown or unhandled CPU?\n")); + return -EINVAL; + } + + if (!new_pol->min) + new_pol->min = cur_pol->min; + + if (!new_pol->max) + new_pol->max = cur_pol->max; + + if (!new_pol->governor) + new_pol->governor = cur_pol->governor; + + ret = cpufreq_set_policy(cpu, new_pol); + + cpufreq_put_policy(cur_pol); + + return ret; +} + + +static int do_one_cpu(unsigned int cpu, struct cpufreq_policy *new_pol, + unsigned long freq, unsigned int pc) +{ + switch (pc) { + case 0: + return cpufreq_set_frequency(cpu, freq); + + case 1: + /* if only one value of a policy is to be changed, we can + * use a "fast path". + */ + if (new_pol->min) + return cpufreq_modify_policy_min(cpu, new_pol->min); + else if (new_pol->max) + return cpufreq_modify_policy_max(cpu, new_pol->max); + else if (new_pol->governor) + return cpufreq_modify_policy_governor(cpu, new_pol->governor); + + default: + /* slow path */ + return do_new_policy(cpu, new_pol); + } +} + +int cmd_freq_set(int argc, char **argv) +{ + extern char *optarg; + extern int optind, opterr, optopt; + int ret = 0, cont = 1; + int double_parm = 0, related = 0, policychange = 0; + unsigned long freq = 0; + char gov[20]; + unsigned int cpu; + + struct cpufreq_policy new_pol = { + .min = 0, + .max = 0, + .governor = NULL, + }; + + /* parameter parsing */ + do { + ret = getopt_long(argc, argv, "d:u:g:f:hr", set_opts, NULL); + switch (ret) { + case '?': + print_unknown_arg(); + return -EINVAL; + case 'h': + freq_set_help(); + return 0; + case -1: + cont = 0; + break; + case 'r': + if (related) + double_parm++; + related++; + break; + case 'd': + if (new_pol.min) + double_parm++; + policychange++; + new_pol.min = string_to_frequency(optarg); + if (new_pol.min == 0) { + print_unknown_arg(); + return -EINVAL; + } + break; + case 'u': + if (new_pol.max) + double_parm++; + policychange++; + new_pol.max = string_to_frequency(optarg); + if (new_pol.max == 0) { + print_unknown_arg(); + return -EINVAL; + } + break; + case 'f': + if (freq) + double_parm++; + freq = string_to_frequency(optarg); + if (freq == 0) { + print_unknown_arg(); + return -EINVAL; + } + break; + case 'g': + if (new_pol.governor) + double_parm++; + policychange++; + if ((strlen(optarg) < 3) || (strlen(optarg) > 18)) { + print_unknown_arg(); + return -EINVAL; + } + if ((sscanf(optarg, "%s", gov)) != 1) { + print_unknown_arg(); + return -EINVAL; + } + new_pol.governor = gov; + break; + } + } while(cont); + + /* parameter checking */ + if (double_parm) { + printf("the same parameter was passed more than once\n"); + return -EINVAL; + } + + if (freq && policychange) { + printf(_("the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n" + "-g/--governor parameters\n")); + return -EINVAL; + } + + if (!freq && !policychange) { + printf(_("At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n" + "-g/--governor must be passed\n")); + return -EINVAL; + } + + /* Default is: set all CPUs */ + if (bitmask_isallclear(cpus_chosen)) + bitmask_setall(cpus_chosen); + + /* Also set frequency settings for related CPUs if -r is passed */ + if (related) { + for (cpu = bitmask_first(cpus_chosen); + cpu <= bitmask_last(cpus_chosen); cpu++) { + struct cpufreq_affected_cpus *cpus; + + if (!bitmask_isbitset(cpus_chosen, cpu) || + cpufreq_cpu_exists(cpu)) + continue; + + cpus = cpufreq_get_related_cpus(cpu); + if (!cpus) + break; + while (cpus->next) { + bitmask_setbit(cpus_chosen, cpus->cpu); + cpus = cpus->next; + } + cpufreq_put_related_cpus(cpus); + } + } + + + /* loop over CPUs */ + for (cpu = bitmask_first(cpus_chosen); + cpu <= bitmask_last(cpus_chosen); cpu++) { + + if (!bitmask_isbitset(cpus_chosen, cpu) || + cpufreq_cpu_exists(cpu)) + continue; + + printf(_("Setting cpu: %d\n"), cpu); + ret = do_one_cpu(cpu, &new_pol, freq, policychange); + if (ret) + break; + } + + if (ret) + print_error(); + + return ret; +} diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c new file mode 100644 index 000000000000..635468224e74 --- /dev/null +++ b/tools/power/cpupower/utils/cpuidle-info.c @@ -0,0 +1,245 @@ +/* + * (C) 2004-2009 Dominik Brodowski + * (C) 2010 Thomas Renninger + * + * Licensed under the terms of the GNU GPL License version 2. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "helpers/helpers.h" +#include "helpers/sysfs.h" +#include "helpers/bitmask.h" + +#define LINE_LEN 10 + +static void cpuidle_cpu_output(unsigned int cpu, int verbose) +{ + int idlestates, idlestate; + char *tmp; + + printf(_ ("Analyzing CPU %d:\n"), cpu); + + idlestates = sysfs_get_idlestate_count(cpu); + if (idlestates == 0) { + printf(_("CPU %u: No idle states\n"), cpu); + return; + } + else if (idlestates <= 0) { + printf(_("CPU %u: Can't read idle state info\n"), cpu); + return; + } + tmp = sysfs_get_idlestate_name(cpu, idlestates - 1); + if (!tmp) { + printf(_("Could not determine max idle state %u\n"), + idlestates - 1); + return; + } + + printf(_("Number of idle states: %d\n"), idlestates); + + printf(_("Available idle states:")); + for (idlestate = 1; idlestate < idlestates; idlestate++) { + tmp = sysfs_get_idlestate_name(cpu, idlestate); + if (!tmp) + continue; + printf(" %s", tmp); + free(tmp); + } + printf("\n"); + + if (!verbose) + return; + + for (idlestate = 1; idlestate < idlestates; idlestate++) { + tmp = sysfs_get_idlestate_name(cpu, idlestate); + if (!tmp) + continue; + printf("%s:\n", tmp); + free(tmp); + + tmp = sysfs_get_idlestate_desc(cpu, idlestate); + if (!tmp) + continue; + printf(_("Flags/Description: %s\n"), tmp); + free(tmp); + + printf(_("Latency: %lu\n"), + sysfs_get_idlestate_latency(cpu, idlestate)); + printf(_("Usage: %lu\n"), + sysfs_get_idlestate_usage(cpu, idlestate)); + printf(_("Duration: %llu\n"), + sysfs_get_idlestate_time(cpu, idlestate)); + } + printf("\n"); +} + +static void cpuidle_general_output(void) +{ + char *tmp; + + tmp = sysfs_get_cpuidle_driver(); + if (!tmp) { + printf(_("Could not determine cpuidle driver\n")); + return; + } + + printf(_("CPUidle driver: %s\n"), tmp); + free (tmp); + + tmp = sysfs_get_cpuidle_governor(); + if (!tmp) { + printf(_("Could not determine cpuidle governor\n")); + return; + } + + printf(_("CPUidle governor: %s\n"), tmp); + free (tmp); +} + +static void proc_cpuidle_cpu_output(unsigned int cpu) +{ + long max_allowed_cstate = 2000000000; + int cstates, cstate; + + cstates = sysfs_get_idlestate_count(cpu); + if (cstates == 0) { + /* + * Go on and print same useless info as you'd see with + * cat /proc/acpi/processor/../power + * printf(_("CPU %u: No C-states available\n"), cpu); + * return; + */ + } + else if (cstates <= 0) { + printf(_("CPU %u: Can't read C-state info\n"), cpu); + return; + } + /* printf("Cstates: %d\n", cstates); */ + + printf(_("active state: C0\n")); + printf(_("max_cstate: C%u\n"), cstates-1); + printf(_("maximum allowed latency: %lu usec\n"), max_allowed_cstate); + printf(_("states:\t\n")); + for (cstate = 1; cstate < cstates; cstate++) { + printf(_(" C%d: " + "type[C%d] "), cstate, cstate); + printf(_("promotion[--] demotion[--] ")); + printf(_("latency[%03lu] "), + sysfs_get_idlestate_latency(cpu, cstate)); + printf(_("usage[%08lu] "), + sysfs_get_idlestate_usage(cpu, cstate)); + printf(_("duration[%020Lu] \n"), + sysfs_get_idlestate_time(cpu, cstate)); + } +} + +/* --freq / -f */ + +void idle_info_help(void) { + printf(_ ("Usage: cpupower idleinfo [options]\n")); + printf(_ ("Options:\n")); + printf(_ (" -s, --silent Only show general C-state information\n")); + printf(_ (" -o, --proc Prints out information like provided by the /proc/acpi/processor/*/power\n" + " interface in older kernels\n")); + printf(_ (" -h, --help Prints out this screen\n")); + + printf("\n"); +} + +static struct option info_opts[] = { + { .name="silent", .has_arg=no_argument, .flag=NULL, .val='s'}, + { .name="proc", .has_arg=no_argument, .flag=NULL, .val='o'}, + { .name="help", .has_arg=no_argument, .flag=NULL, .val='h'}, + { }, +}; + +static inline void cpuidle_exit(int fail) +{ + idle_info_help(); + exit(EXIT_FAILURE); +} + +int cmd_idle_info(int argc, char **argv) +{ + extern char *optarg; + extern int optind, opterr, optopt; + int ret = 0, cont = 1, output_param = 0, verbose = 1; + unsigned int cpu = 0; + + do { + ret = getopt_long(argc, argv, "hos", info_opts, NULL); + if (ret == -1) + break; + switch (ret) { + case '?': + output_param = '?'; + cont = 0; + break; + case 'h': + output_param = 'h'; + cont = 0; + break; + case 's': + verbose = 0; + break; + case -1: + cont = 0; + break; + case 'o': + if (output_param) { + output_param = -1; + cont = 0; + break; + } + output_param = ret; + break; + } + } while(cont); + + switch (output_param) { + case -1: + printf(_("You can't specify more than one " + "output-specific argument\n")); + cpuidle_exit(EXIT_FAILURE); + case '?': + printf(_("invalid or unknown argument\n")); + cpuidle_exit(EXIT_FAILURE); + case 'h': + cpuidle_exit(EXIT_SUCCESS); + } + + /* Default is: show output of CPU 0 only */ + if (bitmask_isallclear(cpus_chosen)) + bitmask_setbit(cpus_chosen, 0); + + if (output_param == 0) + cpuidle_general_output(); + + for (cpu = bitmask_first(cpus_chosen); + cpu <= bitmask_last(cpus_chosen); cpu++) { + + if (!bitmask_isbitset(cpus_chosen, cpu) || + cpufreq_cpu_exists(cpu)) + continue; + + switch (output_param) { + + case 'o': + proc_cpuidle_cpu_output(cpu); + break; + case 0: + printf("\n"); + cpuidle_cpu_output(cpu, verbose); + break; + } + } + return (EXIT_SUCCESS); +} diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c new file mode 100644 index 000000000000..7add04ccbad4 --- /dev/null +++ b/tools/power/cpupower/utils/cpupower-info.c @@ -0,0 +1,154 @@ +/* + * (C) 2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include "helpers/helpers.h" +#include "helpers/sysfs.h" + +void info_help(void) +{ + printf(_("Usage: cpupower info [ -b ] [ -m ] [ -s ]\n")); + printf(_("Options:\n")); + printf(_(" -b, --perf-bias Gets CPU's power vs performance policy on some\n" + " Intel models [0-15], see manpage for details\n")); + printf(_(" -m, --sched-mc Gets the kernel's multi core scheduler policy.\n")); + printf(_(" -s, --sched-smt Gets the kernel's thread sibling scheduler policy.\n")); + printf(_(" -h, --help Prints out this screen\n")); + printf(_("\nPassing no option will show all info, by default only on core 0\n")); + printf("\n"); +} + +static struct option set_opts[] = { + { .name="perf-bias", .has_arg=optional_argument, .flag=NULL, .val='b'}, + { .name="sched-mc", .has_arg=optional_argument, .flag=NULL, .val='m'}, + { .name="sched-smt", .has_arg=optional_argument, .flag=NULL, .val='s'}, + { .name="help", .has_arg=no_argument, .flag=NULL, .val='h'}, + { }, +}; + +static void print_wrong_arg_exit(void) +{ + printf(_("invalid or unknown argument\n")); + info_help(); + exit(EXIT_FAILURE); +} + +int cmd_info(int argc, char **argv) +{ + extern char *optarg; + extern int optind, opterr, optopt; + unsigned int cpu; + + union { + struct { + int sched_mc:1; + int sched_smt:1; + int perf_bias:1; + }; + int params; + + } params = {}; + int ret = 0; + + setlocale(LC_ALL, ""); + textdomain (PACKAGE); + + /* parameter parsing */ + while ((ret = getopt_long(argc, argv, "msbh", set_opts, NULL)) != -1) { + switch (ret) { + case 'h': + info_help(); + return 0; + case 'b': + if (params.perf_bias) + print_wrong_arg_exit(); + params.perf_bias = 1; + break; + case 'm': + if (params.sched_mc) + print_wrong_arg_exit(); + params.sched_mc = 1; + break; + case 's': + if (params.sched_smt) + print_wrong_arg_exit(); + params.sched_smt = 1; + break; + default: + print_wrong_arg_exit(); + } + }; + + if (!params.params) + params.params = 0x7; + + /* Default is: show output of CPU 0 only */ + if (bitmask_isallclear(cpus_chosen)) + bitmask_setbit(cpus_chosen, 0); + + if (params.sched_mc) { + ret = sysfs_get_sched("mc"); + printf(_("System's multi core scheduler setting: ")); + if (ret < 0) + /* if sysfs file is missing it's: errno == ENOENT */ + printf(_("not supported\n")); + else + printf("%d\n", ret); + } + if (params.sched_smt) { + ret = sysfs_get_sched("smt"); + printf(_("System's thread sibling scheduler setting: ")); + if (ret < 0) + /* if sysfs file is missing it's: errno == ENOENT */ + printf(_("not supported\n")); + else + printf("%d\n", ret); + } + + /* Add more per cpu options here */ + if (!params.perf_bias) + return ret; + + if (params.perf_bias) { + if (!run_as_root) { + params.perf_bias = 0; + printf (_("Intel's performance bias setting needs root privileges\n")); + } else if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) { + printf(_("System does not support Intel's performance" + " bias setting\n")); + params.perf_bias = 0; + } + } + + /* loop over CPUs */ + for (cpu = bitmask_first(cpus_chosen); + cpu <= bitmask_last(cpus_chosen); cpu++) { + + if (!bitmask_isbitset(cpus_chosen, cpu) || + cpufreq_cpu_exists(cpu)) + continue; + + printf(_("analyzing CPU %d:\n"), cpu); + + if (params.perf_bias) { + ret = msr_intel_get_perf_bias(cpu); + if (ret < 0) { + printf(_("Could not read perf-bias value\n")); + break; + } else + printf(_("perf-bias: %d\n"), ret); + } + } + return ret; +} diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c new file mode 100644 index 000000000000..3f807bc7a567 --- /dev/null +++ b/tools/power/cpupower/utils/cpupower-set.c @@ -0,0 +1,153 @@ +/* + * (C) 2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include "helpers/helpers.h" +#include "helpers/sysfs.h" +#include "helpers/bitmask.h" + +void set_help(void) +{ + printf(_("Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n")); + printf(_("Options:\n")); + printf(_(" -b, --perf-bias [VAL] Sets CPU's power vs performance policy on some\n" + " Intel models [0-15], see manpage for details\n")); + printf(_(" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n")); + printf(_(" -s, --sched-smt [VAL] Sets the kernel's thread sibling scheduler policy.\n")); + printf(_(" -h, --help Prints out this screen\n")); + printf("\n"); +} + +static struct option set_opts[] = { + { .name="perf-bias", .has_arg=optional_argument, .flag=NULL, .val='b'}, + { .name="sched-mc", .has_arg=optional_argument, .flag=NULL, .val='m'}, + { .name="sched-smt", .has_arg=optional_argument, .flag=NULL, .val='s'}, + { .name="help", .has_arg=no_argument, .flag=NULL, .val='h'}, + { }, +}; + +static void print_wrong_arg_exit(void) +{ + printf(_("invalid or unknown argument\n")); + set_help(); + exit(EXIT_FAILURE); +} + +int cmd_set(int argc, char **argv) +{ + extern char *optarg; + extern int optind, opterr, optopt; + unsigned int cpu; + + union { + struct { + int sched_mc:1; + int sched_smt:1; + int perf_bias:1; + }; + int params; + + } params; + int sched_mc = 0, sched_smt = 0, perf_bias = 0; + int ret = 0; + + setlocale(LC_ALL, ""); + textdomain (PACKAGE); + + params.params = 0; + /* parameter parsing */ + while ((ret = getopt_long(argc, argv, "m:s:b:h", set_opts, NULL)) != -1) { + switch (ret) { + case 'h': + set_help(); + return 0; + case 'b': + if (params.perf_bias) + print_wrong_arg_exit(); + perf_bias = atoi(optarg); + if (perf_bias < 0 || perf_bias > 15) { + printf(_("--perf-bias param out " + "of range [0-%d]\n"), 15); + print_wrong_arg_exit(); + } + params.perf_bias = 1; + break; + case 'm': + if (params.sched_mc) + print_wrong_arg_exit(); + sched_mc = atoi(optarg); + if (sched_mc < 0 || sched_mc > 2) { + printf(_("--sched-mc param out " + "of range [0-%d]\n"), 2); + print_wrong_arg_exit(); + } + params.sched_mc = 1; + break; + case 's': + if (params.sched_smt) + print_wrong_arg_exit(); + sched_smt = atoi(optarg); + if (sched_smt < 0 || sched_smt > 2) { + printf(_("--sched-smt param out " + "of range [0-%d]\n"), 2); + print_wrong_arg_exit(); + } + params.sched_smt = 1; + break; + default: + print_wrong_arg_exit(); + } + }; + + if (!params.params) { + set_help(); + return -EINVAL; + } + + if (params.sched_mc) { + ret = sysfs_set_sched("mc", sched_mc); + if (ret) + fprintf(stderr, _("Error setting sched-mc %s\n"), + (ret == -ENODEV) ? "not supported" : ""); + } + if (params.sched_smt) { + ret = sysfs_set_sched("smt", sched_smt); + if (ret) + fprintf(stderr, _("Error setting sched-smt %s\n"), + (ret == -ENODEV) ? "not supported" : ""); + } + + /* Default is: set all CPUs */ + if (bitmask_isallclear(cpus_chosen)) + bitmask_setall(cpus_chosen); + + /* loop over CPUs */ + for (cpu = bitmask_first(cpus_chosen); + cpu <= bitmask_last(cpus_chosen); cpu++) { + + if (!bitmask_isbitset(cpus_chosen, cpu) || + cpufreq_cpu_exists(cpu)) + continue; + + if (params.perf_bias) { + ret = msr_intel_set_perf_bias(cpu, perf_bias); + if (ret) { + fprintf(stderr, _("Error setting perf-bias " + "value on CPU %d\n"), cpu); + break; + } + } + } + return ret; +} diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c new file mode 100644 index 000000000000..b048e5595359 --- /dev/null +++ b/tools/power/cpupower/utils/cpupower.c @@ -0,0 +1,201 @@ +/* + * (C) 2010,2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Ideas taken over from the perf userspace tool (included in the Linus + * kernel git repo): subcommand builtins and param parsing. + */ + +#include +#include +#include +#include + +#include "builtin.h" +#include "helpers/helpers.h" +#include "helpers/bitmask.h" + +struct cmd_struct { + const char *cmd; + int (*main)(int, const char **); + void (*usage)(void); + int needs_root; +}; + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +int cmd_help(int argc, const char **argv); + +/* Global cpu_info object available for all binaries + * Info only retrieved from CPU 0 + * + * Values will be zero/unknown on non X86 archs + */ +struct cpupower_cpu_info cpupower_cpu_info; +int run_as_root; +/* Affected cpus chosen by -c/--cpu param */ +struct bitmask *cpus_chosen; + +#ifdef DEBUG +int be_verbose; +#endif + +static void print_help(void); + +static struct cmd_struct commands[] = { + { "frequency-info", cmd_freq_info, freq_info_help, 0 }, + { "frequency-set", cmd_freq_set, freq_set_help, 1 }, + { "idle-info", cmd_idle_info, idle_info_help, 0 }, + { "set", cmd_set, set_help, 1 }, + { "info", cmd_info, info_help, 0 }, + { "monitor", cmd_monitor, monitor_help, 0 }, + { "help", cmd_help, print_help, 0 }, + // { "bench", cmd_bench, NULL, 1 }, +}; + +int cmd_help(int argc, const char **argv) +{ + unsigned int i; + + if (argc > 1) { + for (i = 0; i < ARRAY_SIZE(commands); i++) { + struct cmd_struct *p = commands + i; + if (strcmp(p->cmd, argv[1])) + continue; + if (p->usage) { + p->usage(); + return EXIT_SUCCESS; + } + } + } + print_help(); + if (argc == 1) + return EXIT_SUCCESS; /* cpupower help */ + return EXIT_FAILURE; +} + +static void print_help(void) +{ + unsigned int i; + +#ifdef DEBUG + printf(_("cpupower [ -d ][ -c cpulist ] subcommand [ARGS]\n")); + printf(_(" -d, --debug May increase output (stderr) on some subcommands\n")); +#else + printf(_("cpupower [ -c cpulist ] subcommand [ARGS]\n")); +#endif + printf(_("cpupower --version\n")); + printf(_("Supported subcommands are:\n")); + for (i = 0; i < ARRAY_SIZE(commands); i++) + printf("\t%s\n", commands[i].cmd); + printf(_("\nSome subcommands can make use of the -c cpulist option.\n")); + printf(_("Look at the general cpupower manpage how to use it\n")); + printf(_("and read up the subcommand's manpage whether it is supported.\n")); + printf(_("\nUse cpupower help subcommand for getting help for above subcommands.\n")); +} + +static void print_version(void) { + printf(PACKAGE " " VERSION "\n"); + printf(_("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT); +} + +static void handle_options(int *argc, const char ***argv) +{ + int ret, x, new_argc = 0; + + if (*argc < 1) + return; + + for (x = 0; x < *argc && ((*argv)[x])[0] == '-'; x++) { + const char *param = (*argv)[x]; + if (!strcmp(param, "-h") || !strcmp(param, "--help")){ + print_help(); + exit(EXIT_SUCCESS); + } else if (!strcmp(param, "-c") || !strcmp(param, "--cpu")){ + if (*argc < 2) { + print_help(); + exit(EXIT_FAILURE); + } + if (!strcmp((*argv)[x+1], "all")) + bitmask_setall(cpus_chosen); + else { + ret = bitmask_parselist( + (*argv)[x+1], cpus_chosen); + if (ret < 0) { + fprintf(stderr, _("Error parsing cpu " + "list\n")); + exit(EXIT_FAILURE); + } + } + x += 1; + /* Cut out param: cpupower -c 1 info -> cpupower info */ + new_argc += 2; + continue; + } else if (!strcmp(param, "-v") || !strcmp(param, "--version")){ + print_version(); + exit(EXIT_SUCCESS); +#ifdef DEBUG + } else if (!strcmp(param, "-d") || !strcmp(param, "--debug")){ + be_verbose = 1; + new_argc ++; + continue; +#endif + } else { + fprintf(stderr, "Unknown option: %s\n", param); + print_help(); + exit(EXIT_FAILURE); + } + } + *argc -= new_argc; + *argv += new_argc; +} + +int main(int argc, const char *argv[]) +{ + const char *cmd; + unsigned int i, ret; + + cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF)); + + argc--; + argv += 1; + + handle_options(&argc, &argv); + + cmd = argv[0]; + + if (argc < 1) { + print_help(); + return EXIT_FAILURE; + } + + setlocale(LC_ALL, ""); + textdomain (PACKAGE); + + /* Turn "perf cmd --help" into "perf help cmd" */ + if (argc > 1 && !strcmp(argv[1], "--help")) { + argv[1] = argv[0]; + argv[0] = cmd = "help"; + } + + get_cpu_info(0, &cpupower_cpu_info); + run_as_root = !getuid(); + + for (i = 0; i < ARRAY_SIZE(commands); i++) { + struct cmd_struct *p = commands + i; + if (strcmp(p->cmd, cmd)) + continue; + if (!run_as_root && p->needs_root) { + fprintf(stderr, _("Subcommand %s needs root " + "privileges\n"), cmd); + return EXIT_FAILURE; + } + ret = p->main(argc, argv); + if (cpus_chosen) + bitmask_free(cpus_chosen); + return ret; + } + print_help(); + return EXIT_FAILURE; +} diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c new file mode 100644 index 000000000000..5e44e31fc7f9 --- /dev/null +++ b/tools/power/cpupower/utils/helpers/amd.c @@ -0,0 +1,137 @@ +#if defined(__i386__) || defined(__x86_64__) +#include +#include +#include +#include + +#include + +#include "helpers/helpers.h" + +#define MSR_AMD_PSTATE_STATUS 0xc0010063 +#define MSR_AMD_PSTATE 0xc0010064 +#define MSR_AMD_PSTATE_LIMIT 0xc0010061 + +union msr_pstate { + struct { + unsigned fid:6; + unsigned did:3; + unsigned vid:7; + unsigned res1:6; + unsigned nbdid:1; + unsigned res2:2; + unsigned nbvid:7; + unsigned iddval:8; + unsigned idddiv:2; + unsigned res3:21; + unsigned en:1; + } bits; + unsigned long long val; +}; + +static int get_did(int family, union msr_pstate pstate) +{ + int t; + + if (family == 0x12) + t = pstate.val & 0xf; + else + t = pstate.bits.did; + + return t; +} + +static int get_cof(int family, union msr_pstate pstate) +{ + int t; + int fid, did; + + did = get_did(family, pstate); + + t = 0x10; + fid = pstate.bits.fid; + if (family == 0x11) + t = 0x8; + + return ((100 * (fid + t)) >> did); + } + +/* Needs: + * cpu -> the cpu that gets evaluated + * cpu_family -> The cpu's family (0x10, 0x12,...) + * boots_states -> how much boost states the machines support + * + * Fills up: + * pstates -> a pointer to an array of size MAX_HW_PSTATES + * must be initialized with zeros. + * All available HW pstates (including boost states) + * no -> amount of pstates above array got filled up with + * + * returns zero on success, -1 on failure + */ +int decode_pstates(unsigned int cpu, unsigned int cpu_family, + int boost_states, unsigned long *pstates, int *no) +{ + int i, psmax, pscur; + union msr_pstate pstate; + unsigned long long val; + + /* Only read out frequencies from HW when CPU might be boostable + to keep the code as short and clean as possible. + Otherwise frequencies are exported via ACPI tables. + */ + if (cpu_family < 0x10 || cpu_family == 0x14) + return -1; + + if (read_msr(cpu, MSR_AMD_PSTATE_LIMIT, &val)) + return -1; + + psmax = (val >> 4) & 0x7; + + if (read_msr(cpu, MSR_AMD_PSTATE_STATUS, &val)) + return -1; + + pscur = val & 0x7; + + pscur += boost_states; + psmax += boost_states; + for (i=0; i<=psmax; i++) { + if (i >= MAX_HW_PSTATES) { + fprintf(stderr, "HW pstates [%d] exceeding max [%d]\n", + psmax, MAX_HW_PSTATES); + return -1; + } + if (read_msr(cpu, MSR_AMD_PSTATE + i, &pstate.val)) + return -1; + pstates[i] = get_cof(cpu_family, pstate); + } + *no = i; + return 0; +} + +int amd_pci_get_num_boost_states(int *active, int *states) +{ + struct pci_access *pci_acc; + int vendor_id = 0x1022; + int boost_dev_ids[4] = {0x1204, 0x1604, 0x1704, 0}; + struct pci_dev *device; + uint8_t val = 0; + + *active = *states = 0; + + device = pci_acc_init(&pci_acc, vendor_id, boost_dev_ids); + + if (device == NULL) + return -ENODEV; + + val = pci_read_byte(device, 0x15c); + if (val & 3) + *active = 1; + else + *active = 0; + *states = (val >> 2) & 7; + + pci_cleanup(pci_acc); + return 0; +} +#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..60f4d69bb20d --- /dev/null +++ b/tools/power/cpupower/utils/helpers/bitmask.c @@ -0,0 +1,290 @@ +#include +#include +#include + +#include + +/* How many bits in an unsigned long */ +#define bitsperlong (8 * sizeof(unsigned long)) + +/* howmany(a,b) : how many elements of size b needed to hold all of a */ +#define howmany(x,y) (((x)+((y)-1))/(y)) + +/* How many longs in mask of n bits */ +#define longsperbits(n) howmany(n, bitsperlong) + +#define max(a,b) ((a) > (b) ? (a) : (b)) + +/* + * Allocate and free `struct bitmask *` + */ + +/* Allocate a new `struct bitmask` with a size of n bits */ +struct bitmask *bitmask_alloc(unsigned int n) +{ + struct bitmask *bmp; + + bmp = malloc(sizeof(*bmp)); + if (bmp == 0) + return 0; + bmp->size = n; + bmp->maskp = calloc(longsperbits(n), sizeof(unsigned long)); + if (bmp->maskp == 0) { + free(bmp); + return 0; + } + return bmp; +} + +/* Free `struct bitmask` */ +void bitmask_free(struct bitmask *bmp) +{ + if (bmp == 0) + return; + free(bmp->maskp); + bmp->maskp = (unsigned long *)0xdeadcdef; /* double free tripwire */ + free(bmp); +} + +/* + * The routines _getbit() and _setbit() are the only + * routines that actually understand the layout of bmp->maskp[]. + * + * On little endian architectures, this could simply be an array of + * bytes. But the kernel layout of bitmasks _is_ visible to userspace + * via the sched_(set/get)affinity calls in Linux 2.6, and on big + * endian architectures, it is painfully obvious that this is an + * array of unsigned longs. + */ + +/* Return the value (0 or 1) of bit n in bitmask bmp */ +static unsigned int _getbit(const struct bitmask *bmp, unsigned int n) +{ + if (n < bmp->size) + return (bmp->maskp[n/bitsperlong] >> (n % bitsperlong)) & 1; + else + return 0; +} + +/* Set bit n in bitmask bmp to value v (0 or 1) */ +static void _setbit(struct bitmask *bmp, unsigned int n, unsigned int v) +{ + if (n < bmp->size) { + if (v) + bmp->maskp[n/bitsperlong] |= 1UL << (n % bitsperlong); + else + bmp->maskp[n/bitsperlong] &= ~(1UL << (n % bitsperlong)); + } +} + +/* + * When parsing bitmask lists, only allow numbers, separated by one + * of the allowed next characters. + * + * The parameter 'sret' is the return from a sscanf "%u%c". It is + * -1 if the sscanf input string was empty. It is 0 if the first + * character in the sscanf input string was not a decimal number. + * It is 1 if the unsigned number matching the "%u" was the end of the + * input string. It is 2 if one or more additional characters followed + * the matched unsigned number. If it is 2, then 'nextc' is the first + * character following the number. The parameter 'ok_next_chars' + * is the nul-terminated list of allowed next characters. + * + * The mask term just scanned was ok if and only if either the numbers + * matching the %u were all of the input or if the next character in + * the input past the numbers was one of the allowed next characters. + */ +static int scan_was_ok(int sret, char nextc, const char *ok_next_chars) +{ + return sret == 1 || + (sret == 2 && strchr(ok_next_chars, nextc) != NULL); +} + +static const char *nexttoken(const char *q, int sep) +{ + if (q) + q = strchr(q, sep); + if (q) + q++; + return q; +} + +/* Set a single bit i in bitmask */ +struct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i) +{ + _setbit(bmp, i, 1); + return bmp; +} + +/* Set all bits in bitmask: bmp = ~0 */ +struct bitmask *bitmask_setall(struct bitmask *bmp) +{ + unsigned int i; + for (i = 0; i < bmp->size; i++) + _setbit(bmp, i, 1); + return bmp; +} + +/* Clear all bits in bitmask: bmp = 0 */ +struct bitmask *bitmask_clearall(struct bitmask *bmp) +{ + unsigned int i; + for (i = 0; i < bmp->size; i++) + _setbit(bmp, i, 0); + return bmp; +} + +/* True if all bits are clear */ +int bitmask_isallclear(const struct bitmask *bmp) +{ + unsigned int i; + for (i = 0; i < bmp->size; i++) + if (_getbit(bmp, i)) + return 0; + return 1; +} + +/* True if specified bit i is set */ +int bitmask_isbitset(const struct bitmask *bmp, unsigned int i) +{ + return _getbit(bmp, i); +} + +/* Number of lowest set bit (min) */ +unsigned int bitmask_first(const struct bitmask *bmp) +{ + return bitmask_next(bmp, 0); +} + +/* Number of highest set bit (max) */ +unsigned int bitmask_last(const struct bitmask *bmp) +{ + unsigned int i; + unsigned int m = bmp->size; + for (i = 0; i < bmp->size; i++) + if (_getbit(bmp, i)) + m = i; + return m; +} + +/* Number of next set bit at or above given bit i */ +unsigned int bitmask_next(const struct bitmask *bmp, unsigned int i) +{ + unsigned int n; + for (n = i; n < bmp->size; n++) + if (_getbit(bmp, n)) + break; + return n; +} + +/* + * Parses a comma-separated list of numbers and ranges of numbers, + * with optional ':%u' strides modifying ranges, into provided bitmask. + * Some examples of input lists and their equivalent simple list: + * Input Equivalent to + * 0-3 0,1,2,3 + * 0-7:2 0,2,4,6 + * 1,3,5-7 1,3,5,6,7 + * 0-3:2,8-15:4 0,2,8,12 + */ +int bitmask_parselist(const char *buf, struct bitmask *bmp) +{ + const char *p, *q; + + bitmask_clearall(bmp); + + q = buf; + while (p = q, q = nexttoken(q, ','), p) { + unsigned int a; /* begin of range */ + unsigned int b; /* end of range */ + unsigned int s; /* stride */ + const char *c1, *c2; /* next tokens after '-' or ',' */ + char nextc; /* char after sscanf %u match */ + int sret; /* sscanf return (number of matches) */ + + sret = sscanf(p, "%u%c", &a, &nextc); + if (!scan_was_ok(sret, nextc, ",-")) + goto err; + b = a; + s = 1; + c1 = nexttoken(p, '-'); + c2 = nexttoken(p, ','); + if (c1 != NULL && (c2 == NULL || c1 < c2)) { + sret = sscanf(c1, "%u%c", &b, &nextc); + if (!scan_was_ok(sret, nextc, ",:")) + goto err; + c1 = nexttoken(c1, ':'); + if (c1 != NULL && (c2 == NULL || c1 < c2)) { + sret = sscanf(c1, "%u%c", &s, &nextc); + if (!scan_was_ok(sret, nextc, ",")) + goto err; + } + } + if (!(a <= b)) + goto err; + if (b >= bmp->size) + goto err; + while (a <= b) { + _setbit(bmp, a, 1); + a += s; + } + } + return 0; +err: + bitmask_clearall(bmp); + return -1; +} + +/* + * emit(buf, buflen, rbot, rtop, len) + * + * Helper routine for bitmask_displaylist(). Write decimal number + * or range to buf+len, suppressing output past buf+buflen, with optional + * comma-prefix. Return len of what would be written to buf, if it + * all fit. + */ + +static inline int emit(char *buf, int buflen, int rbot, int rtop, int len) +{ + if (len > 0) + len += snprintf(buf + len, max(buflen - len, 0), ","); + if (rbot == rtop) + len += snprintf(buf + len, max(buflen - len, 0), "%d", rbot); + else + len += snprintf(buf + len, max(buflen - len, 0), "%d-%d", rbot, rtop); + return len; +} + +/* + * Write decimal list representation of bmp to buf. + * + * Output format is a comma-separated list of decimal numbers and + * ranges. Consecutively set bits are shown as two hyphen-separated + * decimal numbers, the smallest and largest bit numbers set in + * the range. Output format is compatible with the format + * accepted as input by bitmap_parselist(). + * + * The return value is the number of characters which would be + * generated for the given input, excluding the trailing '\0', as + * per ISO C99. + */ + +int bitmask_displaylist(char *buf, int buflen, const struct bitmask *bmp) +{ + int len = 0; + /* current bit is 'cur', most recently seen range is [rbot, rtop] */ + unsigned int cur, rbot, rtop; + + if (buflen > 0) + *buf = 0; + rbot = cur = bitmask_first(bmp); + while (cur < bmp->size) { + rtop = cur; + cur = bitmask_next(bmp, cur+1); + if (cur >= bmp->size || cur > rtop + 1) { + len = emit(buf, buflen, rbot, rtop, len); + rbot = cur; + } + } + return len; +} 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 @@ +#ifndef __CPUPOWER_BITMASK__ +#define __CPUPOWER_BITMASK__ + +/* Taken over from libbitmask, a project initiated from sgi: + * Url: http://oss.sgi.com/projects/cpusets/ + * Unfortunately it's not very widespread, therefore relevant parts are + * pasted here. + */ + +struct bitmask { + unsigned int size; + unsigned long *maskp; +}; + +struct bitmask *bitmask_alloc(unsigned int n); +void bitmask_free(struct bitmask *bmp); + +struct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i); +struct bitmask *bitmask_setall(struct bitmask *bmp); +struct bitmask *bitmask_clearall(struct bitmask *bmp); + +unsigned int bitmask_first(const struct bitmask *bmp); +unsigned int bitmask_next(const struct bitmask *bmp, unsigned int i); +unsigned int bitmask_last(const struct bitmask *bmp); +int bitmask_isallclear(const struct bitmask *bmp); +int bitmask_isbitset(const struct bitmask *bmp, unsigned int i); + +int bitmask_parselist(const char *buf, struct bitmask *bmp); +int bitmask_displaylist(char *buf, int len, const struct bitmask *bmp); + + + +#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..71021f3bb69d --- /dev/null +++ b/tools/power/cpupower/utils/helpers/cpuid.c @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include + +#include "helpers/helpers.h" + +static const char *cpu_vendor_table[X86_VENDOR_MAX] = { + "Unknown", "GenuineIntel", "AuthenticAMD", +}; + +#if defined(__i386__) || defined(__x86_64__) + +/* from gcc */ +#include + +/* + * CPUID functions returning a single datum + * + * Define unsigned int cpuid_e[abcd]x(unsigned int op) + */ +#define cpuid_func(reg) \ + unsigned int cpuid_##reg(unsigned int op) \ + { \ + unsigned int eax, ebx, ecx, edx; \ + __cpuid(op, eax, ebx, ecx, edx); \ + return reg; \ + } +cpuid_func(eax); +cpuid_func(ebx); +cpuid_func(ecx); +cpuid_func(edx); + +#endif /* defined(__i386__) || defined(__x86_64__) */ + +/* get_cpu_info + * + * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo + * + * Returns 0 on success or a negativ error code + * + * TBD: Should there be a cpuid alternative for this if /proc is not mounted? + */ +int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info) +{ + FILE *fp; + char value[64]; + unsigned int proc, x; + unsigned int unknown = 0xffffff; + unsigned int cpuid_level, ext_cpuid_level; + + int ret = -EINVAL; + + cpu_info->vendor = X86_VENDOR_UNKNOWN; + cpu_info->family = unknown; + cpu_info->model = unknown; + cpu_info->stepping = unknown; + cpu_info->caps = 0; + + fp = fopen("/proc/cpuinfo", "r"); + if (!fp) + return -EIO; + + while (!feof(fp)) { + if (!fgets(value, 64, fp)) + continue; + value[63 - 1] = '\0'; + + if (!strncmp(value, "processor\t: ", 12)) { + sscanf(value, "processor\t: %u", &proc); + } + if (proc != cpu) + continue; + + /* Get CPU vendor */ + if (!strncmp(value, "vendor_id", 9)) + for (x = 1; x < X86_VENDOR_MAX; x++) { + if (strstr(value, cpu_vendor_table[x])) + cpu_info->vendor = x; + } + /* Get CPU family, etc. */ + else if (!strncmp(value, "cpu family\t: ", 13)) { + sscanf(value, "cpu family\t: %u", + &cpu_info->family); + } + else if (!strncmp(value, "model\t\t: ", 9)) { + sscanf(value, "model\t\t: %u", + &cpu_info->model); + } + else if (!strncmp(value, "stepping\t: ", 10)) { + sscanf(value, "stepping\t: %u", + &cpu_info->stepping); + + /* Exit -> all values must have been set */ + if (cpu_info->vendor == X86_VENDOR_UNKNOWN || + cpu_info->family == unknown || + cpu_info->model == unknown || + cpu_info->stepping == unknown) { + ret = -EINVAL; + goto out; + } + + ret = 0; + goto out; + } + } + ret = -ENODEV; +out: + fclose(fp); + /* Get some useful CPU capabilities from cpuid */ + if (cpu_info->vendor != X86_VENDOR_AMD && + cpu_info->vendor != X86_VENDOR_INTEL) + return ret; + + cpuid_level = cpuid_eax(0); + ext_cpuid_level = cpuid_eax(0x80000000); + + /* Invariant TSC */ + if (ext_cpuid_level >= 0x80000007 && + (cpuid_edx(0x80000007) & (1 << 8))) + cpu_info->caps |= CPUPOWER_CAP_INV_TSC; + + /* Aperf/Mperf registers support */ + if (cpuid_level >= 6 && (cpuid_ecx(6) & 0x1)) + cpu_info->caps |= CPUPOWER_CAP_APERF; + + /* AMD Boost state enable/disable register */ + if (cpu_info->vendor == X86_VENDOR_AMD) { + if (ext_cpuid_level >= 0x80000007 && + (cpuid_edx(0x80000007) & (1 << 9))) + cpu_info->caps |= CPUPOWER_CAP_AMD_CBP; + } + + /* Intel's perf-bias MSR support */ + if (cpu_info->vendor == X86_VENDOR_INTEL) { + if (cpuid_level >= 6 && (cpuid_ecx(6) & (1 << 3))) + cpu_info->caps |= CPUPOWER_CAP_PERF_BIAS; + } + + /* printf("ID: %u - Extid: 0x%x - Caps: 0x%llx\n", + cpuid_level, ext_cpuid_level, cpu_info->caps); + */ + return ret; +} diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h new file mode 100644 index 000000000000..a487dadb4cf0 --- /dev/null +++ b/tools/power/cpupower/utils/helpers/helpers.h @@ -0,0 +1,180 @@ +/* + * (C) 2010,2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Miscellaneous helpers which do not fit or are worth + * to put into separate headers + */ + +#ifndef __CPUPOWERUTILS_HELPERS__ +#define __CPUPOWERUTILS_HELPERS__ + +#include +#include + +#include "helpers/bitmask.h" + +/* Internationalization ****************************/ +#define _(String) gettext(String) +#ifndef gettext_noop +#define gettext_noop(String) String +#endif +#define N_(String) gettext_noop (String) +/* Internationalization ****************************/ + +extern int run_as_root; +extern struct bitmask *cpus_chosen; + +/* Global verbose (-d) stuff *********************************/ +/* + * define DEBUG via global Makefile variable + * Debug output is sent to stderr, do: + * cpupower monitor 2>/tmp/debug + * to split debug output away from normal output +*/ +#ifdef DEBUG +extern int be_verbose; + +#define dprint(fmt, ...) { \ + if (be_verbose) { \ + fprintf(stderr, "%s: " fmt, \ + __FUNCTION__, ##__VA_ARGS__); \ + } \ + } +#else +static inline void dprint(const char *fmt, ...) { } +#endif +extern int be_verbose; +/* Global verbose (-v) stuff *********************************/ + +/* cpuid and cpuinfo helpers **************************/ +enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL, + X86_VENDOR_AMD, X86_VENDOR_MAX}; + +#define CPUPOWER_CAP_INV_TSC 0x00000001 +#define CPUPOWER_CAP_APERF 0x00000002 +#define CPUPOWER_CAP_AMD_CBP 0x00000004 +#define CPUPOWER_CAP_PERF_BIAS 0x00000008 + +#define MAX_HW_PSTATES 10 + +struct cpupower_cpu_info { + enum cpupower_cpu_vendor vendor; + unsigned int family; + unsigned int model; + unsigned int stepping; + /* CPU capabilities read out from cpuid */ + unsigned long long caps; +}; + +/* get_cpu_info + * + * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo + * + * Returns 0 on success or a negativ error code + * Only used on x86, below global's struct values are zero/unknown on + * other archs + */ +extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info); +extern struct cpupower_cpu_info cpupower_cpu_info; +/* cpuid and cpuinfo helpers **************************/ + + +/* CPU topology/hierarchy parsing ******************/ +struct cpupower_topology { + /* Amount of CPU cores, packages and threads per core in the system */ + unsigned int cores; + unsigned int pkgs; + unsigned int threads; /* per core */ + + /* Array gets mallocated with cores entries, holding per core info */ + struct { + int pkg; + int core; + int cpu; + } *core_info; +}; + +extern int get_cpu_topology(struct cpupower_topology *cpu_top); +extern void cpu_topology_release(struct cpupower_topology cpu_top); +/* CPU topology/hierarchy parsing ******************/ + +/* X86 ONLY ****************************************/ +#if defined(__i386__) || defined(__x86_64__) + +#include + +/* Read/Write msr ****************************/ +extern int read_msr(int cpu, unsigned int idx, unsigned long long *val); +extern int write_msr(int cpu, unsigned int idx, unsigned long long val); + +extern int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val); +extern int msr_intel_get_perf_bias(unsigned int cpu); + +extern int msr_intel_has_boost_support(unsigned int cpu); +extern int msr_intel_boost_is_active(unsigned int cpu); + +/* Read/Write msr ****************************/ + +/* PCI stuff ****************************/ +extern int amd_pci_get_num_boost_states(int *active, int *states); +extern struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id, + int *dev_ids); + +/* PCI stuff ****************************/ + +/* AMD HW pstate decoding **************************/ + +extern int decode_pstates(unsigned int cpu, unsigned int cpu_family, + int boost_states, unsigned long *pstates, int *no); + +/* AMD HW pstate decoding **************************/ + +extern int cpufreq_has_boost_support(unsigned int cpu, int *support, + int *active, int * states); +/* + * CPUID functions returning a single datum + */ +unsigned int cpuid_eax(unsigned int op); +unsigned int cpuid_ebx(unsigned int op); +unsigned int cpuid_ecx(unsigned int op); +unsigned int cpuid_edx(unsigned int op); + +/* cpuid and cpuinfo helpers **************************/ +/* X86 ONLY ********************************************/ +#else +static inline int decode_pstates(unsigned int cpu, unsigned int cpu_family, + int boost_states, unsigned long *pstates, + int *no) +{ return -1; }; + +static inline int read_msr(int cpu, unsigned int idx, unsigned long long *val) +{ return -1; }; +static inline int write_msr(int cpu, unsigned int idx, unsigned long long val) +{ return -1; }; +static inline int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val) +{ return -1; }; +static inline int msr_intel_get_perf_bias(unsigned int cpu) +{ return -1; }; + +static inline int msr_intel_has_boost_support(unsigned int cpu) +{ return -1; }; +static inline int msr_intel_boost_is_active(unsigned int cpu) +{ return -1; }; + +/* Read/Write msr ****************************/ + +static inline int cpufreq_has_boost_support(unsigned int cpu, int *support, + int *active, int * states) +{ return -1; } + +/* cpuid and cpuinfo helpers **************************/ + +static inline unsigned int cpuid_eax(unsigned int op) { return 0; }; +static inline unsigned int cpuid_ebx(unsigned int op) { return 0; }; +static inline unsigned int cpuid_ecx(unsigned int op) { return 0; }; +static inline unsigned int cpuid_edx(unsigned int op) { return 0; }; +#endif /* defined(__i386__) || defined(__x86_64__) */ + +#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..c1566e93e0ec --- /dev/null +++ b/tools/power/cpupower/utils/helpers/misc.c @@ -0,0 +1,34 @@ +#if defined(__i386__) || defined(__x86_64__) + +#include "helpers/helpers.h" + +int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active, int * states) +{ + struct cpupower_cpu_info cpu_info; + int ret; + + *support = *active = *states = 0; + + ret = get_cpu_info(0, &cpu_info); + if (ret) + return ret; + + if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CBP) { + *support = 1; + amd_pci_get_num_boost_states(active, states); + if (ret <= 0) + return ret; + *support = 1; + } else if (cpupower_cpu_info.vendor == X86_VENDOR_INTEL) { + ret = msr_intel_has_boost_support(cpu); + if (ret <= 0) + return ret; + *support = ret; + ret = msr_intel_boost_is_active(cpu); + if (ret <= 0) + return ret; + *active = ret; + } + return 0; +} +#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..93d48bd56e57 --- /dev/null +++ b/tools/power/cpupower/utils/helpers/msr.c @@ -0,0 +1,122 @@ +#if defined(__i386__) || defined(__x86_64__) + +#include +#include +#include +#include + +#include "helpers/helpers.h" + +/* Intel specific MSRs */ +#define MSR_IA32_PERF_STATUS 0x198 +#define MSR_IA32_MISC_ENABLES 0x1a0 +#define MSR_IA32_ENERGY_PERF_BIAS 0x1b0 + +/* + * read_msr + * + * Will return 0 on success and -1 on failure. + * Possible errno values could be: + * EFAULT -If the read/write did not fully complete + * EIO -If the CPU does not support MSRs + * ENXIO -If the CPU does not exist + */ + +int read_msr(int cpu, unsigned int idx, unsigned long long *val) +{ + int fd; + char msr_file_name[64]; + + sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu); + fd = open(msr_file_name, O_RDONLY); + if (fd < 0) + return -1; + if (lseek(fd, idx, SEEK_CUR) == -1) + goto err; + if (read(fd, val, sizeof *val) != sizeof *val) + goto err; + close(fd); + return 0; + err: + close(fd); + return -1; +} + +/* + * write_msr + * + * Will return 0 on success and -1 on failure. + * Possible errno values could be: + * EFAULT -If the read/write did not fully complete + * EIO -If the CPU does not support MSRs + * ENXIO -If the CPU does not exist + */ +int write_msr(int cpu, unsigned int idx, unsigned long long val) +{ + int fd; + char msr_file_name[64]; + + sprintf(msr_file_name, "/dev/cpu/%d/msr", cpu); + fd = open(msr_file_name, O_WRONLY); + if (fd < 0) + return -1; + if (lseek(fd, idx, SEEK_CUR) == -1) + goto err; + if (write(fd, &val, sizeof val) != sizeof val) + goto err; + close(fd); + return 0; + err: + close(fd); + return -1; +} + +int msr_intel_has_boost_support(unsigned int cpu) +{ + unsigned long long misc_enables; + int ret; + + ret = read_msr(cpu, MSR_IA32_MISC_ENABLES, &misc_enables); + if (ret) + return ret; + return (misc_enables >> 38) & 0x1; +} + +int msr_intel_boost_is_active(unsigned int cpu) +{ + unsigned long long perf_status; + int ret; + + ret = read_msr(cpu, MSR_IA32_PERF_STATUS, &perf_status); + if (ret) + return ret; + return (perf_status >> 32) & 0x1; +} + +int msr_intel_get_perf_bias(unsigned int cpu) +{ + unsigned long long val; + int ret; + + if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) + return -1; + + ret = read_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &val); + if (ret) + return ret; + return val; +} + +int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val) +{ + int ret; + + if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) + return -1; + + ret = write_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, val); + if (ret) + return ret; + return 0; +} +#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..8dcc93813716 --- /dev/null +++ b/tools/power/cpupower/utils/helpers/pci.c @@ -0,0 +1,44 @@ +#if defined(__i386__) || defined(__x86_64__) + +#include + +/* + * pci_acc_init + * + * PCI access helper function depending on libpci + * + * **pacc : if a valid pci_dev is returned + * *pacc must be passed to pci_acc_cleanup to free it + * + * vendor_id : the pci vendor id matching the pci device to access + * dev_ids : device ids matching the pci device to access + * + * Returns : + * struct pci_dev which can be used with pci_{read,write}_* functions + * to access the PCI config space of matching pci devices + */ +struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id, + int *dev_ids) +{ + struct pci_filter filter_nb_link = { -1, -1, -1, -1, vendor_id, 0}; + struct pci_dev *device; + unsigned int i; + + *pacc = pci_alloc(); + if (*pacc == NULL) + return NULL; + + pci_init(*pacc); + pci_scan_bus(*pacc); + + for (i = 0; dev_ids[i] != 0; i++) { + filter_nb_link.device = dev_ids[i]; + for (device=(*pacc)->devices; device; device = device->next) { + if (pci_filter_match(&filter_nb_link, device)) + return device; + } + } + pci_cleanup(*pacc); + return NULL; +} +#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..0c534e79652b --- /dev/null +++ b/tools/power/cpupower/utils/helpers/sysfs.c @@ -0,0 +1,350 @@ +/* + * (C) 2004-2009 Dominik Brodowski + * (C) 2011 Thomas Renninger Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "helpers/sysfs.h" + +unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen) +{ + int fd; + size_t numread; + + if ( ( fd = open(path, O_RDONLY) ) == -1 ) + return 0; + + numread = read(fd, buf, buflen - 1); + if ( numread < 1 ) + { + close(fd); + return 0; + } + + buf[numread] = '\0'; + close(fd); + + return numread; +} + +static unsigned int sysfs_write_file(const char *path, + const char *value, size_t len) +{ + int fd; + size_t numwrite; + + if ( ( fd = open(path, O_WRONLY) ) == -1 ) + return 0; + + numwrite = write(fd, value, len); + if ( numwrite < 1 ) + { + close(fd); + return 0; + } + close(fd); + return numwrite; +} + +/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */ + +/* + * helper function to read file from /sys into given buffer + * fname is a relative path under "cpuX/cpuidle/stateX/" dir + * cstates starting with 0, C0 is not counted as cstate. + * This means if you want C1 info, pass 0 as idlestate param + */ +unsigned int sysfs_idlestate_read_file(unsigned int cpu, unsigned int idlestate, + const char *fname, char *buf, size_t buflen) +{ + char path[SYSFS_PATH_MAX]; + int fd; + size_t numread; + + snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s", + cpu, idlestate, fname); + + if ( ( fd = open(path, O_RDONLY) ) == -1 ) + return 0; + + numread = read(fd, buf, buflen - 1); + if ( numread < 1 ) + { + close(fd); + return 0; + } + + buf[numread] = '\0'; + close(fd); + + return numread; +} + +/* read access to files which contain one numeric value */ + +enum idlestate_value { + IDLESTATE_USAGE, + IDLESTATE_POWER, + IDLESTATE_LATENCY, + IDLESTATE_TIME, + MAX_IDLESTATE_VALUE_FILES +}; + +static const char *idlestate_value_files[MAX_IDLESTATE_VALUE_FILES] = { + [IDLESTATE_USAGE] = "usage", + [IDLESTATE_POWER] = "power", + [IDLESTATE_LATENCY] = "latency", + [IDLESTATE_TIME] = "time", +}; + +static unsigned long long sysfs_idlestate_get_one_value(unsigned int cpu, + unsigned int idlestate, + enum idlestate_value which) +{ + unsigned long long value; + unsigned int len; + char linebuf[MAX_LINE_LEN]; + char *endp; + + if ( which >= MAX_IDLESTATE_VALUE_FILES ) + return 0; + + if ( ( len = sysfs_idlestate_read_file(cpu, idlestate, + idlestate_value_files[which], + linebuf, sizeof(linebuf))) == 0 ) + { + return 0; + } + + value = strtoull(linebuf, &endp, 0); + + if ( endp == linebuf || errno == ERANGE ) + return 0; + + return value; +} + +/* read access to files which contain one string */ + +enum idlestate_string { + IDLESTATE_DESC, + IDLESTATE_NAME, + MAX_IDLESTATE_STRING_FILES +}; + +static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = { + [IDLESTATE_DESC] = "desc", + [IDLESTATE_NAME] = "name", +}; + + +static char * sysfs_idlestate_get_one_string(unsigned int cpu, + unsigned int idlestate, + enum idlestate_string which) +{ + char linebuf[MAX_LINE_LEN]; + char *result; + unsigned int len; + + if (which >= MAX_IDLESTATE_STRING_FILES) + return NULL; + + if ( ( len = sysfs_idlestate_read_file(cpu, idlestate, + idlestate_string_files[which], + linebuf, sizeof(linebuf))) == 0 ) + return NULL; + + if ( ( result = strdup(linebuf) ) == NULL ) + return NULL; + + if (result[strlen(result) - 1] == '\n') + result[strlen(result) - 1] = '\0'; + + return result; +} + +unsigned long sysfs_get_idlestate_latency(unsigned int cpu, unsigned int idlestate) +{ + return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_LATENCY); +} + +unsigned long sysfs_get_idlestate_usage(unsigned int cpu, unsigned int idlestate) +{ + return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_USAGE); +} + +unsigned long long sysfs_get_idlestate_time(unsigned int cpu, unsigned int idlestate) +{ + return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_TIME); +} + +char * sysfs_get_idlestate_name(unsigned int cpu, unsigned int idlestate) +{ + return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_NAME); +} + +char * sysfs_get_idlestate_desc(unsigned int cpu, unsigned int idlestate) +{ + return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_DESC); +} + +/* + * Returns number of supported C-states of CPU core cpu + * Negativ in error case + * Zero if cpuidle does not export any C-states + */ +int sysfs_get_idlestate_count(unsigned int cpu) +{ + char file[SYSFS_PATH_MAX]; + struct stat statbuf; + int idlestates = 1; + + + snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle"); + if ( stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) + return -ENODEV; + + snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu); + if ( stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) + return 0; + + while(stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { + snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU + "cpu%u/cpuidle/state%d", cpu, idlestates); + idlestates++; + } + idlestates--; + return idlestates; +} + +/* CPUidle general /sys/devices/system/cpu/cpuidle/ sysfs access ********/ + +/* + * helper function to read file from /sys into given buffer + * fname is a relative path under "cpu/cpuidle/" dir + */ +static unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf, + size_t buflen) +{ + char path[SYSFS_PATH_MAX]; + + snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname); + + return sysfs_read_file(path, buf, buflen); +} + + + +/* read access to files which contain one string */ + +enum cpuidle_string { + CPUIDLE_GOVERNOR, + CPUIDLE_GOVERNOR_RO, + CPUIDLE_DRIVER, + MAX_CPUIDLE_STRING_FILES +}; + +static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = { + [CPUIDLE_GOVERNOR] = "current_governor", + [CPUIDLE_GOVERNOR_RO] = "current_governor_ro", + [CPUIDLE_DRIVER] = "current_driver", +}; + + +static char * sysfs_cpuidle_get_one_string(enum cpuidle_string which) +{ + char linebuf[MAX_LINE_LEN]; + char *result; + unsigned int len; + + if (which >= MAX_CPUIDLE_STRING_FILES) + return NULL; + + if ( ( len = sysfs_cpuidle_read_file(cpuidle_string_files[which], + linebuf, sizeof(linebuf))) == 0 ) + return NULL; + + if ( ( result = strdup(linebuf) ) == NULL ) + return NULL; + + if (result[strlen(result) - 1] == '\n') + result[strlen(result) - 1] = '\0'; + + return result; +} + +char * sysfs_get_cpuidle_governor(void) +{ + char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO); + if (!tmp) + return sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR); + else + return tmp; +} + +char * sysfs_get_cpuidle_driver(void) +{ + return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER); +} +/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */ + +/* + * Get sched_mc or sched_smt settings + * Pass "mc" or "smt" as argument + * + * Returns negative value on failure + */ +int sysfs_get_sched(const char* smt_mc) +{ + unsigned long value; + char linebuf[MAX_LINE_LEN]; + char *endp; + char path[SYSFS_PATH_MAX]; + + if (strcmp("mc", smt_mc) && strcmp("smt", smt_mc)) + return -EINVAL; + + snprintf(path, sizeof(path), PATH_TO_CPU "sched_%s_power_savings", smt_mc); + if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0 ) + return -1; + value = strtoul(linebuf, &endp, 0); + if ( endp == linebuf || errno == ERANGE ) + return -1; + return value; +} + +/* + * Get sched_mc or sched_smt settings + * Pass "mc" or "smt" as argument + * + * Returns negative value on failure + */ +int sysfs_set_sched(const char* smt_mc, int val) +{ + char linebuf[MAX_LINE_LEN]; + char path[SYSFS_PATH_MAX]; + struct stat statbuf; + + if (strcmp("mc", smt_mc) && strcmp("smt", smt_mc)) + return -EINVAL; + + snprintf(path, sizeof(path), PATH_TO_CPU "sched_%s_power_savings", smt_mc); + sprintf(linebuf, "%d", val); + + if ( stat(path, &statbuf) != 0 ) + return -ENODEV; + + if (sysfs_write_file(path, linebuf, MAX_LINE_LEN) == 0 ) + return -1; + return 0; +} diff --git a/tools/power/cpupower/utils/helpers/sysfs.h b/tools/power/cpupower/utils/helpers/sysfs.h new file mode 100644 index 000000000000..5d02d2fc70e1 --- /dev/null +++ b/tools/power/cpupower/utils/helpers/sysfs.h @@ -0,0 +1,23 @@ +#ifndef __CPUPOWER_HELPERS_SYSFS_H__ +#define __CPUPOWER_HELPERS_SYSFS_H__ + +#define PATH_TO_CPU "/sys/devices/system/cpu/" +#define MAX_LINE_LEN 255 +#define SYSFS_PATH_MAX 255 + +extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen); + +extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu, unsigned int idlestate); +extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu, unsigned int idlestate); +extern unsigned long long sysfs_get_idlestate_time(unsigned int cpu, unsigned int idlestate); +extern char * sysfs_get_idlestate_name(unsigned int cpu, unsigned int idlestate); +extern char * sysfs_get_idlestate_desc(unsigned int cpu, unsigned int idlestate); +extern int sysfs_get_idlestate_count(unsigned int cpu); + +extern char * sysfs_get_cpuidle_governor(void); +extern char * sysfs_get_cpuidle_driver(void); + +extern int sysfs_get_sched(const char* smt_mc); +extern int sysfs_set_sched(const char* smt_mc, int val); + +#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..5ad842b956bb --- /dev/null +++ b/tools/power/cpupower/utils/helpers/topology.c @@ -0,0 +1,108 @@ +/* + * (C) 2010,2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + * + * ToDo: Needs to be done more properly for AMD/Intel specifics + */ + +/* Helper struct for qsort, must be in sync with cpupower_topology.cpu_info */ +/* Be careful: Need to pass unsigned to the sort, so that offlined cores are + in the end, but double check for -1 for offlined cpus at other places */ + +#include +#include +#include +#include +#include + +#include +#include + +/* returns -1 on failure, 0 on success */ +int sysfs_topology_read_file(unsigned int cpu, const char *fname) +{ + unsigned long value; + char linebuf[MAX_LINE_LEN]; + char *endp; + char path[SYSFS_PATH_MAX]; + + snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s", + cpu, fname); + if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0 ) + return -1; + value = strtoul(linebuf, &endp, 0); + if ( endp == linebuf || errno == ERANGE ) + return -1; + return value; +} + +struct cpuid_core_info { + unsigned int pkg; + unsigned int thread; + unsigned int cpu; +}; + +static int __compare(const void *t1, const void *t2) +{ + struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1; + struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2; + if (top1->pkg < top2->pkg) + return -1; + else if (top1->pkg > top2->pkg) + return 1; + else if (top1->thread < top2->thread) + return -1; + else if (top1->thread > top2->thread) + return 1; + else if (top1->cpu < top2->cpu) + return -1; + else if (top1->cpu > top2->cpu) + return 1; + else + return 0; +} + +/* + * Returns amount of cpus, negative on error, cpu_top must be + * passed to cpu_topology_release to free resources + * + * Array is sorted after ->pkg, ->core, then ->cpu + */ +int get_cpu_topology(struct cpupower_topology *cpu_top) +{ + int cpu, cpus = sysconf(_SC_NPROCESSORS_CONF); + + cpu_top->core_info = malloc(sizeof(struct cpupower_topology) * cpus); + if (cpu_top->core_info == NULL) + return -ENOMEM; + cpu_top->pkgs = cpu_top->cores = 0; + for (cpu = 0; cpu < cpus; cpu++) { + cpu_top->core_info[cpu].pkg = + sysfs_topology_read_file(cpu, "physical_package_id"); + if ((int)cpu_top->core_info[cpu].pkg != -1 && + cpu_top->core_info[cpu].pkg > cpu_top->pkgs) + cpu_top->pkgs = cpu_top->core_info[cpu].pkg; + cpu_top->core_info[cpu].core = + sysfs_topology_read_file(cpu, "core_id"); + cpu_top->core_info[cpu].cpu = cpu; + } + cpu_top->pkgs++; + + qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info), + __compare); + + /* Intel's cores count is not consecutively numbered, there may + * be a core_id of 3, but none of 2. Assume there always is 0 + * Get amount of cores by counting duplicates in a package + for (cpu = 0; cpu_top->core_info[cpu].pkg = 0 && cpu < cpus; cpu++) { + if (cpu_top->core_info[cpu].core == 0) + cpu_top->cores++; + */ + return cpus; +} + +void cpu_topology_release(struct cpupower_topology cpu_top) +{ + free(cpu_top.core_info); +} 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..3de94322dfb8 --- /dev/null +++ b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c @@ -0,0 +1,340 @@ +/* + * (C) 2010,2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + * + * PCI initialization based on example code from: + * Andreas Herrmann + */ + +#if defined(__i386__) || defined(__x86_64__) + +#include +#include +#include +#include +#include + +#include + +#include "idle_monitor/cpupower-monitor.h" +#include "helpers/helpers.h" + +/******** PCI parts could go into own file and get shared ***************/ + +#define PCI_NON_PC0_OFFSET 0xb0 +#define PCI_PC1_OFFSET 0xb4 +#define PCI_PC6_OFFSET 0xb8 + +#define PCI_MONITOR_ENABLE_REG 0xe0 + +#define PCI_NON_PC0_ENABLE_BIT 0 +#define PCI_PC1_ENABLE_BIT 1 +#define PCI_PC6_ENABLE_BIT 2 + +#define PCI_NBP1_STAT_OFFSET 0x98 +#define PCI_NBP1_ACTIVE_BIT 2 +#define PCI_NBP1_ENTERED_BIT 1 + +#define PCI_NBP1_CAP_OFFSET 0x90 +#define PCI_NBP1_CAPABLE_BIT 31 + +#define OVERFLOW_MS 343597 /* 32 bit register filled at 12500 HZ + (1 tick per 80ns) */ + +enum amd_fam14h_states {NON_PC0 = 0, PC1, PC6, NBP1, + AMD_FAM14H_STATE_NUM}; + +static int fam14h_get_count_percent(unsigned int self_id, double *percent, + unsigned int cpu); +static int fam14h_nbp1_count(unsigned int id, unsigned long long *count, + unsigned int cpu); + +static cstate_t amd_fam14h_cstates[AMD_FAM14H_STATE_NUM] = { + { + .name = "!PC0", + .desc = N_("Package in sleep state (PC1 or deeper)"), + .id = NON_PC0, + .range = RANGE_PACKAGE, + .get_count_percent = fam14h_get_count_percent, + }, + { + .name = "PC1", + .desc = N_("Processor Package C1"), + .id = PC1, + .range = RANGE_PACKAGE, + .get_count_percent = fam14h_get_count_percent, + }, + { + .name = "PC6", + .desc = N_("Processor Package C6"), + .id = PC6, + .range = RANGE_PACKAGE, + .get_count_percent = fam14h_get_count_percent, + }, + { + .name = "NBP1", + .desc = N_("North Bridge P1 boolean counter (returns 0 or 1)"), + .id = NBP1, + .range = RANGE_PACKAGE, + .get_count = fam14h_nbp1_count, + }, +}; + +static struct pci_access *pci_acc; +static int pci_vendor_id = 0x1022; +static int pci_dev_ids[2] = {0x1716, 0}; +static struct pci_dev *amd_fam14h_pci_dev; + +static int nbp1_entered; + +struct timespec start_time; +static unsigned long long timediff; + +#ifdef DEBUG +struct timespec dbg_time; +long dbg_timediff; +#endif + +static unsigned long long *previous_count[AMD_FAM14H_STATE_NUM]; +static unsigned long long *current_count[AMD_FAM14H_STATE_NUM]; + +static int amd_fam14h_get_pci_info(struct cstate *state, + unsigned int *pci_offset, + unsigned int *enable_bit, + unsigned int cpu) +{ + switch(state->id) { + case NON_PC0: + *enable_bit = PCI_NON_PC0_ENABLE_BIT; + *pci_offset = PCI_NON_PC0_OFFSET; + break; + case PC1: + *enable_bit = PCI_PC1_ENABLE_BIT; + *pci_offset = PCI_PC1_OFFSET; + break; + case PC6: + *enable_bit = PCI_PC6_ENABLE_BIT; + *pci_offset = PCI_PC6_OFFSET; + break; + case NBP1: + *enable_bit = PCI_NBP1_ENTERED_BIT; + *pci_offset = PCI_NBP1_STAT_OFFSET; + break; + default: + return -1; + }; + return 0; +} + +static int amd_fam14h_init(cstate_t *state, unsigned int cpu) +{ + int enable_bit, pci_offset, ret; + uint32_t val; + + ret = amd_fam14h_get_pci_info(state, &pci_offset, &enable_bit, cpu); + if (ret) + return ret; + + /* NBP1 needs extra treating -> write 1 to D18F6x98 bit 1 for init */ + if (state->id == NBP1) { + val = pci_read_long(amd_fam14h_pci_dev, pci_offset); + val |= 1 << enable_bit; + val = pci_write_long(amd_fam14h_pci_dev, pci_offset, val); + return ret; + } + + /* Enable monitor */ + val = pci_read_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG); + dprint("Init %s: read at offset: 0x%x val: %u\n", state->name, + PCI_MONITOR_ENABLE_REG, (unsigned int) val); + val |= 1 << enable_bit; + pci_write_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG, val); + + dprint("Init %s: offset: 0x%x enable_bit: %d - val: %u (%u)\n", + state->name, PCI_MONITOR_ENABLE_REG, enable_bit, + (unsigned int) val, cpu); + + /* Set counter to zero */ + pci_write_long(amd_fam14h_pci_dev, pci_offset, 0); + previous_count[state->id][cpu] = 0; + + return 0; +} + +static int amd_fam14h_disable(cstate_t *state, unsigned int cpu) +{ + int enable_bit, pci_offset, ret; + uint32_t val; + + ret = amd_fam14h_get_pci_info(state, &pci_offset, &enable_bit, cpu); + if (ret) + return ret; + + val = pci_read_long(amd_fam14h_pci_dev, pci_offset); + dprint("%s: offset: 0x%x %u\n", state->name, pci_offset, val); + if (state->id == NBP1) { + /* was the bit whether NBP1 got entered set? */ + nbp1_entered = (val & (1 << PCI_NBP1_ACTIVE_BIT)) | + (val & (1 << PCI_NBP1_ENTERED_BIT)); + + dprint("NBP1 was %sentered - 0x%x - enable_bit: " + "%d - pci_offset: 0x%x\n", + nbp1_entered ? "" : "not ", + val, enable_bit, pci_offset); + return ret; + } + current_count[state->id][cpu] = val; + + dprint("%s: Current - %llu (%u)\n", state->name, + current_count[state->id][cpu], cpu); + dprint("%s: Previous - %llu (%u)\n", state->name, + previous_count[state->id][cpu], cpu); + + val = pci_read_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG); + val &= ~(1 << enable_bit); + pci_write_long(amd_fam14h_pci_dev, PCI_MONITOR_ENABLE_REG, val); + + return 0; +} + +static int fam14h_nbp1_count(unsigned int id, unsigned long long *count, + unsigned int cpu) +{ + if (id == NBP1) { + if (nbp1_entered) + *count = 1; + else + *count = 0; + return 0; + } + return -1; +} +static int fam14h_get_count_percent(unsigned int id, double *percent, + unsigned int cpu) +{ + unsigned long diff; + + if (id >= AMD_FAM14H_STATE_NUM) + return -1; + /* residency count in 80ns -> divide through 12.5 to get us residency */ + diff = current_count[id][cpu] - previous_count[id][cpu]; + + if (timediff == 0) + *percent = 0.0; + else + *percent = 100.0 * diff / timediff / 12.5; + + dprint("Timediff: %llu - res~: %lu us - percent: %.2f %%\n", + timediff, diff * 10 / 125, *percent); + + return 0; +} + +static int amd_fam14h_start(void) +{ + int num, cpu; + clock_gettime(CLOCK_REALTIME, &start_time); + for (num = 0; num < AMD_FAM14H_STATE_NUM; num++) { + for (cpu = 0; cpu < cpu_count; cpu++) { + amd_fam14h_init(&amd_fam14h_cstates[num], cpu); + } + } +#ifdef DEBUG + clock_gettime(CLOCK_REALTIME, &dbg_time); + dbg_timediff = timespec_diff_us(start_time, dbg_time); + dprint("Enabling counters took: %lu us\n", + dbg_timediff); +#endif + return 0; +} + +static int amd_fam14h_stop(void) +{ + int num, cpu; + struct timespec end_time; + + clock_gettime(CLOCK_REALTIME, &end_time); + + for (num = 0; num < AMD_FAM14H_STATE_NUM; num++) { + for (cpu = 0; cpu < cpu_count; cpu++) { + amd_fam14h_disable(&amd_fam14h_cstates[num], cpu); + } + } +#ifdef DEBUG + clock_gettime(CLOCK_REALTIME, &dbg_time); + dbg_timediff = timespec_diff_us(end_time, dbg_time); + dprint("Disabling counters took: %lu ns\n", dbg_timediff); +#endif + timediff = timespec_diff_us(start_time, end_time); + if (timediff / 1000 > OVERFLOW_MS) + print_overflow_err((unsigned int)timediff / 1000000, + OVERFLOW_MS / 1000); + + return 0; +} + +static int is_nbp1_capable(void) +{ + uint32_t val; + val = pci_read_long(amd_fam14h_pci_dev, PCI_NBP1_CAP_OFFSET); + return val & (1 << 31); +} + +struct cpuidle_monitor* amd_fam14h_register(void) { + + int num; + + if (cpupower_cpu_info.vendor != X86_VENDOR_AMD) + return NULL; + + if (cpupower_cpu_info.family == 0x14) { + if (cpu_count <= 0 || cpu_count > 2) { + fprintf(stderr, "AMD fam14h: Invalid cpu count: %d\n", + cpu_count); + return NULL; + } + } else + return NULL; + + /* We do not alloc for nbp1 machine wide counter */ + for (num = 0; num < AMD_FAM14H_STATE_NUM - 1; num++) { + previous_count[num] = calloc (cpu_count, + sizeof(unsigned long long)); + current_count[num] = calloc (cpu_count, + sizeof(unsigned long long)); + } + + amd_fam14h_pci_dev = pci_acc_init(&pci_acc, pci_vendor_id, pci_dev_ids); + if (amd_fam14h_pci_dev == NULL || pci_acc == NULL) + return NULL; + + if (!is_nbp1_capable()) + amd_fam14h_monitor.hw_states_num = AMD_FAM14H_STATE_NUM - 1; + + amd_fam14h_monitor.name_len = strlen(amd_fam14h_monitor.name); + return &amd_fam14h_monitor; +} + +static void amd_fam14h_unregister(void) +{ + int num; + for (num = 0; num < AMD_FAM14H_STATE_NUM - 1; num++) { + free(previous_count[num]); + free(current_count[num]); + } + pci_cleanup(pci_acc); +} + +struct cpuidle_monitor amd_fam14h_monitor = { + .name = "Ontario", + .hw_states = amd_fam14h_cstates, + .hw_states_num = AMD_FAM14H_STATE_NUM, + .start = amd_fam14h_start, + .stop = amd_fam14h_stop, + .do_register = amd_fam14h_register, + .unregister = amd_fam14h_unregister, + .needs_root = 1, + .overflow_s = OVERFLOW_MS / 1000, +}; +#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..63f6d670517b --- /dev/null +++ b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c @@ -0,0 +1,185 @@ +/* + * (C) 2010,2011 Thomas Renninger , Novell Inc + * + * Licensed under the terms of the GNU GPL License version 2. + * + */ + +#include +#include +#include +#include +#include + +#include "helpers/sysfs.h" +#include "helpers/helpers.h" +#include "idle_monitor/cpupower-monitor.h" + +#define CPUIDLE_STATES_MAX 10 +static cstate_t cpuidle_cstates[CPUIDLE_STATES_MAX]; +struct cpuidle_monitor cpuidle_sysfs_monitor; + +static unsigned long long **previous_count; +static unsigned long long **current_count; +struct timespec start_time; +static unsigned long long timediff; + +static int cpuidle_get_count_percent(unsigned int id, double *percent, + unsigned int cpu) +{ + unsigned long long statediff = current_count[cpu][id] + - previous_count[cpu][id]; + dprint("%s: - diff: %llu - percent: %f (%u)\n", + cpuidle_cstates[id].name, timediff, *percent, cpu); + + if (timediff == 0) + *percent = 0.0; + else + *percent = ((100.0 * statediff) / timediff); + + dprint("%s: - timediff: %llu - statediff: %llu - percent: %f (%u)\n", + cpuidle_cstates[id].name, timediff, statediff, *percent, cpu); + + return 0; +} + +static int cpuidle_start(void) +{ + int cpu, state; + clock_gettime(CLOCK_REALTIME, &start_time); + for (cpu = 0; cpu < cpu_count; cpu++) { + for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num; + state++) { + previous_count[cpu][state] = + sysfs_get_idlestate_time(cpu, state); + dprint("CPU %d - State: %d - Val: %llu\n", + cpu, state, previous_count[cpu][state]); + } + + }; + return 0; +} + +static int cpuidle_stop(void) +{ + int cpu, state; + struct timespec end_time; + clock_gettime(CLOCK_REALTIME, &end_time); + timediff = timespec_diff_us(start_time, end_time); + + for (cpu = 0; cpu < cpu_count; cpu++) { + for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num; + state++) { + current_count[cpu][state] = + sysfs_get_idlestate_time(cpu, state); + dprint("CPU %d - State: %d - Val: %llu\n", + cpu, state, previous_count[cpu][state]); + } + }; + return 0; +} + +void fix_up_intel_idle_driver_name(char *tmp, int num) +{ + /* fix up cpuidle name for intel idle driver */ + if (!strncmp(tmp, "NHM-", 4)) { + switch(num) { + case 1: strcpy(tmp, "C1"); + break; + case 2: strcpy(tmp, "C3"); + break; + case 3: strcpy(tmp, "C6"); + break; + } + } else if (!strncmp(tmp, "SNB-", 4)) { + switch(num) { + case 1: strcpy(tmp, "C1"); + break; + case 2: strcpy(tmp, "C3"); + break; + case 3: strcpy(tmp, "C6"); + break; + case 4: strcpy(tmp, "C7"); + break; + } + } else if (!strncmp(tmp, "ATM-", 4)) { + switch(num) { + case 1: strcpy(tmp, "C1"); + break; + case 2: strcpy(tmp, "C2"); + break; + case 3: strcpy(tmp, "C4"); + break; + case 4: strcpy(tmp, "C6"); + break; + } + } +} + +static struct cpuidle_monitor* cpuidle_register(void) +{ + int num; + char *tmp; + + /* Assume idle state count is the same for all CPUs */ + cpuidle_sysfs_monitor.hw_states_num = sysfs_get_idlestate_count(0); + + if (cpuidle_sysfs_monitor.hw_states_num == 0) + return NULL; + + for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num ++) { + tmp = sysfs_get_idlestate_name(0, num); + if (tmp == NULL) + continue; + + fix_up_intel_idle_driver_name(tmp, num); + strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1); + free(tmp); + + tmp = sysfs_get_idlestate_desc(0, num); + if (tmp == NULL) + continue; + strncpy(cpuidle_cstates[num].desc, tmp, CSTATE_DESC_LEN - 1); + free(tmp); + + cpuidle_cstates[num].range = RANGE_THREAD; + cpuidle_cstates[num].id = num; + cpuidle_cstates[num].get_count_percent = cpuidle_get_count_percent; + }; + + /* Free this at program termination */ + previous_count = malloc(sizeof (long long*) * cpu_count); + current_count = malloc(sizeof (long long*) * cpu_count); + for (num = 0; num < cpu_count; num++) { + previous_count[num] = malloc (sizeof(long long) * + cpuidle_sysfs_monitor.hw_states_num); + current_count[num] = malloc (sizeof(long long) * + cpuidle_sysfs_monitor.hw_states_num); + } + + cpuidle_sysfs_monitor.name_len = strlen(cpuidle_sysfs_monitor.name); + return &cpuidle_sysfs_monitor; +} + +void cpuidle_unregister(void) +{ + int num; + + for (num = 0; num < cpu_count; num++) { + free(previous_count[num]); + free(current_count[num]); + } + free(previous_count); + free(current_count); +} + +struct cpuidle_monitor cpuidle_sysfs_monitor = { + .name = "Idle_Stats", + .hw_states = cpuidle_cstates, + .start = cpuidle_start, + .stop = cpuidle_stop, + .do_register = cpuidle_register, + .unregister = cpuidle_unregister, + .needs_root = 0, + .overflow_s = UINT_MAX, +}; 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..3e96e79de3c2 --- /dev/null +++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c @@ -0,0 +1,446 @@ +/* + * (C) 2010,2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Output format inspired by Len Brown's turbostat tool. + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "idle_monitor/cpupower-monitor.h" +#include "idle_monitor/idle_monitors.h" +#include "helpers/helpers.h" + +/* Define pointers to all monitors. */ +#define DEF(x) & x ## _monitor , +struct cpuidle_monitor * all_monitors[] = { +#include "idle_monitors.def" +0 +}; + +static struct cpuidle_monitor *monitors[MONITORS_MAX]; +static unsigned int avail_monitors; + +static char *progname; + +enum operation_mode_e { list = 1, show, show_all }; +static int mode; +static int interval = 1; +static char *show_monitors_param; +static struct cpupower_topology cpu_top; + +/* ToDo: Document this in the manpage */ +static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', }; + +long long timespec_diff_us(struct timespec start, struct timespec end) +{ + struct timespec temp; + if ((end.tv_nsec - start.tv_nsec) < 0) { + temp.tv_sec = end.tv_sec - start.tv_sec - 1; + temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec - start.tv_sec; + temp.tv_nsec = end.tv_nsec - start.tv_nsec; + } + return (temp.tv_sec * 1000000) + (temp.tv_nsec / 1000); +} + +void monitor_help(void) +{ + printf(_("cpupower monitor: [-m ,[],.. ] command\n")); + printf(_("cpupower monitor: [-m ,[],.. ] [ -i interval_sec ]\n")); + printf(_("cpupower monitor: -l\n")); + printf(_("\t command: pass an arbitrary command to measure specific workload\n")); + printf(_("\t -i: time intervall to measure for in seconds (default 1)\n")); + printf(_("\t -l: list available CPU sleep monitors (for use with -m)\n")); + printf(_("\t -m: show specific CPU sleep monitors only (in same order)\n")); + printf(_("\t -h: print this help\n")); + printf("\n"); + printf(_("only one of: -l, -m are allowed\nIf none of them is passed,")); + printf(_(" all supported monitors are shown\n")); +} + +void print_n_spaces(int n) +{ + int x; + for (x = 0; x < n; x++) + printf(" "); +} + +/* size of s must be at least n + 1 */ +int fill_string_with_spaces(char *s, int n) +{ + int len = strlen(s); + if (len > n) + return -1; + for (; len < n; len++) + s[len] = ' '; + s[len] = '\0'; + return 0; +} + +void print_header(int topology_depth) +{ + int unsigned mon; + int state, need_len, pr_mon_len; + cstate_t s; + char buf[128] = ""; + int percent_width = 4; + + fill_string_with_spaces(buf, topology_depth * 5 - 1); + printf("%s|", buf); + + for (mon = 0; mon < avail_monitors; mon++) { + pr_mon_len = 0; + need_len = monitors[mon]->hw_states_num * (percent_width + 3) + - 1; + if (mon != 0) { + printf("|| "); + need_len --; + } + sprintf(buf, "%s", monitors[mon]->name); + fill_string_with_spaces(buf, need_len); + printf("%s", buf); + } + printf("\n"); + + if (topology_depth > 2) + printf("PKG |"); + if (topology_depth > 1) + printf("CORE|"); + if (topology_depth > 0) + printf("CPU |"); + + for (mon = 0; mon < avail_monitors; mon++) { + if (mon != 0) + printf("|| "); + else + printf(" "); + for (state = 0; state < monitors[mon]->hw_states_num; state++) { + if (state != 0) + printf(" | "); + s = monitors[mon]->hw_states[state]; + sprintf(buf, "%s", s.name); + fill_string_with_spaces(buf, percent_width); + printf("%s", buf); + } + printf(" "); + } + printf("\n"); +} + + +void print_results(int topology_depth, int cpu) +{ + unsigned int mon; + int state, ret; + double percent; + unsigned long long result; + cstate_t s; + + if (topology_depth > 2) + printf("%4d|", cpu_top.core_info[cpu].pkg); + if (topology_depth > 1) + printf("%4d|", cpu_top.core_info[cpu].core); + if (topology_depth > 0) + printf("%4d|", cpu_top.core_info[cpu].cpu); + + for (mon = 0; mon < avail_monitors; mon++) { + if (mon != 0) + printf("||"); + + for (state = 0; state < monitors[mon]->hw_states_num; state++) { + if (state != 0) + printf("|"); + + s = monitors[mon]->hw_states[state]; + + if (s.get_count_percent) { + ret = s.get_count_percent(s.id, &percent, + cpu_top.core_info[cpu].cpu); + if (ret) { + printf("******"); + } else if (percent >= 100.0) + printf("%6.1f", percent); + else + printf("%6.2f", percent); + } + else if (s.get_count) { + ret = s.get_count(s.id, &result, + cpu_top.core_info[cpu].cpu); + if (ret) { + printf("******"); + } else + printf("%6llu", result); + } + else { + printf(_("Monitor %s, Counter %s has no count " + "function. Implementation error\n"), + monitors[mon]->name, s.name); + exit (EXIT_FAILURE); + } + } + } + /* cpu offline */ + if (cpu_top.core_info[cpu].pkg == -1 || + cpu_top.core_info[cpu].core == -1) { + printf(_(" *is offline\n")); + return; + } else + printf("\n"); +} + + +/* param: string passed by -m param (The list of monitors to show) + * + * Monitors must have been registered already, matching monitors + * are picked out and available monitors array is overridden + * with matching ones + * + * Monitors get sorted in the same order the user passes them +*/ + +static void parse_monitor_param(char* param) +{ + unsigned int num; + int mon, hits = 0; + char *tmp = param, *token; + struct cpuidle_monitor *tmp_mons[MONITORS_MAX]; + + + for (mon = 0; mon < MONITORS_MAX;mon++, tmp = NULL) { + token = strtok(tmp, ","); + if (token == NULL) + break; + if (strlen(token) >= MONITOR_NAME_LEN) { + printf(_("%s: max monitor name length" + " (%d) exceeded\n"), token, MONITOR_NAME_LEN); + continue; + } + + for (num = 0; num < avail_monitors; num++) { + if (!strcmp(monitors[num]->name, token)) { + dprint("Found requested monitor: %s\n", token); + tmp_mons[hits] = monitors[num]; + hits++; + } + } + } + if (hits == 0) { + printf(_("No matching monitor found in %s, " + "try -l option\n"), param); + monitor_help(); + exit(EXIT_FAILURE); + } + /* Override detected/registerd monitors array with requested one */ + memcpy(monitors, tmp_mons, sizeof(struct cpuidle_monitor*) * MONITORS_MAX); + avail_monitors = hits; +} + +void list_monitors(void) { + unsigned int mon; + int state; + cstate_t s; + + for (mon = 0; mon < avail_monitors; mon++) { + printf(_("Monitor \"%s\" (%d states) - Might overflow after %u " + "s\n"), monitors[mon]->name, monitors[mon]->hw_states_num, + monitors[mon]->overflow_s); + + for (state = 0; state < monitors[mon]->hw_states_num; state++) { + s = monitors[mon]->hw_states[state]; + /* + * ToDo show more state capabilities: + * percent, time (granlarity) + */ + printf("%s\t[%c] -> %s\n", s.name, range_abbr[s.range], + gettext(s.desc)); + } + } +} + +int fork_it(char **argv) +{ + int status; + unsigned int num; + unsigned long long timediff; + pid_t child_pid; + struct timespec start, end; + + child_pid = fork(); + clock_gettime(CLOCK_REALTIME, &start); + + for (num = 0; num < avail_monitors; num++) + monitors[num]->start(); + + if (!child_pid) { + /* child */ + execvp(argv[0], argv); + } else { + /* parent */ + if (child_pid == -1) { + perror("fork"); + exit(1); + } + + signal(SIGINT, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + if (waitpid(child_pid, &status, 0) == -1) { + perror("wait"); + exit(1); + } + } + clock_gettime(CLOCK_REALTIME, &end); + for (num = 0; num < avail_monitors; num++) + monitors[num]->stop(); + + timediff = timespec_diff_us(start, end); + if (WIFEXITED(status)) + printf(_("%s took %.5f seconds and exited with status %d\n"), + argv[0], timediff / (1000.0 * 1000), WEXITSTATUS(status)); + return 0; +} + +int do_interval_measure(int i) +{ + unsigned int num; + + for (num = 0; num < avail_monitors; num++) { + dprint("HW C-state residency monitor: %s - States: %d\n", + monitors[num]->name, monitors[num]->hw_states_num); + monitors[num]->start(); + } + sleep(i); + for (num = 0; num < avail_monitors; num++) { + monitors[num]->stop(); + } + return 0; +} + +static void cmdline(int argc, char *argv[]) +{ + int opt; + progname = basename(argv[0]); + + while ((opt = getopt(argc, argv, "+hli:m:")) != -1) { + switch (opt) { + case 'h': + monitor_help(); + exit(EXIT_SUCCESS); + case 'l': + if (mode) { + monitor_help(); + exit(EXIT_FAILURE); + } + mode = list; + break; + case 'i': + /* only allow -i with -m or no option */ + if (mode && mode != show) { + monitor_help(); + exit(EXIT_FAILURE); + } + interval = atoi(optarg); + break; + case 'm': + if (mode) { + monitor_help(); + exit(EXIT_FAILURE); + } + mode = show; + show_monitors_param = optarg; + break; + default: + monitor_help(); + exit(EXIT_FAILURE); + } + } + if (!mode) + mode = show_all; +} + +int cmd_monitor(int argc, char **argv) +{ + unsigned int num; + struct cpuidle_monitor *test_mon; + int cpu; + + cmdline(argc, argv); + cpu_count = get_cpu_topology(&cpu_top); + if (cpu_count < 0) { + printf(_("Cannot read number of available processors\n")); + return EXIT_FAILURE; + } + + dprint("System has up to %d CPU cores\n", cpu_count); + + for (num = 0; all_monitors[num]; num++) { + dprint("Try to register: %s\n", all_monitors[num]->name); + test_mon = all_monitors[num]->do_register(); + if (test_mon) { + if (test_mon->needs_root && !run_as_root) { + fprintf(stderr, _("Available monitor %s needs " + "root access\n"), test_mon->name); + continue; + } + monitors[avail_monitors] = test_mon; + dprint("%s registered\n", all_monitors[num]->name); + avail_monitors++; + } + } + + if (avail_monitors == 0) { + printf(_("No HW Cstate monitors found\n")); + return 1; + } + + if (mode == list) { + list_monitors(); + exit(EXIT_SUCCESS); + } + + if (mode == show) + parse_monitor_param(show_monitors_param); + + dprint("Packages: %d - Cores: %d - CPUs: %d\n", + cpu_top.pkgs, cpu_top.cores, cpu_count); + + /* + * if any params left, it must be a command to fork + */ + if (argc - optind) + fork_it(argv + optind); + else + do_interval_measure(interval); + + /* ToDo: Topology parsing needs fixing first to do + this more generically */ + if (cpu_top.pkgs > 1) + print_header(3); + else + print_header(1); + + for (cpu = 0; cpu < cpu_count; cpu++) { + if (cpu_top.pkgs > 1) + print_results(3, cpu); + else + print_results(1, cpu); + } + + for (num = 0; num < avail_monitors; num++) { + monitors[num]->unregister(); + } + cpu_topology_release(cpu_top); + return 0; +} 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 @@ +/* + * (C) 2010,2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + * + */ + +#ifndef __CPUIDLE_INFO_HW__ +#define __CPUIDLE_INFO_HW__ + +#include +#include + +#include "idle_monitor/idle_monitors.h" + +#define MONITORS_MAX 20 +#define MONITOR_NAME_LEN 20 +#define CSTATE_NAME_LEN 5 +#define CSTATE_DESC_LEN 60 + +int cpu_count; + +/* Hard to define the right names ...: */ +enum power_range_e { + RANGE_THREAD, /* Lowest in topology hierarcy, AMD: core, Intel: thread + kernel sysfs: cpu */ + RANGE_CORE, /* AMD: unit, Intel: core, kernel_sysfs: core_id */ + RANGE_PACKAGE, /* Package, processor socket */ + RANGE_MACHINE, /* Machine, platform wide */ + RANGE_MAX }; + +typedef struct cstate { + int id; + enum power_range_e range; + char name[CSTATE_NAME_LEN]; + char desc[CSTATE_DESC_LEN]; + + /* either provide a percentage or a general count */ + int (*get_count_percent)(unsigned int self_id, double *percent, + unsigned int cpu); + int (*get_count)(unsigned int self_id, unsigned long long *count, + unsigned int cpu); +} cstate_t; + +struct cpuidle_monitor { + /* Name must not contain whitespaces */ + char name[MONITOR_NAME_LEN]; + int name_len; + int hw_states_num; + cstate_t *hw_states; + int (*start) (void); + int (*stop) (void); + struct cpuidle_monitor* (*do_register) (void); + void (*unregister)(void); + unsigned int overflow_s; + int needs_root; +}; + +extern long long timespec_diff_us(struct timespec start, struct timespec end); + +#define print_overflow_err(mes, ov) \ +{ \ + fprintf(stderr, gettext("Measure took %u seconds, but registers could " \ + "overflow at %u seconds, results " \ + "could be inaccurate\n"), mes, ov); \ +} + +#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 @@ +#if defined(__i386__) || defined(__x86_64__) +DEF(amd_fam14h) +DEF(intel_nhm) +DEF(intel_snb) +DEF(mperf) +#endif +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 @@ +/* + * (C) 2010,2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Based on the idea from Michael Matz + * + */ + +#ifndef _CPUIDLE_IDLE_MONITORS_H_ +#define _CPUIDLE_IDLE_MONITORS_H_ + +#define DEF(x) extern struct cpuidle_monitor x ##_monitor; +#include "idle_monitors.def" +#undef DEF +extern struct cpuidle_monitor *all_monitors[]; + +#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..f8545e40e232 --- /dev/null +++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c @@ -0,0 +1,258 @@ +/* + * (C) 2010,2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + */ + +#if defined(__i386__) || defined(__x86_64__) + +#include +#include +#include +#include +#include + +#include + +#include "helpers/helpers.h" +#include "idle_monitor/cpupower-monitor.h" + +#define MSR_APERF 0xE8 +#define MSR_MPERF 0xE7 + +#define MSR_TSC 0x10 + +enum mperf_id { C0 = 0, Cx, AVG_FREQ, MPERF_CSTATE_COUNT }; + +static int mperf_get_count_percent(unsigned int self_id, double *percent, + unsigned int cpu); +static int mperf_get_count_freq(unsigned int id, unsigned long long *count, + unsigned int cpu); + +static cstate_t mperf_cstates[MPERF_CSTATE_COUNT] = { + { + .name = "C0", + .desc = N_("Processor Core not idle"), + .id = C0, + .range = RANGE_THREAD, + .get_count_percent = mperf_get_count_percent, + }, + { + .name = "Cx", + .desc = N_("Processor Core in an idle state"), + .id = Cx, + .range = RANGE_THREAD, + .get_count_percent = mperf_get_count_percent, + }, + + { + .name = "Freq", + .desc = N_("Average Frequency (including boost) in MHz"), + .id = AVG_FREQ, + .range = RANGE_THREAD, + .get_count = mperf_get_count_freq, + }, +}; + +static unsigned long long tsc_at_measure_start; +static unsigned long long tsc_at_measure_end; +static unsigned long max_frequency; +static unsigned long long *mperf_previous_count; +static unsigned long long *aperf_previous_count; +static unsigned long long *mperf_current_count; +static unsigned long long *aperf_current_count; +/* valid flag for all CPUs. If a MSR read failed it will be zero */ +static int *is_valid; + +static int mperf_get_tsc(unsigned long long *tsc) +{ + return read_msr(0, MSR_TSC, tsc); +} + +static int mperf_init_stats(unsigned int cpu) +{ + unsigned long long val; + int ret; + + ret = read_msr(cpu, MSR_APERF, &val); + aperf_previous_count[cpu] = val; + ret |= read_msr(cpu, MSR_MPERF, &val); + mperf_previous_count[cpu] = val; + is_valid[cpu] = !ret; + + return 0; +} + +static int mperf_measure_stats(unsigned int cpu) +{ + unsigned long long val; + int ret; + + ret = read_msr(cpu, MSR_APERF, &val); + aperf_current_count[cpu] = val; + ret |= read_msr(cpu, MSR_MPERF, &val); + mperf_current_count[cpu] = val; + is_valid[cpu] = !ret; + + return 0; +} + +/* + * get_average_perf() + * + * Returns the average performance (also considers boosted frequencies) + * + * Input: + * aperf_diff: Difference of the aperf register over a time period + * mperf_diff: Difference of the mperf register over the same time period + * max_freq: Maximum frequency (P0) + * + * Returns: + * Average performance over the time period + */ +static unsigned long get_average_perf(unsigned long long aperf_diff, + unsigned long long mperf_diff) +{ + unsigned int perf_percent = 0; + if (((unsigned long)(-1) / 100) < aperf_diff) { + int shift_count = 7; + aperf_diff >>= shift_count; + mperf_diff >>= shift_count; + } + perf_percent = (aperf_diff * 100) / mperf_diff; + return (max_frequency * perf_percent) / 100; +} + +static int mperf_get_count_percent(unsigned int id, double *percent, + unsigned int cpu) +{ + unsigned long long aperf_diff, mperf_diff, tsc_diff; + + if (!is_valid[cpu]) + return -1; + + if (id != C0 && id != Cx) + return -1; + + mperf_diff = mperf_current_count[cpu] - mperf_previous_count[cpu]; + aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu]; + tsc_diff = tsc_at_measure_end - tsc_at_measure_start; + + *percent = 100.0 * mperf_diff / tsc_diff; + dprint("%s: mperf_diff: %llu, tsc_diff: %llu\n", + mperf_cstates[id].name, mperf_diff, tsc_diff); + + if (id == Cx) + *percent = 100.0 - *percent; + + dprint("%s: previous: %llu - current: %llu - (%u)\n", mperf_cstates[id].name, + mperf_diff, aperf_diff, cpu); + dprint("%s: %f\n", mperf_cstates[id].name, *percent); + return 0; +} + +static int mperf_get_count_freq(unsigned int id, unsigned long long *count, + unsigned int cpu) +{ + unsigned long long aperf_diff, mperf_diff; + + if (id != AVG_FREQ) + return 1; + + if (!is_valid[cpu]) + return -1; + + mperf_diff = mperf_current_count[cpu] - mperf_previous_count[cpu]; + aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu]; + + /* Return MHz for now, might want to return KHz if column width is more + generic */ + *count = get_average_perf(aperf_diff, mperf_diff) / 1000; + dprint("%s: %llu\n", mperf_cstates[id].name, *count); + + return 0; +} + +static int mperf_start(void) +{ + int cpu; + unsigned long long dbg; + + mperf_get_tsc(&tsc_at_measure_start); + + for (cpu = 0; cpu < cpu_count; cpu++) + mperf_init_stats(cpu); + + mperf_get_tsc(&dbg); + dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start); + return 0; +} + +static int mperf_stop(void) +{ + unsigned long long dbg; + int cpu; + + mperf_get_tsc(&tsc_at_measure_end); + + for (cpu = 0; cpu < cpu_count; cpu++) + mperf_measure_stats(cpu); + + mperf_get_tsc(&dbg); + dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end); + + return 0; +} + +struct cpuidle_monitor mperf_monitor; + +struct cpuidle_monitor* mperf_register(void) { + + unsigned long min; + + if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_APERF)) + return NULL; + + /* Assume min/max all the same on all cores */ + if (cpufreq_get_hardware_limits(0, &min, &max_frequency)) { + dprint("Cannot retrieve max freq from cpufreq kernel " + "subsystem\n"); + return NULL; + } + + /* Free this at program termination */ + is_valid = calloc(cpu_count, sizeof (int)); + mperf_previous_count = calloc (cpu_count, + sizeof(unsigned long long)); + aperf_previous_count = calloc (cpu_count, + sizeof(unsigned long long)); + mperf_current_count = calloc (cpu_count, + sizeof(unsigned long long)); + aperf_current_count = calloc (cpu_count, + sizeof(unsigned long long)); + + mperf_monitor.name_len = strlen(mperf_monitor.name); + return &mperf_monitor; +} + +void mperf_unregister(void) { + free(mperf_previous_count); + free(aperf_previous_count); + free(mperf_current_count); + free(aperf_current_count); + free(is_valid); +} + +struct cpuidle_monitor mperf_monitor = { + .name = "Mperf", + .hw_states_num = MPERF_CSTATE_COUNT, + .hw_states = mperf_cstates, + .start = mperf_start, + .stop = mperf_stop, + .do_register = mperf_register, + .unregister = mperf_unregister, + .needs_root = 1, + .overflow_s = 922000000 /* 922337203 seconds TSC overflow + at 20GHz */ +}; +#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..6424b6dd3fa5 --- /dev/null +++ b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c @@ -0,0 +1,212 @@ +/* + * (C) 2010,2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Based on Len Brown's turbostat tool. + */ + +#if defined(__i386__) || defined(__x86_64__) + +#include +#include +#include +#include + +#include "helpers/helpers.h" +#include "idle_monitor/cpupower-monitor.h" + +#define MSR_PKG_C3_RESIDENCY 0x3F8 +#define MSR_PKG_C6_RESIDENCY 0x3F9 +#define MSR_CORE_C3_RESIDENCY 0x3FC +#define MSR_CORE_C6_RESIDENCY 0x3FD + +#define MSR_TSC 0x10 + +#define NHM_CSTATE_COUNT 4 + +enum intel_nhm_id { C3 = 0, C6, PC3, PC6, TSC = 0xFFFF }; + +static int nhm_get_count_percent(unsigned int self_id, double *percent, + unsigned int cpu); + +static cstate_t nhm_cstates[NHM_CSTATE_COUNT] = { + { + .name = "C3", + .desc = N_("Processor Core C3"), + .id = C3, + .range = RANGE_CORE, + .get_count_percent = nhm_get_count_percent, + }, + { + .name = "C6", + .desc = N_("Processor Core C6"), + .id = C6, + .range = RANGE_CORE, + .get_count_percent = nhm_get_count_percent, + }, + + { + .name = "PC3", + .desc = N_("Processor Package C3"), + .id = PC3, + .range = RANGE_PACKAGE, + .get_count_percent = nhm_get_count_percent, + }, + { + .name = "PC6", + .desc = N_("Processor Package C6"), + .id = PC6, + .range = RANGE_PACKAGE, + .get_count_percent = nhm_get_count_percent, + }, +}; + +static unsigned long long tsc_at_measure_start; +static unsigned long long tsc_at_measure_end; +static unsigned long long *previous_count[NHM_CSTATE_COUNT]; +static unsigned long long *current_count[NHM_CSTATE_COUNT]; +/* valid flag for all CPUs. If a MSR read failed it will be zero */ +static int *is_valid; + +static int nhm_get_count(enum intel_nhm_id id, unsigned long long *val, unsigned int cpu) +{ + int msr; + + switch(id) { + case C3: + msr = MSR_CORE_C3_RESIDENCY; + break; + case C6: + msr = MSR_CORE_C6_RESIDENCY; + break; + case PC3: + msr = MSR_PKG_C3_RESIDENCY; + break; + case PC6: + msr = MSR_PKG_C6_RESIDENCY; + break; + case TSC: + msr = MSR_TSC; + break; + default: + return -1; + }; + if (read_msr(cpu, msr, val)) + return -1; + + return 0; +} + +static int nhm_get_count_percent(unsigned int id, double *percent, + unsigned int cpu) +{ + *percent = 0.0; + + if (!is_valid[cpu]) + return -1; + + *percent = (100.0 * (current_count[id][cpu] - previous_count[id][cpu])) / + (tsc_at_measure_end - tsc_at_measure_start); + + dprint("%s: previous: %llu - current: %llu - (%u)\n", nhm_cstates[id].name, + previous_count[id][cpu], current_count[id][cpu], + cpu); + + dprint("%s: tsc_diff: %llu - count_diff: %llu - percent: %2.f (%u)\n", + nhm_cstates[id].name, + (unsigned long long) tsc_at_measure_end - tsc_at_measure_start, + current_count[id][cpu] - previous_count[id][cpu], + *percent, cpu); + + return 0; +} + +static int nhm_start(void) +{ + int num, cpu; + unsigned long long dbg, val; + + nhm_get_count(TSC, &tsc_at_measure_start, 0); + + for (num = 0; num < NHM_CSTATE_COUNT; num++) { + for (cpu = 0; cpu < cpu_count; cpu++) { + is_valid[cpu] = !nhm_get_count(num, &val, cpu); + previous_count[num][cpu] = val; + } + } + nhm_get_count(TSC, &dbg, 0); + dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start); + return 0; +} + +static int nhm_stop(void) +{ + unsigned long long val; + unsigned long long dbg; + int num, cpu; + + nhm_get_count(TSC, &tsc_at_measure_end, 0); + + for (num = 0; num < NHM_CSTATE_COUNT; num++) { + for (cpu = 0; cpu < cpu_count; cpu++) { + is_valid[cpu] = !nhm_get_count(num, &val, cpu); + current_count[num][cpu] = val; + } + } + nhm_get_count(TSC, &dbg, 0); + dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end); + + return 0; +} + +struct cpuidle_monitor intel_nhm_monitor; + +struct cpuidle_monitor* intel_nhm_register(void) { + int num; + + if (cpupower_cpu_info.vendor != X86_VENDOR_INTEL) + return NULL; + + if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_INV_TSC)) + return NULL; + + if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_APERF)) + return NULL; + + /* Free this at program termination */ + is_valid = calloc(cpu_count, sizeof (int)); + for (num = 0; num < NHM_CSTATE_COUNT; num++) { + previous_count[num] = calloc (cpu_count, + sizeof(unsigned long long)); + current_count[num] = calloc (cpu_count, + sizeof(unsigned long long)); + } + + intel_nhm_monitor.name_len = strlen(intel_nhm_monitor.name); + return &intel_nhm_monitor; +} + +void intel_nhm_unregister(void) { + int num; + + for (num = 0; num < NHM_CSTATE_COUNT; num++) { + free(previous_count[num]); + free(current_count[num]); + } + free(is_valid); +} + +struct cpuidle_monitor intel_nhm_monitor = { + .name = "Nehalem", + .hw_states_num = NHM_CSTATE_COUNT, + .hw_states = nhm_cstates, + .start = nhm_start, + .stop = nhm_stop, + .do_register = intel_nhm_register, + .unregister = intel_nhm_unregister, + .needs_root = 1, + .overflow_s = 922000000 /* 922337203 seconds TSC overflow + at 20GHz */ +}; +#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..8cc80a5b530c --- /dev/null +++ b/tools/power/cpupower/utils/idle_monitor/snb_idle.c @@ -0,0 +1,189 @@ +/* + * (C) 2010,2011 Thomas Renninger , Novell Inc. + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Based on Len Brown's turbostat tool. + */ + +#if defined(__i386__) || defined(__x86_64__) + +#include +#include +#include +#include + +#include "helpers/helpers.h" +#include "idle_monitor/cpupower-monitor.h" + +#define MSR_PKG_C2_RESIDENCY 0x60D +#define MSR_PKG_C7_RESIDENCY 0x3FA +#define MSR_CORE_C7_RESIDENCY 0x3FE + +#define MSR_TSC 0x10 + +enum intel_snb_id { C7 = 0, PC2, PC7, SNB_CSTATE_COUNT, TSC = 0xFFFF }; + +static int snb_get_count_percent(unsigned int self_id, double *percent, + unsigned int cpu); + +static cstate_t snb_cstates[SNB_CSTATE_COUNT] = { + { + .name = "C7", + .desc = N_("Processor Core C7"), + .id = C7, + .range = RANGE_CORE, + .get_count_percent = snb_get_count_percent, + }, + { + .name = "PC2", + .desc = N_("Processor Package C2"), + .id = PC2, + .range = RANGE_PACKAGE, + .get_count_percent = snb_get_count_percent, + }, + { + .name = "PC7", + .desc = N_("Processor Package C7"), + .id = PC7, + .range = RANGE_PACKAGE, + .get_count_percent = snb_get_count_percent, + }, +}; + +static unsigned long long tsc_at_measure_start; +static unsigned long long tsc_at_measure_end; +static unsigned long long *previous_count[SNB_CSTATE_COUNT]; +static unsigned long long *current_count[SNB_CSTATE_COUNT]; +/* valid flag for all CPUs. If a MSR read failed it will be zero */ +static int *is_valid; + +static int snb_get_count(enum intel_snb_id id, unsigned long long *val, unsigned int cpu) +{ + int msr; + + switch(id) { + case C7: + msr = MSR_CORE_C7_RESIDENCY; + break; + case PC2: + msr = MSR_PKG_C2_RESIDENCY; + break; + case PC7: + msr = MSR_PKG_C7_RESIDENCY; + break; + case TSC: + msr = MSR_TSC; + break; + default: + return -1; + }; + if (read_msr(cpu, msr, val)) + return -1; + return 0; +} + +static int snb_get_count_percent(unsigned int id, double *percent, + unsigned int cpu) +{ + *percent = 0.0; + + if (!is_valid[cpu]) + return -1; + + *percent = (100.0 * (current_count[id][cpu] - previous_count[id][cpu])) / + (tsc_at_measure_end - tsc_at_measure_start); + + dprint("%s: previous: %llu - current: %llu - (%u)\n", snb_cstates[id].name, + previous_count[id][cpu], current_count[id][cpu], + cpu); + + dprint("%s: tsc_diff: %llu - count_diff: %llu - percent: %2.f (%u)\n", + snb_cstates[id].name, + (unsigned long long) tsc_at_measure_end - tsc_at_measure_start, + current_count[id][cpu] + - previous_count[id][cpu], + *percent, cpu); + + return 0; +} + +static int snb_start(void) +{ + int num, cpu; + unsigned long long val; + + for (num = 0; num < SNB_CSTATE_COUNT; num++) { + for (cpu = 0; cpu < cpu_count; cpu++) { + snb_get_count(num, &val, cpu); + previous_count[num][cpu] = val; + } + } + snb_get_count(TSC, &tsc_at_measure_start, 0); + return 0; +} + +static int snb_stop(void) +{ + unsigned long long val; + int num, cpu; + + snb_get_count(TSC, &tsc_at_measure_end, 0); + + for (num = 0; num < SNB_CSTATE_COUNT; num++) { + for (cpu = 0; cpu < cpu_count; cpu++) { + is_valid[cpu] = !snb_get_count(num, &val, cpu); + current_count[num][cpu] = val; + } + } + return 0; +} + +struct cpuidle_monitor intel_snb_monitor; + +static struct cpuidle_monitor* snb_register(void) { + + int num; + + if (cpupower_cpu_info.vendor != X86_VENDOR_INTEL + || cpupower_cpu_info.family != 6) + return NULL; + + if (cpupower_cpu_info.model != 0x2A + && cpupower_cpu_info.model != 0x2D) + return NULL; + + is_valid = calloc(cpu_count, sizeof (int)); + for (num = 0; num < SNB_CSTATE_COUNT; num++) { + previous_count[num] = calloc (cpu_count, + sizeof(unsigned long long)); + current_count[num] = calloc (cpu_count, + sizeof(unsigned long long)); + } + intel_snb_monitor.name_len = strlen(intel_snb_monitor.name); + return &intel_snb_monitor; +} + +void snb_unregister(void) +{ + int num; + free(is_valid); + for (num = 0; num < SNB_CSTATE_COUNT; num++) { + free(previous_count[num]); + free(current_count[num]); + } +} + +struct cpuidle_monitor intel_snb_monitor = { + .name = "SandyBridge", + .hw_states = snb_cstates, + .hw_states_num = SNB_CSTATE_COUNT, + .start = snb_start, + .stop = snb_stop, + .do_register = snb_register, + .unregister = snb_unregister, + .needs_root = 1, + .overflow_s = 922000000 /* 922337203 seconds TSC overflow + at 20GHz */ +}; +#endif /* defined(__i386__) || defined(__x86_64__) */ -- cgit v1.2.3 From c5db37fa0a84a6fd05e669dae3a706fa84012f73 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 12 Apr 2011 22:50:19 +0200 Subject: cpupowerutils: use COPYING, CREDITS from top-level directory Signed-off-by: Dominik Brodowski --- tools/power/cpupower/AUTHORS | 18 --- tools/power/cpupower/COPYING | 340 ------------------------------------------- 2 files changed, 358 deletions(-) delete mode 100644 tools/power/cpupower/AUTHORS delete mode 100644 tools/power/cpupower/COPYING (limited to 'tools') diff --git a/tools/power/cpupower/AUTHORS b/tools/power/cpupower/AUTHORS deleted file mode 100644 index 090af2cb81b1..000000000000 --- a/tools/power/cpupower/AUTHORS +++ /dev/null @@ -1,18 +0,0 @@ -Dominik Brodowski - - -Mattia Dongili -via Latisana, 8 -00177 Rome -Italy - - -Goran Koruga -Slovenia - - -Thomas Renninger -SUSE Linux GmbH -Germany - - diff --git a/tools/power/cpupower/COPYING b/tools/power/cpupower/COPYING deleted file mode 100644 index d60c31a97a54..000000000000 --- a/tools/power/cpupower/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. -- cgit v1.2.3 From 7443af9c9b99ed8eb1eb4496ca1769adba64776b Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 19 Apr 2011 09:03:52 +0200 Subject: cpupowerutils: remove ccdv, use kernel quiet/verbose mechanism Use the quiet/verbose mechanism found in kernel tools, without relying on the special tool "ccdv" Signed-off-by: Dominik Brodowski --- tools/power/cpupower/.gitignore | 6 +- tools/power/cpupower/Makefile | 31 ++- tools/power/cpupower/bench/Makefile | 11 +- tools/power/cpupower/build/ccdv.c | 387 ------------------------------------ 4 files changed, 24 insertions(+), 411 deletions(-) delete mode 100644 tools/power/cpupower/build/ccdv.c (limited to 'tools') diff --git a/tools/power/cpupower/.gitignore b/tools/power/cpupower/.gitignore index f8d7b5ac2719..4f0eb1d798df 100644 --- a/tools/power/cpupower/.gitignore +++ b/tools/power/cpupower/.gitignore @@ -14,8 +14,10 @@ lib/proc.o lib/sysfs.lo lib/sysfs.o libcpufreq.la -po/cpufrequtils.pot +po/cpupowerutils.pot po/*.gmo utils/cpufreq-info.o utils/cpufreq-set.o -utils/cpufreq-aperf.o \ No newline at end of file +utils/cpufreq-aperf.o +cpupower +bench/cpufreq-bench diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index aef1e3b41792..5d30dadbc4e7 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -24,7 +24,7 @@ # Set the following to `true' to make a unstripped, unoptimized # binary. Leave this set to `false' for production use. -DEBUG ?= true +DEBUG ?= false # make the build silent. Set this to something else to make it noisy again. V ?= false @@ -145,12 +145,13 @@ endif CFLAGS += $(WARNINGS) ifeq ($(strip $(V)),false) - QUIET=@$(PWD)/build/ccdv - HOST_PROGS=build/ccdv + QUIET=@ + ECHO=@echo else QUIET= - HOST_PROGS= + ECHO=@\# endif +export QUIET ECHO # if DEBUG is enabled, then we do not strip or optimize ifeq ($(strip $(DEBUG)),true) @@ -165,17 +166,14 @@ endif # the actual make rules -all: ccdv libcpufreq cpupower $(COMPILE_NLS) $(COMPILE_BENCH) +all: libcpufreq cpupower $(COMPILE_NLS) $(COMPILE_BENCH) -ccdv: build/ccdv -build/ccdv: build/ccdv.c - @echo "Building ccdv" - @$(HOSTCC) -O1 $< -o $@ - -lib/%.o: $(LIB_SRC) $(LIB_HEADERS) build/ccdv +lib/%.o: $(LIB_SRC) $(LIB_HEADERS) + $(ECHO) " CC " $@ $(QUIET) $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -o $@ -c lib/$*.c libcpufreq.so.$(LIB_MAJ): $(LIB_OBJS) + $(ECHO) " LD " $@ $(QUIET) $(CC) -shared $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \ -Wl,-soname,libcpufreq.so.$(LIB_MIN) $(LIB_OBJS) @ln -sf $@ libcpufreq.so @@ -188,11 +186,13 @@ libcpufreq: libcpufreq.so.$(LIB_MAJ) $(UTIL_OBJS): $(UTIL_HEADERS) .c.o: + $(ECHO) " CC " $@ $(QUIET) $(CC) $(CFLAGS) $(CPPFLAGS) -I./lib -I ./utils -o $@ -c $*.c -cpupower: $(UTIL_OBJS) libcpufreq +cpupower: $(UTIL_OBJS) libcpufreq.so.$(LIB_MAJ) + $(ECHO) " CC " $@ $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -lcpufreq -lrt -lpci -L. -o $@ $(UTIL_OBJS) - $(STRIPCMD) $@ + $(QUIET) $(STRIPCMD) $@ po/$(PACKAGE).pot: $(UTIL_SRC) @xgettext --default-domain=$(PACKAGE) --add-comments \ @@ -223,7 +223,6 @@ clean: -rm -f $(IDLE_OBJS) -rm -f cpupower -rm -f libcpufreq.so* - -rm -f build/ccdv -rm -rf po/*.gmo po/*.pot $(MAKE) -C bench clean @@ -256,7 +255,7 @@ install-gmo: install-bench: @#DESTDIR must be set from outside to survive @sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench install - + install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH) uninstall: @@ -269,5 +268,5 @@ uninstall: rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo; \ done; -.PHONY: all utils libcpufreq ccdv update-po update-gmo install-lib install-tools install-man install-gmo install uninstall \ +.PHONY: all utils libcpufreq update-po update-gmo install-lib install-tools install-man install-gmo install uninstall \ clean diff --git a/tools/power/cpupower/bench/Makefile b/tools/power/cpupower/bench/Makefile index 3d8fa21855f6..d779aac58ede 100644 --- a/tools/power/cpupower/bench/Makefile +++ b/tools/power/cpupower/bench/Makefile @@ -3,14 +3,13 @@ LIBS = -L../ -lm -lcpufreq OBJS = main.o parse.o system.o benchmark.o CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\" -ifeq ($(strip $(V)),false) - CC=@../build/ccdv gcc -else - CC=gcc -endif +%.o : %.c + $(ECHO) " CC " $@ + $(QUIET) $(CC) -c $(CFLAGS) $< -o $@ cpufreq-bench: $(OBJS) - $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS) + $(ECHO) " CC " $@ + $(QUIET) $(CC) -o $@ $(CFLAGS) $(OBJS) $(LIBS) all: cpufreq-bench diff --git a/tools/power/cpupower/build/ccdv.c b/tools/power/cpupower/build/ccdv.c deleted file mode 100644 index e3ae9da91a53..000000000000 --- a/tools/power/cpupower/build/ccdv.c +++ /dev/null @@ -1,387 +0,0 @@ -/* ccdv.c - * - * Copyright (C) 2002-2003, by Mike Gleason, NcFTP Software. - * All Rights Reserved. - * - * Licensed under the GNU Public License. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SETCOLOR_SUCCESS (gANSIEscapes ? "\033\1331;32m" : "") -#define SETCOLOR_FAILURE (gANSIEscapes ? "\033\1331;31m" : "") -#define SETCOLOR_WARNING (gANSIEscapes ? "\033\1331;33m" : "") -#define SETCOLOR_NORMAL (gANSIEscapes ? "\033\1330;39m" : "") - -#define TEXT_BLOCK_SIZE 8192 -#define INDENT 2 - -#define TERMS "vt100:vt102:vt220:vt320:xterm:xterm-color:ansi:linux:scoterm:scoansi:dtterm:cons25:cygwin" - -size_t gNBufUsed = 0, gNBufAllocated = 0; -char *gBuf = NULL; -int gCCPID; -char gAction[200] = ""; -char gTarget[200] = ""; -char gAr[32] = ""; -char gArLibraryTarget[64] = ""; -int gDumpCmdArgs = 0; -char gArgsStr[1000]; -int gColumns = 80; -int gANSIEscapes = 0; -int gExitStatus = 95; - -static void DumpFormattedOutput(void) -{ - char *cp; - char spaces[8 + 1] = " "; - char *saved; - int curcol; - int i; - - curcol = 0; - saved = NULL; - for (cp = gBuf + ((gDumpCmdArgs == 0) ? strlen(gArgsStr) : 0); ; cp++) { - if (*cp == '\0') { - if (saved != NULL) { - cp = saved; - saved = NULL; - } else break; - } - if (*cp == '\r') - continue; - if (*cp == '\t') { - saved = cp + 1; - cp = spaces + 8 - (8 - ((curcol - INDENT - 1) % 8)); - } - if (curcol == 0) { - for (i = INDENT; --i >= 0; ) - putchar(' '); - curcol = INDENT; - } - putchar(*cp); - if (++curcol == (gColumns - 1)) { - putchar('\n'); - curcol = 0; - } else if (*cp == '\n') - curcol = 0; - } - free(gBuf); -} /* DumpFormattedOutput */ - - - -/* Difftime(), only for timeval structures. */ -static void TimeValSubtract(struct timeval *tdiff, struct timeval *t1, struct timeval *t0) -{ - tdiff->tv_sec = t1->tv_sec - t0->tv_sec; - tdiff->tv_usec = t1->tv_usec - t0->tv_usec; - if (tdiff->tv_usec < 0) { - tdiff->tv_sec--; - tdiff->tv_usec += 1000000; - } -} /* TimeValSubtract */ - - - -static void Wait(void) -{ - int pid2, status; - - do { - status = 0; - pid2 = (int) waitpid(gCCPID, &status, 0); - } while (((pid2 >= 0) && (! WIFEXITED(status))) || ((pid2 < 0) && (errno == EINTR))); - if (WIFEXITED(status)) - gExitStatus = WEXITSTATUS(status); -} /* Wait */ - - - -static int SlurpProgress(int fd) -{ - char s1[71]; - char *newbuf; - int nready; - size_t ntoread; - ssize_t nread; - struct timeval now, tnext, tleft; - fd_set ss; - fd_set ss2; - const char *trail = "/-\\|", *trailcp; - - trailcp = trail; - snprintf(s1, sizeof(s1), "%s%s%s... ", gAction, gTarget[0] ? " " : "", gTarget); - printf("\r%-70s%-9s", s1, ""); - fflush(stdout); - - gettimeofday(&now, NULL); - tnext = now; - tnext.tv_sec++; - tleft.tv_sec = 1; - tleft.tv_usec = 0; - FD_ZERO(&ss2); - FD_SET(fd, &ss2); - for(;;) { - if (gNBufUsed == (gNBufAllocated - 1)) { - if ((newbuf = (char *) realloc(gBuf, gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) { - perror("ccdv: realloc"); - return (-1); - } - gNBufAllocated += TEXT_BLOCK_SIZE; - gBuf = newbuf; - } - for (;;) { - ss = ss2; - nready = select(fd + 1, &ss, NULL, NULL, &tleft); - if (nready == 1) - break; - if (nready < 0) { - if (errno != EINTR) { - perror("ccdv: select"); - return (-1); - } - continue; - } - gettimeofday(&now, NULL); - if ((now.tv_sec > tnext.tv_sec) || ((now.tv_sec == tnext.tv_sec) && (now.tv_usec >= tnext.tv_usec))) { - tnext = now; - tnext.tv_sec++; - tleft.tv_sec = 1; - tleft.tv_usec = 0; - printf("\r%-71s%c%-7s", s1, *trailcp, ""); - fflush(stdout); - if (*++trailcp == '\0') - trailcp = trail; - } else { - TimeValSubtract(&tleft, &tnext, &now); - } - } - ntoread = (gNBufAllocated - gNBufUsed - 1); - nread = read(fd, gBuf + gNBufUsed, ntoread); - if (nread < 0) { - if (errno == EINTR) - continue; - perror("ccdv: read"); - return (-1); - } else if (nread == 0) { - break; - } - gNBufUsed += nread; - gBuf[gNBufUsed] = '\0'; - } - snprintf(s1, sizeof(s1), "%s%s%s: ", gAction, gTarget[0] ? " " : "", gTarget); - Wait(); - if (gExitStatus == 0) { - printf("\r%-70s", s1); - printf("[%s%s%s]", ((gNBufUsed - strlen(gArgsStr)) < 4) ? SETCOLOR_SUCCESS : SETCOLOR_WARNING, "OK", SETCOLOR_NORMAL); - printf("%-5s\n", " "); - } else { - printf("\r%-70s", s1); - printf("[%s%s%s]", SETCOLOR_FAILURE, "ERROR", SETCOLOR_NORMAL); - printf("%-2s\n", " "); - gDumpCmdArgs = 1; /* print cmd when there are errors */ - } - fflush(stdout); - return (0); -} /* SlurpProgress */ - - - -static int SlurpAll(int fd) -{ - char *newbuf; - size_t ntoread; - ssize_t nread; - - printf("%s%s%s.\n", gAction, gTarget[0] ? " " : "", gTarget); - fflush(stdout); - - for(;;) { - if (gNBufUsed == (gNBufAllocated - 1)) { - if ((newbuf = (char *) realloc(gBuf, gNBufAllocated + TEXT_BLOCK_SIZE)) == NULL) { - perror("ccdv: realloc"); - return (-1); - } - gNBufAllocated += TEXT_BLOCK_SIZE; - gBuf = newbuf; - } - ntoread = (gNBufAllocated - gNBufUsed - 1); - nread = read(fd, gBuf + gNBufUsed, ntoread); - if (nread < 0) { - if (errno == EINTR) - continue; - perror("ccdv: read"); - return (-1); - } else if (nread == 0) { - break; - } - gNBufUsed += nread; - gBuf[gNBufUsed] = '\0'; - } - Wait(); - gDumpCmdArgs = (gExitStatus != 0); /* print cmd when there are errors */ - return (0); -} /* SlurpAll */ - - - -static const char *Basename(const char *path) -{ - const char *cp; - cp = strrchr(path, '/'); - if (cp == NULL) - return (path); - return (cp + 1); -} /* Basename */ - - - -static const char * Extension(const char *path) -{ - const char *cp = path; - cp = strrchr(path, '.'); - if (cp == NULL) - return (""); - // printf("Extension='%s'\n", cp); - return (cp); -} /* Extension */ - - - -static void Usage(void) -{ - fprintf(stderr, "Usage: ccdv /path/to/cc CFLAGS...\n\n"); - fprintf(stderr, "I wrote this to reduce the deluge Make output to make finding actual problems\n"); - fprintf(stderr, "easier. It is intended to be invoked from Makefiles, like this. Instead of:\n\n"); - fprintf(stderr, "\t.c.o:\n"); - fprintf(stderr, "\t\t$(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n"); - fprintf(stderr, "\nRewrite your rule so it looks like:\n\n"); - fprintf(stderr, "\t.c.o:\n"); - fprintf(stderr, "\t\t@ccdv $(CC) $(CFLAGS) $(DEFS) $(CPPFLAGS) $< -c\n\n"); - fprintf(stderr, "ccdv 1.1.0 is Free under the GNU Public License. Enjoy!\n"); - fprintf(stderr, " -- Mike Gleason, NcFTP Software \n"); - exit(96); -} /* Usage */ - - - -int main(int argc, char **argv) -{ - int pipe1[2]; - int devnull; - char emerg[256]; - int fd; - int nread; - int i; - int cc = 0, pch = 0; - const char *quote; - - if (argc < 2) - Usage(); - - snprintf(gAction, sizeof(gAction), "Running %s", Basename(argv[1])); - memset(gArgsStr, 0, sizeof(gArgsStr)); - for (i = 1; i < argc; i++) { - // printf("argv[%d]='%s'\n", i, argv[i]); - quote = (strchr(argv[i], ' ') != NULL) ? "\"" : ""; - snprintf(gArgsStr + strlen(gArgsStr), sizeof(gArgsStr) - strlen(gArgsStr), "%s%s%s%s%s", (i == 1) ? "" : " ", quote, argv[i], quote, (i == (argc - 1)) ? "\n" : ""); - if ((strcmp(argv[i], "-o") == 0) && ((i + 1) < argc)) { - if (strcasecmp(Extension(argv[i + 1]), ".o") != 0) { - strcpy(gAction, "Linking"); - snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i + 1])); - } - } else if (strchr("-+", (int) argv[i][0]) != NULL) { - continue; - } else if (strncasecmp(Extension(argv[i]), ".c", 2) == 0) { - cc++; - snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i])); - // printf("gTarget='%s'\n", gTarget); - } else if ((strncasecmp(Extension(argv[i]), ".h", 2) == 0) && (cc == 0)) { - pch++; - snprintf(gTarget, sizeof(gTarget), "%s", Basename(argv[i])); - } else if ((i == 1) && (strcmp(Basename(argv[i]), "ar") == 0)) { - snprintf(gAr, sizeof(gAr), "%s", Basename(argv[i])); - } else if ((gArLibraryTarget[0] == '\0') && (strcasecmp(Extension(argv[i]), ".a") == 0)) { - snprintf(gArLibraryTarget, sizeof(gArLibraryTarget), "%s", Basename(argv[i])); - } - } - if ((gAr[0] != '\0') && (gArLibraryTarget[0] != '\0')) { - strcpy(gAction, "Creating library"); - snprintf(gTarget, sizeof(gTarget), "%s", gArLibraryTarget); - } else if (pch > 0) { - strcpy(gAction, "Precompiling"); - } else if (cc > 0) { - strcpy(gAction, "Compiling"); - } - - if (pipe(pipe1) < 0) { - perror("ccdv: pipe"); - exit(97); - } - - (void) close(0); - devnull = open("/dev/null", O_RDWR, 00666); - if ((devnull != 0) && (dup2(devnull, 0) == 0)) - close(devnull); - - gCCPID = (int) fork(); - if (gCCPID < 0) { - (void) close(pipe1[0]); - (void) close(pipe1[1]); - perror("ccdv: fork"); - exit(98); - } else if (gCCPID == 0) { - /* Child */ - (void) close(pipe1[0]); /* close read end */ - if (pipe1[1] != 1) { /* use write end on stdout */ - (void) dup2(pipe1[1], 1); - (void) close(pipe1[1]); - } - (void) dup2(1, 2); /* use write end on stderr */ - execvp(argv[1], argv + 1); - perror(argv[1]); - exit(99); - } - - /* parent */ - (void) close(pipe1[1]); /* close write end */ - fd = pipe1[0]; /* use read end */ - - gColumns = (getenv("COLUMNS") != NULL) ? atoi(getenv("COLUMNS")) : 80; - gANSIEscapes = (getenv("TERM") != NULL) && (strstr(TERMS, getenv("TERM")) != NULL); - gBuf = (char *) malloc(TEXT_BLOCK_SIZE); - if (gBuf == NULL) - goto panic; - gNBufUsed = 0; - gNBufAllocated = TEXT_BLOCK_SIZE; - if (strlen(gArgsStr) < (gNBufAllocated - 1)) { - strcpy(gBuf, gArgsStr); - gNBufUsed = strlen(gArgsStr); - } - - if (isatty(1)) { - if (SlurpProgress(fd) < 0) - goto panic; - } else { - if (SlurpAll(fd) < 0) - goto panic; - } - DumpFormattedOutput(); - exit(gExitStatus); - -panic: - gDumpCmdArgs = 1; /* print cmd when there are errors */ - DumpFormattedOutput(); - while ((nread = read(fd, emerg, (size_t) sizeof(emerg))) > 0) - (void) write(2, emerg, (size_t) nread); - Wait(); - exit(gExitStatus); -} /* main */ -- cgit v1.2.3 From f5ac0641d129348399a8f39c95e7a16dc6e19f53 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 19 Apr 2011 18:52:44 +0200 Subject: cpupowerutils: do not update po files on each and every compile Signed-off-by: Dominik Brodowski --- tools/power/cpupower/Makefile | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index 5d30dadbc4e7..fea0e6a0a37a 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -95,6 +95,8 @@ HOSTCC = gcc # set up PWD so that older versions of make will work with our build. PWD = $(shell pwd) +GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo po/$$HLANG.gmo; done;} + export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS # check if compiler option is supported @@ -134,7 +136,7 @@ CFLAGS += -pipe ifeq ($(strip $(NLS)),true) INSTALL_NLS += install-gmo - COMPILE_NLS += update-gmo + COMPILE_NLS += create-gmo endif ifeq ($(strip $(CPUFRQ_BENCH)),true) @@ -195,14 +197,22 @@ cpupower: $(UTIL_OBJS) libcpufreq.so.$(LIB_MAJ) $(QUIET) $(STRIPCMD) $@ po/$(PACKAGE).pot: $(UTIL_SRC) - @xgettext --default-domain=$(PACKAGE) --add-comments \ + $(ECHO) " GETTEXT " $@ + $(QUIET) xgettext --default-domain=$(PACKAGE) --add-comments \ --keyword=_ --keyword=N_ $(UTIL_SRC) && \ test -f $(PACKAGE).po && \ mv -f $(PACKAGE).po po/$(PACKAGE).pot -update-gmo: po/$(PACKAGE).pot - @for HLANG in $(LANGUAGES); do \ - echo -n "Translating $$HLANG "; \ +po/%.gmo: po/%.po + $(ECHO) " MSGFMT " $@ + $(QUIET) msgfmt -o $@ po/$*.po + +create-gmo: ${GMO_FILES} + +update-po: po/$(PACKAGE).pot + $(ECHO) " MSGMRG " $@ + $(QUIET) @for HLANG in $(LANGUAGES); do \ + echo -n "Updating $$HLANG "; \ if msgmerge po/$$HLANG.po po/$(PACKAGE).pot -o \ po/$$HLANG.new.po; then \ mv -f po/$$HLANG.new.po po/$$HLANG.po; \ @@ -210,7 +220,6 @@ update-gmo: po/$(PACKAGE).pot echo "msgmerge for $$HLANG failed!"; \ rm -f po/$$HLANG.new.po; \ fi; \ - msgfmt --statistics -o po/$$HLANG.gmo po/$$HLANG.po; \ done; compile-bench: libcpufreq.so.$(LIB_MAJ) @@ -268,5 +277,5 @@ uninstall: rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo; \ done; -.PHONY: all utils libcpufreq update-po update-gmo install-lib install-tools install-man install-gmo install uninstall \ +.PHONY: all utils libcpufreq update-po create-gmo install-lib install-tools install-man install-gmo install uninstall \ clean -- cgit v1.2.3 From 02af3cb5aac13d8ef7edb7876260564b7d42ad2b Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 19 Apr 2011 19:20:12 +0200 Subject: cpupowerutils: bench - ConfigStyle bugfixes Signed-off-by: Dominik Brodowski --- tools/power/cpupower/Makefile | 5 ++-- tools/power/cpupower/bench/benchmark.c | 48 ++++++++++++++++++++-------------- tools/power/cpupower/bench/benchmark.h | 8 +++--- tools/power/cpupower/bench/config.h | 2 +- tools/power/cpupower/bench/main.c | 7 +++-- tools/power/cpupower/bench/parse.c | 37 +++++++++++++------------- tools/power/cpupower/bench/parse.h | 13 +++++---- tools/power/cpupower/bench/system.c | 13 +++++---- 8 files changed, 75 insertions(+), 58 deletions(-) (limited to 'tools') diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index fea0e6a0a37a..62c2716a9588 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -38,7 +38,7 @@ NLS ?= true CPUFRQ_BENCH ?= true # Prefix to the directories we're installing to -DESTDIR ?= +DESTDIR ?= # --- CONFIGURATION END --- @@ -277,5 +277,4 @@ uninstall: rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo; \ done; -.PHONY: all utils libcpufreq update-po create-gmo install-lib install-tools install-man install-gmo install uninstall \ - clean +.PHONY: all utils libcpufreq update-po create-gmo install-lib install-tools install-man install-gmo install uninstall clean diff --git a/tools/power/cpupower/bench/benchmark.c b/tools/power/cpupower/bench/benchmark.c index f538633b8b41..81b1c48607d9 100644 --- a/tools/power/cpupower/bench/benchmark.c +++ b/tools/power/cpupower/bench/benchmark.c @@ -37,7 +37,7 @@ if (config->output != stdout) { \ * compute how many rounds of calculation we should do * to get the given load time * - * @param load aimed load time in µs + * @param load aimed load time in µs * * @retval rounds of calculation **/ @@ -61,9 +61,8 @@ unsigned int calculate_timespace(long load, struct config *config) timed = (unsigned int)(then - now); /* approximation of the wanted load time by comparing with the - * initial calculation time */ - for (i= 0; i < 4; i++) - { + * initial calculation time */ + for (i = 0; i < 4; i++) { rounds = (unsigned int)(load * estimated / timed); dprintf("calibrating with %u rounds\n", rounds); now = get_time(); @@ -102,11 +101,11 @@ void start_benchmark(struct config *config) load_time = config->load; /* For the progress bar */ - for (_round=1; _round <= config->rounds; _round++) + for (_round = 1; _round <= config->rounds; _round++) total_time += _round * (config->sleep + config->load); total_time *= 2; /* powersave and performance cycles */ - for (_round=0; _round < config->rounds; _round++) { + for (_round = 0; _round < config->rounds; _round++) { performance_time = 0LL; powersave_time = 0LL; @@ -130,9 +129,10 @@ void start_benchmark(struct config *config) fprintf(config->output, "%u %li %li ", _round, load_time, sleep_time); - if (config->verbose) { - printf("avarage: %lius, rps:%li\n", load_time / calculations, 1000000 * calculations / load_time); - } + if (config->verbose) + printf("avarage: %lius, rps:%li\n", + load_time / calculations, + 1000000 * calculations / load_time); /* do some sleep/load cycles with the performance governor */ for (cycle = 0; cycle < config->cycles; cycle++) { @@ -142,10 +142,14 @@ void start_benchmark(struct config *config) then = get_time(); performance_time += then - now - sleep_time; if (config->verbose) - printf("performance cycle took %lius, sleep: %lius, load: %lius, rounds: %u\n", - (long)(then - now), sleep_time, load_time, calculations); + printf("performance cycle took %lius, " + "sleep: %lius, " + "load: %lius, rounds: %u\n", + (long)(then - now), sleep_time, + load_time, calculations); } - fprintf(config->output, "%li ", performance_time / config->cycles); + fprintf(config->output, "%li ", + performance_time / config->cycles); progress_time += sleep_time + load_time; show_progress(total_time, progress_time); @@ -155,7 +159,8 @@ void start_benchmark(struct config *config) if (set_cpufreq_governor(config->governor, config->cpu) != 0) return; - /* again, do some sleep/load cycles with the powersave governor */ + /* again, do some sleep/load cycles with the + * powersave governor */ for (cycle = 0; cycle < config->cycles; cycle++) { now = get_time(); usleep(sleep_time); @@ -163,22 +168,27 @@ void start_benchmark(struct config *config) then = get_time(); powersave_time += then - now - sleep_time; if (config->verbose) - printf("powersave cycle took %lius, sleep: %lius, load: %lius, rounds: %u\n", - (long)(then - now), sleep_time, load_time, calculations); + printf("powersave cycle took %lius, " + "sleep: %lius, " + "load: %lius, rounds: %u\n", + (long)(then - now), sleep_time, + load_time, calculations); } progress_time += sleep_time + load_time; /* compare the avarage sleep/load cycles */ - fprintf(config->output, "%li ", powersave_time / config->cycles); - fprintf(config->output, "%.3f\n", performance_time * 100.0 / powersave_time); + fprintf(config->output, "%li ", + powersave_time / config->cycles); + fprintf(config->output, "%.3f\n", + performance_time * 100.0 / powersave_time); fflush(config->output); if (config->verbose) - printf("performance is at %.2f%%\n", performance_time * 100.0 / powersave_time); + printf("performance is at %.2f%%\n", + performance_time * 100.0 / powersave_time); sleep_time += config->sleep_step; load_time += config->load_step; } } - diff --git a/tools/power/cpupower/bench/benchmark.h b/tools/power/cpupower/bench/benchmark.h index 0691f91b720b..51d7f50ac2bb 100644 --- a/tools/power/cpupower/bench/benchmark.h +++ b/tools/power/cpupower/bench/benchmark.h @@ -19,9 +19,11 @@ /* load loop, this schould take about 1 to 2ms to complete */ #define ROUNDS(x) {unsigned int rcnt; \ - for (rcnt = 0; rcnt< x*1000; rcnt++) { \ - (void)(((int)(pow(rcnt, rcnt) * sqrt(rcnt*7230970)) ^ 7230716) ^ (int)atan2(rcnt, rcnt)); \ - }} \ + for (rcnt = 0; rcnt < x*1000; rcnt++) { \ + (void)(((int)(pow(rcnt, rcnt) * \ + sqrt(rcnt*7230970)) ^ 7230716) ^ \ + (int)atan2(rcnt, rcnt)); \ + } } \ void start_benchmark(struct config *config); diff --git a/tools/power/cpupower/bench/config.h b/tools/power/cpupower/bench/config.h index 9690f1be32fd..ee6f258e5336 100644 --- a/tools/power/cpupower/bench/config.h +++ b/tools/power/cpupower/bench/config.h @@ -31,6 +31,6 @@ #ifdef DEBUG #define dprintf printf #else -#define dprintf( ... ) while(0) { } +#define dprintf(...) do { } while (0) #endif diff --git a/tools/power/cpupower/bench/main.c b/tools/power/cpupower/bench/main.c index 60953fc93431..24910313a521 100644 --- a/tools/power/cpupower/bench/main.c +++ b/tools/power/cpupower/bench/main.c @@ -28,8 +28,7 @@ #include "system.h" #include "benchmark.h" -static struct option long_options[] = -{ +static struct option long_options[] = { {"output", 1, 0, 'o'}, {"sleep", 1, 0, 's'}, {"load", 1, 0, 'l'}, @@ -50,7 +49,7 @@ static struct option long_options[] = usage *******************************************************************/ -void usage() +void usage() { printf("usage: ./bench\n"); printf("Options:\n"); @@ -67,7 +66,7 @@ void usage() printf(" -o, --output=\t\t\toutput path. Filename will be OUTPUTPATH/benchmark_TIMESTAMP.log\n"); printf(" -v, --verbose\t\t\t\tverbose output on/off\n"); printf(" -h, --help\t\t\t\tPrint this help screen\n"); - exit (1); + exit(1); } /******************************************************************* diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c index 3b270ac92c46..543bba14ae2c 100644 --- a/tools/power/cpupower/bench/parse.c +++ b/tools/power/cpupower/bench/parse.c @@ -86,20 +86,22 @@ FILE *prepare_output(const char *dirname) len += strlen(sysdata.nodename) + strlen(sysdata.release); filename = realloc(filename, sizeof(char) * len); - if(filename == NULL) { + if (filename == NULL) { perror("realloc"); return NULL; } - snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log", + snprintf(filename, len - 1, "%s/benchmark_%s_%s_%li.log", dirname, sysdata.nodename, sysdata.release, time(NULL)); } else { - snprintf(filename, len -1, "%s/benchmark_%li.log", dirname, time(NULL)); + snprintf(filename, len - 1, "%s/benchmark_%li.log", + dirname, time(NULL)); } dprintf("logilename: %s\n", filename); - if ((output = fopen(filename, "w+")) == NULL) { + output = fopen(filename, "w+"); + if (output == NULL) { perror("fopen"); fprintf(stderr, "error: unable to open logfile\n"); } @@ -130,7 +132,7 @@ struct config *prepare_default_config() config->load_step = 500000; config->cycles = 5; config->rounds = 50; - config->cpu = 0; + config->cpu = 0; config->prio = SCHED_HIGH; config->verbose = 0; strncpy(config->governor, "ondemand", 8); @@ -166,13 +168,12 @@ int prepare_config(const char *path, struct config *config) if (configfile == NULL) { perror("fopen"); - fprintf(stderr, "error: unable to read configfile\n"); + fprintf(stderr, "error: unable to read configfile\n"); free(config); return 1; } - while (getline(&line, &len, configfile) != -1) - { + while (getline(&line, &len, configfile) != -1) { if (line[0] == '#' || line[0] == ' ') continue; @@ -183,35 +184,35 @@ int prepare_config(const char *path, struct config *config) if (strncmp("sleep", opt, strlen(opt)) == 0) sscanf(val, "%li", &config->sleep); - else if (strncmp("load", opt, strlen(opt)) == 0) + else if (strncmp("load", opt, strlen(opt)) == 0) sscanf(val, "%li", &config->load); - else if (strncmp("load_step", opt, strlen(opt)) == 0) + else if (strncmp("load_step", opt, strlen(opt)) == 0) sscanf(val, "%li", &config->load_step); - else if (strncmp("sleep_step", opt, strlen(opt)) == 0) + else if (strncmp("sleep_step", opt, strlen(opt)) == 0) sscanf(val, "%li", &config->sleep_step); - else if (strncmp("cycles", opt, strlen(opt)) == 0) + else if (strncmp("cycles", opt, strlen(opt)) == 0) sscanf(val, "%u", &config->cycles); - else if (strncmp("rounds", opt, strlen(opt)) == 0) + else if (strncmp("rounds", opt, strlen(opt)) == 0) sscanf(val, "%u", &config->rounds); - else if (strncmp("verbose", opt, strlen(opt)) == 0) + else if (strncmp("verbose", opt, strlen(opt)) == 0) sscanf(val, "%u", &config->verbose); - else if (strncmp("output", opt, strlen(opt)) == 0) + else if (strncmp("output", opt, strlen(opt)) == 0) config->output = prepare_output(val); - else if (strncmp("cpu", opt, strlen(opt)) == 0) + else if (strncmp("cpu", opt, strlen(opt)) == 0) sscanf(val, "%u", &config->cpu); - else if (strncmp("governor", opt, 14) == 0) + else if (strncmp("governor", opt, 14) == 0) strncpy(config->governor, val, 14); else if (strncmp("priority", opt, strlen(opt)) == 0) { - if (string_to_prio(val) != SCHED_ERR) + if (string_to_prio(val) != SCHED_ERR) config->prio = string_to_prio(val); } } diff --git a/tools/power/cpupower/bench/parse.h b/tools/power/cpupower/bench/parse.h index 9fcdfa23dd9c..a8dc632d9eee 100644 --- a/tools/power/cpupower/bench/parse.h +++ b/tools/power/cpupower/bench/parse.h @@ -20,19 +20,22 @@ /* struct that holds the required config parameters */ struct config { - long sleep; /* sleep time in µs */ - long load; /* load time in µs */ + long sleep; /* sleep time in µs */ + long load; /* load time in µs */ long sleep_step; /* time value which changes the - * sleep time after every round in µs */ + * sleep time after every round in µs */ long load_step; /* time value which changes the - * load time after every round in µs */ + * load time after every round in µs */ unsigned int cycles; /* calculation cycles with the same sleep/load time */ unsigned int rounds; /* calculation rounds with iterated sleep/load time */ unsigned int cpu; /* cpu for which the affinity is set */ char governor[15]; /* cpufreq governor */ enum sched_prio /* possible scheduler priorities */ { - SCHED_ERR=-1,SCHED_HIGH, SCHED_DEFAULT, SCHED_LOW + SCHED_ERR = -1, + SCHED_HIGH, + SCHED_DEFAULT, + SCHED_LOW } prio; unsigned int verbose; /* verbose output */ diff --git a/tools/power/cpupower/bench/system.c b/tools/power/cpupower/bench/system.c index 3e3a82e8bdd9..f01e3f4be84c 100644 --- a/tools/power/cpupower/bench/system.c +++ b/tools/power/cpupower/bench/system.c @@ -31,7 +31,7 @@ #include "system.h" /** - * returns time since epoch in µs + * returns time since epoch in µs * * @retval time **/ @@ -87,7 +87,7 @@ int set_cpufreq_governor(char *governor, unsigned int cpu) int set_cpu_affinity(unsigned int cpu) { cpu_set_t cpuset; - + CPU_ZERO(&cpuset); CPU_SET(cpu, &cpuset); @@ -129,7 +129,7 @@ int set_process_priority(int priority) } /** - * notifys the user that the benchmark may run some time + * notifies the user that the benchmark may run some time * * @param config benchmark config values * @@ -142,8 +142,11 @@ void prepare_user(const struct config *config) unsigned int round; for (round = 0; round < config->rounds; round++) { - sleep_time += 2 * config->cycles * (config->sleep + config->sleep_step * round); - load_time += 2 * config->cycles * (config->load + config->load_step * round) + (config->load + config->load_step * round * 4); + sleep_time += 2 * config->cycles * + (config->sleep + config->sleep_step * round); + load_time += 2 * config->cycles * + (config->load + config->load_step * round) + + (config->load + config->load_step * round * 4); } if (config->verbose || config->output != stdout) -- cgit v1.2.3 From 6c2b8185517fea46bdb1e4e70c7005901fcc89ab Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 19 Apr 2011 19:42:33 +0200 Subject: cpupowerutils: lib - ConfigStyle bugfixes Signed-off-by: Dominik Brodowski --- tools/power/cpupower/lib/cpufreq.c | 72 +++++++----- tools/power/cpupower/lib/cpufreq.h | 54 +++++---- tools/power/cpupower/lib/sysfs.c | 221 +++++++++++++++++++------------------ tools/power/cpupower/lib/sysfs.h | 34 ++++-- 4 files changed, 209 insertions(+), 172 deletions(-) (limited to 'tools') diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c index ae7d8c57b447..d961101d1cea 100644 --- a/tools/power/cpupower/lib/cpufreq.c +++ b/tools/power/cpupower/lib/cpufreq.c @@ -42,21 +42,25 @@ int cpufreq_get_hardware_limits(unsigned int cpu, return sysfs_get_freq_hardware_limits(cpu, min, max); } -char * cpufreq_get_driver(unsigned int cpu) { +char *cpufreq_get_driver(unsigned int cpu) +{ return sysfs_get_freq_driver(cpu); } -void cpufreq_put_driver(char * ptr) { +void cpufreq_put_driver(char *ptr) +{ if (!ptr) return; free(ptr); } -struct cpufreq_policy * cpufreq_get_policy(unsigned int cpu) { +struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu) +{ return sysfs_get_freq_policy(cpu); } -void cpufreq_put_policy(struct cpufreq_policy *policy) { +void cpufreq_put_policy(struct cpufreq_policy *policy) +{ if ((!policy) || (!policy->governor)) return; @@ -65,11 +69,14 @@ void cpufreq_put_policy(struct cpufreq_policy *policy) { free(policy); } -struct cpufreq_available_governors * cpufreq_get_available_governors(unsigned int cpu) { +struct cpufreq_available_governors *cpufreq_get_available_governors(unsigned + int cpu) +{ return sysfs_get_freq_available_governors(cpu); } -void cpufreq_put_available_governors(struct cpufreq_available_governors *any) { +void cpufreq_put_available_governors(struct cpufreq_available_governors *any) +{ struct cpufreq_available_governors *tmp, *next; if (!any) @@ -86,11 +93,14 @@ void cpufreq_put_available_governors(struct cpufreq_available_governors *any) { } -struct cpufreq_available_frequencies * cpufreq_get_available_frequencies(unsigned int cpu) { +struct cpufreq_available_frequencies +*cpufreq_get_available_frequencies(unsigned int cpu) +{ return sysfs_get_available_frequencies(cpu); } -void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies *any) { +void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies + *any) { struct cpufreq_available_frequencies *tmp, *next; if (!any) @@ -105,11 +115,13 @@ void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies *any } -struct cpufreq_affected_cpus * cpufreq_get_affected_cpus(unsigned int cpu) { +struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned int cpu) +{ return sysfs_get_freq_affected_cpus(cpu); } -void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any) { +void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any) +{ struct cpufreq_affected_cpus *tmp, *next; if (!any) @@ -124,16 +136,19 @@ void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *any) { } -struct cpufreq_affected_cpus * cpufreq_get_related_cpus(unsigned int cpu) { +struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned int cpu) +{ return sysfs_get_freq_related_cpus(cpu); } -void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any) { +void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *any) +{ cpufreq_put_affected_cpus(any); } -int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy) { +int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy) +{ if (!policy || !(policy->governor)) return -EINVAL; @@ -141,35 +156,39 @@ int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy) { } -int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq) { +int cpufreq_modify_policy_min(unsigned int cpu, unsigned long min_freq) +{ return sysfs_modify_freq_policy_min(cpu, min_freq); } -int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq) { +int cpufreq_modify_policy_max(unsigned int cpu, unsigned long max_freq) +{ return sysfs_modify_freq_policy_max(cpu, max_freq); } -int cpufreq_modify_policy_governor(unsigned int cpu, char *governor) { +int cpufreq_modify_policy_governor(unsigned int cpu, char *governor) +{ if ((!governor) || (strlen(governor) > 19)) return -EINVAL; return sysfs_modify_freq_policy_governor(cpu, governor); } -int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency) { +int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency) +{ return sysfs_set_frequency(cpu, target_frequency); } -struct cpufreq_stats * cpufreq_get_stats(unsigned int cpu, unsigned long long *total_time) { - struct cpufreq_stats *ret; - - ret = sysfs_get_freq_stats(cpu, total_time); - return (ret); +struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu, + unsigned long long *total_time) +{ + return sysfs_get_freq_stats(cpu, total_time); } -void cpufreq_put_stats(struct cpufreq_stats *any) { +void cpufreq_put_stats(struct cpufreq_stats *any) +{ struct cpufreq_stats *tmp, *next; if (!any) @@ -183,8 +202,7 @@ void cpufreq_put_stats(struct cpufreq_stats *any) { } } -unsigned long cpufreq_get_transitions(unsigned int cpu) { - unsigned long ret = sysfs_get_freq_transitions(cpu); - - return (ret); +unsigned long cpufreq_get_transitions(unsigned int cpu) +{ + return sysfs_get_freq_transitions(cpu); } diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h index 03be906581b5..3aae8e7a0839 100644 --- a/tools/power/cpupower/lib/cpufreq.h +++ b/tools/power/cpupower/lib/cpufreq.h @@ -93,9 +93,9 @@ extern unsigned long cpufreq_get_transition_latency(unsigned int cpu); * considerations by cpufreq policy notifiers in the kernel. */ -extern int cpufreq_get_hardware_limits(unsigned int cpu, - unsigned long *min, - unsigned long *max); +extern int cpufreq_get_hardware_limits(unsigned int cpu, + unsigned long *min, + unsigned long *max); /* determine CPUfreq driver used @@ -104,9 +104,9 @@ extern int cpufreq_get_hardware_limits(unsigned int cpu, * to avoid memory leakage, please. */ -extern char * cpufreq_get_driver(unsigned int cpu); +extern char *cpufreq_get_driver(unsigned int cpu); -extern void cpufreq_put_driver(char * ptr); +extern void cpufreq_put_driver(char *ptr); /* determine CPUfreq policy currently used @@ -116,7 +116,7 @@ extern void cpufreq_put_driver(char * ptr); */ -extern struct cpufreq_policy * cpufreq_get_policy(unsigned int cpu); +extern struct cpufreq_policy *cpufreq_get_policy(unsigned int cpu); extern void cpufreq_put_policy(struct cpufreq_policy *policy); @@ -129,41 +129,47 @@ extern void cpufreq_put_policy(struct cpufreq_policy *policy); */ -extern struct cpufreq_available_governors * cpufreq_get_available_governors(unsigned int cpu); +extern struct cpufreq_available_governors +*cpufreq_get_available_governors(unsigned int cpu); -extern void cpufreq_put_available_governors(struct cpufreq_available_governors *first); +extern void cpufreq_put_available_governors( + struct cpufreq_available_governors *first); /* determine CPU frequency states available * - * only present on _some_ ->target() cpufreq drivers. For information purposes - * only. Please free allocated memory by calling cpufreq_put_available_frequencies - * after use. + * Only present on _some_ ->target() cpufreq drivers. For information purposes + * only. Please free allocated memory by calling + * cpufreq_put_available_frequencies after use. */ -extern struct cpufreq_available_frequencies * cpufreq_get_available_frequencies(unsigned int cpu); +extern struct cpufreq_available_frequencies +*cpufreq_get_available_frequencies(unsigned int cpu); -extern void cpufreq_put_available_frequencies(struct cpufreq_available_frequencies *first); +extern void cpufreq_put_available_frequencies( + struct cpufreq_available_frequencies *first); -/* determine affected CPUs +/* determine affected CPUs * * Remember to call cpufreq_put_affected_cpus when no longer needed * to avoid memory leakage, please. */ -extern struct cpufreq_affected_cpus * cpufreq_get_affected_cpus(unsigned int cpu); +extern struct cpufreq_affected_cpus *cpufreq_get_affected_cpus(unsigned + int cpu); extern void cpufreq_put_affected_cpus(struct cpufreq_affected_cpus *first); -/* determine related CPUs +/* determine related CPUs * * Remember to call cpufreq_put_related_cpus when no longer needed * to avoid memory leakage, please. */ -extern struct cpufreq_affected_cpus * cpufreq_get_related_cpus(unsigned int cpu); +extern struct cpufreq_affected_cpus *cpufreq_get_related_cpus(unsigned + int cpu); extern void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first); @@ -173,15 +179,16 @@ extern void cpufreq_put_related_cpus(struct cpufreq_affected_cpus *first); * This is not available in all kernel versions or configurations. */ -extern struct cpufreq_stats * cpufreq_get_stats(unsigned int cpu, unsigned long long *total_time); +extern struct cpufreq_stats *cpufreq_get_stats(unsigned int cpu, + unsigned long long *total_time); extern void cpufreq_put_stats(struct cpufreq_stats *stats); extern unsigned long cpufreq_get_transitions(unsigned int cpu); -/* set new cpufreq policy - * +/* set new cpufreq policy + * * Tries to set the passed policy as new policy as close as possible, * but results may differ depending e.g. on governors being available. */ @@ -189,7 +196,7 @@ extern unsigned long cpufreq_get_transitions(unsigned int cpu); extern int cpufreq_set_policy(unsigned int cpu, struct cpufreq_policy *policy); -/* modify a policy by only changing min/max freq or governor +/* modify a policy by only changing min/max freq or governor * * Does not check whether result is what was intended. */ @@ -202,11 +209,12 @@ extern int cpufreq_modify_policy_governor(unsigned int cpu, char *governor); /* set a specific frequency * * Does only work if userspace governor can be used and no external - * interference (other calls to this function or to set/modify_policy) + * interference (other calls to this function or to set/modify_policy) * occurs. Also does not work on ->range() cpufreq drivers. */ -extern int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency); +extern int cpufreq_set_frequency(unsigned int cpu, + unsigned long target_frequency); #ifdef __cplusplus } diff --git a/tools/power/cpupower/lib/sysfs.c b/tools/power/cpupower/lib/sysfs.c index c9b061fe87b1..9a35456ba6b2 100644 --- a/tools/power/cpupower/lib/sysfs.c +++ b/tools/power/cpupower/lib/sysfs.c @@ -24,14 +24,14 @@ static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen) { int fd; - size_t numread; + ssize_t numread; - if ( ( fd = open(path, O_RDONLY) ) == -1 ) + fd = open(path, O_RDONLY); + if (fd == -1) return 0; numread = read(fd, buf, buflen - 1); - if ( numread < 1 ) - { + if (numread < 1) { close(fd); return 0; } @@ -39,7 +39,7 @@ static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen) buf[numread] = '\0'; close(fd); - return numread; + return (unsigned int) numread; } @@ -65,24 +65,24 @@ static unsigned int sysfs_cpufreq_write_file(unsigned int cpu, { char path[SYSFS_PATH_MAX]; int fd; - size_t numwrite; + ssize_t numwrite; snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s", cpu, fname); - if ( ( fd = open(path, O_WRONLY) ) == -1 ) + fd = open(path, O_WRONLY); + if (fd == -1) return 0; numwrite = write(fd, value, len); - if ( numwrite < 1 ) - { + if (numwrite < 1) { close(fd); return 0; } close(fd); - return numwrite; + return (unsigned int) numwrite; } /* read access to files which contain one numeric value */ @@ -114,21 +114,23 @@ static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = { static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu, enum cpufreq_value which) { - unsigned long value; + unsigned long value; unsigned int len; char linebuf[MAX_LINE_LEN]; char *endp; - if ( which >= MAX_CPUFREQ_VALUE_READ_FILES ) + if (which >= MAX_CPUFREQ_VALUE_READ_FILES) return 0; - if ( ( len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which], - linebuf, sizeof(linebuf))) == 0 ) + len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which], + linebuf, sizeof(linebuf)); + + if (len == 0) return 0; value = strtoul(linebuf, &endp, 0); - if ( endp == linebuf || errno == ERANGE ) + if (endp == linebuf || errno == ERANGE) return 0; return value; @@ -148,7 +150,7 @@ static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = { }; -static char * sysfs_cpufreq_get_one_string(unsigned int cpu, +static char *sysfs_cpufreq_get_one_string(unsigned int cpu, enum cpufreq_string which) { char linebuf[MAX_LINE_LEN]; @@ -158,11 +160,13 @@ static char * sysfs_cpufreq_get_one_string(unsigned int cpu, if (which >= MAX_CPUFREQ_STRING_FILES) return NULL; - if ( ( len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which], - linebuf, sizeof(linebuf))) == 0 ) + len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which], + linebuf, sizeof(linebuf)); + if (len == 0) return NULL; - if ( ( result = strdup(linebuf) ) == NULL ) + result = strdup(linebuf); + if (result == NULL) return NULL; if (result[strlen(result) - 1] == '\n') @@ -195,8 +199,8 @@ static int sysfs_cpufreq_write_one_value(unsigned int cpu, if (which >= MAX_CPUFREQ_WRITE_FILES) return 0; - if ( sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which], - new_value, len) != len ) + if (sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which], + new_value, len) != len) return -ENODEV; return 0; @@ -235,11 +239,13 @@ int sysfs_get_freq_hardware_limits(unsigned int cpu, return 0; } -char * sysfs_get_freq_driver(unsigned int cpu) { +char *sysfs_get_freq_driver(unsigned int cpu) +{ return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER); } -struct cpufreq_policy * sysfs_get_freq_policy(unsigned int cpu) { +struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu) +{ struct cpufreq_policy *policy; policy = malloc(sizeof(struct cpufreq_policy)); @@ -270,27 +276,24 @@ sysfs_get_freq_available_governors(unsigned int cpu) { unsigned int pos, i; unsigned int len; - if ( ( len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors", - linebuf, sizeof(linebuf))) == 0 ) - { + len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors", + linebuf, sizeof(linebuf)); + if (len == 0) return NULL; - } pos = 0; - for ( i = 0; i < len; i++ ) - { - if ( linebuf[i] == ' ' || linebuf[i] == '\n' ) - { - if ( i - pos < 2 ) + for (i = 0; i < len; i++) { + if (linebuf[i] == ' ' || linebuf[i] == '\n') { + if (i - pos < 2) continue; - if ( current ) { - current->next = malloc(sizeof *current ); - if ( ! current->next ) + if (current) { + current->next = malloc(sizeof(*current)); + if (!current->next) goto error_out; current = current->next; } else { - first = malloc( sizeof *first ); - if ( ! first ) + first = malloc(sizeof(*first)); + if (!first) goto error_out; current = first; } @@ -298,10 +301,10 @@ sysfs_get_freq_available_governors(unsigned int cpu) { current->next = NULL; current->governor = malloc(i - pos + 1); - if ( ! current->governor ) + if (!current->governor) goto error_out; - memcpy( current->governor, linebuf + pos, i - pos); + memcpy(current->governor, linebuf + pos, i - pos); current->governor[i - pos] = '\0'; pos = i + 1; } @@ -310,11 +313,11 @@ sysfs_get_freq_available_governors(unsigned int cpu) { return first; error_out: - while ( first ) { + while (first) { current = first->next; - if ( first->governor ) - free( first->governor ); - free( first ); + if (first->governor) + free(first->governor); + free(first); first = current; } return NULL; @@ -330,30 +333,26 @@ sysfs_get_available_frequencies(unsigned int cpu) { unsigned int pos, i; unsigned int len; - if ( ( len = sysfs_cpufreq_read_file(cpu, - "scaling_available_frequencies", - linebuf, sizeof(linebuf))) == 0 ) - { + len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies", + linebuf, sizeof(linebuf)); + if (len == 0) return NULL; - } pos = 0; - for ( i = 0; i < len; i++ ) - { - if ( linebuf[i] == ' ' || linebuf[i] == '\n' ) - { - if ( i - pos < 2 ) + for (i = 0; i < len; i++) { + if (linebuf[i] == ' ' || linebuf[i] == '\n') { + if (i - pos < 2) continue; - if ( i - pos >= SYSFS_PATH_MAX ) + if (i - pos >= SYSFS_PATH_MAX) goto error_out; - if ( current ) { - current->next = malloc(sizeof *current ); - if ( ! current->next ) + if (current) { + current->next = malloc(sizeof(*current)); + if (!current->next) goto error_out; current = current->next; } else { - first = malloc(sizeof *first ); - if ( ! first ) + first = malloc(sizeof(*first)); + if (!first) goto error_out; current = first; } @@ -362,7 +361,7 @@ sysfs_get_available_frequencies(unsigned int cpu) { memcpy(one_value, linebuf + pos, i - pos); one_value[i - pos] = '\0'; - if ( sscanf(one_value, "%lu", ¤t->frequency) != 1 ) + if (sscanf(one_value, "%lu", ¤t->frequency) != 1) goto error_out; pos = i + 1; @@ -372,7 +371,7 @@ sysfs_get_available_frequencies(unsigned int cpu) { return first; error_out: - while ( first ) { + while (first) { current = first->next; free(first); first = current; @@ -380,8 +379,9 @@ sysfs_get_available_frequencies(unsigned int cpu) { return NULL; } -static struct cpufreq_affected_cpus * sysfs_get_cpu_list(unsigned int cpu, - const char *file) { +static struct cpufreq_affected_cpus *sysfs_get_cpu_list(unsigned int cpu, + const char *file) +{ struct cpufreq_affected_cpus *first = NULL; struct cpufreq_affected_cpus *current = NULL; char one_value[SYSFS_PATH_MAX]; @@ -389,29 +389,25 @@ static struct cpufreq_affected_cpus * sysfs_get_cpu_list(unsigned int cpu, unsigned int pos, i; unsigned int len; - if ( ( len = sysfs_cpufreq_read_file(cpu, file, linebuf, - sizeof(linebuf))) == 0 ) - { + len = sysfs_cpufreq_read_file(cpu, file, linebuf, sizeof(linebuf)); + if (len == 0) return NULL; - } pos = 0; - for ( i = 0; i < len; i++ ) - { - if ( i == len || linebuf[i] == ' ' || linebuf[i] == '\n' ) - { - if ( i - pos < 1 ) + for (i = 0; i < len; i++) { + if (i == len || linebuf[i] == ' ' || linebuf[i] == '\n') { + if (i - pos < 1) continue; - if ( i - pos >= SYSFS_PATH_MAX ) + if (i - pos >= SYSFS_PATH_MAX) goto error_out; - if ( current ) { - current->next = malloc(sizeof *current); - if ( ! current->next ) + if (current) { + current->next = malloc(sizeof(*current)); + if (!current->next) goto error_out; current = current->next; } else { - first = malloc(sizeof *first); - if ( ! first ) + first = malloc(sizeof(*first)); + if (!first) goto error_out; current = first; } @@ -421,7 +417,7 @@ static struct cpufreq_affected_cpus * sysfs_get_cpu_list(unsigned int cpu, memcpy(one_value, linebuf + pos, i - pos); one_value[i - pos] = '\0'; - if ( sscanf(one_value, "%u", ¤t->cpu) != 1 ) + if (sscanf(one_value, "%u", ¤t->cpu) != 1) goto error_out; pos = i + 1; @@ -439,15 +435,18 @@ static struct cpufreq_affected_cpus * sysfs_get_cpu_list(unsigned int cpu, return NULL; } -struct cpufreq_affected_cpus * sysfs_get_freq_affected_cpus(unsigned int cpu) { +struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(unsigned int cpu) +{ return sysfs_get_cpu_list(cpu, "affected_cpus"); } -struct cpufreq_affected_cpus * sysfs_get_freq_related_cpus(unsigned int cpu) { +struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(unsigned int cpu) +{ return sysfs_get_cpu_list(cpu, "related_cpus"); } -struct cpufreq_stats * sysfs_get_freq_stats(unsigned int cpu, unsigned long long *total_time) { +struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu, + unsigned long long *total_time) { struct cpufreq_stats *first = NULL; struct cpufreq_stats *current = NULL; char one_value[SYSFS_PATH_MAX]; @@ -455,28 +454,27 @@ struct cpufreq_stats * sysfs_get_freq_stats(unsigned int cpu, unsigned long long unsigned int pos, i; unsigned int len; - if ( ( len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state", - linebuf, sizeof(linebuf))) == 0 ) + len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state", + linebuf, sizeof(linebuf)); + if (len == 0) return NULL; *total_time = 0; pos = 0; - for ( i = 0; i < len; i++ ) - { - if ( i == strlen(linebuf) || linebuf[i] == '\n' ) - { - if ( i - pos < 2 ) + for (i = 0; i < len; i++) { + if (i == strlen(linebuf) || linebuf[i] == '\n') { + if (i - pos < 2) continue; - if ( (i - pos) >= SYSFS_PATH_MAX ) + if ((i - pos) >= SYSFS_PATH_MAX) goto error_out; - if ( current ) { - current->next = malloc(sizeof *current ); - if ( ! current->next ) + if (current) { + current->next = malloc(sizeof(*current)); + if (!current->next) goto error_out; current = current->next; } else { - first = malloc(sizeof *first ); - if ( ! first ) + first = malloc(sizeof(*first)); + if (!first) goto error_out; current = first; } @@ -485,7 +483,9 @@ struct cpufreq_stats * sysfs_get_freq_stats(unsigned int cpu, unsigned long long memcpy(one_value, linebuf + pos, i - pos); one_value[i - pos] = '\0'; - if ( sscanf(one_value, "%lu %llu", ¤t->frequency, ¤t->time_in_state) != 2 ) + if (sscanf(one_value, "%lu %llu", + ¤t->frequency, + ¤t->time_in_state) != 2) goto error_out; *total_time = *total_time + current->time_in_state; @@ -496,7 +496,7 @@ struct cpufreq_stats * sysfs_get_freq_stats(unsigned int cpu, unsigned long long return first; error_out: - while ( first ) { + while (first) { current = first->next; free(first); first = current; @@ -511,29 +511,29 @@ unsigned long sysfs_get_freq_transitions(unsigned int cpu) static int verify_gov(char *new_gov, char *passed_gov) { - unsigned int i, j=0; + unsigned int i, j = 0; if (!passed_gov || (strlen(passed_gov) > 19)) return -EINVAL; strncpy(new_gov, passed_gov, 20); - for (i=0;i<20;i++) { + for (i = 0; i < 20; i++) { if (j) { new_gov[i] = '\0'; continue; } - if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z')) { + if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z')) continue; - } - if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z')) { + + if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z')) continue; - } - if (new_gov[i] == '-') { + + if (new_gov[i] == '-') continue; - } - if (new_gov[i] == '_') { + + if (new_gov[i] == '_') continue; - } + if (new_gov[i] == '\0') { j = 1; continue; @@ -627,7 +627,8 @@ int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy) gov, strlen(gov)); } -int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency) { +int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency) +{ struct cpufreq_policy *pol = sysfs_get_freq_policy(cpu); char userspace_gov[] = "userspace"; char freq[SYSFS_PATH_MAX]; @@ -640,7 +641,7 @@ int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency) { ret = sysfs_modify_freq_policy_governor(cpu, userspace_gov); if (ret) { cpufreq_put_policy(pol); - return (ret); + return ret; } } @@ -662,7 +663,7 @@ int sysfs_cpu_exists(unsigned int cpu) snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/", cpu); - if ( stat(file, &statbuf) != 0 ) + if (stat(file, &statbuf) != 0) return -ENOSYS; return S_ISDIR(statbuf.st_mode) ? 0 : -ENOSYS; diff --git a/tools/power/cpupower/lib/sysfs.h b/tools/power/cpupower/lib/sysfs.h index c29e5575be8a..c76a5e0af501 100644 --- a/tools/power/cpupower/lib/sysfs.h +++ b/tools/power/cpupower/lib/sysfs.h @@ -5,17 +5,27 @@ extern unsigned int sysfs_cpu_exists(unsigned int cpu); extern unsigned long sysfs_get_freq_kernel(unsigned int cpu); extern unsigned long sysfs_get_freq_hardware(unsigned int cpu); extern unsigned long sysfs_get_freq_transition_latency(unsigned int cpu); -extern int sysfs_get_freq_hardware_limits(unsigned int cpu, unsigned long *min, unsigned long *max); -extern char * sysfs_get_freq_driver(unsigned int cpu); -extern struct cpufreq_policy * sysfs_get_freq_policy(unsigned int cpu); -extern struct cpufreq_available_governors * sysfs_get_freq_available_governors(unsigned int cpu); -extern struct cpufreq_available_frequencies * sysfs_get_available_frequencies(unsigned int cpu); -extern struct cpufreq_affected_cpus * sysfs_get_freq_affected_cpus(unsigned int cpu); -extern struct cpufreq_affected_cpus * sysfs_get_freq_related_cpus(unsigned int cpu); -extern struct cpufreq_stats * sysfs_get_freq_stats(unsigned int cpu, unsigned long long *total_time); +extern int sysfs_get_freq_hardware_limits(unsigned int cpu, + unsigned long *min, unsigned long *max); +extern char *sysfs_get_freq_driver(unsigned int cpu); +extern struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu); +extern struct cpufreq_available_governors *sysfs_get_freq_available_governors( + unsigned int cpu); +extern struct cpufreq_available_frequencies *sysfs_get_available_frequencies( + unsigned int cpu); +extern struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus( + unsigned int cpu); +extern struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus( + unsigned int cpu); +extern struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu, + unsigned long long *total_time); extern unsigned long sysfs_get_freq_transitions(unsigned int cpu); -extern int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy); -extern int sysfs_modify_freq_policy_min(unsigned int cpu, unsigned long min_freq); -extern int sysfs_modify_freq_policy_max(unsigned int cpu, unsigned long max_freq); +extern int sysfs_set_freq_policy(unsigned int cpu, + struct cpufreq_policy *policy); +extern int sysfs_modify_freq_policy_min(unsigned int cpu, + unsigned long min_freq); +extern int sysfs_modify_freq_policy_max(unsigned int cpu, + unsigned long max_freq); extern int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor); -extern int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency); +extern int sysfs_set_frequency(unsigned int cpu, + unsigned long target_frequency); -- cgit v1.2.3 From b510b54127a4d4112a9a3f200339719bcb463c15 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 19 Apr 2011 19:58:59 +0200 Subject: cpupowerutils: idle_monitor - ConfigStyle bugfixes Signed-off-by: Dominik Brodowski --- .../cpupower/utils/idle_monitor/amd_fam14h_idle.c | 20 +++---- .../cpupower/utils/idle_monitor/cpuidle_sysfs.c | 65 +++++++++++++--------- .../cpupower/utils/idle_monitor/cpupower-monitor.c | 64 ++++++++++----------- .../cpupower/utils/idle_monitor/mperf_monitor.c | 33 +++++------ tools/power/cpupower/utils/idle_monitor/nhm_idle.c | 30 +++++----- tools/power/cpupower/utils/idle_monitor/snb_idle.c | 31 ++++++----- 6 files changed, 128 insertions(+), 115 deletions(-) (limited to 'tools') diff --git a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c index 3de94322dfb8..202e555988be 100644 --- a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c +++ b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c @@ -104,7 +104,7 @@ static int amd_fam14h_get_pci_info(struct cstate *state, unsigned int *enable_bit, unsigned int cpu) { - switch(state->id) { + switch (state->id) { case NON_PC0: *enable_bit = PCI_NON_PC0_ENABLE_BIT; *pci_offset = PCI_NON_PC0_OFFSET; @@ -177,7 +177,7 @@ static int amd_fam14h_disable(cstate_t *state, unsigned int cpu) /* was the bit whether NBP1 got entered set? */ nbp1_entered = (val & (1 << PCI_NBP1_ACTIVE_BIT)) | (val & (1 << PCI_NBP1_ENTERED_BIT)); - + dprint("NBP1 was %sentered - 0x%x - enable_bit: " "%d - pci_offset: 0x%x\n", nbp1_entered ? "" : "not ", @@ -214,7 +214,7 @@ static int fam14h_get_count_percent(unsigned int id, double *percent, unsigned int cpu) { unsigned long diff; - + if (id >= AMD_FAM14H_STATE_NUM) return -1; /* residency count in 80ns -> divide through 12.5 to get us residency */ @@ -236,9 +236,8 @@ static int amd_fam14h_start(void) int num, cpu; clock_gettime(CLOCK_REALTIME, &start_time); for (num = 0; num < AMD_FAM14H_STATE_NUM; num++) { - for (cpu = 0; cpu < cpu_count; cpu++) { + for (cpu = 0; cpu < cpu_count; cpu++) amd_fam14h_init(&amd_fam14h_cstates[num], cpu); - } } #ifdef DEBUG clock_gettime(CLOCK_REALTIME, &dbg_time); @@ -257,9 +256,8 @@ static int amd_fam14h_stop(void) clock_gettime(CLOCK_REALTIME, &end_time); for (num = 0; num < AMD_FAM14H_STATE_NUM; num++) { - for (cpu = 0; cpu < cpu_count; cpu++) { + for (cpu = 0; cpu < cpu_count; cpu++) amd_fam14h_disable(&amd_fam14h_cstates[num], cpu); - } } #ifdef DEBUG clock_gettime(CLOCK_REALTIME, &dbg_time); @@ -281,8 +279,8 @@ static int is_nbp1_capable(void) return val & (1 << 31); } -struct cpuidle_monitor* amd_fam14h_register(void) { - +struct cpuidle_monitor *amd_fam14h_register(void) +{ int num; if (cpupower_cpu_info.vendor != X86_VENDOR_AMD) @@ -299,9 +297,9 @@ struct cpuidle_monitor* amd_fam14h_register(void) { /* We do not alloc for nbp1 machine wide counter */ for (num = 0; num < AMD_FAM14H_STATE_NUM - 1; num++) { - previous_count[num] = calloc (cpu_count, + previous_count[num] = calloc(cpu_count, sizeof(unsigned long long)); - current_count[num] = calloc (cpu_count, + current_count[num] = calloc(cpu_count, sizeof(unsigned long long)); } diff --git a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c index 63f6d670517b..d048b96a6155 100644 --- a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c +++ b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c @@ -36,10 +36,10 @@ static int cpuidle_get_count_percent(unsigned int id, double *percent, *percent = 0.0; else *percent = ((100.0 * statediff) / timediff); - + dprint("%s: - timediff: %llu - statediff: %llu - percent: %f (%u)\n", cpuidle_cstates[id].name, timediff, statediff, *percent, cpu); - + return 0; } @@ -55,7 +55,6 @@ static int cpuidle_start(void) dprint("CPU %d - State: %d - Val: %llu\n", cpu, state, previous_count[cpu][state]); } - }; return 0; } @@ -83,40 +82,51 @@ void fix_up_intel_idle_driver_name(char *tmp, int num) { /* fix up cpuidle name for intel idle driver */ if (!strncmp(tmp, "NHM-", 4)) { - switch(num) { - case 1: strcpy(tmp, "C1"); + switch (num) { + case 1: + strcpy(tmp, "C1"); break; - case 2: strcpy(tmp, "C3"); + case 2: + strcpy(tmp, "C3"); break; - case 3: strcpy(tmp, "C6"); + case 3: + strcpy(tmp, "C6"); break; } } else if (!strncmp(tmp, "SNB-", 4)) { - switch(num) { - case 1: strcpy(tmp, "C1"); + switch (num) { + case 1: + strcpy(tmp, "C1"); break; - case 2: strcpy(tmp, "C3"); + case 2: + strcpy(tmp, "C3"); break; - case 3: strcpy(tmp, "C6"); + case 3: + strcpy(tmp, "C6"); break; - case 4: strcpy(tmp, "C7"); + case 4: + strcpy(tmp, "C7"); break; } } else if (!strncmp(tmp, "ATM-", 4)) { - switch(num) { - case 1: strcpy(tmp, "C1"); + switch (num) { + case 1: + strcpy(tmp, "C1"); break; - case 2: strcpy(tmp, "C2"); + case 2: + strcpy(tmp, "C2"); break; - case 3: strcpy(tmp, "C4"); + case 3: + strcpy(tmp, "C4"); break; - case 4: strcpy(tmp, "C6"); + case 4: + strcpy(tmp, "C6"); break; } } } -static struct cpuidle_monitor* cpuidle_register(void) +static struct cpuidle_monitor *cpuidle_register(void) { int num; char *tmp; @@ -127,7 +137,7 @@ static struct cpuidle_monitor* cpuidle_register(void) if (cpuidle_sysfs_monitor.hw_states_num == 0) return NULL; - for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num ++) { + for (num = 0; num < cpuidle_sysfs_monitor.hw_states_num; num++) { tmp = sysfs_get_idlestate_name(0, num); if (tmp == NULL) continue; @@ -144,17 +154,18 @@ static struct cpuidle_monitor* cpuidle_register(void) cpuidle_cstates[num].range = RANGE_THREAD; cpuidle_cstates[num].id = num; - cpuidle_cstates[num].get_count_percent = cpuidle_get_count_percent; - }; + cpuidle_cstates[num].get_count_percent = + cpuidle_get_count_percent; + }; /* Free this at program termination */ - previous_count = malloc(sizeof (long long*) * cpu_count); - current_count = malloc(sizeof (long long*) * cpu_count); + previous_count = malloc(sizeof(long long *) * cpu_count); + current_count = malloc(sizeof(long long *) * cpu_count); for (num = 0; num < cpu_count; num++) { - previous_count[num] = malloc (sizeof(long long) * - cpuidle_sysfs_monitor.hw_states_num); - current_count[num] = malloc (sizeof(long long) * - cpuidle_sysfs_monitor.hw_states_num); + previous_count[num] = malloc(sizeof(long long) * + cpuidle_sysfs_monitor.hw_states_num); + current_count[num] = malloc(sizeof(long long) * + cpuidle_sysfs_monitor.hw_states_num); } cpuidle_sysfs_monitor.name_len = strlen(cpuidle_sysfs_monitor.name); diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c index 3e96e79de3c2..ba4bf068380d 100644 --- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c +++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c @@ -24,7 +24,7 @@ /* Define pointers to all monitors. */ #define DEF(x) & x ## _monitor , -struct cpuidle_monitor * all_monitors[] = { +struct cpuidle_monitor *all_monitors[] = { #include "idle_monitors.def" 0 }; @@ -76,19 +76,19 @@ void print_n_spaces(int n) int x; for (x = 0; x < n; x++) printf(" "); -} +} /* size of s must be at least n + 1 */ int fill_string_with_spaces(char *s, int n) { - int len = strlen(s); + int len = strlen(s); if (len > n) return -1; - for (; len < n; len++) - s[len] = ' '; - s[len] = '\0'; + for (; len < n; len++) + s[len] = ' '; + s[len] = '\0'; return 0; -} +} void print_header(int topology_depth) { @@ -107,7 +107,7 @@ void print_header(int topology_depth) - 1; if (mon != 0) { printf("|| "); - need_len --; + need_len--; } sprintf(buf, "%s", monitors[mon]->name); fill_string_with_spaces(buf, need_len); @@ -169,26 +169,24 @@ void print_results(int topology_depth, int cpu) if (s.get_count_percent) { ret = s.get_count_percent(s.id, &percent, cpu_top.core_info[cpu].cpu); - if (ret) { + if (ret) printf("******"); - } else if (percent >= 100.0) + else if (percent >= 100.0) printf("%6.1f", percent); else printf("%6.2f", percent); - } - else if (s.get_count) { + } else if (s.get_count) { ret = s.get_count(s.id, &result, cpu_top.core_info[cpu].cpu); - if (ret) { + if (ret) printf("******"); - } else + else printf("%6llu", result); - } - else { + } else { printf(_("Monitor %s, Counter %s has no count " "function. Implementation error\n"), monitors[mon]->name, s.name); - exit (EXIT_FAILURE); + exit(EXIT_FAILURE); } } } @@ -211,7 +209,7 @@ void print_results(int topology_depth, int cpu) * Monitors get sorted in the same order the user passes them */ -static void parse_monitor_param(char* param) +static void parse_monitor_param(char *param) { unsigned int num; int mon, hits = 0; @@ -219,7 +217,7 @@ static void parse_monitor_param(char* param) struct cpuidle_monitor *tmp_mons[MONITORS_MAX]; - for (mon = 0; mon < MONITORS_MAX;mon++, tmp = NULL) { + for (mon = 0; mon < MONITORS_MAX; mon++, tmp = NULL) { token = strtok(tmp, ","); if (token == NULL) break; @@ -235,7 +233,7 @@ static void parse_monitor_param(char* param) tmp_mons[hits] = monitors[num]; hits++; } - } + } } if (hits == 0) { printf(_("No matching monitor found in %s, " @@ -244,20 +242,23 @@ static void parse_monitor_param(char* param) exit(EXIT_FAILURE); } /* Override detected/registerd monitors array with requested one */ - memcpy(monitors, tmp_mons, sizeof(struct cpuidle_monitor*) * MONITORS_MAX); + memcpy(monitors, tmp_mons, + sizeof(struct cpuidle_monitor *) * MONITORS_MAX); avail_monitors = hits; } -void list_monitors(void) { +void list_monitors(void) +{ unsigned int mon; int state; cstate_t s; for (mon = 0; mon < avail_monitors; mon++) { printf(_("Monitor \"%s\" (%d states) - Might overflow after %u " - "s\n"), monitors[mon]->name, monitors[mon]->hw_states_num, - monitors[mon]->overflow_s); - + "s\n"), + monitors[mon]->name, monitors[mon]->hw_states_num, + monitors[mon]->overflow_s); + for (state = 0; state < monitors[mon]->hw_states_num; state++) { s = monitors[mon]->hw_states[state]; /* @@ -308,7 +309,8 @@ int fork_it(char **argv) timediff = timespec_diff_us(start, end); if (WIFEXITED(status)) printf(_("%s took %.5f seconds and exited with status %d\n"), - argv[0], timediff / (1000.0 * 1000), WEXITSTATUS(status)); + argv[0], timediff / (1000.0 * 1000), + WEXITSTATUS(status)); return 0; } @@ -322,9 +324,9 @@ int do_interval_measure(int i) monitors[num]->start(); } sleep(i); - for (num = 0; num < avail_monitors; num++) { + for (num = 0; num < avail_monitors; num++) monitors[num]->stop(); - } + return 0; } @@ -384,7 +386,7 @@ int cmd_monitor(int argc, char **argv) } dprint("System has up to %d CPU cores\n", cpu_count); - + for (num = 0; all_monitors[num]; num++) { dprint("Try to register: %s\n", all_monitors[num]->name); test_mon = all_monitors[num]->do_register(); @@ -438,9 +440,9 @@ int cmd_monitor(int argc, char **argv) print_results(1, cpu); } - for (num = 0; num < avail_monitors; num++) { + for (num = 0; num < avail_monitors; num++) monitors[num]->unregister(); - } + cpu_topology_release(cpu_top); return 0; } diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c index f8545e40e232..63ca87a05e5f 100644 --- a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c +++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c @@ -79,7 +79,7 @@ static int mperf_init_stats(unsigned int cpu) ret |= read_msr(cpu, MSR_MPERF, &val); mperf_previous_count[cpu] = val; is_valid[cpu] = !ret; - + return 0; } @@ -93,7 +93,7 @@ static int mperf_measure_stats(unsigned int cpu) ret |= read_msr(cpu, MSR_MPERF, &val); mperf_current_count[cpu] = val; is_valid[cpu] = !ret; - + return 0; } @@ -145,14 +145,14 @@ static int mperf_get_count_percent(unsigned int id, double *percent, if (id == Cx) *percent = 100.0 - *percent; - dprint("%s: previous: %llu - current: %llu - (%u)\n", mperf_cstates[id].name, - mperf_diff, aperf_diff, cpu); + dprint("%s: previous: %llu - current: %llu - (%u)\n", + mperf_cstates[id].name, mperf_diff, aperf_diff, cpu); dprint("%s: %f\n", mperf_cstates[id].name, *percent); return 0; } static int mperf_get_count_freq(unsigned int id, unsigned long long *count, - unsigned int cpu) + unsigned int cpu) { unsigned long long aperf_diff, mperf_diff; @@ -206,8 +206,8 @@ static int mperf_stop(void) struct cpuidle_monitor mperf_monitor; -struct cpuidle_monitor* mperf_register(void) { - +struct cpuidle_monitor *mperf_register(void) +{ unsigned long min; if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_APERF)) @@ -221,21 +221,18 @@ struct cpuidle_monitor* mperf_register(void) { } /* Free this at program termination */ - is_valid = calloc(cpu_count, sizeof (int)); - mperf_previous_count = calloc (cpu_count, - sizeof(unsigned long long)); - aperf_previous_count = calloc (cpu_count, - sizeof(unsigned long long)); - mperf_current_count = calloc (cpu_count, - sizeof(unsigned long long)); - aperf_current_count = calloc (cpu_count, - sizeof(unsigned long long)); - + is_valid = calloc(cpu_count, sizeof(int)); + mperf_previous_count = calloc(cpu_count, sizeof(unsigned long long)); + aperf_previous_count = calloc(cpu_count, sizeof(unsigned long long)); + mperf_current_count = calloc(cpu_count, sizeof(unsigned long long)); + aperf_current_count = calloc(cpu_count, sizeof(unsigned long long)); + mperf_monitor.name_len = strlen(mperf_monitor.name); return &mperf_monitor; } -void mperf_unregister(void) { +void mperf_unregister(void) +{ free(mperf_previous_count); free(aperf_previous_count); free(mperf_current_count); diff --git a/tools/power/cpupower/utils/idle_monitor/nhm_idle.c b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c index 6424b6dd3fa5..d2a91dd0d563 100644 --- a/tools/power/cpupower/utils/idle_monitor/nhm_idle.c +++ b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c @@ -69,11 +69,12 @@ static unsigned long long *current_count[NHM_CSTATE_COUNT]; /* valid flag for all CPUs. If a MSR read failed it will be zero */ static int *is_valid; -static int nhm_get_count(enum intel_nhm_id id, unsigned long long *val, unsigned int cpu) +static int nhm_get_count(enum intel_nhm_id id, unsigned long long *val, + unsigned int cpu) { int msr; - switch(id) { + switch (id) { case C3: msr = MSR_CORE_C3_RESIDENCY; break; @@ -106,12 +107,13 @@ static int nhm_get_count_percent(unsigned int id, double *percent, if (!is_valid[cpu]) return -1; - *percent = (100.0 * (current_count[id][cpu] - previous_count[id][cpu])) / + *percent = (100.0 * + (current_count[id][cpu] - previous_count[id][cpu])) / (tsc_at_measure_end - tsc_at_measure_start); - dprint("%s: previous: %llu - current: %llu - (%u)\n", nhm_cstates[id].name, - previous_count[id][cpu], current_count[id][cpu], - cpu); + dprint("%s: previous: %llu - current: %llu - (%u)\n", + nhm_cstates[id].name, previous_count[id][cpu], + current_count[id][cpu], cpu); dprint("%s: tsc_diff: %llu - count_diff: %llu - percent: %2.f (%u)\n", nhm_cstates[id].name, @@ -162,7 +164,8 @@ static int nhm_stop(void) struct cpuidle_monitor intel_nhm_monitor; -struct cpuidle_monitor* intel_nhm_register(void) { +struct cpuidle_monitor *intel_nhm_register(void) +{ int num; if (cpupower_cpu_info.vendor != X86_VENDOR_INTEL) @@ -175,19 +178,20 @@ struct cpuidle_monitor* intel_nhm_register(void) { return NULL; /* Free this at program termination */ - is_valid = calloc(cpu_count, sizeof (int)); + is_valid = calloc(cpu_count, sizeof(int)); for (num = 0; num < NHM_CSTATE_COUNT; num++) { - previous_count[num] = calloc (cpu_count, - sizeof(unsigned long long)); - current_count[num] = calloc (cpu_count, - sizeof(unsigned long long)); + previous_count[num] = calloc(cpu_count, + sizeof(unsigned long long)); + current_count[num] = calloc(cpu_count, + sizeof(unsigned long long)); } intel_nhm_monitor.name_len = strlen(intel_nhm_monitor.name); return &intel_nhm_monitor; } -void intel_nhm_unregister(void) { +void intel_nhm_unregister(void) +{ int num; for (num = 0; num < NHM_CSTATE_COUNT; num++) { diff --git a/tools/power/cpupower/utils/idle_monitor/snb_idle.c b/tools/power/cpupower/utils/idle_monitor/snb_idle.c index 8cc80a5b530c..a1bc07cd53e1 100644 --- a/tools/power/cpupower/utils/idle_monitor/snb_idle.c +++ b/tools/power/cpupower/utils/idle_monitor/snb_idle.c @@ -58,11 +58,12 @@ static unsigned long long *current_count[SNB_CSTATE_COUNT]; /* valid flag for all CPUs. If a MSR read failed it will be zero */ static int *is_valid; -static int snb_get_count(enum intel_snb_id id, unsigned long long *val, unsigned int cpu) +static int snb_get_count(enum intel_snb_id id, unsigned long long *val, + unsigned int cpu) { int msr; - switch(id) { + switch (id) { case C7: msr = MSR_CORE_C7_RESIDENCY; break; @@ -91,18 +92,18 @@ static int snb_get_count_percent(unsigned int id, double *percent, if (!is_valid[cpu]) return -1; - *percent = (100.0 * (current_count[id][cpu] - previous_count[id][cpu])) / + *percent = (100.0 * + (current_count[id][cpu] - previous_count[id][cpu])) / (tsc_at_measure_end - tsc_at_measure_start); - dprint("%s: previous: %llu - current: %llu - (%u)\n", snb_cstates[id].name, - previous_count[id][cpu], current_count[id][cpu], - cpu); + dprint("%s: previous: %llu - current: %llu - (%u)\n", + snb_cstates[id].name, previous_count[id][cpu], + current_count[id][cpu], cpu); dprint("%s: tsc_diff: %llu - count_diff: %llu - percent: %2.f (%u)\n", snb_cstates[id].name, (unsigned long long) tsc_at_measure_end - tsc_at_measure_start, - current_count[id][cpu] - - previous_count[id][cpu], + current_count[id][cpu] - previous_count[id][cpu], *percent, cpu); return 0; @@ -141,8 +142,8 @@ static int snb_stop(void) struct cpuidle_monitor intel_snb_monitor; -static struct cpuidle_monitor* snb_register(void) { - +static struct cpuidle_monitor *snb_register(void) +{ int num; if (cpupower_cpu_info.vendor != X86_VENDOR_INTEL @@ -153,12 +154,12 @@ static struct cpuidle_monitor* snb_register(void) { && cpupower_cpu_info.model != 0x2D) return NULL; - is_valid = calloc(cpu_count, sizeof (int)); + is_valid = calloc(cpu_count, sizeof(int)); for (num = 0; num < SNB_CSTATE_COUNT; num++) { - previous_count[num] = calloc (cpu_count, - sizeof(unsigned long long)); - current_count[num] = calloc (cpu_count, - sizeof(unsigned long long)); + previous_count[num] = calloc(cpu_count, + sizeof(unsigned long long)); + current_count[num] = calloc(cpu_count, + sizeof(unsigned long long)); } intel_snb_monitor.name_len = strlen(intel_snb_monitor.name); return &intel_snb_monitor; -- cgit v1.2.3 From 2cd005cac6d586b8ca324814a9c58ed0c08ffe40 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 19 Apr 2011 20:16:05 +0200 Subject: cpupowerutils: helpers - ConfigStyle bugfixes Signed-off-by: Dominik Brodowski --- tools/power/cpupower/utils/helpers/amd.c | 8 +- tools/power/cpupower/utils/helpers/bitmask.c | 12 +-- tools/power/cpupower/utils/helpers/cpuid.c | 14 ++-- tools/power/cpupower/utils/helpers/helpers.h | 6 +- tools/power/cpupower/utils/helpers/misc.c | 3 +- tools/power/cpupower/utils/helpers/pci.c | 2 +- tools/power/cpupower/utils/helpers/sysfs.c | 112 ++++++++++++++------------ tools/power/cpupower/utils/helpers/sysfs.h | 23 +++--- tools/power/cpupower/utils/helpers/topology.c | 6 +- 9 files changed, 100 insertions(+), 86 deletions(-) (limited to 'tools') diff --git a/tools/power/cpupower/utils/helpers/amd.c b/tools/power/cpupower/utils/helpers/amd.c index 5e44e31fc7f9..87d5605bdda8 100644 --- a/tools/power/cpupower/utils/helpers/amd.c +++ b/tools/power/cpupower/utils/helpers/amd.c @@ -53,8 +53,8 @@ static int get_cof(int family, union msr_pstate pstate) if (family == 0x11) t = 0x8; - return ((100 * (fid + t)) >> did); - } + return (100 * (fid + t)) >> did; +} /* Needs: * cpu -> the cpu that gets evaluated @@ -74,7 +74,7 @@ int decode_pstates(unsigned int cpu, unsigned int cpu_family, { int i, psmax, pscur; union msr_pstate pstate; - unsigned long long val; + unsigned long long val; /* Only read out frequencies from HW when CPU might be boostable to keep the code as short and clean as possible. @@ -95,7 +95,7 @@ int decode_pstates(unsigned int cpu, unsigned int cpu_family, pscur += boost_states; psmax += boost_states; - for (i=0; i<=psmax; i++) { + for (i = 0; i <= psmax; i++) { if (i >= MAX_HW_PSTATES) { fprintf(stderr, "HW pstates [%d] exceeding max [%d]\n", psmax, MAX_HW_PSTATES); diff --git a/tools/power/cpupower/utils/helpers/bitmask.c b/tools/power/cpupower/utils/helpers/bitmask.c index 60f4d69bb20d..5c074c60f904 100644 --- a/tools/power/cpupower/utils/helpers/bitmask.c +++ b/tools/power/cpupower/utils/helpers/bitmask.c @@ -8,12 +8,12 @@ #define bitsperlong (8 * sizeof(unsigned long)) /* howmany(a,b) : how many elements of size b needed to hold all of a */ -#define howmany(x,y) (((x)+((y)-1))/(y)) +#define howmany(x, y) (((x)+((y)-1))/(y)) /* How many longs in mask of n bits */ #define longsperbits(n) howmany(n, bitsperlong) -#define max(a,b) ((a) > (b) ? (a) : (b)) +#define max(a, b) ((a) > (b) ? (a) : (b)) /* * Allocate and free `struct bitmask *` @@ -73,7 +73,8 @@ static void _setbit(struct bitmask *bmp, unsigned int n, unsigned int v) if (v) bmp->maskp[n/bitsperlong] |= 1UL << (n % bitsperlong); else - bmp->maskp[n/bitsperlong] &= ~(1UL << (n % bitsperlong)); + bmp->maskp[n/bitsperlong] &= + ~(1UL << (n % bitsperlong)); } } @@ -185,7 +186,7 @@ unsigned int bitmask_next(const struct bitmask *bmp, unsigned int i) * 0-3 0,1,2,3 * 0-7:2 0,2,4,6 * 1,3,5-7 1,3,5,6,7 - * 0-3:2,8-15:4 0,2,8,12 + * 0-3:2,8-15:4 0,2,8,12 */ int bitmask_parselist(const char *buf, struct bitmask *bmp) { @@ -251,7 +252,8 @@ static inline int emit(char *buf, int buflen, int rbot, int rtop, int len) if (rbot == rtop) len += snprintf(buf + len, max(buflen - len, 0), "%d", rbot); else - len += snprintf(buf + len, max(buflen - len, 0), "%d-%d", rbot, rtop); + len += snprintf(buf + len, max(buflen - len, 0), "%d-%d", + rbot, rtop); return len; } diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c index 71021f3bb69d..944b2c1659d8 100644 --- a/tools/power/cpupower/utils/helpers/cpuid.c +++ b/tools/power/cpupower/utils/helpers/cpuid.c @@ -67,28 +67,26 @@ int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info) continue; value[63 - 1] = '\0'; - if (!strncmp(value, "processor\t: ", 12)) { + if (!strncmp(value, "processor\t: ", 12)) sscanf(value, "processor\t: %u", &proc); - } + if (proc != cpu) continue; /* Get CPU vendor */ - if (!strncmp(value, "vendor_id", 9)) + if (!strncmp(value, "vendor_id", 9)) { for (x = 1; x < X86_VENDOR_MAX; x++) { if (strstr(value, cpu_vendor_table[x])) cpu_info->vendor = x; } /* Get CPU family, etc. */ - else if (!strncmp(value, "cpu family\t: ", 13)) { + } else if (!strncmp(value, "cpu family\t: ", 13)) { sscanf(value, "cpu family\t: %u", &cpu_info->family); - } - else if (!strncmp(value, "model\t\t: ", 9)) { + } else if (!strncmp(value, "model\t\t: ", 9)) { sscanf(value, "model\t\t: %u", &cpu_info->model); - } - else if (!strncmp(value, "stepping\t: ", 10)) { + } else if (!strncmp(value, "stepping\t: ", 10)) { sscanf(value, "stepping\t: %u", &cpu_info->stepping); diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h index a487dadb4cf0..048f065925c9 100644 --- a/tools/power/cpupower/utils/helpers/helpers.h +++ b/tools/power/cpupower/utils/helpers/helpers.h @@ -20,7 +20,7 @@ #ifndef gettext_noop #define gettext_noop(String) String #endif -#define N_(String) gettext_noop (String) +#define N_(String) gettext_noop(String) /* Internationalization ****************************/ extern int run_as_root; @@ -39,11 +39,11 @@ extern int be_verbose; #define dprint(fmt, ...) { \ if (be_verbose) { \ fprintf(stderr, "%s: " fmt, \ - __FUNCTION__, ##__VA_ARGS__); \ + __func__, ##__VA_ARGS__); \ } \ } #else -static inline void dprint(const char *fmt, ...) { } +static inline void dprint(const char *fmt, ...) { } #endif extern int be_verbose; /* Global verbose (-v) stuff *********************************/ diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c index c1566e93e0ec..e8b3140cc6b8 100644 --- a/tools/power/cpupower/utils/helpers/misc.c +++ b/tools/power/cpupower/utils/helpers/misc.c @@ -2,7 +2,8 @@ #include "helpers/helpers.h" -int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active, int * states) +int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active, + int *states) { struct cpupower_cpu_info cpu_info; int ret; diff --git a/tools/power/cpupower/utils/helpers/pci.c b/tools/power/cpupower/utils/helpers/pci.c index 8dcc93813716..cd2eb6fe41c4 100644 --- a/tools/power/cpupower/utils/helpers/pci.c +++ b/tools/power/cpupower/utils/helpers/pci.c @@ -33,7 +33,7 @@ struct pci_dev *pci_acc_init(struct pci_access **pacc, int vendor_id, for (i = 0; dev_ids[i] != 0; i++) { filter_nb_link.device = dev_ids[i]; - for (device=(*pacc)->devices; device; device = device->next) { + for (device = (*pacc)->devices; device; device = device->next) { if (pci_filter_match(&filter_nb_link, device)) return device; } diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c index 0c534e79652b..55e2466674c6 100644 --- a/tools/power/cpupower/utils/helpers/sysfs.c +++ b/tools/power/cpupower/utils/helpers/sysfs.c @@ -19,14 +19,14 @@ unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen) { int fd; - size_t numread; + ssize_t numread; - if ( ( fd = open(path, O_RDONLY) ) == -1 ) + fd = open(path, O_RDONLY); + if (fd == -1) return 0; numread = read(fd, buf, buflen - 1); - if ( numread < 1 ) - { + if (numread < 1) { close(fd); return 0; } @@ -34,26 +34,26 @@ unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen) buf[numread] = '\0'; close(fd); - return numread; + return (unsigned int) numread; } static unsigned int sysfs_write_file(const char *path, const char *value, size_t len) { int fd; - size_t numwrite; + ssize_t numwrite; - if ( ( fd = open(path, O_WRONLY) ) == -1 ) + fd = open(path, O_WRONLY); + if (fd == -1) return 0; numwrite = write(fd, value, len); - if ( numwrite < 1 ) - { + if (numwrite < 1) { close(fd); return 0; } close(fd); - return numwrite; + return (unsigned int) numwrite; } /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */ @@ -69,17 +69,17 @@ unsigned int sysfs_idlestate_read_file(unsigned int cpu, unsigned int idlestate, { char path[SYSFS_PATH_MAX]; int fd; - size_t numread; + ssize_t numread; snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpuidle/state%u/%s", cpu, idlestate, fname); - if ( ( fd = open(path, O_RDONLY) ) == -1 ) + fd = open(path, O_RDONLY); + if (fd == -1) return 0; numread = read(fd, buf, buflen - 1); - if ( numread < 1 ) - { + if (numread < 1) { close(fd); return 0; } @@ -87,7 +87,7 @@ unsigned int sysfs_idlestate_read_file(unsigned int cpu, unsigned int idlestate, buf[numread] = '\0'; close(fd); - return numread; + return (unsigned int) numread; } /* read access to files which contain one numeric value */ @@ -116,19 +116,18 @@ static unsigned long long sysfs_idlestate_get_one_value(unsigned int cpu, char linebuf[MAX_LINE_LEN]; char *endp; - if ( which >= MAX_IDLESTATE_VALUE_FILES ) + if (which >= MAX_IDLESTATE_VALUE_FILES) return 0; - if ( ( len = sysfs_idlestate_read_file(cpu, idlestate, - idlestate_value_files[which], - linebuf, sizeof(linebuf))) == 0 ) - { + len = sysfs_idlestate_read_file(cpu, idlestate, + idlestate_value_files[which], + linebuf, sizeof(linebuf)); + if (len == 0) return 0; - } value = strtoull(linebuf, &endp, 0); - if ( endp == linebuf || errno == ERANGE ) + if (endp == linebuf || errno == ERANGE) return 0; return value; @@ -148,9 +147,9 @@ static const char *idlestate_string_files[MAX_IDLESTATE_STRING_FILES] = { }; -static char * sysfs_idlestate_get_one_string(unsigned int cpu, - unsigned int idlestate, - enum idlestate_string which) +static char *sysfs_idlestate_get_one_string(unsigned int cpu, + unsigned int idlestate, + enum idlestate_string which) { char linebuf[MAX_LINE_LEN]; char *result; @@ -159,12 +158,14 @@ static char * sysfs_idlestate_get_one_string(unsigned int cpu, if (which >= MAX_IDLESTATE_STRING_FILES) return NULL; - if ( ( len = sysfs_idlestate_read_file(cpu, idlestate, - idlestate_string_files[which], - linebuf, sizeof(linebuf))) == 0 ) + len = sysfs_idlestate_read_file(cpu, idlestate, + idlestate_string_files[which], + linebuf, sizeof(linebuf)); + if (len == 0) return NULL; - if ( ( result = strdup(linebuf) ) == NULL ) + result = strdup(linebuf); + if (result == NULL) return NULL; if (result[strlen(result) - 1] == '\n') @@ -173,27 +174,30 @@ static char * sysfs_idlestate_get_one_string(unsigned int cpu, return result; } -unsigned long sysfs_get_idlestate_latency(unsigned int cpu, unsigned int idlestate) +unsigned long sysfs_get_idlestate_latency(unsigned int cpu, + unsigned int idlestate) { return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_LATENCY); } -unsigned long sysfs_get_idlestate_usage(unsigned int cpu, unsigned int idlestate) +unsigned long sysfs_get_idlestate_usage(unsigned int cpu, + unsigned int idlestate) { return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_USAGE); } -unsigned long long sysfs_get_idlestate_time(unsigned int cpu, unsigned int idlestate) +unsigned long long sysfs_get_idlestate_time(unsigned int cpu, + unsigned int idlestate) { return sysfs_idlestate_get_one_value(cpu, idlestate, IDLESTATE_TIME); } -char * sysfs_get_idlestate_name(unsigned int cpu, unsigned int idlestate) +char *sysfs_get_idlestate_name(unsigned int cpu, unsigned int idlestate) { return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_NAME); } -char * sysfs_get_idlestate_desc(unsigned int cpu, unsigned int idlestate) +char *sysfs_get_idlestate_desc(unsigned int cpu, unsigned int idlestate) { return sysfs_idlestate_get_one_string(cpu, idlestate, IDLESTATE_DESC); } @@ -211,14 +215,14 @@ int sysfs_get_idlestate_count(unsigned int cpu) snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpuidle"); - if ( stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) + if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) return -ENODEV; snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state0", cpu); - if ( stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) + if (stat(file, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) return 0; - while(stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { + while (stat(file, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/cpuidle/state%d", cpu, idlestates); idlestates++; @@ -261,7 +265,7 @@ static const char *cpuidle_string_files[MAX_CPUIDLE_STRING_FILES] = { }; -static char * sysfs_cpuidle_get_one_string(enum cpuidle_string which) +static char *sysfs_cpuidle_get_one_string(enum cpuidle_string which) { char linebuf[MAX_LINE_LEN]; char *result; @@ -270,11 +274,13 @@ static char * sysfs_cpuidle_get_one_string(enum cpuidle_string which) if (which >= MAX_CPUIDLE_STRING_FILES) return NULL; - if ( ( len = sysfs_cpuidle_read_file(cpuidle_string_files[which], - linebuf, sizeof(linebuf))) == 0 ) + len = sysfs_cpuidle_read_file(cpuidle_string_files[which], + linebuf, sizeof(linebuf)); + if (len == 0) return NULL; - if ( ( result = strdup(linebuf) ) == NULL ) + result = strdup(linebuf); + if (result == NULL) return NULL; if (result[strlen(result) - 1] == '\n') @@ -283,7 +289,7 @@ static char * sysfs_cpuidle_get_one_string(enum cpuidle_string which) return result; } -char * sysfs_get_cpuidle_governor(void) +char *sysfs_get_cpuidle_governor(void) { char *tmp = sysfs_cpuidle_get_one_string(CPUIDLE_GOVERNOR_RO); if (!tmp) @@ -292,7 +298,7 @@ char * sysfs_get_cpuidle_governor(void) return tmp; } -char * sysfs_get_cpuidle_driver(void) +char *sysfs_get_cpuidle_driver(void) { return sysfs_cpuidle_get_one_string(CPUIDLE_DRIVER); } @@ -304,9 +310,9 @@ char * sysfs_get_cpuidle_driver(void) * * Returns negative value on failure */ -int sysfs_get_sched(const char* smt_mc) +int sysfs_get_sched(const char *smt_mc) { - unsigned long value; + unsigned long value; char linebuf[MAX_LINE_LEN]; char *endp; char path[SYSFS_PATH_MAX]; @@ -314,11 +320,12 @@ int sysfs_get_sched(const char* smt_mc) if (strcmp("mc", smt_mc) && strcmp("smt", smt_mc)) return -EINVAL; - snprintf(path, sizeof(path), PATH_TO_CPU "sched_%s_power_savings", smt_mc); - if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0 ) + snprintf(path, sizeof(path), + PATH_TO_CPU "sched_%s_power_savings", smt_mc); + if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0) return -1; value = strtoul(linebuf, &endp, 0); - if ( endp == linebuf || errno == ERANGE ) + if (endp == linebuf || errno == ERANGE) return -1; return value; } @@ -329,7 +336,7 @@ int sysfs_get_sched(const char* smt_mc) * * Returns negative value on failure */ -int sysfs_set_sched(const char* smt_mc, int val) +int sysfs_set_sched(const char *smt_mc, int val) { char linebuf[MAX_LINE_LEN]; char path[SYSFS_PATH_MAX]; @@ -338,13 +345,14 @@ int sysfs_set_sched(const char* smt_mc, int val) if (strcmp("mc", smt_mc) && strcmp("smt", smt_mc)) return -EINVAL; - snprintf(path, sizeof(path), PATH_TO_CPU "sched_%s_power_savings", smt_mc); + snprintf(path, sizeof(path), + PATH_TO_CPU "sched_%s_power_savings", smt_mc); sprintf(linebuf, "%d", val); - if ( stat(path, &statbuf) != 0 ) + if (stat(path, &statbuf) != 0) return -ENODEV; - if (sysfs_write_file(path, linebuf, MAX_LINE_LEN) == 0 ) + if (sysfs_write_file(path, linebuf, MAX_LINE_LEN) == 0) return -1; return 0; } diff --git a/tools/power/cpupower/utils/helpers/sysfs.h b/tools/power/cpupower/utils/helpers/sysfs.h index 5d02d2fc70e1..f9373e090637 100644 --- a/tools/power/cpupower/utils/helpers/sysfs.h +++ b/tools/power/cpupower/utils/helpers/sysfs.h @@ -7,17 +7,22 @@ extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen); -extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu, unsigned int idlestate); -extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu, unsigned int idlestate); -extern unsigned long long sysfs_get_idlestate_time(unsigned int cpu, unsigned int idlestate); -extern char * sysfs_get_idlestate_name(unsigned int cpu, unsigned int idlestate); -extern char * sysfs_get_idlestate_desc(unsigned int cpu, unsigned int idlestate); +extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu, + unsigned int idlestate); +extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu, + unsigned int idlestate); +extern unsigned long long sysfs_get_idlestate_time(unsigned int cpu, + unsigned int idlestate); +extern char *sysfs_get_idlestate_name(unsigned int cpu, + unsigned int idlestate); +extern char *sysfs_get_idlestate_desc(unsigned int cpu, + unsigned int idlestate); extern int sysfs_get_idlestate_count(unsigned int cpu); -extern char * sysfs_get_cpuidle_governor(void); -extern char * sysfs_get_cpuidle_driver(void); +extern char *sysfs_get_cpuidle_governor(void); +extern char *sysfs_get_cpuidle_driver(void); -extern int sysfs_get_sched(const char* smt_mc); -extern int sysfs_set_sched(const char* smt_mc, int val); +extern int sysfs_get_sched(const char *smt_mc); +extern int sysfs_set_sched(const char *smt_mc, int val); #endif /* __CPUPOWER_HELPERS_SYSFS_H__ */ diff --git a/tools/power/cpupower/utils/helpers/topology.c b/tools/power/cpupower/utils/helpers/topology.c index 5ad842b956bb..385ee5c7570c 100644 --- a/tools/power/cpupower/utils/helpers/topology.c +++ b/tools/power/cpupower/utils/helpers/topology.c @@ -22,17 +22,17 @@ /* returns -1 on failure, 0 on success */ int sysfs_topology_read_file(unsigned int cpu, const char *fname) { - unsigned long value; + unsigned long value; char linebuf[MAX_LINE_LEN]; char *endp; char path[SYSFS_PATH_MAX]; snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s", cpu, fname); - if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0 ) + if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0) return -1; value = strtoul(linebuf, &endp, 0); - if ( endp == linebuf || errno == ERANGE ) + if (endp == linebuf || errno == ERANGE) return -1; return value; } -- cgit v1.2.3 From a1ce5ba2b7d08ab6347dc254f86f70e91c5f1a44 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 19 Apr 2011 20:33:50 +0200 Subject: cpupowerutils: utils - ConfigStyle bugfixes Signed-off-by: Dominik Brodowski --- tools/power/cpupower/utils/cpufreq-info.c | 123 ++++++++++++++++------------- tools/power/cpupower/utils/cpufreq-set.c | 25 +++--- tools/power/cpupower/utils/cpuidle-info.c | 27 +++---- tools/power/cpupower/utils/cpupower-info.c | 17 ++-- tools/power/cpupower/utils/cpupower-set.c | 16 ++-- tools/power/cpupower/utils/cpupower.c | 22 +++--- 6 files changed, 122 insertions(+), 108 deletions(-) (limited to 'tools') diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c index eaa8be06edfa..8628644188cf 100644 --- a/tools/power/cpupower/utils/cpufreq-info.c +++ b/tools/power/cpupower/utils/cpufreq-info.c @@ -27,7 +27,7 @@ static unsigned int count_cpus(void) unsigned int cpunr = 0; fp = fopen("/proc/stat", "r"); - if(!fp) { + if (!fp) { printf(_("Couldn't count the number of CPUs (%s: %s), assuming 1\n"), "/proc/stat", strerror(errno)); return 1; } @@ -48,7 +48,7 @@ static unsigned int count_cpus(void) fclose(fp); /* cpu count starts from 0, on error return 1 (UP) */ - return (ret+1); + return ret + 1; } @@ -63,7 +63,7 @@ static void proc_cpufreq_output(void) printf(_(" minimum CPU frequency - maximum CPU frequency - governor\n")); nr_cpus = count_cpus(); - for (cpu=0; cpu < nr_cpus; cpu++) { + for (cpu = 0; cpu < nr_cpus; cpu++) { policy = cpufreq_get_policy(cpu); if (!policy) continue; @@ -75,7 +75,8 @@ static void proc_cpufreq_output(void) max_pctg = (policy->max * 100) / max; } printf("CPU%3d %9lu kHz (%3d %%) - %9lu kHz (%3d %%) - %s\n", - cpu , policy->min, max ? min_pctg : 0, policy->max, max ? max_pctg : 0, policy->governor); + cpu , policy->min, max ? min_pctg : 0, policy->max, + max ? max_pctg : 0, policy->governor); cpufreq_put_policy(policy); } @@ -89,21 +90,21 @@ static void print_speed(unsigned long speed) tmp = speed % 10000; if (tmp >= 5000) speed += 10000; - printf ("%u.%02u GHz", ((unsigned int) speed/1000000), + printf("%u.%02u GHz", ((unsigned int) speed/1000000), ((unsigned int) (speed%1000000)/10000)); } else if (speed > 100000) { tmp = speed % 1000; if (tmp >= 500) speed += 1000; - printf ("%u MHz", ((unsigned int) speed / 1000)); + printf("%u MHz", ((unsigned int) speed / 1000)); } else if (speed > 1000) { tmp = speed % 100; if (tmp >= 50) speed += 100; - printf ("%u.%01u MHz", ((unsigned int) speed/1000), + printf("%u.%01u MHz", ((unsigned int) speed/1000), ((unsigned int) (speed%1000)/100)); } else - printf ("%lu kHz", speed); + printf("%lu kHz", speed); return; } @@ -116,28 +117,29 @@ static void print_duration(unsigned long duration) tmp = duration % 10000; if (tmp >= 5000) duration += 10000; - printf ("%u.%02u ms", ((unsigned int) duration/1000000), + printf("%u.%02u ms", ((unsigned int) duration/1000000), ((unsigned int) (duration%1000000)/10000)); } else if (duration > 100000) { tmp = duration % 1000; if (tmp >= 500) duration += 1000; - printf ("%u us", ((unsigned int) duration / 1000)); + printf("%u us", ((unsigned int) duration / 1000)); } else if (duration > 1000) { tmp = duration % 100; if (tmp >= 50) duration += 100; - printf ("%u.%01u us", ((unsigned int) duration/1000), + printf("%u.%01u us", ((unsigned int) duration/1000), ((unsigned int) (duration%1000)/100)); } else - printf ("%lu ns", duration); + printf("%lu ns", duration); return; } /* --boost / -b */ -static int get_boost_mode(unsigned int cpu) { +static int get_boost_mode(unsigned int cpu) +{ int support, active, b_states = 0, ret, pstate_no, i; /* ToDo: Make this more global */ unsigned long pstates[MAX_HW_PSTATES] = {0,}; @@ -158,13 +160,13 @@ static int get_boost_mode(unsigned int cpu) { && (cpuid_edx(0x80000007) & (1 << 7))) */ - printf(_(" boost state support: \n")); + printf(_(" boost state support:\n")); printf(_(" Supported: %s\n"), support ? _("yes") : _("no")); printf(_(" Active: %s\n"), active ? _("yes") : _("no")); /* ToDo: Only works for AMD for now... */ - + if (cpupower_cpu_info.vendor == X86_VENDOR_AMD && cpupower_cpu_info.family >= 0x10) { ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states, @@ -196,12 +198,11 @@ static void debug_output_one(unsigned int cpu) unsigned long total_trans, latency; unsigned long long total_time; struct cpufreq_policy *policy; - struct cpufreq_available_governors * governors; + struct cpufreq_available_governors *governors; struct cpufreq_stats *stats; - if (cpufreq_cpu_exists(cpu)) { + if (cpufreq_cpu_exists(cpu)) return; - } freq_kernel = cpufreq_get_freq_kernel(cpu); freq_hardware = cpufreq_get_freq_hardware(cpu); @@ -294,8 +295,7 @@ static void debug_output_one(unsigned int cpu) if (freq_hardware) { print_speed(freq_hardware); printf(_(" (asserted by call to hardware)")); - } - else + } else print_speed(freq_kernel); printf(".\n"); } @@ -322,7 +322,8 @@ static void debug_output_one(unsigned int cpu) /* --freq / -f */ -static int get_freq_kernel(unsigned int cpu, unsigned int human) { +static int get_freq_kernel(unsigned int cpu, unsigned int human) +{ unsigned long freq = cpufreq_get_freq_kernel(cpu); if (!freq) return -EINVAL; @@ -337,7 +338,8 @@ static int get_freq_kernel(unsigned int cpu, unsigned int human) { /* --hwfreq / -w */ -static int get_freq_hardware(unsigned int cpu, unsigned int human) { +static int get_freq_hardware(unsigned int cpu, unsigned int human) +{ unsigned long freq = cpufreq_get_freq_hardware(cpu); if (!freq) return -EINVAL; @@ -351,7 +353,8 @@ static int get_freq_hardware(unsigned int cpu, unsigned int human) { /* --hwlimits / -l */ -static int get_hardware_limits(unsigned int cpu) { +static int get_hardware_limits(unsigned int cpu) +{ unsigned long min, max; if (cpufreq_get_hardware_limits(cpu, &min, &max)) return -EINVAL; @@ -361,7 +364,8 @@ static int get_hardware_limits(unsigned int cpu) { /* --driver / -d */ -static int get_driver(unsigned int cpu) { +static int get_driver(unsigned int cpu) +{ char *driver = cpufreq_get_driver(cpu); if (!driver) return -EINVAL; @@ -372,7 +376,8 @@ static int get_driver(unsigned int cpu) { /* --policy / -p */ -static int get_policy(unsigned int cpu) { +static int get_policy(unsigned int cpu) +{ struct cpufreq_policy *policy = cpufreq_get_policy(cpu); if (!policy) return -EINVAL; @@ -383,8 +388,10 @@ static int get_policy(unsigned int cpu) { /* --governors / -g */ -static int get_available_governors(unsigned int cpu) { - struct cpufreq_available_governors *governors = cpufreq_get_available_governors(cpu); +static int get_available_governors(unsigned int cpu) +{ + struct cpufreq_available_governors *governors = + cpufreq_get_available_governors(cpu); if (!governors) return -EINVAL; @@ -400,7 +407,8 @@ static int get_available_governors(unsigned int cpu) { /* --affected-cpus / -a */ -static int get_affected_cpus(unsigned int cpu) { +static int get_affected_cpus(unsigned int cpu) +{ struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu); if (!cpus) return -EINVAL; @@ -416,7 +424,8 @@ static int get_affected_cpus(unsigned int cpu) { /* --related-cpus / -r */ -static int get_related_cpus(unsigned int cpu) { +static int get_related_cpus(unsigned int cpu) +{ struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu); if (!cpus) return -EINVAL; @@ -432,17 +441,19 @@ static int get_related_cpus(unsigned int cpu) { /* --stats / -s */ -static int get_freq_stats(unsigned int cpu, unsigned int human) { +static int get_freq_stats(unsigned int cpu, unsigned int human) +{ unsigned long total_trans = cpufreq_get_transitions(cpu); unsigned long long total_time; struct cpufreq_stats *stats = cpufreq_get_stats(cpu, &total_time); while (stats) { if (human) { print_speed(stats->frequency); - printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time); - } - else - printf("%lu:%llu", stats->frequency, stats->time_in_state); + printf(":%.2f%%", + (100.0 * stats->time_in_state) / total_time); + } else + printf("%lu:%llu", + stats->frequency, stats->time_in_state); stats = stats->next; if (stats) printf(", "); @@ -455,7 +466,8 @@ static int get_freq_stats(unsigned int cpu, unsigned int human) { /* --latency / -y */ -static int get_latency(unsigned int cpu, unsigned int human) { +static int get_latency(unsigned int cpu, unsigned int human) +{ unsigned long latency = cpufreq_get_transition_latency(cpu); if (!latency) return -EINVAL; @@ -468,7 +480,8 @@ static int get_latency(unsigned int cpu, unsigned int human) { return 0; } -void freq_info_help(void) { +void freq_info_help(void) +{ printf(_("Usage: cpupower freqinfo [options]\n")); printf(_("Options:\n")); printf(_(" -e, --debug Prints out debug information [default]\n")); @@ -494,26 +507,26 @@ void freq_info_help(void) { printf("\n"); printf(_("If no argument is given, full output about\n" "cpufreq is printed which is useful e.g. for reporting bugs.\n\n")); - printf(_("By default info of CPU 0 is shown which can be overridden \n" + printf(_("By default info of CPU 0 is shown which can be overridden\n" "with the cpupower --cpu main command option.\n")); } static struct option info_opts[] = { - { .name="debug", .has_arg=no_argument, .flag=NULL, .val='e'}, - { .name="boost", .has_arg=no_argument, .flag=NULL, .val='b'}, - { .name="freq", .has_arg=no_argument, .flag=NULL, .val='f'}, - { .name="hwfreq", .has_arg=no_argument, .flag=NULL, .val='w'}, - { .name="hwlimits", .has_arg=no_argument, .flag=NULL, .val='l'}, - { .name="driver", .has_arg=no_argument, .flag=NULL, .val='d'}, - { .name="policy", .has_arg=no_argument, .flag=NULL, .val='p'}, - { .name="governors", .has_arg=no_argument, .flag=NULL, .val='g'}, - { .name="related-cpus", .has_arg=no_argument, .flag=NULL, .val='r'}, - { .name="affected-cpus",.has_arg=no_argument, .flag=NULL, .val='a'}, - { .name="stats", .has_arg=no_argument, .flag=NULL, .val='s'}, - { .name="latency", .has_arg=no_argument, .flag=NULL, .val='y'}, - { .name="proc", .has_arg=no_argument, .flag=NULL, .val='o'}, - { .name="human", .has_arg=no_argument, .flag=NULL, .val='m'}, - { .name="help", .has_arg=no_argument, .flag=NULL, .val='h'}, + { .name = "debug", .has_arg = no_argument, .flag = NULL, .val = 'e'}, + { .name = "boost", .has_arg = no_argument, .flag = NULL, .val = 'b'}, + { .name = "freq", .has_arg = no_argument, .flag = NULL, .val = 'f'}, + { .name = "hwfreq", .has_arg = no_argument, .flag = NULL, .val = 'w'}, + { .name = "hwlimits", .has_arg = no_argument, .flag = NULL, .val = 'l'}, + { .name = "driver", .has_arg = no_argument, .flag = NULL, .val = 'd'}, + { .name = "policy", .has_arg = no_argument, .flag = NULL, .val = 'p'}, + { .name = "governors", .has_arg = no_argument, .flag = NULL, .val = 'g'}, + { .name = "related-cpus", .has_arg = no_argument, .flag = NULL, .val = 'r'}, + { .name = "affected-cpus",.has_arg = no_argument, .flag = NULL, .val = 'a'}, + { .name = "stats", .has_arg = no_argument, .flag = NULL, .val = 's'}, + { .name = "latency", .has_arg = no_argument, .flag = NULL, .val = 'y'}, + { .name = "proc", .has_arg = no_argument, .flag = NULL, .val = 'o'}, + { .name = "human", .has_arg = no_argument, .flag = NULL, .val = 'm'}, + { .name = "help", .has_arg = no_argument, .flag = NULL, .val = 'h'}, { }, }; @@ -572,7 +585,7 @@ int cmd_freq_info(int argc, char **argv) fprintf(stderr, "invalid or unknown argument\n"); return EXIT_FAILURE; } - } while(cont); + } while (cont); switch (output_param) { case 'o': @@ -591,7 +604,7 @@ int cmd_freq_info(int argc, char **argv) /* Default is: show output of CPU 0 only */ if (bitmask_isallclear(cpus_chosen)) bitmask_setbit(cpus_chosen, 0); - + switch (output_param) { case -1: printf(_("You can't specify more than one --cpu parameter and/or\n" @@ -659,7 +672,7 @@ int cmd_freq_info(int argc, char **argv) break; } if (ret) - return (ret); + return ret; } return ret; } diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c index d415b6b52a09..5f783622bf31 100644 --- a/tools/power/cpupower/utils/cpufreq-set.c +++ b/tools/power/cpupower/utils/cpufreq-set.c @@ -43,12 +43,12 @@ void freq_set_help(void) } static struct option set_opts[] = { - { .name="min", .has_arg=required_argument, .flag=NULL, .val='d'}, - { .name="max", .has_arg=required_argument, .flag=NULL, .val='u'}, - { .name="governor", .has_arg=required_argument, .flag=NULL, .val='g'}, - { .name="freq", .has_arg=required_argument, .flag=NULL, .val='f'}, - { .name="help", .has_arg=no_argument, .flag=NULL, .val='h'}, - { .name="related", .has_arg=no_argument, .flag=NULL, .val='r'}, + { .name = "min", .has_arg = required_argument, .flag = NULL, .val = 'd'}, + { .name = "max", .has_arg = required_argument, .flag = NULL, .val = 'u'}, + { .name = "governor", .has_arg = required_argument, .flag = NULL, .val = 'g'}, + { .name = "freq", .has_arg = required_argument, .flag = NULL, .val = 'f'}, + { .name = "help", .has_arg = no_argument, .flag = NULL, .val = 'h'}, + { .name = "related", .has_arg = no_argument, .flag = NULL, .val='r'}, { }, }; @@ -64,7 +64,7 @@ static void print_error(void) }; struct freq_units { - char* str_unit; + char *str_unit; int power_of_ten; }; @@ -204,7 +204,8 @@ static int do_one_cpu(unsigned int cpu, struct cpufreq_policy *new_pol, else if (new_pol->max) return cpufreq_modify_policy_max(cpu, new_pol->max); else if (new_pol->governor) - return cpufreq_modify_policy_governor(cpu, new_pol->governor); + return cpufreq_modify_policy_governor(cpu, + new_pol->governor); default: /* slow path */ @@ -282,15 +283,15 @@ int cmd_freq_set(int argc, char **argv) if ((strlen(optarg) < 3) || (strlen(optarg) > 18)) { print_unknown_arg(); return -EINVAL; - } + } if ((sscanf(optarg, "%s", gov)) != 1) { print_unknown_arg(); return -EINVAL; - } + } new_pol.governor = gov; break; } - } while(cont); + } while (cont); /* parameter checking */ if (double_parm) { @@ -339,7 +340,7 @@ int cmd_freq_set(int argc, char **argv) /* loop over CPUs */ for (cpu = bitmask_first(cpus_chosen); cpu <= bitmask_last(cpus_chosen); cpu++) { - + if (!bitmask_isbitset(cpus_chosen, cpu) || cpufreq_cpu_exists(cpu)) continue; diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c index 635468224e74..70da3574f1e9 100644 --- a/tools/power/cpupower/utils/cpuidle-info.c +++ b/tools/power/cpupower/utils/cpuidle-info.c @@ -31,8 +31,7 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose) if (idlestates == 0) { printf(_("CPU %u: No idle states\n"), cpu); return; - } - else if (idlestates <= 0) { + } else if (idlestates <= 0) { printf(_("CPU %u: Can't read idle state info\n"), cpu); return; } @@ -92,7 +91,7 @@ static void cpuidle_general_output(void) } printf(_("CPUidle driver: %s\n"), tmp); - free (tmp); + free(tmp); tmp = sysfs_get_cpuidle_governor(); if (!tmp) { @@ -101,7 +100,7 @@ static void cpuidle_general_output(void) } printf(_("CPUidle governor: %s\n"), tmp); - free (tmp); + free(tmp); } static void proc_cpuidle_cpu_output(unsigned int cpu) @@ -117,8 +116,7 @@ static void proc_cpuidle_cpu_output(unsigned int cpu) * printf(_("CPU %u: No C-states available\n"), cpu); * return; */ - } - else if (cstates <= 0) { + } else if (cstates <= 0) { printf(_("CPU %u: Can't read C-state info\n"), cpu); return; } @@ -143,7 +141,8 @@ static void proc_cpuidle_cpu_output(unsigned int cpu) /* --freq / -f */ -void idle_info_help(void) { +void idle_info_help(void) +{ printf(_ ("Usage: cpupower idleinfo [options]\n")); printf(_ ("Options:\n")); printf(_ (" -s, --silent Only show general C-state information\n")); @@ -155,9 +154,9 @@ void idle_info_help(void) { } static struct option info_opts[] = { - { .name="silent", .has_arg=no_argument, .flag=NULL, .val='s'}, - { .name="proc", .has_arg=no_argument, .flag=NULL, .val='o'}, - { .name="help", .has_arg=no_argument, .flag=NULL, .val='h'}, + { .name = "silent", .has_arg = no_argument, .flag = NULL, .val = 's'}, + { .name = "proc", .has_arg = no_argument, .flag = NULL, .val = 'o'}, + { .name = "help", .has_arg = no_argument, .flag = NULL, .val = 'h'}, { }, }; @@ -202,7 +201,7 @@ int cmd_idle_info(int argc, char **argv) output_param = ret; break; } - } while(cont); + } while (cont); switch (output_param) { case -1: @@ -219,10 +218,10 @@ int cmd_idle_info(int argc, char **argv) /* Default is: show output of CPU 0 only */ if (bitmask_isallclear(cpus_chosen)) bitmask_setbit(cpus_chosen, 0); - + if (output_param == 0) cpuidle_general_output(); - + for (cpu = bitmask_first(cpus_chosen); cpu <= bitmask_last(cpus_chosen); cpu++) { @@ -241,5 +240,5 @@ int cmd_idle_info(int argc, char **argv) break; } } - return (EXIT_SUCCESS); + return EXIT_SUCCESS; } diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c index 7add04ccbad4..85253cb7600e 100644 --- a/tools/power/cpupower/utils/cpupower-info.c +++ b/tools/power/cpupower/utils/cpupower-info.c @@ -30,10 +30,10 @@ void info_help(void) } static struct option set_opts[] = { - { .name="perf-bias", .has_arg=optional_argument, .flag=NULL, .val='b'}, - { .name="sched-mc", .has_arg=optional_argument, .flag=NULL, .val='m'}, - { .name="sched-smt", .has_arg=optional_argument, .flag=NULL, .val='s'}, - { .name="help", .has_arg=no_argument, .flag=NULL, .val='h'}, + { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'}, + { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'}, + { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'}, + { .name = "help", .has_arg = no_argument, .flag = NULL, .val = 'h'}, { }, }; @@ -57,12 +57,11 @@ int cmd_info(int argc, char **argv) int perf_bias:1; }; int params; - } params = {}; int ret = 0; setlocale(LC_ALL, ""); - textdomain (PACKAGE); + textdomain(PACKAGE); /* parameter parsing */ while ((ret = getopt_long(argc, argv, "msbh", set_opts, NULL)) != -1) { @@ -105,7 +104,7 @@ int cmd_info(int argc, char **argv) printf(_("not supported\n")); else printf("%d\n", ret); - } + } if (params.sched_smt) { ret = sysfs_get_sched("smt"); printf(_("System's thread sibling scheduler setting: ")); @@ -123,7 +122,7 @@ int cmd_info(int argc, char **argv) if (params.perf_bias) { if (!run_as_root) { params.perf_bias = 0; - printf (_("Intel's performance bias setting needs root privileges\n")); + printf(_("Intel's performance bias setting needs root privileges\n")); } else if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) { printf(_("System does not support Intel's performance" " bias setting\n")); @@ -134,7 +133,7 @@ int cmd_info(int argc, char **argv) /* loop over CPUs */ for (cpu = bitmask_first(cpus_chosen); cpu <= bitmask_last(cpus_chosen); cpu++) { - + if (!bitmask_isbitset(cpus_chosen, cpu) || cpufreq_cpu_exists(cpu)) continue; diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c index 3f807bc7a567..bc1b391e46f0 100644 --- a/tools/power/cpupower/utils/cpupower-set.c +++ b/tools/power/cpupower/utils/cpupower-set.c @@ -30,10 +30,10 @@ void set_help(void) } static struct option set_opts[] = { - { .name="perf-bias", .has_arg=optional_argument, .flag=NULL, .val='b'}, - { .name="sched-mc", .has_arg=optional_argument, .flag=NULL, .val='m'}, - { .name="sched-smt", .has_arg=optional_argument, .flag=NULL, .val='s'}, - { .name="help", .has_arg=no_argument, .flag=NULL, .val='h'}, + { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'}, + { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'}, + { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'}, + { .name = "help", .has_arg = no_argument, .flag = NULL, .val = 'h'}, { }, }; @@ -57,17 +57,17 @@ int cmd_set(int argc, char **argv) int perf_bias:1; }; int params; - } params; int sched_mc = 0, sched_smt = 0, perf_bias = 0; int ret = 0; setlocale(LC_ALL, ""); - textdomain (PACKAGE); + textdomain(PACKAGE); params.params = 0; /* parameter parsing */ - while ((ret = getopt_long(argc, argv, "m:s:b:h", set_opts, NULL)) != -1) { + while ((ret = getopt_long(argc, argv, "m:s:b:h", + set_opts, NULL)) != -1) { switch (ret) { case 'h': set_help(); @@ -135,7 +135,7 @@ int cmd_set(int argc, char **argv) /* loop over CPUs */ for (cpu = bitmask_first(cpus_chosen); cpu <= bitmask_last(cpus_chosen); cpu++) { - + if (!bitmask_isbitset(cpus_chosen, cpu) || cpufreq_cpu_exists(cpu)) continue; diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c index b048e5595359..5844ae0f786f 100644 --- a/tools/power/cpupower/utils/cpupower.c +++ b/tools/power/cpupower/utils/cpupower.c @@ -50,8 +50,8 @@ static struct cmd_struct commands[] = { { "set", cmd_set, set_help, 1 }, { "info", cmd_info, info_help, 0 }, { "monitor", cmd_monitor, monitor_help, 0 }, - { "help", cmd_help, print_help, 0 }, - // { "bench", cmd_bench, NULL, 1 }, + { "help", cmd_help, print_help, 0 }, + /* { "bench", cmd_bench, NULL, 1 }, */ }; int cmd_help(int argc, const char **argv) @@ -95,8 +95,9 @@ static void print_help(void) printf(_("\nUse cpupower help subcommand for getting help for above subcommands.\n")); } -static void print_version(void) { - printf(PACKAGE " " VERSION "\n"); +static void print_version(void) +{ + printf(PACKAGE " " VERSION "\n"); printf(_("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT); } @@ -109,10 +110,10 @@ static void handle_options(int *argc, const char ***argv) for (x = 0; x < *argc && ((*argv)[x])[0] == '-'; x++) { const char *param = (*argv)[x]; - if (!strcmp(param, "-h") || !strcmp(param, "--help")){ + if (!strcmp(param, "-h") || !strcmp(param, "--help")) { print_help(); exit(EXIT_SUCCESS); - } else if (!strcmp(param, "-c") || !strcmp(param, "--cpu")){ + } else if (!strcmp(param, "-c") || !strcmp(param, "--cpu")) { if (*argc < 2) { print_help(); exit(EXIT_FAILURE); @@ -132,13 +133,14 @@ static void handle_options(int *argc, const char ***argv) /* Cut out param: cpupower -c 1 info -> cpupower info */ new_argc += 2; continue; - } else if (!strcmp(param, "-v") || !strcmp(param, "--version")){ + } else if (!strcmp(param, "-v") || + !strcmp(param, "--version")) { print_version(); exit(EXIT_SUCCESS); #ifdef DEBUG - } else if (!strcmp(param, "-d") || !strcmp(param, "--debug")){ + } else if (!strcmp(param, "-d") || !strcmp(param, "--debug")) { be_verbose = 1; - new_argc ++; + new_argc++; continue; #endif } else { @@ -171,7 +173,7 @@ int main(int argc, const char *argv[]) } setlocale(LC_ALL, ""); - textdomain (PACKAGE); + textdomain(PACKAGE); /* Turn "perf cmd --help" into "perf help cmd" */ if (argc > 1 && !strcmp(argv[1], "--help")) { -- cgit v1.2.3 From af594f0ceb73c5bd984c89f3386bd7e8ecc471f5 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 20 Apr 2011 20:01:39 +0200 Subject: cpupowerutils: use kernel version-derived version string As cpupowerutils is intended to be included into the kernel sources, use the kernel versioning instead of a custom version. The script utils/version-gen.sh is largely based on the script already found in tools/perf/util/PERF-VERSION-GEN . Signed-off-by: Dominik Brodowski --- tools/power/cpupower/Makefile | 13 ++++++------ tools/power/cpupower/utils/version-gen.sh | 35 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) create mode 100755 tools/power/cpupower/utils/version-gen.sh (limited to 'tools') diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index 62c2716a9588..90d079e0e48d 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -47,7 +47,7 @@ DESTDIR ?= # Package-related definitions. Distributions can modify the version # and _should_ modify the PACKAGE_BUGREPORT definition -VERSION = 009p1 +VERSION= $(shell ./utils/version-gen.sh) LIB_MAJ= 0.0.0 LIB_MIN= 0 @@ -110,7 +110,7 @@ WARNINGS += $(call cc-supports,-Wno-pointer-sign) WARNINGS += $(call cc-supports,-Wdeclaration-after-statement) WARNINGS += -Wshadow -CPPFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \ +CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \ -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE UTIL_OBJS = utils/helpers/amd.o utils/helpers/topology.o utils/helpers/msr.o \ @@ -157,8 +157,7 @@ export QUIET ECHO # if DEBUG is enabled, then we do not strip or optimize ifeq ($(strip $(DEBUG)),true) - CFLAGS += -O1 -g - CPPFLAGS += -DDEBUG + CFLAGS += -O1 -g -DDEBUG STRIPCMD = /bin/true -Since_we_are_debugging else CFLAGS += $(OPTIMIZATION) -fomit-frame-pointer @@ -172,11 +171,11 @@ all: libcpufreq cpupower $(COMPILE_NLS) $(COMPILE_BENCH) lib/%.o: $(LIB_SRC) $(LIB_HEADERS) $(ECHO) " CC " $@ - $(QUIET) $(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -o $@ -c lib/$*.c + $(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c libcpufreq.so.$(LIB_MAJ): $(LIB_OBJS) $(ECHO) " LD " $@ - $(QUIET) $(CC) -shared $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ \ + $(QUIET) $(CC) -shared $(CFLAGS) $(LDFLAGS) -o $@ \ -Wl,-soname,libcpufreq.so.$(LIB_MIN) $(LIB_OBJS) @ln -sf $@ libcpufreq.so @ln -sf $@ libcpufreq.so.$(LIB_MIN) @@ -189,7 +188,7 @@ $(UTIL_OBJS): $(UTIL_HEADERS) .c.o: $(ECHO) " CC " $@ - $(QUIET) $(CC) $(CFLAGS) $(CPPFLAGS) -I./lib -I ./utils -o $@ -c $*.c + $(QUIET) $(CC) $(CFLAGS) -I./lib -I ./utils -o $@ -c $*.c cpupower: $(UTIL_OBJS) libcpufreq.so.$(LIB_MAJ) $(ECHO) " CC " $@ 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 @@ +#!/bin/sh +# +# Script which prints out the version to use for building cpupowerutils. +# Must be called from tools/power/cpupower/ +# +# Heavily based on tools/perf/util/PERF-VERSION-GEN . + +LF=' +' + +# First check if there is a .git to get the version from git describe +# otherwise try to get the version from the kernel makefile +if test -d ../../../.git -o -f ../../../.git && + VN=$(git describe --abbrev=4 HEAD 2>/dev/null) && + case "$VN" in + *$LF*) (exit 1) ;; + v[0-9]*) + git update-index -q --refresh + test -z "$(git diff-index --name-only HEAD --)" || + VN="$VN-dirty" ;; + esac +then + VN=$(echo "$VN" | sed -e 's/-/./g'); +else + eval $(grep '^VERSION[[:space:]]*=' ../../../Makefile|tr -d ' ') + eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../../Makefile|tr -d ' ') + eval $(grep '^SUBLEVEL[[:space:]]*=' ../../../Makefile|tr -d ' ') + eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../../Makefile|tr -d ' ') + + VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}" +fi + +VN=$(expr "$VN" : v*'\(.*\)') + +echo $VN -- cgit v1.2.3 From 4c22337f866cd3559023372a2111352a7610dfee Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Thu, 21 Apr 2011 17:50:25 +0200 Subject: cpupowerutils: Rename: libcpufreq->libcpupower [linux@dominikbrodowski.net: fix .gitignore] Signed-off-by: Thomas Renninger Signed-off-by: Dominik Brodowski --- tools/power/cpupower/.gitignore | 7 +++---- tools/power/cpupower/Makefile | 26 +++++++++++++------------- tools/power/cpupower/bench/Makefile | 2 +- 3 files changed, 17 insertions(+), 18 deletions(-) (limited to 'tools') diff --git a/tools/power/cpupower/.gitignore b/tools/power/cpupower/.gitignore index 4f0eb1d798df..8a83dd2ffc11 100644 --- a/tools/power/cpupower/.gitignore +++ b/tools/power/cpupower/.gitignore @@ -1,7 +1,7 @@ .libs -libcpufreq.so -libcpufreq.so.0 -libcpufreq.so.0.0.0 +libcpupower.so +libcpupower.so.0 +libcpupower.so.0.0.0 build/ccdv cpufreq-info cpufreq-set @@ -13,7 +13,6 @@ lib/proc.lo lib/proc.o lib/sysfs.lo lib/sysfs.o -libcpufreq.la po/cpupowerutils.pot po/*.gmo utils/cpufreq-info.o diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index 90d079e0e48d..d1a99e0e7b7a 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -167,20 +167,20 @@ endif # the actual make rules -all: libcpufreq cpupower $(COMPILE_NLS) $(COMPILE_BENCH) +all: libcpupower cpupower $(COMPILE_NLS) $(COMPILE_BENCH) lib/%.o: $(LIB_SRC) $(LIB_HEADERS) $(ECHO) " CC " $@ $(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c -libcpufreq.so.$(LIB_MAJ): $(LIB_OBJS) +libcpupower.so.$(LIB_MAJ): $(LIB_OBJS) $(ECHO) " LD " $@ $(QUIET) $(CC) -shared $(CFLAGS) $(LDFLAGS) -o $@ \ - -Wl,-soname,libcpufreq.so.$(LIB_MIN) $(LIB_OBJS) - @ln -sf $@ libcpufreq.so - @ln -sf $@ libcpufreq.so.$(LIB_MIN) + -Wl,-soname,libcpupower.so.$(LIB_MIN) $(LIB_OBJS) + @ln -sf $@ libcpupower.so + @ln -sf $@ libcpupower.so.$(LIB_MIN) -libcpufreq: libcpufreq.so.$(LIB_MAJ) +libcpupower: libcpupower.so.$(LIB_MAJ) # Let all .o files depend on its .c file and all headers # Might be worth to put this into utils/Makefile at some point of time @@ -190,9 +190,9 @@ $(UTIL_OBJS): $(UTIL_HEADERS) $(ECHO) " CC " $@ $(QUIET) $(CC) $(CFLAGS) -I./lib -I ./utils -o $@ -c $*.c -cpupower: $(UTIL_OBJS) libcpufreq.so.$(LIB_MAJ) +cpupower: $(UTIL_OBJS) libcpupower.so.$(LIB_MAJ) $(ECHO) " CC " $@ - $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -lcpufreq -lrt -lpci -L. -o $@ $(UTIL_OBJS) + $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) -lcpupower -lrt -lpci -L. -o $@ $(UTIL_OBJS) $(QUIET) $(STRIPCMD) $@ po/$(PACKAGE).pot: $(UTIL_SRC) @@ -221,7 +221,7 @@ update-po: po/$(PACKAGE).pot fi; \ done; -compile-bench: libcpufreq.so.$(LIB_MAJ) +compile-bench: libcpupower.so.$(LIB_MAJ) @V=$(V) confdir=$(confdir) $(MAKE) -C bench clean: @@ -230,14 +230,14 @@ clean: -rm -f $(UTIL_BINS) -rm -f $(IDLE_OBJS) -rm -f cpupower - -rm -f libcpufreq.so* + -rm -f libcpupower.so* -rm -rf po/*.gmo po/*.pot $(MAKE) -C bench clean install-lib: $(INSTALL) -d $(DESTDIR)${libdir} - $(CP) libcpufreq.so* $(DESTDIR)${libdir}/ + $(CP) libcpupower.so* $(DESTDIR)${libdir}/ $(INSTALL) -d $(DESTDIR)${includedir} $(INSTALL_DATA) lib/cpufreq.h $(DESTDIR)${includedir}/cpufreq.h @@ -267,7 +267,7 @@ install-bench: install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH) uninstall: - - rm -f $(DESTDIR)${libdir}/libcpufreq.* + - rm -f $(DESTDIR)${libdir}/libcpupower.* - rm -f $(DESTDIR)${includedir}/cpufreq.h - rm -f $(DESTDIR)${bindir}/utils/cpupower - rm -f $(DESTDIR)${mandir}/man1/cpufreq-set.1 @@ -276,4 +276,4 @@ uninstall: rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo; \ done; -.PHONY: all utils libcpufreq update-po create-gmo install-lib install-tools install-man install-gmo install uninstall clean +.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/bench/Makefile b/tools/power/cpupower/bench/Makefile index d779aac58ede..2b67606fc3e3 100644 --- a/tools/power/cpupower/bench/Makefile +++ b/tools/power/cpupower/bench/Makefile @@ -1,4 +1,4 @@ -LIBS = -L../ -lm -lcpufreq +LIBS = -L../ -lm -lcpupower OBJS = main.o parse.o system.o benchmark.o CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\" -- cgit v1.2.3 From ee3db6fcafa0b0023c1f5242452e9e4e6e3021c6 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Thu, 21 Apr 2011 17:50:26 +0200 Subject: cpupower: Rename package from cpupowerutils to cpupower Signed-off-by: Thomas Renninger Signed-off-by: Dominik Brodowski --- tools/power/cpupower/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'tools') diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index d1a99e0e7b7a..94c2cf0a98b8 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -1,4 +1,4 @@ -# Makefile for cpupowerutils +# Makefile for cpupower # # Copyright (C) 2005,2006 Dominik Brodowski # @@ -51,7 +51,7 @@ VERSION= $(shell ./utils/version-gen.sh) LIB_MAJ= 0.0.0 LIB_MIN= 0 -PACKAGE = cpupowerutils +PACKAGE = cpupower PACKAGE_BUGREPORT = cpufreq@vger.kernel.org LANGUAGES = de fr it cs pt @@ -66,7 +66,7 @@ mandir ?= /usr/man includedir ?= /usr/include libdir ?= /usr/lib localedir ?= /usr/share/locale -docdir ?= /usr/share/doc/packages/cpupowerutils +docdir ?= /usr/share/doc/packages/cpupower confdir ?= /etc/ # Toolchain: what tools do we use, and what options do they need: @@ -256,8 +256,8 @@ install-man: install-gmo: $(INSTALL) -d $(DESTDIR)${localedir} for HLANG in $(LANGUAGES); do \ - echo '$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo'; \ - $(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo; \ + echo '$(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo'; \ + $(INSTALL_DATA) -D po/$$HLANG.gmo $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \ done; install-bench: @@ -273,7 +273,7 @@ uninstall: - rm -f $(DESTDIR)${mandir}/man1/cpufreq-set.1 - rm -f $(DESTDIR)${mandir}/man1/cpufreq-info.1 - for HLANG in $(LANGUAGES); do \ - rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupowerutils.mo; \ + rm -f $(DESTDIR)${localedir}/$$HLANG/LC_MESSAGES/cpupower.mo; \ done; .PHONY: all utils libcpupower update-po create-gmo install-lib install-tools install-man install-gmo install uninstall clean -- cgit v1.2.3 From 76b659a31df5174d71832b7882ef31b32e1f8d59 Mon Sep 17 00:00:00 2001 From: Roman Vasiyarov Date: Mon, 25 Apr 2011 21:34:23 +0400 Subject: cpupowerutils: increase MAX_LINE_LEN larger sysfs data (>255 bytes) was truncated and thus used improperly [linux@dominikbrodowski.net: adapted to cpupowerutils] Signed-off-by: Roman Vasiyarov Signed-off-by: Dominik Brodowski --- tools/power/cpupower/lib/sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools') diff --git a/tools/power/cpupower/lib/sysfs.c b/tools/power/cpupower/lib/sysfs.c index 9a35456ba6b2..870713a75a81 100644 --- a/tools/power/cpupower/lib/sysfs.c +++ b/tools/power/cpupower/lib/sysfs.c @@ -17,7 +17,7 @@ #include "cpufreq.h" #define PATH_TO_CPU "/sys/devices/system/cpu/" -#define MAX_LINE_LEN 255 +#define MAX_LINE_LEN 4096 #define SYSFS_PATH_MAX 255 -- cgit v1.2.3 From 8fb2e440b223b966f74a04a48f6f71f288fa671b Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Thu, 21 Jul 2011 11:54:53 +0200 Subject: cpupower: Show Intel turbo ratio support via ./cpupower frequency-info This adds the last piece missing from turbostat (if called with -v). It shows on Intel machines supporting Turbo Boost how many cores have to be active/idle to enter which boost mode (frequency). Whether the HW really enters these boost modes can be verified via ./cpupower monitor. Signed-off-by: Thomas Renninger CC: lenb@kernel.org CC: linux@dominikbrodowski.net CC: cpufreq@vger.kernel.org Signed-off-by: Dominik Brodowski --- tools/power/cpupower/utils/cpufreq-info.c | 54 +++++++++++++++++++++------- tools/power/cpupower/utils/helpers/cpuid.c | 29 ++++++++++++++- tools/power/cpupower/utils/helpers/helpers.h | 13 ++++--- tools/power/cpupower/utils/helpers/msr.c | 16 +++++++++ 4 files changed, 95 insertions(+), 17 deletions(-) (limited to 'tools') diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c index 8628644188cf..5a1d25f056b3 100644 --- a/tools/power/cpupower/utils/cpufreq-info.c +++ b/tools/power/cpupower/utils/cpufreq-info.c @@ -165,26 +165,56 @@ static int get_boost_mode(unsigned int cpu) printf(_(" Supported: %s\n"), support ? _("yes") : _("no")); printf(_(" Active: %s\n"), active ? _("yes") : _("no")); - /* ToDo: Only works for AMD for now... */ - if (cpupower_cpu_info.vendor == X86_VENDOR_AMD && cpupower_cpu_info.family >= 0x10) { ret = decode_pstates(cpu, cpupower_cpu_info.family, b_states, pstates, &pstate_no); if (ret) return ret; - } else - return 0; - printf(_(" Boost States: %d\n"), b_states); - printf(_(" Total States: %d\n"), pstate_no); - for (i = 0; i < pstate_no; i++) { - if (i < b_states) - printf(_(" Pstate-Pb%d: %luMHz (boost state)\n"), - i, pstates[i]); + printf(_(" Boost States: %d\n"), b_states); + printf(_(" Total States: %d\n"), pstate_no); + for (i = 0; i < pstate_no; i++) { + if (i < b_states) + printf(_(" Pstate-Pb%d: %luMHz (boost state)" + "\n"), i, pstates[i]); + else + printf(_(" Pstate-P%d: %luMHz\n"), + i - b_states, pstates[i]); + } + } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO) { + double bclk; + unsigned long long intel_turbo_ratio = 0; + unsigned int ratio; + + /* Any way to autodetect this ? */ + if (cpupower_cpu_info.caps & CPUPOWER_CAP_IS_SNB) + bclk = 100.00; else - printf(_(" Pstate-P%d: %luMHz\n"), - i - b_states, pstates[i]); + bclk = 133.33; + intel_turbo_ratio = msr_intel_get_turbo_ratio(cpu); + dprint (" Ratio: 0x%llx - bclk: %f\n", + intel_turbo_ratio, bclk); + + ratio = (intel_turbo_ratio >> 24) & 0xFF; + if (ratio) + printf(_(" %.0f MHz max turbo 4 active cores\n"), + ratio * bclk); + + ratio = (intel_turbo_ratio >> 16) & 0xFF; + if (ratio) + printf(_(" %.0f MHz max turbo 3 active cores\n"), + ratio * bclk); + + ratio = (intel_turbo_ratio >> 8) & 0xFF; + if (ratio) + printf(_(" %.0f MHz max turbo 2 active cores\n"), + ratio * bclk); + + ratio = (intel_turbo_ratio >> 0) & 0xFF; + if (ratio) + printf(_(" %.0f MHz max turbo 1 active cores\n"), + ratio * bclk); } return 0; } diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c index 944b2c1659d8..a97f091fcf2b 100644 --- a/tools/power/cpupower/utils/helpers/cpuid.c +++ b/tools/power/cpupower/utils/helpers/cpuid.c @@ -130,10 +130,37 @@ out: cpu_info->caps |= CPUPOWER_CAP_AMD_CBP; } - /* Intel's perf-bias MSR support */ if (cpu_info->vendor == X86_VENDOR_INTEL) { + /* Intel's perf-bias MSR support */ if (cpuid_level >= 6 && (cpuid_ecx(6) & (1 << 3))) cpu_info->caps |= CPUPOWER_CAP_PERF_BIAS; + + /* Intel's Turbo Ratio Limit support */ + if (cpu_info->family == 6) { + switch (cpu_info->model) { + case 0x1A: /* Core i7, Xeon 5500 series + * Bloomfield, Gainstown NHM-EP + */ + case 0x1E: /* Core i7 and i5 Processor + * Clarksfield, Lynnfield, Jasper Forest + */ + case 0x1F: /* Core i7 and i5 Processor - Nehalem */ + case 0x25: /* Westmere Client + * Clarkdale, Arrandale + */ + case 0x2C: /* Westmere EP - Gulftown */ + cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO; + case 0x2A: /* SNB */ + case 0x2D: /* SNB Xeon */ + cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO; + cpu_info->caps |= CPUPOWER_CAP_IS_SNB; + break; + case 0x2E: /* Nehalem-EX Xeon - Beckton */ + case 0x2F: /* Westmere-EX Xeon - Eagleton */ + default: + break; + } + } } /* printf("ID: %u - Extid: 0x%x - Caps: 0x%llx\n", diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h index 048f065925c9..9125a551ac1d 100644 --- a/tools/power/cpupower/utils/helpers/helpers.h +++ b/tools/power/cpupower/utils/helpers/helpers.h @@ -52,10 +52,12 @@ extern int be_verbose; enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL, X86_VENDOR_AMD, X86_VENDOR_MAX}; -#define CPUPOWER_CAP_INV_TSC 0x00000001 -#define CPUPOWER_CAP_APERF 0x00000002 -#define CPUPOWER_CAP_AMD_CBP 0x00000004 -#define CPUPOWER_CAP_PERF_BIAS 0x00000008 +#define CPUPOWER_CAP_INV_TSC 0x00000001 +#define CPUPOWER_CAP_APERF 0x00000002 +#define CPUPOWER_CAP_AMD_CBP 0x00000004 +#define CPUPOWER_CAP_PERF_BIAS 0x00000008 +#define CPUPOWER_CAP_HAS_TURBO_RATIO 0x00000010 +#define CPUPOWER_CAP_IS_SNB 0x00000011 #define MAX_HW_PSTATES 10 @@ -111,6 +113,7 @@ extern int write_msr(int cpu, unsigned int idx, unsigned long long val); extern int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val); extern int msr_intel_get_perf_bias(unsigned int cpu); +extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu); extern int msr_intel_has_boost_support(unsigned int cpu); extern int msr_intel_boost_is_active(unsigned int cpu); @@ -157,6 +160,8 @@ static inline int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val) { return -1; }; static inline int msr_intel_get_perf_bias(unsigned int cpu) { return -1; }; +static inline unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu) +{ return 0; }; static inline int msr_intel_has_boost_support(unsigned int cpu) { return -1; }; diff --git a/tools/power/cpupower/utils/helpers/msr.c b/tools/power/cpupower/utils/helpers/msr.c index 93d48bd56e57..7869ca64dfd3 100644 --- a/tools/power/cpupower/utils/helpers/msr.c +++ b/tools/power/cpupower/utils/helpers/msr.c @@ -11,6 +11,7 @@ #define MSR_IA32_PERF_STATUS 0x198 #define MSR_IA32_MISC_ENABLES 0x1a0 #define MSR_IA32_ENERGY_PERF_BIAS 0x1b0 +#define MSR_NEHALEM_TURBO_RATIO_LIMIT 0x1ad /* * read_msr @@ -79,6 +80,7 @@ int msr_intel_has_boost_support(unsigned int cpu) ret = read_msr(cpu, MSR_IA32_MISC_ENABLES, &misc_enables); if (ret) return ret; + return (misc_enables >> 38) & 0x1; } @@ -119,4 +121,18 @@ int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val) return ret; return 0; } + +unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu) +{ + unsigned long long val; + int ret; + + if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_HAS_TURBO_RATIO)) + return -1; + + ret = read_msr(cpu, MSR_NEHALEM_TURBO_RATIO_LIMIT, &val); + if (ret) + return ret; + return val; +} #endif -- cgit v1.2.3 From 029e9f73667f9b4661ac9886f706d75d26850260 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Thu, 21 Jul 2011 11:54:54 +0200 Subject: cpupower: Do detect IDA (opportunistic processor performance) via cpuid IA32-Intel Devel guide Volume 3A - 14.3.2.1 ------------------------------------------- ... Opportunistic processor performance operation can be disabled by setting bit 38 of IA32_MISC_ENABLES. This mechanism is intended for BIOS only. If IA32_MISC_ENABLES[38] is set, CPUID.06H:EAX[1] will return 0. Better detect things via cpuid, this cleans up the code a bit and the MSR parts were not working correctly anyway. Signed-off-by: Thomas Renninger CC: lenb@kernel.org CC: linux@dominikbrodowski.net CC: cpufreq@vger.kernel.org Signed-off-by: Dominik Brodowski --- tools/power/cpupower/utils/helpers/cpuid.c | 6 ++++++ tools/power/cpupower/utils/helpers/helpers.h | 9 +-------- tools/power/cpupower/utils/helpers/misc.c | 12 ++---------- tools/power/cpupower/utils/helpers/msr.c | 23 ----------------------- 4 files changed, 9 insertions(+), 41 deletions(-) (limited to 'tools') diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c index a97f091fcf2b..906895d21cce 100644 --- a/tools/power/cpupower/utils/helpers/cpuid.c +++ b/tools/power/cpupower/utils/helpers/cpuid.c @@ -130,6 +130,12 @@ out: cpu_info->caps |= CPUPOWER_CAP_AMD_CBP; } + if (cpu_info->vendor == X86_VENDOR_INTEL) { + if (cpuid_level >= 6 && + (cpuid_eax(6) & (1 << 1))) + cpu_info->caps |= CPUPOWER_CAP_INTEL_IDA; + } + if (cpu_info->vendor == X86_VENDOR_INTEL) { /* Intel's perf-bias MSR support */ if (cpuid_level >= 6 && (cpuid_ecx(6) & (1 << 3))) diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h index 9125a551ac1d..592ee362b877 100644 --- a/tools/power/cpupower/utils/helpers/helpers.h +++ b/tools/power/cpupower/utils/helpers/helpers.h @@ -58,6 +58,7 @@ enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL, #define CPUPOWER_CAP_PERF_BIAS 0x00000008 #define CPUPOWER_CAP_HAS_TURBO_RATIO 0x00000010 #define CPUPOWER_CAP_IS_SNB 0x00000011 +#define CPUPOWER_CAP_INTEL_IDA 0x00000012 #define MAX_HW_PSTATES 10 @@ -115,9 +116,6 @@ extern int msr_intel_set_perf_bias(unsigned int cpu, unsigned int val); extern int msr_intel_get_perf_bias(unsigned int cpu); extern unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu); -extern int msr_intel_has_boost_support(unsigned int cpu); -extern int msr_intel_boost_is_active(unsigned int cpu); - /* Read/Write msr ****************************/ /* PCI stuff ****************************/ @@ -163,11 +161,6 @@ static inline int msr_intel_get_perf_bias(unsigned int cpu) static inline unsigned long long msr_intel_get_turbo_ratio(unsigned int cpu) { return 0; }; -static inline int msr_intel_has_boost_support(unsigned int cpu) -{ return -1; }; -static inline int msr_intel_boost_is_active(unsigned int cpu) -{ return -1; }; - /* Read/Write msr ****************************/ static inline int cpufreq_has_boost_support(unsigned int cpu, int *support, diff --git a/tools/power/cpupower/utils/helpers/misc.c b/tools/power/cpupower/utils/helpers/misc.c index e8b3140cc6b8..1609243f5c64 100644 --- a/tools/power/cpupower/utils/helpers/misc.c +++ b/tools/power/cpupower/utils/helpers/misc.c @@ -20,16 +20,8 @@ int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active, if (ret <= 0) return ret; *support = 1; - } else if (cpupower_cpu_info.vendor == X86_VENDOR_INTEL) { - ret = msr_intel_has_boost_support(cpu); - if (ret <= 0) - return ret; - *support = ret; - ret = msr_intel_boost_is_active(cpu); - if (ret <= 0) - return ret; - *active = ret; - } + } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA) + *support = *active = 1; return 0; } #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 index 7869ca64dfd3..31a4b24a8bc6 100644 --- a/tools/power/cpupower/utils/helpers/msr.c +++ b/tools/power/cpupower/utils/helpers/msr.c @@ -72,29 +72,6 @@ int write_msr(int cpu, unsigned int idx, unsigned long long val) return -1; } -int msr_intel_has_boost_support(unsigned int cpu) -{ - unsigned long long misc_enables; - int ret; - - ret = read_msr(cpu, MSR_IA32_MISC_ENABLES, &misc_enables); - if (ret) - return ret; - - return (misc_enables >> 38) & 0x1; -} - -int msr_intel_boost_is_active(unsigned int cpu) -{ - unsigned long long perf_status; - int ret; - - ret = read_msr(cpu, MSR_IA32_PERF_STATUS, &perf_status); - if (ret) - return ret; - return (perf_status >> 32) & 0x1; -} - int msr_intel_get_perf_bias(unsigned int cpu) { unsigned long long val; -- cgit v1.2.3 From d30c4b7a87e8b19583d5ef1402d9b38f51e30f44 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sun, 31 Jul 2011 18:19:33 -0400 Subject: tools/power turbostat: fit output into 80 columns on snb-ep Reduce columns for package number to 1. If you can afford more than 9 packages, you can also afford a terminal with more than 80 columns:-) Also shave a column also off the package C-states Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 46 +++++++++++++++++------------------ 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'tools') 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) void print_header(void) { if (show_pkg) - fprintf(stderr, "pkg "); + fprintf(stderr, "pk"); if (show_core) - fprintf(stderr, "core"); + fprintf(stderr, " cr"); if (show_cpu) fprintf(stderr, " CPU"); if (do_nhm_cstates) - fprintf(stderr, " %%c0 "); + fprintf(stderr, " %%c0 "); if (has_aperf) - fprintf(stderr, " GHz"); + fprintf(stderr, " GHz"); fprintf(stderr, " TSC"); if (do_nhm_cstates) - fprintf(stderr, " %%c1 "); + fprintf(stderr, " %%c1"); if (do_nhm_cstates) - fprintf(stderr, " %%c3 "); + fprintf(stderr, " %%c3"); if (do_nhm_cstates) - fprintf(stderr, " %%c6 "); + fprintf(stderr, " %%c6"); if (do_snb_cstates) - fprintf(stderr, " %%c7 "); + fprintf(stderr, " %%c7"); if (do_snb_cstates) - fprintf(stderr, " %%pc2 "); + fprintf(stderr, " %%pc2"); if (do_nhm_cstates) - fprintf(stderr, " %%pc3 "); + fprintf(stderr, " %%pc3"); if (do_nhm_cstates) - fprintf(stderr, " %%pc6 "); + fprintf(stderr, " %%pc6"); if (do_snb_cstates) - fprintf(stderr, " %%pc7 "); + fprintf(stderr, " %%pc7"); if (extra_msr_offset) - fprintf(stderr, " MSR 0x%x ", extra_msr_offset); + fprintf(stderr, " MSR 0x%x ", extra_msr_offset); putc('\n', stderr); } @@ -194,14 +194,14 @@ void print_cnt(struct counters *p) /* topology columns, print blanks on 1st (average) line */ if (p == cnt_average) { if (show_pkg) - fprintf(stderr, " "); + fprintf(stderr, " "); if (show_core) fprintf(stderr, " "); if (show_cpu) fprintf(stderr, " "); } else { if (show_pkg) - fprintf(stderr, "%4d", p->pkg); + fprintf(stderr, "%d", p->pkg); if (show_core) fprintf(stderr, "%4d", p->core); if (show_cpu) @@ -241,22 +241,22 @@ void print_cnt(struct counters *p) if (!skip_c1) fprintf(stderr, "%7.2f", 100.0 * p->c1/p->tsc); else - fprintf(stderr, " ****"); + fprintf(stderr, " ****"); } if (do_nhm_cstates) - fprintf(stderr, "%7.2f", 100.0 * p->c3/p->tsc); + fprintf(stderr, " %6.2f", 100.0 * p->c3/p->tsc); if (do_nhm_cstates) - fprintf(stderr, "%7.2f", 100.0 * p->c6/p->tsc); + fprintf(stderr, " %6.2f", 100.0 * p->c6/p->tsc); if (do_snb_cstates) - fprintf(stderr, "%7.2f", 100.0 * p->c7/p->tsc); + fprintf(stderr, " %6.2f", 100.0 * p->c7/p->tsc); if (do_snb_cstates) - fprintf(stderr, "%7.2f", 100.0 * p->pc2/p->tsc); + fprintf(stderr, " %5.2f", 100.0 * p->pc2/p->tsc); if (do_nhm_cstates) - fprintf(stderr, "%7.2f", 100.0 * p->pc3/p->tsc); + fprintf(stderr, " %5.2f", 100.0 * p->pc3/p->tsc); if (do_nhm_cstates) - fprintf(stderr, "%7.2f", 100.0 * p->pc6/p->tsc); + fprintf(stderr, " %5.2f", 100.0 * p->pc6/p->tsc); if (do_snb_cstates) - fprintf(stderr, "%7.2f", 100.0 * p->pc7/p->tsc); + fprintf(stderr, " %5.2f", 100.0 * p->pc7/p->tsc); if (extra_msr_offset) fprintf(stderr, " 0x%016llx", p->extra_msr); putc('\n', stderr); -- cgit v1.2.3